cojson 0.18.28 → 0.18.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +16 -0
  3. package/dist/PeerState.d.ts +23 -14
  4. package/dist/PeerState.d.ts.map +1 -1
  5. package/dist/PeerState.js +74 -23
  6. package/dist/PeerState.js.map +1 -1
  7. package/dist/SyncStateManager.d.ts +3 -3
  8. package/dist/SyncStateManager.d.ts.map +1 -1
  9. package/dist/SyncStateManager.js +18 -44
  10. package/dist/SyncStateManager.js.map +1 -1
  11. package/dist/coValueContentMessage.d.ts.map +1 -1
  12. package/dist/coValueContentMessage.js +2 -1
  13. package/dist/coValueContentMessage.js.map +1 -1
  14. package/dist/coValueCore/PeerKnownState.d.ts +21 -0
  15. package/dist/coValueCore/PeerKnownState.d.ts.map +1 -0
  16. package/dist/coValueCore/PeerKnownState.js +52 -0
  17. package/dist/coValueCore/PeerKnownState.js.map +1 -0
  18. package/dist/coValueCore/coValueCore.d.ts +39 -8
  19. package/dist/coValueCore/coValueCore.d.ts.map +1 -1
  20. package/dist/coValueCore/coValueCore.js +139 -40
  21. package/dist/coValueCore/coValueCore.js.map +1 -1
  22. package/dist/coValueCore/decryptTransactionChangesAndMeta.d.ts.map +1 -1
  23. package/dist/coValueCore/decryptTransactionChangesAndMeta.js +0 -5
  24. package/dist/coValueCore/decryptTransactionChangesAndMeta.js.map +1 -1
  25. package/dist/coValueCore/verifiedState.d.ts +0 -14
  26. package/dist/coValueCore/verifiedState.d.ts.map +1 -1
  27. package/dist/coValueCore/verifiedState.js +2 -32
  28. package/dist/coValueCore/verifiedState.js.map +1 -1
  29. package/dist/coValues/coList.d.ts +3 -4
  30. package/dist/coValues/coList.d.ts.map +1 -1
  31. package/dist/coValues/coList.js +4 -4
  32. package/dist/coValues/coList.js.map +1 -1
  33. package/dist/coValues/coMap.d.ts +3 -4
  34. package/dist/coValues/coMap.d.ts.map +1 -1
  35. package/dist/coValues/coMap.js +5 -4
  36. package/dist/coValues/coMap.js.map +1 -1
  37. package/dist/coValues/coStream.d.ts +3 -3
  38. package/dist/coValues/coStream.d.ts.map +1 -1
  39. package/dist/coValues/coStream.js +3 -4
  40. package/dist/coValues/coStream.js.map +1 -1
  41. package/dist/coValues/group.d.ts +3 -3
  42. package/dist/coValues/group.d.ts.map +1 -1
  43. package/dist/coValues/group.js +74 -52
  44. package/dist/coValues/group.js.map +1 -1
  45. package/dist/exports.d.ts +2 -2
  46. package/dist/exports.d.ts.map +1 -1
  47. package/dist/exports.js +2 -2
  48. package/dist/exports.js.map +1 -1
  49. package/dist/localNode.d.ts.map +1 -1
  50. package/dist/localNode.js +7 -5
  51. package/dist/localNode.js.map +1 -1
  52. package/dist/permissions.d.ts +5 -1
  53. package/dist/permissions.d.ts.map +1 -1
  54. package/dist/permissions.js +173 -109
  55. package/dist/permissions.js.map +1 -1
  56. package/dist/sync.d.ts.map +1 -1
  57. package/dist/sync.js +33 -44
  58. package/dist/sync.js.map +1 -1
  59. package/dist/tests/PeerKnownState.test.d.ts +2 -0
  60. package/dist/tests/PeerKnownState.test.d.ts.map +1 -0
  61. package/dist/tests/PeerKnownState.test.js +342 -0
  62. package/dist/tests/PeerKnownState.test.js.map +1 -0
  63. package/dist/tests/PeerState.test.js +17 -16
  64. package/dist/tests/PeerState.test.js.map +1 -1
  65. package/dist/tests/StorageApiAsync.test.js +12 -12
  66. package/dist/tests/StorageApiAsync.test.js.map +1 -1
  67. package/dist/tests/StorageApiSync.test.js +11 -11
  68. package/dist/tests/StorageApiSync.test.js.map +1 -1
  69. package/dist/tests/SyncStateManager.test.js +16 -21
  70. package/dist/tests/SyncStateManager.test.js.map +1 -1
  71. package/dist/tests/coValueCore.dependencies.test.js +59 -0
  72. package/dist/tests/coValueCore.dependencies.test.js.map +1 -1
  73. package/dist/tests/coValueCore.test.js +41 -21
  74. package/dist/tests/coValueCore.test.js.map +1 -1
  75. package/dist/tests/group.addMember.test.js +266 -219
  76. package/dist/tests/group.addMember.test.js.map +1 -1
  77. package/dist/tests/group.inheritance.test.js +12 -0
  78. package/dist/tests/group.inheritance.test.js.map +1 -1
  79. package/dist/tests/group.invite.test.js +77 -0
  80. package/dist/tests/group.invite.test.js.map +1 -1
  81. package/dist/tests/group.removeMember.test.js +64 -7
  82. package/dist/tests/group.removeMember.test.js.map +1 -1
  83. package/dist/tests/group.roleOf.test.js +14 -4
  84. package/dist/tests/group.roleOf.test.js.map +1 -1
  85. package/dist/tests/permissions.test.js +51 -202
  86. package/dist/tests/permissions.test.js.map +1 -1
  87. package/dist/tests/sync.content.test.js +2 -2
  88. package/dist/tests/sync.content.test.js.map +1 -1
  89. package/dist/tests/sync.invite.test.js +6 -6
  90. package/dist/tests/sync.load.test.js +22 -22
  91. package/dist/tests/sync.mesh.test.js +9 -9
  92. package/dist/tests/sync.storage.test.js +13 -7
  93. package/dist/tests/sync.storage.test.js.map +1 -1
  94. package/dist/tests/sync.storageAsync.test.js +3 -3
  95. package/dist/tests/sync.test.js +13 -33
  96. package/dist/tests/sync.test.js.map +1 -1
  97. package/dist/tests/sync.upload.test.js +2 -2
  98. package/package.json +3 -3
  99. package/src/PeerState.ts +86 -34
  100. package/src/SyncStateManager.ts +25 -60
  101. package/src/coValueContentMessage.ts +3 -1
  102. package/src/coValueCore/PeerKnownState.ts +74 -0
  103. package/src/coValueCore/coValueCore.ts +180 -49
  104. package/src/coValueCore/decryptTransactionChangesAndMeta.ts +0 -6
  105. package/src/coValueCore/verifiedState.ts +2 -37
  106. package/src/coValues/coList.ts +7 -7
  107. package/src/coValues/coMap.ts +9 -7
  108. package/src/coValues/coStream.ts +6 -5
  109. package/src/coValues/group.ts +99 -60
  110. package/src/exports.ts +2 -1
  111. package/src/localNode.ts +7 -5
  112. package/src/permissions.ts +204 -123
  113. package/src/sync.ts +37 -53
  114. package/src/tests/PeerKnownState.test.ts +426 -0
  115. package/src/tests/PeerState.test.ts +24 -24
  116. package/src/tests/StorageApiAsync.test.ts +12 -12
  117. package/src/tests/StorageApiSync.test.ts +11 -11
  118. package/src/tests/SyncStateManager.test.ts +23 -53
  119. package/src/tests/coValueCore.dependencies.test.ts +87 -0
  120. package/src/tests/coValueCore.test.ts +64 -22
  121. package/src/tests/group.addMember.test.ts +384 -345
  122. package/src/tests/group.inheritance.test.ts +33 -0
  123. package/src/tests/group.invite.test.ts +117 -0
  124. package/src/tests/group.removeMember.test.ts +95 -9
  125. package/src/tests/group.roleOf.test.ts +16 -4
  126. package/src/tests/permissions.test.ts +56 -295
  127. package/src/tests/sync.content.test.ts +2 -2
  128. package/src/tests/sync.invite.test.ts +6 -6
  129. package/src/tests/sync.load.test.ts +22 -22
  130. package/src/tests/sync.mesh.test.ts +9 -9
  131. package/src/tests/sync.storage.test.ts +13 -8
  132. package/src/tests/sync.storageAsync.test.ts +3 -3
  133. package/src/tests/sync.test.ts +21 -50
  134. package/src/tests/sync.upload.test.ts +2 -2
  135. package/dist/PeerKnownStates.d.ts +0 -19
  136. package/dist/PeerKnownStates.d.ts.map +0 -1
  137. package/dist/PeerKnownStates.js +0 -64
  138. package/dist/PeerKnownStates.js.map +0 -1
  139. package/dist/tests/PeerKnownStates.test.d.ts +0 -2
  140. package/dist/tests/PeerKnownStates.test.d.ts.map +0 -1
  141. package/dist/tests/PeerKnownStates.test.js +0 -77
  142. package/dist/tests/PeerKnownStates.test.js.map +0 -1
  143. package/src/PeerKnownStates.ts +0 -93
  144. package/src/tests/PeerKnownStates.test.ts +0 -99
