@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
@@ -1,4 +1,5 @@
1
1
  import fs from "fs";
2
+ export const DEFAULT_REMOTE_GROUP = "default";
2
3
  export class Remotes {
3
4
  path;
4
5
  data;
@@ -19,21 +20,19 @@ export class Remotes {
19
20
  getByName(name) {
20
21
  return this.data.remotes.find((x) => x.name === name);
21
22
  }
23
+ getByGroup(group) {
24
+ return this.data.remotes.filter((x) => x.group === group);
25
+ }
22
26
  getByAddress(address) {
23
27
  return this.data.remotes.find((x) => x.address === address);
24
28
  }
25
- add(name, address, password) {
26
- const obj = {
27
- address,
28
- name,
29
- password,
30
- };
31
- const existing = this.data.remotes.findIndex((x) => x.name === name);
29
+ add(remote) {
30
+ const existing = this.data.remotes.findIndex((x) => x.name === remote.name);
32
31
  if (existing >= 0) {
33
- this.data.remotes[existing] = obj;
32
+ this.data.remotes[existing] = remote;
34
33
  }
35
34
  else {
36
- this.data.remotes.push(obj);
35
+ this.data.remotes.push(remote);
37
36
  }
38
37
  this.save();
39
38
  }
@@ -1 +1 @@
1
- {"version":3,"file":"remotes.js","sourceRoot":"","sources":["../../src/remotes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAYpB,MAAM,OAAO,OAAO;IAGE;IAFb,IAAI,CAAgB;IAE5B,YAAqB,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QAChC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;YACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CACrB,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CACtB,CAAC;SACnB;aAAM;YACN,IAAI,CAAC,IAAI,GAAG;gBACX,OAAO,EAAE,EAAE;aACX,CAAC;SACF;IACF,CAAC;IAED,IAAI;QACH,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,SAAS,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACvD,CAAC;IACD,YAAY,CAAC,OAAe;QAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;IAC7D,CAAC;IACD,GAAG,CAAC,IAAY,EAAE,OAAe,EAAE,QAAgB;QAClD,MAAM,GAAG,GAAiB;YACzB,OAAO;YACP,IAAI;YACJ,QAAQ;SACR,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACrE,IAAI,QAAQ,IAAI,CAAC,EAAE;YAClB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC;SAClC;aAAM;YACN,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SAC5B;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;IAED,MAAM,CAAC,IAAY;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACrE,IAAI,QAAQ,IAAI,CAAC,EAAE;YAClB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YACtC,OAAO,IAAI,CAAC;SACZ;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IAED,KAAK,CAAC,GAAG;QACR,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAC1B,CAAC;CACD"}
1
+ {"version":3,"file":"remotes.js","sourceRoot":"","sources":["../../src/remotes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAUpB,MAAM,CAAC,MAAM,oBAAoB,GAAG,SAAS,CAAC;AAa9C,MAAM,OAAO,OAAO;IAGE;IAFb,IAAI,CAAgB;IAE5B,YAAqB,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QAChC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;YACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CACrB,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CACtB,CAAC;SACnB;aAAM;YACN,IAAI,CAAC,IAAI,GAAG;gBACX,OAAO,EAAE,EAAE;aACX,CAAC;SACF;IACF,CAAC;IAED,IAAI;QACH,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,SAAS,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,UAAU,CAAC,KAAa;QACvB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;IAC3D,CAAC;IAED,YAAY,CAAC,OAAe;QAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;IAC7D,CAAC;IAED,GAAG,CAAC,MAAoB;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5E,IAAI,QAAQ,IAAI,CAAC,EAAE;YAClB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;SACrC;aAAM;YACN,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SAC/B;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;IAED,MAAM,CAAC,IAAY;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACrE,IAAI,QAAQ,IAAI,CAAC,EAAE;YAClB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YACtC,OAAO,IAAI,CAAC;SACZ;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IAED,KAAK,CAAC,GAAG;QACR,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAC1B,CAAC;CACD"}
@@ -1,6 +1,7 @@
1
1
  export declare const getPort: (protocol: string) => 9002 | 8082;
2
- export declare const SSL_PORT = 9002;
3
- export declare const LOCAL_PORT = 8082;
2
+ export declare const REMOTE_API_PORT = 9002;
3
+ export declare const LOCAL_API_PORT = 8082;
4
+ export declare const TRUST_PATH = "/trust";
4
5
  export declare const PEER_ID_PATH = "/peer/id";
5
6
  export declare const ADDRESS_PATH = "/peer/address";
6
7
  export declare const PROGRAM_PATH = "/program";
@@ -9,3 +10,4 @@ export declare const INSTALL_PATH = "/install";
9
10
  export declare const BOOTSTRAP_PATH = "/network/bootstrap";
10
11
  export declare const RESTART_PATH = "/restart";
11
12
  export declare const TERMINATE_PATH = "/terminate";
13
+ export declare const STOP_PATH = "/path";
package/lib/esm/routes.js CHANGED
@@ -1,14 +1,15 @@
1
1
  export const getPort = (protocol) => {
2
2
  if (protocol === "https:") {
3
- return SSL_PORT;
3
+ return REMOTE_API_PORT;
4
4
  }
5
5
  if (protocol === "http:") {
6
- return LOCAL_PORT;
6
+ return LOCAL_API_PORT;
7
7
  }
8
8
  throw new Error("Unsupported protocol: " + protocol);
9
9
  };
10
- export const SSL_PORT = 9002;
11
- export const LOCAL_PORT = 8082;
10
+ export const REMOTE_API_PORT = 9002;
11
+ export const LOCAL_API_PORT = 8082;
12
+ export const TRUST_PATH = "/trust";
12
13
  export const PEER_ID_PATH = "/peer/id";
13
14
  export const ADDRESS_PATH = "/peer/address";
14
15
  export const PROGRAM_PATH = "/program";
@@ -17,4 +18,5 @@ export const INSTALL_PATH = "/install";
17
18
  export const BOOTSTRAP_PATH = "/network/bootstrap";
18
19
  export const RESTART_PATH = "/restart";
19
20
  export const TERMINATE_PATH = "/terminate";
21
+ export const STOP_PATH = "/path";
20
22
  //# sourceMappingURL=routes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,QAAgB,EAAE,EAAE;IAC3C,IAAI,QAAQ,KAAK,QAAQ,EAAE;QAC1B,OAAO,QAAQ,CAAC;KAChB;IAED,IAAI,QAAQ,KAAK,OAAO,EAAE;QACzB,OAAO,UAAU,CAAC;KAClB;IAED,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,QAAQ,CAAC,CAAC;AACtD,CAAC,CAAC;AACF,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC;AAC7B,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC;AAE/B,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,eAAe,CAAC;AAC5C,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AACvC,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AACzC,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,oBAAoB,CAAC;AACnD,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,YAAY,CAAC"}
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,QAAgB,EAAE,EAAE;IAC3C,IAAI,QAAQ,KAAK,QAAQ,EAAE;QAC1B,OAAO,eAAe,CAAC;KACvB;IAED,IAAI,QAAQ,KAAK,OAAO,EAAE;QACzB,OAAO,cAAc,CAAC;KACtB;IAED,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,QAAQ,CAAC,CAAC;AACtD,CAAC,CAAC;AACF,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC;AACpC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AACnC,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC;AACnC,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,eAAe,CAAC;AAC5C,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AACvC,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AACzC,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,oBAAoB,CAAC;AACnD,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,YAAY,CAAC;AAC3C,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC"}
@@ -3,15 +3,14 @@ import http from "http";
3
3
  import { ProgramClient } from "@peerbit/program";
4
4
  import { Peerbit } from "peerbit";
5
5
  import { Session } from "./session.js";
6
+ import { Trust } from "./trust.js";
6
7
  export declare const stopAndWait: (server: http.Server) => Promise<boolean | undefined>;
7
- export declare const createPassword: (configDirectory: string, password?: string) => Promise<string>;
8
- export declare const loadOrCreatePassword: (configDirectory: string, password?: string) => Promise<string>;
9
8
  export declare const startServerWithNode: (properties: {
10
- directory?: string;
9
+ directory: string;
11
10
  domain?: string;
12
11
  bootstrap?: boolean;
13
12
  newSession?: boolean;
14
- password?: string;
13
+ grantAccess?: string[];
15
14
  ports?: {
16
15
  node: number;
17
16
  api: number;
@@ -21,9 +20,8 @@ export declare const startServerWithNode: (properties: {
21
20
  server: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
22
21
  node: Peerbit;
23
22
  }>;
24
- export declare const startApiServer: (client: ProgramClient, options: {
25
- configDirectory: string;
23
+ export declare const startApiServer: (client: ProgramClient, properties: {
24
+ trust: Trust;
26
25
  session?: Session;
27
26
  port?: number;
28
- password?: string;
29
27
  }) => Promise<http.Server>;
package/lib/esm/server.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import http from "http";
2
- import { fromBase64 } from "@peerbit/crypto";
2
+ import { fromBase64, getPublicKeyFromPeerId, } from "@peerbit/crypto";
3
3
  import { deserialize } from "@dao-xyz/borsh";
4
4
  import { Program, getProgramFromVariant, getProgramFromVariants, } from "@peerbit/program";
5
5
  import { waitFor } from "@peerbit/time";
6
6
  import { v4 as uuid } from "uuid";
7
- import { checkExistPath, getHomeConfigDir, getCredentialsPath, loadPassword, NotFoundError, getNodePath, } from "./config.js";
7
+ import { getNodePath, getKeypair, getTrustPath, } from "./config.js";
8
8
  import { setMaxListeners } from "events";
9
9
  import { create } from "./peerbit.js";
10
10
  import { Peerbit } from "peerbit";
11
11
  import { getSchema } from "@dao-xyz/borsh";
12
- import { ADDRESS_PATH, BOOTSTRAP_PATH, TERMINATE_PATH, INSTALL_PATH, LOCAL_PORT, PEER_ID_PATH, PROGRAMS_PATH, PROGRAM_PATH, RESTART_PATH, } from "./routes.js";
12
+ import { ADDRESS_PATH, BOOTSTRAP_PATH, INSTALL_PATH, LOCAL_API_PORT, PEER_ID_PATH, PROGRAMS_PATH, PROGRAM_PATH, RESTART_PATH, TRUST_PATH, STOP_PATH, } from "./routes.js";
13
13
  import { Session } from "./session.js";
14
14
  import fs from "fs";
15
15
  import { exit } from "process";
@@ -21,6 +21,9 @@ import { dirname } from "path";
21
21
  import { fileURLToPath } from "url";
22
22
  import { Level } from "level";
23
23
  import { MemoryLevel } from "memory-level";
24
+ import { Trust } from "./trust.js";
25
+ import { getBody, verifyRequest } from "./signes-request.js";
26
+ import { peerIdFromString } from "@libp2p/peer-id";
24
27
  const __dirname = dirname(fileURLToPath(import.meta.url));
25
28
  export const stopAndWait = (server) => {
26
29
  let closed = false;
@@ -30,44 +33,19 @@ export const stopAndWait = (server) => {
30
33
  server.close();
31
34
  return waitFor(() => closed);
32
35
  };
33
- export const createPassword = async (configDirectory, password) => {
34
- const configDir = configDirectory ?? (await getHomeConfigDir());
35
- const credentialsPath = await getCredentialsPath(configDir);
36
- if (!password && (await checkExistPath(credentialsPath))) {
37
- throw new Error("Config path for credentials: " + credentialsPath + ", already exist");
38
- }
39
- console.log(`Creating config folder ${configDir}`);
40
- fs.mkdirSync(configDir, { recursive: true });
41
- await waitFor(() => fs.existsSync(configDir));
42
- console.log(`Created config folder ${configDir}`);
43
- password = password || uuid();
44
- fs.writeFileSync(credentialsPath, JSON.stringify({ username: "admin", password }));
45
- console.log(`Created credentials at ${credentialsPath}`);
46
- return password;
47
- };
48
- export const loadOrCreatePassword = async (configDirectory, password) => {
49
- if (!password) {
50
- try {
51
- return await loadPassword(configDirectory);
52
- }
53
- catch (error) {
54
- if (error instanceof NotFoundError) {
55
- return createPassword(configDirectory, password);
56
- }
57
- throw error;
58
- }
59
- }
60
- else {
61
- return createPassword(configDirectory, password);
62
- }
63
- };
64
36
  export const startServerWithNode = async (properties) => {
37
+ if (!fs.existsSync(properties.directory)) {
38
+ fs.mkdirSync(properties.directory, { recursive: true });
39
+ }
40
+ const trustPeerIds = properties.grantAccess && properties.grantAccess.length > 0
41
+ ? properties.grantAccess.map((x) => peerIdFromString(x))
42
+ : [];
43
+ const keypair = await getKeypair(properties.directory);
65
44
  const peer = await create({
66
- directory: properties.directory != null
67
- ? getNodePath(properties.directory)
68
- : undefined,
45
+ directory: getNodePath(properties.directory),
69
46
  domain: properties.domain,
70
47
  listenPort: properties.ports?.node,
48
+ peerId: await keypair.toPeerId(),
71
49
  });
72
50
  if (properties.bootstrap) {
73
51
  await peer.bootstrap();
@@ -98,13 +76,11 @@ export const startServerWithNode = async (properties) => {
98
76
  else {
99
77
  await session.clear();
100
78
  }
79
+ const trust = new Trust(getTrustPath(properties.directory));
101
80
  const server = await startApiServer(peer, {
102
81
  port: properties.ports?.api,
103
- configDirectory: properties.directory != null
104
- ? path.join(properties.directory, "server")
105
- : undefined || getHomeConfigDir(),
82
+ trust,
106
83
  session,
107
- password: properties.password,
108
84
  });
109
85
  const printNodeInfo = async () => {
110
86
  console.log("Starting node with address(es): ");
@@ -138,9 +114,14 @@ export const startServerWithNode = async (properties) => {
138
114
  });
139
115
  };
140
116
  await shutDownHook(peer, server);
117
+ if (trustPeerIds.length > 0) {
118
+ for (const id of trustPeerIds) {
119
+ trust.add(getPublicKeyFromPeerId(id).hashcode());
120
+ }
121
+ }
141
122
  return { server, node: peer };
142
123
  };
143
- const getProgramFromPath = (client, req, pathIndex) => {
124
+ const getPathValue = (req, pathIndex) => {
144
125
  if (!req.url) {
145
126
  throw new Error("Missing url");
146
127
  }
@@ -152,7 +133,7 @@ const getProgramFromPath = (client, req, pathIndex) => {
152
133
  throw new Error("Invalid path");
153
134
  }
154
135
  const address = decodeURIComponent(path[pathIndex]);
155
- return client.handler?.items.get(address);
136
+ return address;
156
137
  };
157
138
  function findPeerbitProgramFolder(inputDirectory) {
158
139
  let currentDir = path.resolve(inputDirectory);
@@ -171,9 +152,8 @@ function findPeerbitProgramFolder(inputDirectory) {
171
152
  }
172
153
  return null;
173
154
  }
174
- export const startApiServer = async (client, options) => {
175
- const port = options?.port ?? LOCAL_PORT;
176
- const password = await loadOrCreatePassword(options.configDirectory, options?.password);
155
+ export const startApiServer = async (client, properties) => {
156
+ const port = properties?.port ?? LOCAL_API_PORT;
177
157
  const restart = async () => {
178
158
  await client.stop();
179
159
  await stopAndWait(server);
@@ -187,37 +167,21 @@ export const startApiServer = async (client, options) => {
187
167
  stdio: "inherit",
188
168
  gid: process.getgid(),
189
169
  });
190
- /* process.on("exit", async () => {
191
- child.kill("SIGINT")
192
- });
193
- process.on("SIGINT", async () => {
194
- child.kill("SIGINT")
195
- }); */
196
170
  process.exit(0);
197
171
  };
198
- const adminACL = (req) => {
199
- const auth = req.headers["authorization"];
200
- if (!auth?.startsWith("Basic ")) {
201
- return false;
202
- }
203
- const credentials = auth?.substring("Basic ".length);
204
- const username = credentials.split(":")[0];
205
- if (username !== "admin") {
206
- return false;
172
+ if (!client.peerId.equals(await client.identity.publicKey.toPeerId())) {
173
+ throw new Error("Expecting node identity to equal peerId");
174
+ }
175
+ const getVerifiedBody = async (req) => {
176
+ const body = await getBody(req);
177
+ const result = await verifyRequest(req.headers, req.method, req.url, body);
178
+ if (result.equals(client.identity.publicKey)) {
179
+ return body;
207
180
  }
208
- if (password !== credentials.substring(username.length + 1)) {
209
- return false;
181
+ if (properties.trust.isTrusted(result.hashcode())) {
182
+ return body;
210
183
  }
211
- return true;
212
- };
213
- const getBody = (req, callback) => {
214
- let body = "";
215
- req.on("data", function (d) {
216
- body += d;
217
- });
218
- req.on("end", function () {
219
- callback(body);
220
- });
184
+ throw new Error("Not trusted");
221
185
  };
222
186
  const e404 = "404";
223
187
  const endpoints = (client) => {
@@ -232,14 +196,20 @@ export const startApiServer = async (client, options) => {
232
196
  };
233
197
  try {
234
198
  if (req.url) {
235
- if (!req.url.startsWith(PEER_ID_PATH) &&
236
- !req.url.startsWith(ADDRESS_PATH) &&
237
- !(await adminACL(req))) {
199
+ let body;
200
+ try {
201
+ body =
202
+ req.url.startsWith(PEER_ID_PATH) ||
203
+ req.url.startsWith(ADDRESS_PATH)
204
+ ? await getBody(req)
205
+ : await getVerifiedBody(req);
206
+ }
207
+ catch (error) {
238
208
  res.writeHead(401);
239
- res.end("Not authorized");
209
+ res.end("Not authorized: " + error.toString());
240
210
  return;
241
211
  }
242
- else if (req.url.startsWith(PROGRAMS_PATH)) {
212
+ if (req.url.startsWith(PROGRAMS_PATH)) {
243
213
  if (client instanceof Peerbit === false) {
244
214
  res.writeHead(400);
245
215
  res.end("Server node is not running a native client");
@@ -273,7 +243,7 @@ export const startApiServer = async (client, options) => {
273
243
  switch (req.method) {
274
244
  case "HEAD":
275
245
  try {
276
- const program = getProgramFromPath(client, req, 1);
246
+ const program = client.handler?.items.get(getPathValue(req, 1));
277
247
  if (program) {
278
248
  res.writeHead(200);
279
249
  res.end();
@@ -292,7 +262,7 @@ export const startApiServer = async (client, options) => {
292
262
  try {
293
263
  const url = new URL(req.url, "http://localhost:" + 1234);
294
264
  const queryData = url.searchParams.get("delete");
295
- const program = getProgramFromPath(client, req, 1);
265
+ const program = client.handler?.items.get(getPathValue(req, 1));
296
266
  if (program) {
297
267
  let closed = false;
298
268
  if (queryData === "true") {
@@ -302,7 +272,7 @@ export const startApiServer = async (client, options) => {
302
272
  closed = await program.close();
303
273
  }
304
274
  if (closed) {
305
- await options?.session?.programs.remove(program.address);
275
+ await properties?.session?.programs.remove(program.address);
306
276
  }
307
277
  res.writeHead(200);
308
278
  res.end();
@@ -318,42 +288,40 @@ export const startApiServer = async (client, options) => {
318
288
  }
319
289
  break;
320
290
  case "PUT":
321
- getBody(req, (body) => {
322
- try {
323
- const startArguments = JSON.parse(body);
324
- let program;
325
- if (startArguments.variant) {
326
- const P = getProgramFromVariant(startArguments.variant);
327
- if (!P) {
328
- res.writeHead(400);
329
- res.end("Missing program with variant: " +
330
- startArguments.variant);
331
- return;
332
- }
333
- program = new P();
334
- }
335
- else {
336
- program = deserialize(fromBase64(startArguments.base64), Program);
337
- }
338
- client
339
- .open(program) // TODO all users to pass args
340
- .then(async (program) => {
341
- // TODO what if this is a reopen?
342
- console.log("OPEN ADDRESS", program.address, client.directory, await client.services.blocks.has(program.address));
343
- await options?.session?.programs.add(program.address, new Uint8Array());
344
- res.writeHead(200);
345
- res.end(program.address.toString());
346
- })
347
- .catch((error) => {
291
+ try {
292
+ const startArguments = JSON.parse(body);
293
+ let program;
294
+ if (startArguments.variant) {
295
+ const P = getProgramFromVariant(startArguments.variant);
296
+ if (!P) {
348
297
  res.writeHead(400);
349
- res.end("Failed to open program: " + error.toString());
350
- });
298
+ res.end("Missing program with variant: " +
299
+ startArguments.variant);
300
+ return;
301
+ }
302
+ program = new P();
351
303
  }
352
- catch (error) {
353
- res.writeHead(400);
354
- res.end(error.toString());
304
+ else {
305
+ program = deserialize(fromBase64(startArguments.base64), Program);
355
306
  }
356
- });
307
+ client
308
+ .open(program) // TODO all users to pass args
309
+ .then(async (program) => {
310
+ // TODO what if this is a reopen?
311
+ console.log("OPEN ADDRESS", program.address, client.directory, await client.services.blocks.has(program.address));
312
+ await properties?.session?.programs.add(program.address, new Uint8Array());
313
+ res.writeHead(200);
314
+ res.end(program.address.toString());
315
+ })
316
+ .catch((error) => {
317
+ res.writeHead(400);
318
+ res.end("Failed to open program: " + error.toString());
319
+ });
320
+ }
321
+ catch (error) {
322
+ res.writeHead(400);
323
+ res.end(error.toString());
324
+ }
357
325
  break;
358
326
  default:
359
327
  r404();
@@ -362,85 +330,85 @@ export const startApiServer = async (client, options) => {
362
330
  }
363
331
  else if (req.url.startsWith(INSTALL_PATH)) {
364
332
  switch (req.method) {
365
- case "PUT":
366
- getBody(req, async (body) => {
367
- const installArgs = JSON.parse(body);
368
- const packageName = installArgs.name; // @abc/123
369
- let installName = installArgs.name; // abc123.tgz or @abc/123 (npm package name)
370
- let clear;
371
- if (installArgs.type === "tgz") {
372
- const binary = fromBase64(installArgs.base64);
373
- const tempFile = tmp.fileSync({
374
- name: base58btc.encode(Buffer.from(installName)) +
375
- uuid() +
376
- ".tgz",
377
- });
378
- fs.writeFileSync(tempFile.fd, binary);
379
- clear = () => tempFile.removeCallback();
380
- installName = tempFile.name;
381
- }
382
- else {
383
- clear = undefined;
384
- }
385
- if (!installName || installName.length === 0) {
386
- res.writeHead(400);
387
- res.end("Invalid package: " + packageName);
388
- }
389
- else {
390
- try {
391
- // TODO do this without sudo. i.e. for servers provide arguments so that this app folder is writeable by default by the user
392
- const installDir = process.env.PEERBIT_MODULES_PATH ||
393
- findPeerbitProgramFolder(__dirname);
394
- let permission = "";
395
- if (!installDir) {
396
- res.writeHead(400);
397
- res.end("Missing installation directory");
398
- return;
399
- }
400
- try {
401
- fs.accessSync(installDir, fs.constants.W_OK);
402
- }
403
- catch (error) {
404
- permission = "sudo";
405
- }
406
- console.log("Installing package: " + installName);
407
- execSync(`${permission} npm install ${installName} --prefix ${installDir} --no-save --no-package-lock`); // TODO omit=dev ? but this makes breaks the tests after running once?
408
- }
409
- catch (error) {
333
+ case "PUT": {
334
+ const installArgs = JSON.parse(body);
335
+ const packageName = installArgs.name; // @abc/123
336
+ let installName = installArgs.name; // abc123.tgz or @abc/123 (npm package name)
337
+ let clear;
338
+ if (installArgs.type === "tgz") {
339
+ const binary = fromBase64(installArgs.base64);
340
+ const tempFile = tmp.fileSync({
341
+ name: base58btc.encode(Buffer.from(installName)) +
342
+ uuid() +
343
+ ".tgz",
344
+ });
345
+ fs.writeFileSync(tempFile.fd, binary);
346
+ clear = () => tempFile.removeCallback();
347
+ installName = tempFile.name;
348
+ }
349
+ else {
350
+ clear = undefined;
351
+ }
352
+ if (!installName || installName.length === 0) {
353
+ res.writeHead(400);
354
+ res.end("Invalid package: " + packageName);
355
+ }
356
+ else {
357
+ try {
358
+ // TODO do this without sudo. i.e. for servers provide arguments so that this app folder is writeable by default by the user
359
+ const installDir = process.env.PEERBIT_MODULES_PATH ||
360
+ findPeerbitProgramFolder(__dirname);
361
+ let permission = "";
362
+ if (!installDir) {
410
363
  res.writeHead(400);
411
- res.end("Failed to install library: " +
412
- packageName +
413
- ". " +
414
- error.toString());
415
- clear?.();
364
+ res.end("Missing installation directory");
416
365
  return;
417
366
  }
418
367
  try {
419
- const programsPre = new Set(getProgramFromVariants().map((x) => getSchema(x).variant));
420
- await import(
421
- /* webpackIgnore: true */ /* @vite-ignore */ packageName);
422
- await options?.session?.imports.add(packageName, new Uint8Array());
423
- const programsPost = getProgramFromVariants()?.map((x) => getSchema(x));
424
- const newPrograms = [];
425
- for (const p of programsPost) {
426
- if (!programsPre.has(p.variant)) {
427
- newPrograms.push(p);
428
- }
429
- }
430
- res.writeHead(200);
431
- res.end(JSON.stringify(newPrograms.map((x) => x.variant)));
368
+ fs.accessSync(installDir, fs.constants.W_OK);
432
369
  }
433
- catch (e) {
434
- res.writeHead(400);
435
- res.end(e.message.toString?.());
436
- clear?.();
370
+ catch (error) {
371
+ permission = "sudo";
437
372
  }
373
+ console.log("Installing package: " + installName);
374
+ execSync(`${permission} npm install ${installName} --prefix ${installDir} --no-save --no-package-lock`); // TODO omit=dev ? but this makes breaks the tests after running once?
375
+ }
376
+ catch (error) {
377
+ res.writeHead(400);
378
+ res.end("Failed to install library: " +
379
+ packageName +
380
+ ". " +
381
+ error.toString());
382
+ clear?.();
383
+ return;
384
+ }
385
+ try {
386
+ const programsPre = new Set(getProgramFromVariants().map((x) => getSchema(x).variant));
387
+ await import(
388
+ /* webpackIgnore: true */ /* @vite-ignore */ packageName);
389
+ await properties?.session?.imports.add(packageName, new Uint8Array());
390
+ const programsPost = getProgramFromVariants()?.map((x) => getSchema(x));
391
+ const newPrograms = [];
392
+ for (const p of programsPost) {
393
+ if (!programsPre.has(p.variant)) {
394
+ newPrograms.push(p);
395
+ }
396
+ }
397
+ res.writeHead(200);
398
+ res.end(JSON.stringify(newPrograms.map((x) => x.variant)));
399
+ }
400
+ catch (e) {
401
+ res.writeHead(400);
402
+ res.end(e.message.toString?.());
403
+ clear?.();
438
404
  }
439
- });
405
+ }
440
406
  break;
441
- default:
407
+ }
408
+ default: {
442
409
  r404();
443
410
  break;
411
+ }
444
412
  }
445
413
  }
446
414
  else if (req.url.startsWith(BOOTSTRAP_PATH)) {
@@ -460,6 +428,25 @@ export const startApiServer = async (client, options) => {
460
428
  break;
461
429
  }
462
430
  }
431
+ else if (req.url.startsWith(TRUST_PATH)) {
432
+ switch (req.method) {
433
+ case "PUT": {
434
+ properties.trust.add(getPathValue(req, 1));
435
+ res.writeHead(200);
436
+ res.end();
437
+ break;
438
+ }
439
+ case "DELETE": {
440
+ const removed = properties.trust.remove(getPathValue(req, 1));
441
+ res.writeHead(200);
442
+ res.end(removed);
443
+ break;
444
+ }
445
+ default:
446
+ r404();
447
+ break;
448
+ }
449
+ }
463
450
  else if (req.url.startsWith(RESTART_PATH)) {
464
451
  switch (req.method) {
465
452
  case "POST":
@@ -472,7 +459,7 @@ export const startApiServer = async (client, options) => {
472
459
  break;
473
460
  }
474
461
  }
475
- else if (req.url.startsWith(TERMINATE_PATH)) {
462
+ else if (req.url.startsWith(STOP_PATH)) {
476
463
  switch (req.method) {
477
464
  case "POST":
478
465
  res.writeHead(200);
@@ -483,7 +470,18 @@ export const startApiServer = async (client, options) => {
483
470
  r404();
484
471
  break;
485
472
  }
486
- }
473
+ } /* else if (req.url.startsWith(TERMINATE_PATH)) {
474
+ switch (req.method) {
475
+ case "POST":
476
+ execSync("shutdown -h now")
477
+ process.exit(0);
478
+ break;
479
+
480
+ default:
481
+ r404();
482
+ break;
483
+ }
484
+ } */
487
485
  else if (req.url.startsWith(PEER_ID_PATH)) {
488
486
  res.writeHead(200);
489
487
  res.end(client.peerId.toString());