cojson 0.13.16 → 0.13.18
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 +16 -0
- package/dist/PeerState.d.ts +3 -0
- package/dist/PeerState.d.ts.map +1 -1
- package/dist/PeerState.js +9 -0
- package/dist/PeerState.js.map +1 -1
- package/dist/SyncStateManager.d.ts.map +1 -1
- package/dist/SyncStateManager.js +2 -3
- package/dist/SyncStateManager.js.map +1 -1
- package/dist/coValue.d.ts +6 -4
- package/dist/coValue.d.ts.map +1 -1
- package/dist/coValue.js +5 -4
- package/dist/coValue.js.map +1 -1
- package/dist/coValueCore/coValueCore.d.ts +143 -0
- package/dist/coValueCore/coValueCore.d.ts.map +1 -0
- package/dist/{coValueCore.js → coValueCore/coValueCore.js} +314 -246
- package/dist/coValueCore/coValueCore.js.map +1 -0
- package/dist/coValueCore/verifiedState.d.ts +65 -0
- package/dist/coValueCore/verifiedState.d.ts.map +1 -0
- package/dist/coValueCore/verifiedState.js +210 -0
- package/dist/coValueCore/verifiedState.js.map +1 -0
- package/dist/coValues/account.d.ts +8 -10
- package/dist/coValues/account.d.ts.map +1 -1
- package/dist/coValues/account.js +12 -13
- package/dist/coValues/account.js.map +1 -1
- package/dist/coValues/coList.d.ts +10 -6
- package/dist/coValues/coList.d.ts.map +1 -1
- package/dist/coValues/coList.js +41 -15
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.d.ts +4 -3
- package/dist/coValues/coMap.d.ts.map +1 -1
- package/dist/coValues/coMap.js +5 -3
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coPlainText.d.ts +2 -2
- package/dist/coValues/coPlainText.d.ts.map +1 -1
- package/dist/coValues/coPlainText.js +5 -5
- package/dist/coValues/coPlainText.js.map +1 -1
- package/dist/coValues/coStream.d.ts +5 -4
- package/dist/coValues/coStream.d.ts.map +1 -1
- package/dist/coValues/coStream.js +5 -3
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/coValues/group.d.ts +7 -2
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +29 -26
- package/dist/coValues/group.js.map +1 -1
- package/dist/coreToCoValue.d.ts +4 -3
- package/dist/coreToCoValue.d.ts.map +1 -1
- package/dist/coreToCoValue.js +10 -14
- package/dist/coreToCoValue.js.map +1 -1
- package/dist/exports.d.ts +6 -5
- package/dist/exports.d.ts.map +1 -1
- package/dist/exports.js +3 -4
- package/dist/exports.js.map +1 -1
- package/dist/localNode.d.ts +30 -24
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +153 -177
- package/dist/localNode.js.map +1 -1
- package/dist/permissions.d.ts +2 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +15 -11
- package/dist/permissions.js.map +1 -1
- package/dist/priority.d.ts +1 -1
- package/dist/priority.d.ts.map +1 -1
- package/dist/sync.d.ts +2 -2
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +86 -55
- package/dist/sync.js.map +1 -1
- package/dist/tests/coList.test.js +133 -13
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/coMap.test.js +43 -14
- package/dist/tests/coMap.test.js.map +1 -1
- package/dist/tests/coPlainText.test.js +9 -10
- package/dist/tests/coPlainText.test.js.map +1 -1
- package/dist/tests/coStream.test.js +49 -18
- package/dist/tests/coStream.test.js.map +1 -1
- package/dist/tests/coValueCore.test.js +22 -28
- package/dist/tests/coValueCore.test.js.map +1 -1
- package/dist/tests/coValueCoreLoadingState.test.d.ts +2 -0
- package/dist/tests/coValueCoreLoadingState.test.d.ts.map +1 -0
- package/dist/tests/coValueCoreLoadingState.test.js +227 -0
- package/dist/tests/coValueCoreLoadingState.test.js.map +1 -0
- package/dist/tests/group.test.js +42 -43
- package/dist/tests/group.test.js.map +1 -1
- package/dist/tests/messagesTestUtils.d.ts +2 -2
- package/dist/tests/messagesTestUtils.d.ts.map +1 -1
- package/dist/tests/messagesTestUtils.js +1 -1
- package/dist/tests/messagesTestUtils.js.map +1 -1
- package/dist/tests/permissions.test.js +224 -292
- package/dist/tests/permissions.test.js.map +1 -1
- package/dist/tests/priority.test.js +13 -14
- package/dist/tests/priority.test.js.map +1 -1
- package/dist/tests/sync.auth.test.d.ts +2 -0
- package/dist/tests/sync.auth.test.d.ts.map +1 -0
- package/dist/tests/sync.auth.test.js +141 -0
- package/dist/tests/sync.auth.test.js.map +1 -0
- package/dist/tests/sync.load.test.js +60 -2
- package/dist/tests/sync.load.test.js.map +1 -1
- package/dist/tests/sync.mesh.test.js +70 -10
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.peerReconciliation.test.js +19 -19
- package/dist/tests/sync.peerReconciliation.test.js.map +1 -1
- package/dist/tests/sync.storage.test.js +20 -13
- package/dist/tests/sync.storage.test.js.map +1 -1
- package/dist/tests/sync.test.js +32 -39
- package/dist/tests/sync.test.js.map +1 -1
- package/dist/tests/sync.upload.test.js +126 -37
- package/dist/tests/sync.upload.test.js.map +1 -1
- package/dist/tests/testUtils.d.ts +24 -15
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +88 -61
- package/dist/tests/testUtils.js.map +1 -1
- package/dist/typeUtils/expectGroup.js +1 -1
- package/dist/typeUtils/expectGroup.js.map +1 -1
- package/package.json +1 -1
- package/src/PeerState.ts +11 -0
- package/src/SyncStateManager.ts +2 -3
- package/src/coValue.ts +14 -8
- package/src/{coValueCore.ts → coValueCore/coValueCore.ts} +470 -413
- package/src/coValueCore/verifiedState.ts +376 -0
- package/src/coValues/account.ts +20 -25
- package/src/coValues/coList.ts +63 -29
- package/src/coValues/coMap.ts +13 -6
- package/src/coValues/coPlainText.ts +10 -8
- package/src/coValues/coStream.ts +12 -7
- package/src/coValues/group.ts +50 -28
- package/src/coreToCoValue.ts +14 -15
- package/src/exports.ts +9 -7
- package/src/localNode.ts +248 -283
- package/src/permissions.ts +18 -12
- package/src/priority.ts +1 -1
- package/src/sync.ts +96 -63
- package/src/tests/coList.test.ts +200 -12
- package/src/tests/coMap.test.ts +65 -14
- package/src/tests/coPlainText.test.ts +12 -9
- package/src/tests/coStream.test.ts +80 -17
- package/src/tests/coValueCore.test.ts +30 -27
- package/src/tests/coValueCoreLoadingState.test.ts +337 -0
- package/src/tests/group.test.ts +44 -68
- package/src/tests/messagesTestUtils.ts +3 -8
- package/src/tests/permissions.test.ts +283 -449
- package/src/tests/priority.test.ts +17 -13
- package/src/tests/sync.auth.test.ts +188 -0
- package/src/tests/sync.load.test.ts +79 -2
- package/src/tests/sync.mesh.test.ts +89 -9
- package/src/tests/sync.peerReconciliation.test.ts +25 -25
- package/src/tests/sync.storage.test.ts +20 -13
- package/src/tests/sync.test.ts +43 -43
- package/src/tests/sync.upload.test.ts +157 -37
- package/src/tests/testUtils.ts +120 -74
- package/src/typeUtils/expectGroup.ts +1 -1
- package/dist/CoValuesStore.d.ts +0 -14
- package/dist/CoValuesStore.d.ts.map +0 -1
- package/dist/CoValuesStore.js +0 -32
- package/dist/CoValuesStore.js.map +0 -1
- package/dist/coValueCore.d.ts +0 -141
- package/dist/coValueCore.d.ts.map +0 -1
- package/dist/coValueCore.js.map +0 -1
- package/dist/coValueState.d.ts +0 -34
- package/dist/coValueState.d.ts.map +0 -1
- package/dist/coValueState.js +0 -228
- package/dist/coValueState.js.map +0 -1
- package/dist/tests/coValueState.test.d.ts +0 -2
- package/dist/tests/coValueState.test.d.ts.map +0 -1
- package/dist/tests/coValueState.test.js +0 -344
- package/dist/tests/coValueState.test.js.map +0 -1
- package/src/CoValuesStore.ts +0 -41
- package/src/coValueState.ts +0 -300
- package/src/tests/coValueState.test.ts +0 -525
|
@@ -3,7 +3,7 @@ import { expectMap } from "../coValue.js";
|
|
|
3
3
|
import { ControlledAgent } from "../coValues/account.js";
|
|
4
4
|
import { WasmCrypto } from "../crypto/WasmCrypto.js";
|
|
5
5
|
import { expectGroup } from "../typeUtils/expectGroup.js";
|
|
6
|
-
import { connectTwoPeers, createThreeConnectedNodes, createTwoConnectedNodes, groupWithTwoAdmins, groupWithTwoAdminsHighLevel, loadCoValueOrFail, newGroup, newGroupHighLevel, } from "./testUtils.js";
|
|
6
|
+
import { connectTwoPeers, createAccountInNode, createThreeConnectedNodes, createTwoConnectedNodes, groupWithTwoAdmins, groupWithTwoAdminsHighLevel, loadCoValueOrFail, newGroup, newGroupHighLevel, waitFor, } from "./testUtils.js";
|
|
7
7
|
const Crypto = await WasmCrypto.create();
|
|
8
8
|
test("Initial admin can add another admin to a group", () => {
|
|
9
9
|
groupWithTwoAdmins();
|
|
@@ -13,20 +13,16 @@ test("Initial admin can add another admin to a group (high level)", () => {
|
|
|
13
13
|
});
|
|
14
14
|
test("Added admin can add a third admin to a group", () => {
|
|
15
15
|
const { groupCore, otherAdmin, node } = groupWithTwoAdmins();
|
|
16
|
-
const groupAsOtherAdmin = expectGroup(groupCore
|
|
17
|
-
.testWithDifferentAccount(otherAdmin, Crypto.newRandomSessionID(otherAdmin.id))
|
|
18
|
-
.getCurrentContent());
|
|
16
|
+
const groupAsOtherAdmin = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(otherAdmin));
|
|
19
17
|
expect(groupAsOtherAdmin.get(otherAdmin.id)).toEqual("admin");
|
|
20
|
-
const thirdAdmin = node
|
|
18
|
+
const thirdAdmin = createAccountInNode(groupAsOtherAdmin.core.node);
|
|
21
19
|
groupAsOtherAdmin.set(thirdAdmin.id, "admin", "trusting");
|
|
22
20
|
expect(groupAsOtherAdmin.get(thirdAdmin.id)).toEqual("admin");
|
|
23
21
|
});
|
|
24
22
|
test("Added adming can add a third admin to a group (high level)", () => {
|
|
25
23
|
const { group, otherAdmin } = groupWithTwoAdminsHighLevel();
|
|
26
|
-
const groupAsOtherAdmin = expectGroup(group.core
|
|
27
|
-
|
|
28
|
-
.getCurrentContent());
|
|
29
|
-
const thirdAdmin = groupAsOtherAdmin.core.node.createAccount();
|
|
24
|
+
const groupAsOtherAdmin = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(otherAdmin));
|
|
25
|
+
const thirdAdmin = createAccountInNode(groupAsOtherAdmin.core.node);
|
|
30
26
|
groupAsOtherAdmin.addMember(thirdAdmin, "admin");
|
|
31
27
|
expect(groupAsOtherAdmin.get(thirdAdmin.id)).toEqual("admin");
|
|
32
28
|
});
|
|
@@ -36,32 +32,26 @@ test("Admins can't demote other admins in a group", () => {
|
|
|
36
32
|
groupContent.set(otherAdmin.id, "writer", "trusting");
|
|
37
33
|
expect(groupContent.get(otherAdmin.id)).toEqual("admin");
|
|
38
34
|
expect(groupContent.get(otherAdmin.id)).toEqual("admin");
|
|
39
|
-
const groupAsOtherAdmin = expectGroup(groupCore
|
|
40
|
-
.testWithDifferentAccount(otherAdmin, Crypto.newRandomSessionID(otherAdmin.id))
|
|
41
|
-
.getCurrentContent());
|
|
35
|
+
const groupAsOtherAdmin = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(otherAdmin));
|
|
42
36
|
groupAsOtherAdmin.set(admin.id, "writer", "trusting");
|
|
43
37
|
expect(groupAsOtherAdmin.get(admin.id)).toEqual("admin");
|
|
44
38
|
});
|
|
45
39
|
test("Admins can't demote other admins in a group (high level)", () => {
|
|
46
40
|
const { group, admin, otherAdmin } = groupWithTwoAdminsHighLevel();
|
|
47
|
-
const groupAsOtherAdmin = expectGroup(group.core
|
|
48
|
-
.testWithDifferentAccount(otherAdmin, Crypto.newRandomSessionID(otherAdmin.id))
|
|
49
|
-
.getCurrentContent());
|
|
41
|
+
const groupAsOtherAdmin = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(otherAdmin));
|
|
50
42
|
expect(() => groupAsOtherAdmin.addMemberInternal(admin.id, "writer")).toThrow("Failed to set role");
|
|
51
43
|
expect(groupAsOtherAdmin.get(admin.id)).toEqual("admin");
|
|
52
44
|
});
|
|
53
45
|
test("Admins an add writers to a group, who can't add admins, writers, or readers", () => {
|
|
54
46
|
const { groupCore, node } = newGroup();
|
|
55
|
-
const writer = node
|
|
47
|
+
const writer = createAccountInNode(node);
|
|
56
48
|
const groupContent = expectGroup(groupCore.getCurrentContent());
|
|
57
49
|
groupContent.set(writer.id, "writer", "trusting");
|
|
58
50
|
expect(groupContent.get(writer.id)).toEqual("writer");
|
|
59
51
|
expect(groupContent.get(writer.id)).toEqual("writer");
|
|
60
|
-
const groupAsWriter = expectGroup(groupCore
|
|
61
|
-
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
|
|
62
|
-
.getCurrentContent());
|
|
52
|
+
const groupAsWriter = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(writer));
|
|
63
53
|
expect(groupAsWriter.get(writer.id)).toEqual("writer");
|
|
64
|
-
const otherAgent = node
|
|
54
|
+
const otherAgent = createAccountInNode(node);
|
|
65
55
|
groupAsWriter.set(otherAgent.id, "admin", "trusting");
|
|
66
56
|
expect(groupAsWriter.get(otherAgent.id)).toBeUndefined();
|
|
67
57
|
groupAsWriter.set(otherAgent.id, "writer", "trusting");
|
|
@@ -71,14 +61,12 @@ test("Admins an add writers to a group, who can't add admins, writers, or reader
|
|
|
71
61
|
});
|
|
72
62
|
test("Admins an add writers to a group, who can't add admins, writers, or readers (high level)", () => {
|
|
73
63
|
const { group, node } = newGroupHighLevel();
|
|
74
|
-
const writer = node
|
|
64
|
+
const writer = createAccountInNode(node);
|
|
75
65
|
group.addMember(writer, "writer");
|
|
76
66
|
expect(group.get(writer.id)).toEqual("writer");
|
|
77
|
-
const groupAsWriter = expectGroup(group.core
|
|
78
|
-
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
|
|
79
|
-
.getCurrentContent());
|
|
67
|
+
const groupAsWriter = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(writer));
|
|
80
68
|
expect(groupAsWriter.get(writer.id)).toEqual("writer");
|
|
81
|
-
const otherAgent = groupAsWriter.core.node
|
|
69
|
+
const otherAgent = createAccountInNode(groupAsWriter.core.node);
|
|
82
70
|
expect(() => groupAsWriter.addMember(otherAgent, "admin")).toThrow("Failed to set role");
|
|
83
71
|
expect(() => groupAsWriter.addMember(otherAgent, "writer")).toThrow("Failed to set role");
|
|
84
72
|
expect(() => groupAsWriter.addMember(otherAgent, "reader")).toThrow("Failed to set role");
|
|
@@ -86,15 +74,13 @@ test("Admins an add writers to a group, who can't add admins, writers, or reader
|
|
|
86
74
|
});
|
|
87
75
|
test("Admins can add readers to a group, who can't add admins, writers, or readers", () => {
|
|
88
76
|
const { groupCore, node } = newGroup();
|
|
89
|
-
const reader = node
|
|
77
|
+
const reader = createAccountInNode(node);
|
|
90
78
|
const groupContent = expectGroup(groupCore.getCurrentContent());
|
|
91
79
|
groupContent.set(reader.id, "reader", "trusting");
|
|
92
80
|
expect(groupContent.get(reader.id)).toEqual("reader");
|
|
93
|
-
const groupAsReader = expectGroup(groupCore
|
|
94
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
95
|
-
.getCurrentContent());
|
|
81
|
+
const groupAsReader = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(reader));
|
|
96
82
|
expect(groupAsReader.get(reader.id)).toEqual("reader");
|
|
97
|
-
const otherAgent = node
|
|
83
|
+
const otherAgent = createAccountInNode(node);
|
|
98
84
|
groupAsReader.set(otherAgent.id, "admin", "trusting");
|
|
99
85
|
expect(groupAsReader.get(otherAgent.id)).toBeUndefined();
|
|
100
86
|
groupAsReader.set(otherAgent.id, "writer", "trusting");
|
|
@@ -104,14 +90,12 @@ test("Admins can add readers to a group, who can't add admins, writers, or reade
|
|
|
104
90
|
});
|
|
105
91
|
test("Admins can add readers to a group, who can't add admins, writers, or readers (high level)", () => {
|
|
106
92
|
const { group, node } = newGroupHighLevel();
|
|
107
|
-
const reader = node
|
|
93
|
+
const reader = createAccountInNode(node);
|
|
108
94
|
group.addMember(reader, "reader");
|
|
109
95
|
expect(group.get(reader.id)).toEqual("reader");
|
|
110
|
-
const groupAsReader = expectGroup(group.core
|
|
111
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
112
|
-
.getCurrentContent());
|
|
96
|
+
const groupAsReader = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(reader));
|
|
113
97
|
expect(groupAsReader.get(reader.id)).toEqual("reader");
|
|
114
|
-
const otherAgent = groupAsReader.core.node
|
|
98
|
+
const otherAgent = createAccountInNode(groupAsReader.core.node);
|
|
115
99
|
expect(() => groupAsReader.addMember(otherAgent, "admin")).toThrow("Failed to set role");
|
|
116
100
|
expect(() => groupAsReader.addMember(otherAgent, "writer")).toThrow("Failed to set role");
|
|
117
101
|
expect(() => groupAsReader.addMember(otherAgent, "reader")).toThrow("Failed to set role");
|
|
@@ -137,7 +121,7 @@ test("Admins can write to an object that is owned by their group (high level)",
|
|
|
137
121
|
});
|
|
138
122
|
test("Writers can write to an object that is owned by their group", () => {
|
|
139
123
|
const { node, groupCore } = newGroup();
|
|
140
|
-
const writer = node
|
|
124
|
+
const writer = createAccountInNode(node);
|
|
141
125
|
const group = expectGroup(groupCore.getCurrentContent());
|
|
142
126
|
group.set(writer.id, "writer", "trusting");
|
|
143
127
|
expect(group.get(writer.id)).toEqual("writer");
|
|
@@ -147,25 +131,22 @@ test("Writers can write to an object that is owned by their group", () => {
|
|
|
147
131
|
meta: null,
|
|
148
132
|
...Crypto.createdNowUnique(),
|
|
149
133
|
});
|
|
150
|
-
const childObjectAsWriter = childObject.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
expect(childContentAsWriter.get("foo")).toEqual("bar");
|
|
134
|
+
const childObjectAsWriter = expectMap(childObject.contentInClonedNodeWithDifferentAccount(writer));
|
|
135
|
+
childObjectAsWriter.set("foo", "bar", "trusting");
|
|
136
|
+
expect(childObjectAsWriter.get("foo")).toEqual("bar");
|
|
154
137
|
});
|
|
155
138
|
test("Writers can write to an object that is owned by their group (high level)", () => {
|
|
156
139
|
const { node, group } = newGroupHighLevel();
|
|
157
|
-
const writer = node
|
|
140
|
+
const writer = createAccountInNode(node);
|
|
158
141
|
group.addMember(writer, "writer");
|
|
159
142
|
const childObject = group.createMap();
|
|
160
|
-
const childObjectAsWriter = expectMap(childObject.core
|
|
161
|
-
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
|
|
162
|
-
.getCurrentContent());
|
|
143
|
+
const childObjectAsWriter = expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(writer));
|
|
163
144
|
childObjectAsWriter.set("foo", "bar", "trusting");
|
|
164
145
|
expect(childObjectAsWriter.get("foo")).toEqual("bar");
|
|
165
146
|
});
|
|
166
147
|
test("Readers can not write to an object that is owned by their group", () => {
|
|
167
148
|
const { node, groupCore } = newGroup();
|
|
168
|
-
const reader = node
|
|
149
|
+
const reader = createAccountInNode(node);
|
|
169
150
|
const group = expectGroup(groupCore.getCurrentContent());
|
|
170
151
|
group.set(reader.id, "reader", "trusting");
|
|
171
152
|
expect(group.get(reader.id)).toEqual("reader");
|
|
@@ -175,19 +156,17 @@ test("Readers can not write to an object that is owned by their group", () => {
|
|
|
175
156
|
meta: null,
|
|
176
157
|
...Crypto.createdNowUnique(),
|
|
177
158
|
});
|
|
178
|
-
const childObjectAsReader = childObject.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
expect(
|
|
159
|
+
const childObjectAsReader = expectMap(childObject.contentInClonedNodeWithDifferentAccount(reader));
|
|
160
|
+
childObjectAsReader.set("foo", "bar", "trusting");
|
|
161
|
+
childObjectAsReader.set("foo", "bar", "trusting");
|
|
162
|
+
expect(childObjectAsReader.get("foo")).toBeUndefined();
|
|
182
163
|
});
|
|
183
164
|
test("Readers can not write to an object that is owned by their group (high level)", () => {
|
|
184
165
|
const { node, group } = newGroupHighLevel();
|
|
185
|
-
const reader = node
|
|
166
|
+
const reader = createAccountInNode(node);
|
|
186
167
|
group.addMember(reader, "reader");
|
|
187
168
|
const childObject = group.createMap();
|
|
188
|
-
const childObjectAsReader = expectMap(childObject.core
|
|
189
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
190
|
-
.getCurrentContent());
|
|
169
|
+
const childObjectAsReader = expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(reader));
|
|
191
170
|
childObjectAsReader.set("foo", "bar", "trusting");
|
|
192
171
|
expect(childObjectAsReader.get("foo")).toBeUndefined();
|
|
193
172
|
});
|
|
@@ -227,7 +206,7 @@ test("Admins can set group read key and then use it to create and read private t
|
|
|
227
206
|
});
|
|
228
207
|
test("Admins can set group read key and then writers can use it to create and read private transactions in owned objects", () => {
|
|
229
208
|
const { node, groupCore, admin } = newGroup();
|
|
230
|
-
const writer = node
|
|
209
|
+
const writer = createAccountInNode(node);
|
|
231
210
|
const { secret: readKey, id: readKeyID } = Crypto.newRandomKeySecret();
|
|
232
211
|
const groupContent = expectGroup(groupCore.getCurrentContent());
|
|
233
212
|
groupContent.set(writer.id, "writer", "trusting");
|
|
@@ -259,26 +238,24 @@ test("Admins can set group read key and then writers can use it to create and re
|
|
|
259
238
|
meta: null,
|
|
260
239
|
...Crypto.createdNowUnique(),
|
|
261
240
|
});
|
|
262
|
-
const childObjectAsWriter = childObject.
|
|
241
|
+
const childObjectAsWriter = expectMap(childObject.contentInClonedNodeWithDifferentAccount(writer));
|
|
263
242
|
expect(childObject.getCurrentReadKey().secret).toEqual(readKey);
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
expect(
|
|
243
|
+
expect(childObjectAsWriter.core.getCurrentReadKey().secret).toEqual(readKey);
|
|
244
|
+
childObjectAsWriter.set("foo", "bar", "private");
|
|
245
|
+
expect(childObjectAsWriter.get("foo")).toEqual("bar");
|
|
267
246
|
});
|
|
268
247
|
test("Admins can set group read key and then writers can use it to create and read private transactions in owned objects (high level)", () => {
|
|
269
248
|
const { node, group } = newGroupHighLevel();
|
|
270
|
-
const writer = node
|
|
249
|
+
const writer = createAccountInNode(node);
|
|
271
250
|
group.addMember(writer, "writer");
|
|
272
251
|
const childObject = group.createMap();
|
|
273
|
-
const childObjectAsWriter = expectMap(childObject.core
|
|
274
|
-
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
|
|
275
|
-
.getCurrentContent());
|
|
252
|
+
const childObjectAsWriter = expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(writer));
|
|
276
253
|
childObjectAsWriter.set("foo", "bar", "private");
|
|
277
254
|
expect(childObjectAsWriter.get("foo")).toEqual("bar");
|
|
278
255
|
});
|
|
279
256
|
test("Admins can set group read key and then use it to create private transactions in owned objects, which readers can read", () => {
|
|
280
257
|
const { node, groupCore, admin } = newGroup();
|
|
281
|
-
const reader = node
|
|
258
|
+
const reader = createAccountInNode(node);
|
|
282
259
|
const { secret: readKey, id: readKeyID } = Crypto.newRandomKeySecret();
|
|
283
260
|
const groupContent = expectGroup(groupCore.getCurrentContent());
|
|
284
261
|
groupContent.set(reader.id, "reader", "trusting");
|
|
@@ -313,27 +290,24 @@ test("Admins can set group read key and then use it to create private transactio
|
|
|
313
290
|
const childContent = expectMap(childObject.getCurrentContent());
|
|
314
291
|
childContent.set("foo", "bar", "private");
|
|
315
292
|
expect(childContent.get("foo")).toEqual("bar");
|
|
316
|
-
const childObjectAsReader = childObject.
|
|
317
|
-
expect(childObjectAsReader.getCurrentReadKey().secret).toEqual(readKey);
|
|
318
|
-
|
|
319
|
-
expect(childContentAsReader.get("foo")).toEqual("bar");
|
|
293
|
+
const childObjectAsReader = expectMap(childObject.contentInClonedNodeWithDifferentAccount(reader));
|
|
294
|
+
expect(childObjectAsReader.core.getCurrentReadKey().secret).toEqual(readKey);
|
|
295
|
+
expect(childObjectAsReader.get("foo")).toEqual("bar");
|
|
320
296
|
});
|
|
321
297
|
test("Admins can set group read key and then use it to create private transactions in owned objects, which readers can read (high level)", () => {
|
|
322
298
|
const { node, group } = newGroupHighLevel();
|
|
323
|
-
const reader = node
|
|
299
|
+
const reader = createAccountInNode(node);
|
|
324
300
|
group.addMember(reader, "reader");
|
|
325
301
|
const childObject = group.createMap();
|
|
326
302
|
childObject.set("foo", "bar", "private");
|
|
327
303
|
expect(childObject.get("foo")).toEqual("bar");
|
|
328
|
-
const childContentAsReader = expectMap(childObject.core
|
|
329
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
330
|
-
.getCurrentContent());
|
|
304
|
+
const childContentAsReader = expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(reader));
|
|
331
305
|
expect(childContentAsReader.get("foo")).toEqual("bar");
|
|
332
306
|
});
|
|
333
307
|
test("Admins can set group read key and then use it to create private transactions in owned objects, which readers can read, even with a separate later revelation for the same read key", () => {
|
|
334
308
|
const { node, groupCore, admin } = newGroup();
|
|
335
|
-
const reader1 = node
|
|
336
|
-
const reader2 = node
|
|
309
|
+
const reader1 = createAccountInNode(node);
|
|
310
|
+
const reader2 = createAccountInNode(node);
|
|
337
311
|
const { secret: readKey, id: readKeyID } = Crypto.newRandomKeySecret();
|
|
338
312
|
const groupContent = expectGroup(groupCore.getCurrentContent());
|
|
339
313
|
groupContent.set(reader1.id, "reader", "trusting");
|
|
@@ -368,10 +342,9 @@ test("Admins can set group read key and then use it to create private transactio
|
|
|
368
342
|
const childContent = expectMap(childObject.getCurrentContent());
|
|
369
343
|
childContent.set("foo", "bar", "private");
|
|
370
344
|
expect(childContent.get("foo")).toEqual("bar");
|
|
371
|
-
const childObjectAsReader1 = childObject.
|
|
372
|
-
expect(childObjectAsReader1.getCurrentReadKey().secret).toEqual(readKey);
|
|
373
|
-
|
|
374
|
-
expect(childContentAsReader1.get("foo")).toEqual("bar");
|
|
345
|
+
const childObjectAsReader1 = expectMap(childObject.contentInClonedNodeWithDifferentAccount(reader1));
|
|
346
|
+
expect(childObjectAsReader1.core.getCurrentReadKey().secret).toEqual(readKey);
|
|
347
|
+
expect(childObjectAsReader1.get("foo")).toEqual("bar");
|
|
375
348
|
const revelation3 = Crypto.seal({
|
|
376
349
|
message: readKey,
|
|
377
350
|
from: admin.currentSealerSecret(),
|
|
@@ -382,27 +355,22 @@ test("Admins can set group read key and then use it to create private transactio
|
|
|
382
355
|
},
|
|
383
356
|
});
|
|
384
357
|
groupContent.set(`${readKeyID}_for_${reader2.id}`, revelation3, "trusting");
|
|
385
|
-
const childObjectAsReader2 = childObject.
|
|
386
|
-
expect(childObjectAsReader2.getCurrentReadKey().secret).toEqual(readKey);
|
|
387
|
-
|
|
388
|
-
expect(childContentAsReader2.get("foo")).toEqual("bar");
|
|
358
|
+
const childObjectAsReader2 = expectMap(childObject.contentInClonedNodeWithDifferentAccount(reader2));
|
|
359
|
+
expect(childObjectAsReader2.core.getCurrentReadKey().secret).toEqual(readKey);
|
|
360
|
+
expect(childObjectAsReader2.get("foo")).toEqual("bar");
|
|
389
361
|
});
|
|
390
362
|
test("Admins can set group read key and then use it to create private transactions in owned objects, which readers can read, even with a separate later revelation for the same read key (high level)", () => {
|
|
391
363
|
const { node, group } = newGroupHighLevel();
|
|
392
|
-
const reader1 = node
|
|
393
|
-
const reader2 = node
|
|
364
|
+
const reader1 = createAccountInNode(node);
|
|
365
|
+
const reader2 = createAccountInNode(node);
|
|
394
366
|
group.addMember(reader1, "reader");
|
|
395
367
|
const childObject = group.createMap();
|
|
396
368
|
childObject.set("foo", "bar", "private");
|
|
397
369
|
expect(childObject.get("foo")).toEqual("bar");
|
|
398
|
-
const childContentAsReader1 = expectMap(childObject.core
|
|
399
|
-
.testWithDifferentAccount(reader1, Crypto.newRandomSessionID(reader1.id))
|
|
400
|
-
.getCurrentContent());
|
|
370
|
+
const childContentAsReader1 = expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(reader1));
|
|
401
371
|
expect(childContentAsReader1.get("foo")).toEqual("bar");
|
|
402
372
|
group.addMember(reader2, "reader");
|
|
403
|
-
const childContentAsReader2 = expectMap(childObject.core
|
|
404
|
-
.testWithDifferentAccount(reader2, Crypto.newRandomSessionID(reader2.id))
|
|
405
|
-
.getCurrentContent());
|
|
373
|
+
const childContentAsReader2 = expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(reader2));
|
|
406
374
|
expect(childContentAsReader2.get("foo")).toEqual("bar");
|
|
407
375
|
});
|
|
408
376
|
test("Admins can set group read key, make a private transaction in an owned object, rotate the read key, make another private transaction, and both can be read by the admin", () => {
|
|
@@ -487,7 +455,7 @@ test("Admins can set group read key, make a private transaction in an owned obje
|
|
|
487
455
|
childContent.set("foo", "bar", "private");
|
|
488
456
|
expect(childContent.get("foo")).toEqual("bar");
|
|
489
457
|
expect(childContent.get("foo")).toEqual("bar");
|
|
490
|
-
const reader = node
|
|
458
|
+
const reader = createAccountInNode(node);
|
|
491
459
|
const { secret: readKey2, id: readKeyID2 } = Crypto.newRandomKeySecret();
|
|
492
460
|
const revelation2 = Crypto.seal({
|
|
493
461
|
message: readKey2,
|
|
@@ -520,11 +488,10 @@ test("Admins can set group read key, make a private transaction in an owned obje
|
|
|
520
488
|
expect(groupContent.get(reader.id)).toEqual("reader");
|
|
521
489
|
childContent.set("foo2", "bar2", "private");
|
|
522
490
|
expect(childContent.get("foo2")).toEqual("bar2");
|
|
523
|
-
const childObjectAsReader = childObject.
|
|
524
|
-
expect(childObjectAsReader.getCurrentReadKey().secret).toEqual(readKey2);
|
|
525
|
-
|
|
526
|
-
expect(
|
|
527
|
-
expect(childContentAsReader.get("foo2")).toEqual("bar2");
|
|
491
|
+
const childObjectAsReader = expectMap(childObject.contentInClonedNodeWithDifferentAccount(reader));
|
|
492
|
+
expect(childObjectAsReader.core.getCurrentReadKey().secret).toEqual(readKey2);
|
|
493
|
+
expect(childObjectAsReader.get("foo")).toEqual("bar");
|
|
494
|
+
expect(childObjectAsReader.get("foo2")).toEqual("bar2");
|
|
528
495
|
});
|
|
529
496
|
test("Admins can set group read key, make a private transaction in an owned object, rotate the read key, add a reader, make another private transaction in the owned object, and both can be read by the reader (high level)", () => {
|
|
530
497
|
const { node, group } = newGroupHighLevel();
|
|
@@ -535,13 +502,11 @@ test("Admins can set group read key, make a private transaction in an owned obje
|
|
|
535
502
|
expect(childObject.get("foo")).toEqual("bar");
|
|
536
503
|
group.rotateReadKey();
|
|
537
504
|
expect(childObject.core.getCurrentReadKey()).not.toEqual(firstReadKey);
|
|
538
|
-
const reader = node
|
|
505
|
+
const reader = createAccountInNode(node);
|
|
539
506
|
group.addMember(reader, "reader");
|
|
540
507
|
childObject.set("foo2", "bar2", "private");
|
|
541
508
|
expect(childObject.get("foo2")).toEqual("bar2");
|
|
542
|
-
const childContentAsReader = expectMap(childObject.core
|
|
543
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
544
|
-
.getCurrentContent());
|
|
509
|
+
const childContentAsReader = expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(reader));
|
|
545
510
|
expect(childContentAsReader.get("foo")).toEqual("bar");
|
|
546
511
|
expect(childContentAsReader.get("foo2")).toEqual("bar2");
|
|
547
512
|
});
|
|
@@ -549,9 +514,7 @@ test("only admins can add agent ids", () => {
|
|
|
549
514
|
const { groupCore } = newGroup();
|
|
550
515
|
const inviteSecret = Crypto.newRandomAgentSecret();
|
|
551
516
|
const inviteID = Crypto.getAgentID(inviteSecret);
|
|
552
|
-
const groupAsInvite = expectGroup(groupCore
|
|
553
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
554
|
-
.getCurrentContent());
|
|
517
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
555
518
|
groupAsInvite.set(inviteID, "adminInvite", "trusting");
|
|
556
519
|
expect(groupAsInvite.get(inviteID)).toEqual(undefined);
|
|
557
520
|
});
|
|
@@ -565,8 +528,8 @@ test("Admins can set group read rey, make a private transaction in an owned obje
|
|
|
565
528
|
});
|
|
566
529
|
const groupContent = expectGroup(groupCore.getCurrentContent());
|
|
567
530
|
const { secret: readKey, id: readKeyID } = Crypto.newRandomKeySecret();
|
|
568
|
-
const reader = node
|
|
569
|
-
const reader2 = node
|
|
531
|
+
const reader = createAccountInNode(node);
|
|
532
|
+
const reader2 = createAccountInNode(node);
|
|
570
533
|
const revelation1 = Crypto.seal({
|
|
571
534
|
message: readKey,
|
|
572
535
|
from: admin.currentSealerSecret(),
|
|
@@ -607,10 +570,10 @@ test("Admins can set group read rey, make a private transaction in an owned obje
|
|
|
607
570
|
const childContent = expectMap(childObject.getCurrentContent());
|
|
608
571
|
childContent.set("foo", "bar", "private");
|
|
609
572
|
expect(childContent.get("foo")).toEqual("bar");
|
|
610
|
-
let childObjectAsReader = childObject.
|
|
611
|
-
expect(
|
|
612
|
-
let childObjectAsReader2 = childObject.
|
|
613
|
-
expect(
|
|
573
|
+
let childObjectAsReader = expectMap(childObject.contentInClonedNodeWithDifferentAccount(reader));
|
|
574
|
+
expect(childObjectAsReader.get("foo")).toEqual("bar");
|
|
575
|
+
let childObjectAsReader2 = expectMap(childObject.contentInClonedNodeWithDifferentAccount(reader2));
|
|
576
|
+
expect(childObjectAsReader2.get("foo")).toEqual("bar");
|
|
614
577
|
const { secret: readKey2, id: readKeyID2 } = Crypto.newRandomKeySecret();
|
|
615
578
|
const newRevelation1 = Crypto.seal({
|
|
616
579
|
message: readKey2,
|
|
@@ -641,10 +604,10 @@ test("Admins can set group read rey, make a private transaction in an owned obje
|
|
|
641
604
|
childContent.set("foo2", "bar2", "private");
|
|
642
605
|
expect(childContent.get("foo2")).toEqual("bar2");
|
|
643
606
|
// TODO: make sure these instances of coValues sync between each other so this isn't necessary?
|
|
644
|
-
childObjectAsReader = childObject.
|
|
645
|
-
childObjectAsReader2 = childObject.
|
|
646
|
-
expect(
|
|
647
|
-
expect(
|
|
607
|
+
childObjectAsReader = expectMap(childObject.contentInClonedNodeWithDifferentAccount(reader));
|
|
608
|
+
childObjectAsReader2 = expectMap(childObject.contentInClonedNodeWithDifferentAccount(reader2));
|
|
609
|
+
expect(childObjectAsReader.get("foo2")).toBeUndefined();
|
|
610
|
+
expect(childObjectAsReader2.get("foo2")).toEqual("bar2");
|
|
648
611
|
});
|
|
649
612
|
test("Admins can set group read rey, make a private transaction in an owned object, rotate the read key, add two readers, rotate the read key again to kick out one reader, make another private transaction in the owned object, and only the remaining reader can read both transactions (high level)", async () => {
|
|
650
613
|
const { node, group } = newGroupHighLevel();
|
|
@@ -654,8 +617,8 @@ test("Admins can set group read rey, make a private transaction in an owned obje
|
|
|
654
617
|
expect(childObject.get("foo")).toEqual("bar");
|
|
655
618
|
group.rotateReadKey();
|
|
656
619
|
const secondReadKey = childObject.core.getCurrentReadKey();
|
|
657
|
-
const reader = node
|
|
658
|
-
const reader2 = node
|
|
620
|
+
const reader = createAccountInNode(node);
|
|
621
|
+
const reader2 = createAccountInNode(node);
|
|
659
622
|
group.addMember(reader, "reader");
|
|
660
623
|
group.addMember(reader2, "reader");
|
|
661
624
|
childObject.set("foo2", "bar2", "private");
|
|
@@ -664,15 +627,11 @@ test("Admins can set group read rey, make a private transaction in an owned obje
|
|
|
664
627
|
expect(childObject.core.getCurrentReadKey()).not.toEqual(secondReadKey);
|
|
665
628
|
childObject.set("foo3", "bar3", "private");
|
|
666
629
|
expect(childObject.get("foo3")).toEqual("bar3");
|
|
667
|
-
const childContentAsReader2 = expectMap(childObject.core
|
|
668
|
-
.testWithDifferentAccount(reader2, Crypto.newRandomSessionID(reader2.id))
|
|
669
|
-
.getCurrentContent());
|
|
630
|
+
const childContentAsReader2 = expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(reader2));
|
|
670
631
|
expect(childContentAsReader2.get("foo")).toEqual("bar");
|
|
671
632
|
expect(childContentAsReader2.get("foo2")).toEqual("bar2");
|
|
672
633
|
expect(childContentAsReader2.get("foo3")).toEqual("bar3");
|
|
673
|
-
expect(expectMap(childObject.core
|
|
674
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
675
|
-
.getCurrentContent()).get("foo3")).toBeUndefined();
|
|
634
|
+
expect(expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(reader)).get("foo3")).toBeUndefined();
|
|
676
635
|
});
|
|
677
636
|
test("Can create two owned objects in the same group and they will have different ids", () => {
|
|
678
637
|
const { node, groupCore } = newGroup();
|
|
@@ -719,9 +678,7 @@ test("Admins can create an adminInvite, which can add an admin", () => {
|
|
|
719
678
|
},
|
|
720
679
|
});
|
|
721
680
|
group.set(`${readKeyID}_for_${inviteID}`, revelationForInvite, "trusting");
|
|
722
|
-
const groupAsInvite = expectGroup(groupCore
|
|
723
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
724
|
-
.getCurrentContent());
|
|
681
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
725
682
|
const invitedAdminSecret = Crypto.newRandomAgentSecret();
|
|
726
683
|
const invitedAdminID = Crypto.getAgentID(invitedAdminSecret);
|
|
727
684
|
groupAsInvite.set(invitedAdminID, "admin", "trusting");
|
|
@@ -745,7 +702,7 @@ test("Admins can create an adminInvite, which can add an admin (high-level)", as
|
|
|
745
702
|
const inviteSecret = group.createInvite("admin");
|
|
746
703
|
const invitedAdminSecret = Crypto.newRandomAgentSecret();
|
|
747
704
|
const invitedAdminID = Crypto.getAgentID(invitedAdminSecret);
|
|
748
|
-
const nodeAsInvitedAdmin = node.
|
|
705
|
+
const nodeAsInvitedAdmin = node.cloneWithDifferentAccount(new ControlledAgent(invitedAdminSecret, Crypto));
|
|
749
706
|
await nodeAsInvitedAdmin.acceptInvite(group.id, inviteSecret);
|
|
750
707
|
const thirdAdmin = Crypto.newRandomAgentSecret();
|
|
751
708
|
const thirdAdminID = Crypto.getAgentID(thirdAdmin);
|
|
@@ -787,9 +744,7 @@ test("Admins can create a writerInvite, which can add a writer", () => {
|
|
|
787
744
|
},
|
|
788
745
|
});
|
|
789
746
|
group.set(`${readKeyID}_for_${inviteID}`, revelationForInvite, "trusting");
|
|
790
|
-
const groupAsInvite = expectGroup(groupCore
|
|
791
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
792
|
-
.getCurrentContent());
|
|
747
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
793
748
|
const invitedWriterSecret = Crypto.newRandomAgentSecret();
|
|
794
749
|
const invitedWriterID = Crypto.getAgentID(invitedWriterSecret);
|
|
795
750
|
groupAsInvite.set(invitedWriterID, "writer", "trusting");
|
|
@@ -813,7 +768,7 @@ test("Admins can create a writerInvite, which can add a writer (high-level)", as
|
|
|
813
768
|
const inviteSecret = group.createInvite("writer");
|
|
814
769
|
const invitedWriterSecret = Crypto.newRandomAgentSecret();
|
|
815
770
|
const invitedWriterID = Crypto.getAgentID(invitedWriterSecret);
|
|
816
|
-
const nodeAsInvitedWriter = node.
|
|
771
|
+
const nodeAsInvitedWriter = node.cloneWithDifferentAccount(new ControlledAgent(invitedWriterSecret, Crypto));
|
|
817
772
|
await nodeAsInvitedWriter.acceptInvite(group.id, inviteSecret);
|
|
818
773
|
const groupAsInvitedWriter = await nodeAsInvitedWriter.load(group.id);
|
|
819
774
|
if (groupAsInvitedWriter === "unavailable") {
|
|
@@ -851,9 +806,7 @@ test("Admins can create a readerInvite, which can add a reader", () => {
|
|
|
851
806
|
},
|
|
852
807
|
});
|
|
853
808
|
group.set(`${readKeyID}_for_${inviteID}`, revelationForInvite, "trusting");
|
|
854
|
-
const groupAsInvite = expectGroup(groupCore
|
|
855
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
856
|
-
.getCurrentContent());
|
|
809
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
857
810
|
const invitedReaderSecret = Crypto.newRandomAgentSecret();
|
|
858
811
|
const invitedReaderID = Crypto.getAgentID(invitedReaderSecret);
|
|
859
812
|
groupAsInvite.set(invitedReaderID, "reader", "trusting");
|
|
@@ -868,7 +821,7 @@ test("Admins can create a readerInvite, which can add a reader (high-level)", as
|
|
|
868
821
|
const inviteSecret = group.createInvite("reader");
|
|
869
822
|
const invitedReaderSecret = Crypto.newRandomAgentSecret();
|
|
870
823
|
const invitedReaderID = Crypto.getAgentID(invitedReaderSecret);
|
|
871
|
-
const nodeAsInvitedReader = node.
|
|
824
|
+
const nodeAsInvitedReader = node.cloneWithDifferentAccount(new ControlledAgent(invitedReaderSecret, Crypto));
|
|
872
825
|
await nodeAsInvitedReader.acceptInvite(group.id, inviteSecret);
|
|
873
826
|
const groupAsInvitedReader = await nodeAsInvitedReader.load(group.id);
|
|
874
827
|
if (groupAsInvitedReader === "unavailable") {
|
|
@@ -906,9 +859,7 @@ test("WriterInvites can not invite admins", () => {
|
|
|
906
859
|
},
|
|
907
860
|
});
|
|
908
861
|
group.set(`${readKeyID}_for_${inviteID}`, revelationForInvite, "trusting");
|
|
909
|
-
const groupAsInvite = expectGroup(groupCore
|
|
910
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
911
|
-
.getCurrentContent());
|
|
862
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
912
863
|
const invitedAdminSecret = Crypto.newRandomAgentSecret();
|
|
913
864
|
const invitedAdminID = Crypto.getAgentID(invitedAdminSecret);
|
|
914
865
|
groupAsInvite.set(invitedAdminID, "admin", "trusting");
|
|
@@ -943,9 +894,7 @@ test("ReaderInvites can not invite admins", () => {
|
|
|
943
894
|
},
|
|
944
895
|
});
|
|
945
896
|
group.set(`${readKeyID}_for_${inviteID}`, revelationForInvite, "trusting");
|
|
946
|
-
const groupAsInvite = expectGroup(groupCore
|
|
947
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
948
|
-
.getCurrentContent());
|
|
897
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
949
898
|
const invitedAdminSecret = Crypto.newRandomAgentSecret();
|
|
950
899
|
const invitedAdminID = Crypto.getAgentID(invitedAdminSecret);
|
|
951
900
|
groupAsInvite.set(invitedAdminID, "admin", "trusting");
|
|
@@ -980,9 +929,7 @@ test("ReaderInvites can not invite writers", () => {
|
|
|
980
929
|
},
|
|
981
930
|
});
|
|
982
931
|
group.set(`${readKeyID}_for_${inviteID}`, revelationForInvite, "trusting");
|
|
983
|
-
const groupAsInvite = expectGroup(groupCore
|
|
984
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
985
|
-
.getCurrentContent());
|
|
932
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
986
933
|
const invitedWriterSecret = Crypto.newRandomAgentSecret();
|
|
987
934
|
const invitedWriterID = Crypto.getAgentID(invitedWriterSecret);
|
|
988
935
|
groupAsInvite.set(invitedWriterID, "writer", "trusting");
|
|
@@ -1017,9 +964,7 @@ test("WriteOnlyInvites can not invite writers", () => {
|
|
|
1017
964
|
},
|
|
1018
965
|
});
|
|
1019
966
|
group.set(`${readKeyID}_for_${inviteID}`, revelationForInvite, "trusting");
|
|
1020
|
-
const groupAsInvite = expectGroup(groupCore
|
|
1021
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
1022
|
-
.getCurrentContent());
|
|
967
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
1023
968
|
const invitedWriterSecret = Crypto.newRandomAgentSecret();
|
|
1024
969
|
const invitedWriterID = Crypto.getAgentID(invitedWriterSecret);
|
|
1025
970
|
groupAsInvite.set(invitedWriterID, "writer", "trusting");
|
|
@@ -1054,9 +999,7 @@ test("WriteOnlyInvites can not invite admins", () => {
|
|
|
1054
999
|
},
|
|
1055
1000
|
});
|
|
1056
1001
|
group.set(`${readKeyID}_for_${inviteID}`, revelationForInvite, "trusting");
|
|
1057
|
-
const groupAsInvite = expectGroup(groupCore
|
|
1058
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
1059
|
-
.getCurrentContent());
|
|
1002
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
1060
1003
|
const invitedWriterSecret = Crypto.newRandomAgentSecret();
|
|
1061
1004
|
const invitedWriterID = Crypto.getAgentID(invitedWriterSecret);
|
|
1062
1005
|
groupAsInvite.set(invitedWriterID, "admin", "trusting");
|
|
@@ -1091,9 +1034,7 @@ test("WriteOnlyInvites can invite writeOnly", () => {
|
|
|
1091
1034
|
},
|
|
1092
1035
|
});
|
|
1093
1036
|
group.set(`${readKeyID}_for_${inviteID}`, revelationForInvite, "trusting");
|
|
1094
|
-
const groupAsInvite = expectGroup(groupCore
|
|
1095
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
1096
|
-
.getCurrentContent());
|
|
1037
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
1097
1038
|
const invitedWriterSecret = Crypto.newRandomAgentSecret();
|
|
1098
1039
|
const invitedWriterID = Crypto.getAgentID(invitedWriterSecret);
|
|
1099
1040
|
groupAsInvite.set(invitedWriterID, "writeOnly", "trusting");
|
|
@@ -1128,9 +1069,7 @@ test("WriteOnlyInvites can set writeKeys", () => {
|
|
|
1128
1069
|
},
|
|
1129
1070
|
});
|
|
1130
1071
|
group.set(`${readKeyID}_for_${inviteID}`, revelationForInvite, "trusting");
|
|
1131
|
-
const groupAsInvite = expectGroup(groupCore
|
|
1132
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
1133
|
-
.getCurrentContent());
|
|
1072
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
1134
1073
|
groupAsInvite.set(`writeKeyFor_${admin.id}`, readKeyID, "trusting");
|
|
1135
1074
|
expect(groupAsInvite.get(`writeKeyFor_${admin.id}`)).toEqual(readKeyID);
|
|
1136
1075
|
});
|
|
@@ -1163,9 +1102,7 @@ test("Invites can't override key revelations", () => {
|
|
|
1163
1102
|
},
|
|
1164
1103
|
});
|
|
1165
1104
|
group.set(`${readKeyID}_for_${inviteID}`, revelationForInvite, "trusting");
|
|
1166
|
-
const groupAsInvite = expectGroup(groupCore
|
|
1167
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
1168
|
-
.getCurrentContent());
|
|
1105
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
1169
1106
|
groupAsInvite.set(`${readKeyID}_for_${admin.id}`, "Evil change", "trusting");
|
|
1170
1107
|
expect(groupAsInvite.get(`${readKeyID}_for_${admin.id}`)).toBe(revelation);
|
|
1171
1108
|
});
|
|
@@ -1198,9 +1135,7 @@ test("WriteOnlyInvites can't override writeKeys", () => {
|
|
|
1198
1135
|
},
|
|
1199
1136
|
});
|
|
1200
1137
|
group.set(`${readKeyID}_for_${inviteID}`, revelationForInvite, "trusting");
|
|
1201
|
-
const groupAsInvite = expectGroup(groupCore
|
|
1202
|
-
.testWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto), Crypto.newRandomSessionID(inviteID))
|
|
1203
|
-
.getCurrentContent());
|
|
1138
|
+
const groupAsInvite = expectGroup(groupCore.contentInClonedNodeWithDifferentAccount(new ControlledAgent(inviteSecret, Crypto)));
|
|
1204
1139
|
groupAsInvite.set(`writeKeyFor_${admin.id}`, readKeyID, "trusting");
|
|
1205
1140
|
groupAsInvite.set(`writeKeyFor_${admin.id}`, "Evil change", "trusting");
|
|
1206
1141
|
expect(groupAsInvite.get(`writeKeyFor_${admin.id}`)).toEqual(readKeyID);
|
|
@@ -1223,9 +1158,7 @@ test("Can give read permission to 'everyone'", () => {
|
|
|
1223
1158
|
childContent.set("foo", "bar", "private");
|
|
1224
1159
|
expect(childContent.get("foo")).toEqual("bar");
|
|
1225
1160
|
const newAccount = new ControlledAgent(Crypto.newRandomAgentSecret(), Crypto);
|
|
1226
|
-
const childContent2 = expectMap(childObject
|
|
1227
|
-
.testWithDifferentAccount(newAccount, Crypto.newRandomSessionID(newAccount.currentAgentID()))
|
|
1228
|
-
.getCurrentContent());
|
|
1161
|
+
const childContent2 = expectMap(childObject.contentInClonedNodeWithDifferentAccount(newAccount));
|
|
1229
1162
|
expect(childContent2.get("foo")).toEqual("bar");
|
|
1230
1163
|
});
|
|
1231
1164
|
test("Can give read permissions to 'everyone' (high-level)", async () => {
|
|
@@ -1236,9 +1169,7 @@ test("Can give read permissions to 'everyone' (high-level)", async () => {
|
|
|
1236
1169
|
childObject.set("foo", "bar", "private");
|
|
1237
1170
|
expect(childObject.get("foo")).toEqual("bar");
|
|
1238
1171
|
const newAccount = new ControlledAgent(Crypto.newRandomAgentSecret(), Crypto);
|
|
1239
|
-
const childContent2 = expectMap(childObject.core
|
|
1240
|
-
.testWithDifferentAccount(new ControlledAgent(Crypto.newRandomAgentSecret(), Crypto), Crypto.newRandomSessionID(newAccount.currentAgentID()))
|
|
1241
|
-
.getCurrentContent());
|
|
1172
|
+
const childContent2 = expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(newAccount));
|
|
1242
1173
|
expect(childContent2.get("foo")).toEqual("bar");
|
|
1243
1174
|
});
|
|
1244
1175
|
test("Can give write permission to 'everyone'", async () => {
|
|
@@ -1259,9 +1190,7 @@ test("Can give write permission to 'everyone'", async () => {
|
|
|
1259
1190
|
childContent.set("foo", "bar", "private");
|
|
1260
1191
|
expect(childContent.get("foo")).toEqual("bar");
|
|
1261
1192
|
const newAccount = new ControlledAgent(Crypto.newRandomAgentSecret(), Crypto);
|
|
1262
|
-
const childContent2 = expectMap(childObject
|
|
1263
|
-
.testWithDifferentAccount(newAccount, Crypto.newRandomSessionID(newAccount.currentAgentID()))
|
|
1264
|
-
.getCurrentContent());
|
|
1193
|
+
const childContent2 = expectMap(childObject.contentInClonedNodeWithDifferentAccount(newAccount));
|
|
1265
1194
|
// TODO: resolve race condition
|
|
1266
1195
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1267
1196
|
expect(childContent2.get("foo")).toEqual("bar");
|
|
@@ -1276,9 +1205,7 @@ test("Can give write permissions to 'everyone' (high-level)", async () => {
|
|
|
1276
1205
|
childObject.set("foo", "bar", "private");
|
|
1277
1206
|
expect(childObject.get("foo")).toEqual("bar");
|
|
1278
1207
|
const newAccount = new ControlledAgent(Crypto.newRandomAgentSecret(), Crypto);
|
|
1279
|
-
const childContent2 = expectMap(childObject.core
|
|
1280
|
-
.testWithDifferentAccount(newAccount, Crypto.newRandomSessionID(newAccount.currentAgentID()))
|
|
1281
|
-
.getCurrentContent());
|
|
1208
|
+
const childContent2 = expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(newAccount));
|
|
1282
1209
|
connectTwoPeers(group.core.node, childContent2.core.node, "server", "server");
|
|
1283
1210
|
// Ensure that the group is available to newAccount
|
|
1284
1211
|
await group.core.waitForSync();
|
|
@@ -1295,39 +1222,29 @@ test("Admins can set parent extensions", () => {
|
|
|
1295
1222
|
test("Writers, readers and invitees can not set parent extensions", () => {
|
|
1296
1223
|
const { group, node } = newGroupHighLevel();
|
|
1297
1224
|
const parentGroup = node.createGroup();
|
|
1298
|
-
const writer = node
|
|
1299
|
-
const reader = node
|
|
1300
|
-
const adminInvite = node
|
|
1301
|
-
const writerInvite = node
|
|
1302
|
-
const readerInvite = node
|
|
1225
|
+
const writer = createAccountInNode(node);
|
|
1226
|
+
const reader = createAccountInNode(node);
|
|
1227
|
+
const adminInvite = createAccountInNode(node);
|
|
1228
|
+
const writerInvite = createAccountInNode(node);
|
|
1229
|
+
const readerInvite = createAccountInNode(node);
|
|
1303
1230
|
group.addMember(writer, "writer");
|
|
1304
1231
|
group.addMember(reader, "reader");
|
|
1305
1232
|
group.addMember(adminInvite, "adminInvite");
|
|
1306
1233
|
group.addMember(writerInvite, "writerInvite");
|
|
1307
1234
|
group.addMember(readerInvite, "readerInvite");
|
|
1308
|
-
const groupAsWriter = expectGroup(group.core
|
|
1309
|
-
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
|
|
1310
|
-
.getCurrentContent());
|
|
1235
|
+
const groupAsWriter = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(writer));
|
|
1311
1236
|
groupAsWriter.set(`parent_${parentGroup.id}`, "extend", "trusting");
|
|
1312
1237
|
expect(groupAsWriter.get(`parent_${parentGroup.id}`)).toBeUndefined();
|
|
1313
|
-
const groupAsReader = expectGroup(group.core
|
|
1314
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
1315
|
-
.getCurrentContent());
|
|
1238
|
+
const groupAsReader = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(reader));
|
|
1316
1239
|
groupAsReader.set(`parent_${parentGroup.id}`, "extend", "trusting");
|
|
1317
1240
|
expect(groupAsReader.get(`parent_${parentGroup.id}`)).toBeUndefined();
|
|
1318
|
-
const groupAsAdminInvite = expectGroup(group.core
|
|
1319
|
-
.testWithDifferentAccount(adminInvite, Crypto.newRandomSessionID(adminInvite.currentAgentID()))
|
|
1320
|
-
.getCurrentContent());
|
|
1241
|
+
const groupAsAdminInvite = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(adminInvite));
|
|
1321
1242
|
groupAsAdminInvite.set(`parent_${parentGroup.id}`, "extend", "trusting");
|
|
1322
1243
|
expect(groupAsAdminInvite.get(`parent_${parentGroup.id}`)).toBeUndefined();
|
|
1323
|
-
const groupAsWriterInvite = expectGroup(group.core
|
|
1324
|
-
.testWithDifferentAccount(writerInvite, Crypto.newRandomSessionID(writerInvite.currentAgentID()))
|
|
1325
|
-
.getCurrentContent());
|
|
1244
|
+
const groupAsWriterInvite = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(writerInvite));
|
|
1326
1245
|
groupAsWriterInvite.set(`parent_${parentGroup.id}`, "extend", "trusting");
|
|
1327
1246
|
expect(groupAsWriterInvite.get(`parent_${parentGroup.id}`)).toBeUndefined();
|
|
1328
|
-
const groupAsReaderInvite = expectGroup(group.core
|
|
1329
|
-
.testWithDifferentAccount(readerInvite, Crypto.newRandomSessionID(readerInvite.currentAgentID()))
|
|
1330
|
-
.getCurrentContent());
|
|
1247
|
+
const groupAsReaderInvite = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(readerInvite));
|
|
1331
1248
|
groupAsReaderInvite.set(`parent_${parentGroup.id}`, "extend", "trusting");
|
|
1332
1249
|
expect(groupAsReaderInvite.get(`parent_${parentGroup.id}`)).toBeUndefined();
|
|
1333
1250
|
});
|
|
@@ -1354,45 +1271,35 @@ test("Admins can set child extensions when the admin role is inherited", async (
|
|
|
1354
1271
|
test("Writers, readers and writeOnly can set child extensions", () => {
|
|
1355
1272
|
const { group, node } = newGroupHighLevel();
|
|
1356
1273
|
const childGroup = node.createGroup();
|
|
1357
|
-
const writer = node
|
|
1358
|
-
const reader = node
|
|
1359
|
-
const writeOnly = node
|
|
1274
|
+
const writer = createAccountInNode(node);
|
|
1275
|
+
const reader = createAccountInNode(node);
|
|
1276
|
+
const writeOnly = createAccountInNode(node);
|
|
1360
1277
|
group.addMember(writer, "writer");
|
|
1361
1278
|
group.addMember(reader, "reader");
|
|
1362
1279
|
group.addMember(writeOnly, "writeOnly");
|
|
1363
|
-
const groupAsWriter = expectGroup(group.core
|
|
1364
|
-
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
|
|
1365
|
-
.getCurrentContent());
|
|
1280
|
+
const groupAsWriter = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(writer));
|
|
1366
1281
|
groupAsWriter.set(`child_${childGroup.id}`, "extend", "trusting");
|
|
1367
1282
|
expect(groupAsWriter.get(`child_${childGroup.id}`)).toEqual("extend");
|
|
1368
|
-
const groupAsReader = expectGroup(group.core
|
|
1369
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
1370
|
-
.getCurrentContent());
|
|
1283
|
+
const groupAsReader = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(reader));
|
|
1371
1284
|
groupAsReader.set(`child_${childGroup.id}`, "extend", "trusting");
|
|
1372
1285
|
expect(groupAsReader.get(`child_${childGroup.id}`)).toEqual("extend");
|
|
1373
1286
|
});
|
|
1374
1287
|
test("Invitees can not set child extensions", () => {
|
|
1375
1288
|
const { group, node } = newGroupHighLevel();
|
|
1376
1289
|
const childGroup = node.createGroup();
|
|
1377
|
-
const adminInvite = node
|
|
1378
|
-
const writerInvite = node
|
|
1379
|
-
const readerInvite = node
|
|
1290
|
+
const adminInvite = createAccountInNode(node);
|
|
1291
|
+
const writerInvite = createAccountInNode(node);
|
|
1292
|
+
const readerInvite = createAccountInNode(node);
|
|
1380
1293
|
group.addMember(adminInvite, "adminInvite");
|
|
1381
1294
|
group.addMember(writerInvite, "writerInvite");
|
|
1382
1295
|
group.addMember(readerInvite, "readerInvite");
|
|
1383
|
-
const groupAsAdminInvite = expectGroup(group.core
|
|
1384
|
-
.testWithDifferentAccount(adminInvite, Crypto.newRandomSessionID(adminInvite.currentAgentID()))
|
|
1385
|
-
.getCurrentContent());
|
|
1296
|
+
const groupAsAdminInvite = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(adminInvite));
|
|
1386
1297
|
groupAsAdminInvite.set(`child_${childGroup.id}`, "extend", "trusting");
|
|
1387
1298
|
expect(groupAsAdminInvite.get(`child_${childGroup.id}`)).toBeUndefined();
|
|
1388
|
-
const groupAsWriterInvite = expectGroup(group.core
|
|
1389
|
-
.testWithDifferentAccount(writerInvite, Crypto.newRandomSessionID(writerInvite.currentAgentID()))
|
|
1390
|
-
.getCurrentContent());
|
|
1299
|
+
const groupAsWriterInvite = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(writerInvite));
|
|
1391
1300
|
groupAsWriterInvite.set(`child_${childGroup.id}`, "extend", "trusting");
|
|
1392
1301
|
expect(groupAsWriterInvite.get(`child_${childGroup.id}`)).toBeUndefined();
|
|
1393
|
-
const groupAsReaderInvite = expectGroup(group.core
|
|
1394
|
-
.testWithDifferentAccount(readerInvite, Crypto.newRandomSessionID(readerInvite.currentAgentID()))
|
|
1395
|
-
.getCurrentContent());
|
|
1302
|
+
const groupAsReaderInvite = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(readerInvite));
|
|
1396
1303
|
groupAsReaderInvite.set(`child_${childGroup.id}`, "extend", "trusting");
|
|
1397
1304
|
expect(groupAsReaderInvite.get(`child_${childGroup.id}`)).toBeUndefined();
|
|
1398
1305
|
});
|
|
@@ -1400,11 +1307,11 @@ test("Member roles are inherited by child groups (except invites)", () => {
|
|
|
1400
1307
|
const { group, node, admin } = newGroupHighLevel();
|
|
1401
1308
|
const parentGroup = node.createGroup();
|
|
1402
1309
|
group.set(`parent_${parentGroup.id}`, "extend", "trusting");
|
|
1403
|
-
const writer = node
|
|
1404
|
-
const reader = node
|
|
1405
|
-
const adminInvite = node
|
|
1406
|
-
const writerInvite = node
|
|
1407
|
-
const readerInvite = node
|
|
1310
|
+
const writer = createAccountInNode(node);
|
|
1311
|
+
const reader = createAccountInNode(node);
|
|
1312
|
+
const adminInvite = createAccountInNode(node);
|
|
1313
|
+
const writerInvite = createAccountInNode(node);
|
|
1314
|
+
const readerInvite = createAccountInNode(node);
|
|
1408
1315
|
parentGroup.addMember(writer, "writer");
|
|
1409
1316
|
parentGroup.addMember(reader, "reader");
|
|
1410
1317
|
parentGroup.addMember(adminInvite, "adminInvite");
|
|
@@ -1423,11 +1330,11 @@ test("Member roles are inherited by grand-children groups (except invites)", ()
|
|
|
1423
1330
|
const grandParentGroup = node.createGroup();
|
|
1424
1331
|
group.set(`parent_${parentGroup.id}`, "extend", "trusting");
|
|
1425
1332
|
parentGroup.set(`parent_${grandParentGroup.id}`, "extend", "trusting");
|
|
1426
|
-
const writer = node
|
|
1427
|
-
const reader = node
|
|
1428
|
-
const adminInvite = node
|
|
1429
|
-
const writerInvite = node
|
|
1430
|
-
const readerInvite = node
|
|
1333
|
+
const writer = createAccountInNode(node);
|
|
1334
|
+
const reader = createAccountInNode(node);
|
|
1335
|
+
const adminInvite = createAccountInNode(node);
|
|
1336
|
+
const writerInvite = createAccountInNode(node);
|
|
1337
|
+
const readerInvite = createAccountInNode(node);
|
|
1431
1338
|
grandParentGroup.addMember(writer, "writer");
|
|
1432
1339
|
grandParentGroup.addMember(reader, "reader");
|
|
1433
1340
|
grandParentGroup.addMember(adminInvite, "adminInvite");
|
|
@@ -1456,7 +1363,7 @@ test("Admins can reveal parent read keys to child groups", () => {
|
|
|
1456
1363
|
group.set(`${readKeyID}_for_${parentReadKeyID}`, encrypted, "trusting");
|
|
1457
1364
|
expect(group.get(`${readKeyID}_for_${parentReadKeyID}`)).toEqual(encrypted);
|
|
1458
1365
|
});
|
|
1459
|
-
test("Writers
|
|
1366
|
+
test("Writers can't reveal parent read keys to child groups", () => {
|
|
1460
1367
|
const { group, node } = newGroupHighLevel();
|
|
1461
1368
|
const parentGroup = node.createGroup();
|
|
1462
1369
|
const parentReadKeyID = parentGroup.get("readKey");
|
|
@@ -1469,39 +1376,85 @@ test("Writers, readers and invites can't reveal parent read keys to child groups
|
|
|
1469
1376
|
}
|
|
1470
1377
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1471
1378
|
const encrypted = "fake_encrypted_key_secret";
|
|
1472
|
-
const writer = node
|
|
1473
|
-
const reader = node.createAccount();
|
|
1474
|
-
const adminInvite = node.createAccount();
|
|
1475
|
-
const writerInvite = node.createAccount();
|
|
1476
|
-
const readerInvite = node.createAccount();
|
|
1379
|
+
const writer = createAccountInNode(node);
|
|
1477
1380
|
group.addMember(writer, "writer");
|
|
1478
|
-
group.
|
|
1479
|
-
group.addMember(adminInvite, "adminInvite");
|
|
1480
|
-
group.addMember(writerInvite, "writerInvite");
|
|
1481
|
-
group.addMember(readerInvite, "readerInvite");
|
|
1482
|
-
const groupAsWriter = expectGroup(group.core
|
|
1483
|
-
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
|
|
1484
|
-
.getCurrentContent());
|
|
1381
|
+
const groupAsWriter = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(writer));
|
|
1485
1382
|
groupAsWriter.set(`${readKeyID}_for_${parentReadKeyID}`, encrypted, "trusting");
|
|
1486
1383
|
expect(groupAsWriter.get(`${readKeyID}_for_${parentReadKeyID}`)).toBeUndefined();
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1384
|
+
});
|
|
1385
|
+
test("Readers can't reveal parent read keys to child groups", () => {
|
|
1386
|
+
const { group, node } = newGroupHighLevel();
|
|
1387
|
+
const parentGroup = node.createGroup();
|
|
1388
|
+
const parentReadKeyID = parentGroup.get("readKey");
|
|
1389
|
+
if (!parentReadKeyID) {
|
|
1390
|
+
throw new Error("Can't get parent group read key");
|
|
1391
|
+
}
|
|
1392
|
+
const readKeyID = group.get("readKey");
|
|
1393
|
+
if (!readKeyID) {
|
|
1394
|
+
throw new Error("Can't get group read key");
|
|
1395
|
+
}
|
|
1396
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1397
|
+
const encrypted = "fake_encrypted_key_secret";
|
|
1398
|
+
const reader = createAccountInNode(node);
|
|
1399
|
+
group.addMember(reader, "reader");
|
|
1400
|
+
const groupAsReader = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(reader));
|
|
1490
1401
|
groupAsReader.set(`${readKeyID}_for_${parentReadKeyID}`, encrypted, "trusting");
|
|
1491
1402
|
expect(groupAsReader.get(`${readKeyID}_for_${parentReadKeyID}`)).toBeUndefined();
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1403
|
+
});
|
|
1404
|
+
test.skip("Admin invites can't reveal parent read keys to child groups", () => {
|
|
1405
|
+
const { group, node } = newGroupHighLevel();
|
|
1406
|
+
const parentGroup = node.createGroup();
|
|
1407
|
+
const parentReadKeyID = parentGroup.get("readKey");
|
|
1408
|
+
if (!parentReadKeyID) {
|
|
1409
|
+
throw new Error("Can't get parent group read key");
|
|
1410
|
+
}
|
|
1411
|
+
const readKeyID = group.get("readKey");
|
|
1412
|
+
if (!readKeyID) {
|
|
1413
|
+
throw new Error("Can't get group read key");
|
|
1414
|
+
}
|
|
1415
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1416
|
+
const encrypted = "fake_encrypted_key_secret";
|
|
1417
|
+
const adminInvite = createAccountInNode(node);
|
|
1418
|
+
group.addMember(adminInvite, "adminInvite");
|
|
1419
|
+
const groupAsAdminInvite = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(adminInvite));
|
|
1495
1420
|
groupAsAdminInvite.set(`${readKeyID}_for_${parentReadKeyID}`, encrypted, "trusting");
|
|
1496
1421
|
expect(groupAsAdminInvite.get(`${readKeyID}_for_${parentReadKeyID}`)).toBeUndefined();
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1422
|
+
});
|
|
1423
|
+
test.skip("Writer invites can't reveal parent read keys to child groups", () => {
|
|
1424
|
+
const { group, node } = newGroupHighLevel();
|
|
1425
|
+
const parentGroup = node.createGroup();
|
|
1426
|
+
const parentReadKeyID = parentGroup.get("readKey");
|
|
1427
|
+
if (!parentReadKeyID) {
|
|
1428
|
+
throw new Error("Can't get parent group read key");
|
|
1429
|
+
}
|
|
1430
|
+
const readKeyID = group.get("readKey");
|
|
1431
|
+
if (!readKeyID) {
|
|
1432
|
+
throw new Error("Can't get group read key");
|
|
1433
|
+
}
|
|
1434
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1435
|
+
const encrypted = "fake_encrypted_key_secret";
|
|
1436
|
+
const writerInvite = createAccountInNode(node);
|
|
1437
|
+
group.addMember(writerInvite, "writerInvite");
|
|
1438
|
+
const groupAsWriterInvite = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(writerInvite));
|
|
1500
1439
|
groupAsWriterInvite.set(`${readKeyID}_for_${parentReadKeyID}`, encrypted, "trusting");
|
|
1501
1440
|
expect(groupAsWriterInvite.get(`${readKeyID}_for_${parentReadKeyID}`)).toBeUndefined();
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1441
|
+
});
|
|
1442
|
+
test.skip("Reader invites can't reveal parent read keys to child groups", () => {
|
|
1443
|
+
const { group, node } = newGroupHighLevel();
|
|
1444
|
+
const parentGroup = node.createGroup();
|
|
1445
|
+
const parentReadKeyID = parentGroup.get("readKey");
|
|
1446
|
+
if (!parentReadKeyID) {
|
|
1447
|
+
throw new Error("Can't get parent group read key");
|
|
1448
|
+
}
|
|
1449
|
+
const readKeyID = group.get("readKey");
|
|
1450
|
+
if (!readKeyID) {
|
|
1451
|
+
throw new Error("Can't get group read key");
|
|
1452
|
+
}
|
|
1453
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1454
|
+
const encrypted = "fake_encrypted_key_secret";
|
|
1455
|
+
const readerInvite = createAccountInNode(node);
|
|
1456
|
+
group.addMember(readerInvite, "readerInvite");
|
|
1457
|
+
const groupAsReaderInvite = expectGroup(group.core.contentInClonedNodeWithDifferentAccount(readerInvite));
|
|
1505
1458
|
groupAsReaderInvite.set(`${readKeyID}_for_${parentReadKeyID}`, encrypted, "trusting");
|
|
1506
1459
|
expect(groupAsReaderInvite.get(`${readKeyID}_for_${parentReadKeyID}`)).toBeUndefined();
|
|
1507
1460
|
});
|
|
@@ -1530,8 +1483,8 @@ test("Writers and readers in a parent group can read from an object owned by a c
|
|
|
1530
1483
|
},
|
|
1531
1484
|
}).encrypted;
|
|
1532
1485
|
group.set(`${readKeyID}_for_${parentReadKeyID}`, encrypted, "trusting");
|
|
1533
|
-
const writer = node
|
|
1534
|
-
const reader = node
|
|
1486
|
+
const writer = createAccountInNode(node);
|
|
1487
|
+
const reader = createAccountInNode(node);
|
|
1535
1488
|
parentGroup.addMember(writer, "writer");
|
|
1536
1489
|
parentGroup.addMember(reader, "reader");
|
|
1537
1490
|
const childObject = node.createCoValue({
|
|
@@ -1543,13 +1496,9 @@ test("Writers and readers in a parent group can read from an object owned by a c
|
|
|
1543
1496
|
const childContent = expectMap(childObject.getCurrentContent());
|
|
1544
1497
|
childContent.set("foo", "bar", "private");
|
|
1545
1498
|
expect(childContent.get("foo")).toEqual("bar");
|
|
1546
|
-
const childContentAsWriter = expectMap(childObject
|
|
1547
|
-
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
|
|
1548
|
-
.getCurrentContent());
|
|
1499
|
+
const childContentAsWriter = expectMap(childObject.contentInClonedNodeWithDifferentAccount(writer));
|
|
1549
1500
|
expect(childContentAsWriter.get("foo")).toEqual("bar");
|
|
1550
|
-
const childContentAsReader = expectMap(childObject
|
|
1551
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
1552
|
-
.getCurrentContent());
|
|
1501
|
+
const childContentAsReader = expectMap(childObject.contentInClonedNodeWithDifferentAccount(reader));
|
|
1553
1502
|
expect(childContentAsReader.get("foo")).toEqual("bar");
|
|
1554
1503
|
});
|
|
1555
1504
|
test("Writers in a parent group can write to an object owned by a child group", () => {
|
|
@@ -1577,7 +1526,7 @@ test("Writers in a parent group can write to an object owned by a child group",
|
|
|
1577
1526
|
},
|
|
1578
1527
|
}).encrypted;
|
|
1579
1528
|
group.set(`${readKeyID}_for_${parentReadKeyID}`, encrypted, "trusting");
|
|
1580
|
-
const writer = node
|
|
1529
|
+
const writer = createAccountInNode(node);
|
|
1581
1530
|
parentGroup.addMember(writer, "writer");
|
|
1582
1531
|
const childObject = node.createCoValue({
|
|
1583
1532
|
type: "comap",
|
|
@@ -1585,9 +1534,7 @@ test("Writers in a parent group can write to an object owned by a child group",
|
|
|
1585
1534
|
meta: null,
|
|
1586
1535
|
...Crypto.createdNowUnique(),
|
|
1587
1536
|
});
|
|
1588
|
-
const childContentAsWriter = expectMap(childObject
|
|
1589
|
-
.testWithDifferentAccount(writer, Crypto.newRandomSessionID(writer.id))
|
|
1590
|
-
.getCurrentContent());
|
|
1537
|
+
const childContentAsWriter = expectMap(childObject.contentInClonedNodeWithDifferentAccount(writer));
|
|
1591
1538
|
childContentAsWriter.set("foo", "bar", "private");
|
|
1592
1539
|
expect(childContentAsWriter.get("foo")).toEqual("bar");
|
|
1593
1540
|
});
|
|
@@ -1699,7 +1646,7 @@ test("Calling extend on group sets up parent and child references and reveals ch
|
|
|
1699
1646
|
throw new Error("Can't get group read key");
|
|
1700
1647
|
}
|
|
1701
1648
|
expect(group.get(`${childReadKeyID}_for_${parentReadKeyID}`)).toBeDefined();
|
|
1702
|
-
const reader = node
|
|
1649
|
+
const reader = createAccountInNode(node);
|
|
1703
1650
|
parentGroup.addMember(reader, "reader");
|
|
1704
1651
|
const childObject = node.createCoValue({
|
|
1705
1652
|
type: "comap",
|
|
@@ -1709,9 +1656,7 @@ test("Calling extend on group sets up parent and child references and reveals ch
|
|
|
1709
1656
|
});
|
|
1710
1657
|
const childMap = expectMap(childObject.getCurrentContent());
|
|
1711
1658
|
childMap.set("foo", "bar", "private");
|
|
1712
|
-
const childContentAsReader = expectMap(childObject
|
|
1713
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
1714
|
-
.getCurrentContent());
|
|
1659
|
+
const childContentAsReader = expectMap(childObject.contentInClonedNodeWithDifferentAccount(reader));
|
|
1715
1660
|
expect(childContentAsReader.get("foo")).toEqual("bar");
|
|
1716
1661
|
});
|
|
1717
1662
|
test("Calling extend to create grand-child groups parent and child references and reveals child key to parent(s)", () => {
|
|
@@ -1724,7 +1669,7 @@ test("Calling extend to create grand-child groups parent and child references an
|
|
|
1724
1669
|
expect(parentGroup.get(`parent_${grandParentGroup.id}`)).toEqual("extend");
|
|
1725
1670
|
expect(parentGroup.get(`child_${group.id}`)).toEqual("extend");
|
|
1726
1671
|
expect(grandParentGroup.get(`child_${parentGroup.id}`)).toEqual("extend");
|
|
1727
|
-
const reader = node
|
|
1672
|
+
const reader = createAccountInNode(node);
|
|
1728
1673
|
grandParentGroup.addMember(reader, "reader");
|
|
1729
1674
|
const childObject = node.createCoValue({
|
|
1730
1675
|
type: "comap",
|
|
@@ -1734,9 +1679,7 @@ test("Calling extend to create grand-child groups parent and child references an
|
|
|
1734
1679
|
});
|
|
1735
1680
|
const childMap = expectMap(childObject.getCurrentContent());
|
|
1736
1681
|
childMap.set("foo", "bar", "private");
|
|
1737
|
-
const childContentAsReader = expectMap(childObject
|
|
1738
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
1739
|
-
.getCurrentContent());
|
|
1682
|
+
const childContentAsReader = expectMap(childObject.contentInClonedNodeWithDifferentAccount(reader));
|
|
1740
1683
|
expect(childContentAsReader.get("foo")).toEqual("bar");
|
|
1741
1684
|
});
|
|
1742
1685
|
test("revoking access on a child group doesn't block access to that group if a more permissive role is inheritable", async () => {
|
|
@@ -1796,8 +1739,8 @@ test("revoking write access to parent group", async () => {
|
|
|
1796
1739
|
group.extend(parentGroup);
|
|
1797
1740
|
// Create an account (`alice`) that can write to the parent group
|
|
1798
1741
|
// Create an account (`bob`) that can write to the child group
|
|
1799
|
-
const alice = node
|
|
1800
|
-
const bob = node
|
|
1742
|
+
const alice = createAccountInNode(node);
|
|
1743
|
+
const bob = createAccountInNode(node);
|
|
1801
1744
|
parentGroup.addMember(alice, "writer");
|
|
1802
1745
|
group.addMember(bob, "writer");
|
|
1803
1746
|
// The child group has a map that can be written to by `bob`
|
|
@@ -1807,16 +1750,12 @@ test("revoking write access to parent group", async () => {
|
|
|
1807
1750
|
meta: null,
|
|
1808
1751
|
...Crypto.createdNowUnique(),
|
|
1809
1752
|
});
|
|
1810
|
-
const bobMap = expectMap(mapCore
|
|
1811
|
-
.testWithDifferentAccount(bob, Crypto.newRandomSessionID(bob.id))
|
|
1812
|
-
.getCurrentContent());
|
|
1753
|
+
const bobMap = expectMap(mapCore.contentInClonedNodeWithDifferentAccount(bob));
|
|
1813
1754
|
// `bob` sets `foo` to `bar`
|
|
1814
1755
|
bobMap.set("foo", "bar", "private");
|
|
1815
1756
|
// `bob`'s change is made successfully
|
|
1816
1757
|
expect(bobMap.get("foo")).toEqual("bar");
|
|
1817
|
-
const aliceMap = expectMap(mapCore
|
|
1818
|
-
.testWithDifferentAccount(alice, Crypto.newRandomSessionID(alice.id))
|
|
1819
|
-
.getCurrentContent());
|
|
1758
|
+
const aliceMap = expectMap(mapCore.contentInClonedNodeWithDifferentAccount(alice));
|
|
1820
1759
|
// `alice` sets `foo` to `baz`
|
|
1821
1760
|
aliceMap.set("foo", "baz", "private");
|
|
1822
1761
|
// `alice`'s change is made successfully
|
|
@@ -1827,9 +1766,7 @@ test("revoking write access to parent group", async () => {
|
|
|
1827
1766
|
bobMap.set("foo", "abc", "private");
|
|
1828
1767
|
// `bob`'s change is made successfully
|
|
1829
1768
|
expect(bobMap.get("foo")).toEqual("abc");
|
|
1830
|
-
const aliceMapAfterUnextend = expectMap(mapCore
|
|
1831
|
-
.testWithDifferentAccount(alice, Crypto.newRandomSessionID(alice.id))
|
|
1832
|
-
.getCurrentContent());
|
|
1769
|
+
const aliceMapAfterUnextend = expectMap(mapCore.contentInClonedNodeWithDifferentAccount(alice));
|
|
1833
1770
|
// `alice` attempts to set `foo` to `def`, but fails
|
|
1834
1771
|
expect(() => aliceMapAfterUnextend.set("foo", "def", "private")).toThrow("Can't make transaction without read key secret");
|
|
1835
1772
|
// `alice`'s change is not made successfully
|
|
@@ -1918,15 +1855,18 @@ test("a user should have write access if the parent group has everyone as a writ
|
|
|
1918
1855
|
group.addMember(randomUser, "reader");
|
|
1919
1856
|
const childMap = group.createMap();
|
|
1920
1857
|
childMap.set("foo", "bar", "private");
|
|
1858
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
1921
1859
|
const mapOnNode2 = await loadCoValueOrFail(node2.node, childMap.id);
|
|
1922
1860
|
mapOnNode2.set("foo", "baz", "private");
|
|
1923
|
-
|
|
1861
|
+
await waitFor(async () => {
|
|
1862
|
+
expect(mapOnNode2.get("foo")).toEqual("baz");
|
|
1863
|
+
});
|
|
1924
1864
|
});
|
|
1925
1865
|
test("High-level permissions work correctly when a group is extended", async () => {
|
|
1926
1866
|
const { group, node } = newGroupHighLevel();
|
|
1927
1867
|
const parentGroup = node.createGroup();
|
|
1928
1868
|
group.extend(parentGroup);
|
|
1929
|
-
const reader = node
|
|
1869
|
+
const reader = createAccountInNode(node);
|
|
1930
1870
|
parentGroup.addMember(reader, "reader");
|
|
1931
1871
|
const mapCore = node.createCoValue({
|
|
1932
1872
|
type: "comap",
|
|
@@ -1936,18 +1876,14 @@ test("High-level permissions work correctly when a group is extended", async ()
|
|
|
1936
1876
|
});
|
|
1937
1877
|
const map = expectMap(mapCore.getCurrentContent());
|
|
1938
1878
|
map.set("foo", "bar", "private");
|
|
1939
|
-
const mapAsReader = expectMap(mapCore
|
|
1940
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
1941
|
-
.getCurrentContent());
|
|
1879
|
+
const mapAsReader = expectMap(mapCore.contentInClonedNodeWithDifferentAccount(reader));
|
|
1942
1880
|
expect(mapAsReader.get("foo")).toEqual("bar");
|
|
1943
1881
|
const groupKeyBeforeRemove = group.core.getCurrentReadKey().id;
|
|
1944
1882
|
await parentGroup.removeMember(reader);
|
|
1945
1883
|
const groupKeyAfterRemove = group.core.getCurrentReadKey().id;
|
|
1946
1884
|
expect(groupKeyAfterRemove).not.toEqual(groupKeyBeforeRemove);
|
|
1947
1885
|
map.set("foo", "baz", "private");
|
|
1948
|
-
const mapAsReaderAfterRemove = expectMap(mapCore
|
|
1949
|
-
.testWithDifferentAccount(reader, Crypto.newRandomSessionID(reader.id))
|
|
1950
|
-
.getCurrentContent());
|
|
1886
|
+
const mapAsReaderAfterRemove = expectMap(mapCore.contentInClonedNodeWithDifferentAccount(reader));
|
|
1951
1887
|
expect(mapAsReaderAfterRemove.get("foo")).not.toEqual("baz");
|
|
1952
1888
|
});
|
|
1953
1889
|
test("self-extensions should not break the permissions checks", () => {
|
|
@@ -2004,9 +1940,7 @@ test("Can revoke read permission from 'everyone'", async () => {
|
|
|
2004
1940
|
expect(childObject.get("foo")).toEqual("bar");
|
|
2005
1941
|
// Create a new account to verify access
|
|
2006
1942
|
const newAccount = new ControlledAgent(Crypto.newRandomAgentSecret(), Crypto);
|
|
2007
|
-
const childContent = expectMap(childObject.core
|
|
2008
|
-
.testWithDifferentAccount(newAccount, Crypto.newRandomSessionID(newAccount.currentAgentID()))
|
|
2009
|
-
.getCurrentContent());
|
|
1943
|
+
const childContent = expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(newAccount));
|
|
2010
1944
|
// Verify the new account can read
|
|
2011
1945
|
expect(childContent.get("foo")).toEqual("bar");
|
|
2012
1946
|
// Revoke everyone's access
|
|
@@ -2014,9 +1948,7 @@ test("Can revoke read permission from 'everyone'", async () => {
|
|
|
2014
1948
|
childObject.set("foo", "updated after revoke", "private");
|
|
2015
1949
|
// Create another new account to verify access is revoked
|
|
2016
1950
|
const newAccount2 = new ControlledAgent(Crypto.newRandomAgentSecret(), Crypto);
|
|
2017
|
-
const childContent2 = expectMap(childObject.core
|
|
2018
|
-
.testWithDifferentAccount(newAccount2, Crypto.newRandomSessionID(newAccount2.currentAgentID()))
|
|
2019
|
-
.getCurrentContent());
|
|
1951
|
+
const childContent2 = expectMap(childObject.core.contentInClonedNodeWithDifferentAccount(newAccount2));
|
|
2020
1952
|
// Verify the new account cannot read after revocation
|
|
2021
1953
|
expect(childContent2.get("foo")).toEqual("bar");
|
|
2022
1954
|
});
|