@@ -1,326 +1,452 @@
1
1
  import { beforeEach, describe, expect, test } from "vitest";
2
- import { expectMap } from "../coValue.js";
3
2
  import {
4
3
  SyncMessagesLog,
5
4
  loadCoValueOrFail,
6
5
  setupTestAccount,
7
6
  setupTestNode,
8
- waitFor,
9
7
  } from "./testUtils.js";
8
+ import { Role } from "../permissions.js";
10
9
 
11
10
  beforeEach(async () => {
12
11
  SyncMessagesLog.clear();
13
12
  setupTestNode({ isSyncServer: true });
14
13
  });
15
14
 
16
- describe("Group.addMember", () => {
17
- test("an admin should be able to grant read access", async () => {
18
- const admin = await setupTestAccount({
19
- connected: true,
20
- });
21
-
22
- const reader = await setupTestAccount({
23
- connected: true,
24
- });
25
-
26
- const group = admin.node.createGroup();
27
- const person = group.createMap({
28
- name: "John Doe",
29
- });
30
-
31
- const personOnReaderNode = await loadCoValueOrFail(reader.node, person.id);
32
-
33
- expect(personOnReaderNode.get("name")).toEqual(undefined);
34
-
35
- const readerOnAdminNode = await loadCoValueOrFail(
36
- admin.node,
37
- reader.accountID,
38
- );
39
- group.addMember(readerOnAdminNode, "reader");
40
-
41
- expect(group.roleOf(reader.accountID)).toEqual("reader");
42
-
43
- await waitFor(() => {
44
- expect(
45
- expectMap(personOnReaderNode.core.getCurrentContent()).get("name"),
46
- ).toEqual("John Doe");
47
- });
48
- });
49
-
50
- test("an admin should be able to grant write access", async () => {
51
- const admin = await setupTestAccount({
52
- connected: true,
53
- });
54
-
55
- const writer = await setupTestAccount({
56
- connected: true,
57
- });
58
-
59
- const group = admin.node.createGroup();
60
- const person = group.createMap({
61
- name: "John Doe",
62
- });
63
-
64
- const personOnWriterNode = await loadCoValueOrFail(writer.node, person.id);
65
-
66
- expect(personOnWriterNode.get("name")).toEqual(undefined);
67
-
68
- const writerOnAdminNode = await loadCoValueOrFail(
69
- admin.node,
70
- writer.accountID,
71
- );
72
- group.addMember(writerOnAdminNode, "writer");
73
- expect(group.roleOf(writer.accountID)).toEqual("writer");
74
-
75
- await waitFor(() => {
76
- expect(
77
- expectMap(personOnWriterNode.core.getCurrentContent()).get("name"),
78
- ).toEqual("John Doe");
79
- });
80
-
81
- personOnWriterNode.set("name", "Jane Doe");
82
- expect(personOnWriterNode.get("name")).toEqual("Jane Doe");
83
- });
84
-
85
- test("an admin should be able to grant writeOnly access", async () => {
86
- const admin = await setupTestAccount({
87
- connected: true,
88
- });
15
+ // [sourceRole, from, to, canGrant]
16
+ const GRANT_MATRIX: [Role, Role | undefined, Role, boolean][] = [
17
+ // Admin can grant any role to anyone
18
+ ["admin", undefined, "admin", true],
19
+ ["admin", undefined, "manager", true],
20
+ ["admin", undefined, "writer", true],
21
+ ["admin", undefined, "reader", true],
22
+ ["admin", undefined, "writeOnly", true],
23
+
24
+ ["admin", "manager", "admin", true],
25
+ ["admin", "manager", "manager", true],
26
+ ["admin", "manager", "writer", true],
27
+ ["admin", "manager", "reader", true],
28
+ ["admin", "manager", "writeOnly", true],
29
+
30
+ ["admin", "admin", "admin", true],
31
+ ["admin", "admin", "manager", false],
32
+ ["admin", "admin", "writer", false],
33
+ ["admin", "admin", "reader", false],
34
+ ["admin", "admin", "writeOnly", false],
35
+
36
+ ["admin", "writer", "admin", true],
37
+ ["admin", "writer", "manager", true],
38
+ ["admin", "writer", "writer", true],
39
+ ["admin", "writer", "reader", true],
40
+ ["admin", "writer", "writeOnly", true],
41
+
42
+ ["admin", "reader", "admin", true],
43
+ ["admin", "reader", "manager", true],
44
+ ["admin", "reader", "writer", true],
45
+ ["admin", "reader", "reader", true],
46
+ ["admin", "reader", "writeOnly", true],
47
+
48
+ ["admin", "writeOnly", "admin", true],
49
+ ["admin", "writeOnly", "manager", true],
50
+ ["admin", "writeOnly", "writer", true],
51
+ ["admin", "writeOnly", "reader", true],
52
+ ["admin", "writeOnly", "writeOnly", true],
53
+
54
+ // Manager can grant any role except admin
55
+ // Manager can downgrade any role except admin
56
+ ["manager", undefined, "admin", false],
57
+ ["manager", undefined, "manager", true],
58
+ ["manager", undefined, "writer", true],
59
+ ["manager", undefined, "reader", true],
60
+ ["manager", undefined, "writeOnly", true],
61
+
62
+ ["manager", "manager", "admin", false],
63
+ ["manager", "manager", "manager", true],
64
+ ["manager", "manager", "writer", true],
65
+ ["manager", "manager", "reader", true],
66
+ ["manager", "manager", "writeOnly", true],
67
+
68
+ ["manager", "admin", "admin", true],
69
+ ["manager", "admin", "manager", false],
70
+ ["manager", "admin", "writer", false],
71
+ ["manager", "admin", "reader", false],
72
+ ["manager", "admin", "writeOnly", false],
73
+
74
+ ["manager", "writer", "admin", false],
75
+ ["manager", "writer", "manager", true],
76
+ ["manager", "writer", "writer", true],
77
+ ["manager", "writer", "reader", true],
78
+ ["manager", "writer", "writeOnly", true],
79
+
80
+ ["manager", "reader", "admin", false],
81
+ ["manager", "reader", "manager", true],
82
+ ["manager", "reader", "writer", true],
83
+ ["manager", "reader", "reader", true],
84
+ ["manager", "reader", "writeOnly", true],
85
+
86
+ ["manager", "writeOnly", "admin", false],
87
+ ["manager", "writeOnly", "manager", true],
88
+ ["manager", "writeOnly", "writer", true],
89
+ ["manager", "writeOnly", "reader", true],
90
+ ["manager", "writeOnly", "writeOnly", true],
91
+
92
+ // Writer cannot grant any roles to anyone
93
+ ["writer", undefined, "admin", false],
94
+ ["writer", undefined, "manager", false],
95
+ ["writer", undefined, "writer", false],
96
+ ["writer", undefined, "reader", false],
97
+ ["writer", undefined, "writeOnly", false],
98
+
99
+ ["writer", "manager", "admin", false],
100
+ ["writer", "manager", "manager", false],
101
+ ["writer", "manager", "writer", false],
102
+ ["writer", "manager", "reader", false],
103
+ ["writer", "manager", "writeOnly", false],
104
+
105
+ ["writer", "admin", "admin", false],
106
+ ["writer", "admin", "manager", false],
107
+ ["writer", "admin", "writer", false],
108
+ ["writer", "admin", "reader", false],
109
+ ["writer", "admin", "writeOnly", false],
110
+
111
+ ["writer", "writer", "admin", false],
112
+ ["writer", "writer", "manager", false],
113
+ ["writer", "writer", "writer", false],
114
+ ["writer", "writer", "reader", false],
115
+ ["writer", "writer", "writeOnly", false],
116
+
117
+ ["writer", "reader", "admin", false],
118
+ ["writer", "reader", "manager", false],
119
+ ["writer", "reader", "writer", false],
120
+ ["writer", "reader", "reader", false],
121
+ ["writer", "reader", "writeOnly", false],
122
+
123
+ ["writer", "writeOnly", "manager", false],
124
+ ["writer", "writeOnly", "admin", false],
125
+ ["writer", "writeOnly", "writer", false],
126
+ ["writer", "writeOnly", "reader", false],
127
+ ["writer", "writeOnly", "writeOnly", false],
128
+
129
+ // Reader cannot grant any roles to anyone
130
+ ["reader", undefined, "admin", false],
131
+ ["reader", undefined, "manager", false],
132
+ ["reader", undefined, "writer", false],
133
+ ["reader", undefined, "reader", false],
134
+ ["reader", undefined, "writeOnly", false],
135
+
136
+ ["reader", "manager", "admin", false],
137
+ ["reader", "manager", "manager", false],
138
+ ["reader", "manager", "writer", false],
139
+ ["reader", "manager", "reader", false],
140
+ ["reader", "manager", "writeOnly", false],
141
+
142
+ ["reader", "admin", "admin", false],
143
+ ["reader", "admin", "manager", false],
144
+ ["reader", "admin", "writer", false],
145
+ ["reader", "admin", "reader", false],
146
+ ["reader", "admin", "writeOnly", false],
147
+
148
+ ["reader", "writer", "admin", false],
149
+ ["reader", "writer", "manager", false],
150
+ ["reader", "writer", "writer", false],
151
+ ["reader", "writer", "reader", false],
152
+ ["reader", "writer", "writeOnly", false],
153
+
154
+ ["reader", "reader", "admin", false],
155
+ ["reader", "reader", "manager", false],
156
+ ["reader", "reader", "writer", false],
157
+ ["reader", "reader", "reader", false],
158
+ ["reader", "reader", "writeOnly", false],
159
+
160
+ ["reader", "writeOnly", "admin", false],
161
+ ["reader", "writeOnly", "manager", false],
162
+ ["reader", "writeOnly", "writer", false],
163
+ ["reader", "writeOnly", "reader", false],
164
+ ["reader", "writeOnly", "writeOnly", false],
165
+
166
+ // WriteOnly cannot grant any roles to anyone, so spell all writeOnly combinations out:
167
+ ["writeOnly", undefined, "admin", false],
168
+ ["writeOnly", undefined, "manager", false],
169
+ ["writeOnly", undefined, "writer", false],
170
+ ["writeOnly", undefined, "reader", false],
171
+ ["writeOnly", undefined, "writeOnly", false],
172
+
173
+ ["writeOnly", "manager", "admin", false],
174
+ ["writeOnly", "manager", "manager", false],
175
+ ["writeOnly", "manager", "writer", false],
176
+ ["writeOnly", "manager", "reader", false],
177
+ ["writeOnly", "manager", "writeOnly", false],
178
+
179
+ ["writeOnly", "admin", "admin", false],
180
+ ["writeOnly", "admin", "manager", false],
181
+ ["writeOnly", "admin", "writer", false],
182
+ ["writeOnly", "admin", "reader", false],
183
+ ["writeOnly", "admin", "writeOnly", false],
184
+
185
+ ["writeOnly", "writer", "admin", false],
186
+ ["writeOnly", "writer", "manager", false],
187
+ ["writeOnly", "writer", "writer", false],
188
+ ["writeOnly", "writer", "reader", false],
189
+ ["writeOnly", "writer", "writeOnly", false],
190
+
191
+ ["writeOnly", "reader", "admin", false],
192
+ ["writeOnly", "reader", "manager", false],
193
+ ["writeOnly", "reader", "writer", false],
194
+ ["writeOnly", "reader", "reader", false],
195
+ ["writeOnly", "reader", "writeOnly", false],
196
+
197
+ ["writeOnly", "writeOnly", "admin", false],
198
+ ["writeOnly", "writeOnly", "manager", false],
199
+ ["writeOnly", "writeOnly", "writer", false],
200
+ ["writeOnly", "writeOnly", "reader", false],
201
+ ["writeOnly", "writeOnly", "writeOnly", false],
202
+ ];
89
203
 
90
- const writeOnlyUser = await setupTestAccount({
91
- connected: true,
92
- });
204
+ describe("Group.addMember", () => {
205
+ for (const [sourceRole, from, to, canGrant] of GRANT_MATRIX) {
206
+ test(`${sourceRole} should ${canGrant ? "be able" : "not be able"} to grant ${from !== undefined ? `${from} -> ` : ""}${to} role`, async () => {
207
+ const source = await setupTestAccount({
208
+ connected: true,
209
+ });
93
210
 
94
- const group = admin.node.createGroup();
95
- const person = group.createMap({
96
- name: "John Doe",
97
- });
211
+ const member = await setupTestAccount({
212
+ connected: true,
213
+ });
98
214
 
99
- const writeOnlyUserOnAdminNode = await loadCoValueOrFail(
100
- admin.node,
101
- writeOnlyUser.accountID,
102
- );
103
- group.addMember(writeOnlyUserOnAdminNode, "writeOnly");
104
- expect(group.roleOf(writeOnlyUser.accountID)).toEqual("writeOnly");
105
- const personOnWriteOnlyNode = await loadCoValueOrFail(
106
- writeOnlyUser.node,
107
- person.id,
108
- );
215
+ const memberOnSourceNode = await loadCoValueOrFail(
216
+ source.node,
217
+ member.accountID,
218
+ );
109
219
 
110
- // Should not be able to read
111
- expect(personOnWriteOnlyNode.get("name")).toEqual(undefined);
220
+ const group = source.node.createGroup();
112
221
 
113
- // Should be able to write
114
- personOnWriteOnlyNode.set("name", "Jane Doe");
222
+ // setup initial role for member
223
+ if (from !== undefined) {
224
+ group.addMember(memberOnSourceNode, from);
225
+ }
115
226
 
116
- expect(personOnWriteOnlyNode.get("name")).toEqual("Jane Doe");
117
- });
227
+ group.addMember(
228
+ await loadCoValueOrFail(source.node, source.accountID),
229
+ sourceRole as Role,
230
+ );
118
231
 
119
- test("an admin should be able to grant admin access", async () => {
120
- const admin = await setupTestAccount({
121
- connected: true,
122
- });
232
+ expect(group.roleOf(source.accountID)).toEqual(sourceRole);
123
233
 
124
- const otherAdmin = await setupTestAccount({
125
- connected: true,
126
- });
234
+ if (canGrant || from === to) {
235
+ group.addMember(memberOnSourceNode, to);
127
236
 
128
- const reader = await setupTestAccount({
129
- connected: true,
130
- });
237
+ expect(group.roleOf(member.accountID)).toEqual(to);
238
+ } else {
239
+ expect(() => {
240
+ group.addMember(memberOnSourceNode, to);
241
+ }).toThrow(
242
+ `Failed to set role ${to} to ${member.accountID} (role of current account is ${sourceRole})`,
243
+ );
131
244
 
132
- const group = admin.node.createGroup();
133
- const person = group.createMap({
134
- name: "John Doe",
245
+ expect(group.roleOf(member.accountID)).toEqual(from);
246
+ }
135
247
  });
248
+ }
136
249
 
137
- const otherAdminOnAdminNode = await loadCoValueOrFail(
138
- admin.node,
139
- otherAdmin.accountID,
140
- );
141
- group.addMember(otherAdminOnAdminNode, "admin");
142
-
143
- const personOnReaderNode = await loadCoValueOrFail(reader.node, person.id);
144
-
145
- expect(personOnReaderNode.get("name")).toEqual(undefined);
146
-
147
- const readerOnOtherAdminNode = await loadCoValueOrFail(
148
- otherAdmin.node,
149
- reader.accountID,
150
- );
151
- group.addMember(readerOnOtherAdminNode, "reader");
250
+ test.each(["admin", "manager", "writer", "reader", "writeOnly"] as Role[])(
251
+ "admin should be able to self downgrade to %s role",
252
+ async (role) => {
253
+ const source = await setupTestAccount({
254
+ connected: true,
255
+ });
256
+ const memberOnSourceNode = await loadCoValueOrFail(
257
+ source.node,
258
+ source.accountID,
259
+ );
152
260
 
153
- await waitFor(() => {
154
- expect(
155
- expectMap(personOnReaderNode.core.getCurrentContent()).get("name"),
156
- ).toEqual("John Doe");
157
- });
158
- });
261
+ const group = source.node.createGroup();
159
262
 
160
- test("an admin should be able downgrade a writer to reader", async () => {
161
- const admin = await setupTestAccount({
162
- connected: true,
163
- });
263
+ group.addMember(memberOnSourceNode, role);
164
264
 
165
- const writer = await setupTestAccount({
166
- connected: true,
167
- });
265
+ expect(group.roleOf(source.accountID)).toEqual(role);
266
+ },
267
+ );
168
268
 
169
- const group = admin.node.createGroup();
170
- const person = group.createMap({
171
- name: "John Doe",
172
- });
269
+ test.each(["admin", "manager", "reader", "writeOnly"] as Role[])(
270
+ "writer should not be able to self upgrade to %s role",
271
+ async (role) => {
272
+ const source = await setupTestAccount({
273
+ connected: true,
274
+ });
275
+ const memberOnSourceNode = await loadCoValueOrFail(
276
+ source.node,
277
+ source.accountID,
278
+ );
173
279
 
174
- const writerOnAdminNode = await loadCoValueOrFail(
175
- admin.node,
176
- writer.accountID,
177
- );
178
- group.addMember(writerOnAdminNode, "writer");
179
- group.addMember(writerOnAdminNode, "reader");
280
+ const group = source.node.createGroup();
180
281
 
181
- expect(group.roleOf(writer.accountID)).toEqual("reader");
282
+ group.addMember(memberOnSourceNode, "writer");
182
283
 
183
- // Verify writer can read and write
184
- const personOnWriterNode = await loadCoValueOrFail(writer.node, person.id);
284
+ expect(group.roleOf(source.accountID)).toEqual("writer");
185
285
 
186
- // Should not be able to write
187
- personOnWriterNode.set("name", "Jane Doe");
286
+ expect(() => {
287
+ group.addMember(memberOnSourceNode, role);
288
+ }).toThrow(
289
+ `Failed to set role ${role} to ${source.accountID} (role of current account is writer)`,
290
+ );
291
+ },
292
+ );
188
293
 
189
- expect(personOnWriterNode.get("name")).toEqual("John Doe");
190
- });
294
+ test.each(["admin", "manager", "writer", "writeOnly"] as Role[])(
295
+ "reader should not be able to self upgrade to %s role",
296
+ async (role) => {
297
+ const source = await setupTestAccount({
298
+ connected: true,
299
+ });
300
+ const memberOnSourceNode = await loadCoValueOrFail(
301
+ source.node,
302
+ source.accountID,
303
+ );
191
304
 
192
- test("an admin should be able downgrade a reader to writeOnly", async () => {
193
- const admin = await setupTestAccount({
194
- connected: true,
195
- });
305
+ const group = source.node.createGroup();
196
306
 
197
- const reader = await setupTestAccount({
198
- connected: true,
199
- });
307
+ group.addMember(memberOnSourceNode, "reader");
200
308
 
201
- const group = admin.node.createGroup();
309
+ expect(group.roleOf(source.accountID)).toEqual("reader");
202
310
 
203
- const readerOnAdminNode = await loadCoValueOrFail(
204
- admin.node,
205
- reader.accountID,
206
- );
207
- group.addMember(readerOnAdminNode, "reader");
208
- group.addMember(readerOnAdminNode, "writeOnly");
311
+ expect(() => {
312
+ group.addMember(memberOnSourceNode, role);
313
+ }).toThrow(
314
+ `Failed to set role ${role} to ${source.accountID} (role of current account is reader)`,
315
+ );
316
+ },
317
+ );
209
318
 
210
- expect(group.roleOf(reader.accountID)).toEqual("writeOnly");
319
+ test.each(["admin", "superAdmin", "writer", "reader"] as Role[])(
320
+ "writeOnly should not be able to self upgrade to %s role",
321
+ async (role) => {
322
+ const source = await setupTestAccount({
323
+ connected: true,
324
+ });
325
+ const memberOnSourceNode = await loadCoValueOrFail(
326
+ source.node,
327
+ source.accountID,
328
+ );
211
329
 
212
- const person = group.createMap({
213
- name: "John Doe",
214
- });
330
+ const group = source.node.createGroup();
215
331
 
216
- // Verify reader can read
217
- const personOnReaderNode = await loadCoValueOrFail(reader.node, person.id);
332
+ group.addMember(memberOnSourceNode, "writeOnly");
218
333
 
219
- expect(personOnReaderNode.get("name")).toEqual(undefined);
220
- });
334
+ expect(group.roleOf(source.accountID)).toEqual("writeOnly");
221
335
 
222
- test.each(["writer", "reader", "writeOnly"] as const)(
223
- "an admin should not be able to downgrade an admin to %s",
224
- async (targetRole) => {
225
- const admin = await setupTestAccount({
226
- connected: true,
227
- });
336
+ expect(() => {
337
+ group.addMember(memberOnSourceNode, role);
338
+ }).toThrow(
339
+ `Failed to set role ${role} to ${source.accountID} (role of current account is writeOnly)`,
340
+ );
341
+ },
342
+ );
228
343
 
229
- const otherAdmin = await setupTestAccount({
344
+ test.each(["admin"] as Role[])(
345
+ "%s should be able to set writer role to EVERYONE",
346
+ async (role) => {
347
+ const source = await setupTestAccount({
230
348
  connected: true,
231
349
  });
232
-
233
- const group = admin.node.createGroup();
234
- const person = group.createMap({
235
- name: "John Doe",
236
- });
237
-
238
- const otherAdminOnAdminNode = await loadCoValueOrFail(
239
- admin.node,
240
- otherAdmin.accountID,
350
+ const memberOnSourceNode = await loadCoValueOrFail(
351
+ source.node,
352
+ source.accountID,
241
353
  );
242
- group.addMember(otherAdminOnAdminNode, "admin");
243
354
 
244
- // Try to downgrade other admin
245
- expect(() => group.addMember(otherAdminOnAdminNode, targetRole)).toThrow(
246
- "Administrators cannot demote other administrators in a group",
247
- );
355
+ const group = source.node.createGroup();
356
+
357
+ group.addMember(memberOnSourceNode, role);
358
+ expect(group.roleOf(source.accountID)).toEqual(role);
248
359
 
249
- expect(group.roleOf(otherAdmin.accountID)).toEqual("admin");
360
+ group.addMember("everyone", "writer");
361
+ expect(group.roleOf("everyone")).toEqual("writer");
362
+ },
363
+ );
250
364
 
251
- // Verify other admin still has admin access by adding a new member
252
- const reader = await setupTestAccount({
365
+ test.each(["admin"] as Role[])(
366
+ "%s should be able to set writeOnly role to EVERYONE",
367
+ async (role) => {
368
+ const source = await setupTestAccount({
253
369
  connected: true,
254
370
  });
255
-
256
- const readerOnOtherAdminNode = await loadCoValueOrFail(
257
- otherAdmin.node,
258
- reader.accountID,
371
+ const memberOnSourceNode = await loadCoValueOrFail(
372
+ source.node,
373
+ source.accountID,
259
374
  );
260
- group.addMember(readerOnOtherAdminNode, "reader");
261
375
 
262
- const personOnReaderNode = await loadCoValueOrFail(
263
- reader.node,
264
- person.id,
265
- );
376
+ const group = source.node.createGroup();
266
377
 
267
- await waitFor(() => {
268
- expect(
269
- expectMap(personOnReaderNode.core.getCurrentContent()).get("name"),
270
- ).toEqual("John Doe");
271
- });
378
+ group.addMember(memberOnSourceNode, role);
379
+ expect(group.roleOf(source.accountID)).toEqual(role);
380
+
381
+ group.addMember("everyone", "writeOnly");
382
+ expect(group.roleOf("everyone")).toEqual("writeOnly");
272
383
  },
273
384
  );
274
385
 
275
- test.each(["writer", "reader", "writeOnly"] as const)(
276
- "an admin should be able downgrade themselves to %s",
277
- async (targetRole) => {
278
- const admin = await setupTestAccount({
386
+ test.each(["admin", "manager"] as Role[])(
387
+ "%s should be able to set reader role to EVERYONE",
388
+ async (role) => {
389
+ const source = await setupTestAccount({
279
390
  connected: true,
280
391
  });
392
+ const memberOnSourceNode = await loadCoValueOrFail(
393
+ source.node,
394
+ source.accountID,
395
+ );
281
396
 
282
- const group = admin.node.createGroup();
397
+ const group = source.node.createGroup();
283
398
 
284
- const account = await loadCoValueOrFail(admin.node, admin.accountID);
399
+ group.addMember(memberOnSourceNode, role);
400
+ expect(group.roleOf(source.accountID)).toEqual(role);
285
401
 
286
- // Downgrade self to target role
287
- group.addMember(account, targetRole);
288
- expect(group.roleOf(admin.accountID)).toEqual(targetRole);
402
+ group.addMember("everyone", "reader");
403
+ expect(group.roleOf("everyone")).toEqual("reader");
289
404
  },
290
405
  );
291
406
 
292
- test("an admin should be able downgrade a writeOnly to reader", async () => {
293
- const admin = await setupTestAccount({
294
- connected: true,
295
- });
407
+ test.each(["writer", "reader", "writeOnly"] as Role[])(
408
+ "%s should not be able to set any role to EVERYONE",
409
+ async (role) => {
410
+ const source = await setupTestAccount({
411
+ connected: true,
412
+ });
413
+ const memberOnSourceNode = await loadCoValueOrFail(
414
+ source.node,
415
+ source.accountID,
416
+ );
296
417
 
297
- const writeOnlyUser = await setupTestAccount({
298
- connected: true,
299
- });
418
+ const group = source.node.createGroup();
300
419
 
301
- const group = admin.node.createGroup();
302
- const person = group.createMap({
303
- name: "John Doe",
304
- });
420
+ group.addMember(memberOnSourceNode, role);
421
+ expect(group.roleOf(source.accountID)).toEqual(role);
305
422
 
306
- const writeOnlyUserOnAdminNode = await loadCoValueOrFail(
307
- admin.node,
308
- writeOnlyUser.accountID,
309
- );
310
- group.addMember(writeOnlyUserOnAdminNode, "writeOnly");
311
- group.addMember(writeOnlyUserOnAdminNode, "reader");
423
+ expect(() => {
424
+ group.addMember("everyone", "writer");
425
+ }).toThrow(
426
+ `Failed to set role writer to everyone (role of current account is ${role})`,
427
+ );
312
428
 
313
- expect(group.roleOf(writeOnlyUser.accountID)).toEqual("reader");
429
+ expect(group.roleOf("everyone")).toEqual(undefined);
314
430
 
315
- const personOnWriteOnlyNode = await loadCoValueOrFail(
316
- writeOnlyUser.node,
317
- person.id,
318
- );
431
+ expect(() => {
432
+ group.addMember("everyone", "reader");
433
+ }).toThrow(
434
+ `Failed to set role reader to everyone (role of current account is ${role})`,
435
+ );
319
436
 
320
- expect(personOnWriteOnlyNode.get("name")).toEqual("John Doe");
321
- });
437
+ expect(group.roleOf("everyone")).toEqual(undefined);
438
+
439
+ expect(() => {
440
+ group.addMember("everyone", "writeOnly");
441
+ }).toThrow(
442
+ `Failed to set role writeOnly to everyone (role of current account is ${role})`,
443
+ );
444
+
445
+ expect(group.roleOf("everyone")).toEqual(undefined);
446
+ },
447
+ );
322
448
 
323
- test("a reader should not be able to add a member", async () => {
449
+ test("an admin should be able downgrade a reader to writeOnly", async () => {
324
450
  const admin = await setupTestAccount({
325
451
  connected: true,
326
452
  });
@@ -329,111 +455,24 @@ describe("Group.addMember", () => {
329
455
  connected: true,
330
456
  });
331
457
 
332
- const newUser = await setupTestAccount({
333
- connected: true,
334
- });
335
-
336
458
  const group = admin.node.createGroup();
459
+
337
460
  const readerOnAdminNode = await loadCoValueOrFail(
338
461
  admin.node,
339
462
  reader.accountID,
340
463
  );
341
464
  group.addMember(readerOnAdminNode, "reader");
465
+ group.addMember(readerOnAdminNode, "writeOnly");
342
466
 
343
- const newUserOnReaderNode = await loadCoValueOrFail(
344
- reader.node,
345
- newUser.accountID,
346
- );
347
-
348
- const groupOnReaderNode = await loadCoValueOrFail(reader.node, group.id);
349
-
350
- // Try to add member as reader
351
- try {
352
- groupOnReaderNode.addMember(newUserOnReaderNode, "reader");
353
- throw new Error("Should not be able to add member as reader");
354
- } catch (e) {
355
- expect(e).toBeDefined();
356
- }
357
-
358
- expect(groupOnReaderNode.roleOf(newUser.accountID)).toBeUndefined();
359
- });
360
-
361
- test("a writer should not be able to add a member", async () => {
362
- const admin = await setupTestAccount({
363
- connected: true,
364
- });
365
-
366
- const writer = await setupTestAccount({
367
- connected: true,
368
- });
369
-
370
- const newUser = await setupTestAccount({
371
- connected: true,
372
- });
373
-
374
- const group = admin.node.createGroup();
375
- const writerOnAdminNode = await loadCoValueOrFail(
376
- admin.node,
377
- writer.accountID,
378
- );
379
- group.addMember(writerOnAdminNode, "writer");
380
-
381
- const newUserOnWriterNode = await loadCoValueOrFail(
382
- writer.node,
383
- newUser.accountID,
384
- );
385
-
386
- const groupOnWriterNode = await loadCoValueOrFail(writer.node, group.id);
387
-
388
- // Try to add member as writer
389
- try {
390
- groupOnWriterNode.addMember(newUserOnWriterNode, "reader");
391
- throw new Error("Should not be able to add member as writer");
392
- } catch (e) {
393
- expect(e).toBeDefined();
394
- }
395
-
396
- expect(groupOnWriterNode.roleOf(newUser.accountID)).toBeUndefined();
397
- });
398
-
399
- test("a writeOnly should not be able to add a member", async () => {
400
- const admin = await setupTestAccount({
401
- connected: true,
402
- });
403
-
404
- const writeOnlyUser = await setupTestAccount({
405
- connected: true,
406
- });
467
+ expect(group.roleOf(reader.accountID)).toEqual("writeOnly");
407
468
 
408
- const newUser = await setupTestAccount({
409
- connected: true,
469
+ const person = group.createMap({
470
+ name: "John Doe",
410
471
  });
411
472
 
412
- const group = admin.node.createGroup();
413
- const writeOnlyUserOnAdminNode = await loadCoValueOrFail(
414
- admin.node,
415
- writeOnlyUser.accountID,
416
- );
417
- group.addMember(writeOnlyUserOnAdminNode, "writeOnly");
418
-
419
- const newUserOnWriteOnlyNode = await loadCoValueOrFail(
420
- writeOnlyUser.node,
421
- newUser.accountID,
422
- );
423
-
424
- const groupOnWriteOnlyNode = await loadCoValueOrFail(
425
- writeOnlyUser.node,
426
- group.id,
427
- );
428
-
429
- // Try to add member as writeOnly user
430
- try {
431
- groupOnWriteOnlyNode.addMember(newUserOnWriteOnlyNode, "reader");
432
- throw new Error("Should not be able to add member as writeOnly user");
433
- } catch (e) {
434
- expect(e).toBeDefined();
435
- }
473
+ // Verify reader can read
474
+ const personOnReaderNode = await loadCoValueOrFail(reader.node, person.id);
436
475
 
437
- expect(groupOnWriteOnlyNode.roleOf(newUser.accountID)).toBeUndefined();
476
+ expect(personOnReaderNode.get("name")).toEqual(undefined);
438
477
  });
439
478
  });