@peerbit/server 2.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/lib/esm/aws.browser.d.ts +0 -0
  2. package/lib/esm/aws.browser.js +3 -0
  3. package/lib/esm/aws.browser.js.map +1 -0
  4. package/lib/esm/aws.d.ts +19 -0
  5. package/lib/esm/aws.js +185 -1
  6. package/lib/esm/aws.js.map +1 -1
  7. package/lib/esm/cli.js +614 -299
  8. package/lib/esm/cli.js.map +1 -1
  9. package/lib/esm/client.d.ts +13 -1
  10. package/lib/esm/client.js +101 -31
  11. package/lib/esm/client.js.map +1 -1
  12. package/lib/esm/config.d.ts +3 -3
  13. package/lib/esm/config.js +18 -16
  14. package/lib/esm/config.js.map +1 -1
  15. package/lib/esm/docker.browser.d.ts +0 -0
  16. package/lib/esm/docker.browser.js +3 -0
  17. package/lib/esm/docker.browser.js.map +1 -0
  18. package/lib/esm/domain.js +1 -1
  19. package/lib/esm/domain.js.map +1 -1
  20. package/lib/esm/peerbit.d.ts +2 -0
  21. package/lib/esm/peerbit.js +1 -0
  22. package/lib/esm/peerbit.js.map +1 -1
  23. package/lib/esm/remotes.d.ts +15 -3
  24. package/lib/esm/remotes.js +8 -9
  25. package/lib/esm/remotes.js.map +1 -1
  26. package/lib/esm/routes.d.ts +4 -2
  27. package/lib/esm/routes.js +6 -4
  28. package/lib/esm/routes.js.map +1 -1
  29. package/lib/esm/server.d.ts +5 -7
  30. package/lib/esm/server.js +183 -185
  31. package/lib/esm/server.js.map +1 -1
  32. package/lib/esm/signes-request.d.ts +5 -0
  33. package/lib/esm/signes-request.js +54 -0
  34. package/lib/esm/signes-request.js.map +1 -0
  35. package/lib/esm/trust.browser.d.ts +0 -0
  36. package/lib/esm/trust.browser.js +3 -0
  37. package/lib/esm/trust.browser.js.map +1 -0
  38. package/lib/esm/trust.d.ts +9 -0
  39. package/lib/esm/trust.js +36 -0
  40. package/lib/esm/trust.js.map +1 -0
  41. package/lib/ui/assets/aws.browser-4ed993c7.js +1 -0
  42. package/lib/ui/assets/index-5ed0229d.js +77 -0
  43. package/lib/ui/index.html +1 -1
  44. package/package.json +13 -7
  45. package/src/aws.browser.ts +1 -0
  46. package/src/aws.ts +250 -1
  47. package/src/cli.ts +726 -348
  48. package/src/client.ts +145 -38
  49. package/src/config.ts +21 -23
  50. package/src/docker.browser.ts +1 -0
  51. package/src/domain.ts +1 -1
  52. package/src/peerbit.ts +3 -0
  53. package/src/remotes.ts +24 -12
  54. package/src/routes.ts +6 -5
  55. package/src/server.ts +238 -254
  56. package/src/signes-request.ts +84 -0
  57. package/src/trust.browser.ts +1 -0
  58. package/src/trust.ts +39 -0
  59. package/lib/ui/assets/index-73eaa3bc.js +0 -53
package/src/server.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  import http from "http";
2
- import { fromBase64, sha256Base64Sync } from "@peerbit/crypto";
2
+ import {
3
+ fromBase64,
4
+ getKeypairFromPeerId,
5
+ getPublicKeyFromPeerId,
6
+ } from "@peerbit/crypto";
3
7
  import { deserialize } from "@dao-xyz/borsh";
