@synnaxlabs/client 0.47.0 → 0.49.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 +7 -7
- package/dist/client.cjs +35 -35
- package/dist/client.js +6264 -5984
- package/dist/eslint.config.d.ts +3 -2
- package/dist/eslint.config.d.ts.map +1 -1
- package/dist/src/access/client.d.ts +3 -1
- package/dist/src/access/client.d.ts.map +1 -1
- package/dist/src/access/enforce.d.ts +35 -0
- package/dist/src/access/enforce.d.ts.map +1 -0
- package/dist/src/access/enforce.spec.d.ts +2 -0
- package/dist/src/access/enforce.spec.d.ts.map +1 -0
- package/dist/src/access/external.d.ts +3 -0
- package/dist/src/access/external.d.ts.map +1 -1
- package/dist/src/access/payload.d.ts +0 -6
- package/dist/src/access/payload.d.ts.map +1 -1
- package/dist/src/access/policy/access.spec.d.ts +2 -0
- package/dist/src/access/policy/access.spec.d.ts.map +1 -0
- package/dist/src/access/policy/client.d.ts +485 -31
- package/dist/src/access/policy/client.d.ts.map +1 -1
- package/dist/src/access/policy/payload.d.ts +36 -113
- package/dist/src/access/policy/payload.d.ts.map +1 -1
- package/dist/src/access/role/client.d.ts +135 -0
- package/dist/src/access/role/client.d.ts.map +1 -0
- package/dist/src/access/role/external.d.ts.map +1 -0
- package/dist/src/access/role/index.d.ts +2 -0
- package/dist/src/access/role/index.d.ts.map +1 -0
- package/dist/src/access/role/payload.d.ts +27 -0
- package/dist/src/access/role/payload.d.ts.map +1 -0
- package/dist/src/access/role/role.spec.d.ts +2 -0
- package/dist/src/access/role/role.spec.d.ts.map +1 -0
- package/dist/src/arc/access.spec.d.ts +2 -0
- package/dist/src/arc/access.spec.d.ts.map +1 -0
- package/dist/src/arc/client.d.ts +5 -14
- package/dist/src/arc/client.d.ts.map +1 -1
- package/dist/src/arc/payload.d.ts +11 -2
- package/dist/src/arc/payload.d.ts.map +1 -1
- package/dist/src/auth/auth.d.ts +5 -3
- package/dist/src/auth/auth.d.ts.map +1 -1
- package/dist/src/channel/access.spec.d.ts +2 -0
- package/dist/src/channel/access.spec.d.ts.map +1 -0
- package/dist/src/channel/client.d.ts +0 -1
- package/dist/src/channel/client.d.ts.map +1 -1
- package/dist/src/channel/payload.d.ts +19 -8
- package/dist/src/channel/payload.d.ts.map +1 -1
- package/dist/src/channel/payload.spec.d.ts +2 -0
- package/dist/src/channel/payload.spec.d.ts.map +1 -0
- package/dist/src/channel/retriever.d.ts +4 -6
- package/dist/src/channel/retriever.d.ts.map +1 -1
- package/dist/src/channel/writer.d.ts.map +1 -1
- package/dist/src/client.d.ts +18 -10
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/connection/checker.d.ts +2 -3
- package/dist/src/connection/checker.d.ts.map +1 -1
- package/dist/src/connection.spec.d.ts +2 -0
- package/dist/src/connection.spec.d.ts.map +1 -0
- package/dist/src/device/access.spec.d.ts +2 -0
- package/dist/src/device/access.spec.d.ts.map +1 -0
- package/dist/src/{hardware/device → device}/client.d.ts +14 -7
- package/dist/src/device/client.d.ts.map +1 -0
- package/dist/src/device/device.spec.d.ts.map +1 -0
- package/dist/src/device/external.d.ts.map +1 -0
- package/dist/src/device/index.d.ts.map +1 -0
- package/dist/src/{hardware/device → device}/payload.d.ts +1 -1
- package/dist/src/device/payload.d.ts.map +1 -0
- package/dist/src/errors.d.ts +3 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/framer/adapter.d.ts +2 -2
- package/dist/src/framer/adapter.d.ts.map +1 -1
- package/dist/src/framer/client.d.ts +8 -1
- package/dist/src/framer/client.d.ts.map +1 -1
- package/dist/src/framer/frame.d.ts +11 -5
- package/dist/src/framer/frame.d.ts.map +1 -1
- package/dist/src/framer/iterator.d.ts +3 -3
- package/dist/src/framer/streamer.d.ts +24 -21
- package/dist/src/framer/streamer.d.ts.map +1 -1
- package/dist/src/framer/writer.d.ts +13 -13
- package/dist/src/index.d.ts +6 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/label/access.spec.d.ts +2 -0
- package/dist/src/label/access.spec.d.ts.map +1 -0
- package/dist/src/label/client.d.ts +20 -11
- package/dist/src/label/client.d.ts.map +1 -1
- package/dist/src/ontology/client.d.ts +6 -6
- package/dist/src/ontology/client.d.ts.map +1 -1
- package/dist/src/ontology/group/access.spec.d.ts +2 -0
- package/dist/src/ontology/group/access.spec.d.ts.map +1 -0
- package/dist/src/ontology/group/client.d.ts +2 -2
- package/dist/src/ontology/group/client.d.ts.map +1 -1
- package/dist/src/ontology/group/payload.d.ts +1 -2
- package/dist/src/ontology/group/payload.d.ts.map +1 -1
- package/dist/src/ontology/payload.d.ts +23 -17
- package/dist/src/ontology/payload.d.ts.map +1 -1
- package/dist/src/ontology/writer.d.ts +10 -10
- package/dist/src/ontology/writer.d.ts.map +1 -1
- package/dist/src/rack/access.spec.d.ts +2 -0
- package/dist/src/rack/access.spec.d.ts.map +1 -0
- package/dist/src/{hardware/rack → rack}/client.d.ts +15 -8
- package/dist/src/rack/client.d.ts.map +1 -0
- package/dist/src/rack/external.d.ts.map +1 -0
- package/dist/src/rack/index.d.ts.map +1 -0
- package/dist/src/{hardware/rack → rack}/payload.d.ts +1 -1
- package/dist/src/rack/payload.d.ts.map +1 -0
- package/dist/src/rack/rack.spec.d.ts.map +1 -0
- package/dist/src/ranger/access.spec.d.ts +2 -0
- package/dist/src/ranger/access.spec.d.ts.map +1 -0
- package/dist/src/ranger/alias.d.ts +1 -8
- package/dist/src/ranger/alias.d.ts.map +1 -1
- package/dist/src/ranger/client.d.ts +12 -5
- package/dist/src/ranger/client.d.ts.map +1 -1
- package/dist/src/ranger/kv.d.ts +0 -3
- package/dist/src/ranger/kv.d.ts.map +1 -1
- package/dist/src/ranger/writer.d.ts +2 -2
- package/dist/src/ranger/writer.d.ts.map +1 -1
- package/dist/src/status/access.spec.d.ts +2 -0
- package/dist/src/status/access.spec.d.ts.map +1 -0
- package/dist/src/status/client.d.ts +4 -4
- package/dist/src/status/client.d.ts.map +1 -1
- package/dist/src/status/payload.d.ts +9 -2
- package/dist/src/status/payload.d.ts.map +1 -1
- package/dist/src/task/access.spec.d.ts +2 -0
- package/dist/src/task/access.spec.d.ts.map +1 -0
- package/dist/src/{hardware/task → task}/client.d.ts +26 -15
- package/dist/src/task/client.d.ts.map +1 -0
- package/dist/src/task/external.d.ts +3 -0
- package/dist/src/task/external.d.ts.map +1 -0
- package/dist/src/task/index.d.ts.map +1 -0
- package/dist/src/{hardware/task → task}/payload.d.ts +45 -6
- package/dist/src/task/payload.d.ts.map +1 -0
- package/dist/src/task/task.spec.d.ts.map +1 -0
- package/dist/src/testutil/access.d.ts +4 -0
- package/dist/src/testutil/access.d.ts.map +1 -0
- package/dist/src/testutil/client.d.ts +3 -3
- package/dist/src/testutil/client.d.ts.map +1 -1
- package/dist/src/transport.d.ts.map +1 -1
- package/dist/src/user/access.spec.d.ts +2 -0
- package/dist/src/user/access.spec.d.ts.map +1 -0
- package/dist/src/user/client.d.ts +10 -1
- package/dist/src/user/client.d.ts.map +1 -1
- package/dist/src/user/external.d.ts +1 -1
- package/dist/src/user/external.d.ts.map +1 -1
- package/dist/src/user/payload.d.ts.map +1 -1
- package/dist/src/workspace/access.spec.d.ts +2 -0
- package/dist/src/workspace/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/client.d.ts +10 -5
- package/dist/src/workspace/client.d.ts.map +1 -1
- package/dist/src/workspace/lineplot/access.spec.d.ts +2 -0
- package/dist/src/workspace/lineplot/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/lineplot/client.d.ts +8 -1
- package/dist/src/workspace/lineplot/client.d.ts.map +1 -1
- package/dist/src/workspace/log/access.spec.d.ts +2 -0
- package/dist/src/workspace/log/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/log/client.d.ts +8 -1
- package/dist/src/workspace/log/client.d.ts.map +1 -1
- package/dist/src/workspace/schematic/access.spec.d.ts +2 -0
- package/dist/src/workspace/schematic/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/schematic/client.d.ts +8 -1
- package/dist/src/workspace/schematic/client.d.ts.map +1 -1
- package/dist/src/workspace/schematic/symbol/access.spec.d.ts +2 -0
- package/dist/src/workspace/schematic/symbol/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/schematic/symbol/client.d.ts +1 -5
- package/dist/src/workspace/schematic/symbol/client.d.ts.map +1 -1
- package/dist/src/workspace/schematic/symbol/payload.d.ts +2 -2
- package/dist/src/workspace/table/access.spec.d.ts +2 -0
- package/dist/src/workspace/table/access.spec.d.ts.map +1 -0
- package/dist/src/workspace/table/client.d.ts +8 -1
- package/dist/src/workspace/table/client.d.ts.map +1 -1
- package/eslint.config.ts +3 -1
- package/package.json +8 -8
- package/src/access/client.ts +5 -2
- package/src/access/enforce.spec.ts +189 -0
- package/src/access/enforce.ts +84 -0
- package/src/access/external.ts +3 -0
- package/src/access/payload.ts +1 -13
- package/src/access/policy/access.spec.ts +147 -0
- package/src/access/policy/client.ts +21 -25
- package/src/access/policy/payload.ts +9 -5
- package/src/access/role/client.ts +135 -0
- package/src/access/role/external.ts +11 -0
- package/src/{hardware → access/role}/index.ts +1 -1
- package/src/access/role/payload.ts +32 -0
- package/src/access/role/role.spec.ts +95 -0
- package/src/arc/access.spec.ts +143 -0
- package/src/arc/client.ts +7 -31
- package/src/arc/payload.ts +4 -0
- package/src/auth/auth.spec.ts +13 -13
- package/src/auth/auth.ts +33 -11
- package/src/channel/access.spec.ts +116 -0
- package/src/channel/channel.spec.ts +63 -73
- package/src/channel/client.ts +2 -8
- package/src/channel/payload.spec.ts +171 -0
- package/src/channel/payload.ts +37 -8
- package/src/channel/retriever.ts +10 -11
- package/src/channel/writer.ts +3 -7
- package/src/client.ts +38 -28
- package/src/connection/checker.ts +10 -10
- package/src/connection/connection.spec.ts +13 -13
- package/src/connection.spec.ts +145 -0
- package/src/device/access.spec.ts +159 -0
- package/src/{hardware/device → device}/client.ts +12 -21
- package/src/{hardware/device → device}/device.spec.ts +70 -34
- package/src/device/external.ts +11 -0
- package/src/{hardware/rack → device}/index.ts +1 -1
- package/src/{hardware/device → device}/payload.ts +3 -3
- package/src/errors.ts +2 -0
- package/src/framer/adapter.spec.ts +351 -13
- package/src/framer/adapter.ts +23 -13
- package/src/framer/client.spec.ts +14 -20
- package/src/framer/client.ts +3 -5
- package/src/framer/deleter.spec.ts +1 -1
- package/src/framer/frame.spec.ts +427 -0
- package/src/framer/frame.ts +30 -3
- package/src/framer/iterator.ts +4 -4
- package/src/framer/streamer.spec.ts +155 -10
- package/src/framer/streamer.ts +35 -12
- package/src/framer/writer.spec.ts +5 -5
- package/src/index.ts +13 -7
- package/src/label/access.spec.ts +109 -0
- package/src/label/client.ts +10 -14
- package/src/ontology/client.ts +4 -6
- package/src/ontology/group/access.spec.ts +77 -0
- package/src/ontology/group/client.ts +3 -7
- package/src/ontology/group/group.spec.ts +18 -0
- package/src/ontology/group/payload.ts +2 -2
- package/src/ontology/ontology.spec.ts +2 -0
- package/src/ontology/payload.ts +18 -2
- package/src/ontology/writer.ts +3 -7
- package/src/rack/access.spec.ts +102 -0
- package/src/{hardware/rack → rack}/client.ts +14 -19
- package/src/{hardware/device/index.ts → rack/external.ts} +2 -1
- package/src/{hardware/external.ts → rack/index.ts} +1 -1
- package/src/{hardware/rack → rack}/payload.ts +2 -2
- package/src/{hardware/rack → rack}/rack.spec.ts +43 -17
- package/src/ranger/access.spec.ts +115 -0
- package/src/ranger/alias.ts +6 -14
- package/src/ranger/client.ts +13 -14
- package/src/ranger/kv.ts +7 -9
- package/src/ranger/ranger.spec.ts +4 -4
- package/src/ranger/writer.ts +3 -7
- package/src/status/access.spec.ts +129 -0
- package/src/status/client.ts +5 -9
- package/src/status/payload.ts +3 -2
- package/src/task/access.spec.ts +131 -0
- package/src/{hardware/task → task}/client.ts +50 -25
- package/src/task/external.ts +11 -0
- package/src/{hardware/task → task}/index.ts +1 -1
- package/src/{hardware/task → task}/payload.ts +22 -3
- package/src/{hardware/task → task}/task.spec.ts +197 -34
- package/src/testutil/access.ts +34 -0
- package/src/testutil/channels.ts +3 -3
- package/src/testutil/client.ts +4 -4
- package/src/transport.ts +1 -3
- package/src/user/access.spec.ts +107 -0
- package/src/user/client.ts +10 -12
- package/src/user/external.ts +12 -1
- package/src/user/payload.ts +3 -5
- package/src/workspace/access.spec.ts +108 -0
- package/src/workspace/client.ts +11 -27
- package/src/workspace/lineplot/access.spec.ts +134 -0
- package/src/workspace/lineplot/client.ts +8 -13
- package/src/workspace/log/access.spec.ts +134 -0
- package/src/workspace/log/client.ts +8 -13
- package/src/workspace/schematic/access.spec.ts +134 -0
- package/src/workspace/schematic/client.ts +9 -18
- package/src/workspace/schematic/symbol/access.spec.ts +172 -0
- package/src/workspace/schematic/symbol/client.ts +6 -17
- package/src/workspace/schematic/symbol/payload.ts +1 -1
- package/src/workspace/table/access.spec.ts +134 -0
- package/src/workspace/table/client.ts +8 -13
- package/dist/src/access/policy/policy.spec.d.ts +0 -2
- package/dist/src/access/policy/policy.spec.d.ts.map +0 -1
- package/dist/src/hardware/client.d.ts +0 -10
- package/dist/src/hardware/client.d.ts.map +0 -1
- package/dist/src/hardware/device/client.d.ts.map +0 -1
- package/dist/src/hardware/device/device.spec.d.ts.map +0 -1
- package/dist/src/hardware/device/external.d.ts.map +0 -1
- package/dist/src/hardware/device/index.d.ts.map +0 -1
- package/dist/src/hardware/device/payload.d.ts.map +0 -1
- package/dist/src/hardware/external.d.ts +0 -2
- package/dist/src/hardware/external.d.ts.map +0 -1
- package/dist/src/hardware/index.d.ts +0 -2
- package/dist/src/hardware/index.d.ts.map +0 -1
- package/dist/src/hardware/rack/client.d.ts.map +0 -1
- package/dist/src/hardware/rack/external.d.ts.map +0 -1
- package/dist/src/hardware/rack/index.d.ts.map +0 -1
- package/dist/src/hardware/rack/payload.d.ts.map +0 -1
- package/dist/src/hardware/rack/rack.spec.d.ts.map +0 -1
- package/dist/src/hardware/task/client.d.ts.map +0 -1
- package/dist/src/hardware/task/external.d.ts.map +0 -1
- package/dist/src/hardware/task/index.d.ts.map +0 -1
- package/dist/src/hardware/task/payload.d.ts.map +0 -1
- package/dist/src/hardware/task/task.spec.d.ts.map +0 -1
- package/dist/src/user/retriever.d.ts +0 -16
- package/dist/src/user/retriever.d.ts.map +0 -1
- package/dist/src/user/writer.d.ts +0 -11
- package/dist/src/user/writer.d.ts.map +0 -1
- package/src/access/policy/policy.spec.ts +0 -329
- package/src/hardware/client.ts +0 -24
- package/src/hardware/device/external.ts +0 -11
- package/src/hardware/rack/external.ts +0 -11
- package/src/hardware/task/external.ts +0 -11
- package/src/user/retriever.ts +0 -41
- package/src/user/writer.ts +0 -84
- /package/dist/src/{hardware/device → access/role}/external.d.ts +0 -0
- /package/dist/src/{hardware/device → device}/device.spec.d.ts +0 -0
- /package/dist/src/{hardware/rack → device}/external.d.ts +0 -0
- /package/dist/src/{hardware/device → device}/index.d.ts +0 -0
- /package/dist/src/{hardware/task → rack}/external.d.ts +0 -0
- /package/dist/src/{hardware/rack → rack}/index.d.ts +0 -0
- /package/dist/src/{hardware/rack → rack}/rack.spec.d.ts +0 -0
- /package/dist/src/{hardware/task → task}/index.d.ts +0 -0
- /package/dist/src/{hardware/task → task}/task.spec.d.ts +0 -0
|
@@ -7,16 +7,17 @@
|
|
|
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 {
|
|
10
|
+
import { TimeStamp } from "@synnaxlabs/x";
|
|
11
11
|
import { beforeAll, describe, expect, it } from "vitest";
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import { ontology } from "@/ontology";
|
|
14
|
+
import { task } from "@/task";
|
|
14
15
|
import { createTestClient } from "@/testutil/client";
|
|
15
16
|
|
|
16
17
|
const client = createTestClient();
|
|
17
18
|
|
|
18
19
|
describe("Task", async () => {
|
|
19
|
-
const testRack = await client.
|
|
20
|
+
const testRack = await client.racks.create({ name: "test" });
|
|
20
21
|
describe("create", () => {
|
|
21
22
|
it("should create a task on a rack", async () => {
|
|
22
23
|
const m = await testRack.createTask({
|
|
@@ -44,6 +45,31 @@ describe("Task", async () => {
|
|
|
44
45
|
});
|
|
45
46
|
expect(m.config).toStrictEqual(config);
|
|
46
47
|
});
|
|
48
|
+
it("should create a task with a custom status", async () => {
|
|
49
|
+
const m = await testRack.createTask({
|
|
50
|
+
name: "task-with-status",
|
|
51
|
+
config: { test: true },
|
|
52
|
+
type: "ni",
|
|
53
|
+
status: {
|
|
54
|
+
variant: "success",
|
|
55
|
+
message: "Custom task status",
|
|
56
|
+
description: "Task is running",
|
|
57
|
+
time: TimeStamp.now(),
|
|
58
|
+
details: { running: true, data: { customData: true } },
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
expect(m.key).not.toHaveLength(0);
|
|
62
|
+
const retrieved = await client.tasks.retrieve({
|
|
63
|
+
key: m.key,
|
|
64
|
+
includeStatus: true,
|
|
65
|
+
});
|
|
66
|
+
expect(retrieved.status).toBeDefined();
|
|
67
|
+
expect(retrieved.status?.variant).toBe("success");
|
|
68
|
+
expect(retrieved.status?.message).toBe("Custom task status");
|
|
69
|
+
expect(retrieved.status?.description).toBe("Task is running");
|
|
70
|
+
expect(retrieved.status?.details?.task).toBe(m.key);
|
|
71
|
+
expect(retrieved.status?.details?.running).toBe(true);
|
|
72
|
+
});
|
|
47
73
|
});
|
|
48
74
|
describe("update", () => {
|
|
49
75
|
it("should update a task if the key is provided", async () => {
|
|
@@ -52,12 +78,12 @@ describe("Task", async () => {
|
|
|
52
78
|
config: { a: "dog" },
|
|
53
79
|
type: "ni",
|
|
54
80
|
});
|
|
55
|
-
const updated = await client.
|
|
81
|
+
const updated = await client.tasks.create({
|
|
56
82
|
...m,
|
|
57
83
|
name: "updated",
|
|
58
84
|
});
|
|
59
85
|
expect(updated.name).toBe("updated");
|
|
60
|
-
const retrieved = await client.
|
|
86
|
+
const retrieved = await client.tasks.retrieve({ key: m.key });
|
|
61
87
|
expect(retrieved.name).toBe("updated");
|
|
62
88
|
});
|
|
63
89
|
});
|
|
@@ -68,7 +94,7 @@ describe("Task", async () => {
|
|
|
68
94
|
config: { a: "dog" },
|
|
69
95
|
type: "ni",
|
|
70
96
|
});
|
|
71
|
-
const retrieved = await client.
|
|
97
|
+
const retrieved = await client.tasks.retrieve({ key: m.key });
|
|
72
98
|
expect(retrieved.key).toBe(m.key);
|
|
73
99
|
expect(retrieved.name).toBe("test");
|
|
74
100
|
expect(retrieved.config).toStrictEqual({ a: "dog" });
|
|
@@ -78,31 +104,29 @@ describe("Task", async () => {
|
|
|
78
104
|
it("should retrieve a task by its name", async () => {
|
|
79
105
|
const name = `test-${Date.now()}-${Math.random()}`;
|
|
80
106
|
const m = await testRack.createTask({ name, config: { a: "dog" }, type: "ni" });
|
|
81
|
-
const retrieved = await client.
|
|
107
|
+
const retrieved = await client.tasks.retrieve({ name });
|
|
82
108
|
expect(retrieved.key).toBe(m.key);
|
|
83
109
|
});
|
|
84
110
|
|
|
85
|
-
describe("
|
|
111
|
+
describe("status", () => {
|
|
86
112
|
it("should include task status when requested", async () => {
|
|
87
113
|
const t = await testRack.createTask({
|
|
88
114
|
name: "test",
|
|
89
115
|
config: { a: "dog" },
|
|
90
116
|
type: "ni",
|
|
91
117
|
});
|
|
92
|
-
const w = await client.openWriter([task.STATUS_CHANNEL_NAME]);
|
|
93
118
|
const communicatedStatus: task.Status = {
|
|
94
|
-
key:
|
|
119
|
+
key: ontology.idToString(task.ontologyID(t.key)),
|
|
95
120
|
name: "test",
|
|
96
121
|
variant: "success",
|
|
97
122
|
details: { task: t.key, running: false, data: {} },
|
|
98
123
|
message: "test",
|
|
99
124
|
time: TimeStamp.now(),
|
|
100
125
|
};
|
|
101
|
-
await
|
|
102
|
-
await w.close();
|
|
126
|
+
await client.statuses.set(communicatedStatus);
|
|
103
127
|
await expect
|
|
104
128
|
.poll(async () => {
|
|
105
|
-
const retrieved = await client.
|
|
129
|
+
const retrieved = await client.tasks.retrieve({
|
|
106
130
|
key: t.key,
|
|
107
131
|
includeStatus: true,
|
|
108
132
|
});
|
|
@@ -117,7 +141,7 @@ describe("Task", async () => {
|
|
|
117
141
|
let secondRack: any;
|
|
118
142
|
|
|
119
143
|
beforeAll(async () => {
|
|
120
|
-
secondRack = await client.
|
|
144
|
+
secondRack = await client.racks.create({ name: "test-rack-2" });
|
|
121
145
|
|
|
122
146
|
const taskConfigs = [
|
|
123
147
|
{ name: "sensor_task1", type: "ni", rack: testRack },
|
|
@@ -138,7 +162,7 @@ describe("Task", async () => {
|
|
|
138
162
|
});
|
|
139
163
|
|
|
140
164
|
it("should retrieve tasks by rack", async () => {
|
|
141
|
-
const result = await client.
|
|
165
|
+
const result = await client.tasks.retrieve({
|
|
142
166
|
rack: testRack.key,
|
|
143
167
|
});
|
|
144
168
|
expect(result.length).toBeGreaterThanOrEqual(3);
|
|
@@ -147,7 +171,7 @@ describe("Task", async () => {
|
|
|
147
171
|
|
|
148
172
|
it("should retrieve tasks by multiple keys", async () => {
|
|
149
173
|
const keysToQuery = testTasks.slice(0, 2).map((t) => t.key);
|
|
150
|
-
const result = await client.
|
|
174
|
+
const result = await client.tasks.retrieve({
|
|
151
175
|
keys: keysToQuery,
|
|
152
176
|
});
|
|
153
177
|
expect(result).toHaveLength(2);
|
|
@@ -156,7 +180,7 @@ describe("Task", async () => {
|
|
|
156
180
|
|
|
157
181
|
it("should retrieve tasks by multiple names", async () => {
|
|
158
182
|
const namesToQuery = ["sensor_task1", "actuator_task1"];
|
|
159
|
-
const result = await client.
|
|
183
|
+
const result = await client.tasks.retrieve({
|
|
160
184
|
names: namesToQuery,
|
|
161
185
|
});
|
|
162
186
|
expect(result.length).toBeGreaterThanOrEqual(2);
|
|
@@ -164,7 +188,7 @@ describe("Task", async () => {
|
|
|
164
188
|
});
|
|
165
189
|
|
|
166
190
|
it("should retrieve tasks by types", async () => {
|
|
167
|
-
const result = await client.
|
|
191
|
+
const result = await client.tasks.retrieve({
|
|
168
192
|
types: ["ni"],
|
|
169
193
|
});
|
|
170
194
|
expect(result.length).toBeGreaterThanOrEqual(2);
|
|
@@ -173,7 +197,7 @@ describe("Task", async () => {
|
|
|
173
197
|
|
|
174
198
|
it("should retrieve tasks by multiple types", async () => {
|
|
175
199
|
const typesToQuery = ["ni", "labjack"];
|
|
176
|
-
const result = await client.
|
|
200
|
+
const result = await client.tasks.retrieve({
|
|
177
201
|
types: typesToQuery,
|
|
178
202
|
});
|
|
179
203
|
expect(result.length).toBeGreaterThanOrEqual(4);
|
|
@@ -181,7 +205,7 @@ describe("Task", async () => {
|
|
|
181
205
|
});
|
|
182
206
|
|
|
183
207
|
it("should support pagination with limit and offset", async () => {
|
|
184
|
-
const firstPage = await client.
|
|
208
|
+
const firstPage = await client.tasks.retrieve({
|
|
185
209
|
rack: testRack.key,
|
|
186
210
|
limit: 2,
|
|
187
211
|
offset: 0,
|
|
@@ -189,7 +213,7 @@ describe("Task", async () => {
|
|
|
189
213
|
expect(firstPage.length).toBeLessThanOrEqual(2);
|
|
190
214
|
|
|
191
215
|
if (firstPage.length === 2) {
|
|
192
|
-
const secondPage = await client.
|
|
216
|
+
const secondPage = await client.tasks.retrieve({
|
|
193
217
|
rack: testRack.key,
|
|
194
218
|
limit: 2,
|
|
195
219
|
offset: 2,
|
|
@@ -204,7 +228,7 @@ describe("Task", async () => {
|
|
|
204
228
|
});
|
|
205
229
|
|
|
206
230
|
it("should support combined filters", async () => {
|
|
207
|
-
const result = await client.
|
|
231
|
+
const result = await client.tasks.retrieve({
|
|
208
232
|
rack: testRack.key,
|
|
209
233
|
types: ["ni"],
|
|
210
234
|
includeStatus: true,
|
|
@@ -214,7 +238,7 @@ describe("Task", async () => {
|
|
|
214
238
|
|
|
215
239
|
await expect
|
|
216
240
|
.poll(async () => {
|
|
217
|
-
const tasks = await client.
|
|
241
|
+
const tasks = await client.tasks.retrieve({
|
|
218
242
|
rack: testRack.key,
|
|
219
243
|
types: ["ni"],
|
|
220
244
|
includeStatus: true,
|
|
@@ -225,14 +249,14 @@ describe("Task", async () => {
|
|
|
225
249
|
});
|
|
226
250
|
|
|
227
251
|
it("should handle empty results gracefully", async () => {
|
|
228
|
-
const result = await client.
|
|
252
|
+
const result = await client.tasks.retrieve({
|
|
229
253
|
types: ["nonexistent_type"],
|
|
230
254
|
});
|
|
231
255
|
expect(result).toEqual([]);
|
|
232
256
|
});
|
|
233
257
|
|
|
234
258
|
it("should combine rack and type filters", async () => {
|
|
235
|
-
const result = await client.
|
|
259
|
+
const result = await client.tasks.retrieve({
|
|
236
260
|
rack: secondRack.key,
|
|
237
261
|
types: ["labjack"],
|
|
238
262
|
});
|
|
@@ -241,14 +265,14 @@ describe("Task", async () => {
|
|
|
241
265
|
});
|
|
242
266
|
|
|
243
267
|
it("should handle limit without offset", async () => {
|
|
244
|
-
const result = await client.
|
|
268
|
+
const result = await client.tasks.retrieve({
|
|
245
269
|
limit: 1,
|
|
246
270
|
});
|
|
247
271
|
expect(result).toHaveLength(1);
|
|
248
272
|
});
|
|
249
273
|
|
|
250
274
|
it("should retrieve tasks with includeStatus in request object", async () => {
|
|
251
|
-
const result = await client.
|
|
275
|
+
const result = await client.tasks.retrieve({
|
|
252
276
|
rack: testRack.key,
|
|
253
277
|
includeStatus: true,
|
|
254
278
|
});
|
|
@@ -256,7 +280,7 @@ describe("Task", async () => {
|
|
|
256
280
|
|
|
257
281
|
await expect
|
|
258
282
|
.poll(async () => {
|
|
259
|
-
const tasks = await client.
|
|
283
|
+
const tasks = await client.tasks.retrieve({
|
|
260
284
|
rack: testRack.key,
|
|
261
285
|
includeStatus: true,
|
|
262
286
|
});
|
|
@@ -272,19 +296,19 @@ describe("Task", async () => {
|
|
|
272
296
|
config: { test: true },
|
|
273
297
|
});
|
|
274
298
|
|
|
275
|
-
const snapshotTask = await client.
|
|
299
|
+
const snapshotTask = await client.tasks.copy(
|
|
276
300
|
regularTask.key,
|
|
277
301
|
"snapshot_test_task",
|
|
278
302
|
true,
|
|
279
303
|
);
|
|
280
304
|
|
|
281
|
-
const snapshotOnlyResult = await client.
|
|
305
|
+
const snapshotOnlyResult = await client.tasks.retrieve({
|
|
282
306
|
snapshot: true,
|
|
283
307
|
});
|
|
284
308
|
expect(snapshotOnlyResult.some((t) => t.key === snapshotTask.key)).toBe(true);
|
|
285
309
|
expect(snapshotOnlyResult.every((t) => t.snapshot === true)).toBe(true);
|
|
286
310
|
|
|
287
|
-
const regularOnlyResult = await client.
|
|
311
|
+
const regularOnlyResult = await client.tasks.retrieve({
|
|
288
312
|
snapshot: false,
|
|
289
313
|
});
|
|
290
314
|
expect(regularOnlyResult.some((t) => t.key === regularTask.key)).toBe(true);
|
|
@@ -298,7 +322,7 @@ describe("Task", async () => {
|
|
|
298
322
|
config: { test: true },
|
|
299
323
|
});
|
|
300
324
|
|
|
301
|
-
const result = await client.
|
|
325
|
+
const result = await client.tasks.retrieve({
|
|
302
326
|
rack: testRack.key,
|
|
303
327
|
types: ["ni"],
|
|
304
328
|
snapshot: false,
|
|
@@ -311,6 +335,35 @@ describe("Task", async () => {
|
|
|
311
335
|
});
|
|
312
336
|
});
|
|
313
337
|
|
|
338
|
+
describe("list", () => {
|
|
339
|
+
it("should list all tasks excluding internal tasks", async () => {
|
|
340
|
+
const tasks = await client.tasks.list();
|
|
341
|
+
expect(Array.isArray(tasks)).toBe(true);
|
|
342
|
+
expect(tasks.every((t) => t.internal === false)).toBe(true);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it("should list tasks on a specific rack", async () => {
|
|
346
|
+
const task1 = await testRack.createTask({
|
|
347
|
+
name: `list-test-${Date.now()}`,
|
|
348
|
+
config: { test: true },
|
|
349
|
+
type: "ni",
|
|
350
|
+
});
|
|
351
|
+
const tasks = await client.tasks.list(testRack.key);
|
|
352
|
+
expect(tasks.some((t) => t.key === task1.key)).toBe(true);
|
|
353
|
+
expect(tasks.every((t) => task.rackKey(t.key) === testRack.key)).toBe(true);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it("should exclude internal tasks by default", async () => {
|
|
357
|
+
const allTasks = await client.tasks.list();
|
|
358
|
+
const internalTasks = await client.tasks.retrieve({
|
|
359
|
+
internal: true,
|
|
360
|
+
});
|
|
361
|
+
const allTaskKeys = allTasks.map((t) => t.key);
|
|
362
|
+
const internalTaskKeys = internalTasks.map((t) => t.key);
|
|
363
|
+
expect(internalTaskKeys.every((key) => !allTaskKeys.includes(key))).toBe(true);
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
|
|
314
367
|
describe("copy", () => {
|
|
315
368
|
it("should correctly copy the task", async () => {
|
|
316
369
|
const m = await testRack.createTask({
|
|
@@ -318,12 +371,122 @@ describe("Task", async () => {
|
|
|
318
371
|
config: { a: "dog" },
|
|
319
372
|
type: "ni",
|
|
320
373
|
});
|
|
321
|
-
const copy = await client.
|
|
374
|
+
const copy = await client.tasks.copy(m.key, "New Name", false);
|
|
322
375
|
expect(copy.name).toBe("New Name");
|
|
323
376
|
expect(copy.config).toStrictEqual({ a: "dog" });
|
|
324
377
|
});
|
|
325
378
|
});
|
|
326
379
|
|
|
380
|
+
describe("lifecycle methods", () => {
|
|
381
|
+
it("should start a task", async () => {
|
|
382
|
+
const t = await testRack.createTask({
|
|
383
|
+
name: "lifecycle-start-test",
|
|
384
|
+
config: {},
|
|
385
|
+
type: "ni",
|
|
386
|
+
});
|
|
387
|
+
const streamer = await client.openStreamer(task.COMMAND_CHANNEL_NAME);
|
|
388
|
+
await t.start();
|
|
389
|
+
await expect
|
|
390
|
+
.poll<Promise<task.Command>>(async () => {
|
|
391
|
+
const fr = await streamer.read();
|
|
392
|
+
const sample = fr.at(-1)[task.COMMAND_CHANNEL_NAME];
|
|
393
|
+
return task.commandZ.parse(sample);
|
|
394
|
+
})
|
|
395
|
+
.toMatchObject({ task: t.key, type: "start" });
|
|
396
|
+
streamer.close();
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
it("should stop a task", async () => {
|
|
400
|
+
const t = await testRack.createTask({
|
|
401
|
+
name: "lifecycle-stop-test",
|
|
402
|
+
config: {},
|
|
403
|
+
type: "ni",
|
|
404
|
+
});
|
|
405
|
+
const streamer = await client.openStreamer(task.COMMAND_CHANNEL_NAME);
|
|
406
|
+
await t.stop();
|
|
407
|
+
await expect
|
|
408
|
+
.poll<Promise<task.Command>>(async () => {
|
|
409
|
+
const fr = await streamer.read();
|
|
410
|
+
const sample = fr.at(-1)[task.COMMAND_CHANNEL_NAME];
|
|
411
|
+
return task.commandZ.parse(sample);
|
|
412
|
+
})
|
|
413
|
+
.toMatchObject({ task: t.key, type: "stop" });
|
|
414
|
+
streamer.close();
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
it("should run a task with automatic start and stop", async () => {
|
|
418
|
+
const t = await testRack.createTask({
|
|
419
|
+
name: "lifecycle-run-test",
|
|
420
|
+
config: {},
|
|
421
|
+
type: "ni",
|
|
422
|
+
});
|
|
423
|
+
const streamer = await client.openStreamer(task.COMMAND_CHANNEL_NAME);
|
|
424
|
+
let executedCallback = false;
|
|
425
|
+
|
|
426
|
+
await t.run(async () => {
|
|
427
|
+
executedCallback = true;
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
expect(executedCallback).toBe(true);
|
|
431
|
+
|
|
432
|
+
// Should have received both start and stop commands
|
|
433
|
+
const commands: task.Command[] = [];
|
|
434
|
+
await expect
|
|
435
|
+
.poll(async () => {
|
|
436
|
+
try {
|
|
437
|
+
const fr = await streamer.read();
|
|
438
|
+
const samples = fr.get(task.COMMAND_CHANNEL_NAME);
|
|
439
|
+
for (const sample of samples) commands.push(task.commandZ.parse(sample));
|
|
440
|
+
|
|
441
|
+
return (
|
|
442
|
+
commands.some((c) => c.task === t.key && c.type === "start") &&
|
|
443
|
+
commands.some((c) => c.task === t.key && c.type === "stop")
|
|
444
|
+
);
|
|
445
|
+
} catch {
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
})
|
|
449
|
+
.toBe(true);
|
|
450
|
+
|
|
451
|
+
streamer.close();
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
it("should stop task even if callback throws error", async () => {
|
|
455
|
+
const t = await testRack.createTask({
|
|
456
|
+
name: "lifecycle-run-error-test",
|
|
457
|
+
config: {},
|
|
458
|
+
type: "ni",
|
|
459
|
+
});
|
|
460
|
+
const streamer = await client.openStreamer(task.COMMAND_CHANNEL_NAME);
|
|
461
|
+
|
|
462
|
+
await expect(
|
|
463
|
+
t.run(async () => {
|
|
464
|
+
throw new Error("Test error");
|
|
465
|
+
}),
|
|
466
|
+
).rejects.toThrow("Test error");
|
|
467
|
+
|
|
468
|
+
// Should still have received stop command
|
|
469
|
+
const stopCommands: task.Command[] = [];
|
|
470
|
+
await expect
|
|
471
|
+
.poll(async () => {
|
|
472
|
+
try {
|
|
473
|
+
const fr = await streamer.read();
|
|
474
|
+
const samples = fr.get(task.COMMAND_CHANNEL_NAME);
|
|
475
|
+
for (const sample of samples) {
|
|
476
|
+
const cmd = task.commandZ.parse(sample);
|
|
477
|
+
if (cmd.task === t.key && cmd.type === "stop") stopCommands.push(cmd);
|
|
478
|
+
}
|
|
479
|
+
return stopCommands.length > 0;
|
|
480
|
+
} catch {
|
|
481
|
+
return false;
|
|
482
|
+
}
|
|
483
|
+
})
|
|
484
|
+
.toBe(true);
|
|
485
|
+
|
|
486
|
+
streamer.close();
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
|
|
327
490
|
describe("executeCommand", () => {
|
|
328
491
|
it("should execute a command on a task", async () => {
|
|
329
492
|
const type = "testCmd";
|
|
@@ -334,7 +497,7 @@ describe("Task", async () => {
|
|
|
334
497
|
type: "ni",
|
|
335
498
|
});
|
|
336
499
|
const streamer = await client.openStreamer(task.COMMAND_CHANNEL_NAME);
|
|
337
|
-
const key = await client.
|
|
500
|
+
const key = await client.tasks.executeCommand({
|
|
338
501
|
task: t.key,
|
|
339
502
|
type,
|
|
340
503
|
args,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Copyright 2025 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 { id } from "@synnaxlabs/x";
|
|
11
|
+
|
|
12
|
+
import { policy } from "@/access/policy";
|
|
13
|
+
import { role } from "@/access/role";
|
|
14
|
+
import type Synnax from "@/client";
|
|
15
|
+
import { createTestClient } from "@/testutil/client";
|
|
16
|
+
|
|
17
|
+
export const createTestClientWithPolicy = async (client: Synnax, pol: policy.New) => {
|
|
18
|
+
const username = id.create();
|
|
19
|
+
const u = await client.users.create({
|
|
20
|
+
username,
|
|
21
|
+
password: "test",
|
|
22
|
+
firstName: "test",
|
|
23
|
+
lastName: "test",
|
|
24
|
+
});
|
|
25
|
+
const p = await client.access.policies.create(pol);
|
|
26
|
+
const r = await client.access.roles.create({
|
|
27
|
+
name: "test",
|
|
28
|
+
description: "test",
|
|
29
|
+
});
|
|
30
|
+
await client.ontology.addChildren(role.ontologyID(r.key), policy.ontologyID(p.key));
|
|
31
|
+
await client.access.roles.assign({ user: u.key, role: r.key });
|
|
32
|
+
const userClient = createTestClient({ username, password: "test" });
|
|
33
|
+
return userClient;
|
|
34
|
+
};
|
package/src/testutil/channels.ts
CHANGED
|
@@ -17,13 +17,13 @@ export const newIndexedPair = async (
|
|
|
17
17
|
): Promise<[channel.Channel, channel.Channel]> => {
|
|
18
18
|
const index = await client.channels.create({
|
|
19
19
|
leaseholder: 1,
|
|
20
|
-
name:
|
|
20
|
+
name: id.create(),
|
|
21
21
|
dataType: DataType.TIMESTAMP,
|
|
22
22
|
isIndex: true,
|
|
23
23
|
});
|
|
24
24
|
const data = await client.channels.create({
|
|
25
25
|
leaseholder: 1,
|
|
26
|
-
name:
|
|
26
|
+
name: id.create(),
|
|
27
27
|
dataType: DataType.FLOAT64,
|
|
28
28
|
index: index.key,
|
|
29
29
|
});
|
|
@@ -32,7 +32,7 @@ export const newIndexedPair = async (
|
|
|
32
32
|
|
|
33
33
|
export const newVirtualChannel = async (client: Synnax): Promise<channel.Channel> => {
|
|
34
34
|
const ch = await client.channels.create({
|
|
35
|
-
name:
|
|
35
|
+
name: id.create(),
|
|
36
36
|
dataType: DataType.FLOAT64,
|
|
37
37
|
virtual: true,
|
|
38
38
|
});
|
package/src/testutil/client.ts
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
import { TimeSpan } from "@synnaxlabs/x";
|
|
11
11
|
|
|
12
|
-
import Synnax, { type
|
|
12
|
+
import Synnax, { type SynnaxParams } from "@/client";
|
|
13
13
|
|
|
14
|
-
export const
|
|
14
|
+
export const TEST_CLIENT_PARAMS: SynnaxParams = {
|
|
15
15
|
host: "localhost",
|
|
16
16
|
port: 9090,
|
|
17
17
|
username: "synnax",
|
|
@@ -23,5 +23,5 @@ export const TEST_CLIENT_PROPS: SynnaxProps = {
|
|
|
23
23
|
},
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
export const createTestClient = (
|
|
27
|
-
new Synnax({ ...
|
|
26
|
+
export const createTestClient = (params?: Partial<SynnaxParams>): Synnax =>
|
|
27
|
+
new Synnax({ ...TEST_CLIENT_PARAMS, ...params });
|
package/src/transport.ts
CHANGED
|
@@ -16,8 +16,6 @@ import {
|
|
|
16
16
|
} from "@synnaxlabs/freighter";
|
|
17
17
|
import { binary, type breaker, type URL } from "@synnaxlabs/x";
|
|
18
18
|
|
|
19
|
-
const baseAPIEndpoint = "/api/v1/";
|
|
20
|
-
|
|
21
19
|
export class Transport {
|
|
22
20
|
readonly url: URL;
|
|
23
21
|
readonly unary: UnaryClient;
|
|
@@ -26,7 +24,7 @@ export class Transport {
|
|
|
26
24
|
|
|
27
25
|
constructor(url: URL, breakerCfg: breaker.Config = {}, secure: boolean = false) {
|
|
28
26
|
this.secure = secure;
|
|
29
|
-
this.url = url.child(
|
|
27
|
+
this.url = url.child("/api/v1/");
|
|
30
28
|
const codec = new binary.JSONCodec();
|
|
31
29
|
this.unary = unaryWithBreaker(
|
|
32
30
|
new HTTPClient(this.url, codec, this.secure),
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Copyright 2025 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 { id } from "@synnaxlabs/x";
|
|
11
|
+
import { describe, expect, it } from "vitest";
|
|
12
|
+
|
|
13
|
+
import { AuthError, NotFoundError } from "@/errors";
|
|
14
|
+
import { createTestClientWithPolicy } from "@/testutil/access";
|
|
15
|
+
import { createTestClient } from "@/testutil/client";
|
|
16
|
+
import { user } from "@/user";
|
|
17
|
+
|
|
18
|
+
const client = createTestClient();
|
|
19
|
+
|
|
20
|
+
describe("user", () => {
|
|
21
|
+
describe("access control", () => {
|
|
22
|
+
it("should deny access when no retrieve policy exists", async () => {
|
|
23
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
24
|
+
name: "test",
|
|
25
|
+
objects: [],
|
|
26
|
+
actions: [],
|
|
27
|
+
});
|
|
28
|
+
const randomUser = await client.users.create({
|
|
29
|
+
username: id.create(),
|
|
30
|
+
password: "test",
|
|
31
|
+
});
|
|
32
|
+
await expect(userClient.users.retrieve({ key: randomUser.key })).rejects.toThrow(
|
|
33
|
+
AuthError,
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should allow the caller to retrieve users with the correct policy", async () => {
|
|
38
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
39
|
+
name: "test",
|
|
40
|
+
objects: [user.ontologyID("")],
|
|
41
|
+
actions: ["retrieve"],
|
|
42
|
+
});
|
|
43
|
+
const randomUser = await client.users.create({
|
|
44
|
+
username: id.create(),
|
|
45
|
+
password: "test",
|
|
46
|
+
});
|
|
47
|
+
const retrieved = await userClient.users.retrieve({ key: randomUser.key });
|
|
48
|
+
expect(retrieved.key).toBe(randomUser.key);
|
|
49
|
+
expect(retrieved.username).toBe(randomUser.username);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should allow the caller to create users with the correct policy", async () => {
|
|
53
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
54
|
+
name: "test",
|
|
55
|
+
objects: [user.ontologyID("")],
|
|
56
|
+
actions: ["create"],
|
|
57
|
+
});
|
|
58
|
+
await userClient.users.create({
|
|
59
|
+
username: id.create(),
|
|
60
|
+
password: "test",
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("should deny access when no create policy exists", async () => {
|
|
65
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
66
|
+
name: "test",
|
|
67
|
+
objects: [user.ontologyID("")],
|
|
68
|
+
actions: [],
|
|
69
|
+
});
|
|
70
|
+
await expect(
|
|
71
|
+
userClient.users.create({
|
|
72
|
+
username: id.create(),
|
|
73
|
+
password: "test",
|
|
74
|
+
}),
|
|
75
|
+
).rejects.toThrow(AuthError);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("should allow the caller to delete users with the correct policy", async () => {
|
|
79
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
80
|
+
name: "test",
|
|
81
|
+
objects: [user.ontologyID("")],
|
|
82
|
+
actions: ["delete"],
|
|
83
|
+
});
|
|
84
|
+
const randomUser = await client.users.create({
|
|
85
|
+
username: id.create(),
|
|
86
|
+
password: "test",
|
|
87
|
+
});
|
|
88
|
+
await userClient.users.delete(randomUser.key);
|
|
89
|
+
await expect(userClient.users.retrieve({ key: randomUser.key })).rejects.toThrow(
|
|
90
|
+
NotFoundError,
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("should deny access when no delete policy exists", async () => {
|
|
95
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
96
|
+
name: "test",
|
|
97
|
+
objects: [user.ontologyID("")],
|
|
98
|
+
actions: [],
|
|
99
|
+
});
|
|
100
|
+
const randomUser = await client.users.create({
|
|
101
|
+
username: id.create(),
|
|
102
|
+
password: "test",
|
|
103
|
+
});
|
|
104
|
+
await expect(userClient.users.delete(randomUser.key)).rejects.toThrow(AuthError);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|