@liveblocks/core 3.21.0-private1 → 3.21.0-private2
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/dist/index.cjs +239 -327
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -17
- package/dist/index.d.ts +24 -17
- package/dist/index.js +210 -298
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ var __export = (target, all) => {
|
|
|
6
6
|
|
|
7
7
|
// src/version.ts
|
|
8
8
|
var PKG_NAME = "@liveblocks/core";
|
|
9
|
-
var PKG_VERSION = "3.21.0-
|
|
9
|
+
var PKG_VERSION = "3.21.0-private2";
|
|
10
10
|
var PKG_FORMAT = "esm";
|
|
11
11
|
|
|
12
12
|
// src/dupe-detection.ts
|
|
@@ -1718,7 +1718,7 @@ function createApiClient({
|
|
|
1718
1718
|
url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}`,
|
|
1719
1719
|
await authManager.getAuthValue({
|
|
1720
1720
|
roomId: options.roomId,
|
|
1721
|
-
resource:
|
|
1721
|
+
resource: commentsResourceForVisibility(options.visibility),
|
|
1722
1722
|
access: "write"
|
|
1723
1723
|
})
|
|
1724
1724
|
);
|
|
@@ -1756,7 +1756,7 @@ function createApiClient({
|
|
|
1756
1756
|
url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/metadata`,
|
|
1757
1757
|
await authManager.getAuthValue({
|
|
1758
1758
|
roomId: options.roomId,
|
|
1759
|
-
resource:
|
|
1759
|
+
resource: commentsResourceForVisibility(options.visibility),
|
|
1760
1760
|
access: "write"
|
|
1761
1761
|
}),
|
|
1762
1762
|
options.metadata
|
|
@@ -1767,7 +1767,7 @@ function createApiClient({
|
|
|
1767
1767
|
url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments/${options.commentId}/metadata`,
|
|
1768
1768
|
await authManager.getAuthValue({
|
|
1769
1769
|
roomId: options.roomId,
|
|
1770
|
-
resource:
|
|
1770
|
+
resource: commentsResourceForVisibility(options.visibility),
|
|
1771
1771
|
access: "write"
|
|
1772
1772
|
}),
|
|
1773
1773
|
options.metadata
|
|
@@ -1779,7 +1779,7 @@ function createApiClient({
|
|
|
1779
1779
|
url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments`,
|
|
1780
1780
|
await authManager.getAuthValue({
|
|
1781
1781
|
roomId: options.roomId,
|
|
1782
|
-
resource:
|
|
1782
|
+
resource: commentsResourceForVisibility(options.visibility),
|
|
1783
1783
|
access: "write"
|
|
1784
1784
|
}),
|
|
1785
1785
|
{
|
|
@@ -1796,7 +1796,7 @@ function createApiClient({
|
|
|
1796
1796
|
url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments/${options.commentId}`,
|
|
1797
1797
|
await authManager.getAuthValue({
|
|
1798
1798
|
roomId: options.roomId,
|
|
1799
|
-
resource:
|
|
1799
|
+
resource: commentsResourceForVisibility(options.visibility),
|
|
1800
1800
|
access: "write"
|
|
1801
1801
|
}),
|
|
1802
1802
|
{
|
|
@@ -1812,7 +1812,7 @@ function createApiClient({
|
|
|
1812
1812
|
url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments/${options.commentId}`,
|
|
1813
1813
|
await authManager.getAuthValue({
|
|
1814
1814
|
roomId: options.roomId,
|
|
1815
|
-
resource:
|
|
1815
|
+
resource: commentsResourceForVisibility(options.visibility),
|
|
1816
1816
|
access: "write"
|
|
1817
1817
|
})
|
|
1818
1818
|
);
|
|
@@ -1822,7 +1822,7 @@ function createApiClient({
|
|
|
1822
1822
|
url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments/${options.commentId}/reactions`,
|
|
1823
1823
|
await authManager.getAuthValue({
|
|
1824
1824
|
roomId: options.roomId,
|
|
1825
|
-
resource:
|
|
1825
|
+
resource: commentsResourceForVisibility(options.visibility),
|
|
1826
1826
|
access: "write"
|
|
1827
1827
|
}),
|
|
1828
1828
|
{ emoji: options.emoji }
|
|
@@ -1834,7 +1834,7 @@ function createApiClient({
|
|
|
1834
1834
|
url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/comments/${options.commentId}/reactions/${options.emoji}`,
|
|
1835
1835
|
await authManager.getAuthValue({
|
|
1836
1836
|
roomId: options.roomId,
|
|
1837
|
-
resource:
|
|
1837
|
+
resource: commentsResourceForVisibility(options.visibility),
|
|
1838
1838
|
access: "write"
|
|
1839
1839
|
})
|
|
1840
1840
|
);
|
|
@@ -1844,7 +1844,7 @@ function createApiClient({
|
|
|
1844
1844
|
url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/mark-as-resolved`,
|
|
1845
1845
|
await authManager.getAuthValue({
|
|
1846
1846
|
roomId: options.roomId,
|
|
1847
|
-
resource:
|
|
1847
|
+
resource: commentsResourceForVisibility(options.visibility),
|
|
1848
1848
|
access: "write"
|
|
1849
1849
|
})
|
|
1850
1850
|
);
|
|
@@ -1854,7 +1854,7 @@ function createApiClient({
|
|
|
1854
1854
|
url`/v2/c/rooms/${options.roomId}/threads/${options.threadId}/mark-as-unresolved`,
|
|
1855
1855
|
await authManager.getAuthValue({
|
|
1856
1856
|
roomId: options.roomId,
|
|
1857
|
-
resource:
|
|
1857
|
+
resource: commentsResourceForVisibility(options.visibility),
|
|
1858
1858
|
access: "write"
|
|
1859
1859
|
})
|
|
1860
1860
|
);
|
|
@@ -5207,9 +5207,6 @@ var Permission = {
|
|
|
5207
5207
|
CommentsPrivateWrite: "comments:private:write",
|
|
5208
5208
|
CommentsPrivateRead: "comments:private:read",
|
|
5209
5209
|
CommentsPrivateNone: "comments:private:none",
|
|
5210
|
-
CommentsPersonalWrite: "comments:personal:write",
|
|
5211
|
-
CommentsPersonalRead: "comments:personal:read",
|
|
5212
|
-
CommentsPersonalNone: "comments:personal:none",
|
|
5213
5210
|
/**
|
|
5214
5211
|
* Feeds
|
|
5215
5212
|
*/
|
|
@@ -5227,75 +5224,11 @@ var ACCESS_LEVEL_RANKS = {
|
|
|
5227
5224
|
read: 1,
|
|
5228
5225
|
write: 2
|
|
5229
5226
|
};
|
|
5230
|
-
var
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
room: "none",
|
|
5236
|
-
storage: "none",
|
|
5237
|
-
comments: "none",
|
|
5238
|
-
"comments:public": "none",
|
|
5239
|
-
"comments:private": "none",
|
|
5240
|
-
"comments:personal": "none",
|
|
5241
|
-
feeds: "none",
|
|
5242
|
-
personal: "none"
|
|
5243
|
-
};
|
|
5244
|
-
var BASE_PERMISSION_RESOURCE = "room";
|
|
5245
|
-
var basePermissionScopes = /* @__PURE__ */ new Set([
|
|
5246
|
-
Permission.Read,
|
|
5247
|
-
Permission.Write,
|
|
5248
|
-
Permission.RoomRead,
|
|
5249
|
-
Permission.RoomWrite
|
|
5250
|
-
]);
|
|
5251
|
-
var ROOM_PERMISSION_RESOURCES = Object.freeze([
|
|
5252
|
-
"storage",
|
|
5253
|
-
"comments",
|
|
5254
|
-
"comments:public",
|
|
5255
|
-
"comments:private",
|
|
5256
|
-
"comments:personal",
|
|
5257
|
-
"feeds"
|
|
5258
|
-
]);
|
|
5259
|
-
var CHILD_ROOM_PERMISSION_RESOURCES = (() => {
|
|
5260
|
-
const result = /* @__PURE__ */ new Map();
|
|
5261
|
-
for (const resource of ROOM_PERMISSION_RESOURCES) {
|
|
5262
|
-
const childResourcePrefix = `${resource}:`;
|
|
5263
|
-
result.set(
|
|
5264
|
-
resource,
|
|
5265
|
-
Object.freeze(
|
|
5266
|
-
ROOM_PERMISSION_RESOURCES.filter((candidate) => {
|
|
5267
|
-
if (!candidate.startsWith(childResourcePrefix)) {
|
|
5268
|
-
return false;
|
|
5269
|
-
}
|
|
5270
|
-
return !candidate.slice(childResourcePrefix.length).includes(":");
|
|
5271
|
-
})
|
|
5272
|
-
)
|
|
5273
|
-
);
|
|
5274
|
-
}
|
|
5275
|
-
return result;
|
|
5276
|
-
})();
|
|
5277
|
-
var LEAF_ROOM_PERMISSION_RESOURCES_BY_PARENT = (() => {
|
|
5278
|
-
const result = /* @__PURE__ */ new Map();
|
|
5279
|
-
for (const resource of ROOM_PERMISSION_RESOURCES) {
|
|
5280
|
-
result.set(resource, Object.freeze(getLeafResources(resource)));
|
|
5281
|
-
}
|
|
5282
|
-
return result;
|
|
5283
|
-
})();
|
|
5284
|
-
var PARENT_ROOM_PERMISSION_RESOURCES = (() => {
|
|
5285
|
-
const result = /* @__PURE__ */ new Map();
|
|
5286
|
-
for (const parentResource of ROOM_PERMISSION_RESOURCES) {
|
|
5287
|
-
for (const childResource of childResourcesOf(parentResource)) {
|
|
5288
|
-
result.set(childResource, parentResource);
|
|
5289
|
-
}
|
|
5290
|
-
}
|
|
5291
|
-
return result;
|
|
5292
|
-
})();
|
|
5293
|
-
var LEAF_ROOM_PERMISSION_RESOURCES = Object.freeze(
|
|
5294
|
-
ROOM_PERMISSION_RESOURCES.filter(
|
|
5295
|
-
(resource) => childResourcesOf(resource).length === 0
|
|
5296
|
-
)
|
|
5297
|
-
);
|
|
5298
|
-
var PERMISSIONS_BY_ROOM_RESOURCE = {
|
|
5227
|
+
var PERMISSIONS_BY_RESOURCE = {
|
|
5228
|
+
room: {
|
|
5229
|
+
read: [Permission.Read, Permission.RoomRead],
|
|
5230
|
+
write: [Permission.Write, Permission.RoomWrite]
|
|
5231
|
+
},
|
|
5299
5232
|
storage: {
|
|
5300
5233
|
write: [Permission.StorageWrite],
|
|
5301
5234
|
read: [Permission.StorageRead],
|
|
@@ -5316,31 +5249,134 @@ var PERMISSIONS_BY_ROOM_RESOURCE = {
|
|
|
5316
5249
|
read: [Permission.CommentsPrivateRead],
|
|
5317
5250
|
none: [Permission.CommentsPrivateNone]
|
|
5318
5251
|
},
|
|
5319
|
-
"comments:personal": {
|
|
5320
|
-
write: [Permission.CommentsPersonalWrite],
|
|
5321
|
-
read: [Permission.CommentsPersonalRead],
|
|
5322
|
-
none: [Permission.CommentsPersonalNone]
|
|
5323
|
-
},
|
|
5324
5252
|
feeds: {
|
|
5325
5253
|
write: [Permission.FeedsWrite],
|
|
5326
5254
|
read: [Permission.FeedsRead],
|
|
5327
5255
|
none: [Permission.FeedsNone]
|
|
5328
5256
|
}
|
|
5329
5257
|
};
|
|
5258
|
+
var NO_PERMISSION_MATRIX = {
|
|
5259
|
+
room: "none",
|
|
5260
|
+
storage: "none",
|
|
5261
|
+
comments: "none",
|
|
5262
|
+
"comments:public": "none",
|
|
5263
|
+
"comments:private": "none",
|
|
5264
|
+
feeds: "none",
|
|
5265
|
+
personal: "none"
|
|
5266
|
+
};
|
|
5267
|
+
var BASE_PERMISSION_RESOURCE = "room";
|
|
5268
|
+
var ROOM_PERMISSION_RESOURCES = [
|
|
5269
|
+
"storage",
|
|
5270
|
+
"comments",
|
|
5271
|
+
"comments:public",
|
|
5272
|
+
"comments:private",
|
|
5273
|
+
"feeds"
|
|
5274
|
+
];
|
|
5275
|
+
var COMMENT_VISIBILITY_RESOURCES = [
|
|
5276
|
+
"comments:public",
|
|
5277
|
+
"comments:private"
|
|
5278
|
+
];
|
|
5279
|
+
var basePermissionScopes = /* @__PURE__ */ new Set([
|
|
5280
|
+
Permission.Read,
|
|
5281
|
+
Permission.Write,
|
|
5282
|
+
Permission.RoomRead,
|
|
5283
|
+
Permission.RoomWrite
|
|
5284
|
+
]);
|
|
5330
5285
|
var VALID_PERMISSIONS = new Set(Object.values(Permission));
|
|
5286
|
+
function isPermission(permission) {
|
|
5287
|
+
return VALID_PERMISSIONS.has(permission);
|
|
5288
|
+
}
|
|
5289
|
+
function resolveResourceAccess(scopes, resource) {
|
|
5290
|
+
const permissions = PERMISSIONS_BY_RESOURCE[resource];
|
|
5291
|
+
let resourceAccess;
|
|
5292
|
+
for (const access of ACCESS_LEVELS) {
|
|
5293
|
+
const scopedPermissions = permissions[access];
|
|
5294
|
+
if (scopedPermissions !== void 0 && scopedPermissions.some((permission) => scopes.includes(permission))) {
|
|
5295
|
+
resourceAccess = access;
|
|
5296
|
+
}
|
|
5297
|
+
}
|
|
5298
|
+
return resourceAccess;
|
|
5299
|
+
}
|
|
5300
|
+
function explicitPermissionMatrixFromScopes(scopes) {
|
|
5301
|
+
const matrix = {};
|
|
5302
|
+
const baseAccess = resolveResourceAccess(scopes, BASE_PERMISSION_RESOURCE);
|
|
5303
|
+
if (baseAccess !== void 0) {
|
|
5304
|
+
matrix.room = baseAccess;
|
|
5305
|
+
}
|
|
5306
|
+
for (const resource of ROOM_PERMISSION_RESOURCES) {
|
|
5307
|
+
const access = resolveResourceAccess(scopes, resource);
|
|
5308
|
+
if (access !== void 0) {
|
|
5309
|
+
matrix[resource] = access;
|
|
5310
|
+
}
|
|
5311
|
+
}
|
|
5312
|
+
return matrix;
|
|
5313
|
+
}
|
|
5314
|
+
function permissionMatrixFromExplicitPermissions(explicitMatrix) {
|
|
5315
|
+
const baseAccess = explicitMatrix.room;
|
|
5316
|
+
if (baseAccess === void 0) {
|
|
5317
|
+
return { ...NO_PERMISSION_MATRIX };
|
|
5318
|
+
}
|
|
5319
|
+
const commentsAccess = explicitMatrix.comments ?? baseAccess;
|
|
5320
|
+
return {
|
|
5321
|
+
room: baseAccess,
|
|
5322
|
+
storage: explicitMatrix.storage ?? baseAccess,
|
|
5323
|
+
comments: commentsAccess,
|
|
5324
|
+
"comments:public": explicitMatrix["comments:public"] ?? commentsAccess,
|
|
5325
|
+
"comments:private": explicitMatrix["comments:private"] ?? commentsAccess,
|
|
5326
|
+
feeds: explicitMatrix.feeds ?? baseAccess,
|
|
5327
|
+
personal: "write"
|
|
5328
|
+
};
|
|
5329
|
+
}
|
|
5330
|
+
function permissionMatrixFromScopes(scopes) {
|
|
5331
|
+
return permissionMatrixFromExplicitPermissions(
|
|
5332
|
+
explicitPermissionMatrixFromScopes(scopes)
|
|
5333
|
+
);
|
|
5334
|
+
}
|
|
5335
|
+
function hasPermissionAccess(matrix, resource, requiredAccess) {
|
|
5336
|
+
const access = matrix[resource] ?? "none";
|
|
5337
|
+
return ACCESS_LEVEL_RANKS[access] >= ACCESS_LEVEL_RANKS[requiredAccess];
|
|
5338
|
+
}
|
|
5339
|
+
function resolveRoomPermissionMatrix(permissions, roomId) {
|
|
5340
|
+
const matchedPermissions = permissions.filter(
|
|
5341
|
+
(entry) => roomPatternMatches(entry.pattern, roomId)
|
|
5342
|
+
);
|
|
5343
|
+
if (matchedPermissions.length === 0) {
|
|
5344
|
+
return void 0;
|
|
5345
|
+
}
|
|
5346
|
+
const matrix = {};
|
|
5347
|
+
const specificityByResource = {};
|
|
5348
|
+
for (const entry of matchedPermissions) {
|
|
5349
|
+
const explicitMatrix = explicitPermissionMatrixFromScopes(entry.scopes);
|
|
5350
|
+
const specificity = roomPatternSpecificity(entry.pattern);
|
|
5351
|
+
if (explicitMatrix.room !== void 0) {
|
|
5352
|
+
matrix.room = strongestAccess(matrix.room ?? "none", explicitMatrix.room);
|
|
5353
|
+
}
|
|
5354
|
+
for (const resource of ROOM_PERMISSION_RESOURCES) {
|
|
5355
|
+
const access = explicitAccessForResource(explicitMatrix, resource);
|
|
5356
|
+
if (access === void 0) {
|
|
5357
|
+
continue;
|
|
5358
|
+
}
|
|
5359
|
+
const currentSpecificity = specificityByResource[resource] ?? -1;
|
|
5360
|
+
if (specificity > currentSpecificity) {
|
|
5361
|
+
matrix[resource] = access;
|
|
5362
|
+
specificityByResource[resource] = specificity;
|
|
5363
|
+
} else if (specificity === currentSpecificity) {
|
|
5364
|
+
matrix[resource] = strongestAccess(matrix[resource] ?? "none", access);
|
|
5365
|
+
}
|
|
5366
|
+
}
|
|
5367
|
+
}
|
|
5368
|
+
return permissionMatrixFromExplicitPermissions(matrix);
|
|
5369
|
+
}
|
|
5331
5370
|
function normalizeRoomPermissions(permissions) {
|
|
5332
5371
|
if (!Array.isArray(permissions)) {
|
|
5333
5372
|
throw new Error("Permission list must be an array");
|
|
5334
5373
|
}
|
|
5335
5374
|
const result = [];
|
|
5336
5375
|
for (const permission of permissions) {
|
|
5337
|
-
|
|
5338
|
-
(value) => value === permission
|
|
5339
|
-
);
|
|
5340
|
-
if (knownPermission === void 0) {
|
|
5376
|
+
if (!isPermission(permission)) {
|
|
5341
5377
|
throw new Error(`Not a valid permission: ${permission}`);
|
|
5342
5378
|
}
|
|
5343
|
-
result.push(
|
|
5379
|
+
result.push(permission);
|
|
5344
5380
|
}
|
|
5345
5381
|
return result;
|
|
5346
5382
|
}
|
|
@@ -5366,90 +5402,28 @@ function normalizeUpdateRoomAccesses(accesses) {
|
|
|
5366
5402
|
])
|
|
5367
5403
|
);
|
|
5368
5404
|
}
|
|
5369
|
-
function validatePermissionsSet(scopes) {
|
|
5370
|
-
const unknownScopes = scopes.filter((scope) => !VALID_PERMISSIONS.has(scope));
|
|
5371
|
-
if (unknownScopes.length > 0) {
|
|
5372
|
-
return `Unknown permission scope(s): ${unknownScopes.join(", ")}`;
|
|
5373
|
-
}
|
|
5374
|
-
const baseScopes = scopes.filter((scope) => basePermissionScopes.has(scope));
|
|
5375
|
-
if (baseScopes.length !== 1) {
|
|
5376
|
-
return `Permissions must include exactly one of ${Permission.Read}, ${Permission.Write} (or the legacy aliases ${Permission.RoomRead}, ${Permission.RoomWrite}), got ${baseScopes.length === 0 ? "none" : baseScopes.join(", ")}`;
|
|
5377
|
-
}
|
|
5378
|
-
const seenFeatures = /* @__PURE__ */ new Set();
|
|
5379
|
-
for (const scope of scopes) {
|
|
5380
|
-
if (basePermissionScopes.has(scope) || scope === Permission.LegacyRoomPresenceWrite) {
|
|
5381
|
-
continue;
|
|
5382
|
-
}
|
|
5383
|
-
const feature = scope.split(":").slice(0, -1).join(":");
|
|
5384
|
-
if (seenFeatures.has(feature)) {
|
|
5385
|
-
return `Permissions can include at most one scope per feature, got multiple "${feature}" scopes`;
|
|
5386
|
-
}
|
|
5387
|
-
seenFeatures.add(feature);
|
|
5388
|
-
}
|
|
5389
|
-
return true;
|
|
5390
|
-
}
|
|
5391
|
-
function permissionMatrixFromScopes(scopes) {
|
|
5392
|
-
return permissionMatrixFromResolvedScopes(resolvePermissionScopes(scopes));
|
|
5393
|
-
}
|
|
5394
5405
|
function permissionMatrixToScopes(matrix) {
|
|
5395
5406
|
const scopes = [];
|
|
5396
5407
|
const baseAccess = matrix.room;
|
|
5397
5408
|
if (baseAccess !== "none") {
|
|
5398
5409
|
scopes.push(permissionForAccessLevel(BASE_PERMISSION_RESOURCE, baseAccess));
|
|
5399
5410
|
}
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
pushResourcePermissions(scopes, matrix, resource, baseAccess);
|
|
5403
|
-
}
|
|
5411
|
+
if (matrix.storage !== baseAccess) {
|
|
5412
|
+
scopes.push(permissionForAccessLevel("storage", matrix.storage));
|
|
5404
5413
|
}
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
const access = matrix[resource] ?? "none";
|
|
5409
|
-
return ACCESS_LEVEL_RANKS[access] >= ACCESS_LEVEL_RANKS[requiredAccess];
|
|
5410
|
-
}
|
|
5411
|
-
function resolveRoomPermissionMatrix(permissions, roomId) {
|
|
5412
|
-
const matchedPermissions = permissions.filter((entry) => {
|
|
5413
|
-
if (entry.pattern.includes("*")) {
|
|
5414
|
-
return roomId.startsWith(entry.pattern.replace("*", ""));
|
|
5415
|
-
}
|
|
5416
|
-
return entry.pattern === roomId;
|
|
5417
|
-
});
|
|
5418
|
-
if (matchedPermissions.length === 0) {
|
|
5419
|
-
return void 0;
|
|
5414
|
+
const commentsAccess = matrix.comments;
|
|
5415
|
+
if (commentsAccess !== baseAccess) {
|
|
5416
|
+
scopes.push(permissionForAccessLevel("comments", commentsAccess));
|
|
5420
5417
|
}
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
const leafSpecificity = {};
|
|
5425
|
-
for (const entry of matchedPermissions) {
|
|
5426
|
-
const resolved = resolvePermissionScopes(entry.scopes);
|
|
5427
|
-
const specificity = entry.pattern.replace("*", "").length;
|
|
5428
|
-
if (resolved.baseAccess !== void 0) {
|
|
5429
|
-
hasDefaultPermission = true;
|
|
5430
|
-
baseAccess = strongestAccess(baseAccess, resolved.baseAccess);
|
|
5431
|
-
}
|
|
5432
|
-
for (const resource of LEAF_ROOM_PERMISSION_RESOURCES) {
|
|
5433
|
-
if (resolved.leafAccesses[resource] === void 0) {
|
|
5434
|
-
continue;
|
|
5435
|
-
}
|
|
5436
|
-
const access = resolveLeafAccessFromSource(resolved, resource);
|
|
5437
|
-
const currentSpecificity = leafSpecificity[resource] ?? -1;
|
|
5438
|
-
if (specificity > currentSpecificity) {
|
|
5439
|
-
leafAccesses[resource] = access;
|
|
5440
|
-
leafSpecificity[resource] = specificity;
|
|
5441
|
-
} else if (specificity === currentSpecificity) {
|
|
5442
|
-
leafAccesses[resource] = strongestAccess(
|
|
5443
|
-
leafAccesses[resource] ?? "none",
|
|
5444
|
-
access
|
|
5445
|
-
);
|
|
5446
|
-
}
|
|
5418
|
+
for (const resource of COMMENT_VISIBILITY_RESOURCES) {
|
|
5419
|
+
if (matrix[resource] !== commentsAccess) {
|
|
5420
|
+
scopes.push(permissionForAccessLevel(resource, matrix[resource]));
|
|
5447
5421
|
}
|
|
5448
5422
|
}
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5423
|
+
if (matrix.feeds !== baseAccess) {
|
|
5424
|
+
scopes.push(permissionForAccessLevel("feeds", matrix.feeds));
|
|
5425
|
+
}
|
|
5426
|
+
return scopes;
|
|
5453
5427
|
}
|
|
5454
5428
|
function mergeRoomPermissionScopes({
|
|
5455
5429
|
defaultAccesses,
|
|
@@ -5457,139 +5431,48 @@ function mergeRoomPermissionScopes({
|
|
|
5457
5431
|
userAccesses
|
|
5458
5432
|
}) {
|
|
5459
5433
|
const sources = [
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
groupsAccesses.map(
|
|
5434
|
+
explicitPermissionMatrixFromScopes(defaultAccesses),
|
|
5435
|
+
mergeExplicitPermissionMatricesByHighestAccess(
|
|
5436
|
+
groupsAccesses.map(explicitPermissionMatrixFromScopes)
|
|
5463
5437
|
),
|
|
5464
|
-
|
|
5438
|
+
explicitPermissionMatrixFromScopes(userAccesses)
|
|
5465
5439
|
];
|
|
5466
|
-
const merged = {
|
|
5467
|
-
leafAccesses: {}
|
|
5468
|
-
};
|
|
5440
|
+
const merged = {};
|
|
5469
5441
|
for (const source of sources) {
|
|
5470
|
-
if (source.
|
|
5471
|
-
merged.
|
|
5442
|
+
if (source.room !== void 0) {
|
|
5443
|
+
merged.room = source.room;
|
|
5472
5444
|
}
|
|
5473
|
-
for (const resource of
|
|
5474
|
-
const
|
|
5475
|
-
if (
|
|
5476
|
-
|
|
5445
|
+
for (const resource of ROOM_PERMISSION_RESOURCES) {
|
|
5446
|
+
const access = explicitAccessForResource(source, resource);
|
|
5447
|
+
if (access !== void 0) {
|
|
5448
|
+
merged[resource] = access;
|
|
5477
5449
|
}
|
|
5478
|
-
merged.leafAccesses[resource] = sourceAccess;
|
|
5479
5450
|
}
|
|
5480
5451
|
}
|
|
5481
|
-
return permissionMatrixToScopes(
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
const baseAccess = resolveAccess(scopes, BASE_PERMISSIONS_BY_ACCESS);
|
|
5485
|
-
const leafAccesses = {};
|
|
5486
|
-
for (const resource of ROOM_PERMISSION_RESOURCES) {
|
|
5487
|
-
const access = resolveResourceAccess(scopes, resource);
|
|
5488
|
-
if (access !== void 0) {
|
|
5489
|
-
for (const leafResource of leafResourcesOf(resource)) {
|
|
5490
|
-
leafAccesses[leafResource] = access;
|
|
5491
|
-
}
|
|
5492
|
-
}
|
|
5493
|
-
}
|
|
5494
|
-
return { baseAccess, leafAccesses };
|
|
5495
|
-
}
|
|
5496
|
-
function resolveResourceAccess(scopes, resource) {
|
|
5497
|
-
return resolveAccess(scopes, PERMISSIONS_BY_ROOM_RESOURCE[resource]);
|
|
5498
|
-
}
|
|
5499
|
-
function resolveAccess(scopes, permissions) {
|
|
5500
|
-
let resourceAccess;
|
|
5501
|
-
for (const access of ACCESS_LEVELS) {
|
|
5502
|
-
const scopedPermissions = permissions[access];
|
|
5503
|
-
if (scopedPermissions !== void 0 && scopedPermissions.some((permission) => scopes.includes(permission))) {
|
|
5504
|
-
resourceAccess = access;
|
|
5505
|
-
}
|
|
5506
|
-
}
|
|
5507
|
-
return resourceAccess;
|
|
5508
|
-
}
|
|
5509
|
-
function permissionMatrixFromResolvedScopes(resolved) {
|
|
5510
|
-
if (resolved.baseAccess === void 0) {
|
|
5511
|
-
return { ...NO_PERMISSION_MATRIX };
|
|
5512
|
-
}
|
|
5513
|
-
const matrix = {
|
|
5514
|
-
...NO_PERMISSION_MATRIX,
|
|
5515
|
-
[BASE_PERMISSION_RESOURCE]: resolved.baseAccess,
|
|
5516
|
-
personal: "write"
|
|
5517
|
-
};
|
|
5518
|
-
for (const resource of LEAF_ROOM_PERMISSION_RESOURCES) {
|
|
5519
|
-
matrix[resource] = resolveLeafAccessFromSource(resolved, resource);
|
|
5520
|
-
}
|
|
5521
|
-
for (const resource of ROOM_PERMISSION_RESOURCES) {
|
|
5522
|
-
if (childResourcesOf(resource).length > 0) {
|
|
5523
|
-
let strongest = "none";
|
|
5524
|
-
for (const leafResource of leafResourcesOf(resource)) {
|
|
5525
|
-
strongest = strongestAccess(strongest, matrix[leafResource]);
|
|
5526
|
-
}
|
|
5527
|
-
matrix[resource] = strongest;
|
|
5528
|
-
}
|
|
5529
|
-
}
|
|
5530
|
-
return matrix;
|
|
5531
|
-
}
|
|
5532
|
-
function resolveLeafAccessFromSource(source, resource) {
|
|
5533
|
-
const access = source.leafAccesses[resource];
|
|
5534
|
-
if (access !== void 0) {
|
|
5535
|
-
return access;
|
|
5536
|
-
}
|
|
5537
|
-
return source.baseAccess ?? "none";
|
|
5538
|
-
}
|
|
5539
|
-
function pushResourcePermissions(scopes, matrix, resource, baseAccess) {
|
|
5540
|
-
const childResources = childResourcesOf(resource);
|
|
5541
|
-
if (childResources.length === 0) {
|
|
5542
|
-
const access = matrix[resource];
|
|
5543
|
-
if (access !== baseAccess) {
|
|
5544
|
-
scopes.push(permissionForAccessLevel(resource, access));
|
|
5545
|
-
}
|
|
5546
|
-
return;
|
|
5547
|
-
}
|
|
5548
|
-
const leafResources = leafResourcesOf(resource);
|
|
5549
|
-
let sharedAccess;
|
|
5550
|
-
let allLeavesShareAccess = true;
|
|
5551
|
-
for (const leafResource of leafResources) {
|
|
5552
|
-
const access = matrix[leafResource];
|
|
5553
|
-
sharedAccess ??= access;
|
|
5554
|
-
if (access !== sharedAccess) {
|
|
5555
|
-
allLeavesShareAccess = false;
|
|
5556
|
-
break;
|
|
5557
|
-
}
|
|
5558
|
-
}
|
|
5559
|
-
if (sharedAccess !== void 0 && sharedAccess !== baseAccess && allLeavesShareAccess) {
|
|
5560
|
-
scopes.push(permissionForAccessLevel(resource, sharedAccess));
|
|
5561
|
-
return;
|
|
5562
|
-
}
|
|
5563
|
-
for (const childResource of childResources) {
|
|
5564
|
-
pushResourcePermissions(scopes, matrix, childResource, baseAccess);
|
|
5565
|
-
}
|
|
5452
|
+
return permissionMatrixToScopes(
|
|
5453
|
+
permissionMatrixFromExplicitPermissions(merged)
|
|
5454
|
+
);
|
|
5566
5455
|
}
|
|
5567
|
-
function
|
|
5568
|
-
const merged = {
|
|
5569
|
-
leafAccesses: {}
|
|
5570
|
-
};
|
|
5456
|
+
function mergeExplicitPermissionMatricesByHighestAccess(sources) {
|
|
5457
|
+
const merged = {};
|
|
5571
5458
|
for (const source of sources) {
|
|
5572
|
-
if (source.
|
|
5573
|
-
merged.
|
|
5574
|
-
merged.baseAccess ?? "none",
|
|
5575
|
-
source.baseAccess
|
|
5576
|
-
);
|
|
5459
|
+
if (source.room !== void 0) {
|
|
5460
|
+
merged.room = strongestAccess(merged.room ?? "none", source.room);
|
|
5577
5461
|
}
|
|
5578
|
-
for (const resource of
|
|
5579
|
-
const
|
|
5580
|
-
if (
|
|
5581
|
-
|
|
5462
|
+
for (const resource of ROOM_PERMISSION_RESOURCES) {
|
|
5463
|
+
const access = explicitAccessForResource(source, resource);
|
|
5464
|
+
if (access !== void 0) {
|
|
5465
|
+
merged[resource] = strongestAccess(merged[resource] ?? "none", access);
|
|
5582
5466
|
}
|
|
5583
|
-
merged.leafAccesses[resource] = strongestAccess(
|
|
5584
|
-
merged.leafAccesses[resource] ?? "none",
|
|
5585
|
-
sourceAccess
|
|
5586
|
-
);
|
|
5587
5467
|
}
|
|
5588
5468
|
}
|
|
5589
5469
|
return merged;
|
|
5590
5470
|
}
|
|
5471
|
+
function explicitAccessForResource(source, resource) {
|
|
5472
|
+
return source[resource] ?? (isCommentVisibilityResource(resource) ? source.comments : void 0);
|
|
5473
|
+
}
|
|
5591
5474
|
function permissionForAccessLevel(resource, access, field = resource) {
|
|
5592
|
-
const permissions =
|
|
5475
|
+
const permissions = PERMISSIONS_BY_RESOURCE[resource][access];
|
|
5593
5476
|
const permission = permissions?.[0];
|
|
5594
5477
|
if (permission !== void 0) {
|
|
5595
5478
|
return permission;
|
|
@@ -5601,21 +5484,43 @@ function permissionForAccessLevel(resource, access, field = resource) {
|
|
|
5601
5484
|
function strongestAccess(left, right) {
|
|
5602
5485
|
return ACCESS_LEVEL_RANKS[right] > ACCESS_LEVEL_RANKS[left] ? right : left;
|
|
5603
5486
|
}
|
|
5604
|
-
function
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
return
|
|
5487
|
+
function roomPatternMatches(pattern, roomId) {
|
|
5488
|
+
if (pattern.includes("*")) {
|
|
5489
|
+
return roomId.startsWith(pattern.replace("*", ""));
|
|
5490
|
+
}
|
|
5491
|
+
return pattern === roomId;
|
|
5609
5492
|
}
|
|
5610
|
-
function
|
|
5611
|
-
return
|
|
5493
|
+
function roomPatternSpecificity(pattern) {
|
|
5494
|
+
return pattern.replace("*", "").length;
|
|
5612
5495
|
}
|
|
5613
|
-
function
|
|
5614
|
-
const
|
|
5615
|
-
if (
|
|
5616
|
-
return
|
|
5496
|
+
function validatePermissionsSet(scopes) {
|
|
5497
|
+
const unknownScopes = scopes.filter((scope) => !VALID_PERMISSIONS.has(scope));
|
|
5498
|
+
if (unknownScopes.length > 0) {
|
|
5499
|
+
return `Unknown permission scope(s): ${unknownScopes.join(", ")}`;
|
|
5500
|
+
}
|
|
5501
|
+
const baseScopes = scopes.filter((scope) => basePermissionScopes.has(scope));
|
|
5502
|
+
if (baseScopes.length !== 1) {
|
|
5503
|
+
return `Permissions must include exactly one of ${Permission.Read}, ${Permission.Write} (or the legacy aliases ${Permission.RoomRead}, ${Permission.RoomWrite}), got ${baseScopes.length === 0 ? "none" : baseScopes.join(", ")}`;
|
|
5504
|
+
}
|
|
5505
|
+
const seenFeatures = /* @__PURE__ */ new Set();
|
|
5506
|
+
for (const scope of scopes) {
|
|
5507
|
+
if (basePermissionScopes.has(scope) || scope === Permission.LegacyRoomPresenceWrite) {
|
|
5508
|
+
continue;
|
|
5509
|
+
}
|
|
5510
|
+
const feature = permissionFeature(scope);
|
|
5511
|
+
if (seenFeatures.has(feature)) {
|
|
5512
|
+
return `Permissions can include at most one scope per feature, got multiple "${feature}" scopes`;
|
|
5513
|
+
}
|
|
5514
|
+
seenFeatures.add(feature);
|
|
5617
5515
|
}
|
|
5618
|
-
return
|
|
5516
|
+
return true;
|
|
5517
|
+
}
|
|
5518
|
+
function permissionFeature(scope) {
|
|
5519
|
+
const accessSeparatorIndex = scope.lastIndexOf(":");
|
|
5520
|
+
return accessSeparatorIndex === -1 ? scope : scope.slice(0, accessSeparatorIndex);
|
|
5521
|
+
}
|
|
5522
|
+
function isCommentVisibilityResource(resource) {
|
|
5523
|
+
return resource.startsWith("comments:");
|
|
5619
5524
|
}
|
|
5620
5525
|
|
|
5621
5526
|
// src/protocol/AuthToken.ts
|
|
@@ -5804,7 +5709,13 @@ function cachedTokenSatisfiesRequest(cachedToken, request) {
|
|
|
5804
5709
|
cachedToken.permissions ?? [],
|
|
5805
5710
|
request.roomId
|
|
5806
5711
|
);
|
|
5807
|
-
|
|
5712
|
+
if (matrix === void 0) {
|
|
5713
|
+
return false;
|
|
5714
|
+
}
|
|
5715
|
+
if (request.resource === "comments" && request.access === "read") {
|
|
5716
|
+
return hasPermissionAccess(matrix, "comments", "read") || hasPermissionAccess(matrix, "comments:public", "read") || hasPermissionAccess(matrix, "comments:private", "read");
|
|
5717
|
+
}
|
|
5718
|
+
return hasPermissionAccess(matrix, request.resource, request.access);
|
|
5808
5719
|
}
|
|
5809
5720
|
function prepareAuthentication(authOptions) {
|
|
5810
5721
|
const { publicApiKey, authEndpoint } = authOptions;
|
|
@@ -8662,7 +8573,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
8662
8573
|
const preciseSize = new TextEncoder().encode(jsonString).length;
|
|
8663
8574
|
if (preciseSize > MAX_LIVE_OBJECT_SIZE) {
|
|
8664
8575
|
throw new Error(
|
|
8665
|
-
`LiveObject size exceeded limit: ${preciseSize} bytes > ${MAX_LIVE_OBJECT_SIZE} bytes. See https://liveblocks.io/docs/
|
|
8576
|
+
`LiveObject size exceeded limit: ${preciseSize} bytes > ${MAX_LIVE_OBJECT_SIZE} bytes. See https://liveblocks.io/docs/pricing/limits#Other-limits`
|
|
8666
8577
|
);
|
|
8667
8578
|
}
|
|
8668
8579
|
}
|
|
@@ -11605,6 +11516,7 @@ function createRoom(options, config) {
|
|
|
11605
11516
|
yjsProviderDidChange: context.yjsProviderDidChange.observable,
|
|
11606
11517
|
// send metadata when using a text editor
|
|
11607
11518
|
reportTextEditor,
|
|
11519
|
+
getPermissionMatrix: () => context.dynamicSessionInfoSig.get()?.permissionMatrix,
|
|
11608
11520
|
// create a text mention when using a text editor
|
|
11609
11521
|
createTextMention,
|
|
11610
11522
|
// delete a text mention when using a text editor
|