@peers-app/peers-sdk 0.1.4
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/README.md +1 -0
- package/dist/context/data-context.d.ts +31 -0
- package/dist/context/data-context.js +56 -0
- package/dist/context/index.d.ts +3 -0
- package/dist/context/index.js +19 -0
- package/dist/context/user-context-singleton.d.ts +11 -0
- package/dist/context/user-context-singleton.js +121 -0
- package/dist/context/user-context.d.ts +55 -0
- package/dist/context/user-context.js +205 -0
- package/dist/data/assistants.d.ts +68 -0
- package/dist/data/assistants.js +64 -0
- package/dist/data/change-tracking.d.ts +219 -0
- package/dist/data/change-tracking.js +119 -0
- package/dist/data/channels.d.ts +29 -0
- package/dist/data/channels.js +25 -0
- package/dist/data/data-locks.d.ts +37 -0
- package/dist/data/data-locks.js +180 -0
- package/dist/data/data-locks.test.d.ts +1 -0
- package/dist/data/data-locks.test.js +456 -0
- package/dist/data/device-sync-info.d.ts +19 -0
- package/dist/data/device-sync-info.js +24 -0
- package/dist/data/devices.d.ts +51 -0
- package/dist/data/devices.js +36 -0
- package/dist/data/embeddings.d.ts +47 -0
- package/dist/data/embeddings.js +36 -0
- package/dist/data/files/file-read-stream.d.ts +27 -0
- package/dist/data/files/file-read-stream.js +195 -0
- package/dist/data/files/file-write-stream.d.ts +20 -0
- package/dist/data/files/file-write-stream.js +113 -0
- package/dist/data/files/file.types.d.ts +47 -0
- package/dist/data/files/file.types.js +55 -0
- package/dist/data/files/files.d.ts +28 -0
- package/dist/data/files/files.js +127 -0
- package/dist/data/files/files.test.d.ts +1 -0
- package/dist/data/files/files.test.js +728 -0
- package/dist/data/files/index.d.ts +4 -0
- package/dist/data/files/index.js +23 -0
- package/dist/data/group-member-roles.d.ts +9 -0
- package/dist/data/group-member-roles.js +25 -0
- package/dist/data/group-members.d.ts +39 -0
- package/dist/data/group-members.js +68 -0
- package/dist/data/group-members.test.d.ts +1 -0
- package/dist/data/group-members.test.js +287 -0
- package/dist/data/group-permissions.d.ts +8 -0
- package/dist/data/group-permissions.js +73 -0
- package/dist/data/group-share.d.ts +50 -0
- package/dist/data/group-share.js +196 -0
- package/dist/data/groups.d.ts +50 -0
- package/dist/data/groups.js +73 -0
- package/dist/data/groups.test.d.ts +1 -0
- package/dist/data/groups.test.js +153 -0
- package/dist/data/index.d.ts +31 -0
- package/dist/data/index.js +47 -0
- package/dist/data/knowledge/knowledge-frames.d.ts +34 -0
- package/dist/data/knowledge/knowledge-frames.js +34 -0
- package/dist/data/knowledge/knowledge-links.d.ts +30 -0
- package/dist/data/knowledge/knowledge-links.js +25 -0
- package/dist/data/knowledge/knowledge-values.d.ts +35 -0
- package/dist/data/knowledge/knowledge-values.js +35 -0
- package/dist/data/knowledge/peer-types.d.ts +112 -0
- package/dist/data/knowledge/peer-types.js +27 -0
- package/dist/data/knowledge/predicates.d.ts +34 -0
- package/dist/data/knowledge/predicates.js +27 -0
- package/dist/data/messages.d.ts +57 -0
- package/dist/data/messages.js +97 -0
- package/dist/data/orm/client-proxy.data-source.d.ts +27 -0
- package/dist/data/orm/client-proxy.data-source.js +65 -0
- package/dist/data/orm/cursor.d.ts +25 -0
- package/dist/data/orm/cursor.js +47 -0
- package/dist/data/orm/cursor.test.d.ts +1 -0
- package/dist/data/orm/cursor.test.js +315 -0
- package/dist/data/orm/data-query.d.ts +96 -0
- package/dist/data/orm/data-query.js +208 -0
- package/dist/data/orm/data-query.mongo.d.ts +17 -0
- package/dist/data/orm/data-query.mongo.js +267 -0
- package/dist/data/orm/data-query.mongo.test.d.ts +1 -0
- package/dist/data/orm/data-query.mongo.test.js +398 -0
- package/dist/data/orm/data-query.sqlite.d.ts +14 -0
- package/dist/data/orm/data-query.sqlite.js +297 -0
- package/dist/data/orm/data-query.sqlite.test.d.ts +1 -0
- package/dist/data/orm/data-query.sqlite.test.js +377 -0
- package/dist/data/orm/data-query.test.d.ts +1 -0
- package/dist/data/orm/data-query.test.js +553 -0
- package/dist/data/orm/decorators.d.ts +6 -0
- package/dist/data/orm/decorators.js +21 -0
- package/dist/data/orm/dependency-injection.test.d.ts +1 -0
- package/dist/data/orm/dependency-injection.test.js +171 -0
- package/dist/data/orm/doc.d.ts +26 -0
- package/dist/data/orm/doc.js +124 -0
- package/dist/data/orm/event-registry.d.ts +24 -0
- package/dist/data/orm/event-registry.js +40 -0
- package/dist/data/orm/event-registry.test.d.ts +1 -0
- package/dist/data/orm/event-registry.test.js +44 -0
- package/dist/data/orm/factory.d.ts +8 -0
- package/dist/data/orm/factory.js +147 -0
- package/dist/data/orm/index.d.ts +16 -0
- package/dist/data/orm/index.js +32 -0
- package/dist/data/orm/multi-cursors.d.ts +11 -0
- package/dist/data/orm/multi-cursors.js +146 -0
- package/dist/data/orm/multi-cursors.test.d.ts +1 -0
- package/dist/data/orm/multi-cursors.test.js +455 -0
- package/dist/data/orm/sql-db.d.ts +6 -0
- package/dist/data/orm/sql-db.js +2 -0
- package/dist/data/orm/sql.data-source.d.ts +38 -0
- package/dist/data/orm/sql.data-source.js +379 -0
- package/dist/data/orm/sql.data-source.test.d.ts +1 -0
- package/dist/data/orm/sql.data-source.test.js +406 -0
- package/dist/data/orm/subscribable.data-source.d.ts +25 -0
- package/dist/data/orm/subscribable.data-source.js +72 -0
- package/dist/data/orm/table-container-events.test.d.ts +1 -0
- package/dist/data/orm/table-container-events.test.js +93 -0
- package/dist/data/orm/table-container.d.ts +39 -0
- package/dist/data/orm/table-container.js +96 -0
- package/dist/data/orm/table-definitions.system.d.ts +9 -0
- package/dist/data/orm/table-definitions.system.js +29 -0
- package/dist/data/orm/table-definitions.type.d.ts +19 -0
- package/dist/data/orm/table-definitions.type.js +2 -0
- package/dist/data/orm/table-dependencies.d.ts +32 -0
- package/dist/data/orm/table-dependencies.js +2 -0
- package/dist/data/orm/table.d.ts +42 -0
- package/dist/data/orm/table.event-source.test.d.ts +1 -0
- package/dist/data/orm/table.event-source.test.js +341 -0
- package/dist/data/orm/table.js +244 -0
- package/dist/data/orm/types.d.ts +20 -0
- package/dist/data/orm/types.js +115 -0
- package/dist/data/orm/types.test.d.ts +1 -0
- package/dist/data/orm/types.test.js +71 -0
- package/dist/data/package-permissions.d.ts +7 -0
- package/dist/data/package-permissions.js +18 -0
- package/dist/data/packages.d.ts +92 -0
- package/dist/data/packages.js +90 -0
- package/dist/data/peer-events/peer-event-handlers.d.ts +21 -0
- package/dist/data/peer-events/peer-event-handlers.js +28 -0
- package/dist/data/peer-events/peer-event-types.d.ts +119 -0
- package/dist/data/peer-events/peer-event-types.js +29 -0
- package/dist/data/peer-events/peer-events.d.ts +41 -0
- package/dist/data/peer-events/peer-events.js +102 -0
- package/dist/data/persistent-vars.d.ts +87 -0
- package/dist/data/persistent-vars.js +230 -0
- package/dist/data/tool-tests.d.ts +37 -0
- package/dist/data/tool-tests.js +27 -0
- package/dist/data/tools.d.ts +358 -0
- package/dist/data/tools.js +48 -0
- package/dist/data/user-permissions.d.ts +15 -0
- package/dist/data/user-permissions.js +39 -0
- package/dist/data/user-permissions.test.d.ts +1 -0
- package/dist/data/user-permissions.test.js +252 -0
- package/dist/data/users.d.ts +38 -0
- package/dist/data/users.js +73 -0
- package/dist/data/workflow-logs.d.ts +106 -0
- package/dist/data/workflow-logs.js +67 -0
- package/dist/data/workflow-runs.d.ts +103 -0
- package/dist/data/workflow-runs.js +313 -0
- package/dist/data/workflows.d.ts +16 -0
- package/dist/data/workflows.js +21 -0
- package/dist/device/connection.d.ts +41 -0
- package/dist/device/connection.js +249 -0
- package/dist/device/connection.test.d.ts +1 -0
- package/dist/device/connection.test.js +292 -0
- package/dist/device/device-election.d.ts +36 -0
- package/dist/device/device-election.js +137 -0
- package/dist/device/device.d.ts +22 -0
- package/dist/device/device.js +110 -0
- package/dist/device/device.test.d.ts +1 -0
- package/dist/device/device.test.js +203 -0
- package/dist/device/get-trust-level.d.ts +3 -0
- package/dist/device/get-trust-level.js +87 -0
- package/dist/device/socket.type.d.ts +20 -0
- package/dist/device/socket.type.js +15 -0
- package/dist/device/streamed-socket.d.ts +27 -0
- package/dist/device/streamed-socket.js +154 -0
- package/dist/device/streamed-socket.test.d.ts +1 -0
- package/dist/device/streamed-socket.test.js +44 -0
- package/dist/events.d.ts +35 -0
- package/dist/events.js +128 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +50 -0
- package/dist/keys.d.ts +51 -0
- package/dist/keys.js +234 -0
- package/dist/keys.test.d.ts +1 -0
- package/dist/keys.test.js +215 -0
- package/dist/mentions.d.ts +9 -0
- package/dist/mentions.js +46 -0
- package/dist/observable.d.ts +19 -0
- package/dist/observable.js +112 -0
- package/dist/observable.test.d.ts +1 -0
- package/dist/observable.test.js +183 -0
- package/dist/package-loader/get-require.d.ts +10 -0
- package/dist/package-loader/get-require.js +31 -0
- package/dist/package-loader/index.d.ts +1 -0
- package/dist/package-loader/index.js +17 -0
- package/dist/package-loader/package-loader.d.ts +16 -0
- package/dist/package-loader/package-loader.js +102 -0
- package/dist/peers-ui/peers-ui.d.ts +15 -0
- package/dist/peers-ui/peers-ui.js +23 -0
- package/dist/peers-ui/peers-ui.types.d.ts +35 -0
- package/dist/peers-ui/peers-ui.types.js +3 -0
- package/dist/rpc-types.d.ts +45 -0
- package/dist/rpc-types.js +47 -0
- package/dist/serial-json.d.ts +5 -0
- package/dist/serial-json.js +186 -0
- package/dist/serial-json.test.d.ts +1 -0
- package/dist/serial-json.test.js +86 -0
- package/dist/system-ids.d.ts +6 -0
- package/dist/system-ids.js +10 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +17 -0
- package/dist/tools/tools-factory.d.ts +5 -0
- package/dist/tools/tools-factory.js +34 -0
- package/dist/types/app-nav.d.ts +18 -0
- package/dist/types/app-nav.js +10 -0
- package/dist/types/assistant-runner-args.d.ts +9 -0
- package/dist/types/assistant-runner-args.js +2 -0
- package/dist/types/field-type.d.ts +37 -0
- package/dist/types/field-type.js +26 -0
- package/dist/types/peer-device.d.ts +40 -0
- package/dist/types/peer-device.js +14 -0
- package/dist/types/peers-package.d.ts +23 -0
- package/dist/types/peers-package.js +2 -0
- package/dist/types/workflow-logger.d.ts +2 -0
- package/dist/types/workflow-logger.js +2 -0
- package/dist/types/workflow-run-context.d.ts +12 -0
- package/dist/types/workflow-run-context.js +2 -0
- package/dist/types/workflow.d.ts +72 -0
- package/dist/types/workflow.js +24 -0
- package/dist/types/zod-types.d.ts +7 -0
- package/dist/types/zod-types.js +12 -0
- package/dist/users.query.d.ts +13 -0
- package/dist/users.query.js +134 -0
- package/dist/utils.d.ts +39 -0
- package/dist/utils.js +240 -0
- package/dist/utils.test.d.ts +1 -0
- package/dist/utils.test.js +140 -0
- package/package.json +50 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.FileReadStream = exports.FileWriteStream = void 0;
|
|
18
|
+
__exportStar(require("./file.types"), exports);
|
|
19
|
+
__exportStar(require("./files"), exports);
|
|
20
|
+
var file_write_stream_1 = require("./file-write-stream");
|
|
21
|
+
Object.defineProperty(exports, "FileWriteStream", { enumerable: true, get: function () { return file_write_stream_1.FileWriteStream; } });
|
|
22
|
+
var file_read_stream_1 = require("./file-read-stream");
|
|
23
|
+
Object.defineProperty(exports, "FileReadStream", { enumerable: true, get: function () { return file_read_stream_1.FileReadStream; } });
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GroupMemberRole = void 0;
|
|
4
|
+
exports.getRoleLabel = getRoleLabel;
|
|
5
|
+
var GroupMemberRole;
|
|
6
|
+
(function (GroupMemberRole) {
|
|
7
|
+
GroupMemberRole[GroupMemberRole["None"] = 0] = "None";
|
|
8
|
+
GroupMemberRole[GroupMemberRole["Reader"] = 20] = "Reader";
|
|
9
|
+
GroupMemberRole[GroupMemberRole["Writer"] = 40] = "Writer";
|
|
10
|
+
GroupMemberRole[GroupMemberRole["Admin"] = 60] = "Admin";
|
|
11
|
+
GroupMemberRole[GroupMemberRole["Owner"] = 80] = "Owner";
|
|
12
|
+
GroupMemberRole[GroupMemberRole["Founder"] = 100] = "Founder";
|
|
13
|
+
})(GroupMemberRole || (exports.GroupMemberRole = GroupMemberRole = {}));
|
|
14
|
+
function getRoleLabel(value) {
|
|
15
|
+
const roleEntries = Object.entries(GroupMemberRole)
|
|
16
|
+
.filter(([key, val]) => typeof val === 'number')
|
|
17
|
+
.map(([key, val]) => ({ level: val, label: key }))
|
|
18
|
+
.sort((a, b) => b.level - a.level);
|
|
19
|
+
for (const role of roleEntries) {
|
|
20
|
+
if (value >= role.level) {
|
|
21
|
+
return value === role.level ? role.label : `${role.label}+`;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return 'None';
|
|
25
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { DataContext } from "../context/data-context";
|
|
3
|
+
import { Table } from "./orm";
|
|
4
|
+
import { GroupMemberRole } from './group-member-roles';
|
|
5
|
+
import { ISaveOptions } from "..";
|
|
6
|
+
export declare const groupMemberSchema: z.ZodObject<{
|
|
7
|
+
groupMemberId: z.ZodEffects<z.ZodString, string, string>;
|
|
8
|
+
groupId: z.ZodEffects<z.ZodString, string, string>;
|
|
9
|
+
userId: z.ZodEffects<z.ZodString, string, string>;
|
|
10
|
+
role: z.ZodNativeEnum<typeof GroupMemberRole>;
|
|
11
|
+
signature: z.ZodString;
|
|
12
|
+
deleted: z.ZodOptional<z.ZodBoolean>;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
role: GroupMemberRole;
|
|
15
|
+
signature: string;
|
|
16
|
+
groupMemberId: string;
|
|
17
|
+
groupId: string;
|
|
18
|
+
userId: string;
|
|
19
|
+
deleted?: boolean | undefined;
|
|
20
|
+
}, {
|
|
21
|
+
role: GroupMemberRole;
|
|
22
|
+
signature: string;
|
|
23
|
+
groupMemberId: string;
|
|
24
|
+
groupId: string;
|
|
25
|
+
userId: string;
|
|
26
|
+
deleted?: boolean | undefined;
|
|
27
|
+
}>;
|
|
28
|
+
export type IGroupMember = z.infer<typeof groupMemberSchema>;
|
|
29
|
+
export declare const groupMembersTableName = "GroupMembers";
|
|
30
|
+
export declare class GroupMembersTable extends Table<IGroupMember> {
|
|
31
|
+
static isPassthrough: boolean;
|
|
32
|
+
save(groupMember: IGroupMember, opts?: ISaveOptions): Promise<IGroupMember>;
|
|
33
|
+
delete(groupMemberId: string): Promise<void>;
|
|
34
|
+
/** @deprecated Forbidden on GroupsTable; use save() */
|
|
35
|
+
insert(..._args: Parameters<Table<IGroupMember>['insert']>): never;
|
|
36
|
+
/** @deprecated Forbidden on GroupsTable; use save() */
|
|
37
|
+
update(..._args: Parameters<Table<IGroupMember>['update']>): never;
|
|
38
|
+
}
|
|
39
|
+
export declare function GroupMembers(dataContext?: DataContext): GroupMembersTable;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GroupMembersTable = exports.groupMembersTableName = exports.groupMemberSchema = void 0;
|
|
4
|
+
exports.GroupMembers = GroupMembers;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const user_context_singleton_1 = require("../context/user-context-singleton");
|
|
7
|
+
const zod_types_1 = require("../types/zod-types");
|
|
8
|
+
const orm_1 = require("./orm");
|
|
9
|
+
const table_definitions_system_1 = require("./orm/table-definitions.system");
|
|
10
|
+
const types_1 = require("./orm/types");
|
|
11
|
+
const group_member_roles_1 = require("./group-member-roles");
|
|
12
|
+
const group_permissions_1 = require("./group-permissions");
|
|
13
|
+
const __1 = require("..");
|
|
14
|
+
exports.groupMemberSchema = zod_1.z.object({
|
|
15
|
+
groupMemberId: zod_types_1.zodPeerId,
|
|
16
|
+
groupId: zod_types_1.zodPeerId.describe('The id of the group'),
|
|
17
|
+
userId: zod_types_1.zodPeerId.describe('The id of the user who is a member of the group'),
|
|
18
|
+
role: zod_1.z.nativeEnum(group_member_roles_1.GroupMemberRole).describe('The role of the user in the group. Use "none" to explicitly block a user'),
|
|
19
|
+
signature: zod_1.z.string().describe('The signed hash of this data excluding the signature itself'),
|
|
20
|
+
deleted: zod_1.z.boolean().optional().describe('Whether this membership has been deleted (soft delete)'),
|
|
21
|
+
});
|
|
22
|
+
exports.groupMembersTableName = 'GroupMembers';
|
|
23
|
+
const metaData = {
|
|
24
|
+
name: exports.groupMembersTableName,
|
|
25
|
+
description: 'group membership associations',
|
|
26
|
+
primaryKeyName: 'groupMemberId',
|
|
27
|
+
fields: (0, types_1.schemaToFields)(exports.groupMemberSchema),
|
|
28
|
+
indexes: [
|
|
29
|
+
{ fields: ['groupId', 'userId'], unique: true },
|
|
30
|
+
]
|
|
31
|
+
};
|
|
32
|
+
class GroupMembersTable extends orm_1.Table {
|
|
33
|
+
static isPassthrough = false;
|
|
34
|
+
async save(groupMember, opts) {
|
|
35
|
+
if (GroupMembersTable.isPassthrough) {
|
|
36
|
+
return super.save(groupMember, opts);
|
|
37
|
+
}
|
|
38
|
+
const oldGroupMember = groupMember.groupMemberId ? await this.get(groupMember.groupMemberId) : undefined;
|
|
39
|
+
if (await (0, group_permissions_1.isGroupMemberSignatureValid)(groupMember.groupId, groupMember, oldGroupMember)) {
|
|
40
|
+
return super.save(groupMember, opts);
|
|
41
|
+
}
|
|
42
|
+
throw new Error('Group member signature is not valid');
|
|
43
|
+
}
|
|
44
|
+
async delete(groupMemberId) {
|
|
45
|
+
if (GroupMembersTable.isPassthrough) {
|
|
46
|
+
return super.delete(groupMemberId);
|
|
47
|
+
}
|
|
48
|
+
const groupMember = await this.get(groupMemberId);
|
|
49
|
+
if (groupMember) {
|
|
50
|
+
groupMember.deleted = true;
|
|
51
|
+
groupMember.role = group_member_roles_1.GroupMemberRole.None;
|
|
52
|
+
await __1.rpcServerCalls.tableSave(groupMember.groupId, "GroupMembers", groupMember);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** @deprecated Forbidden on GroupsTable; use save() */
|
|
56
|
+
insert(..._args) {
|
|
57
|
+
throw new Error('GroupsTable forbids insert; use save()');
|
|
58
|
+
}
|
|
59
|
+
/** @deprecated Forbidden on GroupsTable; use save() */
|
|
60
|
+
update(..._args) {
|
|
61
|
+
throw new Error('GroupsTable forbids update; use save()');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.GroupMembersTable = GroupMembersTable;
|
|
65
|
+
(0, table_definitions_system_1.registerSystemTableDefinition)(metaData, exports.groupMemberSchema, GroupMembersTable);
|
|
66
|
+
function GroupMembers(dataContext) {
|
|
67
|
+
return (0, user_context_singleton_1.getTableContainer)(dataContext).getTable(metaData, exports.groupMemberSchema, GroupMembersTable);
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const keys_1 = require("../keys");
|
|
4
|
+
const group_permissions_1 = require("./group-permissions");
|
|
5
|
+
// Test the group members signature logic directly without ORM dependencies
|
|
6
|
+
describe('Group Members Signature Logic', () => {
|
|
7
|
+
let testGroupMember;
|
|
8
|
+
let ownerKeys;
|
|
9
|
+
let adminKeys;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
ownerKeys = (0, keys_1.newKeys)();
|
|
12
|
+
adminKeys = (0, keys_1.newKeys)();
|
|
13
|
+
testGroupMember = {
|
|
14
|
+
groupMemberId: 'test-member-1',
|
|
15
|
+
groupId: 'test-group-1',
|
|
16
|
+
userId: 'test-user-1',
|
|
17
|
+
role: group_permissions_1.GroupMemberRole.Reader,
|
|
18
|
+
signature: ''
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
describe('basic signature functionality', () => {
|
|
22
|
+
it('should add signature to group member object', () => {
|
|
23
|
+
const signedGroupMember = (0, keys_1.addSignatureToObject)(testGroupMember, ownerKeys.secretKey);
|
|
24
|
+
expect(signedGroupMember.signature).toBeTruthy();
|
|
25
|
+
expect(signedGroupMember.signature).toContain(':');
|
|
26
|
+
expect(signedGroupMember.groupId).toBe(testGroupMember.groupId);
|
|
27
|
+
expect(signedGroupMember.userId).toBe(testGroupMember.userId);
|
|
28
|
+
expect(signedGroupMember.role).toBe(testGroupMember.role);
|
|
29
|
+
});
|
|
30
|
+
it('should verify valid signature', () => {
|
|
31
|
+
const signedGroupMember = (0, keys_1.addSignatureToObject)(testGroupMember, ownerKeys.secretKey);
|
|
32
|
+
const isValid = (0, keys_1.isObjectSignatureValid)(signedGroupMember);
|
|
33
|
+
expect(isValid).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
it('should reject invalid signature after modification', () => {
|
|
36
|
+
const signedGroupMember = (0, keys_1.addSignatureToObject)(testGroupMember, ownerKeys.secretKey);
|
|
37
|
+
// Modify the group member after signing
|
|
38
|
+
signedGroupMember.role = group_permissions_1.GroupMemberRole.Admin;
|
|
39
|
+
const isValid = (0, keys_1.isObjectSignatureValid)(signedGroupMember);
|
|
40
|
+
expect(isValid).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
it('should extract correct public key from signature', () => {
|
|
43
|
+
const signedGroupMember = (0, keys_1.addSignatureToObject)(testGroupMember, ownerKeys.secretKey);
|
|
44
|
+
const extractedKey = (0, keys_1.getPublicKeyFromObjectSignature)(signedGroupMember);
|
|
45
|
+
expect(extractedKey).toBe(ownerKeys.publicKey);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
describe('permission validation with group context', () => {
|
|
49
|
+
// Note: These tests use basic signature verification since the new permission system
|
|
50
|
+
// requires actual user/group data context which isn't available in unit tests
|
|
51
|
+
it('should allow owner to add any role', () => {
|
|
52
|
+
const memberWithAdminRole = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Admin };
|
|
53
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithAdminRole, ownerKeys.secretKey);
|
|
54
|
+
expect(signedMember.signature).toBeTruthy();
|
|
55
|
+
expect(signedMember.role).toBe(group_permissions_1.GroupMemberRole.Admin);
|
|
56
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
it('should allow admin to add non-admin roles', () => {
|
|
59
|
+
const signedMember = (0, keys_1.addSignatureToObject)(testGroupMember, adminKeys.secretKey);
|
|
60
|
+
expect(signedMember.signature).toBeTruthy();
|
|
61
|
+
expect(signedMember.role).toBe(group_permissions_1.GroupMemberRole.Reader);
|
|
62
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
63
|
+
});
|
|
64
|
+
it('should allow admin to assign admin roles', () => {
|
|
65
|
+
const memberWithAdminRole = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Admin };
|
|
66
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithAdminRole, adminKeys.secretKey);
|
|
67
|
+
expect(signedMember.signature).toBeTruthy();
|
|
68
|
+
expect(signedMember.role).toBe(group_permissions_1.GroupMemberRole.Admin);
|
|
69
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
describe('role assignment rules', () => {
|
|
73
|
+
// Note: These tests focus on basic signature functionality since the new permission system
|
|
74
|
+
// requires actual user/group data context for role-based validation
|
|
75
|
+
it('should allow signing owner role', () => {
|
|
76
|
+
const memberWithOwnerRole = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Owner };
|
|
77
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithOwnerRole, ownerKeys.secretKey);
|
|
78
|
+
expect(signedMember.role).toBe(group_permissions_1.GroupMemberRole.Owner);
|
|
79
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
it('should allow signing founder role', () => {
|
|
82
|
+
const memberWithFounderRole = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Founder };
|
|
83
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithFounderRole, ownerKeys.secretKey);
|
|
84
|
+
expect(signedMember.role).toBe(group_permissions_1.GroupMemberRole.Founder);
|
|
85
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
it('should allow signing writer role', () => {
|
|
88
|
+
const memberWithWriterRole = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Writer };
|
|
89
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithWriterRole, adminKeys.secretKey);
|
|
90
|
+
expect(signedMember.role).toBe(group_permissions_1.GroupMemberRole.Writer);
|
|
91
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
92
|
+
});
|
|
93
|
+
it('should allow setting role to None (blocking user)', () => {
|
|
94
|
+
const memberWithNoneRole = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.None };
|
|
95
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithNoneRole, adminKeys.secretKey);
|
|
96
|
+
expect(signedMember.role).toBe(group_permissions_1.GroupMemberRole.None);
|
|
97
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
it('should handle role modifications with signatures', () => {
|
|
100
|
+
const demotedToWriter = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Writer };
|
|
101
|
+
const signedMember = (0, keys_1.addSignatureToObject)(demotedToWriter, adminKeys.secretKey);
|
|
102
|
+
expect(signedMember.role).toBe(group_permissions_1.GroupMemberRole.Writer);
|
|
103
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
describe('signature tampering detection', () => {
|
|
107
|
+
it('should detect tampered signature', () => {
|
|
108
|
+
const signedMember = (0, keys_1.addSignatureToObject)(testGroupMember, ownerKeys.secretKey);
|
|
109
|
+
// Tamper with signature by adding extra characters
|
|
110
|
+
signedMember.signature = signedMember.signature + 'tampered';
|
|
111
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
it('should detect empty signature', () => {
|
|
114
|
+
testGroupMember.signature = '';
|
|
115
|
+
expect((0, keys_1.isObjectSignatureValid)(testGroupMember)).toBe(false);
|
|
116
|
+
});
|
|
117
|
+
it('should detect malformed signature', () => {
|
|
118
|
+
testGroupMember.signature = 'malformed-signature';
|
|
119
|
+
expect((0, keys_1.isObjectSignatureValid)(testGroupMember)).toBe(false);
|
|
120
|
+
});
|
|
121
|
+
it('should handle signature without colon separator', () => {
|
|
122
|
+
testGroupMember.signature = 'noseparator';
|
|
123
|
+
expect((0, keys_1.isObjectSignatureValid)(testGroupMember)).toBe(false);
|
|
124
|
+
expect((0, keys_1.getPublicKeyFromObjectSignature)(testGroupMember)).toBeUndefined();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
describe('complex group member objects', () => {
|
|
128
|
+
it('should handle all role types', () => {
|
|
129
|
+
const roles = [
|
|
130
|
+
group_permissions_1.GroupMemberRole.None,
|
|
131
|
+
group_permissions_1.GroupMemberRole.Reader,
|
|
132
|
+
group_permissions_1.GroupMemberRole.Writer,
|
|
133
|
+
group_permissions_1.GroupMemberRole.Admin,
|
|
134
|
+
group_permissions_1.GroupMemberRole.Owner,
|
|
135
|
+
group_permissions_1.GroupMemberRole.Founder
|
|
136
|
+
];
|
|
137
|
+
roles.forEach(role => {
|
|
138
|
+
const member = { ...testGroupMember, role };
|
|
139
|
+
const signedMember = (0, keys_1.addSignatureToObject)(member, ownerKeys.secretKey);
|
|
140
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
141
|
+
expect(signedMember.role).toBe(role);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
it('should handle different user and group IDs', () => {
|
|
145
|
+
const memberWithDifferentIds = {
|
|
146
|
+
...testGroupMember,
|
|
147
|
+
groupMemberId: 'member-123',
|
|
148
|
+
groupId: 'group-456',
|
|
149
|
+
userId: 'user-789'
|
|
150
|
+
};
|
|
151
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithDifferentIds, ownerKeys.secretKey);
|
|
152
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
153
|
+
expect(signedMember.groupMemberId).toBe('member-123');
|
|
154
|
+
expect(signedMember.groupId).toBe('group-456');
|
|
155
|
+
expect(signedMember.userId).toBe('user-789');
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
describe('edge cases', () => {
|
|
159
|
+
it('should handle long IDs', () => {
|
|
160
|
+
const memberWithLongIds = {
|
|
161
|
+
...testGroupMember,
|
|
162
|
+
groupMemberId: 'A'.repeat(1000),
|
|
163
|
+
groupId: 'B'.repeat(1000),
|
|
164
|
+
userId: 'C'.repeat(1000)
|
|
165
|
+
};
|
|
166
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithLongIds, ownerKeys.secretKey);
|
|
167
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
168
|
+
});
|
|
169
|
+
it('should handle special characters in IDs', () => {
|
|
170
|
+
const memberWithSpecialIds = {
|
|
171
|
+
...testGroupMember,
|
|
172
|
+
groupMemberId: 'member-🚀-test',
|
|
173
|
+
groupId: 'group-"with"-quotes',
|
|
174
|
+
userId: 'user\nwith\nnewlines'
|
|
175
|
+
};
|
|
176
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithSpecialIds, ownerKeys.secretKey);
|
|
177
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
178
|
+
expect(signedMember.groupMemberId).toContain('🚀');
|
|
179
|
+
});
|
|
180
|
+
it('should handle empty string IDs', () => {
|
|
181
|
+
const memberWithEmptyIds = {
|
|
182
|
+
...testGroupMember,
|
|
183
|
+
groupMemberId: '',
|
|
184
|
+
groupId: '',
|
|
185
|
+
userId: ''
|
|
186
|
+
};
|
|
187
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithEmptyIds, ownerKeys.secretKey);
|
|
188
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
189
|
+
});
|
|
190
|
+
it('should handle modification of existing group member', () => {
|
|
191
|
+
const originalMember = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Reader };
|
|
192
|
+
const modifiedMember = { ...originalMember, role: group_permissions_1.GroupMemberRole.Writer };
|
|
193
|
+
const signedMember = (0, keys_1.addSignatureToObject)(modifiedMember, adminKeys.secretKey);
|
|
194
|
+
expect(signedMember.role).toBe(group_permissions_1.GroupMemberRole.Writer);
|
|
195
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
describe('permission functions with role override', () => {
|
|
199
|
+
// Use the optional signerRole parameter to avoid mocking complexity
|
|
200
|
+
describe('signGroupMemberObject', () => {
|
|
201
|
+
it('should allow admin to sign group member', async () => {
|
|
202
|
+
const memberToSign = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Writer };
|
|
203
|
+
const signedMember = await (0, keys_1.addSignatureToObject)(memberToSign, adminKeys.secretKey);
|
|
204
|
+
expect(signedMember.signature).toBeTruthy();
|
|
205
|
+
expect(signedMember.role).toBe(group_permissions_1.GroupMemberRole.Writer);
|
|
206
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
207
|
+
});
|
|
208
|
+
it('should allow owner to sign group member', async () => {
|
|
209
|
+
const memberToSign = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Admin };
|
|
210
|
+
const signedMember = await (0, keys_1.addSignatureToObject)(memberToSign, ownerKeys.secretKey);
|
|
211
|
+
expect(signedMember.signature).toBeTruthy();
|
|
212
|
+
expect(signedMember.role).toBe(group_permissions_1.GroupMemberRole.Admin);
|
|
213
|
+
expect((0, keys_1.isObjectSignatureValid)(signedMember)).toBe(true);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
describe('verifyGroupMemberSignature with role override', () => {
|
|
217
|
+
it('should verify valid signature with admin signer role', async () => {
|
|
218
|
+
const signedMember = (0, keys_1.addSignatureToObject)(testGroupMember, adminKeys.secretKey);
|
|
219
|
+
const isValid = await (0, group_permissions_1.isGroupMemberSignatureValid)(testGroupMember.groupId, signedMember, undefined, group_permissions_1.GroupMemberRole.Admin);
|
|
220
|
+
expect(isValid).toBe(true);
|
|
221
|
+
});
|
|
222
|
+
it('should verify valid signature with owner signer role', async () => {
|
|
223
|
+
const memberWithAdminRole = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Admin };
|
|
224
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithAdminRole, ownerKeys.secretKey);
|
|
225
|
+
const isValid = await (0, group_permissions_1.isGroupMemberSignatureValid)(memberWithAdminRole.groupId, signedMember, undefined, group_permissions_1.GroupMemberRole.Owner);
|
|
226
|
+
expect(isValid).toBe(true);
|
|
227
|
+
});
|
|
228
|
+
it('should reject when signer role is below admin', async () => {
|
|
229
|
+
const signedMember = (0, keys_1.addSignatureToObject)(testGroupMember, adminKeys.secretKey);
|
|
230
|
+
const isValid = await (0, group_permissions_1.isGroupMemberSignatureValid)(testGroupMember.groupId, signedMember, undefined, group_permissions_1.GroupMemberRole.Writer);
|
|
231
|
+
expect(isValid).toBe(false);
|
|
232
|
+
});
|
|
233
|
+
it('should reject when signer role is below new member role', async () => {
|
|
234
|
+
const memberWithOwnerRole = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Owner };
|
|
235
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithOwnerRole, adminKeys.secretKey);
|
|
236
|
+
const isValid = await (0, group_permissions_1.isGroupMemberSignatureValid)(memberWithOwnerRole.groupId, signedMember, undefined, group_permissions_1.GroupMemberRole.Admin);
|
|
237
|
+
expect(isValid).toBe(false);
|
|
238
|
+
});
|
|
239
|
+
it('should reject when signer role is below old member role', async () => {
|
|
240
|
+
const oldMember = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Owner };
|
|
241
|
+
const newMember = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Writer };
|
|
242
|
+
const signedNewMember = (0, keys_1.addSignatureToObject)(newMember, adminKeys.secretKey);
|
|
243
|
+
const isValid = await (0, group_permissions_1.isGroupMemberSignatureValid)(newMember.groupId, signedNewMember, oldMember, group_permissions_1.GroupMemberRole.Admin);
|
|
244
|
+
expect(isValid).toBe(false);
|
|
245
|
+
});
|
|
246
|
+
it('should allow admin to modify reader role', async () => {
|
|
247
|
+
const memberWithReaderRole = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Reader };
|
|
248
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithReaderRole, adminKeys.secretKey);
|
|
249
|
+
const isValid = await (0, group_permissions_1.isGroupMemberSignatureValid)(memberWithReaderRole.groupId, signedMember, undefined, group_permissions_1.GroupMemberRole.Admin);
|
|
250
|
+
expect(isValid).toBe(true);
|
|
251
|
+
});
|
|
252
|
+
it('should allow owner to modify admin role', async () => {
|
|
253
|
+
const memberWithAdminRole = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Admin };
|
|
254
|
+
const signedMember = (0, keys_1.addSignatureToObject)(memberWithAdminRole, ownerKeys.secretKey);
|
|
255
|
+
const isValid = await (0, group_permissions_1.isGroupMemberSignatureValid)(memberWithAdminRole.groupId, signedMember, undefined, group_permissions_1.GroupMemberRole.Owner);
|
|
256
|
+
expect(isValid).toBe(true);
|
|
257
|
+
});
|
|
258
|
+
it('should reject invalid signature', async () => {
|
|
259
|
+
const signedMember = (0, keys_1.addSignatureToObject)(testGroupMember, adminKeys.secretKey);
|
|
260
|
+
signedMember.signature = 'invalid-signature';
|
|
261
|
+
const isValid = await (0, group_permissions_1.isGroupMemberSignatureValid)(testGroupMember.groupId, signedMember, undefined, group_permissions_1.GroupMemberRole.Admin);
|
|
262
|
+
expect(isValid).toBe(false);
|
|
263
|
+
});
|
|
264
|
+
it('should reject when signature is missing', async () => {
|
|
265
|
+
const memberWithoutSignature = { ...testGroupMember, signature: '' };
|
|
266
|
+
const isValid = await (0, group_permissions_1.isGroupMemberSignatureValid)(testGroupMember.groupId, memberWithoutSignature, undefined, group_permissions_1.GroupMemberRole.Admin);
|
|
267
|
+
expect(isValid).toBe(false);
|
|
268
|
+
});
|
|
269
|
+
it('should handle role modifications correctly', async () => {
|
|
270
|
+
const oldMember = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Writer };
|
|
271
|
+
const newMember = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Admin };
|
|
272
|
+
const signedNewMember = (0, keys_1.addSignatureToObject)(newMember, ownerKeys.secretKey);
|
|
273
|
+
// Owner can promote writer to admin
|
|
274
|
+
const isValid = await (0, group_permissions_1.isGroupMemberSignatureValid)(newMember.groupId, signedNewMember, oldMember, group_permissions_1.GroupMemberRole.Owner);
|
|
275
|
+
expect(isValid).toBe(true);
|
|
276
|
+
});
|
|
277
|
+
it('should handle role demotion correctly', async () => {
|
|
278
|
+
const oldMember = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Admin };
|
|
279
|
+
const newMember = { ...testGroupMember, role: group_permissions_1.GroupMemberRole.Writer };
|
|
280
|
+
const signedNewMember = (0, keys_1.addSignatureToObject)(newMember, ownerKeys.secretKey);
|
|
281
|
+
// Owner can demote admin to writer
|
|
282
|
+
const isValid = await (0, group_permissions_1.isGroupMemberSignatureValid)(newMember.groupId, signedNewMember, oldMember, group_permissions_1.GroupMemberRole.Owner);
|
|
283
|
+
expect(isValid).toBe(true);
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { GroupMemberRole } from './group-member-roles';
|
|
2
|
+
import type { IGroupMember } from './group-members';
|
|
3
|
+
import type { IGroup } from './groups';
|
|
4
|
+
export { GroupMemberRole };
|
|
5
|
+
export declare function getUserRole(groupId: string, userId: string): Promise<GroupMemberRole>;
|
|
6
|
+
export declare function getUserRoleFromPublicKey(groupId: string, publicKey: string): Promise<GroupMemberRole>;
|
|
7
|
+
export declare function verifyGroupSignature(group: IGroup, oldGroup?: IGroup): Promise<void>;
|
|
8
|
+
export declare function isGroupMemberSignatureValid(groupId: string, newGroupMember: IGroupMember, oldGroupMember?: IGroupMember, signerRole?: GroupMemberRole): Promise<boolean>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GroupMemberRole = void 0;
|
|
4
|
+
exports.getUserRole = getUserRole;
|
|
5
|
+
exports.getUserRoleFromPublicKey = getUserRoleFromPublicKey;
|
|
6
|
+
exports.verifyGroupSignature = verifyGroupSignature;
|
|
7
|
+
exports.isGroupMemberSignatureValid = isGroupMemberSignatureValid;
|
|
8
|
+
const context_1 = require("../context");
|
|
9
|
+
const keys_1 = require("../keys");
|
|
10
|
+
const group_member_roles_1 = require("./group-member-roles");
|
|
11
|
+
Object.defineProperty(exports, "GroupMemberRole", { enumerable: true, get: function () { return group_member_roles_1.GroupMemberRole; } });
|
|
12
|
+
async function getUserRole(groupId, userId) {
|
|
13
|
+
const { Groups } = await Promise.resolve().then(() => require('./groups'));
|
|
14
|
+
const { GroupMembers } = await Promise.resolve().then(() => require('./group-members'));
|
|
15
|
+
const userContext = await (0, context_1.getUserContext)();
|
|
16
|
+
const groupDataContext = userContext.getDataContext(groupId);
|
|
17
|
+
const group = await Groups(groupDataContext).get(groupId)
|
|
18
|
+
|| await Groups(userContext.userDataContext).get(groupId);
|
|
19
|
+
// If the group doesn't exist or the current user is explicitly the founder, return Founder role
|
|
20
|
+
if (!group || group.founderUserId === userId) {
|
|
21
|
+
return group_member_roles_1.GroupMemberRole.Founder;
|
|
22
|
+
}
|
|
23
|
+
const groupMembership = await GroupMembers(groupDataContext).findOne({ userId });
|
|
24
|
+
if (groupMembership) {
|
|
25
|
+
return groupMembership.role;
|
|
26
|
+
}
|
|
27
|
+
return group.publicRole || group_member_roles_1.GroupMemberRole.None;
|
|
28
|
+
}
|
|
29
|
+
async function getUserRoleFromPublicKey(groupId, publicKey) {
|
|
30
|
+
const { Users } = await Promise.resolve().then(() => require('./users'));
|
|
31
|
+
const userContext = await (0, context_1.getUserContext)();
|
|
32
|
+
const groupDataContext = userContext.getDataContext(groupId);
|
|
33
|
+
const user = await Users(groupDataContext).findOne({ publicKey })
|
|
34
|
+
|| await Users(userContext.userDataContext).findOne({ publicKey });
|
|
35
|
+
if (user) {
|
|
36
|
+
return getUserRole(groupId, user?.userId);
|
|
37
|
+
}
|
|
38
|
+
return group_member_roles_1.GroupMemberRole.None;
|
|
39
|
+
}
|
|
40
|
+
async function verifyGroupSignature(group, oldGroup) {
|
|
41
|
+
(0, keys_1.verifyObjectSignature)(group);
|
|
42
|
+
const publicKey = (0, keys_1.getPublicKeyFromObjectSignature)(group) ?? '';
|
|
43
|
+
const signerRole = await getUserRoleFromPublicKey(group.groupId, publicKey);
|
|
44
|
+
if (oldGroup && oldGroup.founderUserId !== group.founderUserId && signerRole < group_member_roles_1.GroupMemberRole.Founder) {
|
|
45
|
+
throw new Error('Only group founders can change the founder of the group');
|
|
46
|
+
}
|
|
47
|
+
if (signerRole < group_member_roles_1.GroupMemberRole.Admin) {
|
|
48
|
+
throw new Error('Only group admins can modify group settings');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function isGroupMemberSignatureValid(groupId, newGroupMember, oldGroupMember, signerRole) {
|
|
52
|
+
oldGroupMember ??= newGroupMember;
|
|
53
|
+
// Basic signature verification
|
|
54
|
+
if (!(0, keys_1.isObjectSignatureValid)(newGroupMember)) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
// Get the public key that signed this group member
|
|
58
|
+
const signerPublicKey = (0, keys_1.getPublicKeyFromObjectSignature)(newGroupMember);
|
|
59
|
+
if (!signerPublicKey) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
// Determine signer's role in the group using the user-based permission system
|
|
63
|
+
signerRole ??= await getUserRoleFromPublicKey(groupId, signerPublicKey);
|
|
64
|
+
// Validate permissions for group member modifications
|
|
65
|
+
if (signerRole < group_member_roles_1.GroupMemberRole.Admin) {
|
|
66
|
+
return false; // Only group admins or above can modify group membership
|
|
67
|
+
}
|
|
68
|
+
// admins or above can only modify roles up to their own level
|
|
69
|
+
if (signerRole < newGroupMember.role || signerRole < oldGroupMember.role) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { IGroupMember } from './group-members';
|
|
2
|
+
import { IGroup } from './groups';
|
|
3
|
+
/**
|
|
4
|
+
* Interface representing a shareable group with admin+ members
|
|
5
|
+
*/
|
|
6
|
+
export interface IGroupShare {
|
|
7
|
+
/** The group information */
|
|
8
|
+
group: IGroup;
|
|
9
|
+
/** Members with Admin role or above (Admin=60, Owner=80, Founder=100) */
|
|
10
|
+
groupMembers: IGroupMember[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Generates a GroupShare object containing the group and its admin+ members
|
|
14
|
+
* @param groupId The ID of the group to share
|
|
15
|
+
* @returns Promise<GroupShare> The shareable group data
|
|
16
|
+
* @throws Error if group not found or user lacks permission
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateGroupShare(groupId: string): Promise<IGroupShare>;
|
|
19
|
+
/**
|
|
20
|
+
* Validates that an object has the correct GroupShare structure
|
|
21
|
+
* @param obj Object to validate
|
|
22
|
+
* @returns boolean True if valid GroupShare structure
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateGroupShare(obj: any): obj is IGroupShare;
|
|
25
|
+
/**
|
|
26
|
+
* Estimates the size of a GroupShare object when serialized to JSON
|
|
27
|
+
* @param groupShare The GroupShare object to estimate
|
|
28
|
+
* @returns number Estimated size in characters
|
|
29
|
+
*/
|
|
30
|
+
export declare function estimateGroupShareSize(groupShare: IGroupShare): number;
|
|
31
|
+
/**
|
|
32
|
+
* Checks if a GroupShare object would fit in a QR code of the specified version
|
|
33
|
+
* @param groupShare The GroupShare object to check
|
|
34
|
+
* @param qrVersion QR code version (10, 20, or 40)
|
|
35
|
+
* @returns Object with size info and QR code compatibility
|
|
36
|
+
*/
|
|
37
|
+
export declare function checkQRCodeCompatibility(groupShare: IGroupShare, qrVersion?: 10 | 20 | 40): {
|
|
38
|
+
size: number;
|
|
39
|
+
maxSize: number;
|
|
40
|
+
fits: boolean;
|
|
41
|
+
usagePercent: number;
|
|
42
|
+
qrVersion: 10 | 20 | 40;
|
|
43
|
+
memberCount: number;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Copies text to clipboard with fallback handling
|
|
47
|
+
* @param text Text to copy to clipboard
|
|
48
|
+
* @returns Promise<boolean> True if successful
|
|
49
|
+
*/
|
|
50
|
+
export declare function copyToClipboard(text: string): Promise<boolean>;
|