@meridianjs/meridian 1.30.0 → 1.31.0

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.
Files changed (29) hide show
  1. package/dist/api/admin/users/route.d.ts.map +1 -1
  2. package/dist/api/admin/users/route.js +1 -11
  3. package/dist/api/admin/users/route.js.map +1 -1
  4. package/dist/api/admin/workspaces/[id]/access-requests/[requestId]/route.d.ts +3 -0
  5. package/dist/api/admin/workspaces/[id]/access-requests/[requestId]/route.d.ts.map +1 -0
  6. package/dist/api/admin/workspaces/[id]/access-requests/[requestId]/route.js +53 -0
  7. package/dist/api/admin/workspaces/[id]/access-requests/[requestId]/route.js.map +1 -0
  8. package/dist/api/admin/workspaces/[id]/access-requests/route.d.ts +4 -0
  9. package/dist/api/admin/workspaces/[id]/access-requests/route.d.ts.map +1 -0
  10. package/dist/api/admin/workspaces/[id]/access-requests/route.js +111 -0
  11. package/dist/api/admin/workspaces/[id]/access-requests/route.js.map +1 -0
  12. package/dist/api/admin/workspaces/[id]/members/batch/route.d.ts.map +1 -1
  13. package/dist/api/admin/workspaces/[id]/members/batch/route.js +56 -59
  14. package/dist/api/admin/workspaces/[id]/members/batch/route.js.map +1 -1
  15. package/dist/api/admin/workspaces/[id]/members/route.d.ts.map +1 -1
  16. package/dist/api/admin/workspaces/[id]/members/route.js +41 -44
  17. package/dist/api/admin/workspaces/[id]/members/route.js.map +1 -1
  18. package/dist/api/admin/workspaces/route.d.ts.map +1 -1
  19. package/dist/api/admin/workspaces/route.js +33 -24
  20. package/dist/api/admin/workspaces/route.js.map +1 -1
  21. package/dist/api/admin/workspaces/search/route.d.ts +3 -0
  22. package/dist/api/admin/workspaces/search/route.d.ts.map +1 -0
  23. package/dist/api/admin/workspaces/search/route.js +17 -0
  24. package/dist/api/admin/workspaces/search/route.js.map +1 -0
  25. package/dist/subscribers/workspace-access-requested.d.ts +13 -0
  26. package/dist/subscribers/workspace-access-requested.d.ts.map +1 -0
  27. package/dist/subscribers/workspace-access-requested.js +43 -0
  28. package/dist/subscribers/workspace-access-requested.js.map +1 -0
  29. package/package.json +14 -14
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/admin/users/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAErD,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBAmCpE,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/admin/users/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAErD,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBAsBpE,CAAA"}
@@ -1,15 +1,5 @@
1
1
  export const GET = async (req, res, next) => {
2
2
  try {
3
- const roles = req.user?.roles ?? [];
4
- const permissions = req.user?.permissions ?? [];
5
- const canSearch = roles.includes("super-admin") ||
6
- roles.includes("admin") ||
7
- permissions.includes("workspace:admin") ||
8
- permissions.includes("member:invite");
9
- if (!canSearch) {
10
- res.status(403).json({ error: { message: "Forbidden" } });
11
- return;
12
- }
13
3
  const userService = req.scope.resolve("userModuleService");
14
4
  const limit = Math.min(Number(req.query.limit) || 20, 100);
15
5
  const offset = Number(req.query.offset) || 0;
@@ -22,7 +12,7 @@ export const GET = async (req, res, next) => {
22
12
  { last_name: { $ilike: `%${q}%` } },
23
13
  ];
24
14
  }
25
- const [users, count] = await userService.listAndCountUsers(filters, { limit, offset });
15
+ const [users, count] = await userService.listAndCountUsers(filters, { limit, offset, orderBy: { created_at: "DESC" } });
26
16
  const safeUsers = users.map(({ password_hash: _, ...u }) => u);
27
17
  res.json({ users: safeUsers, count, limit, offset });
28
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/admin/users/route.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;IACvE,IAAI,CAAC;QACH,MAAM,KAAK,GAAa,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAA;QAC7C,MAAM,WAAW,GAAa,GAAG,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAA;QACzD,MAAM,SAAS,GACb,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC;YAC7B,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;YACvB,WAAW,CAAC,QAAQ,CAAC,iBAAiB,CAAC;YACvC,WAAW,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAA;QAEvC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC,CAAA;YACzD,OAAM;QACR,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAQ,CAAA;QACjE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAA;QAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAC5C,MAAM,CAAC,GAAG,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QAEnE,MAAM,OAAO,GAA4B,EAAE,CAAA;QAC3C,IAAI,CAAC,EAAE,CAAC;YACN,OAAO,CAAC,GAAG,GAAG;gBACZ,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;gBAC/B,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;gBACpC,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;aACpC,CAAA;QACH,CAAC;QAED,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACtF,MAAM,SAAS,GAAI,KAAe,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;QACzE,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IACtD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,CAAA;IACX,CAAC;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/admin/users/route.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;IACvE,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAQ,CAAA;QACjE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAA;QAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAC5C,MAAM,CAAC,GAAG,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QAEnE,MAAM,OAAO,GAA4B,EAAE,CAAA;QAC3C,IAAI,CAAC,EAAE,CAAC;YACN,OAAO,CAAC,GAAG,GAAG;gBACZ,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;gBAC/B,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;gBACpC,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;aACpC,CAAA;QACH,CAAC;QAED,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC,CAAA;QACvH,MAAM,SAAS,GAAI,KAAe,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;QACzE,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IACtD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,CAAA;IACX,CAAC;AACH,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { Response } from "express";
2
+ export declare const PATCH: (req: any, res: Response) => Promise<void>;
3
+ //# sourceMappingURL=route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/admin/workspaces/[id]/access-requests/[requestId]/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC,eAAO,MAAM,KAAK,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAgElD,CAAA"}
@@ -0,0 +1,53 @@
1
+ export const PATCH = async (req, res) => {
2
+ const workspaceService = req.scope.resolve("workspaceModuleService");
3
+ const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
4
+ const notificationService = req.scope.resolve("notificationModuleService");
5
+ const userService = req.scope.resolve("userModuleService");
6
+ const workspace = await workspaceService.retrieveWorkspace(req.params.id);
7
+ if (!workspace) {
8
+ res.status(404).json({ error: { message: "Workspace not found" } });
9
+ return;
10
+ }
11
+ // Only workspace admins or global admins can approve/deny
12
+ const roles = req.user?.roles ?? [];
13
+ const isGlobalAdmin = roles.includes("super-admin") || roles.includes("admin");
14
+ if (!isGlobalAdmin) {
15
+ const membership = await workspaceMemberService.getMembership(req.params.id, req.user?.id);
16
+ if (!membership || membership.role !== "admin") {
17
+ res.status(403).json({ error: { message: "Workspace admin access required" } });
18
+ return;
19
+ }
20
+ }
21
+ const accessRequest = await workspaceMemberService.getAccessRequest(req.params.requestId);
22
+ if (!accessRequest || accessRequest.workspace_id !== req.params.id) {
23
+ res.status(404).json({ error: { message: "Access request not found" } });
24
+ return;
25
+ }
26
+ if (accessRequest.status !== "pending") {
27
+ res.status(409).json({ error: { message: "Access request has already been resolved" } });
28
+ return;
29
+ }
30
+ const { action } = req.body;
31
+ if (action !== "approve" && action !== "deny") {
32
+ res.status(400).json({ error: { message: "action must be 'approve' or 'deny'" } });
33
+ return;
34
+ }
35
+ if (action === "approve") {
36
+ await workspaceMemberService.ensureMember(req.params.id, accessRequest.user_id, "member");
37
+ }
38
+ const updated = await workspaceMemberService.updateAccessRequestStatus(req.params.requestId, action === "approve" ? "approved" : "denied");
39
+ // Notify the requesting user of the outcome
40
+ const approvedMsg = `Your request to join ${workspace.name} has been approved`;
41
+ const deniedMsg = `Your request to join ${workspace.name} was not approved`;
42
+ notificationService.createNotification({
43
+ user_id: accessRequest.user_id,
44
+ entity_type: "workspace_access_request",
45
+ entity_id: accessRequest.id,
46
+ action: action === "approve" ? "access_approved" : "access_denied",
47
+ message: action === "approve" ? approvedMsg : deniedMsg,
48
+ workspace_id: req.params.id,
49
+ metadata: { workspace_id: req.params.id, workspace_slug: workspace.slug },
50
+ }).catch(() => { });
51
+ res.json({ access_request: updated });
52
+ };
53
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../../src/api/admin/workspaces/[id]/access-requests/[requestId]/route.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Response } from "express";
2
+ export declare const GET: (req: any, res: Response) => Promise<void>;
3
+ export declare const POST: (req: any, res: Response) => Promise<void>;
4
+ //# sourceMappingURL=route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/api/admin/workspaces/[id]/access-requests/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAwBvC,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAyBhD,CAAA;AAED,eAAO,MAAM,IAAI,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAsFjD,CAAA"}
@@ -0,0 +1,111 @@
1
+ async function assertWorkspaceAdmin(req, res) {
2
+ const workspaceService = req.scope.resolve("workspaceModuleService");
3
+ const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
4
+ const workspace = await workspaceService.retrieveWorkspace(req.params.id);
5
+ if (!workspace) {
6
+ res.status(404).json({ error: { message: "Workspace not found" } });
7
+ return false;
8
+ }
9
+ const roles = req.user?.roles ?? [];
10
+ const isGlobalAdmin = roles.includes("super-admin") || roles.includes("admin");
11
+ if (isGlobalAdmin)
12
+ return true;
13
+ const membership = await workspaceMemberService.getMembership(req.params.id, req.user?.id);
14
+ if (!membership || membership.role !== "admin") {
15
+ res.status(403).json({ error: { message: "Workspace admin access required" } });
16
+ return false;
17
+ }
18
+ return true;
19
+ }
20
+ export const GET = async (req, res) => {
21
+ if (!await assertWorkspaceAdmin(req, res))
22
+ return;
23
+ const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
24
+ const userService = req.scope.resolve("userModuleService");
25
+ const requests = await workspaceMemberService.listPendingAccessRequests(req.params.id);
26
+ const userIds = [...new Set(requests.map((r) => r.user_id))];
27
+ const userMap = userIds.length > 0 ? await userService.listUsersByIds(userIds) : new Map();
28
+ const enriched = requests.map((r) => {
29
+ const user = userMap.get(r.user_id) ?? null;
30
+ return {
31
+ id: r.id,
32
+ workspace_id: r.workspace_id,
33
+ user_id: r.user_id,
34
+ message: r.message,
35
+ status: r.status,
36
+ created_at: r.created_at,
37
+ user: user ? { id: user.id, email: user.email, first_name: user.first_name, last_name: user.last_name } : null,
38
+ };
39
+ });
40
+ res.json({ access_requests: enriched, count: enriched.length });
41
+ };
42
+ export const POST = async (req, res) => {
43
+ const workspaceService = req.scope.resolve("workspaceModuleService");
44
+ const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
45
+ const notificationService = req.scope.resolve("notificationModuleService");
46
+ const userService = req.scope.resolve("userModuleService");
47
+ const workspace = await workspaceService.retrieveWorkspace(req.params.id);
48
+ if (!workspace) {
49
+ res.status(404).json({ error: { message: "Workspace not found" } });
50
+ return;
51
+ }
52
+ const userId = req.user?.id;
53
+ if (!userId) {
54
+ res.status(401).json({ error: { message: "Unauthorized" } });
55
+ return;
56
+ }
57
+ // Cannot request if already a member
58
+ const alreadyMember = await workspaceMemberService.isMember(req.params.id, userId);
59
+ if (alreadyMember) {
60
+ res.status(409).json({ error: { message: "You are already a member of this workspace" } });
61
+ return;
62
+ }
63
+ // Cannot request if already has a pending request
64
+ const existingRequest = await workspaceMemberService.getPendingRequest(req.params.id, userId);
65
+ if (existingRequest) {
66
+ res.status(409).json({ error: { message: "You already have a pending access request for this workspace" } });
67
+ return;
68
+ }
69
+ const { message } = req.body;
70
+ const accessRequest = await workspaceMemberService.createAccessRequest({
71
+ workspace_id: req.params.id,
72
+ user_id: userId,
73
+ message: message ?? null,
74
+ });
75
+ // Notify workspace admins
76
+ const [wsMembers] = await workspaceMemberService.listAndCountWorkspaceMembers({ workspace_id: req.params.id, role: "admin" }, { limit: 100 });
77
+ const requestingUser = await userService.retrieveUser(userId).catch(() => null);
78
+ const requesterName = requestingUser
79
+ ? `${requestingUser.first_name ?? ""} ${requestingUser.last_name ?? ""}`.trim() || requestingUser.email
80
+ : "A user";
81
+ const notifyUserIds = [...new Set(wsMembers.map((m) => m.user_id))];
82
+ await Promise.all(notifyUserIds.map((adminId) => notificationService.createNotification({
83
+ user_id: adminId,
84
+ entity_type: "workspace_access_request",
85
+ entity_id: accessRequest.id,
86
+ action: "access_requested",
87
+ message: `${requesterName} requested access to ${workspace.name}`,
88
+ workspace_id: req.params.id,
89
+ metadata: {
90
+ requesting_user_id: userId,
91
+ requesting_user_name: requesterName,
92
+ workspace_id: req.params.id,
93
+ workspace_slug: workspace.slug,
94
+ },
95
+ }).catch(() => { })));
96
+ // Emit event for subscriber (email + SSE broadcast)
97
+ const eventBus = req.scope.resolve("eventBus");
98
+ eventBus.emit({
99
+ name: "workspace.access_requested",
100
+ data: {
101
+ access_request_id: accessRequest.id,
102
+ workspace_id: req.params.id,
103
+ user_id: userId,
104
+ requester_name: requesterName,
105
+ requester_email: requestingUser?.email ?? null,
106
+ admin_user_ids: notifyUserIds,
107
+ },
108
+ }).catch(() => { });
109
+ res.status(201).json({ access_request: accessRequest });
110
+ };
111
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../src/api/admin/workspaces/[id]/access-requests/route.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/admin/workspaces/[id]/members/batch/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAGrD,eAAO,MAAM,IAAI,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBA6ErE,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/admin/workspaces/[id]/members/batch/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAErD,eAAO,MAAM,IAAI,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBA2ErE,CAAA"}
@@ -1,71 +1,68 @@
1
- import { requirePermission } from "@meridianjs/auth";
2
1
  export const POST = async (req, res, next) => {
3
- requirePermission("member:invite")(req, res, async () => {
4
- try {
5
- const workspaceService = req.scope.resolve("workspaceModuleService");
6
- const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
7
- const workspace = await workspaceService.retrieveWorkspace(req.params.id);
8
- if (!workspace) {
9
- res.status(404).json({ error: { message: "Workspace not found" } });
2
+ try {
3
+ const workspaceService = req.scope.resolve("workspaceModuleService");
4
+ const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
5
+ const workspace = await workspaceService.retrieveWorkspace(req.params.id);
6
+ if (!workspace) {
7
+ res.status(404).json({ error: { message: "Workspace not found" } });
8
+ return;
9
+ }
10
+ const roles = req.user?.roles ?? [];
11
+ const isPrivileged = roles.includes("super-admin") || roles.includes("admin");
12
+ if (workspace.is_private || !isPrivileged) {
13
+ const membership = await workspaceMemberService.getMembership(req.params.id, req.user?.id);
14
+ if (!membership) {
15
+ res.status(403).json({ error: { message: "Forbidden — not a member of this workspace" } });
10
16
  return;
11
17
  }
12
- const roles = req.user?.roles ?? [];
13
- const isPrivileged = roles.includes("super-admin") || roles.includes("admin");
14
- if (workspace.is_private || !isPrivileged) {
15
- const membership = await workspaceMemberService.getMembership(req.params.id, req.user?.id);
16
- if (!membership) {
17
- res.status(403).json({ error: { message: "Forbidden — not a member of this workspace" } });
18
- return;
19
- }
20
- }
21
- const { user_ids, role, app_role_id } = req.body;
22
- if (!Array.isArray(user_ids) || user_ids.length === 0) {
23
- res.status(400).json({ error: { message: "user_ids must be a non-empty array" } });
24
- return;
18
+ }
19
+ const { user_ids, role, app_role_id } = req.body;
20
+ if (!Array.isArray(user_ids) || user_ids.length === 0) {
21
+ res.status(400).json({ error: { message: "user_ids must be a non-empty array" } });
22
+ return;
23
+ }
24
+ const wsRole = role === "member" ? "member" : "admin";
25
+ let added = 0;
26
+ let skipped = 0;
27
+ for (const userId of user_ids) {
28
+ const existing = await workspaceMemberService.getMembership(req.params.id, userId);
29
+ if (existing) {
30
+ skipped++;
31
+ continue;
25
32
  }
26
- const wsRole = role === "member" ? "member" : "admin";
27
- let added = 0;
28
- let skipped = 0;
29
- for (const userId of user_ids) {
30
- const existing = await workspaceMemberService.getMembership(req.params.id, userId);
31
- if (existing) {
32
- skipped++;
33
- continue;
34
- }
35
- await workspaceMemberService.createWorkspaceMember({
33
+ await workspaceMemberService.createWorkspaceMember({
34
+ workspace_id: req.params.id,
35
+ user_id: userId,
36
+ role: wsRole,
37
+ });
38
+ added++;
39
+ const eventBus = req.scope.resolve("eventBus");
40
+ eventBus.emit({
41
+ name: "workspace.member_added",
42
+ data: {
36
43
  workspace_id: req.params.id,
37
44
  user_id: userId,
38
45
  role: wsRole,
39
- });
40
- added++;
41
- const eventBus = req.scope.resolve("eventBus");
42
- eventBus.emit({
43
- name: "workspace.member_added",
44
- data: {
45
- workspace_id: req.params.id,
46
- user_id: userId,
47
- role: wsRole,
48
- actor_id: req.user?.id ?? "system",
49
- },
50
- }).catch(() => { });
51
- }
52
- // Optionally assign custom app role to all added users
53
- if (app_role_id) {
54
- try {
55
- const userService = req.scope.resolve("userModuleService");
56
- for (const userId of user_ids) {
57
- await userService.updateUser(userId, { app_role_id }).catch(() => { });
58
- }
59
- }
60
- catch {
61
- // Non-fatal
46
+ actor_id: req.user?.id ?? "system",
47
+ },
48
+ }).catch(() => { });
49
+ }
50
+ // Optionally assign custom app role to all added users
51
+ if (app_role_id) {
52
+ try {
53
+ const userService = req.scope.resolve("userModuleService");
54
+ for (const userId of user_ids) {
55
+ await userService.updateUser(userId, { app_role_id }).catch(() => { });
62
56
  }
63
57
  }
64
- res.status(201).json({ added, skipped });
65
- }
66
- catch (err) {
67
- next(err);
58
+ catch {
59
+ // Non-fatal
60
+ }
68
61
  }
69
- });
62
+ res.status(201).json({ added, skipped });
63
+ }
64
+ catch (err) {
65
+ next(err);
66
+ }
70
67
  };
71
68
  //# sourceMappingURL=route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../../src/api/admin/workspaces/[id]/members/batch/route.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../../src/api/admin/workspaces/[id]/members/batch/route.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;IACxE,IAAI,CAAC;QACH,MAAM,gBAAgB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,wBAAwB,CAAQ,CAAA;QAC3E,MAAM,sBAAsB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,8BAA8B,CAAQ,CAAA;QAEvF,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACzE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,qBAAqB,EAAE,EAAE,CAAC,CAAA;YACnE,OAAM;QACR,CAAC;QAED,MAAM,KAAK,GAAa,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAA;QAC7C,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAE7E,IAAI,SAAS,CAAC,UAAU,IAAI,CAAC,YAAY,EAAE,CAAC;YAC1C,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;YAC1F,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,4CAA4C,EAAE,EAAE,CAAC,CAAA;gBAC1F,OAAM;YACR,CAAC;QACH,CAAC;QAED,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC,IAAI,CAAA;QAEhD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,oCAAoC,EAAE,EAAE,CAAC,CAAA;YAClF,OAAM;QACR,CAAC;QAED,MAAM,MAAM,GAAuB,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAA;QACzE,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,IAAI,OAAO,GAAG,CAAC,CAAA;QAEf,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;YAClF,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,EAAE,CAAA;gBACT,SAAQ;YACV,CAAC;YAED,MAAM,sBAAsB,CAAC,qBAAqB,CAAC;gBACjD,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE;gBAC3B,OAAO,EAAE,MAAM;gBACf,IAAI,EAAE,MAAM;aACb,CAAC,CAAA;YACF,KAAK,EAAE,CAAA;YAEP,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAQ,CAAA;YACrD,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,wBAAwB;gBAC9B,IAAI,EAAE;oBACJ,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE;oBAC3B,OAAO,EAAE,MAAM;oBACf,IAAI,EAAE,MAAM;oBACZ,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,QAAQ;iBACnC;aACF,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QACpB,CAAC;QAED,uDAAuD;QACvD,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAQ,CAAA;gBACjE,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;oBAC9B,MAAM,WAAW,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;gBACvE,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC;QAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,CAAA;IACX,CAAC;AACH,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/api/admin/workspaces/[id]/members/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AA0BrD,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBA2BhD,CAAA;AAED,eAAO,MAAM,IAAI,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBAsDrE,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../src/api/admin/workspaces/[id]/members/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAyBrD,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBA2BhD,CAAA;AAED,eAAO,MAAM,IAAI,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBAoDrE,CAAA"}
@@ -1,4 +1,3 @@
1
- import { requirePermission } from "@meridianjs/auth";
2
1
  async function assertWorkspaceAccess(req, res) {
3
2
  const workspaceService = req.scope.resolve("workspaceModuleService");
4
3
  const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
@@ -41,53 +40,51 @@ export const GET = async (req, res) => {
41
40
  res.json({ members: enriched, count: enriched.length });
42
41
  };
43
42
  export const POST = async (req, res, next) => {
44
- requirePermission("member:invite")(req, res, async () => {
45
- try {
46
- if (!await assertWorkspaceAccess(req, res))
47
- return;
48
- const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
49
- const { user_id, role, app_role_id } = req.body;
50
- if (!user_id) {
51
- res.status(400).json({ error: { message: "user_id is required" } });
52
- return;
43
+ try {
44
+ if (!await assertWorkspaceAccess(req, res))
45
+ return;
46
+ const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
47
+ const { user_id, role, app_role_id } = req.body;
48
+ if (!user_id) {
49
+ res.status(400).json({ error: { message: "user_id is required" } });
50
+ return;
51
+ }
52
+ const existing = await workspaceMemberService.getMembership(req.params.id, user_id);
53
+ if (existing) {
54
+ res.status(409).json({ error: { message: "User is already a member of this workspace" } });
55
+ return;
56
+ }
57
+ // workspace_member.role only supports "admin" | "member" — map super-admin → admin
58
+ const wsRole = role === "member" ? "member" : "admin";
59
+ const member = await workspaceMemberService.createWorkspaceMember({
60
+ workspace_id: req.params.id,
61
+ user_id,
62
+ role: wsRole,
63
+ });
64
+ // Optionally assign custom app role to the user
65
+ if (app_role_id) {
66
+ try {
67
+ const userService = req.scope.resolve("userModuleService");
68
+ await userService.updateUser(user_id, { app_role_id });
53
69
  }
54
- const existing = await workspaceMemberService.getMembership(req.params.id, user_id);
55
- if (existing) {
56
- res.status(409).json({ error: { message: "User is already a member of this workspace" } });
57
- return;
70
+ catch {
71
+ // Non-fatal
58
72
  }
59
- // workspace_member.role only supports "admin" | "member" — map super-admin → admin
60
- const wsRole = role === "member" ? "member" : "admin";
61
- const member = await workspaceMemberService.createWorkspaceMember({
73
+ }
74
+ const eventBus = req.scope.resolve("eventBus");
75
+ eventBus.emit({
76
+ name: "workspace.member_added",
77
+ data: {
62
78
  workspace_id: req.params.id,
63
79
  user_id,
64
80
  role: wsRole,
65
- });
66
- // Optionally assign custom app role to the user
67
- if (app_role_id) {
68
- try {
69
- const userService = req.scope.resolve("userModuleService");
70
- await userService.updateUser(user_id, { app_role_id });
71
- }
72
- catch {
73
- // Non-fatal
74
- }
75
- }
76
- const eventBus = req.scope.resolve("eventBus");
77
- eventBus.emit({
78
- name: "workspace.member_added",
79
- data: {
80
- workspace_id: req.params.id,
81
- user_id,
82
- role: wsRole,
83
- actor_id: req.user?.id ?? "system",
84
- },
85
- }).catch(() => { });
86
- res.status(201).json({ member });
87
- }
88
- catch (err) {
89
- next(err);
90
- }
91
- });
81
+ actor_id: req.user?.id ?? "system",
82
+ },
83
+ }).catch(() => { });
84
+ res.status(201).json({ member });
85
+ }
86
+ catch (err) {
87
+ next(err);
88
+ }
92
89
  };
93
90
  //# sourceMappingURL=route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../src/api/admin/workspaces/[id]/members/route.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../../src/api/admin/workspaces/[id]/members/route.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/admin/workspaces/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAGrD,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAuChD,CAAA;AAED,eAAO,MAAM,IAAI,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBA8BrE,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/admin/workspaces/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAErD,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAuChD,CAAA;AAED,eAAO,MAAM,IAAI,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBA0CrE,CAAA"}
@@ -1,4 +1,3 @@
1
- import { requirePermission } from "@meridianjs/auth";
2
1
  export const GET = async (req, res) => {
3
2
  const workspaceService = req.scope.resolve("workspaceModuleService");
4
3
  const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
@@ -30,31 +29,41 @@ export const GET = async (req, res) => {
30
29
  res.json({ workspaces, count, limit, offset });
31
30
  };
32
31
  export const POST = async (req, res, next) => {
33
- requirePermission("workspace:create")(req, res, async () => {
34
- try {
35
- const workspaceService = req.scope.resolve("workspaceModuleService");
36
- const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
37
- const { name, plan, is_private } = req.body;
38
- if (!name || typeof name !== "string" || name.trim().length === 0) {
39
- res.status(400).json({ error: { message: "name is required" } });
40
- return;
41
- }
42
- const slug = workspaceService.generateSlug(name.trim());
43
- const workspace = await workspaceService.createWorkspace({
44
- name: name.trim(),
45
- slug,
46
- plan: plan ?? "free",
47
- is_private: is_private ?? false,
32
+ try {
33
+ const workspaceService = req.scope.resolve("workspaceModuleService");
34
+ const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
35
+ const { name, plan, is_private } = req.body;
36
+ if (!name || typeof name !== "string" || name.trim().length === 0) {
37
+ res.status(400).json({ error: { message: "name is required" } });
38
+ return;
39
+ }
40
+ const slug = workspaceService.generateSlug(name.trim());
41
+ // Reject duplicate workspace slugs (same name resolves to same slug)
42
+ const existing = await workspaceService.retrieveWorkspaceBySlug(slug);
43
+ if (existing) {
44
+ res.status(409).json({
45
+ error: {
46
+ message: `A workspace named "${existing.name}" already exists.`,
47
+ code: "WORKSPACE_EXISTS",
48
+ workspace: { id: existing.id, name: existing.name, slug: existing.slug },
49
+ },
48
50
  });
49
- // Auto-create workspace membership for the creator (admin role)
50
- if (req.user?.id) {
51
- await workspaceMemberService.ensureMember(workspace.id, req.user.id, "admin");
52
- }
53
- res.status(201).json({ workspace });
51
+ return;
54
52
  }
55
- catch (err) {
56
- next(err);
53
+ const workspace = await workspaceService.createWorkspace({
54
+ name: name.trim(),
55
+ slug,
56
+ plan: plan ?? "free",
57
+ is_private: is_private ?? false,
58
+ });
59
+ // Auto-create workspace membership for the creator (admin role)
60
+ if (req.user?.id) {
61
+ await workspaceMemberService.ensureMember(workspace.id, req.user.id, "admin");
57
62
  }
58
- });
63
+ res.status(201).json({ workspace });
64
+ }
65
+ catch (err) {
66
+ next(err);
67
+ }
59
68
  };
60
69
  //# sourceMappingURL=route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/admin/workspaces/route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEpD,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,EAAE;IACnD,MAAM,gBAAgB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,wBAAwB,CAAQ,CAAA;IAC3E,MAAM,sBAAsB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,8BAA8B,CAAQ,CAAA;IACvF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAA;IAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAE5C,MAAM,KAAK,GAAa,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAA;IAC7C,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IAE7E,yFAAyF;IACzF,MAAM,gBAAgB,GAAG,MAAM,sBAAsB,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEzF,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,MAAM,gBAAgB,CAAC,sBAAsB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QAChG,iEAAiE;QACjE,IAAI,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;YACpE,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;YAC9C,OAAM;QACR,CAAC;QACD,yDAAyD;QACzD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAA;QAC3C,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAChC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CACjD,CAAA;QACD,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACzE,OAAM;IACR,CAAC;IAED,+CAA+C;IAC/C,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACrD,OAAM;IACR,CAAC;IAED,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,MAAM,gBAAgB,CAAC,sBAAsB,CACvE,EAAE,EAAE,EAAE,gBAAgB,EAAE,EACxB,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAA;IACD,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;AAChD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;IACxE,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE;QACzD,IAAI,CAAC;YACH,MAAM,gBAAgB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,wBAAwB,CAAQ,CAAA;YAC3E,MAAM,sBAAsB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,8BAA8B,CAAQ,CAAA;YACvF,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC,IAAI,CAAA;YAE3C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAClE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAA;gBAChE,OAAM;YACR,CAAC;YAED,MAAM,IAAI,GAAG,gBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;YACvD,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,eAAe,CAAC;gBACvD,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;gBACjB,IAAI;gBACJ,IAAI,EAAE,IAAI,IAAI,MAAM;gBACpB,UAAU,EAAE,UAAU,IAAI,KAAK;aAChC,CAAC,CAAA;YAEF,gEAAgE;YAChE,IAAI,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;gBACjB,MAAM,sBAAsB,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;YAC/E,CAAC;YAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,CAAA;QACX,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA"}
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/admin/workspaces/route.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,EAAE;IACnD,MAAM,gBAAgB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,wBAAwB,CAAQ,CAAA;IAC3E,MAAM,sBAAsB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,8BAA8B,CAAQ,CAAA;IACvF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAA;IAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAE5C,MAAM,KAAK,GAAa,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAA;IAC7C,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IAE7E,yFAAyF;IACzF,MAAM,gBAAgB,GAAG,MAAM,sBAAsB,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEzF,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,MAAM,gBAAgB,CAAC,sBAAsB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QAChG,iEAAiE;QACjE,IAAI,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;YACpE,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;YAC9C,OAAM;QACR,CAAC;QACD,yDAAyD;QACzD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAA;QAC3C,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAChC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CACjD,CAAA;QACD,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACzE,OAAM;IACR,CAAC;IAED,+CAA+C;IAC/C,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACrD,OAAM;IACR,CAAC;IAED,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,MAAM,gBAAgB,CAAC,sBAAsB,CACvE,EAAE,EAAE,EAAE,gBAAgB,EAAE,EACxB,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAA;IACD,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;AAChD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;IACxE,IAAI,CAAC;QACH,MAAM,gBAAgB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,wBAAwB,CAAQ,CAAA;QAC3E,MAAM,sBAAsB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,8BAA8B,CAAQ,CAAA;QACvF,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC,IAAI,CAAA;QAE3C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAA;YAChE,OAAM;QACR,CAAC;QAED,MAAM,IAAI,GAAG,gBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;QAEvD,qEAAqE;QACrE,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAA;QACrE,IAAI,QAAQ,EAAE,CAAC;YACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE;oBACL,OAAO,EAAE,sBAAsB,QAAQ,CAAC,IAAI,mBAAmB;oBAC/D,IAAI,EAAE,kBAAkB;oBACxB,SAAS,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE;iBACzE;aACF,CAAC,CAAA;YACF,OAAM;QACR,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,eAAe,CAAC;YACvD,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;YACjB,IAAI;YACJ,IAAI,EAAE,IAAI,IAAI,MAAM;YACpB,UAAU,EAAE,UAAU,IAAI,KAAK;SAChC,CAAC,CAAA;QAEF,gEAAgE;QAChE,IAAI,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;YACjB,MAAM,sBAAsB,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;QAC/E,CAAC;QAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,CAAA;IACX,CAAC;AACH,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { Response } from "express";
2
+ export declare const GET: (req: any, res: Response) => Promise<void>;
3
+ //# sourceMappingURL=route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/api/admin/workspaces/search/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBA0BhD,CAAA"}
@@ -0,0 +1,17 @@
1
+ export const GET = async (req, res) => {
2
+ const workspaceService = req.scope.resolve("workspaceModuleService");
3
+ const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
4
+ const q = (req.query.q ?? "").trim().toLowerCase();
5
+ const [workspaces] = await workspaceService.listAndCountWorkspaces({ is_private: false }, { limit: 100 });
6
+ const filtered = q
7
+ ? workspaces.filter((w) => w.name.toLowerCase().includes(q))
8
+ : workspaces;
9
+ const limited = filtered.slice(0, 20);
10
+ // Check membership for each workspace
11
+ const results = await Promise.all(limited.map(async (w) => {
12
+ const isMember = await workspaceMemberService.isMember(w.id, req.user?.id);
13
+ return { id: w.id, name: w.name, slug: w.slug, is_private: w.is_private, is_member: isMember };
14
+ }));
15
+ res.json({ workspaces: results });
16
+ };
17
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../src/api/admin/workspaces/search/route.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,EAAE;IACnD,MAAM,gBAAgB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,wBAAwB,CAAQ,CAAA;IAC3E,MAAM,sBAAsB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,8BAA8B,CAAQ,CAAA;IAEvF,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAE5D,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,gBAAgB,CAAC,sBAAsB,CAChE,EAAE,UAAU,EAAE,KAAK,EAAE,EACrB,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAA;IAED,MAAM,QAAQ,GAAG,CAAC;QAChB,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACjE,CAAC,CAAC,UAAU,CAAA;IAEd,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAErC,sCAAsC;IACtC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAM,EAAE,EAAE;QAC3B,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QAC1E,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAA;IAChG,CAAC,CAAC,CACH,CAAA;IAED,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAA;AACnC,CAAC,CAAA"}
@@ -0,0 +1,13 @@
1
+ import type { SubscriberArgs, SubscriberConfig } from "@meridianjs/types";
2
+ interface WorkspaceAccessRequestedData {
3
+ access_request_id: string;
4
+ workspace_id: string;
5
+ user_id: string;
6
+ requester_name: string;
7
+ requester_email: string | null;
8
+ admin_user_ids: string[];
9
+ }
10
+ export default function handler({ event, container }: SubscriberArgs<WorkspaceAccessRequestedData>): Promise<void>;
11
+ export declare const config: SubscriberConfig;
12
+ export {};
13
+ //# sourceMappingURL=workspace-access-requested.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-access-requested.d.ts","sourceRoot":"","sources":["../../src/subscribers/workspace-access-requested.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzE,UAAU,4BAA4B;IACpC,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,cAAc,EAAE,MAAM,EAAE,CAAA;CACzB;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,4BAA4B,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA8CvH;AAED,eAAO,MAAM,MAAM,EAAE,gBAA0D,CAAA"}
@@ -0,0 +1,43 @@
1
+ import { sseManager } from "@meridianjs/framework";
2
+ import { emailHtml, resolveTemplate } from "./_email-helper.js";
3
+ export default async function handler({ event, container }) {
4
+ const data = event.data;
5
+ // SSE broadcast so admins get real-time badge update
6
+ sseManager.broadcast(data.workspace_id, "workspace.access_requested", {
7
+ access_request_id: data.access_request_id,
8
+ });
9
+ // Email all workspace admins
10
+ if (data.admin_user_ids.length === 0)
11
+ return;
12
+ try {
13
+ const emailService = container.resolve("emailService");
14
+ const workspaceSvc = container.resolve("workspaceModuleService");
15
+ const userSvc = container.resolve("userModuleService");
16
+ const workspace = await workspaceSvc.retrieveWorkspace(data.workspace_id);
17
+ if (!workspace)
18
+ return;
19
+ const appUrl = process.env.APP_URL ?? "http://localhost:9000";
20
+ const settingsUrl = `${appUrl}/${workspace.slug}/settings?tab=access-requests`;
21
+ const adminUsers = await userSvc.listUsersByIds(data.admin_user_ids);
22
+ const tpl = resolveTemplate(container, "workspace.access_requested", {
23
+ workspace: { name: workspace.name },
24
+ requester: { name: data.requester_name, email: data.requester_email },
25
+ });
26
+ await Promise.all([...adminUsers.values()].map(async (admin) => {
27
+ if (!admin.email)
28
+ return;
29
+ const subject = tpl?.subject ?? `${data.requester_name} requested access to "${workspace.name}"`;
30
+ const text = tpl?.text ?? `${data.requester_name} has requested access to "${workspace.name}".\n\nReview their request here: ${settingsUrl}`;
31
+ const html = tpl?.html ?? emailHtml(`<strong>${data.requester_name}</strong> has requested access to join <strong>${workspace.name}</strong>.<br/><br/>` +
32
+ `<a href="${settingsUrl}" style="display:inline-block;padding:10px 20px;background:#4f46e5;color:#fff;text-decoration:none;border-radius:6px;font-weight:600">Review Request</a><br/><br/>` +
33
+ `Or visit: <a href="${settingsUrl}">${settingsUrl}</a>`);
34
+ await emailService.send({ to: admin.email, subject, text, html });
35
+ }));
36
+ }
37
+ catch (err) {
38
+ const logger = container.resolve("logger");
39
+ logger.error(`[email] workspace.access_requested: ${err instanceof Error ? err.message : String(err)}`);
40
+ }
41
+ }
42
+ export const config = { event: "workspace.access_requested" };
43
+ //# sourceMappingURL=workspace-access-requested.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-access-requested.js","sourceRoot":"","sources":["../../src/subscribers/workspace-access-requested.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meridianjs/meridian",
3
- "version": "1.30.0",
3
+ "version": "1.31.0",
4
4
  "description": "Default API routes, workflows, links, and subscribers for Meridian applications",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -20,22 +20,22 @@
20
20
  "prepublishOnly": "cd ../.. && npm run check:routes && cd packages/meridian && npm run build"
21
21
  },
22
22
  "dependencies": {
23
- "@meridianjs/framework": "^1.30.0",
24
- "@meridianjs/framework-utils": "^1.30.0",
25
- "@meridianjs/workflow-engine": "^1.30.0",
26
- "@meridianjs/types": "^1.30.0",
27
- "@meridianjs/user": "^1.0.0",
23
+ "@meridianjs/framework": "^1.31.0",
24
+ "@meridianjs/framework-utils": "^1.31.0",
25
+ "@meridianjs/workflow-engine": "^1.31.0",
26
+ "@meridianjs/types": "^1.31.0",
27
+ "@meridianjs/user": "^1.1.0",
28
28
  "@meridianjs/workspace": "^1.2.0",
29
- "@meridianjs/auth": "^1.30.0",
30
- "@meridianjs/project": "^1.3.0",
31
- "@meridianjs/issue": "^1.7.0",
29
+ "@meridianjs/auth": "^1.31.0",
30
+ "@meridianjs/project": "^1.4.0",
31
+ "@meridianjs/issue": "^1.8.0",
32
32
  "@meridianjs/sprint": "^1.0.0",
33
33
  "@meridianjs/activity": "^1.0.0",
34
- "@meridianjs/notification": "^1.0.0",
35
- "@meridianjs/invitation": "^1.1.0",
36
- "@meridianjs/workspace-member": "^1.1.0",
37
- "@meridianjs/team-member": "^1.0.0",
38
- "@meridianjs/project-member": "^1.1.0",
34
+ "@meridianjs/notification": "^1.1.0",
35
+ "@meridianjs/invitation": "^1.2.0",
36
+ "@meridianjs/workspace-member": "^1.2.0",
37
+ "@meridianjs/team-member": "^1.1.0",
38
+ "@meridianjs/project-member": "^1.2.0",
39
39
  "@meridianjs/app-role": "^1.0.0",
40
40
  "@meridianjs/org-calendar": "^1.0.0",
41
41
  "multer": "^1.4.5-lts.1",