mirror of
https://github.com/usatiuk/dhfs.git
synced 2025-10-28 12:37:48 +01:00
Peer certificate check when adding
This commit is contained in:
@@ -67,14 +67,14 @@ public class DhfsFuseIT {
|
||||
var c1curl = container1.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c2uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/" + c2uuid);
|
||||
|
||||
var c2curl = container2.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c1uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/" + c1uuid);
|
||||
|
||||
waitingConsumer2.waitUntil(frame -> frame.getUtf8String().contains("Connected"), 60, TimeUnit.SECONDS);
|
||||
waitingConsumer1.waitUntil(frame -> frame.getUtf8String().contains("Connected"), 60, TimeUnit.SECONDS);
|
||||
|
||||
@@ -93,26 +93,26 @@ public class DhfsFusex3IT {
|
||||
var c1curl = container1.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c2uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/" + c2uuid);
|
||||
|
||||
var c2curl1 = container2.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c1uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/" + c1uuid);
|
||||
|
||||
var c2curl3 = container2.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c3uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/" + c3uuid);
|
||||
|
||||
var c3curl = container3.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c2uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/" + c2uuid);
|
||||
|
||||
waitingConsumer3.waitUntil(frame -> frame.getUtf8String().contains("Connected"), 60, TimeUnit.SECONDS, 2);
|
||||
waitingConsumer2.waitUntil(frame -> frame.getUtf8String().contains("Connected"), 60, TimeUnit.SECONDS, 2);
|
||||
|
||||
@@ -78,6 +78,7 @@ public class DhfsImage implements Future<String> {
|
||||
"-Ddhfs.objects.sync.timeout=30",
|
||||
"-Ddhfs.objects.sync.ping.timeout=5",
|
||||
"-Ddhfs.objects.reconnect_interval=1s",
|
||||
"-Ddhfs.sync.cert-check=false",
|
||||
"-Dquarkus.log.category.\"com.usatiuk\".level=TRACE",
|
||||
"-Dquarkus.log.category.\"com.usatiuk.dhfs\".level=TRACE",
|
||||
"-Dquarkus.log.category.\"com.usatiuk.objects.transaction\".level=INFO",
|
||||
|
||||
@@ -81,14 +81,14 @@ public class KillIT {
|
||||
var c1curl = container1.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c2uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/" + c2uuid);
|
||||
|
||||
var c2curl = container2.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c1uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/" + c1uuid);
|
||||
|
||||
waitingConsumer2.waitUntil(frame -> frame.getUtf8String().contains("Connected"), 60, TimeUnit.SECONDS);
|
||||
waitingConsumer1.waitUntil(frame -> frame.getUtf8String().contains("Connected"), 60, TimeUnit.SECONDS);
|
||||
|
||||
@@ -93,14 +93,14 @@ public class LazyFsIT {
|
||||
var c1curl = container1.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c2uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/"+c2uuid);
|
||||
|
||||
var c2curl = container2.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c1uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/"+c1uuid);
|
||||
|
||||
waitingConsumer2.waitUntil(frame -> frame.getUtf8String().contains("Connected"), 60, TimeUnit.SECONDS);
|
||||
waitingConsumer1.waitUntil(frame -> frame.getUtf8String().contains("Connected"), 60, TimeUnit.SECONDS);
|
||||
|
||||
@@ -75,14 +75,14 @@ public class ResyncIT {
|
||||
var c1curl = container1.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c2uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/" + c2uuid);
|
||||
|
||||
var c2curl = container2.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c1uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/" + c1uuid);
|
||||
|
||||
waitingConsumer2.waitUntil(frame -> frame.getUtf8String().contains("Connected"), 60, TimeUnit.SECONDS);
|
||||
waitingConsumer1.waitUntil(frame -> frame.getUtf8String().contains("Connected"), 60, TimeUnit.SECONDS);
|
||||
@@ -115,14 +115,14 @@ public class ResyncIT {
|
||||
var c1curl = container1.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c2uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/" + c2uuid);
|
||||
|
||||
var c2curl = container2.execInContainer("/bin/sh", "-c",
|
||||
"curl --header \"Content-Type: application/json\" " +
|
||||
" --request PUT " +
|
||||
" --data '{\"uuid\":\"" + c1uuid + "\"}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers");
|
||||
" --data '{}' " +
|
||||
" http://localhost:8080/peers-manage/known-peers/" + c1uuid);
|
||||
|
||||
waitingConsumer2.waitUntil(frame -> frame.getUtf8String().contains("Connected"), 60, TimeUnit.SECONDS);
|
||||
waitingConsumer1.waitUntil(frame -> frame.getUtf8String().contains("Connected"), 60, TimeUnit.SECONDS);
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.usatiuk.dhfs.peersync;
|
||||
|
||||
import com.usatiuk.dhfs.peerdiscovery.PeerAddress;
|
||||
import com.usatiuk.dhfs.peerdiscovery.PeerDiscoveryDirectory;
|
||||
import com.usatiuk.dhfs.peersync.api.ApiPeerInfo;
|
||||
import com.usatiuk.dhfs.peersync.api.PeerSyncApiClientDynamic;
|
||||
import com.usatiuk.dhfs.peertrust.PeerTrustManager;
|
||||
import com.usatiuk.dhfs.remoteobj.SyncHandler;
|
||||
@@ -13,11 +14,13 @@ import io.quarkus.logging.Log;
|
||||
import io.quarkus.runtime.StartupEvent;
|
||||
import io.quarkus.scheduler.Scheduled;
|
||||
import io.smallrye.common.annotation.Blocking;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.enterprise.inject.Instance;
|
||||
import jakarta.inject.Inject;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -47,6 +50,8 @@ public class PeerManager {
|
||||
PeerTrustManager peerTrustManager;
|
||||
@ConfigProperty(name = "dhfs.objects.sync.ping.timeout")
|
||||
long pingTimeout;
|
||||
@ConfigProperty(name = "dhfs.sync.cert-check", defaultValue = "true")
|
||||
boolean certCheck;
|
||||
@Inject
|
||||
PeerDiscoveryDirectory peerDiscoveryDirectory;
|
||||
@Inject
|
||||
@@ -185,24 +190,39 @@ public class PeerManager {
|
||||
return peerDiscoveryDirectory.getForPeer(host).stream().min(Comparator.comparing(PeerAddress::type));
|
||||
}
|
||||
|
||||
public void addRemoteHost(PeerId host) {
|
||||
transactionManager.run(() -> {
|
||||
private ApiPeerInfo getInfo(PeerId host) {
|
||||
return transactionManager.run(() -> {
|
||||
if (peerInfoService.getPeerInfo(host).isPresent())
|
||||
throw new IllegalStateException("Host " + host + " is already added");
|
||||
|
||||
var addr = selectBestAddress(host).orElseThrow(() -> new IllegalStateException("Host " + host + " is unreachable"));
|
||||
var info = peerSyncApiClient.getSelfInfo(addr);
|
||||
|
||||
var cert = Base64.getDecoder().decode(info.cert());
|
||||
peerInfoService.putPeer(host, cert);
|
||||
return info;
|
||||
});
|
||||
}
|
||||
|
||||
public void addRemoteHost(PeerId host, @Nullable String cert) {
|
||||
transactionManager.run(() -> {
|
||||
var info = getInfo(host);
|
||||
|
||||
var certGot = Base64.getDecoder().decode(info.cert());
|
||||
if (certCheck) {
|
||||
var certApi = Base64.getDecoder().decode(cert);
|
||||
if (!Arrays.equals(certGot, certApi))
|
||||
throw new IllegalStateException("Host " + host + " has different cert");
|
||||
}
|
||||
peerInfoService.putPeer(host, certGot);
|
||||
});
|
||||
|
||||
peerTrustManager.reloadTrustManagerHosts(transactionManager.run(() -> peerInfoService.getPeers().stream().toList())); //FIXME:
|
||||
}
|
||||
|
||||
public Collection<PeerId> getSeenButNotAddedHosts() {
|
||||
|
||||
public Collection<Pair<PeerId, ApiPeerInfo>> getSeenButNotAddedHosts() {
|
||||
return transactionManager.run(() -> {
|
||||
return peerDiscoveryDirectory.getReachablePeers().stream().filter(p -> !peerInfoService.getPeerInfo(p).isPresent()).toList();
|
||||
return peerDiscoveryDirectory.getReachablePeers().stream().filter(p -> !peerInfoService.getPeerInfo(p).isPresent())
|
||||
.map(p -> Pair.of(p, getInfo(p))).toList();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.usatiuk.dhfs.webapi;
|
||||
|
||||
public record KnownPeerDelete(String uuid) {
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.usatiuk.dhfs.webapi;
|
||||
|
||||
import jakarta.annotation.Nullable;
|
||||
|
||||
public record KnownPeerInfo(String uuid, @Nullable String knownAddress) {
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
package com.usatiuk.dhfs.webapi;
|
||||
|
||||
public record KnownPeerPut(String uuid) {
|
||||
import jakarta.annotation.Nullable;
|
||||
|
||||
public record KnownPeerPut(@Nullable String cert) {
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.usatiuk.dhfs.webapi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record KnownPeers(List<KnownPeerInfo> peers, String selfUuid) {
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
package com.usatiuk.dhfs.webapi;
|
||||
|
||||
public record PeerInfo(String uuid, String address) {
|
||||
import jakarta.annotation.Nullable;
|
||||
|
||||
public record PeerInfo(String uuid, String cert, @Nullable String knownAddress) {
|
||||
}
|
||||
|
||||
@@ -5,14 +5,9 @@ import com.usatiuk.dhfs.peersync.PeerInfoService;
|
||||
import com.usatiuk.dhfs.peersync.PeerManager;
|
||||
import com.usatiuk.dhfs.peersync.PersistentPeerDataService;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
|
||||
@Path("/peers-manage")
|
||||
public class PeerManagementApi {
|
||||
@@ -25,43 +20,30 @@ public class PeerManagementApi {
|
||||
|
||||
@Path("known-peers")
|
||||
@GET
|
||||
public KnownPeers knownPeers() {
|
||||
return new KnownPeers(peerInfoService.getPeers().stream().map(peerInfo -> new KnownPeerInfo(peerInfo.id().toString(),
|
||||
Optional.ofNullable(peerManager.getAddress(peerInfo.id())).map(Objects::toString).orElse(null))).toList(),
|
||||
persistentPeerDataService.getSelfUuid().toString());
|
||||
public List<PeerInfo> knownPeers() {
|
||||
return peerInfoService.getPeers().stream().map(
|
||||
peerInfo -> new PeerInfo(peerInfo.id().toString(), Base64.getEncoder().encodeToString(peerInfo.cert().toByteArray()),
|
||||
Optional.ofNullable(peerManager.getAddress(peerInfo.id())).map(Objects::toString).orElse(null))).toList();
|
||||
}
|
||||
|
||||
@Path("known-peers")
|
||||
@Path("known-peers/{peerId}")
|
||||
@PUT
|
||||
public void addPeer(KnownPeerPut knownPeerPut) {
|
||||
peerManager.addRemoteHost(PeerId.of(knownPeerPut.uuid()));
|
||||
public void addPeer(@PathParam("peerId") String peerId, KnownPeerPut knownPeerPut) {
|
||||
peerManager.addRemoteHost(PeerId.of(peerId), knownPeerPut.cert());
|
||||
}
|
||||
|
||||
@Path("known-peers")
|
||||
@Path("known-peers/{peerId}")
|
||||
@DELETE
|
||||
public void deletePeer(KnownPeerDelete knownPeerDelete) {
|
||||
peerManager.removeRemoteHost(PeerId.of(knownPeerDelete.uuid()));
|
||||
public void deletePeer(@PathParam("peerId") String peerId) {
|
||||
peerManager.removeRemoteHost(PeerId.of(peerId));
|
||||
}
|
||||
|
||||
@Path("available-peers")
|
||||
@GET
|
||||
public Collection<KnownPeerInfo> availablePeers() {
|
||||
public Collection<PeerInfo> availablePeers() {
|
||||
return peerManager.getSeenButNotAddedHosts().stream()
|
||||
.map(p -> new KnownPeerInfo(p.toString(),
|
||||
peerManager.selectBestAddress(p).map(Objects::toString).orElse(null)))
|
||||
.map(p -> new PeerInfo(p.getLeft().toString(), p.getRight().cert(),
|
||||
peerManager.selectBestAddress(p.getLeft()).map(Objects::toString).orElse(null)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Path("peer-state")
|
||||
@GET
|
||||
public Collection<PeerInfo> peerInfos(Collection<String> peerIdStrings) {
|
||||
return peerIdStrings.stream().map(PeerId::of).map(
|
||||
peerId -> {
|
||||
return new PeerInfo(
|
||||
peerId.toString(),
|
||||
peerManager.getAddress(peerId).toString()
|
||||
);
|
||||
}
|
||||
).toList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.usatiuk.dhfs.webapi;
|
||||
|
||||
public record SelfInfo(String uuid, String cert) {
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { TAvailablePeerInfoTo } from "./api/dto";
|
||||
import { useFetcher } from "react-router-dom";
|
||||
|
||||
import "./PeerAvailableCard.scss";
|
||||
import { hashCert } from "./hash";
|
||||
|
||||
export interface TPeerAvailableCardProps {
|
||||
peerInfo: TAvailablePeerInfoTo;
|
||||
@@ -16,6 +17,9 @@ export function PeerAvailableCard({ peerInfo }: TPeerAvailableCardProps) {
|
||||
<span>UUID: </span>
|
||||
<span>{peerInfo.uuid}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Cert: {hashCert(peerInfo.cert)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<fetcher.Form
|
||||
className="actions"
|
||||
@@ -25,6 +29,7 @@ export function PeerAvailableCard({ peerInfo }: TPeerAvailableCardProps) {
|
||||
<button type="submit">connect</button>
|
||||
<input name="intent" hidden={true} defaultValue={"add_peer"} />
|
||||
<input name="uuid" hidden={true} defaultValue={peerInfo.uuid} />
|
||||
<input name="cert" hidden={true} defaultValue={peerInfo.cert} />
|
||||
</fetcher.Form>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,6 +4,7 @@ import "./PeerKnownCard.scss";
|
||||
import { useFetcher, useLoaderData } from "react-router-dom";
|
||||
import { LoaderToType } from "./commonPlumbing";
|
||||
import { peerStateLoader } from "./PeerStatePlumbing";
|
||||
import { hashCert } from "./hash";
|
||||
|
||||
export interface TPeerKnownCardProps {
|
||||
peerInfo: TKnownPeerInfoTo;
|
||||
@@ -32,6 +33,9 @@ export function PeerKnownCard({ peerInfo }: TPeerKnownCardProps) {
|
||||
: "not connected"}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>Cert: {hashCert(peerInfo.cert)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<fetcher.Form method="put" action={"/home/peers"}>
|
||||
|
||||
@@ -4,12 +4,13 @@ import { LoaderToType } from "./commonPlumbing";
|
||||
import { peerStateLoader } from "./PeerStatePlumbing";
|
||||
import { PeerAvailableCard } from "./PeerAvailableCard";
|
||||
import { PeerKnownCard } from "./PeerKnownCard";
|
||||
import { hashCert } from "./hash";
|
||||
|
||||
export function PeerState() {
|
||||
const loaderData = useLoaderData() as LoaderToType<typeof peerStateLoader>;
|
||||
|
||||
const knownPeers = loaderData.knownPeers.peers
|
||||
?.filter((p) => p.uuid !== loaderData.knownPeers.selfUuid)
|
||||
const knownPeers = loaderData.knownPeers
|
||||
?.filter((p) => p.uuid !== loaderData.selfInfo.selfUuid)
|
||||
?.map((p) => <PeerKnownCard peerInfo={p} key={p.uuid} />);
|
||||
|
||||
const availablePeers = loaderData.availablePeers.map((p) => (
|
||||
@@ -18,7 +19,8 @@ export function PeerState() {
|
||||
|
||||
return (
|
||||
<div id={"PeerState"}>
|
||||
<div>Self UUID: {loaderData.knownPeers.selfUuid}</div>
|
||||
<div>UUID: {loaderData.selfInfo.selfUuid}</div>
|
||||
<div>Certificate: {hashCert(loaderData.selfInfo.cert)} </div>
|
||||
<div>
|
||||
<div>Known peers</div>
|
||||
<div>{knownPeers}</div>
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
getAvailablePeers,
|
||||
getKnownPeers,
|
||||
getPeerAddresses,
|
||||
getSelfInfo,
|
||||
putKnownPeer,
|
||||
putPeerAddress,
|
||||
removeKnownPeer,
|
||||
@@ -10,6 +11,7 @@ import { ActionFunctionArgs } from "react-router-dom";
|
||||
|
||||
export async function peerStateLoader() {
|
||||
return {
|
||||
selfInfo: await getSelfInfo(),
|
||||
availablePeers: await getAvailablePeers(),
|
||||
knownPeers: await getKnownPeers(),
|
||||
peerAddresses: await getPeerAddresses(),
|
||||
@@ -26,7 +28,10 @@ export async function peerStateAction({ request }: ActionFunctionArgs) {
|
||||
const formData = await request.formData();
|
||||
const intent = formData.get("intent") as PeerStateActionType;
|
||||
if (intent === "add_peer") {
|
||||
return await putKnownPeer(formData.get("uuid") as string);
|
||||
return await putKnownPeer(
|
||||
formData.get("uuid") as string,
|
||||
formData.get("cert") as string,
|
||||
);
|
||||
} else if (intent === "remove_peer") {
|
||||
return await removeKnownPeer(formData.get("uuid") as string);
|
||||
} else if (intent === "save_addr") {
|
||||
|
||||
@@ -4,15 +4,26 @@ import {
|
||||
KnownPeersToResp,
|
||||
NoContentToResp,
|
||||
PeerAddressInfoToResp,
|
||||
SelfInfoToResp,
|
||||
TAvailablePeerInfoArrTo,
|
||||
TAvailablePeerInfoToResp,
|
||||
TKnownPeerInfoArrTo, TKnownPeersTo,
|
||||
TKnownPeersTo,
|
||||
TKnownPeersToResp,
|
||||
TNoContentToResp,
|
||||
TPeerAddressInfoArrTo,
|
||||
TPeerAddressInfoToResp,
|
||||
TSelfInfoTo,
|
||||
TSelfInfoToResp,
|
||||
} from "./dto";
|
||||
|
||||
export async function getSelfInfo(): Promise<TSelfInfoTo> {
|
||||
return fetchJSON_throws<TSelfInfoToResp, typeof SelfInfoToResp>(
|
||||
"/peer-info/self",
|
||||
"GET",
|
||||
SelfInfoToResp,
|
||||
);
|
||||
}
|
||||
|
||||
export async function getAvailablePeers(): Promise<TAvailablePeerInfoArrTo> {
|
||||
return fetchJSON_throws<
|
||||
TAvailablePeerInfoToResp,
|
||||
@@ -28,16 +39,27 @@ export async function getKnownPeers(): Promise<TKnownPeersTo> {
|
||||
);
|
||||
}
|
||||
|
||||
export async function putKnownPeer(uuid: string): Promise<TNoContentToResp> {
|
||||
return fetchJSON("/peers-manage/known-peers", "PUT", NoContentToResp, {
|
||||
uuid,
|
||||
});
|
||||
export async function putKnownPeer(
|
||||
uuid: string,
|
||||
cert: string,
|
||||
): Promise<TNoContentToResp> {
|
||||
return fetchJSON(
|
||||
`/peers-manage/known-peers/${uuid}`,
|
||||
"PUT",
|
||||
NoContentToResp,
|
||||
{
|
||||
cert,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export async function removeKnownPeer(uuid: string): Promise<TNoContentToResp> {
|
||||
return fetchJSON("/peers-manage/known-peers", "DELETE", NoContentToResp, {
|
||||
uuid,
|
||||
});
|
||||
return fetchJSON(
|
||||
`/peers-manage/known-peers/${uuid}`,
|
||||
"DELETE",
|
||||
NoContentToResp,
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
export async function getPeerAddresses(): Promise<TPeerAddressInfoArrTo> {
|
||||
|
||||
@@ -36,13 +36,28 @@ export type TTokenTo = z.infer<typeof TokenTo>;
|
||||
export const TokenToResp = CreateAPIResponse(TokenTo);
|
||||
export type TTokenToResp = z.infer<typeof TokenToResp>;
|
||||
|
||||
// AvailablePeerInfo
|
||||
export const AvailablePeerInfoTo = z.object({
|
||||
// SelfInfo
|
||||
|
||||
export const SelfInfoTo = z.object({
|
||||
selfUuid: z.string(),
|
||||
cert: z.string(),
|
||||
});
|
||||
export type TSelfInfoTo = z.infer<typeof SelfInfoTo>;
|
||||
|
||||
export const SelfInfoToResp = CreateAPIResponse(SelfInfoTo);
|
||||
export type TSelfInfoToResp = z.infer<typeof SelfInfoToResp>;
|
||||
|
||||
// PeerInfo
|
||||
|
||||
export const PeerInfoTo = z.object({
|
||||
uuid: z.string(),
|
||||
knownAddress: z.string().optional(),
|
||||
// addr: z.string(),
|
||||
// port: z.number(),
|
||||
cert: z.string(),
|
||||
});
|
||||
export type TPeerInfoTo = z.infer<typeof PeerInfoTo>;
|
||||
|
||||
// AvailablePeerInfo
|
||||
export const AvailablePeerInfoTo = PeerInfoTo;
|
||||
export type TAvailablePeerInfoTo = z.infer<typeof AvailablePeerInfoTo>;
|
||||
|
||||
export const AvailablePeerInfoArrTo = z.array(AvailablePeerInfoTo);
|
||||
@@ -54,19 +69,13 @@ export const AvailablePeerInfoToResp = CreateAPIResponse(
|
||||
export type TAvailablePeerInfoToResp = z.infer<typeof AvailablePeerInfoToResp>;
|
||||
|
||||
// KnownPeerInfo
|
||||
export const KnownPeerInfoTo = z.object({
|
||||
uuid: z.string(),
|
||||
knownAddress: z.string().optional(),
|
||||
});
|
||||
export const KnownPeerInfoTo = PeerInfoTo;
|
||||
export type TKnownPeerInfoTo = z.infer<typeof KnownPeerInfoTo>;
|
||||
|
||||
export const KnownPeerInfoArrTo = z.array(KnownPeerInfoTo);
|
||||
export type TKnownPeerInfoArrTo = z.infer<typeof KnownPeerInfoArrTo>;
|
||||
|
||||
export const KnownPeersTo = z.object({
|
||||
selfUuid: z.string(),
|
||||
peers: KnownPeerInfoArrTo,
|
||||
});
|
||||
export const KnownPeersTo = KnownPeerInfoArrTo;
|
||||
export type TKnownPeersTo = z.infer<typeof KnownPeersTo>;
|
||||
|
||||
export const KnownPeersToResp = CreateAPIResponse(KnownPeersTo);
|
||||
@@ -86,9 +95,9 @@ export const PeerAddressInfoToResp = CreateAPIResponse(PeerAddressInfoArrTo);
|
||||
export type TPeerAddressInfoToResp = z.infer<typeof PeerAddressInfoToResp>;
|
||||
|
||||
// KnownPeerPut
|
||||
export const KnownPeerPutTo = z.object({ uuid: z.string() });
|
||||
export const KnownPeerPutTo = z.object({ cert: z.string() });
|
||||
export type TKnownPeerPutTo = z.infer<typeof KnownPeerPutTo>;
|
||||
|
||||
// KnownPeerDelete
|
||||
export const KnownPeerDeleteTo = z.object({ uuid: z.string() });
|
||||
export const KnownPeerDeleteTo = NoContentTo;
|
||||
export type TKnownPeerDeleteTo = z.infer<typeof KnownPeerDeleteTo>;
|
||||
|
||||
7
webui/src/hash.ts
Normal file
7
webui/src/hash.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export async function hashCert(cert: string) {
|
||||
const hash = await crypto.subtle.digest(
|
||||
"SHA-1",
|
||||
new TextEncoder().encode(cert),
|
||||
);
|
||||
return btoa(String.fromCharCode(...new Uint8Array(hash)));
|
||||
}
|
||||
Reference in New Issue
Block a user