cojson 0.13.30 → 0.14.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 +1 -1
- package/CHANGELOG.md +15 -2
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +1 -4
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +4 -1
- package/dist/coValues/group.js.map +1 -1
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +1 -1
- package/dist/localNode.js.map +1 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +0 -12
- package/dist/permissions.js.map +1 -1
- package/dist/tests/group.inheritance.test.d.ts +2 -0
- package/dist/tests/group.inheritance.test.d.ts.map +1 -0
- package/dist/tests/group.inheritance.test.js +235 -0
- package/dist/tests/group.inheritance.test.js.map +1 -0
- package/dist/tests/group.invite.test.d.ts +2 -0
- package/dist/tests/group.invite.test.d.ts.map +1 -0
- package/dist/tests/group.invite.test.js +214 -0
- package/dist/tests/group.invite.test.js.map +1 -0
- package/dist/tests/group.removeMember.test.js +22 -0
- package/dist/tests/group.removeMember.test.js.map +1 -1
- package/dist/tests/group.roleOf.test.d.ts +2 -0
- package/dist/tests/group.roleOf.test.d.ts.map +1 -0
- package/dist/tests/group.roleOf.test.js +275 -0
- package/dist/tests/group.roleOf.test.js.map +1 -0
- package/dist/tests/group.test.js +1 -505
- package/dist/tests/group.test.js.map +1 -1
- package/dist/tests/permissions.test.js +0 -33
- package/dist/tests/permissions.test.js.map +1 -1
- package/package.json +1 -1
- package/src/coValueCore/coValueCore.ts +1 -6
- package/src/coValues/group.ts +4 -1
- package/src/localNode.ts +2 -1
- package/src/permissions.ts +0 -18
- package/src/tests/group.inheritance.test.ts +418 -0
- package/src/tests/group.invite.test.ts +350 -0
- package/src/tests/group.removeMember.test.ts +48 -0
- package/src/tests/group.roleOf.test.ts +450 -0
- package/src/tests/group.test.ts +0 -852
- package/src/tests/permissions.test.ts +0 -52
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { RawAccountID } from "../exports";
|
|
3
|
+
import {
|
|
4
|
+
createThreeConnectedNodes,
|
|
5
|
+
createTwoConnectedNodes,
|
|
6
|
+
loadCoValueOrFail,
|
|
7
|
+
nodeWithRandomAgentAndSessionID,
|
|
8
|
+
randomAgentAndSessionID,
|
|
9
|
+
waitFor,
|
|
10
|
+
} from "./testUtils";
|
|
11
|
+
|
|
12
|
+
describe("roleOf", () => {
|
|
13
|
+
test("returns direct role assignments", () => {
|
|
14
|
+
const node = nodeWithRandomAgentAndSessionID();
|
|
15
|
+
const group = node.createGroup();
|
|
16
|
+
const [agent2] = randomAgentAndSessionID();
|
|
17
|
+
|
|
18
|
+
group.addMember(agent2, "writer");
|
|
19
|
+
expect(group.roleOfInternal(agent2.id)).toEqual("writer");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("returns undefined for non-members", () => {
|
|
23
|
+
const node = nodeWithRandomAgentAndSessionID();
|
|
24
|
+
const group = node.createGroup();
|
|
25
|
+
const [agent2] = randomAgentAndSessionID();
|
|
26
|
+
|
|
27
|
+
expect(group.roleOfInternal(agent2.id)).toEqual(undefined);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("revoked roles return undefined", () => {
|
|
31
|
+
const node = nodeWithRandomAgentAndSessionID();
|
|
32
|
+
const group = node.createGroup();
|
|
33
|
+
const [agent2] = randomAgentAndSessionID();
|
|
34
|
+
|
|
35
|
+
group.addMember(agent2, "writer");
|
|
36
|
+
group.removeMemberInternal(agent2);
|
|
37
|
+
expect(group.roleOfInternal(agent2.id)).toEqual(undefined);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("everyone role applies to all accounts", () => {
|
|
41
|
+
const node = nodeWithRandomAgentAndSessionID();
|
|
42
|
+
const group = node.createGroup();
|
|
43
|
+
const [agent2, sessionID2] = randomAgentAndSessionID();
|
|
44
|
+
|
|
45
|
+
group.addMemberInternal("everyone", "reader");
|
|
46
|
+
expect(group.roleOfInternal(agent2.id)).toEqual("reader");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("account role overrides everyone role", () => {
|
|
50
|
+
const node = nodeWithRandomAgentAndSessionID();
|
|
51
|
+
const group = node.createGroup();
|
|
52
|
+
const [agent2, sessionID2] = randomAgentAndSessionID();
|
|
53
|
+
|
|
54
|
+
group.addMemberInternal("everyone", "writer");
|
|
55
|
+
group.addMember(agent2, "reader");
|
|
56
|
+
expect(group.roleOfInternal(agent2.id)).toEqual("reader");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("Revoking access on everyone role should not affect existing members", () => {
|
|
60
|
+
const node = nodeWithRandomAgentAndSessionID();
|
|
61
|
+
const group = node.createGroup();
|
|
62
|
+
const [agent2, sessionID2] = randomAgentAndSessionID();
|
|
63
|
+
|
|
64
|
+
group.addMemberInternal("everyone", "reader");
|
|
65
|
+
group.addMember(agent2, "writer");
|
|
66
|
+
group.removeMemberInternal("everyone");
|
|
67
|
+
expect(group.roleOfInternal(agent2.id)).toEqual("writer");
|
|
68
|
+
expect(group.roleOfInternal("123" as RawAccountID)).toEqual(undefined);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("Everyone role is inherited following the most permissive algorithm", () => {
|
|
72
|
+
const node = nodeWithRandomAgentAndSessionID();
|
|
73
|
+
const group = node.createGroup();
|
|
74
|
+
const [agent2, sessionID2] = randomAgentAndSessionID();
|
|
75
|
+
|
|
76
|
+
const parentGroup = node.createGroup();
|
|
77
|
+
parentGroup.addMemberInternal("everyone", "writer");
|
|
78
|
+
|
|
79
|
+
group.extend(parentGroup);
|
|
80
|
+
group.addMember(agent2, "reader");
|
|
81
|
+
|
|
82
|
+
expect(group.roleOfInternal(agent2.id)).toEqual("writer");
|
|
83
|
+
});
|
|
84
|
+
test("roleOf should prioritize explicit account role over everyone role in same group", async () => {
|
|
85
|
+
const { node1, node2 } = await createTwoConnectedNodes("server", "server");
|
|
86
|
+
|
|
87
|
+
const group = node1.node.createGroup();
|
|
88
|
+
const account2 = await loadCoValueOrFail(node1.node, node2.accountID);
|
|
89
|
+
|
|
90
|
+
// Add both everyone and specific account
|
|
91
|
+
group.addMember("everyone", "reader");
|
|
92
|
+
group.addMember(account2, "writer");
|
|
93
|
+
|
|
94
|
+
// Should return the explicit role, not everyone's role
|
|
95
|
+
expect(group.roleOf(node2.accountID)).toEqual("writer");
|
|
96
|
+
|
|
97
|
+
// Change everyone's role
|
|
98
|
+
group.addMember("everyone", "writer");
|
|
99
|
+
|
|
100
|
+
// Should still return the explicit role
|
|
101
|
+
expect(group.roleOf(node2.accountID)).toEqual("writer");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("roleOf should prioritize inherited everyone role over explicit account role", async () => {
|
|
105
|
+
const { node1, node2 } = await createTwoConnectedNodes("server", "server");
|
|
106
|
+
|
|
107
|
+
const parentGroup = node1.node.createGroup();
|
|
108
|
+
const childGroup = node1.node.createGroup();
|
|
109
|
+
const account2 = await loadCoValueOrFail(node1.node, node2.accountID);
|
|
110
|
+
|
|
111
|
+
// Set up inheritance
|
|
112
|
+
childGroup.extend(parentGroup);
|
|
113
|
+
|
|
114
|
+
// Add everyone to parent and account to child
|
|
115
|
+
parentGroup.addMember("everyone", "writer");
|
|
116
|
+
childGroup.addMember(account2, "reader");
|
|
117
|
+
|
|
118
|
+
// Should return the explicit role from child, not inherited everyone role
|
|
119
|
+
expect(childGroup.roleOf(node2.accountID)).toEqual("writer");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("roleOf should use everyone role when no explicit role exists", async () => {
|
|
123
|
+
const { node1, node2 } = await createTwoConnectedNodes("server", "server");
|
|
124
|
+
|
|
125
|
+
const group = node1.node.createGroup();
|
|
126
|
+
|
|
127
|
+
// Add only everyone role
|
|
128
|
+
group.addMember("everyone", "reader");
|
|
129
|
+
|
|
130
|
+
// Should return everyone's role when no explicit role exists
|
|
131
|
+
expect(group.roleOf(node2.accountID)).toEqual("reader");
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("roleOf should inherit everyone role from parent when no explicit roles exist", async () => {
|
|
135
|
+
const { node1, node2 } = await createTwoConnectedNodes("server", "server");
|
|
136
|
+
|
|
137
|
+
const parentGroup = node1.node.createGroup();
|
|
138
|
+
const childGroup = node1.node.createGroup();
|
|
139
|
+
|
|
140
|
+
// Set up inheritance
|
|
141
|
+
childGroup.extend(parentGroup);
|
|
142
|
+
|
|
143
|
+
// Add everyone to parent only
|
|
144
|
+
parentGroup.addMember("everyone", "reader");
|
|
145
|
+
|
|
146
|
+
// Should inherit everyone's role from parent
|
|
147
|
+
expect(childGroup.roleOf(node2.accountID)).toEqual("reader");
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test("roleOf should handle everyone role inheritance through multiple levels", async () => {
|
|
151
|
+
const { node1, node2 } = await createTwoConnectedNodes("server", "server");
|
|
152
|
+
|
|
153
|
+
const grandParentGroup = node1.node.createGroup();
|
|
154
|
+
const parentGroup = node1.node.createGroup();
|
|
155
|
+
const childGroup = node1.node.createGroup();
|
|
156
|
+
|
|
157
|
+
const childGroupOnNode2 = await loadCoValueOrFail(
|
|
158
|
+
node2.node,
|
|
159
|
+
childGroup.id,
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const account2 = await loadCoValueOrFail(node1.node, node2.accountID);
|
|
163
|
+
|
|
164
|
+
// Set up inheritance chain
|
|
165
|
+
parentGroup.extend(grandParentGroup);
|
|
166
|
+
childGroup.extend(parentGroup);
|
|
167
|
+
|
|
168
|
+
// Add everyone to grandparent
|
|
169
|
+
grandParentGroup.addMember("everyone", "writer");
|
|
170
|
+
|
|
171
|
+
// Should inherit everyone's role from grandparent
|
|
172
|
+
expect(childGroup.roleOf(node2.accountID)).toEqual("writer");
|
|
173
|
+
|
|
174
|
+
// Add explicit role in parent
|
|
175
|
+
parentGroup.addMember(account2, "reader");
|
|
176
|
+
|
|
177
|
+
// Should use parent's explicit role instead of grandparent's everyone role
|
|
178
|
+
expect(childGroup.roleOf(node2.accountID)).toEqual("writer");
|
|
179
|
+
|
|
180
|
+
// Add explicit role in child
|
|
181
|
+
childGroup.addMember(account2, "admin");
|
|
182
|
+
await childGroup.core.waitForSync();
|
|
183
|
+
|
|
184
|
+
// Should use child's explicit role
|
|
185
|
+
expect(childGroup.roleOf(node2.accountID)).toEqual("admin");
|
|
186
|
+
|
|
187
|
+
// Remove child's explicit role
|
|
188
|
+
await childGroupOnNode2.removeMember(account2);
|
|
189
|
+
await childGroupOnNode2.core.waitForSync();
|
|
190
|
+
|
|
191
|
+
// Should fall back to parent's explicit role
|
|
192
|
+
expect(childGroup.roleOf(node2.accountID)).toEqual("writer");
|
|
193
|
+
|
|
194
|
+
// Remove parent's explicit role
|
|
195
|
+
await parentGroup.removeMember(account2);
|
|
196
|
+
await childGroup.core.waitForSync();
|
|
197
|
+
|
|
198
|
+
// Should fall back to grandparent's everyone role
|
|
199
|
+
expect(childGroup.roleOf(node2.accountID)).toEqual("writer");
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
describe("writeOnly can be used as a role for everyone", () => {
|
|
203
|
+
test("writeOnly can be used as a role for everyone", async () => {
|
|
204
|
+
const { node1, node2 } = await createTwoConnectedNodes(
|
|
205
|
+
"server",
|
|
206
|
+
"server",
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
const group = node1.node.createGroup();
|
|
210
|
+
|
|
211
|
+
group.addMember("everyone", "writeOnly");
|
|
212
|
+
|
|
213
|
+
const map = group.createMap();
|
|
214
|
+
|
|
215
|
+
const groupOnNode2 = await loadCoValueOrFail(node2.node, group.id);
|
|
216
|
+
|
|
217
|
+
expect(groupOnNode2.myRole()).toEqual("writeOnly");
|
|
218
|
+
|
|
219
|
+
const mapOnNode2 = await loadCoValueOrFail(node2.node, map.id);
|
|
220
|
+
|
|
221
|
+
mapOnNode2.set("test", "Written from everyone");
|
|
222
|
+
|
|
223
|
+
await waitFor(async () => {
|
|
224
|
+
const mapOnNode1 = await loadCoValueOrFail(node1.node, map.id);
|
|
225
|
+
expect(mapOnNode1.get("test")).toEqual("Written from everyone");
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test("switching from everyone reader to writeOnly", async () => {
|
|
230
|
+
const { node1, node2 } = await createTwoConnectedNodes(
|
|
231
|
+
"server",
|
|
232
|
+
"server",
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
const group = node1.node.createGroup();
|
|
236
|
+
|
|
237
|
+
group.addMember("everyone", "reader");
|
|
238
|
+
|
|
239
|
+
group.addMember("everyone", "writeOnly");
|
|
240
|
+
|
|
241
|
+
const map = group.createMap();
|
|
242
|
+
|
|
243
|
+
map.set("test", "Written from admin");
|
|
244
|
+
|
|
245
|
+
const groupOnNode2 = await loadCoValueOrFail(node2.node, group.id);
|
|
246
|
+
|
|
247
|
+
expect(groupOnNode2.myRole()).toEqual("writeOnly");
|
|
248
|
+
|
|
249
|
+
const mapOnNode2 = await loadCoValueOrFail(node2.node, map.id);
|
|
250
|
+
|
|
251
|
+
expect(mapOnNode2.get("test")).toEqual(undefined);
|
|
252
|
+
|
|
253
|
+
mapOnNode2.set("test", "Written from everyone");
|
|
254
|
+
|
|
255
|
+
await waitFor(async () => {
|
|
256
|
+
const mapOnNode1 = await loadCoValueOrFail(node1.node, map.id);
|
|
257
|
+
expect(mapOnNode1.get("test")).toEqual("Written from everyone");
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test("switching from everyone writer to writeOnly", async () => {
|
|
262
|
+
const { node1, node2 } = await createTwoConnectedNodes(
|
|
263
|
+
"server",
|
|
264
|
+
"server",
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
const group = node1.node.createGroup();
|
|
268
|
+
|
|
269
|
+
group.addMember("everyone", "writer");
|
|
270
|
+
|
|
271
|
+
group.addMember("everyone", "writeOnly");
|
|
272
|
+
|
|
273
|
+
const map = group.createMap();
|
|
274
|
+
|
|
275
|
+
map.set("test", "Written from admin");
|
|
276
|
+
|
|
277
|
+
const groupOnNode2 = await loadCoValueOrFail(node2.node, group.id);
|
|
278
|
+
|
|
279
|
+
expect(groupOnNode2.myRole()).toEqual("writeOnly");
|
|
280
|
+
|
|
281
|
+
const mapOnNode2 = await loadCoValueOrFail(node2.node, map.id);
|
|
282
|
+
|
|
283
|
+
expect(mapOnNode2.get("test")).toEqual(undefined);
|
|
284
|
+
|
|
285
|
+
mapOnNode2.set("test", "Written from everyone");
|
|
286
|
+
|
|
287
|
+
await waitFor(async () => {
|
|
288
|
+
const mapOnNode1 = await loadCoValueOrFail(node1.node, map.id);
|
|
289
|
+
expect(mapOnNode1.get("test")).toEqual("Written from everyone");
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
test("switching from everyone writeOnly to reader", async () => {
|
|
294
|
+
const { node1, node2 } = await createTwoConnectedNodes(
|
|
295
|
+
"server",
|
|
296
|
+
"server",
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
const group = node1.node.createGroup();
|
|
300
|
+
|
|
301
|
+
group.addMember("everyone", "writeOnly");
|
|
302
|
+
|
|
303
|
+
const map = group.createMap();
|
|
304
|
+
|
|
305
|
+
map.set("fromAdmin", "Written from admin");
|
|
306
|
+
|
|
307
|
+
const groupOnNode2 = await loadCoValueOrFail(node2.node, group.id);
|
|
308
|
+
|
|
309
|
+
expect(groupOnNode2.myRole()).toEqual("writeOnly");
|
|
310
|
+
|
|
311
|
+
const mapOnNode2 = await loadCoValueOrFail(node2.node, map.id);
|
|
312
|
+
|
|
313
|
+
expect(mapOnNode2.get("test")).toEqual(undefined);
|
|
314
|
+
|
|
315
|
+
mapOnNode2.set("test", "Written from everyone");
|
|
316
|
+
|
|
317
|
+
await waitFor(async () => {
|
|
318
|
+
const mapOnNode1 = await loadCoValueOrFail(node1.node, map.id);
|
|
319
|
+
expect(mapOnNode1.get("test")).toEqual("Written from everyone");
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
group.addMember("everyone", "reader");
|
|
323
|
+
|
|
324
|
+
await group.core.waitForSync();
|
|
325
|
+
|
|
326
|
+
mapOnNode2.set("test", "Updated after the downgrade");
|
|
327
|
+
|
|
328
|
+
expect(mapOnNode2.get("test")).toEqual("Written from everyone");
|
|
329
|
+
expect(mapOnNode2.get("fromAdmin")).toEqual("Written from admin");
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
test("switching from everyone writeOnly to writer", async () => {
|
|
333
|
+
const { node1, node2 } = await createTwoConnectedNodes(
|
|
334
|
+
"server",
|
|
335
|
+
"server",
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
const group = node1.node.createGroup();
|
|
339
|
+
|
|
340
|
+
group.addMember("everyone", "writeOnly");
|
|
341
|
+
|
|
342
|
+
const map = group.createMap();
|
|
343
|
+
|
|
344
|
+
map.set("fromAdmin", "Written from admin");
|
|
345
|
+
|
|
346
|
+
const groupOnNode2 = await loadCoValueOrFail(node2.node, group.id);
|
|
347
|
+
|
|
348
|
+
expect(groupOnNode2.myRole()).toEqual("writeOnly");
|
|
349
|
+
|
|
350
|
+
const mapOnNode2 = await loadCoValueOrFail(node2.node, map.id);
|
|
351
|
+
|
|
352
|
+
expect(mapOnNode2.get("test")).toEqual(undefined);
|
|
353
|
+
|
|
354
|
+
mapOnNode2.set("test", "Written from everyone");
|
|
355
|
+
|
|
356
|
+
await waitFor(async () => {
|
|
357
|
+
const mapOnNode1 = await loadCoValueOrFail(node1.node, map.id);
|
|
358
|
+
expect(mapOnNode1.get("test")).toEqual("Written from everyone");
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
group.addMember("everyone", "writer");
|
|
362
|
+
|
|
363
|
+
await group.core.waitForSync();
|
|
364
|
+
|
|
365
|
+
mapOnNode2.set("test", "Updated after the upgrade");
|
|
366
|
+
|
|
367
|
+
expect(mapOnNode2.get("test")).toEqual("Updated after the upgrade");
|
|
368
|
+
expect(mapOnNode2.get("fromAdmin")).toEqual("Written from admin");
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
test("adding a reader member after writeOnly", async () => {
|
|
372
|
+
const { node1, node2, node3 } = await createThreeConnectedNodes(
|
|
373
|
+
"server",
|
|
374
|
+
"server",
|
|
375
|
+
"server",
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
const group = node1.node.createGroup();
|
|
379
|
+
|
|
380
|
+
group.addMember("everyone", "writeOnly");
|
|
381
|
+
|
|
382
|
+
const map = group.createMap();
|
|
383
|
+
|
|
384
|
+
map.set("fromAdmin", "Written from admin");
|
|
385
|
+
|
|
386
|
+
const groupOnNode2 = await loadCoValueOrFail(node2.node, group.id);
|
|
387
|
+
|
|
388
|
+
expect(groupOnNode2.myRole()).toEqual("writeOnly");
|
|
389
|
+
|
|
390
|
+
const mapOnNode2 = await loadCoValueOrFail(node2.node, map.id);
|
|
391
|
+
|
|
392
|
+
expect(mapOnNode2.get("test")).toEqual(undefined);
|
|
393
|
+
|
|
394
|
+
mapOnNode2.set("test", "Written from everyone");
|
|
395
|
+
|
|
396
|
+
await waitFor(async () => {
|
|
397
|
+
const mapOnNode1 = await loadCoValueOrFail(node1.node, map.id);
|
|
398
|
+
expect(mapOnNode1.get("test")).toEqual("Written from everyone");
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
const account3 = await loadCoValueOrFail(node1.node, node3.accountID);
|
|
402
|
+
|
|
403
|
+
group.addMember(account3, "reader");
|
|
404
|
+
|
|
405
|
+
await group.core.waitForSync();
|
|
406
|
+
|
|
407
|
+
const mapOnNode3 = await loadCoValueOrFail(node3.node, map.id);
|
|
408
|
+
|
|
409
|
+
expect(mapOnNode3.get("test")).toEqual("Written from everyone");
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
test.skip("adding a reader member while creating the writeOnly keys", async () => {
|
|
413
|
+
const { node1, node2, node3 } = await createThreeConnectedNodes(
|
|
414
|
+
"server",
|
|
415
|
+
"server",
|
|
416
|
+
"server",
|
|
417
|
+
);
|
|
418
|
+
const account3 = await loadCoValueOrFail(node1.node, node3.accountID);
|
|
419
|
+
const group = node1.node.createGroup();
|
|
420
|
+
|
|
421
|
+
group.addMember("everyone", "writeOnly");
|
|
422
|
+
|
|
423
|
+
const map = group.createMap();
|
|
424
|
+
|
|
425
|
+
map.set("fromAdmin", "Written from admin");
|
|
426
|
+
|
|
427
|
+
const groupOnNode2 = await loadCoValueOrFail(node2.node, group.id);
|
|
428
|
+
|
|
429
|
+
expect(groupOnNode2.myRole()).toEqual("writeOnly");
|
|
430
|
+
|
|
431
|
+
const mapOnNode2 = await loadCoValueOrFail(node2.node, map.id);
|
|
432
|
+
group.addMember(account3, "reader");
|
|
433
|
+
|
|
434
|
+
expect(mapOnNode2.get("test")).toEqual(undefined);
|
|
435
|
+
|
|
436
|
+
mapOnNode2.set("test", "Written from everyone");
|
|
437
|
+
|
|
438
|
+
await waitFor(async () => {
|
|
439
|
+
const mapOnNode1 = await loadCoValueOrFail(node1.node, map.id);
|
|
440
|
+
expect(mapOnNode1.get("test")).toEqual("Written from everyone");
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
await group.core.waitForSync();
|
|
444
|
+
|
|
445
|
+
const mapOnNode3 = await loadCoValueOrFail(node3.node, map.id);
|
|
446
|
+
|
|
447
|
+
expect(mapOnNode3.get("test")).toEqual("Written from everyone");
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
});
|