4
8
  import {
5
9
  Program,
@@ -10,13 +14,10 @@ import {
10
14
  import { waitFor } from "@peerbit/time";
11
15
  import { v4 as uuid } from "uuid";
12
16
  import {
13
- checkExistPath,
14
17
  getHomeConfigDir,
15
- getCredentialsPath,
16
- getPackageName,
17
- loadPassword,
18
- NotFoundError,
19
18
  getNodePath,
19
+ getKeypair,
20
+ getTrustPath,
20
21
  } from "./config.js";
21
22
  import { setMaxListeners } from "events";
22
23
  import { create } from "./peerbit.js";
@@ -31,13 +32,14 @@ import {
31
32
  import {
32
33
  ADDRESS_PATH,
33
34
  BOOTSTRAP_PATH,
34
- TERMINATE_PATH,
35
35
  INSTALL_PATH,
36
- LOCAL_PORT,
36
+ LOCAL_API_PORT,
37
37
  PEER_ID_PATH,
38
38
  PROGRAMS_PATH,
39
39
  PROGRAM_PATH,
40
40
  RESTART_PATH,
41
+ TRUST_PATH,
42
+ STOP_PATH,
41
43
  } from "./routes.js";
42
44
  import { Session } from "./session.js";
43
45
  import fs from "fs";
@@ -50,6 +52,10 @@ import { dirname } from "path";
50
52
  import { fileURLToPath } from "url";
51
53
  import { Level } from "level";
52
54
  import { MemoryLevel } from "memory-level";
55
+ import { Trust } from "./trust.js";
56
+ import { getBody, verifyRequest } from "./signes-request.js";
57
+ import { cli } from "./cli.js";
58
+ import { peerIdFromString } from "@libp2p/peer-id";
53
59
 
54
60
  const __dirname = dirname(fileURLToPath(import.meta.url));
55
61
 
@@ -62,69 +68,34 @@ export const stopAndWait = (server: http.Server) => {
62
68
  return waitFor(() => closed);
63
69
  };
64
70
 
65
- export const createPassword = async (
66
- configDirectory: string,
67
- password?: string
68
- ): Promise<string> => {
69
- const configDir = configDirectory ?? (await getHomeConfigDir());
70
- const credentialsPath = await getCredentialsPath(configDir);
71
- if (!password && (await checkExistPath(credentialsPath))) {
72
- throw new Error(
73
- "Config path for credentials: " + credentialsPath + ", already exist"
74
- );
75
- }
76
- console.log(`Creating config folder ${configDir}`);
77
-
78
- fs.mkdirSync(configDir, { recursive: true });
79
- await waitFor(() => fs.existsSync(configDir));
80
-
81
- console.log(`Created config folder ${configDir}`);
82
-
83
- password = password || uuid();
84
- fs.writeFileSync(
85
- credentialsPath,
86
- JSON.stringify({ username: "admin", password })
87
- );
88
- console.log(`Created credentials at ${credentialsPath}`);
89
- return password!;
90
- };
91
-
92
- export const loadOrCreatePassword = async (
93
- configDirectory: string,
94
- password?: string
95
- ): Promise<string> => {
96
- if (!password) {
97
- try {
98
- return await loadPassword(configDirectory);
99
- } catch (error) {
100
- if (error instanceof NotFoundError) {
101
- return createPassword(configDirectory, password);
102
- }
103
- throw error;
104
- }
105
- } else {
106
- return createPassword(configDirectory, password);
107
- }
108
- };
109
71
  export const startServerWithNode = async (properties: {
110
- directory?: string;
72
+ directory: string;
111
73
  domain?: string;
112
74
  bootstrap?: boolean;
113
75
  newSession?: boolean;
114
- password?: string;
76
+ grantAccess?: string[];
115
77
  ports?: {
116
78
  node: number;
117
79
  api: number;
118
80
  };
119
81
  restart?: () => void;
120
82
  }) => {
83
+ if (!fs.existsSync(properties.directory)) {
84
+ fs.mkdirSync(properties.directory, { recursive: true });
85
+ }
86
+
87
+ const trustPeerIds =
88
+ properties.grantAccess && properties.grantAccess.length > 0
89
+ ? properties.grantAccess.map((x) => peerIdFromString(x))
90
+ : [];
91
+
92
+ const keypair = await getKeypair(properties.directory);
93
+
121
94
  const peer = await create({
122
- directory:
123
- properties.directory != null
124
- ? getNodePath(properties.directory)
125
- : undefined,
95
+ directory: getNodePath(properties.directory),
126
96
  domain: properties.domain,
127
97
  listenPort: properties.ports?.node,
98
+ peerId: await keypair.toPeerId(),
128
99
  });
129
100
 
130
101
  if (properties.bootstrap) {
@@ -134,6 +105,7 @@ export const startServerWithNode = async (properties: {
134
105
  properties.directory != null
135
106
  ? path.join(properties.directory, "session")
136
107
  : undefined;
108
+
137
109
  const session = new Session(
138
110
  sessionDirectory
139
111
  ? new Level<string, Uint8Array>(sessionDirectory, {
@@ -158,14 +130,11 @@ export const startServerWithNode = async (properties: {
158
130
  await session.clear();
159
131
  }
160
132
 
133
+ const trust = new Trust(getTrustPath(properties.directory));
161
134
  const server = await startApiServer(peer, {
162
135
  port: properties.ports?.api,
163
- configDirectory:
164
- properties.directory != null
165
- ? path.join(properties.directory, "server")
166
- : undefined || getHomeConfigDir(),
136
+ trust,
167
137
  session,
168
- password: properties.password,
169
138
  });
170
139
  const printNodeInfo = async () => {
171
140
  console.log("Starting node with address(es): ");
@@ -203,14 +172,16 @@ export const startServerWithNode = async (properties: {
203
172
  });
204
173
  };
205
174
  await shutDownHook(peer, server);
175
+
176
+ if (trustPeerIds.length > 0) {
177
+ for (const id of trustPeerIds) {
178
+ trust.add(getPublicKeyFromPeerId(id).hashcode());
179
+ }
180
+ }
206
181
  return { server, node: peer };
207
182
  };
208
183
 
209
- const getProgramFromPath = (
210
- client: Peerbit,
211
- req: http.IncomingMessage,
212
- pathIndex: number
213
- ): Program | undefined => {
184
+ const getPathValue = (req: http.IncomingMessage, pathIndex: number): string => {
214
185
  if (!req.url) {
215
186
  throw new Error("Missing url");
216
187
  }
@@ -222,7 +193,7 @@ const getProgramFromPath = (
222
193
  throw new Error("Invalid path");
223
194
  }
224
195
  const address = decodeURIComponent(path[pathIndex]);
225
- return client.handler?.items.get(address);
196
+ return address;
226
197
  };
227
198
  function findPeerbitProgramFolder(inputDirectory: string): string | null {
228
199
  let currentDir = path.resolve(inputDirectory);
@@ -254,18 +225,13 @@ function findPeerbitProgramFolder(inputDirectory: string): string | null {
254
225
 
255
226
  export const startApiServer = async (
256
227
  client: ProgramClient,
257
- options: {
258
- configDirectory: string;
228
+ properties: {
229
+ trust: Trust;
259
230
  session?: Session;
260
231
  port?: number;
261
- password?: string;
262
232
  }
263
233
  ): Promise<http.Server> => {
264
- const port = options?.port ?? LOCAL_PORT;
265
- const password = await loadOrCreatePassword(
266
- options.configDirectory,
267
- options?.password
268
- );
234
+ const port = properties?.port ?? LOCAL_API_PORT;
269
235
 
270
236
  const restart = async () => {
271
237
  await client.stop();
@@ -285,43 +251,27 @@ export const startApiServer = async (
285
251
  gid: process.getgid!(),
286
252
  }
287
253
  );
288
-
289
- /* process.on("exit", async () => {
290
- child.kill("SIGINT")
291
- });
292
- process.on("SIGINT", async () => {
293
- child.kill("SIGINT")
294
- }); */
295
254
  process.exit(0);
296
255
  };
256
+ if (!client.peerId.equals(await client.identity.publicKey.toPeerId())) {
257
+ throw new Error("Expecting node identity to equal peerId");
258
+ }
297
259
 
298
- const adminACL = (req: http.IncomingMessage): boolean => {
299
- const auth = req.headers["authorization"];
300
- if (!auth?.startsWith("Basic ")) {
301
- return false;
302
- }
303
- const credentials = auth?.substring("Basic ".length);
304
- const username = credentials.split(":")[0];
305
- if (username !== "admin") {
306
- return false;
260
+ const getVerifiedBody = async (req: http.IncomingMessage) => {
261
+ const body = await getBody(req);
262
+ const result = await verifyRequest(
263
+ req.headers,
264
+ req.method!,
265
+ req.url!,
266
+ body
267
+ );
268
+ if (result.equals(client.identity.publicKey)) {
269
+ return body;
307
270
  }
308
- if (password !== credentials.substring(username.length + 1)) {
309
- return false;
271
+ if (properties.trust.isTrusted(result.hashcode())) {
272
+ return body;
310
273
  }
311
- return true;
312
- };
313
-
314
- const getBody = (
315
- req: http.IncomingMessage,
316
- callback: (body: string) => Promise<void> | void
317
- ) => {
318
- let body = "";
319
- req.on("data", function (d) {
320
- body += d;
321
- });
322
- req.on("end", function () {
323
- callback(body);
324
- });
274
+ throw new Error("Not trusted");
325
275
  };
326
276
 
327
277
  const e404 = "404";
@@ -339,15 +289,20 @@ export const startApiServer = async (
339
289
 
340
290
  try {
341
291
  if (req.url) {
342
- if (
343
- !req.url.startsWith(PEER_ID_PATH) &&
344
- !req.url.startsWith(ADDRESS_PATH) &&
345
- !(await adminACL(req))
346
- ) {
292
+ let body: string;
293
+ try {
294
+ body =
295
+ req.url.startsWith(PEER_ID_PATH) ||
296
+ req.url.startsWith(ADDRESS_PATH)
297
+ ? await getBody(req)
298
+ : await getVerifiedBody(req);
299
+ } catch (error: any) {
347
300
  res.writeHead(401);
348
- res.end("Not authorized");
301
+ res.end("Not authorized: " + error.toString());
349
302
  return;
350
- } else if (req.url.startsWith(PROGRAMS_PATH)) {
303
+ }
304
+
305
+ if (req.url.startsWith(PROGRAMS_PATH)) {
351
306
  if (client instanceof Peerbit === false) {
352
307
  res.writeHead(400);
353
308
  res.end("Server node is not running a native client");
@@ -380,7 +335,9 @@ export const startApiServer = async (
380
335
  switch (req.method) {
381
336
  case "HEAD":
382
337
  try {
383
- const program = getProgramFromPath(client as Peerbit, req, 1);
338
+ const program = (client as Peerbit).handler?.items.get(
339
+ getPathValue(req, 1)
340
+ );
384
341
  if (program) {
385
342
  res.writeHead(200);
386
343
  res.end();
@@ -399,7 +356,9 @@ export const startApiServer = async (
399
356
  const url = new URL(req.url, "http://localhost:" + 1234);
400
357
  const queryData = url.searchParams.get("delete");
401
358
 
402
- const program = getProgramFromPath(client as Peerbit, req, 1);
359
+ const program = (client as Peerbit).handler?.items.get(
360
+ getPathValue(req, 1)
361
+ );
403
362
  if (program) {
404
363
  let closed = false;
405
364
  if (queryData === "true") {
@@ -408,7 +367,9 @@ export const startApiServer = async (
408
367
  closed = await program.close();
409
368
  }
410
369
  if (closed) {
411
- await options?.session?.programs.remove(program.address);
370
+ await properties?.session?.programs.remove(
371
+ program.address
372
+ );
412
373
  }
413
374
 
414
375
  res.writeHead(200);
@@ -423,56 +384,54 @@ export const startApiServer = async (
423
384
  }
424
385
  break;
425
386
  case "PUT":
426
- getBody(req, (body) => {
427
- try {
428
- const startArguments: StartProgram = JSON.parse(body);
429
-
430
- let program: Program;
431
- if ((startArguments as StartByVariant).variant) {
432
- const P = getProgramFromVariant(
433
- (startArguments as StartByVariant).variant
434
- );
435
- if (!P) {
436
- res.writeHead(400);
437
- res.end(
438
- "Missing program with variant: " +
439
- (startArguments as StartByVariant).variant
440
- );
441
- return;
442
- }
443
- program = new P();
444
- } else {
445
- program = deserialize(
446
- fromBase64((startArguments as StartByBase64).base64),
447
- Program
387
+ try {
388
+ const startArguments: StartProgram = JSON.parse(body);
389
+
390
+ let program: Program;
391
+ if ((startArguments as StartByVariant).variant) {
392
+ const P = getProgramFromVariant(
393
+ (startArguments as StartByVariant).variant
394
+ );
395
+ if (!P) {
396
+ res.writeHead(400);
397
+ res.end(
398
+ "Missing program with variant: " +
399
+ (startArguments as StartByVariant).variant
448
400
  );
401
+ return;
449
402
  }
450
- client
451
- .open(program) // TODO all users to pass args
452
- .then(async (program) => {
453
- // TODO what if this is a reopen?
454
- console.log(
455
- "OPEN ADDRESS",
456
- program.address,
457
- (client as Peerbit).directory,
458
- await client.services.blocks.has(program.address)
459
- );
460
- await options?.session?.programs.add(
461
- program.address,
462
- new Uint8Array()
463
- );
464
- res.writeHead(200);
465
- res.end(program.address.toString());
466
- })
467
- .catch((error) => {
468
- res.writeHead(400);
469
- res.end("Failed to open program: " + error.toString());
470
- });
471
- } catch (error: any) {
472
- res.writeHead(400);
473
- res.end(error.toString());
403
+ program = new P();
404
+ } else {
405
+ program = deserialize(
406
+ fromBase64((startArguments as StartByBase64).base64),
407
+ Program
408
+ );
474
409
  }
475
- });
410
+ client
411
+ .open(program) // TODO all users to pass args
412
+ .then(async (program) => {
413
+ // TODO what if this is a reopen?
414
+ console.log(
415
+ "OPEN ADDRESS",
416
+ program.address,
417
+ (client as Peerbit).directory,
418
+ await client.services.blocks.has(program.address)
419
+ );
420
+ await properties?.session?.programs.add(
421
+ program.address,
422
+ new Uint8Array()
423
+ );
424
+ res.writeHead(200);
425
+ res.end(program.address.toString());
426
+ })
427
+ .catch((error) => {
428
+ res.writeHead(400);
429
+ res.end("Failed to open program: " + error.toString());
430
+ });
431
+ } catch (error: any) {
432
+ res.writeHead(400);
433
+ res.end(error.toString());
434
+ }
476
435
  break;
477
436
 
478
437
  default:
@@ -481,105 +440,101 @@ export const startApiServer = async (
481
440
  }
482
441
  } else if (req.url.startsWith(INSTALL_PATH)) {
483
442
  switch (req.method) {
484
- case "PUT":
485
- getBody(req, async (body) => {
486
- const installArgs: InstallDependency = JSON.parse(body);
487
-
488
- const packageName = installArgs.name; // @abc/123
489
- let installName = installArgs.name; // abc123.tgz or @abc/123 (npm package name)
490
- let clear: (() => void) | undefined;
491
- if (installArgs.type === "tgz") {
492
- const binary = fromBase64(installArgs.base64);
493
- const tempFile = tmp.fileSync({
494
- name:
495
- base58btc.encode(Buffer.from(installName)) +
496
- uuid() +
497
- ".tgz",
498
- });
499
- fs.writeFileSync(tempFile.fd, binary);
500
- clear = () => tempFile.removeCallback();
501
- installName = tempFile.name;
502
- } else {
503
- clear = undefined;
504
- }
505
-
506
- if (!installName || installName.length === 0) {
507
- res.writeHead(400);
508
- res.end("Invalid package: " + packageName);
509
- } else {
510
- try {
511
- // TODO do this without sudo. i.e. for servers provide arguments so that this app folder is writeable by default by the user
512
- const installDir =
513
- process.env.PEERBIT_MODULES_PATH ||
514
- findPeerbitProgramFolder(__dirname);
515
- let permission = "";
516
- if (!installDir) {
517
- res.writeHead(400);
518
- res.end("Missing installation directory");
519
- return;
520
- }
521
- try {
522
- fs.accessSync(installDir, fs.constants.W_OK);
523
- } catch (error) {
524
- permission = "sudo";
525
- }
443
+ case "PUT": {
444
+ const installArgs: InstallDependency = JSON.parse(body);
445
+
446
+ const packageName = installArgs.name; // @abc/123
447
+ let installName = installArgs.name; // abc123.tgz or @abc/123 (npm package name)
448
+ let clear: (() => void) | undefined;
449
+ if (installArgs.type === "tgz") {
450
+ const binary = fromBase64(installArgs.base64);
451
+ const tempFile = tmp.fileSync({
452
+ name:
453
+ base58btc.encode(Buffer.from(installName)) +
454
+ uuid() +
455
+ ".tgz",
456
+ });
457
+ fs.writeFileSync(tempFile.fd, binary);
458
+ clear = () => tempFile.removeCallback();
459
+ installName = tempFile.name;
460
+ } else {
461
+ clear = undefined;
462
+ }
526
463
 
527
- console.log("Installing package: " + installName);
528
- execSync(
529
- `${permission} npm install ${installName} --prefix ${installDir} --no-save --no-package-lock`
530
- ); // TODO omit=dev ? but this makes breaks the tests after running once?
531
- } catch (error: any) {
464
+ if (!installName || installName.length === 0) {
465
+ res.writeHead(400);
466
+ res.end("Invalid package: " + packageName);
467
+ } else {
468
+ try {
469
+ // TODO do this without sudo. i.e. for servers provide arguments so that this app folder is writeable by default by the user
470
+ const installDir =
471
+ process.env.PEERBIT_MODULES_PATH ||
472
+ findPeerbitProgramFolder(__dirname);
473
+ let permission = "";
474
+ if (!installDir) {
532
475
  res.writeHead(400);
533
- res.end(
534
- "Failed to install library: " +
535
- packageName +
536
- ". " +
537
- error.toString()
538
- );
539
- clear?.();
476
+ res.end("Missing installation directory");
540
477
  return;
541
478
  }
542
-
543
479
  try {
544
- const programsPre = new Set(
545
- getProgramFromVariants().map(
546
- (x) => getSchema(x).variant
547
- )
548
- );
480
+ fs.accessSync(installDir, fs.constants.W_OK);
481
+ } catch (error) {
482
+ permission = "sudo";
483
+ }
549
484
 
550
- await import(
551
- /* webpackIgnore: true */ /* @vite-ignore */ packageName
552
- );
553
- await options?.session?.imports.add(
554
- packageName,
555
- new Uint8Array()
556
- );
557
- const programsPost = getProgramFromVariants()?.map((x) =>
558
- getSchema(x)
559
- );
560
- const newPrograms: { variant: string }[] = [];
561
- for (const p of programsPost) {
562
- if (!programsPre.has(p.variant)) {
563
- newPrograms.push(p as { variant: string });
564
- }
565
- }
485
+ console.log("Installing package: " + installName);
486
+ execSync(
487
+ `${permission} npm install ${installName} --prefix ${installDir} --no-save --no-package-lock`
488
+ ); // TODO omit=dev ? but this makes breaks the tests after running once?
489
+ } catch (error: any) {
490
+ res.writeHead(400);
491
+ res.end(
492
+ "Failed to install library: " +
493
+ packageName +
494
+ ". " +
495
+ error.toString()
496
+ );
497
+ clear?.();
498
+ return;
499
+ }
566
500
 
567
- res.writeHead(200);
568
- res.end(
569
- JSON.stringify(newPrograms.map((x) => x.variant))
570
- );
571
- } catch (e: any) {
572
- res.writeHead(400);
573
- res.end(e.message.toString?.());
574
- clear?.();
501
+ try {
502
+ const programsPre = new Set(
503
+ getProgramFromVariants().map((x) => getSchema(x).variant)
504
+ );
505
+
506
+ await import(
507
+ /* webpackIgnore: true */ /* @vite-ignore */ packageName
508
+ );
509
+ await properties?.session?.imports.add(
510
+ packageName,
511
+ new Uint8Array()
512
+ );
513
+ const programsPost = getProgramFromVariants()?.map((x) =>
514
+ getSchema(x)
515
+ );
516
+ const newPrograms: { variant: string }[] = [];
517
+ for (const p of programsPost) {
518
+ if (!programsPre.has(p.variant)) {
519
+ newPrograms.push(p as { variant: string });
520
+ }
575
521
  }
522
+
523
+ res.writeHead(200);
524
+ res.end(JSON.stringify(newPrograms.map((x) => x.variant)));
525
+ } catch (e: any) {
526
+ res.writeHead(400);
527
+ res.end(e.message.toString?.());
528
+ clear?.();
576
529
  }
577
- });
530
+ }
578
531
  break;
532
+ }
579
533
 
580
- default:
534
+ default: {
581
535
  r404();
582
536
  break;
537
+ }
583
538
  }
584
539
  } else if (req.url.startsWith(BOOTSTRAP_PATH)) {
585
540
  switch (req.method) {
@@ -598,6 +553,24 @@ export const startApiServer = async (
598
553
  r404();
599
554
  break;
600
555
  }
556
+ } else if (req.url.startsWith(TRUST_PATH)) {
557
+ switch (req.method) {
558
+ case "PUT": {
559
+ properties.trust.add(getPathValue(req, 1));
560
+ res.writeHead(200);
561
+ res.end();
562
+ break;
563
+ }
564
+ case "DELETE": {
565
+ const removed = properties.trust.remove(getPathValue(req, 1));
566
+ res.writeHead(200);
567
+ res.end(removed);
568
+ break;
569
+ }
570
+ default:
571
+ r404();
572
+ break;
573
+ }
601
574
  } else if (req.url.startsWith(RESTART_PATH)) {
602
575
  switch (req.method) {
603
576
  case "POST":
@@ -610,7 +583,7 @@ export const startApiServer = async (
610
583
  r404();
611
584
  break;
612
585
  }
613
- } else if (req.url.startsWith(TERMINATE_PATH)) {
586
+ } else if (req.url.startsWith(STOP_PATH)) {
614
587
  switch (req.method) {
615
588
  case "POST":
616
589
  res.writeHead(200);
@@ -622,7 +595,18 @@ export const startApiServer = async (
622
595
  r404();
623
596
  break;
624
597
  }
625
- } else if (req.url.startsWith(PEER_ID_PATH)) {
598
+ } /* else if (req.url.startsWith(TERMINATE_PATH)) {
599
+ switch (req.method) {
600
+ case "POST":
601
+ execSync("shutdown -h now")
602
+ process.exit(0);
603
+ break;
604
+
605
+ default:
606
+ r404();
607
+ break;
608
+ }
609
+ } */ else if (req.url.startsWith(PEER_ID_PATH)) {
626
610
  res.writeHead(200);
627
611
  res.end(client.peerId.toString());
628
612
  } else if (req.url.startsWith(ADDRESS_PATH)) {