@synnaxlabs/client 0.48.0 → 0.49.2
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 +6 -6
- package/dist/client.cjs +33 -31
- package/dist/client.js +6522 -6167
- 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 +18 -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 +9 -5
- package/dist/src/client.d.ts.map +1 -1
- 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/client.d.ts +11 -1
- package/dist/src/framer/client.d.ts.map +1 -1
- package/dist/src/framer/frame.d.ts +10 -5
- package/dist/src/framer/frame.d.ts.map +1 -1
- package/dist/src/framer/iterator.d.ts +3 -3
- package/dist/src/framer/reader.d.ts +16 -0
- package/dist/src/framer/reader.d.ts.map +1 -0
- package/dist/src/framer/reader.spec.d.ts +2 -0
- package/dist/src/framer/reader.spec.d.ts.map +1 -0
- 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 +4 -5
- 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/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/package.json +3 -3
- 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.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 +35 -7
- package/src/channel/retriever.ts +10 -11
- package/src/channel/writer.ts +3 -7
- package/src/client.ts +14 -18
- 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 +14 -14
- package/src/framer/client.spec.ts +14 -20
- package/src/framer/client.ts +15 -20
- package/src/framer/deleter.spec.ts +1 -1
- package/src/framer/frame.spec.ts +131 -0
- package/src/framer/frame.ts +10 -2
- package/src/framer/iterator.ts +3 -3
- package/src/framer/reader.spec.ts +736 -0
- package/src/framer/reader.ts +265 -0
- package/src/framer/streamer.spec.ts +100 -12
- package/src/framer/streamer.ts +29 -9
- package/src/framer/writer.spec.ts +5 -5
- package/src/index.ts +4 -5
- 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/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
|
@@ -13,8 +13,8 @@ import { z } from "zod";
|
|
|
13
13
|
export const keyZ = z.uint32();
|
|
14
14
|
export type Key = z.infer<typeof keyZ>;
|
|
15
15
|
|
|
16
|
-
export const
|
|
17
|
-
export const statusZ = status.statusZ(
|
|
16
|
+
export const statusDetailsZ = z.object({ rack: keyZ });
|
|
17
|
+
export const statusZ = status.statusZ(statusDetailsZ);
|
|
18
18
|
|
|
19
19
|
export interface Status extends z.infer<typeof statusZ> {}
|
|
20
20
|
|
|
@@ -7,10 +7,11 @@
|
|
|
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 { TimeStamp } from "@synnaxlabs/x";
|
|
10
11
|
import { describe, expect, it } from "vitest";
|
|
11
12
|
import { ZodError } from "zod";
|
|
12
13
|
|
|
13
|
-
import { type rack } from "@/
|
|
14
|
+
import { type rack } from "@/rack";
|
|
14
15
|
import { createTestClient } from "@/testutil/client";
|
|
15
16
|
|
|
16
17
|
const client = createTestClient();
|
|
@@ -18,55 +19,80 @@ const client = createTestClient();
|
|
|
18
19
|
describe("Rack", () => {
|
|
19
20
|
describe("create", () => {
|
|
20
21
|
it("should create a single rack", async () => {
|
|
21
|
-
const r = await client.
|
|
22
|
+
const r = await client.racks.create({ name: "test" });
|
|
22
23
|
expect(r.key).toBeGreaterThan(0n);
|
|
23
24
|
});
|
|
24
25
|
it("should return an error if the rack doesn't have a name", async () => {
|
|
25
26
|
// @ts-expect-error - Testing for error
|
|
26
|
-
await expect(client.
|
|
27
|
+
await expect(client.racks.create({})).rejects.toThrow(ZodError);
|
|
28
|
+
});
|
|
29
|
+
it("should create a rack with a custom status", async () => {
|
|
30
|
+
const customStatus: rack.Status = {
|
|
31
|
+
key: "",
|
|
32
|
+
name: "",
|
|
33
|
+
variant: "success",
|
|
34
|
+
message: "Custom rack status",
|
|
35
|
+
description: "Rack is running",
|
|
36
|
+
time: TimeStamp.now(),
|
|
37
|
+
details: { rack: 0 },
|
|
38
|
+
};
|
|
39
|
+
const r = await client.racks.create({
|
|
40
|
+
name: "rack-with-status",
|
|
41
|
+
status: customStatus,
|
|
42
|
+
});
|
|
43
|
+
expect(r.key).toBeGreaterThan(0n);
|
|
44
|
+
const retrieved = await client.racks.retrieve({
|
|
45
|
+
key: r.key,
|
|
46
|
+
includeStatus: true,
|
|
47
|
+
});
|
|
48
|
+
expect(retrieved.status).toBeDefined();
|
|
49
|
+
expect(retrieved.status?.variant).toBe("success");
|
|
50
|
+
expect(retrieved.status?.message).toBe("Custom rack status");
|
|
51
|
+
expect(retrieved.status?.description).toBe("Rack is running");
|
|
52
|
+
expect(retrieved.status?.details?.rack).toBe(r.key);
|
|
27
53
|
});
|
|
28
54
|
});
|
|
29
55
|
describe("update", () => {
|
|
30
56
|
it("should update a rack if the key is provided", async () => {
|
|
31
|
-
const r = await client.
|
|
32
|
-
const updated = await client.
|
|
57
|
+
const r = await client.racks.create({ name: "test" });
|
|
58
|
+
const updated = await client.racks.create({
|
|
33
59
|
key: r.key,
|
|
34
60
|
name: "updated",
|
|
35
61
|
});
|
|
36
62
|
expect(updated.name).toBe("updated");
|
|
37
|
-
const retrieved = await client.
|
|
63
|
+
const retrieved = await client.racks.retrieve({ key: r.key });
|
|
38
64
|
expect(retrieved.name).toBe("updated");
|
|
39
65
|
});
|
|
40
66
|
});
|
|
41
67
|
describe("retrieve", () => {
|
|
42
68
|
it("should retrieve a rack by its key", async () => {
|
|
43
|
-
const r = await client.
|
|
44
|
-
const retrieved = await client.
|
|
69
|
+
const r = await client.racks.create({ name: "test" });
|
|
70
|
+
const retrieved = await client.racks.retrieve({ key: r.key });
|
|
45
71
|
expect(retrieved.key).toBe(r.key);
|
|
46
72
|
expect(retrieved.name).toBe("test");
|
|
47
73
|
});
|
|
48
74
|
it("should retrieve a rack by its name", async () => {
|
|
49
|
-
const name =
|
|
50
|
-
const r = await client.
|
|
51
|
-
const retrieved = await client.
|
|
75
|
+
const name = `${TimeStamp.now().toString()}-${Math.random()}`;
|
|
76
|
+
const r = await client.racks.create({ name });
|
|
77
|
+
const retrieved = await client.racks.retrieve({ name });
|
|
52
78
|
expect(retrieved.key).toBe(r.key);
|
|
53
79
|
expect(retrieved.name).toEqual(name);
|
|
54
80
|
});
|
|
55
81
|
});
|
|
56
82
|
describe("tasks", () => {
|
|
57
83
|
it("should list the tasks on a rack", async () => {
|
|
58
|
-
const r = await client.
|
|
84
|
+
const r = await client.racks.create({ name: "test" });
|
|
59
85
|
const tasks = await r.listTasks();
|
|
60
86
|
expect(tasks).toHaveLength(0);
|
|
61
87
|
});
|
|
62
88
|
});
|
|
63
89
|
describe("status", () => {
|
|
64
90
|
it("should include the rack's status when includeStatus is true", async () => {
|
|
65
|
-
const r = await client.
|
|
91
|
+
const r = await client.racks.create({ name: "test" });
|
|
66
92
|
let status: rack.Status | undefined;
|
|
67
93
|
await expect
|
|
68
94
|
.poll(async () => {
|
|
69
|
-
const retrieved = await client.
|
|
95
|
+
const retrieved = await client.racks.retrieve({
|
|
70
96
|
key: r.key,
|
|
71
97
|
includeStatus: true,
|
|
72
98
|
});
|
|
@@ -77,12 +103,12 @@ describe("Rack", () => {
|
|
|
77
103
|
expect(status?.details?.rack).toBe(r.key);
|
|
78
104
|
});
|
|
79
105
|
it("should include the status for multiple racks", async () => {
|
|
80
|
-
const r1 = await client.
|
|
81
|
-
const r2 = await client.
|
|
106
|
+
const r1 = await client.racks.create({ name: "test1" });
|
|
107
|
+
const r2 = await client.racks.create({ name: "test2" });
|
|
82
108
|
let statuses: (rack.Status | undefined)[] = [];
|
|
83
109
|
await expect
|
|
84
110
|
.poll(async () => {
|
|
85
|
-
const retrieved = await client.
|
|
111
|
+
const retrieved = await client.racks.retrieve({
|
|
86
112
|
keys: [r1.key, r2.key],
|
|
87
113
|
includeStatus: true,
|
|
88
114
|
});
|
|
@@ -0,0 +1,115 @@
|
|
|
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 { TimeRange } from "@synnaxlabs/x";
|
|
11
|
+
import { describe, expect, it } from "vitest";
|
|
12
|
+
|
|
13
|
+
import { AuthError, NotFoundError } from "@/errors";
|
|
14
|
+
import { ranger } from "@/ranger";
|
|
15
|
+
import { createTestClientWithPolicy } from "@/testutil/access";
|
|
16
|
+
import { createTestClient } from "@/testutil/client";
|
|
17
|
+
|
|
18
|
+
const client = createTestClient();
|
|
19
|
+
|
|
20
|
+
describe("range", () => {
|
|
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 randomRange = await client.ranges.create({
|
|
29
|
+
name: "test",
|
|
30
|
+
timeRange: new TimeRange(1n, 1000n),
|
|
31
|
+
color: "#E774D0",
|
|
32
|
+
});
|
|
33
|
+
await expect(userClient.ranges.retrieve(randomRange.key)).rejects.toThrow(
|
|
34
|
+
AuthError,
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should allow the caller to retrieve ranges with the correct policy", async () => {
|
|
39
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
40
|
+
name: "test",
|
|
41
|
+
objects: [ranger.ontologyID("")],
|
|
42
|
+
actions: ["retrieve"],
|
|
43
|
+
});
|
|
44
|
+
const randomRange = await client.ranges.create({
|
|
45
|
+
name: "test",
|
|
46
|
+
timeRange: new TimeRange(1n, 1000n),
|
|
47
|
+
color: "#E774D0",
|
|
48
|
+
});
|
|
49
|
+
const retrieved = await userClient.ranges.retrieve(randomRange.key);
|
|
50
|
+
expect(retrieved.key).toBe(randomRange.key);
|
|
51
|
+
expect(retrieved.name).toBe(randomRange.name);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should allow the caller to create ranges with the correct policy", async () => {
|
|
55
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
56
|
+
name: "test",
|
|
57
|
+
objects: [ranger.ontologyID("")],
|
|
58
|
+
actions: ["create"],
|
|
59
|
+
});
|
|
60
|
+
await userClient.ranges.create({
|
|
61
|
+
name: "test",
|
|
62
|
+
timeRange: new TimeRange(1n, 1000n),
|
|
63
|
+
color: "#E774D0",
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("should deny access when no create policy exists", async () => {
|
|
68
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
69
|
+
name: "test",
|
|
70
|
+
objects: [ranger.ontologyID("")],
|
|
71
|
+
actions: [],
|
|
72
|
+
});
|
|
73
|
+
await expect(
|
|
74
|
+
userClient.ranges.create({
|
|
75
|
+
name: "test",
|
|
76
|
+
timeRange: new TimeRange(1n, 1000n),
|
|
77
|
+
color: "#E774D0",
|
|
78
|
+
}),
|
|
79
|
+
).rejects.toThrow(AuthError);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should allow the caller to delete ranges with the correct policy", async () => {
|
|
83
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
84
|
+
name: "test",
|
|
85
|
+
objects: [ranger.ontologyID("")],
|
|
86
|
+
actions: ["delete"],
|
|
87
|
+
});
|
|
88
|
+
const randomRange = await client.ranges.create({
|
|
89
|
+
name: "test",
|
|
90
|
+
timeRange: new TimeRange(1n, 1000n),
|
|
91
|
+
color: "#E774D0",
|
|
92
|
+
});
|
|
93
|
+
await userClient.ranges.delete(randomRange.key);
|
|
94
|
+
await expect(userClient.ranges.retrieve(randomRange.key)).rejects.toThrow(
|
|
95
|
+
NotFoundError,
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("should deny access when no delete policy exists", async () => {
|
|
100
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
101
|
+
name: "test",
|
|
102
|
+
objects: [ranger.ontologyID("")],
|
|
103
|
+
actions: [],
|
|
104
|
+
});
|
|
105
|
+
const randomRange = await client.ranges.create({
|
|
106
|
+
name: "test",
|
|
107
|
+
timeRange: new TimeRange(1n, 1000n),
|
|
108
|
+
color: "#E774D0",
|
|
109
|
+
});
|
|
110
|
+
await expect(userClient.ranges.delete(randomRange.key)).rejects.toThrow(
|
|
111
|
+
AuthError,
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
package/src/ranger/alias.ts
CHANGED
|
@@ -12,7 +12,6 @@ import { array, type change } from "@synnaxlabs/x";
|
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
|
|
14
14
|
import { channel } from "@/channel";
|
|
15
|
-
import { type framer } from "@/framer";
|
|
16
15
|
import { type Key, keyZ } from "@/ranger/payload";
|
|
17
16
|
|
|
18
17
|
export const SET_ALIAS_CHANNEL_NAME = "sy_range_alias_set";
|
|
@@ -39,21 +38,14 @@ const retrieveReqZ = z.object({ range: keyZ, channels: channel.keyZ.array() });
|
|
|
39
38
|
const retrieveResZ = z.object({ aliases: z.record(z.string(), z.string()) });
|
|
40
39
|
|
|
41
40
|
export class Aliaser {
|
|
42
|
-
private static readonly SET_ENDPOINT = "/range/alias/set";
|
|
43
|
-
private static readonly RESOLVE_ENDPOINT = "/range/alias/resolve";
|
|
44
|
-
private static readonly LIST_ENDPOINT = "/range/alias/list";
|
|
45
|
-
private static readonly RETRIEVE_ENDPOINT = "/range/alias/retrieve";
|
|
46
|
-
private static readonly DELETE_ENDPOINT = "/range/alias/delete";
|
|
47
|
-
private readonly frameClient: framer.Client;
|
|
48
41
|
private readonly cache = new Map<string, channel.Key>();
|
|
49
42
|
private readonly client: UnaryClient;
|
|
50
43
|
private readonly rangeKey: Key;
|
|
51
44
|
|
|
52
|
-
constructor(rangeKey: Key,
|
|
45
|
+
constructor(rangeKey: Key, client: UnaryClient) {
|
|
53
46
|
this.rangeKey = rangeKey;
|
|
54
47
|
this.cache = new Map();
|
|
55
48
|
this.client = client;
|
|
56
|
-
this.frameClient = frameClient;
|
|
57
49
|
}
|
|
58
50
|
|
|
59
51
|
resolve(aliases: string): Promise<channel.Key>;
|
|
@@ -79,7 +71,7 @@ export class Aliaser {
|
|
|
79
71
|
if (toFetch.length === 0) return cached;
|
|
80
72
|
const res = await sendRequired<typeof resolveReqZ, typeof resolveResZ>(
|
|
81
73
|
this.client,
|
|
82
|
-
|
|
74
|
+
"/range/alias/resolve",
|
|
83
75
|
{ range: this.rangeKey, aliases: toFetch },
|
|
84
76
|
resolveReqZ,
|
|
85
77
|
resolveResZ,
|
|
@@ -91,7 +83,7 @@ export class Aliaser {
|
|
|
91
83
|
async set(aliases: Record<channel.Key, string>): Promise<void> {
|
|
92
84
|
await sendRequired<typeof setReqZ, typeof setResZ>(
|
|
93
85
|
this.client,
|
|
94
|
-
|
|
86
|
+
"/range/alias/set",
|
|
95
87
|
{ range: this.rangeKey, aliases },
|
|
96
88
|
setReqZ,
|
|
97
89
|
setResZ,
|
|
@@ -102,7 +94,7 @@ export class Aliaser {
|
|
|
102
94
|
return (
|
|
103
95
|
await sendRequired<typeof listReqZ, typeof listResZ>(
|
|
104
96
|
this.client,
|
|
105
|
-
|
|
97
|
+
"/range/alias/list",
|
|
106
98
|
{ range: this.rangeKey },
|
|
107
99
|
listReqZ,
|
|
108
100
|
listResZ,
|
|
@@ -119,7 +111,7 @@ export class Aliaser {
|
|
|
119
111
|
const isSingle = typeof alias === "number";
|
|
120
112
|
const res = await sendRequired<typeof retrieveReqZ, typeof retrieveResZ>(
|
|
121
113
|
this.client,
|
|
122
|
-
|
|
114
|
+
"/range/alias/retrieve",
|
|
123
115
|
{ range: this.rangeKey, channels: array.toArray(alias) },
|
|
124
116
|
retrieveReqZ,
|
|
125
117
|
retrieveResZ,
|
|
@@ -130,7 +122,7 @@ export class Aliaser {
|
|
|
130
122
|
async delete(aliases: channel.Key | channel.Key[]): Promise<void> {
|
|
131
123
|
await sendRequired<typeof deleteReqZ, typeof deleteResZ>(
|
|
132
124
|
this.client,
|
|
133
|
-
|
|
125
|
+
"/range/alias/delete",
|
|
134
126
|
{ range: this.rangeKey, channels: array.toArray(aliases) },
|
|
135
127
|
deleteReqZ,
|
|
136
128
|
deleteResZ,
|
package/src/ranger/client.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { type channel } from "@/channel";
|
|
|
15
15
|
import { QueryError } from "@/errors";
|
|
16
16
|
import { type framer } from "@/framer";
|
|
17
17
|
import { label } from "@/label";
|
|
18
|
-
import {
|
|
18
|
+
import { ontology } from "@/ontology";
|
|
19
19
|
import { Aliaser } from "@/ranger/alias";
|
|
20
20
|
import { KV } from "@/ranger/kv";
|
|
21
21
|
import {
|
|
@@ -163,12 +163,12 @@ export class Range {
|
|
|
163
163
|
|
|
164
164
|
const retrieveRequestZ = z.object({
|
|
165
165
|
keys: keyZ.array().optional(),
|
|
166
|
-
names: z.
|
|
166
|
+
names: z.string().array().optional(),
|
|
167
167
|
searchTerm: z.string().optional(),
|
|
168
168
|
overlapsWith: TimeRange.z.optional(),
|
|
169
|
-
limit: z.number().int().optional(),
|
|
170
|
-
offset: z.number().int().optional(),
|
|
171
169
|
hasLabels: label.keyZ.array().optional(),
|
|
170
|
+
limit: z.int().optional(),
|
|
171
|
+
offset: z.int().optional(),
|
|
172
172
|
includeLabels: z.boolean().optional(),
|
|
173
173
|
includeParent: z.boolean().optional(),
|
|
174
174
|
});
|
|
@@ -189,8 +189,6 @@ const retrieveArgsZ = retrieveRequestZ
|
|
|
189
189
|
|
|
190
190
|
export type RetrieveArgs = z.input<typeof retrieveArgsZ>;
|
|
191
191
|
|
|
192
|
-
const RETRIEVE_ENDPOINT = "/range/retrieve";
|
|
193
|
-
|
|
194
192
|
const retrieveResZ = z.object({ ranges: array.nullableZ(payloadZ) });
|
|
195
193
|
|
|
196
194
|
export class Client {
|
|
@@ -244,7 +242,7 @@ export class Client {
|
|
|
244
242
|
const isSingle = typeof params === "string";
|
|
245
243
|
const { ranges } = await sendRequired(
|
|
246
244
|
this.unaryClient,
|
|
247
|
-
|
|
245
|
+
"/range/retrieve",
|
|
248
246
|
params,
|
|
249
247
|
retrieveArgsZ,
|
|
250
248
|
retrieveResZ,
|
|
@@ -271,7 +269,7 @@ export class Client {
|
|
|
271
269
|
}
|
|
272
270
|
|
|
273
271
|
async retrieveAlias(range: Key, channel: channel.Key): Promise<string> {
|
|
274
|
-
const aliaser = new Aliaser(range, this.
|
|
272
|
+
const aliaser = new Aliaser(range, this.unaryClient);
|
|
275
273
|
return await aliaser.retrieve(channel);
|
|
276
274
|
}
|
|
277
275
|
|
|
@@ -279,22 +277,22 @@ export class Client {
|
|
|
279
277
|
range: Key,
|
|
280
278
|
channels: channel.Key[],
|
|
281
279
|
): Promise<Record<channel.Key, string>> {
|
|
282
|
-
const aliaser = new Aliaser(range, this.
|
|
280
|
+
const aliaser = new Aliaser(range, this.unaryClient);
|
|
283
281
|
return await aliaser.retrieve(channels);
|
|
284
282
|
}
|
|
285
283
|
|
|
286
284
|
async listAliases(range: Key): Promise<Record<channel.Key, string>> {
|
|
287
|
-
const aliaser = new Aliaser(range, this.
|
|
285
|
+
const aliaser = new Aliaser(range, this.unaryClient);
|
|
288
286
|
return await aliaser.list();
|
|
289
287
|
}
|
|
290
288
|
|
|
291
289
|
async setAlias(range: Key, channel: channel.Key, alias: string): Promise<void> {
|
|
292
|
-
const aliaser = new Aliaser(range, this.
|
|
290
|
+
const aliaser = new Aliaser(range, this.unaryClient);
|
|
293
291
|
await aliaser.set({ [channel]: alias });
|
|
294
292
|
}
|
|
295
293
|
|
|
296
294
|
async deleteAlias(range: Key, channels: channel.Key | channel.Key[]): Promise<void> {
|
|
297
|
-
const aliaser = new Aliaser(range, this.
|
|
295
|
+
const aliaser = new Aliaser(range, this.unaryClient);
|
|
298
296
|
await aliaser.delete(channels);
|
|
299
297
|
}
|
|
300
298
|
|
|
@@ -302,7 +300,7 @@ export class Client {
|
|
|
302
300
|
return new Range(payload, {
|
|
303
301
|
frameClient: this.frameClient,
|
|
304
302
|
kv: new KV(payload.key, this.unaryClient),
|
|
305
|
-
aliaser: new Aliaser(payload.key, this.
|
|
303
|
+
aliaser: new Aliaser(payload.key, this.unaryClient),
|
|
306
304
|
channels: this.channels,
|
|
307
305
|
labelClient: this.labelClient,
|
|
308
306
|
ontologyClient: this.ontologyClient,
|
|
@@ -326,7 +324,8 @@ export class Client {
|
|
|
326
324
|
}
|
|
327
325
|
}
|
|
328
326
|
|
|
329
|
-
export const ontologyID =
|
|
327
|
+
export const ontologyID = ontology.createIDFactory<Key>("range");
|
|
328
|
+
export const TYPE_ONTOLOGY_ID = ontologyID("");
|
|
330
329
|
|
|
331
330
|
export const aliasOntologyID = (key: Key): ontology.ID => ({
|
|
332
331
|
type: "range-alias",
|
package/src/ranger/kv.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
10
|
import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
|
|
11
|
-
import { array
|
|
11
|
+
import { array } from "@synnaxlabs/x";
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
|
|
14
14
|
import { type Key, keyZ } from "@/ranger/payload";
|
|
@@ -34,9 +34,6 @@ const deleteReqZ = z.object({ range: keyZ, keys: z.string().array() });
|
|
|
34
34
|
export interface DeleteRequest extends z.infer<typeof deleteReqZ> {}
|
|
35
35
|
|
|
36
36
|
export class KV {
|
|
37
|
-
private static readonly GET_ENDPOINT = "/range/kv/get";
|
|
38
|
-
private static readonly SET_ENDPOINT = "/range/kv/set";
|
|
39
|
-
private static readonly DELETE_ENDPOINT = "/range/kv/delete";
|
|
40
37
|
private readonly rangeKey: Key;
|
|
41
38
|
private readonly client: UnaryClient;
|
|
42
39
|
|
|
@@ -50,7 +47,7 @@ export class KV {
|
|
|
50
47
|
async get(keys: string | string[]): Promise<string | Record<string, string>> {
|
|
51
48
|
const res = await sendRequired(
|
|
52
49
|
this.client,
|
|
53
|
-
|
|
50
|
+
"/range/kv/get",
|
|
54
51
|
{ range: this.rangeKey, keys: array.toArray(keys) },
|
|
55
52
|
getReqZ,
|
|
56
53
|
getResZ,
|
|
@@ -67,16 +64,17 @@ export class KV {
|
|
|
67
64
|
async set(kv: Record<string, string>): Promise<void>;
|
|
68
65
|
async set(key: string | Record<string, string>, value: string = ""): Promise<void> {
|
|
69
66
|
let pairs: KVPair[];
|
|
70
|
-
if (
|
|
67
|
+
if (typeof key == "string") pairs = [{ range: this.rangeKey, key, value }];
|
|
68
|
+
else
|
|
71
69
|
pairs = Object.entries(key).map(([k, v]) => ({
|
|
72
70
|
range: this.rangeKey,
|
|
73
71
|
key: k,
|
|
74
72
|
value: v,
|
|
75
73
|
}));
|
|
76
|
-
|
|
74
|
+
|
|
77
75
|
await sendRequired(
|
|
78
76
|
this.client,
|
|
79
|
-
|
|
77
|
+
"/range/kv/set",
|
|
80
78
|
{ range: this.rangeKey, pairs },
|
|
81
79
|
setReqZ,
|
|
82
80
|
z.unknown(),
|
|
@@ -86,7 +84,7 @@ export class KV {
|
|
|
86
84
|
async delete(key: string | string[]): Promise<void> {
|
|
87
85
|
await sendRequired(
|
|
88
86
|
this.client,
|
|
89
|
-
|
|
87
|
+
"/range/kv/delete",
|
|
90
88
|
{ range: this.rangeKey, keys: array.toArray(key) },
|
|
91
89
|
deleteReqZ,
|
|
92
90
|
z.unknown(),
|
|
@@ -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 { DataType, math, TimeSpan, TimeStamp, uuid } from "@synnaxlabs/x";
|
|
10
|
+
import { DataType, id, math, TimeSpan, TimeStamp, uuid } from "@synnaxlabs/x";
|
|
11
11
|
import { describe, expect, it } from "vitest";
|
|
12
12
|
|
|
13
13
|
import { NotFoundError } from "@/errors";
|
|
@@ -284,7 +284,7 @@ describe("Ranger", () => {
|
|
|
284
284
|
describe("set + resolve", () => {
|
|
285
285
|
it("should set and resolve an alias for the range", async () => {
|
|
286
286
|
const ch = await client.channels.create({
|
|
287
|
-
name:
|
|
287
|
+
name: id.create(),
|
|
288
288
|
dataType: DataType.FLOAT32,
|
|
289
289
|
virtual: true,
|
|
290
290
|
});
|
|
@@ -300,7 +300,7 @@ describe("Ranger", () => {
|
|
|
300
300
|
describe("deleteAlias", () => {
|
|
301
301
|
it("should remove an alias for the range", async () => {
|
|
302
302
|
const ch = await client.channels.create({
|
|
303
|
-
name:
|
|
303
|
+
name: id.create(),
|
|
304
304
|
dataType: DataType.FLOAT32,
|
|
305
305
|
virtual: true,
|
|
306
306
|
});
|
|
@@ -316,7 +316,7 @@ describe("Ranger", () => {
|
|
|
316
316
|
describe("list", () => {
|
|
317
317
|
it("should list the aliases for the range", async () => {
|
|
318
318
|
const ch = await client.channels.create({
|
|
319
|
-
name:
|
|
319
|
+
name: id.create(),
|
|
320
320
|
dataType: DataType.FLOAT32,
|
|
321
321
|
virtual: true,
|
|
322
322
|
});
|
package/src/ranger/writer.ts
CHANGED
|
@@ -26,10 +26,6 @@ const deleteResZ = z.object({});
|
|
|
26
26
|
const renameReqZ = z.object({ key: keyZ, name: nameZ });
|
|
27
27
|
const renameResZ = z.object({});
|
|
28
28
|
|
|
29
|
-
const CREATE_ENDPOINT = "/range/create";
|
|
30
|
-
const DELETE_ENDPOINT = "/range/delete";
|
|
31
|
-
const RENAME_ENDPOINT = "/range/rename";
|
|
32
|
-
|
|
33
29
|
export class Writer {
|
|
34
30
|
client: UnaryClient;
|
|
35
31
|
|
|
@@ -40,7 +36,7 @@ export class Writer {
|
|
|
40
36
|
async rename(key: string, name: string): Promise<void> {
|
|
41
37
|
await sendRequired<typeof renameReqZ, typeof renameResZ>(
|
|
42
38
|
this.client,
|
|
43
|
-
|
|
39
|
+
"/range/rename",
|
|
44
40
|
{ key, name },
|
|
45
41
|
renameReqZ,
|
|
46
42
|
renameResZ,
|
|
@@ -50,7 +46,7 @@ export class Writer {
|
|
|
50
46
|
async create(ranges: New[], options?: CreateOptions): Promise<Payload[]> {
|
|
51
47
|
const res = await sendRequired<typeof createReqZ, typeof createResZ>(
|
|
52
48
|
this.client,
|
|
53
|
-
|
|
49
|
+
"/range/create",
|
|
54
50
|
{ ranges, ...options },
|
|
55
51
|
createReqZ,
|
|
56
52
|
createResZ,
|
|
@@ -61,7 +57,7 @@ export class Writer {
|
|
|
61
57
|
async delete(keys: string[]): Promise<void> {
|
|
62
58
|
await sendRequired<typeof deleteReqZ, typeof deleteResZ>(
|
|
63
59
|
this.client,
|
|
64
|
-
|
|
60
|
+
"/range/delete",
|
|
65
61
|
{ keys },
|
|
66
62
|
deleteReqZ,
|
|
67
63
|
deleteResZ,
|
|
@@ -0,0 +1,129 @@
|
|
|
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 { TimeStamp, uuid } from "@synnaxlabs/x";
|
|
11
|
+
import { describe, expect, it } from "vitest";
|
|
12
|
+
|
|
13
|
+
import { AuthError, NotFoundError } from "@/errors";
|
|
14
|
+
import { status } from "@/status";
|
|
15
|
+
import { createTestClientWithPolicy } from "@/testutil/access";
|
|
16
|
+
import { createTestClient } from "@/testutil/client";
|
|
17
|
+
|
|
18
|
+
const client = createTestClient();
|
|
19
|
+
|
|
20
|
+
describe("status", () => {
|
|
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 randomStatus = await client.statuses.set({
|
|
29
|
+
name: "test",
|
|
30
|
+
key: uuid.create(),
|
|
31
|
+
variant: "info",
|
|
32
|
+
message: "test",
|
|
33
|
+
time: TimeStamp.now(),
|
|
34
|
+
});
|
|
35
|
+
await expect(
|
|
36
|
+
userClient.statuses.retrieve({ key: randomStatus.key }),
|
|
37
|
+
).rejects.toThrow(AuthError);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should allow the caller to retrieve statuses with the correct policy", async () => {
|
|
41
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
42
|
+
name: "test",
|
|
43
|
+
objects: [status.ontologyID("")],
|
|
44
|
+
actions: ["retrieve"],
|
|
45
|
+
});
|
|
46
|
+
const randomStatus = await client.statuses.set({
|
|
47
|
+
name: "test",
|
|
48
|
+
key: uuid.create(),
|
|
49
|
+
variant: "info",
|
|
50
|
+
message: "test",
|
|
51
|
+
time: TimeStamp.now(),
|
|
52
|
+
});
|
|
53
|
+
const retrieved = await userClient.statuses.retrieve({
|
|
54
|
+
key: randomStatus.key,
|
|
55
|
+
});
|
|
56
|
+
expect(retrieved.key).toBe(randomStatus.key);
|
|
57
|
+
expect(retrieved.name).toBe(randomStatus.name);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("should allow the caller to set statuses with the correct policy", async () => {
|
|
61
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
62
|
+
name: "test",
|
|
63
|
+
objects: [status.ontologyID("")],
|
|
64
|
+
actions: ["create"],
|
|
65
|
+
});
|
|
66
|
+
await userClient.statuses.set({
|
|
67
|
+
name: "test",
|
|
68
|
+
key: uuid.create(),
|
|
69
|
+
variant: "info",
|
|
70
|
+
message: "test",
|
|
71
|
+
time: TimeStamp.now(),
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("should deny access when no create policy exists", async () => {
|
|
76
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
77
|
+
name: "test",
|
|
78
|
+
objects: [status.ontologyID("")],
|
|
79
|
+
actions: [],
|
|
80
|
+
});
|
|
81
|
+
await expect(
|
|
82
|
+
userClient.statuses.set({
|
|
83
|
+
name: "test",
|
|
84
|
+
key: uuid.create(),
|
|
85
|
+
variant: "info",
|
|
86
|
+
message: "test",
|
|
87
|
+
time: TimeStamp.now(),
|
|
88
|
+
}),
|
|
89
|
+
).rejects.toThrow(AuthError);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should allow the caller to delete statuses with the correct policy", async () => {
|
|
93
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
94
|
+
name: "test",
|
|
95
|
+
objects: [status.ontologyID("")],
|
|
96
|
+
actions: ["delete", "retrieve"],
|
|
97
|
+
});
|
|
98
|
+
const randomStatus = await client.statuses.set({
|
|
99
|
+
name: "test",
|
|
100
|
+
key: uuid.create(),
|
|
101
|
+
variant: "info",
|
|
102
|
+
message: "test",
|
|
103
|
+
time: TimeStamp.now(),
|
|
104
|
+
});
|
|
105
|
+
await userClient.statuses.delete(randomStatus.key);
|
|
106
|
+
await expect(
|
|
107
|
+
userClient.statuses.retrieve({ key: randomStatus.key }),
|
|
108
|
+
).rejects.toThrow(NotFoundError);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("should deny access when no delete policy exists", async () => {
|
|
112
|
+
const userClient = await createTestClientWithPolicy(client, {
|
|
113
|
+
name: "test",
|
|
114
|
+
objects: [status.ontologyID("")],
|
|
115
|
+
actions: [],
|
|
116
|
+
});
|
|
117
|
+
const randomStatus = await client.statuses.set({
|
|
118
|
+
name: "test",
|
|
119
|
+
key: uuid.create(),
|
|
120
|
+
variant: "info",
|
|
121
|
+
message: "test",
|
|
122
|
+
time: TimeStamp.now(),
|
|
123
|
+
});
|
|
124
|
+
await expect(userClient.statuses.delete(randomStatus.key)).rejects.toThrow(
|
|
125
|
+
AuthError,
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|