mirror of
https://github.com/Drop-OSS/drop.git
synced 2025-11-09 20:12:10 +10:00
feat: preliminary peer api
This commit is contained in:
@ -17,7 +17,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@drop-oss/droplet": "^0.7.2",
|
"@drop-oss/droplet": "^0.7.2",
|
||||||
"@drop-oss/headscalez": "^0.0.3",
|
"@drop-oss/headscalez": "0.0.4",
|
||||||
"@headlessui/vue": "^1.7.23",
|
"@headlessui/vue": "^1.7.23",
|
||||||
"@heroicons/vue": "^2.1.5",
|
"@heroicons/vue": "^2.1.5",
|
||||||
"@nuxt/fonts": "^0.11.0",
|
"@nuxt/fonts": "^0.11.0",
|
||||||
|
|||||||
20
server/api/v1/client/peer/index.get.ts
Normal file
20
server/api/v1/client/peer/index.get.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { ClientCapabilities } from "~/prisma/client";
|
||||||
|
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||||
|
import headscaleManager from "~/server/internal/p2p/headscale";
|
||||||
|
|
||||||
|
export default defineClientEventHandler(async (h3, { fetchClient }) => {
|
||||||
|
const client = await fetchClient();
|
||||||
|
if (!client.capabilities.includes(ClientCapabilities.PeerAPI))
|
||||||
|
throw createError({
|
||||||
|
statusCode: 403,
|
||||||
|
statusMessage: "Capability not allowed.",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!headscaleManager.enabled())
|
||||||
|
throw createError({
|
||||||
|
statusCode: 500,
|
||||||
|
statusMessage: "Peer network not available.",
|
||||||
|
});
|
||||||
|
|
||||||
|
return headscaleManager.configuration();
|
||||||
|
});
|
||||||
26
server/api/v1/client/peer/index.post.ts
Normal file
26
server/api/v1/client/peer/index.post.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { ClientCapabilities } from "~/prisma/client";
|
||||||
|
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
|
||||||
|
import headscaleManager from "~/server/internal/p2p/headscale";
|
||||||
|
|
||||||
|
export default defineClientEventHandler(
|
||||||
|
async (h3, { fetchClient, fetchUser }) => {
|
||||||
|
const client = await fetchClient();
|
||||||
|
if (!client.capabilities.includes(ClientCapabilities.PeerAPI))
|
||||||
|
throw createError({
|
||||||
|
statusCode: 403,
|
||||||
|
statusMessage: "Capability not allowed.",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!headscaleManager.enabled())
|
||||||
|
throw createError({
|
||||||
|
statusCode: 500,
|
||||||
|
statusMessage: "Peer network not available.",
|
||||||
|
});
|
||||||
|
|
||||||
|
const user = await fetchUser();
|
||||||
|
|
||||||
|
const key = await headscaleManager.createPreauthKey(user, client);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
},
|
||||||
|
);
|
||||||
@ -1,9 +1,12 @@
|
|||||||
import type { HeadscaleService } from "@drop-oss/headscalez";
|
import type { HeadscaleService } from "@drop-oss/headscalez";
|
||||||
import { startHeadscale } from "@drop-oss/headscalez";
|
import { HeadscaleControlService, startHeadscale } from "@drop-oss/headscalez";
|
||||||
import { systemConfig } from "../config/sys-conf";
|
import { systemConfig } from "../config/sys-conf";
|
||||||
|
import type { Client, User } from "~/prisma/client";
|
||||||
|
|
||||||
export class HeadscaleManager {
|
export class HeadscaleManager {
|
||||||
|
private controlURL?: string;
|
||||||
private headscaleService?: HeadscaleService;
|
private headscaleService?: HeadscaleService;
|
||||||
|
private headscaleClient?: HeadscaleControlService;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.setup();
|
this.setup();
|
||||||
@ -12,17 +15,67 @@ export class HeadscaleManager {
|
|||||||
async setup() {
|
async setup() {
|
||||||
const externalUrl = process.env.CONTROL_URL;
|
const externalUrl = process.env.CONTROL_URL;
|
||||||
if (externalUrl) {
|
if (externalUrl) {
|
||||||
|
this.controlURL = externalUrl;
|
||||||
const headscale = await startHeadscale({
|
const headscale = await startHeadscale({
|
||||||
externalUrl,
|
externalUrl,
|
||||||
dir: systemConfig.getHeadscaleFolder(),
|
dir: systemConfig.getHeadscaleFolder(),
|
||||||
});
|
});
|
||||||
this.headscaleService = headscale;
|
this.headscaleService = headscale;
|
||||||
|
this.headscaleClient = new HeadscaleControlService(headscale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enabled() {
|
enabled() {
|
||||||
return !!this.headscaleService;
|
return !!this.headscaleService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configuration() {
|
||||||
|
if (!this.controlURL) throw new Error("Headscale not available");
|
||||||
|
return {
|
||||||
|
controlURL: this.controlURL,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async fetchUser(user: User) {
|
||||||
|
if (!this.headscaleClient)
|
||||||
|
throw new Error("Headscale client not available");
|
||||||
|
const { response } = await this.headscaleClient.client.listUsers({
|
||||||
|
id: 0n,
|
||||||
|
name: user.id,
|
||||||
|
email: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.users.length == 0) {
|
||||||
|
const { response } = await this.headscaleClient.client.createUser({
|
||||||
|
name: user.id,
|
||||||
|
displayName: user.displayName,
|
||||||
|
email: user.email,
|
||||||
|
pictureUrl: user.profilePictureObjectId,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.user) throw new Error("Could not create user");
|
||||||
|
|
||||||
|
return response.user;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.users[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
async createPreauthKey(user: User, client: Client) {
|
||||||
|
if (!this.headscaleClient)
|
||||||
|
throw new Error("Headscale client not available");
|
||||||
|
|
||||||
|
const headscaleUser = await this.fetchUser(user);
|
||||||
|
const { response } = await this.headscaleClient.client.createPreAuthKey({
|
||||||
|
user: headscaleUser.name,
|
||||||
|
reusable: false,
|
||||||
|
ephemeral: false,
|
||||||
|
aclTags: ["client", `user:${user.id}`, `client:${client.id}`],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.preAuthKey) throw new Error("Could not create pre-auth key");
|
||||||
|
return response.preAuthKey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const headscaleManager = new HeadscaleManager();
|
export const headscaleManager = new HeadscaleManager();
|
||||||
|
|||||||
31
yarn.lock
31
yarn.lock
@ -371,11 +371,14 @@
|
|||||||
"@drop-oss/droplet-win32-arm64-msvc" "0.7.2"
|
"@drop-oss/droplet-win32-arm64-msvc" "0.7.2"
|
||||||
"@drop-oss/droplet-win32-x64-msvc" "0.7.2"
|
"@drop-oss/droplet-win32-x64-msvc" "0.7.2"
|
||||||
|
|
||||||
"@drop-oss/headscalez@^0.0.3":
|
"@drop-oss/headscalez@0.0.4":
|
||||||
version "0.0.3"
|
version "0.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/@drop-oss/headscalez/-/headscalez-0.0.3.tgz#deb6eae13b9b65cf225bb2e0e84bc47159b4a91e"
|
resolved "https://registry.yarnpkg.com/@drop-oss/headscalez/-/headscalez-0.0.4.tgz#7558fbbc542d93fb0c69bdcf48917bdae676c62d"
|
||||||
integrity sha512-Zsl0T/pwJyw7vbLwEUVAf9zXKKTG3qAbUVQEDiRe88bwhzauPG9/MgBBHA2N/9GHXMUFRRDcchPbwGjCcmcJ3Q==
|
integrity sha512-vdDq6Qe/T5S0FKKYdnBXvOh53wGs8nxy6O3ACVyUjTbTGkDn3z5og4joh5TxoAOFodPHRLCihVuroiymS7yNTg==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@protobuf-ts/grpcweb-transport" "^2.10.0"
|
||||||
|
"@protobuf-ts/runtime" "^2.10.0"
|
||||||
|
"@protobuf-ts/runtime-rpc" "^2.10.0"
|
||||||
execa "^9.5.3"
|
execa "^9.5.3"
|
||||||
fs-extra "^11.3.0"
|
fs-extra "^11.3.0"
|
||||||
node-graceful-shutdown "^1.1.5"
|
node-graceful-shutdown "^1.1.5"
|
||||||
@ -1549,6 +1552,26 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@prisma/debug" "6.7.0"
|
"@prisma/debug" "6.7.0"
|
||||||
|
|
||||||
|
"@protobuf-ts/grpcweb-transport@^2.10.0":
|
||||||
|
version "2.10.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobuf-ts/grpcweb-transport/-/grpcweb-transport-2.10.0.tgz#c09f29694ec7dc4fc1107a0bf30d359325939311"
|
||||||
|
integrity sha512-VUyD+8kn4XEfWoEiKjAsWX5XWkt8Gfdp/uquS17yt9hdfMBVx3o5tlXX5ylwfWhcIjbRvkf7WHEEdS2wMuq86Q==
|
||||||
|
dependencies:
|
||||||
|
"@protobuf-ts/runtime" "^2.10.0"
|
||||||
|
"@protobuf-ts/runtime-rpc" "^2.10.0"
|
||||||
|
|
||||||
|
"@protobuf-ts/runtime-rpc@^2.10.0":
|
||||||
|
version "2.10.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobuf-ts/runtime-rpc/-/runtime-rpc-2.10.0.tgz#68de8dcc369e56579569a4deafd394cf4683dc66"
|
||||||
|
integrity sha512-8CS/XPv3+pMK4v8UKhtCdvbS4h9l7aqlteKdRt0/UbIKZ8n0qHj6hX8cBhz2ngvohxCOS0N08zPr9aCLBNhW3Q==
|
||||||
|
dependencies:
|
||||||
|
"@protobuf-ts/runtime" "^2.10.0"
|
||||||
|
|
||||||
|
"@protobuf-ts/runtime@^2.10.0":
|
||||||
|
version "2.10.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobuf-ts/runtime/-/runtime-2.10.0.tgz#bc90f632647ff2ae72887546ddf3d193f3f43d98"
|
||||||
|
integrity sha512-ypYwGg9Pn3W/2lZ7/HW60hONGuSdzphvOY8Dq7LeNttymDe0y3LaTUUMRpuGqOT6FfrWEMnfQbyqU8AAreo8wA==
|
||||||
|
|
||||||
"@rollup/plugin-alias@^5.1.1":
|
"@rollup/plugin-alias@^5.1.1":
|
||||||
version "5.1.1"
|
version "5.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-alias/-/plugin-alias-5.1.1.tgz#53601d88cda8b1577aa130b4a6e452283605bf26"
|
resolved "https://registry.yarnpkg.com/@rollup/plugin-alias/-/plugin-alias-5.1.1.tgz#53601d88cda8b1577aa130b4a6e452283605bf26"
|
||||||
|
|||||||
Reference in New Issue
Block a user