@fonderie/workspaces 5.2.3 → 5.3.1
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/brain/signatures.md +2 -0
- package/dist/index.cjs +61 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +60 -18
- package/dist/index.js.map +1 -1
- package/dist/middlewares/index.cjs.map +1 -1
- package/dist/middlewares/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -36,6 +36,14 @@ declare class WorkspacesModule implements IFonderieModule {
|
|
|
36
36
|
private provisionPersonalWorkspace;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
declare const DEFAULT_TEMPLATES: {
|
|
40
|
+
"workspace-invitation": {
|
|
41
|
+
subject: string;
|
|
42
|
+
html: string;
|
|
43
|
+
text: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
39
47
|
interface IWorkspaceAddressDTO {
|
|
40
48
|
line1: string;
|
|
41
49
|
line2: string;
|
|
@@ -234,4 +242,4 @@ declare function workspaceExportContributor(store: IStoreAdapter): {
|
|
|
234
242
|
collect: (userId: string) => Promise<unknown>;
|
|
235
243
|
};
|
|
236
244
|
|
|
237
|
-
export { EVENT_KEYS, type IImportMembership, type IImportRole, type IImportWorkspace, IInvitation, type IInvitationDTO, IMember, type IMemberDTO, IRole, type IRoleDTO, IWorkspace, type IWorkspaceDTO, IWorkspaceSettings, type IWorkspaceSettingsDTO, type IWorkspacesConfig, MESSAGE_KEYS, type WorkspacesEventKey, type WorkspacesMessageKey, WorkspacesModule, deleteUserData, exportUserData, importMembership, importRole, importWorkspace, schemas, toInvitationDTO, toMemberDTO, toRoleDTO, toSettingsDTO, toWorkspaceDTO, workspaceExportContributor };
|
|
245
|
+
export { DEFAULT_TEMPLATES, EVENT_KEYS, type IImportMembership, type IImportRole, type IImportWorkspace, IInvitation, type IInvitationDTO, IMember, type IMemberDTO, IRole, type IRoleDTO, IWorkspace, type IWorkspaceDTO, IWorkspaceSettings, type IWorkspaceSettingsDTO, type IWorkspacesConfig, MESSAGE_KEYS, type WorkspacesEventKey, type WorkspacesMessageKey, WorkspacesModule, deleteUserData, exportUserData, importMembership, importRole, importWorkspace, schemas, toInvitationDTO, toMemberDTO, toRoleDTO, toSettingsDTO, toWorkspaceDTO, workspaceExportContributor };
|
package/dist/index.d.ts
CHANGED
|
@@ -36,6 +36,14 @@ declare class WorkspacesModule implements IFonderieModule {
|
|
|
36
36
|
private provisionPersonalWorkspace;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
declare const DEFAULT_TEMPLATES: {
|
|
40
|
+
"workspace-invitation": {
|
|
41
|
+
subject: string;
|
|
42
|
+
html: string;
|
|
43
|
+
text: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
39
47
|
interface IWorkspaceAddressDTO {
|
|
40
48
|
line1: string;
|
|
41
49
|
line2: string;
|
|
@@ -234,4 +242,4 @@ declare function workspaceExportContributor(store: IStoreAdapter): {
|
|
|
234
242
|
collect: (userId: string) => Promise<unknown>;
|
|
235
243
|
};
|
|
236
244
|
|
|
237
|
-
export { EVENT_KEYS, type IImportMembership, type IImportRole, type IImportWorkspace, IInvitation, type IInvitationDTO, IMember, type IMemberDTO, IRole, type IRoleDTO, IWorkspace, type IWorkspaceDTO, IWorkspaceSettings, type IWorkspaceSettingsDTO, type IWorkspacesConfig, MESSAGE_KEYS, type WorkspacesEventKey, type WorkspacesMessageKey, WorkspacesModule, deleteUserData, exportUserData, importMembership, importRole, importWorkspace, schemas, toInvitationDTO, toMemberDTO, toRoleDTO, toSettingsDTO, toWorkspaceDTO, workspaceExportContributor };
|
|
245
|
+
export { DEFAULT_TEMPLATES, EVENT_KEYS, type IImportMembership, type IImportRole, type IImportWorkspace, IInvitation, type IInvitationDTO, IMember, type IMemberDTO, IRole, type IRoleDTO, IWorkspace, type IWorkspaceDTO, IWorkspaceSettings, type IWorkspaceSettingsDTO, type IWorkspacesConfig, MESSAGE_KEYS, type WorkspacesEventKey, type WorkspacesMessageKey, WorkspacesModule, deleteUserData, exportUserData, importMembership, importRole, importWorkspace, schemas, toInvitationDTO, toMemberDTO, toRoleDTO, toSettingsDTO, toWorkspaceDTO, workspaceExportContributor };
|
package/dist/index.js
CHANGED
|
@@ -173,13 +173,21 @@ async function getUserRoles(userId, workspaceId, store) {
|
|
|
173
173
|
);
|
|
174
174
|
}
|
|
175
175
|
async function addRoleToMember(userId, workspaceId, roleId, store) {
|
|
176
|
-
await store.query(
|
|
176
|
+
const rows = await store.query(
|
|
177
177
|
`INSERT INTO fonderie_role_user_workspaces (user_id, workspace_id, role_id, confirmed)
|
|
178
|
-
|
|
178
|
+
SELECT $1, $2, $3, true
|
|
179
|
+
WHERE EXISTS (
|
|
180
|
+
SELECT 1 FROM fonderie_roles r
|
|
181
|
+
WHERE r.id = $3
|
|
182
|
+
AND r.workspace_id = $2
|
|
183
|
+
AND r.is_system = false
|
|
184
|
+
)
|
|
179
185
|
ON CONFLICT (user_id, workspace_id, role_id) DO UPDATE
|
|
180
|
-
SET confirmed = true, removed = false, suspended = false
|
|
186
|
+
SET confirmed = true, removed = false, suspended = false
|
|
187
|
+
RETURNING user_id`,
|
|
181
188
|
[userId, workspaceId, roleId]
|
|
182
189
|
);
|
|
190
|
+
return rows.length > 0;
|
|
183
191
|
}
|
|
184
192
|
async function removeRoleFromMember(userId, workspaceId, roleId, store) {
|
|
185
193
|
const remaining = await store.query(
|
|
@@ -511,10 +519,11 @@ async function findSystemRole(name2, store) {
|
|
|
511
519
|
);
|
|
512
520
|
return row ?? null;
|
|
513
521
|
}
|
|
514
|
-
async function getRoleById(id, store) {
|
|
522
|
+
async function getRoleById(id, workspaceId, store) {
|
|
515
523
|
const [row] = await store.query(
|
|
516
|
-
`SELECT ${SELECT_ROLE} FROM fonderie_roles
|
|
517
|
-
|
|
524
|
+
`SELECT ${SELECT_ROLE} FROM fonderie_roles
|
|
525
|
+
WHERE id = $1 AND (workspace_id = $2 OR is_system = true)`,
|
|
526
|
+
[id, workspaceId]
|
|
518
527
|
);
|
|
519
528
|
return row ?? null;
|
|
520
529
|
}
|
|
@@ -527,9 +536,9 @@ async function listWorkspaceRoles(workspaceId, store) {
|
|
|
527
536
|
[workspaceId]
|
|
528
537
|
);
|
|
529
538
|
}
|
|
530
|
-
async function updateRole(id, opts, store) {
|
|
539
|
+
async function updateRole(id, workspaceId, opts, store) {
|
|
531
540
|
const sets = [];
|
|
532
|
-
const params = [id];
|
|
541
|
+
const params = [id, workspaceId];
|
|
533
542
|
if (opts.name !== void 0) {
|
|
534
543
|
params.push(opts.name);
|
|
535
544
|
sets.push(`name = $${params.length}`);
|
|
@@ -542,11 +551,11 @@ async function updateRole(id, opts, store) {
|
|
|
542
551
|
params.push(opts.active);
|
|
543
552
|
sets.push(`active = $${params.length}`);
|
|
544
553
|
}
|
|
545
|
-
if (sets.length === 0) return getRoleById(id, store);
|
|
554
|
+
if (sets.length === 0) return getRoleById(id, workspaceId, store);
|
|
546
555
|
const [row] = await store.query(
|
|
547
556
|
`UPDATE fonderie_roles
|
|
548
557
|
SET ${sets.join(", ")}
|
|
549
|
-
WHERE id = $1 AND is_system = false
|
|
558
|
+
WHERE id = $1 AND workspace_id = $2 AND is_system = false
|
|
550
559
|
RETURNING ${SELECT_ROLE}`,
|
|
551
560
|
params
|
|
552
561
|
);
|
|
@@ -612,14 +621,14 @@ var RoleModel = class {
|
|
|
612
621
|
findSystem(name2) {
|
|
613
622
|
return findSystemRole(name2, this.store);
|
|
614
623
|
}
|
|
615
|
-
findById(id) {
|
|
616
|
-
return getRoleById(id, this.store);
|
|
624
|
+
findById(id, workspaceId) {
|
|
625
|
+
return getRoleById(id, workspaceId, this.store);
|
|
617
626
|
}
|
|
618
627
|
list(workspaceId) {
|
|
619
628
|
return listWorkspaceRoles(workspaceId, this.store);
|
|
620
629
|
}
|
|
621
|
-
update(id, opts) {
|
|
622
|
-
return updateRole(id, opts, this.store);
|
|
630
|
+
update(id, workspaceId, opts) {
|
|
631
|
+
return updateRole(id, workspaceId, opts, this.store);
|
|
623
632
|
}
|
|
624
633
|
delete(id, workspaceId) {
|
|
625
634
|
return deleteRole(id, workspaceId, this.store);
|
|
@@ -891,7 +900,14 @@ function memberController(store) {
|
|
|
891
900
|
return setApiResponse3(HTTP3.UNPROCESSABLE, "INVALID_PARAMETER", "userId is required");
|
|
892
901
|
if (!roleId)
|
|
893
902
|
return setApiResponse3(HTTP3.UNPROCESSABLE, "INVALID_PARAMETER", "roleId is required");
|
|
894
|
-
await members.addRole(userId, ctx.workspace.id, roleId);
|
|
903
|
+
const assigned = await members.addRole(userId, ctx.workspace.id, roleId);
|
|
904
|
+
if (!assigned) {
|
|
905
|
+
return setApiResponse3(
|
|
906
|
+
HTTP3.UNPROCESSABLE,
|
|
907
|
+
"INVALID_ROLE",
|
|
908
|
+
"Role is not assignable in this workspace."
|
|
909
|
+
);
|
|
910
|
+
}
|
|
895
911
|
return setApiResponse3(HTTP3.OK, "ROLE_ASSIGNED", "Role assigned successfully.");
|
|
896
912
|
},
|
|
897
913
|
async removeRole(ctx) {
|
|
@@ -964,7 +980,7 @@ function roleController(store) {
|
|
|
964
980
|
if (!roleId) {
|
|
965
981
|
return setApiResponse4(HTTP4.UNPROCESSABLE, "INVALID_PARAMETER", "roleId is required");
|
|
966
982
|
}
|
|
967
|
-
const role = await roles.findById(roleId);
|
|
983
|
+
const role = await roles.findById(roleId, ctx.workspace.id);
|
|
968
984
|
if (!role) {
|
|
969
985
|
return setApiResponse4(HTTP4.NOT_FOUND, "NOT_FOUND", "Role not found");
|
|
970
986
|
}
|
|
@@ -995,7 +1011,7 @@ function roleController(store) {
|
|
|
995
1011
|
if (typeof body?.["active"] === "boolean") {
|
|
996
1012
|
opts.active = body["active"];
|
|
997
1013
|
}
|
|
998
|
-
const role = await roles.update(roleId, opts);
|
|
1014
|
+
const role = await roles.update(roleId, ctx.workspace.id, opts);
|
|
999
1015
|
if (!role) {
|
|
1000
1016
|
return setApiResponse4(HTTP4.NOT_FOUND, "NOT_FOUND", "Role not found or is a system role");
|
|
1001
1017
|
}
|
|
@@ -1024,7 +1040,7 @@ function roleController(store) {
|
|
|
1024
1040
|
if (!roleId) {
|
|
1025
1041
|
return setApiResponse4(HTTP4.UNPROCESSABLE, "INVALID_PARAMETER", "roleId is required");
|
|
1026
1042
|
}
|
|
1027
|
-
const role = await roles.findById(roleId);
|
|
1043
|
+
const role = await roles.findById(roleId, ctx.workspace.id);
|
|
1028
1044
|
if (!role) {
|
|
1029
1045
|
return setApiResponse4(HTTP4.NOT_FOUND, "NOT_FOUND", "Role not found");
|
|
1030
1046
|
}
|
|
@@ -1043,6 +1059,10 @@ function roleController(store) {
|
|
|
1043
1059
|
if (!roleId) {
|
|
1044
1060
|
return setApiResponse4(HTTP4.UNPROCESSABLE, "INVALID_PARAMETER", "roleId is required");
|
|
1045
1061
|
}
|
|
1062
|
+
const target = await roles.findById(roleId, ctx.workspace.id);
|
|
1063
|
+
if (!target || target.isSystem) {
|
|
1064
|
+
return setApiResponse4(HTTP4.NOT_FOUND, "NOT_FOUND", "Role not found");
|
|
1065
|
+
}
|
|
1046
1066
|
const perms = body?.["permissions"];
|
|
1047
1067
|
if (!Array.isArray(perms)) {
|
|
1048
1068
|
return setApiResponse4(
|
|
@@ -1417,6 +1437,27 @@ var WorkspacesModule = class {
|
|
|
1417
1437
|
}
|
|
1418
1438
|
};
|
|
1419
1439
|
|
|
1440
|
+
// src/templates.ts
|
|
1441
|
+
var DEFAULT_TEMPLATES = {
|
|
1442
|
+
// Payload carries { token, pin }; the code path is PIN-based, so the copy
|
|
1443
|
+
// uses {{pin}} only — token is intentionally not surfaced.
|
|
1444
|
+
[MESSAGE_KEYS.workspaceInvitation]: {
|
|
1445
|
+
subject: "You've been invited to a workspace",
|
|
1446
|
+
html: `<h1>You’ve been invited</h1>
|
|
1447
|
+
<p>You’ve been invited to join a workspace. Use this code to accept the invitation:</p>
|
|
1448
|
+
<p><span class="pin-code">{{pin}}</span></p>
|
|
1449
|
+
<p class="muted">Enter this code on the invitation screen to join the team.</p>`,
|
|
1450
|
+
text: `You've been invited
|
|
1451
|
+
|
|
1452
|
+
You've been invited to join a workspace. Use this code to accept the invitation: {{pin}}
|
|
1453
|
+
|
|
1454
|
+
Enter this code on the invitation screen to join the team.`
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
var SAMPLE_PAYLOADS = {
|
|
1458
|
+
[MESSAGE_KEYS.workspaceInvitation]: { token: "inv_abc123", pin: "123456" }
|
|
1459
|
+
};
|
|
1460
|
+
|
|
1420
1461
|
// src/middlewares/require-workspace.ts
|
|
1421
1462
|
import { setApiResponse as setApiResponse6, HTTP as HTTP6 } from "@fonderie/core";
|
|
1422
1463
|
var requireWorkspace = async (ctx, next) => {
|
|
@@ -1524,6 +1565,7 @@ function workspaceExportContributor(store) {
|
|
|
1524
1565
|
return { name: "workspaces", collect: (userId) => exportUserData(store, userId) };
|
|
1525
1566
|
}
|
|
1526
1567
|
export {
|
|
1568
|
+
DEFAULT_TEMPLATES,
|
|
1527
1569
|
EVENT_KEYS,
|
|
1528
1570
|
MESSAGE_KEYS,
|
|
1529
1571
|
WorkspacesModule,
|