cojson 0.8.11 → 0.8.16
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/CHANGELOG.md +94 -82
- package/dist/native/PeerKnownStates.js +1 -1
- package/dist/native/PeerKnownStates.js.map +1 -1
- package/dist/native/PeerState.js +4 -1
- package/dist/native/PeerState.js.map +1 -1
- package/dist/native/PriorityBasedMessageQueue.js +1 -10
- package/dist/native/PriorityBasedMessageQueue.js.map +1 -1
- package/dist/native/base64url.js.map +1 -1
- package/dist/native/base64url.test.js +1 -1
- package/dist/native/base64url.test.js.map +1 -1
- package/dist/native/coValue.js.map +1 -1
- package/dist/native/coValueCore.js +141 -149
- package/dist/native/coValueCore.js.map +1 -1
- package/dist/native/coValueState.js.map +1 -1
- package/dist/native/coValues/account.js +6 -6
- package/dist/native/coValues/account.js.map +1 -1
- package/dist/native/coValues/coList.js +2 -3
- package/dist/native/coValues/coList.js.map +1 -1
- package/dist/native/coValues/coMap.js +1 -1
- package/dist/native/coValues/coMap.js.map +1 -1
- package/dist/native/coValues/coStream.js +3 -5
- package/dist/native/coValues/coStream.js.map +1 -1
- package/dist/native/coValues/group.js +11 -11
- package/dist/native/coValues/group.js.map +1 -1
- package/dist/native/coreToCoValue.js +2 -2
- package/dist/native/coreToCoValue.js.map +1 -1
- package/dist/native/crypto/PureJSCrypto.js +4 -4
- package/dist/native/crypto/PureJSCrypto.js.map +1 -1
- package/dist/native/crypto/crypto.js.map +1 -1
- package/dist/native/exports.js +12 -12
- package/dist/native/exports.js.map +1 -1
- package/dist/native/ids.js.map +1 -1
- package/dist/native/jsonStringify.js.map +1 -1
- package/dist/native/localNode.js +6 -8
- package/dist/native/localNode.js.map +1 -1
- package/dist/native/permissions.js +4 -7
- package/dist/native/permissions.js.map +1 -1
- package/dist/native/priority.js.map +1 -1
- package/dist/native/storage/FileSystem.js.map +1 -1
- package/dist/native/storage/chunksAndKnownStates.js +2 -4
- package/dist/native/storage/chunksAndKnownStates.js.map +1 -1
- package/dist/native/storage/index.js +7 -16
- package/dist/native/storage/index.js.map +1 -1
- package/dist/native/streamUtils.js.map +1 -1
- package/dist/native/sync.js +6 -8
- package/dist/native/sync.js.map +1 -1
- package/dist/native/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
- package/dist/native/typeUtils/expectGroup.js.map +1 -1
- package/dist/native/typeUtils/isAccountID.js.map +1 -1
- package/dist/native/typeUtils/isCoValue.js +1 -1
- package/dist/native/typeUtils/isCoValue.js.map +1 -1
- package/dist/web/PeerKnownStates.js +1 -1
- package/dist/web/PeerKnownStates.js.map +1 -1
- package/dist/web/PeerState.js +4 -1
- package/dist/web/PeerState.js.map +1 -1
- package/dist/web/PriorityBasedMessageQueue.js +1 -10
- package/dist/web/PriorityBasedMessageQueue.js.map +1 -1
- package/dist/web/base64url.js.map +1 -1
- package/dist/web/base64url.test.js +1 -1
- package/dist/web/base64url.test.js.map +1 -1
- package/dist/web/coValue.js.map +1 -1
- package/dist/web/coValueCore.js +141 -149
- package/dist/web/coValueCore.js.map +1 -1
- package/dist/web/coValueState.js.map +1 -1
- package/dist/web/coValues/account.js +6 -6
- package/dist/web/coValues/account.js.map +1 -1
- package/dist/web/coValues/coList.js +2 -3
- package/dist/web/coValues/coList.js.map +1 -1
- package/dist/web/coValues/coMap.js +1 -1
- package/dist/web/coValues/coMap.js.map +1 -1
- package/dist/web/coValues/coStream.js +3 -5
- package/dist/web/coValues/coStream.js.map +1 -1
- package/dist/web/coValues/group.js +11 -11
- package/dist/web/coValues/group.js.map +1 -1
- package/dist/web/coreToCoValue.js +2 -2
- package/dist/web/coreToCoValue.js.map +1 -1
- package/dist/web/crypto/PureJSCrypto.js +4 -4
- package/dist/web/crypto/PureJSCrypto.js.map +1 -1
- package/dist/web/crypto/WasmCrypto.js +5 -5
- package/dist/web/crypto/WasmCrypto.js.map +1 -1
- package/dist/web/crypto/crypto.js.map +1 -1
- package/dist/web/exports.js +12 -12
- package/dist/web/exports.js.map +1 -1
- package/dist/web/ids.js.map +1 -1
- package/dist/web/jsonStringify.js.map +1 -1
- package/dist/web/localNode.js +6 -8
- package/dist/web/localNode.js.map +1 -1
- package/dist/web/permissions.js +4 -7
- package/dist/web/permissions.js.map +1 -1
- package/dist/web/priority.js.map +1 -1
- package/dist/web/storage/FileSystem.js.map +1 -1
- package/dist/web/storage/chunksAndKnownStates.js +2 -4
- package/dist/web/storage/chunksAndKnownStates.js.map +1 -1
- package/dist/web/storage/index.js +7 -16
- package/dist/web/storage/index.js.map +1 -1
- package/dist/web/streamUtils.js.map +1 -1
- package/dist/web/sync.js +6 -8
- package/dist/web/sync.js.map +1 -1
- package/dist/web/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
- package/dist/web/typeUtils/expectGroup.js.map +1 -1
- package/dist/web/typeUtils/isAccountID.js.map +1 -1
- package/dist/web/typeUtils/isCoValue.js +1 -1
- package/dist/web/typeUtils/isCoValue.js.map +1 -1
- package/package.json +4 -14
- package/src/PeerKnownStates.ts +91 -89
- package/src/PeerState.ts +72 -69
- package/src/PriorityBasedMessageQueue.ts +42 -49
- package/src/base64url.test.ts +24 -24
- package/src/base64url.ts +44 -45
- package/src/coValue.ts +45 -45
- package/src/coValueCore.ts +746 -785
- package/src/coValueState.ts +82 -72
- package/src/coValues/account.ts +143 -150
- package/src/coValues/coList.ts +520 -522
- package/src/coValues/coMap.ts +283 -285
- package/src/coValues/coStream.ts +320 -324
- package/src/coValues/group.ts +306 -305
- package/src/coreToCoValue.ts +28 -31
- package/src/crypto/PureJSCrypto.ts +188 -194
- package/src/crypto/WasmCrypto.ts +236 -254
- package/src/crypto/crypto.ts +302 -309
- package/src/exports.ts +116 -116
- package/src/ids.ts +9 -9
- package/src/jsonStringify.ts +46 -46
- package/src/jsonValue.ts +24 -10
- package/src/localNode.ts +635 -660
- package/src/media.ts +3 -3
- package/src/permissions.ts +272 -278
- package/src/priority.ts +21 -19
- package/src/storage/FileSystem.ts +91 -99
- package/src/storage/chunksAndKnownStates.ts +110 -115
- package/src/storage/index.ts +466 -497
- package/src/streamUtils.ts +60 -60
- package/src/sync.ts +593 -615
- package/src/tests/PeerKnownStates.test.ts +38 -34
- package/src/tests/PeerState.test.ts +101 -64
- package/src/tests/PriorityBasedMessageQueue.test.ts +91 -91
- package/src/tests/account.test.ts +59 -59
- package/src/tests/coList.test.ts +65 -65
- package/src/tests/coMap.test.ts +137 -137
- package/src/tests/coStream.test.ts +254 -257
- package/src/tests/coValueCore.test.ts +153 -156
- package/src/tests/crypto.test.ts +136 -144
- package/src/tests/cryptoImpl.test.ts +205 -197
- package/src/tests/group.test.ts +24 -24
- package/src/tests/permissions.test.ts +1306 -1371
- package/src/tests/priority.test.ts +65 -82
- package/src/tests/sync.test.ts +1300 -1291
- package/src/tests/testUtils.ts +52 -53
- package/src/typeUtils/accountOrAgentIDfromSessionID.ts +4 -4
- package/src/typeUtils/expectGroup.ts +9 -9
- package/src/typeUtils/isAccountID.ts +1 -1
- package/src/typeUtils/isCoValue.ts +9 -9
- package/tsconfig.json +4 -6
- package/tsconfig.native.json +9 -11
- package/tsconfig.web.json +4 -10
- package/.eslintrc.cjs +0 -25
- package/.prettierrc.js +0 -9
package/src/media.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { RawCoMap } from "./coValues/coMap.js";
|
|
|
2
2
|
import { RawBinaryCoStream } from "./coValues/coStream.js";
|
|
3
3
|
|
|
4
4
|
export type ImageDefinition = RawCoMap<{
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
originalSize: [number, number];
|
|
6
|
+
placeholderDataURL?: string;
|
|
7
|
+
[res: `${number}x${number}`]: RawBinaryCoStream["id"];
|
|
8
8
|
}>;
|
package/src/permissions.ts
CHANGED
|
@@ -1,312 +1,306 @@
|
|
|
1
1
|
import { CoID } from "./coValue.js";
|
|
2
|
+
import { CoValueCore, Transaction } from "./coValueCore.js";
|
|
3
|
+
import { RawAccount, RawAccountID, RawProfile } from "./coValues/account.js";
|
|
2
4
|
import { MapOpPayload } from "./coValues/coMap.js";
|
|
3
|
-
import {
|
|
5
|
+
import { EVERYONE, Everyone } from "./coValues/group.js";
|
|
4
6
|
import { KeyID } from "./crypto/crypto.js";
|
|
5
|
-
import { CoValueCore, Transaction } from "./coValueCore.js";
|
|
6
|
-
import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromSessionID.js";
|
|
7
7
|
import { AgentID, RawCoID, SessionID, TransactionID } from "./ids.js";
|
|
8
|
-
import { RawAccount, RawAccountID, RawProfile } from "./coValues/account.js";
|
|
9
8
|
import { parseJSON } from "./jsonStringify.js";
|
|
10
|
-
import {
|
|
9
|
+
import { JsonValue } from "./jsonValue.js";
|
|
10
|
+
import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromSessionID.js";
|
|
11
11
|
import { expectGroup } from "./typeUtils/expectGroup.js";
|
|
12
12
|
|
|
13
13
|
export type PermissionsDef =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
| { type: "group"; initialAdmin: RawAccountID | AgentID }
|
|
15
|
+
| { type: "ownedByGroup"; group: RawCoID }
|
|
16
|
+
| { type: "unsafeAllowAll" };
|
|
17
17
|
|
|
18
18
|
export type Role =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
| "reader"
|
|
20
|
+
| "writer"
|
|
21
|
+
| "admin"
|
|
22
|
+
| "revoked"
|
|
23
|
+
| "adminInvite"
|
|
24
|
+
| "writerInvite"
|
|
25
|
+
| "readerInvite";
|
|
26
26
|
|
|
27
27
|
export function determineValidTransactions(
|
|
28
|
-
|
|
28
|
+
coValue: CoValueCore,
|
|
29
29
|
): { txID: TransactionID; tx: Transaction }[] {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
allTransactionsSorted.sort((a, b) => {
|
|
46
|
-
return a.tx.madeAt - b.tx.madeAt;
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const initialAdmin = coValue.header.ruleset.initialAdmin;
|
|
50
|
-
|
|
51
|
-
if (!initialAdmin) {
|
|
52
|
-
throw new Error("Group must have initialAdmin");
|
|
53
|
-
}
|
|
30
|
+
if (coValue.header.ruleset.type === "group") {
|
|
31
|
+
const allTransactionsSorted = [...coValue.sessionLogs.entries()].flatMap(
|
|
32
|
+
([sessionID, sessionLog]) => {
|
|
33
|
+
return sessionLog.transactions.map((tx, txIndex) => ({
|
|
34
|
+
sessionID,
|
|
35
|
+
txIndex,
|
|
36
|
+
tx,
|
|
37
|
+
})) as {
|
|
38
|
+
sessionID: SessionID;
|
|
39
|
+
txIndex: number;
|
|
40
|
+
tx: Transaction;
|
|
41
|
+
}[];
|
|
42
|
+
},
|
|
43
|
+
);
|
|
54
44
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
} = {};
|
|
59
|
-
|
|
60
|
-
const validTransactions: { txID: TransactionID; tx: Transaction }[] =
|
|
61
|
-
[];
|
|
62
|
-
|
|
63
|
-
for (const { sessionID, txIndex, tx } of allTransactionsSorted) {
|
|
64
|
-
// console.log("before", { memberState, validTransactions });
|
|
65
|
-
const transactor = accountOrAgentIDfromSessionID(sessionID);
|
|
66
|
-
|
|
67
|
-
if (tx.privacy === "private") {
|
|
68
|
-
if (memberState[transactor] === "admin") {
|
|
69
|
-
validTransactions.push({
|
|
70
|
-
txID: { sessionID, txIndex },
|
|
71
|
-
tx,
|
|
72
|
-
});
|
|
73
|
-
continue;
|
|
74
|
-
} else {
|
|
75
|
-
console.warn(
|
|
76
|
-
"Only admins can make private transactions in groups",
|
|
77
|
-
);
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
45
|
+
allTransactionsSorted.sort((a, b) => {
|
|
46
|
+
return a.tx.madeAt - b.tx.madeAt;
|
|
47
|
+
});
|
|
81
48
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
changes = parseJSON(tx.changes);
|
|
86
|
-
} catch (e) {
|
|
87
|
-
console.warn(
|
|
88
|
-
coValue.id,
|
|
89
|
-
"Invalid JSON in transaction",
|
|
90
|
-
e,
|
|
91
|
-
tx,
|
|
92
|
-
JSON.stringify(tx.changes, (k, v) =>
|
|
93
|
-
k === "changes" || k === "encryptedChanges"
|
|
94
|
-
? v.slice(0, 20) + "..."
|
|
95
|
-
: v,
|
|
96
|
-
),
|
|
97
|
-
);
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
49
|
+
const initialAdmin = coValue.header.ruleset.initialAdmin;
|
|
100
50
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
| MapOpPayload<"profile", CoID<RawProfile>>;
|
|
105
|
-
if (changes.length !== 1) {
|
|
106
|
-
console.warn("Group transaction must have exactly one change");
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
51
|
+
if (!initialAdmin) {
|
|
52
|
+
throw new Error("Group must have initialAdmin");
|
|
53
|
+
}
|
|
109
54
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
55
|
+
const memberState: {
|
|
56
|
+
[agent: RawAccountID | AgentID]: Role;
|
|
57
|
+
[EVERYONE]?: Role;
|
|
58
|
+
} = {};
|
|
59
|
+
|
|
60
|
+
const validTransactions: { txID: TransactionID; tx: Transaction }[] = [];
|
|
61
|
+
|
|
62
|
+
for (const { sessionID, txIndex, tx } of allTransactionsSorted) {
|
|
63
|
+
// console.log("before", { memberState, validTransactions });
|
|
64
|
+
const transactor = accountOrAgentIDfromSessionID(sessionID);
|
|
65
|
+
|
|
66
|
+
if (tx.privacy === "private") {
|
|
67
|
+
if (memberState[transactor] === "admin") {
|
|
68
|
+
validTransactions.push({
|
|
69
|
+
txID: { sessionID, txIndex },
|
|
70
|
+
tx,
|
|
71
|
+
});
|
|
72
|
+
continue;
|
|
73
|
+
} else {
|
|
74
|
+
console.warn("Only admins can make private transactions in groups");
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let changes;
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
changes = parseJSON(tx.changes);
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.warn(
|
|
85
|
+
coValue.id,
|
|
86
|
+
"Invalid JSON in transaction",
|
|
87
|
+
e,
|
|
88
|
+
tx,
|
|
89
|
+
JSON.stringify(tx.changes, (k, v) =>
|
|
90
|
+
k === "changes" || k === "encryptedChanges"
|
|
91
|
+
? v.slice(0, 20) + "..."
|
|
92
|
+
: v,
|
|
93
|
+
),
|
|
94
|
+
);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const change = changes[0] as
|
|
99
|
+
| MapOpPayload<RawAccountID | AgentID | Everyone, Role>
|
|
100
|
+
| MapOpPayload<"readKey", JsonValue>
|
|
101
|
+
| MapOpPayload<"profile", CoID<RawProfile>>;
|
|
102
|
+
if (changes.length !== 1) {
|
|
103
|
+
console.warn("Group transaction must have exactly one change");
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (change.op !== "set") {
|
|
108
|
+
console.warn("Group transaction must set a role or readKey");
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (change.key === "readKey") {
|
|
113
|
+
if (memberState[transactor] !== "admin") {
|
|
114
|
+
console.warn("Only admins can set readKeys");
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
114
117
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
continue;
|
|
123
|
-
} else if (change.key === "profile") {
|
|
124
|
-
if (memberState[transactor] !== "admin") {
|
|
125
|
-
console.warn("Only admins can set profile");
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
validTransactions.push({ txID: { sessionID, txIndex }, tx });
|
|
130
|
-
continue;
|
|
131
|
-
} else if (
|
|
132
|
-
isKeyForKeyField(change.key) ||
|
|
133
|
-
isKeyForAccountField(change.key)
|
|
134
|
-
) {
|
|
135
|
-
if (
|
|
136
|
-
memberState[transactor] !== "admin" &&
|
|
137
|
-
memberState[transactor] !== "adminInvite" &&
|
|
138
|
-
memberState[transactor] !== "writerInvite" &&
|
|
139
|
-
memberState[transactor] !== "readerInvite"
|
|
140
|
-
) {
|
|
141
|
-
console.warn("Only admins can reveal keys");
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// TODO: check validity of agents who the key is revealed to?
|
|
146
|
-
|
|
147
|
-
validTransactions.push({ txID: { sessionID, txIndex }, tx });
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
118
|
+
validTransactions.push({ txID: { sessionID, txIndex }, tx });
|
|
119
|
+
continue;
|
|
120
|
+
} else if (change.key === "profile") {
|
|
121
|
+
if (memberState[transactor] !== "admin") {
|
|
122
|
+
console.warn("Only admins can set profile");
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
150
125
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
126
|
+
validTransactions.push({ txID: { sessionID, txIndex }, tx });
|
|
127
|
+
continue;
|
|
128
|
+
} else if (
|
|
129
|
+
isKeyForKeyField(change.key) ||
|
|
130
|
+
isKeyForAccountField(change.key)
|
|
131
|
+
) {
|
|
132
|
+
if (
|
|
133
|
+
memberState[transactor] !== "admin" &&
|
|
134
|
+
memberState[transactor] !== "adminInvite" &&
|
|
135
|
+
memberState[transactor] !== "writerInvite" &&
|
|
136
|
+
memberState[transactor] !== "readerInvite"
|
|
137
|
+
) {
|
|
138
|
+
console.warn("Only admins can reveal keys");
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
166
141
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
142
|
+
// TODO: check validity of agents who the key is revealed to?
|
|
143
|
+
|
|
144
|
+
validTransactions.push({ txID: { sessionID, txIndex }, tx });
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const affectedMember = change.key;
|
|
149
|
+
const assignedRole = change.value;
|
|
150
|
+
|
|
151
|
+
if (
|
|
152
|
+
change.value !== "admin" &&
|
|
153
|
+
change.value !== "writer" &&
|
|
154
|
+
change.value !== "reader" &&
|
|
155
|
+
change.value !== "revoked" &&
|
|
156
|
+
change.value !== "adminInvite" &&
|
|
157
|
+
change.value !== "writerInvite" &&
|
|
158
|
+
change.value !== "readerInvite"
|
|
159
|
+
) {
|
|
160
|
+
console.warn("Group transaction must set a valid role");
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (
|
|
165
|
+
affectedMember === EVERYONE &&
|
|
166
|
+
!(
|
|
167
|
+
change.value === "reader" ||
|
|
168
|
+
change.value === "writer" ||
|
|
169
|
+
change.value === "revoked"
|
|
170
|
+
)
|
|
171
|
+
) {
|
|
172
|
+
console.warn("Everyone can only be set to reader, writer or revoked");
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const isFirstSelfAppointment =
|
|
177
|
+
!memberState[transactor] &&
|
|
178
|
+
transactor === initialAdmin &&
|
|
179
|
+
change.op === "set" &&
|
|
180
|
+
change.key === transactor &&
|
|
181
|
+
change.value === "admin";
|
|
182
|
+
|
|
183
|
+
if (!isFirstSelfAppointment) {
|
|
184
|
+
if (memberState[transactor] === "admin") {
|
|
185
|
+
if (
|
|
186
|
+
memberState[affectedMember] === "admin" &&
|
|
187
|
+
affectedMember !== transactor &&
|
|
188
|
+
assignedRole !== "admin"
|
|
189
|
+
) {
|
|
190
|
+
console.warn("Admins can only demote themselves.");
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
} else if (memberState[transactor] === "adminInvite") {
|
|
194
|
+
if (change.value !== "admin") {
|
|
195
|
+
console.warn("AdminInvites can only create admins.");
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
} else if (memberState[transactor] === "writerInvite") {
|
|
199
|
+
if (change.value !== "writer") {
|
|
200
|
+
console.warn("WriterInvites can only create writers.");
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
} else if (memberState[transactor] === "readerInvite") {
|
|
204
|
+
if (change.value !== "reader") {
|
|
205
|
+
console.warn("ReaderInvites can only create reader.");
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
console.warn(
|
|
210
|
+
"Group transaction must be made by current admin or invite",
|
|
211
|
+
);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
180
215
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
transactor === initialAdmin &&
|
|
184
|
-
change.op === "set" &&
|
|
185
|
-
change.key === transactor &&
|
|
186
|
-
change.value === "admin";
|
|
187
|
-
|
|
188
|
-
if (!isFirstSelfAppointment) {
|
|
189
|
-
if (memberState[transactor] === "admin") {
|
|
190
|
-
if (
|
|
191
|
-
memberState[affectedMember] === "admin" &&
|
|
192
|
-
affectedMember !== transactor &&
|
|
193
|
-
assignedRole !== "admin"
|
|
194
|
-
) {
|
|
195
|
-
console.warn("Admins can only demote themselves.");
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
} else if (memberState[transactor] === "adminInvite") {
|
|
199
|
-
if (change.value !== "admin") {
|
|
200
|
-
console.warn("AdminInvites can only create admins.");
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
} else if (memberState[transactor] === "writerInvite") {
|
|
204
|
-
if (change.value !== "writer") {
|
|
205
|
-
console.warn("WriterInvites can only create writers.");
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
} else if (memberState[transactor] === "readerInvite") {
|
|
209
|
-
if (change.value !== "reader") {
|
|
210
|
-
console.warn("ReaderInvites can only create reader.");
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
} else {
|
|
214
|
-
console.warn(
|
|
215
|
-
"Group transaction must be made by current admin or invite",
|
|
216
|
-
);
|
|
217
|
-
continue;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
216
|
+
memberState[affectedMember] = change.value;
|
|
217
|
+
validTransactions.push({ txID: { sessionID, txIndex }, tx });
|
|
220
218
|
|
|
221
|
-
|
|
222
|
-
|
|
219
|
+
// console.log("after", { memberState, validTransactions });
|
|
220
|
+
}
|
|
223
221
|
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
return validTransactions;
|
|
223
|
+
} else if (coValue.header.ruleset.type === "ownedByGroup") {
|
|
224
|
+
const groupContent = expectGroup(
|
|
225
|
+
coValue.node
|
|
226
|
+
.expectCoValueLoaded(
|
|
227
|
+
coValue.header.ruleset.group,
|
|
228
|
+
"Determining valid transaction in owned object but its group wasn't loaded",
|
|
229
|
+
)
|
|
230
|
+
.getCurrentContent(),
|
|
231
|
+
);
|
|
226
232
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
coValue.node
|
|
231
|
-
.expectCoValueLoaded(
|
|
232
|
-
coValue.header.ruleset.group,
|
|
233
|
-
"Determining valid transaction in owned object but its group wasn't loaded",
|
|
234
|
-
)
|
|
235
|
-
.getCurrentContent(),
|
|
236
|
-
);
|
|
233
|
+
if (groupContent.type !== "comap") {
|
|
234
|
+
throw new Error("Group must be a map");
|
|
235
|
+
}
|
|
237
236
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
237
|
+
return [...coValue.sessionLogs.entries()].flatMap(
|
|
238
|
+
([sessionID, sessionLog]) => {
|
|
239
|
+
const transactor = accountOrAgentIDfromSessionID(sessionID);
|
|
240
|
+
|
|
241
|
+
return sessionLog.transactions
|
|
242
|
+
.filter((tx) => {
|
|
243
|
+
const groupAtTime = groupContent.atTime(tx.madeAt);
|
|
244
|
+
const effectiveTransactor =
|
|
245
|
+
transactor === groupContent.id &&
|
|
246
|
+
groupAtTime instanceof RawAccount
|
|
247
|
+
? groupAtTime.currentAgentID().match(
|
|
248
|
+
(agentID) => agentID,
|
|
249
|
+
(e) => {
|
|
250
|
+
console.error(
|
|
251
|
+
"Error while determining current agent ID in valid transactions",
|
|
252
|
+
e,
|
|
253
|
+
);
|
|
254
|
+
return undefined;
|
|
255
|
+
},
|
|
256
|
+
)
|
|
257
|
+
: transactor;
|
|
258
|
+
|
|
259
|
+
if (!effectiveTransactor) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
241
262
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return (
|
|
273
|
-
transactorRoleAtTxTime === "admin" ||
|
|
274
|
-
transactorRoleAtTxTime === "writer"
|
|
275
|
-
);
|
|
276
|
-
})
|
|
277
|
-
.map((tx, txIndex) => ({
|
|
278
|
-
txID: { sessionID: sessionID, txIndex },
|
|
279
|
-
tx,
|
|
280
|
-
}));
|
|
281
|
-
},
|
|
282
|
-
);
|
|
283
|
-
} else if (coValue.header.ruleset.type === "unsafeAllowAll") {
|
|
284
|
-
return [...coValue.sessionLogs.entries()].flatMap(
|
|
285
|
-
([sessionID, sessionLog]) => {
|
|
286
|
-
return sessionLog.transactions.map((tx, txIndex) => ({
|
|
287
|
-
txID: { sessionID: sessionID, txIndex },
|
|
288
|
-
tx,
|
|
289
|
-
}));
|
|
290
|
-
},
|
|
291
|
-
);
|
|
292
|
-
} else {
|
|
293
|
-
throw new Error(
|
|
294
|
-
"Unknown ruleset type " +
|
|
295
|
-
(coValue.header.ruleset as { type: string }).type,
|
|
296
|
-
);
|
|
297
|
-
}
|
|
263
|
+
const transactorRoleAtTxTime =
|
|
264
|
+
groupAtTime.get(effectiveTransactor) || groupAtTime.get(EVERYONE);
|
|
265
|
+
|
|
266
|
+
return (
|
|
267
|
+
transactorRoleAtTxTime === "admin" ||
|
|
268
|
+
transactorRoleAtTxTime === "writer"
|
|
269
|
+
);
|
|
270
|
+
})
|
|
271
|
+
.map((tx, txIndex) => ({
|
|
272
|
+
txID: { sessionID: sessionID, txIndex },
|
|
273
|
+
tx,
|
|
274
|
+
}));
|
|
275
|
+
},
|
|
276
|
+
);
|
|
277
|
+
} else if (coValue.header.ruleset.type === "unsafeAllowAll") {
|
|
278
|
+
return [...coValue.sessionLogs.entries()].flatMap(
|
|
279
|
+
([sessionID, sessionLog]) => {
|
|
280
|
+
return sessionLog.transactions.map((tx, txIndex) => ({
|
|
281
|
+
txID: { sessionID: sessionID, txIndex },
|
|
282
|
+
tx,
|
|
283
|
+
}));
|
|
284
|
+
},
|
|
285
|
+
);
|
|
286
|
+
} else {
|
|
287
|
+
throw new Error(
|
|
288
|
+
"Unknown ruleset type " +
|
|
289
|
+
(coValue.header.ruleset as { type: string }).type,
|
|
290
|
+
);
|
|
291
|
+
}
|
|
298
292
|
}
|
|
299
293
|
|
|
300
294
|
export function isKeyForKeyField(co: string): co is `${KeyID}_for_${KeyID}` {
|
|
301
|
-
|
|
295
|
+
return co.startsWith("key_") && co.includes("_for_key");
|
|
302
296
|
}
|
|
303
297
|
|
|
304
298
|
export function isKeyForAccountField(
|
|
305
|
-
|
|
299
|
+
co: string,
|
|
306
300
|
): co is `${KeyID}_for_${RawAccountID | AgentID}` {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
301
|
+
return (
|
|
302
|
+
(co.startsWith("key_") &&
|
|
303
|
+
(co.includes("_for_sealer") || co.includes("_for_co"))) ||
|
|
304
|
+
co.includes("_for_everyone")
|
|
305
|
+
);
|
|
312
306
|
}
|
package/src/priority.ts
CHANGED
|
@@ -3,37 +3,39 @@ import { type CoValueHeader } from "./coValueCore.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* The priority of a `CoValue` determines how much priority is given
|
|
5
5
|
* to its content messages.
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* The priority value is handled as weight in the weighed round robin algorithm
|
|
8
8
|
* used to determine the order in which messages are sent.
|
|
9
|
-
*
|
|
9
|
+
*
|
|
10
10
|
* Follows the HTTP urgency range and order:
|
|
11
11
|
* - https://www.rfc-editor.org/rfc/rfc9218.html#name-urgency
|
|
12
12
|
*/
|
|
13
13
|
export const CO_VALUE_PRIORITY = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
HIGH: 0,
|
|
15
|
+
MEDIUM: 3,
|
|
16
|
+
LOW: 6,
|
|
17
17
|
} as const;
|
|
18
18
|
|
|
19
19
|
export type CoValuePriority = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
|
20
20
|
|
|
21
|
-
export function getPriorityFromHeader(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
export function getPriorityFromHeader(
|
|
22
|
+
header: CoValueHeader | undefined | boolean,
|
|
23
|
+
): CoValuePriority {
|
|
24
|
+
if (typeof header === "boolean" || !header) {
|
|
25
|
+
return CO_VALUE_PRIORITY.MEDIUM;
|
|
26
|
+
}
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
if (header.meta?.type === "account") {
|
|
29
|
+
return CO_VALUE_PRIORITY.HIGH;
|
|
30
|
+
}
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
if (header.ruleset.type === "group") {
|
|
33
|
+
return CO_VALUE_PRIORITY.HIGH;
|
|
34
|
+
}
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
if (header.type === "costream" && header.meta?.type === "binary") {
|
|
37
|
+
return CO_VALUE_PRIORITY.LOW;
|
|
38
|
+
}
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
return CO_VALUE_PRIORITY.MEDIUM;
|
|
39
41
|
}
|