@synnaxlabs/client 0.25.0 → 0.26.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.
- package/.turbo/turbo-build.log +5 -5
- package/dist/access/access.spec.d.ts +2 -0
- package/dist/access/access.spec.d.ts.map +1 -0
- package/dist/access/client.d.ts +13 -0
- package/dist/access/client.d.ts.map +1 -0
- package/dist/access/external.d.ts +3 -0
- package/dist/access/external.d.ts.map +1 -0
- package/dist/access/index.d.ts +2 -0
- package/dist/access/index.d.ts.map +1 -0
- package/dist/access/payload.d.ts +105 -0
- package/dist/access/payload.d.ts.map +1 -0
- package/dist/auth/auth.d.ts.map +1 -1
- package/dist/channel/payload.d.ts +17 -14
- package/dist/channel/payload.d.ts.map +1 -1
- package/dist/channel/retriever.d.ts +7 -7
- package/dist/client.cjs +18 -18
- package/dist/client.d.ts +4 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2177 -2103
- package/dist/control/state.d.ts +1 -1
- package/dist/control/state.d.ts.map +1 -1
- package/dist/framer/client.d.ts.map +1 -1
- package/dist/framer/deleter.d.ts +1 -1
- package/dist/framer/deleter.d.ts.map +1 -1
- package/dist/hardware/device/client.d.ts +1 -66
- package/dist/hardware/device/client.d.ts.map +1 -1
- package/dist/hardware/device/external.d.ts +1 -0
- package/dist/hardware/device/external.d.ts.map +1 -1
- package/dist/hardware/device/index.d.ts +1 -1
- package/dist/hardware/device/index.d.ts.map +1 -1
- package/dist/hardware/device/payload.d.ts +73 -0
- package/dist/hardware/device/payload.d.ts.map +1 -0
- package/dist/hardware/rack/client.d.ts +2 -25
- package/dist/hardware/rack/client.d.ts.map +1 -1
- package/dist/hardware/rack/external.d.ts +1 -0
- package/dist/hardware/rack/external.d.ts.map +1 -1
- package/dist/hardware/rack/payload.d.ts +30 -0
- package/dist/hardware/rack/payload.d.ts.map +1 -0
- package/dist/hardware/task/client.d.ts +1 -145
- package/dist/hardware/task/client.d.ts.map +1 -1
- package/dist/hardware/task/external.d.ts +3 -0
- package/dist/hardware/task/external.d.ts.map +1 -0
- package/dist/hardware/task/index.d.ts +1 -1
- package/dist/hardware/task/index.d.ts.map +1 -1
- package/dist/hardware/task/payload.d.ts +151 -0
- package/dist/hardware/task/payload.d.ts.map +1 -0
- package/dist/label/payload.d.ts +1 -0
- package/dist/label/payload.d.ts.map +1 -1
- package/dist/ontology/client.d.ts +5 -5
- package/dist/ontology/payload.d.ts +40 -37
- package/dist/ontology/payload.d.ts.map +1 -1
- package/dist/ranger/payload.d.ts +5 -0
- package/dist/ranger/payload.d.ts.map +1 -1
- package/dist/setupspecs.d.ts.map +1 -1
- package/dist/signals/observable.d.ts +1 -1
- package/dist/signals/observable.d.ts.map +1 -1
- package/dist/user/client.d.ts +9 -0
- package/dist/user/client.d.ts.map +1 -0
- package/dist/user/external.d.ts +3 -0
- package/dist/user/external.d.ts.map +1 -0
- package/dist/user/index.d.ts +1 -1
- package/dist/user/index.d.ts.map +1 -1
- package/dist/user/payload.d.ts +5 -0
- package/dist/user/payload.d.ts.map +1 -1
- package/dist/workspace/lineplot/payload.d.ts +3 -0
- package/dist/workspace/lineplot/payload.d.ts.map +1 -1
- package/dist/workspace/payload.d.ts +3 -0
- package/dist/workspace/payload.d.ts.map +1 -1
- package/dist/workspace/schematic/payload.d.ts +3 -0
- package/dist/workspace/schematic/payload.d.ts.map +1 -1
- package/examples/node/package.json +1 -1
- package/package.json +5 -5
- package/src/access/access.spec.ts +276 -0
- package/src/access/client.ts +86 -0
- package/src/access/external.ts +11 -0
- package/src/access/index.ts +10 -0
- package/src/access/payload.ts +35 -0
- package/src/auth/auth.ts +1 -1
- package/src/channel/payload.ts +7 -0
- package/src/client.ts +7 -1
- package/src/control/state.ts +3 -3
- package/src/framer/client.ts +1 -0
- package/src/framer/deleter.ts +2 -4
- package/src/hardware/device/client.ts +8 -36
- package/src/hardware/device/external.ts +1 -0
- package/src/hardware/device/index.ts +1 -1
- package/src/hardware/device/payload.ts +44 -0
- package/src/hardware/rack/client.ts +10 -15
- package/src/hardware/rack/external.ts +1 -0
- package/src/hardware/rack/payload.ts +23 -0
- package/src/hardware/task/client.ts +1 -84
- package/src/hardware/task/external.ts +11 -0
- package/src/hardware/task/index.ts +1 -1
- package/src/hardware/task/payload.ts +92 -0
- package/src/label/payload.ts +3 -1
- package/src/ontology/payload.ts +6 -1
- package/src/ranger/payload.ts +11 -0
- package/src/setupspecs.ts +4 -2
- package/src/signals/observable.ts +5 -3
- package/src/transport.ts +3 -3
- package/src/user/client.ts +37 -0
- package/src/user/external.ts +11 -0
- package/src/user/index.ts +1 -1
- package/src/user/payload.ts +11 -0
- package/src/workspace/lineplot/payload.ts +7 -0
- package/src/workspace/payload.ts +7 -0
- package/src/workspace/schematic/payload.ts +7 -0
- package/tsconfig.json +4 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../src/workspace/lineplot/payload.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,IAAI,aAAoB,CAAC;AACtC,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AACvC,MAAM,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AAEjC,eAAO,MAAM,SAAS;;;;;;;;;;;;EAIpB,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../src/workspace/lineplot/payload.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,eAAO,MAAM,IAAI,aAAoB,CAAC;AACtC,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AACvC,MAAM,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AAEjC,eAAO,MAAM,SAAS;;;;;;;;;;;;EAIpB,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAEjD,eAAO,MAAM,oBAAoB,EAAiB,QAAQ,CAAC,YAAY,CAAC;AAExE,eAAO,MAAM,UAAU,QAAS,GAAG,KAAG,QAAQ,CAAC,EACY,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UnknownRecord } from '@synnaxlabs/x/record';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import { ontology } from '../ontology';
|
|
3
4
|
|
|
4
5
|
export declare const keyZ: z.ZodString;
|
|
5
6
|
export type Key = z.infer<typeof keyZ>;
|
|
@@ -33,4 +34,6 @@ export declare const workspaceRemoteZ: z.ZodObject<z.objectUtil.extendShape<Omit
|
|
|
33
34
|
layout: string;
|
|
34
35
|
}>;
|
|
35
36
|
export type Workspace = z.infer<typeof workspaceZ>;
|
|
37
|
+
export declare const WorkspaceOntologyType: ontology.ResourceType;
|
|
38
|
+
export declare const ontologyID: (key: Key) => ontology.ID;
|
|
36
39
|
//# sourceMappingURL=payload.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/workspace/payload.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,IAAI,aAAoB,CAAC;AAEtC,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAEvC,MAAM,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AAUjC,eAAO,MAAM,UAAU;;;;;;;;;;;;EAIrB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;EAE3B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/workspace/payload.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,eAAO,MAAM,IAAI,aAAoB,CAAC;AAEtC,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAEvC,MAAM,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AAUjC,eAAO,MAAM,UAAU;;;;;;;;;;;;EAIrB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;EAE3B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEnD,eAAO,MAAM,qBAAqB,EAAkB,QAAQ,CAAC,YAAY,CAAC;AAE1E,eAAO,MAAM,UAAU,QAAS,GAAG,KAAG,QAAQ,CAAC,EACa,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UnknownRecord } from '@synnaxlabs/x/record';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import { ontology } from '../../ontology';
|
|
3
4
|
|
|
4
5
|
export declare const keyZ: z.ZodString;
|
|
5
6
|
export type Key = z.infer<typeof keyZ>;
|
|
@@ -37,4 +38,6 @@ export declare const schematicRemoteZ: z.ZodObject<{
|
|
|
37
38
|
snapshot: boolean;
|
|
38
39
|
}>;
|
|
39
40
|
export type Schematic = z.infer<typeof schematicZ>;
|
|
41
|
+
export declare const SchematicOntologyType: ontology.ResourceType;
|
|
42
|
+
export declare const ontologyID: (key: Key) => ontology.ID;
|
|
40
43
|
//# sourceMappingURL=payload.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../src/workspace/schematic/payload.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,IAAI,aAAoB,CAAC;AACtC,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AACvC,MAAM,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AAEjC,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;EAKrB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;EAK3B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../src/workspace/schematic/payload.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,eAAO,MAAM,IAAI,aAAoB,CAAC;AACtC,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AACvC,MAAM,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AAEjC,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;EAKrB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;EAK3B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEnD,eAAO,MAAM,qBAAqB,EAAkB,QAAQ,CAAC,YAAY,CAAC;AAE1E,eAAO,MAAM,UAAU,QAAS,GAAG,KAAG,QAAQ,CAAC,EACa,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synnaxlabs/client",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.26.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The Client Library for Synnax",
|
|
7
7
|
"repository": "https://github.com/synnaxlabs/synnax/tree/main/client/ts",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"async-mutex": "^0.5.0",
|
|
20
20
|
"zod": "3.23.8",
|
|
21
|
-
"@synnaxlabs/freighter": "0.
|
|
22
|
-
"@synnaxlabs/x": "0.
|
|
21
|
+
"@synnaxlabs/freighter": "0.26.0",
|
|
22
|
+
"@synnaxlabs/x": "0.26.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/node": "^20.14.9",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"vite": "5.3.3",
|
|
30
30
|
"vitest": "^1.6.0",
|
|
31
31
|
"@synnaxlabs/tsconfig": "0.0.2",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
32
|
+
"eslint-config-synnaxlabs": "0.0.1",
|
|
33
|
+
"@synnaxlabs/vite-plugin": "0.0.1"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"zod": "^3.23.8"
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
// Copyright 2024 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
import { DataType, id, Rate } from "@synnaxlabs/x";
|
|
11
|
+
import { describe, expect, test } from "vitest";
|
|
12
|
+
|
|
13
|
+
import { Policy } from "@/access/payload";
|
|
14
|
+
import { Channel } from "@/channel/client";
|
|
15
|
+
import { ChannelOntologyType } from "@/channel/payload";
|
|
16
|
+
import Synnax from "@/client";
|
|
17
|
+
import { AuthError } from "@/errors";
|
|
18
|
+
import { LabelOntologyType } from "@/label/payload";
|
|
19
|
+
import { HOST, newClient, PORT } from "@/setupspecs";
|
|
20
|
+
import { UserOntologyType } from "@/user/payload";
|
|
21
|
+
|
|
22
|
+
const client = newClient();
|
|
23
|
+
|
|
24
|
+
describe("Policy", () => {
|
|
25
|
+
describe("create", () => {
|
|
26
|
+
test("create one", async () => {
|
|
27
|
+
const policy = await client.access.create({
|
|
28
|
+
subjects: [{ type: UserOntologyType, key: "1" }],
|
|
29
|
+
objects: [
|
|
30
|
+
{ type: UserOntologyType, key: "2" },
|
|
31
|
+
{ type: ChannelOntologyType, key: "3" },
|
|
32
|
+
],
|
|
33
|
+
actions: ["update"],
|
|
34
|
+
});
|
|
35
|
+
expect(policy.key).not.toEqual("");
|
|
36
|
+
expect(policy.subjects).toEqual([{ type: UserOntologyType, key: "1" }]);
|
|
37
|
+
expect(policy.objects).toEqual([
|
|
38
|
+
{ type: UserOntologyType, key: "2" },
|
|
39
|
+
{ type: ChannelOntologyType, key: "3" },
|
|
40
|
+
]);
|
|
41
|
+
expect(policy.actions).toEqual(["update"]);
|
|
42
|
+
});
|
|
43
|
+
test("create many", async () => {
|
|
44
|
+
const policies = await client.access.create([
|
|
45
|
+
{
|
|
46
|
+
subjects: [{ type: UserOntologyType, key: "10" }],
|
|
47
|
+
objects: [
|
|
48
|
+
{ type: UserOntologyType, key: "20" },
|
|
49
|
+
{ type: UserOntologyType, key: "21" },
|
|
50
|
+
],
|
|
51
|
+
actions: ["update"],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
subjects: [
|
|
55
|
+
{ type: UserOntologyType, key: "20" },
|
|
56
|
+
{ type: UserOntologyType, key: "21" },
|
|
57
|
+
],
|
|
58
|
+
objects: [
|
|
59
|
+
{ type: UserOntologyType, key: "20" },
|
|
60
|
+
{ type: ChannelOntologyType, key: "30" },
|
|
61
|
+
],
|
|
62
|
+
actions: ["update"],
|
|
63
|
+
},
|
|
64
|
+
]);
|
|
65
|
+
expect(policies.length).toEqual(2);
|
|
66
|
+
expect(policies[0].subjects[0].key).toEqual("10");
|
|
67
|
+
expect(policies[1].subjects[1].key).toEqual("21");
|
|
68
|
+
});
|
|
69
|
+
test("create instances of policies", async () => {
|
|
70
|
+
const policy = {
|
|
71
|
+
key: undefined,
|
|
72
|
+
subjects: [
|
|
73
|
+
{ type: UserOntologyType, key: "20" },
|
|
74
|
+
{ type: UserOntologyType, key: "21" },
|
|
75
|
+
],
|
|
76
|
+
objects: [
|
|
77
|
+
{ type: UserOntologyType, key: "20" },
|
|
78
|
+
{ type: ChannelOntologyType, key: "30" },
|
|
79
|
+
],
|
|
80
|
+
actions: ["update"],
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const p = await client.access.create(policy);
|
|
84
|
+
expect(p.subjects).toEqual(policy.subjects);
|
|
85
|
+
expect(p.key).not.toEqual(policy.key);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
test("retrieve by subject", async () => {
|
|
89
|
+
const key1 = id.id();
|
|
90
|
+
const policies = [
|
|
91
|
+
{
|
|
92
|
+
key: undefined,
|
|
93
|
+
subjects: [
|
|
94
|
+
{ type: UserOntologyType, key: key1 },
|
|
95
|
+
{ type: UserOntologyType, key: "21" },
|
|
96
|
+
],
|
|
97
|
+
objects: [
|
|
98
|
+
{ type: UserOntologyType, key: "234" },
|
|
99
|
+
{ type: ChannelOntologyType, key: "30" },
|
|
100
|
+
],
|
|
101
|
+
actions: ["update"],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
key: undefined,
|
|
105
|
+
subjects: [
|
|
106
|
+
{ type: UserOntologyType, key: key1 },
|
|
107
|
+
{ type: UserOntologyType, key: "22" },
|
|
108
|
+
],
|
|
109
|
+
objects: [
|
|
110
|
+
{ type: LabelOntologyType, key: "23123" },
|
|
111
|
+
{ type: ChannelOntologyType, key: "30" },
|
|
112
|
+
],
|
|
113
|
+
actions: ["delete"],
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
await client.access.create(policies);
|
|
118
|
+
|
|
119
|
+
const p = (await client.access.retrieve(policies[0].subjects[0])) as Policy[];
|
|
120
|
+
expect(p).toHaveLength(2);
|
|
121
|
+
expect([p[0].actions, p[1].actions].sort()).toEqual([["delete"], ["update"]]);
|
|
122
|
+
});
|
|
123
|
+
test("retrieve by subject - not found", async () => {
|
|
124
|
+
const res = await client.access.retrieve({ type: UserOntologyType, key: "999" });
|
|
125
|
+
expect(res).toHaveLength(0);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe("delete", async () => {
|
|
129
|
+
test("delete one", async () => {
|
|
130
|
+
const id1 = id.id();
|
|
131
|
+
const id2 = id.id();
|
|
132
|
+
const id3 = id.id();
|
|
133
|
+
const policies = [
|
|
134
|
+
{
|
|
135
|
+
key: undefined,
|
|
136
|
+
subjects: [
|
|
137
|
+
{ type: UserOntologyType, key: id1 },
|
|
138
|
+
{ type: UserOntologyType, key: id2 },
|
|
139
|
+
],
|
|
140
|
+
objects: [
|
|
141
|
+
{ type: UserOntologyType, key: "20" },
|
|
142
|
+
{ type: ChannelOntologyType, key: "30" },
|
|
143
|
+
],
|
|
144
|
+
actions: ["update"],
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
key: undefined,
|
|
148
|
+
subjects: [
|
|
149
|
+
{ type: UserOntologyType, key: id1 },
|
|
150
|
+
{ type: UserOntologyType, key: id3 },
|
|
151
|
+
],
|
|
152
|
+
objects: [
|
|
153
|
+
{ type: LabelOntologyType, key: "20" },
|
|
154
|
+
{ type: ChannelOntologyType, key: "30" },
|
|
155
|
+
],
|
|
156
|
+
actions: ["delete"],
|
|
157
|
+
},
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
const created = await client.access.create(policies);
|
|
161
|
+
await client.access.delete(created[0].key);
|
|
162
|
+
const res = await client.access.retrieve(created[0].subjects[0]);
|
|
163
|
+
expect(res).toHaveLength(1);
|
|
164
|
+
expect(res[0].actions).toEqual(["delete"]);
|
|
165
|
+
});
|
|
166
|
+
test("delete many", async () => {
|
|
167
|
+
const id1 = id.id();
|
|
168
|
+
const id2 = id.id();
|
|
169
|
+
const id3 = id.id();
|
|
170
|
+
const policies = [
|
|
171
|
+
{
|
|
172
|
+
subjects: [
|
|
173
|
+
{ type: UserOntologyType, key: id1 },
|
|
174
|
+
{ type: UserOntologyType, key: id2 },
|
|
175
|
+
],
|
|
176
|
+
objects: [
|
|
177
|
+
{ type: UserOntologyType, key: "20" },
|
|
178
|
+
{ type: ChannelOntologyType, key: "30" },
|
|
179
|
+
],
|
|
180
|
+
actions: ["update"],
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
subjects: [
|
|
184
|
+
{ type: UserOntologyType, key: id1 },
|
|
185
|
+
{ type: UserOntologyType, key: id3 },
|
|
186
|
+
],
|
|
187
|
+
objects: [
|
|
188
|
+
{ type: LabelOntologyType, key: "20" },
|
|
189
|
+
{ type: ChannelOntologyType, key: "30" },
|
|
190
|
+
],
|
|
191
|
+
actions: ["delete"],
|
|
192
|
+
},
|
|
193
|
+
];
|
|
194
|
+
|
|
195
|
+
const created = await client.access.create(policies);
|
|
196
|
+
await client.access.delete([created[0].key, created[1].key]);
|
|
197
|
+
let res = await client.access.retrieve({ type: UserOntologyType, key: id1 });
|
|
198
|
+
expect(res).toHaveLength(0);
|
|
199
|
+
res = await client.access.retrieve({ type: UserOntologyType, key: id2 });
|
|
200
|
+
expect(res).toHaveLength(0);
|
|
201
|
+
res = await client.access.retrieve({ type: UserOntologyType, key: id3 });
|
|
202
|
+
expect(res).toHaveLength(0);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
describe("registration", async () => {
|
|
206
|
+
test("register a user", async () => {
|
|
207
|
+
const username = id.id();
|
|
208
|
+
await client.user.register(username, "pwd1");
|
|
209
|
+
new Synnax({
|
|
210
|
+
host: HOST,
|
|
211
|
+
port: PORT,
|
|
212
|
+
username: username,
|
|
213
|
+
password: "pwd1",
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
test("duplicate username", async () => {
|
|
217
|
+
const username = id.id();
|
|
218
|
+
await client.user.register(username, "pwd1");
|
|
219
|
+
await expect(client.user.register(username, "pwd1")).rejects.toThrow(AuthError);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
describe("privilege", async () => {
|
|
223
|
+
test("new user", async () => {
|
|
224
|
+
const username = id.id();
|
|
225
|
+
const user2 = await client.user.register(username, "pwd1");
|
|
226
|
+
expect(user2).toBeDefined();
|
|
227
|
+
const client2 = new Synnax({
|
|
228
|
+
host: HOST,
|
|
229
|
+
port: PORT,
|
|
230
|
+
username: username,
|
|
231
|
+
password: "pwd1",
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
await expect(
|
|
235
|
+
client2.user.register(id.id(), "pwd3")
|
|
236
|
+
).rejects.toThrow(AuthError);
|
|
237
|
+
|
|
238
|
+
await expect(
|
|
239
|
+
client2.channels.create(
|
|
240
|
+
new Channel({
|
|
241
|
+
dataType: DataType.FLOAT64,
|
|
242
|
+
rate: Rate.hz(1),
|
|
243
|
+
name: "my_channel",
|
|
244
|
+
}),
|
|
245
|
+
),
|
|
246
|
+
).rejects.toThrow(AuthError);
|
|
247
|
+
|
|
248
|
+
const p = await client.access.create({
|
|
249
|
+
subjects: [{ type: UserOntologyType, key: user2.key }],
|
|
250
|
+
objects: [{ type: ChannelOntologyType, key: "" }],
|
|
251
|
+
actions: ["create"],
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
await client2.channels.create(
|
|
255
|
+
new Channel({
|
|
256
|
+
dataType: DataType.FLOAT64,
|
|
257
|
+
rate: Rate.hz(1),
|
|
258
|
+
name: "my_channel",
|
|
259
|
+
}),
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
// Remove privileges
|
|
263
|
+
await client.access.delete(p.key);
|
|
264
|
+
|
|
265
|
+
await expect(
|
|
266
|
+
client2.channels.create(
|
|
267
|
+
new Channel({
|
|
268
|
+
dataType: DataType.FLOAT64,
|
|
269
|
+
rate: Rate.hz(1),
|
|
270
|
+
name: "my_channel",
|
|
271
|
+
}),
|
|
272
|
+
),
|
|
273
|
+
).rejects.toThrow(AuthError);
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Copyright 2024 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
|
|
11
|
+
import { toArray } from "@synnaxlabs/x/toArray";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
Key,
|
|
16
|
+
keyZ,
|
|
17
|
+
NewPolicyPayload,
|
|
18
|
+
newPolicyPayloadZ,
|
|
19
|
+
Policy,
|
|
20
|
+
policyZ,
|
|
21
|
+
} from "@/access/payload";
|
|
22
|
+
import { IDPayload, idZ } from "@/ontology/payload";
|
|
23
|
+
|
|
24
|
+
const CREATE_ENDPOINT = "/access/policy/create";
|
|
25
|
+
const DELETE_ENDPOINT = "/access/policy/delete";
|
|
26
|
+
const RETRIEVE_ENDPOINT = "/access/policy/retrieve";
|
|
27
|
+
|
|
28
|
+
const createReqZ = z.object({ policies: newPolicyPayloadZ.array() });
|
|
29
|
+
const createResZ = z.object({ policies: policyZ.array() });
|
|
30
|
+
|
|
31
|
+
const deleteReqZ = z.object({ keys: keyZ.array() });
|
|
32
|
+
const deleteResZ = z.object({});
|
|
33
|
+
|
|
34
|
+
const retrieveReqZ = z.object({ subject: idZ });
|
|
35
|
+
const retrieveResZ = z.object({
|
|
36
|
+
policies: policyZ.array().optional().default([]),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export class Client {
|
|
40
|
+
private readonly client: UnaryClient;
|
|
41
|
+
|
|
42
|
+
constructor(client: UnaryClient) {
|
|
43
|
+
this.client = client;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async create(policies: NewPolicyPayload): Promise<Policy>;
|
|
47
|
+
|
|
48
|
+
async create(policies: NewPolicyPayload[]): Promise<Policy[]>;
|
|
49
|
+
|
|
50
|
+
async create(
|
|
51
|
+
policies: NewPolicyPayload | NewPolicyPayload[],
|
|
52
|
+
): Promise<Policy | Policy[]> {
|
|
53
|
+
const single = !Array.isArray(policies);
|
|
54
|
+
|
|
55
|
+
const { policies: created } = await sendRequired<
|
|
56
|
+
typeof createReqZ,
|
|
57
|
+
typeof createResZ
|
|
58
|
+
>(
|
|
59
|
+
this.client,
|
|
60
|
+
CREATE_ENDPOINT,
|
|
61
|
+
{ policies: toArray(policies) },
|
|
62
|
+
createReqZ,
|
|
63
|
+
createResZ,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
return single ? created[0] : created;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async retrieve(subject: IDPayload): Promise<Policy[]> {
|
|
70
|
+
const { policies: retrieved } = await sendRequired<
|
|
71
|
+
typeof retrieveReqZ,
|
|
72
|
+
typeof retrieveResZ
|
|
73
|
+
>(this.client, RETRIEVE_ENDPOINT, { subject: subject }, retrieveReqZ, retrieveResZ);
|
|
74
|
+
return retrieved;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async delete(keys: Key | Key[]): Promise<void> {
|
|
78
|
+
await sendRequired<typeof deleteReqZ, typeof deleteResZ>(
|
|
79
|
+
this.client,
|
|
80
|
+
DELETE_ENDPOINT,
|
|
81
|
+
{ keys: toArray(keys) },
|
|
82
|
+
deleteReqZ,
|
|
83
|
+
deleteResZ,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Copyright 2024 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
export * from "@/access/client";
|
|
11
|
+
export * from "@/access/payload";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Copyright 2024 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
export * as access from "@/access/external";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Copyright 2024 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
|
|
12
|
+
import { ontology } from "@/ontology";
|
|
13
|
+
import { idZ } from "@/ontology/payload";
|
|
14
|
+
|
|
15
|
+
export const keyZ = z.string().uuid();
|
|
16
|
+
|
|
17
|
+
export type Key = z.infer<typeof keyZ>;
|
|
18
|
+
|
|
19
|
+
export type Params = Key | Key[];
|
|
20
|
+
|
|
21
|
+
export const policyZ = z.object({
|
|
22
|
+
key: keyZ,
|
|
23
|
+
subjects: idZ.array(),
|
|
24
|
+
objects: idZ.array(),
|
|
25
|
+
actions: z.string().array(),
|
|
26
|
+
});
|
|
27
|
+
export type Policy = z.infer<typeof policyZ>;
|
|
28
|
+
|
|
29
|
+
export const newPolicyPayloadZ = policyZ.extend({ key: keyZ.optional() });
|
|
30
|
+
export type NewPolicyPayload = z.infer<typeof newPolicyPayloadZ>;
|
|
31
|
+
|
|
32
|
+
export const PolicyOntologyType = "policy" as ontology.ResourceType;
|
|
33
|
+
|
|
34
|
+
export const ontologyID = (key: Key): ontology.ID =>
|
|
35
|
+
new ontology.ID({ type: PolicyOntologyType, key });
|
package/src/auth/auth.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
|
-
import type
|
|
10
|
+
import { type Middleware, type UnaryClient } from "@synnaxlabs/freighter";
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
|
|
13
13
|
import { InvalidTokenError } from "@/errors";
|
package/src/channel/payload.ts
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
import { DataType, Rate } from "@synnaxlabs/x/telem";
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
|
|
13
|
+
import { ontology } from "@/ontology";
|
|
14
|
+
|
|
13
15
|
export const keyZ = z.number();
|
|
14
16
|
export type Key = number;
|
|
15
17
|
export type Keys = number[];
|
|
@@ -44,3 +46,8 @@ export const newPayload = payload.extend({
|
|
|
44
46
|
});
|
|
45
47
|
|
|
46
48
|
export type NewPayload = z.input<typeof newPayload>;
|
|
49
|
+
|
|
50
|
+
export const ChannelOntologyType = "channel" as ontology.ResourceType;
|
|
51
|
+
|
|
52
|
+
export const ontologyID = (key: Key): ontology.ID =>
|
|
53
|
+
new ontology.ID({ type: ChannelOntologyType, key: key.toString() });
|
package/src/client.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { TimeSpan, TimeStamp } from "@synnaxlabs/x/telem";
|
|
|
11
11
|
import { URL } from "@synnaxlabs/x/url";
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
|
|
14
|
+
import { access } from "@/access";
|
|
14
15
|
import { auth } from "@/auth";
|
|
15
16
|
import { channel } from "@/channel";
|
|
16
17
|
import { connection } from "@/connection";
|
|
@@ -25,6 +26,7 @@ import { label } from "@/label";
|
|
|
25
26
|
import { ontology } from "@/ontology";
|
|
26
27
|
import { ranger } from "@/ranger";
|
|
27
28
|
import { Transport } from "@/transport";
|
|
29
|
+
import { user } from "@/user";
|
|
28
30
|
import { workspace } from "@/workspace";
|
|
29
31
|
|
|
30
32
|
export const synnaxPropsZ = z.object({
|
|
@@ -66,6 +68,8 @@ export default class Synnax extends framer.Client {
|
|
|
66
68
|
readonly ranges: ranger.Client;
|
|
67
69
|
readonly channels: channel.Client;
|
|
68
70
|
readonly auth: auth.Client | undefined;
|
|
71
|
+
readonly user: user.Client;
|
|
72
|
+
readonly access: access.Client;
|
|
69
73
|
readonly connectivity: connection.Checker;
|
|
70
74
|
readonly ontology: ontology.Client;
|
|
71
75
|
readonly workspaces: workspace.Client;
|
|
@@ -97,7 +101,7 @@ export default class Synnax extends framer.Client {
|
|
|
97
101
|
transport.use(errorsMiddleware);
|
|
98
102
|
let auth_: auth.Client | undefined;
|
|
99
103
|
if (username != null && password != null) {
|
|
100
|
-
|
|
104
|
+
auth_ = new auth.Client(transport.unary, {
|
|
101
105
|
username,
|
|
102
106
|
password,
|
|
103
107
|
});
|
|
@@ -129,6 +133,8 @@ export default class Synnax extends framer.Client {
|
|
|
129
133
|
chRetriever,
|
|
130
134
|
this.labels,
|
|
131
135
|
);
|
|
136
|
+
this.access = new access.Client(this.transport.unary);
|
|
137
|
+
this.user = new user.Client(this.transport.unary);
|
|
132
138
|
this.workspaces = new workspace.Client(this.transport.unary);
|
|
133
139
|
const devices = new device.Client(this.transport.unary, this);
|
|
134
140
|
const tasks = new task.Client(this.transport.unary, this);
|
package/src/control/state.ts
CHANGED
|
@@ -43,16 +43,16 @@ export class StateTracker
|
|
|
43
43
|
implements observe.ObservableAsyncCloseable<Transfer[]>
|
|
44
44
|
{
|
|
45
45
|
readonly states: Map<ChannelKey, State>;
|
|
46
|
-
private readonly
|
|
46
|
+
private readonly codec: binary.Codec;
|
|
47
47
|
|
|
48
48
|
constructor(streamer: FrameStreamer) {
|
|
49
49
|
super(streamer, (frame) => {
|
|
50
|
-
const update: Update = this.
|
|
50
|
+
const update: Update = this.codec.decode(frame.series[0].buffer);
|
|
51
51
|
this.merge(update);
|
|
52
52
|
return [update.transfers, true];
|
|
53
53
|
});
|
|
54
54
|
this.states = new Map();
|
|
55
|
-
this.
|
|
55
|
+
this.codec = new binary.JSONCodec();
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
subjects(): Subject[] {
|
package/src/framer/client.ts
CHANGED
package/src/framer/deleter.ts
CHANGED
|
@@ -15,8 +15,8 @@ import { keyZ } from "@/channel/payload";
|
|
|
15
15
|
|
|
16
16
|
const reqZ = z.object({
|
|
17
17
|
keys: keyZ.array().optional(),
|
|
18
|
-
names: z.string().array().optional(),
|
|
19
18
|
bounds: TimeRange.z,
|
|
19
|
+
names: z.string().array().optional(),
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
type RequestProps = z.infer<typeof reqZ>;
|
|
@@ -31,9 +31,7 @@ export class Deleter {
|
|
|
31
31
|
*/
|
|
32
32
|
private readonly client: UnaryClient;
|
|
33
33
|
|
|
34
|
-
constructor(
|
|
35
|
-
client: UnaryClient,
|
|
36
|
-
) {
|
|
34
|
+
constructor(client: UnaryClient) {
|
|
37
35
|
this.client = client;
|
|
38
36
|
}
|
|
39
37
|
|