@meridianjs/meridian 1.31.0 → 2.1.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 (171) hide show
  1. package/dist/api/admin/events/route.d.ts.map +1 -1
  2. package/dist/api/admin/events/route.js +15 -8
  3. package/dist/api/admin/events/route.js.map +1 -1
  4. package/dist/api/admin/issues/[id]/attachments/[attachmentId]/route.d.ts.map +1 -1
  5. package/dist/api/admin/issues/[id]/attachments/[attachmentId]/route.js +34 -31
  6. package/dist/api/admin/issues/[id]/attachments/[attachmentId]/route.js.map +1 -1
  7. package/dist/api/admin/issues/[id]/attachments/route.d.ts.map +1 -1
  8. package/dist/api/admin/issues/[id]/attachments/route.js +47 -22
  9. package/dist/api/admin/issues/[id]/attachments/route.js.map +1 -1
  10. package/dist/api/admin/issues/[id]/comments/route.d.ts.map +1 -1
  11. package/dist/api/admin/issues/[id]/comments/route.js +20 -17
  12. package/dist/api/admin/issues/[id]/comments/route.js.map +1 -1
  13. package/dist/api/admin/issues/[id]/time-logs/[logId]/route.d.ts.map +1 -1
  14. package/dist/api/admin/issues/[id]/time-logs/[logId]/route.js +63 -60
  15. package/dist/api/admin/issues/[id]/time-logs/[logId]/route.js.map +1 -1
  16. package/dist/api/admin/issues/[id]/time-logs/route.d.ts.map +1 -1
  17. package/dist/api/admin/issues/[id]/time-logs/route.js +42 -17
  18. package/dist/api/admin/issues/[id]/time-logs/route.js.map +1 -1
  19. package/dist/api/admin/issues/[id]/time-logs/timer/route.d.ts.map +1 -1
  20. package/dist/api/admin/issues/[id]/time-logs/timer/route.js +49 -24
  21. package/dist/api/admin/issues/[id]/time-logs/timer/route.js.map +1 -1
  22. package/dist/api/admin/issues/route.d.ts.map +1 -1
  23. package/dist/api/admin/issues/route.js +2 -7
  24. package/dist/api/admin/issues/route.js.map +1 -1
  25. package/dist/api/admin/my/tasks/route.d.ts.map +1 -1
  26. package/dist/api/admin/my/tasks/route.js +16 -24
  27. package/dist/api/admin/my/tasks/route.js.map +1 -1
  28. package/dist/api/admin/projects/[id]/access/route.d.ts.map +1 -1
  29. package/dist/api/admin/projects/[id]/access/route.js +15 -2
  30. package/dist/api/admin/projects/[id]/access/route.js.map +1 -1
  31. package/dist/api/admin/projects/[id]/access-requests/[requestId]/route.d.ts +4 -0
  32. package/dist/api/admin/projects/[id]/access-requests/[requestId]/route.d.ts.map +1 -0
  33. package/dist/api/admin/projects/[id]/access-requests/[requestId]/route.js +105 -0
  34. package/dist/api/admin/projects/[id]/access-requests/[requestId]/route.js.map +1 -0
  35. package/dist/api/admin/projects/[id]/access-requests/route.d.ts +5 -0
  36. package/dist/api/admin/projects/[id]/access-requests/route.d.ts.map +1 -0
  37. package/dist/api/admin/projects/[id]/access-requests/route.js +138 -0
  38. package/dist/api/admin/projects/[id]/access-requests/route.js.map +1 -0
  39. package/dist/api/admin/projects/[id]/health/[updateId]/route.d.ts.map +1 -1
  40. package/dist/api/admin/projects/[id]/health/[updateId]/route.js +83 -73
  41. package/dist/api/admin/projects/[id]/health/[updateId]/route.js.map +1 -1
  42. package/dist/api/admin/projects/[id]/health/[updateId]/send/route.d.ts.map +1 -1
  43. package/dist/api/admin/projects/[id]/health/[updateId]/send/route.js +68 -65
  44. package/dist/api/admin/projects/[id]/health/[updateId]/send/route.js.map +1 -1
  45. package/dist/api/admin/projects/[id]/health/route.d.ts.map +1 -1
  46. package/dist/api/admin/projects/[id]/health/route.js +33 -30
  47. package/dist/api/admin/projects/[id]/health/route.js.map +1 -1
  48. package/dist/api/admin/projects/[id]/share/route.d.ts.map +1 -1
  49. package/dist/api/admin/projects/[id]/share/route.js +44 -39
  50. package/dist/api/admin/projects/[id]/share/route.js.map +1 -1
  51. package/dist/api/admin/projects/[id]/statuses/[statusId]/route.d.ts.map +1 -1
  52. package/dist/api/admin/projects/[id]/statuses/[statusId]/route.js +77 -72
  53. package/dist/api/admin/projects/[id]/statuses/[statusId]/route.js.map +1 -1
  54. package/dist/api/admin/projects/[id]/statuses/reorder/route.d.ts.map +1 -1
  55. package/dist/api/admin/projects/[id]/statuses/reorder/route.js +20 -17
  56. package/dist/api/admin/projects/[id]/statuses/reorder/route.js.map +1 -1
  57. package/dist/api/admin/projects/[id]/statuses/route.d.ts.map +1 -1
  58. package/dist/api/admin/projects/[id]/statuses/route.js +23 -20
  59. package/dist/api/admin/projects/[id]/statuses/route.js.map +1 -1
  60. package/dist/api/admin/projects/[id]/task-lists/route.d.ts.map +1 -1
  61. package/dist/api/admin/projects/[id]/task-lists/route.js +22 -19
  62. package/dist/api/admin/projects/[id]/task-lists/route.js.map +1 -1
  63. package/dist/api/admin/projects/route.d.ts.map +1 -1
  64. package/dist/api/admin/projects/route.js +58 -40
  65. package/dist/api/admin/projects/route.js.map +1 -1
  66. package/dist/api/admin/reporting/members/route.d.ts.map +1 -1
  67. package/dist/api/admin/reporting/members/route.js +2 -6
  68. package/dist/api/admin/reporting/members/route.js.map +1 -1
  69. package/dist/api/admin/reporting/time-logs/route.d.ts.map +1 -1
  70. package/dist/api/admin/reporting/time-logs/route.js +11 -26
  71. package/dist/api/admin/reporting/time-logs/route.js.map +1 -1
  72. package/dist/api/admin/task-lists/[id]/route.d.ts.map +1 -1
  73. package/dist/api/admin/task-lists/[id]/route.js +44 -39
  74. package/dist/api/admin/task-lists/[id]/route.js.map +1 -1
  75. package/dist/api/admin/time-logs/active-timer/route.d.ts.map +1 -1
  76. package/dist/api/admin/time-logs/active-timer/route.js +14 -11
  77. package/dist/api/admin/time-logs/active-timer/route.js.map +1 -1
  78. package/dist/api/admin/workspaces/[id]/access-requests/[requestId]/route.d.ts +1 -0
  79. package/dist/api/admin/workspaces/[id]/access-requests/[requestId]/route.d.ts.map +1 -1
  80. package/dist/api/admin/workspaces/[id]/access-requests/[requestId]/route.js +35 -15
  81. package/dist/api/admin/workspaces/[id]/access-requests/[requestId]/route.js.map +1 -1
  82. package/dist/api/admin/workspaces/[id]/access-requests/route.d.ts.map +1 -1
  83. package/dist/api/admin/workspaces/[id]/access-requests/route.js +5 -19
  84. package/dist/api/admin/workspaces/[id]/access-requests/route.js.map +1 -1
  85. package/dist/api/admin/workspaces/[id]/invitations/[inviteId]/resend/route.d.ts.map +1 -1
  86. package/dist/api/admin/workspaces/[id]/invitations/[inviteId]/resend/route.js +1 -15
  87. package/dist/api/admin/workspaces/[id]/invitations/[inviteId]/resend/route.js.map +1 -1
  88. package/dist/api/admin/workspaces/[id]/invitations/[inviteId]/route.d.ts.map +1 -1
  89. package/dist/api/admin/workspaces/[id]/invitations/[inviteId]/route.js +1 -15
  90. package/dist/api/admin/workspaces/[id]/invitations/[inviteId]/route.js.map +1 -1
  91. package/dist/api/admin/workspaces/[id]/invitations/route.d.ts.map +1 -1
  92. package/dist/api/admin/workspaces/[id]/invitations/route.js +49 -65
  93. package/dist/api/admin/workspaces/[id]/invitations/route.js.map +1 -1
  94. package/dist/api/admin/workspaces/[id]/logo/route.d.ts.map +1 -1
  95. package/dist/api/admin/workspaces/[id]/logo/route.js +1 -15
  96. package/dist/api/admin/workspaces/[id]/logo/route.js.map +1 -1
  97. package/dist/api/admin/workspaces/[id]/members/[userId]/route.d.ts.map +1 -1
  98. package/dist/api/admin/workspaces/[id]/members/[userId]/route.js +1 -19
  99. package/dist/api/admin/workspaces/[id]/members/[userId]/route.js.map +1 -1
  100. package/dist/api/admin/workspaces/[id]/members/batch/route.d.ts.map +1 -1
  101. package/dist/api/admin/workspaces/[id]/members/batch/route.js +48 -56
  102. package/dist/api/admin/workspaces/[id]/members/batch/route.js.map +1 -1
  103. package/dist/api/admin/workspaces/[id]/members/route.d.ts.map +1 -1
  104. package/dist/api/admin/workspaces/[id]/members/route.js +43 -60
  105. package/dist/api/admin/workspaces/[id]/members/route.js.map +1 -1
  106. package/dist/api/admin/workspaces/[id]/route.d.ts.map +1 -1
  107. package/dist/api/admin/workspaces/[id]/route.js +3 -22
  108. package/dist/api/admin/workspaces/[id]/route.js.map +1 -1
  109. package/dist/api/admin/workspaces/[id]/teams/[teamId]/members/[userId]/route.d.ts.map +1 -1
  110. package/dist/api/admin/workspaces/[id]/teams/[teamId]/members/[userId]/route.js +1 -19
  111. package/dist/api/admin/workspaces/[id]/teams/[teamId]/members/[userId]/route.js.map +1 -1
  112. package/dist/api/admin/workspaces/[id]/teams/[teamId]/members/route.d.ts.map +1 -1
  113. package/dist/api/admin/workspaces/[id]/teams/[teamId]/members/route.js +1 -19
  114. package/dist/api/admin/workspaces/[id]/teams/[teamId]/members/route.js.map +1 -1
  115. package/dist/api/admin/workspaces/[id]/teams/[teamId]/route.d.ts.map +1 -1
  116. package/dist/api/admin/workspaces/[id]/teams/[teamId]/route.js +1 -19
  117. package/dist/api/admin/workspaces/[id]/teams/[teamId]/route.js.map +1 -1
  118. package/dist/api/admin/workspaces/[id]/teams/route.d.ts.map +1 -1
  119. package/dist/api/admin/workspaces/[id]/teams/route.js +1 -19
  120. package/dist/api/admin/workspaces/[id]/teams/route.js.map +1 -1
  121. package/dist/api/admin/workspaces/my-access-requests/route.d.ts +3 -0
  122. package/dist/api/admin/workspaces/my-access-requests/route.d.ts.map +1 -0
  123. package/dist/api/admin/workspaces/my-access-requests/route.js +20 -0
  124. package/dist/api/admin/workspaces/my-access-requests/route.js.map +1 -0
  125. package/dist/api/admin/workspaces/route.d.ts.map +1 -1
  126. package/dist/api/admin/workspaces/route.js +49 -34
  127. package/dist/api/admin/workspaces/route.js.map +1 -1
  128. package/dist/api/admin/workspaces/search/route.d.ts.map +1 -1
  129. package/dist/api/admin/workspaces/search/route.js +5 -2
  130. package/dist/api/admin/workspaces/search/route.js.map +1 -1
  131. package/dist/api/auth/_apply-pending-invites.d.ts +12 -0
  132. package/dist/api/auth/_apply-pending-invites.d.ts.map +1 -0
  133. package/dist/api/auth/_apply-pending-invites.js +68 -0
  134. package/dist/api/auth/_apply-pending-invites.js.map +1 -0
  135. package/dist/api/auth/google/callback/route.d.ts.map +1 -1
  136. package/dist/api/auth/google/callback/route.js +20 -0
  137. package/dist/api/auth/google/callback/route.js.map +1 -1
  138. package/dist/api/auth/invite/[token]/route.d.ts.map +1 -1
  139. package/dist/api/auth/invite/[token]/route.js +2 -9
  140. package/dist/api/auth/invite/[token]/route.js.map +1 -1
  141. package/dist/api/auth/register/route.d.ts.map +1 -1
  142. package/dist/api/auth/register/route.js +16 -0
  143. package/dist/api/auth/register/route.js.map +1 -1
  144. package/dist/api/utils/assign-default-role.d.ts +6 -0
  145. package/dist/api/utils/assign-default-role.d.ts.map +1 -0
  146. package/dist/api/utils/assign-default-role.js +23 -0
  147. package/dist/api/utils/assign-default-role.js.map +1 -0
  148. package/dist/api/utils/project-access.d.ts +9 -0
  149. package/dist/api/utils/project-access.d.ts.map +1 -1
  150. package/dist/api/utils/project-access.js +27 -0
  151. package/dist/api/utils/project-access.js.map +1 -1
  152. package/dist/api/utils/workspace-access.d.ts +17 -0
  153. package/dist/api/utils/workspace-access.d.ts.map +1 -0
  154. package/dist/api/utils/workspace-access.js +72 -0
  155. package/dist/api/utils/workspace-access.js.map +1 -0
  156. package/dist/subscribers/project-access-request-resolved.d.ts +12 -0
  157. package/dist/subscribers/project-access-request-resolved.d.ts.map +1 -0
  158. package/dist/subscribers/project-access-request-resolved.js +55 -0
  159. package/dist/subscribers/project-access-request-resolved.js.map +1 -0
  160. package/dist/subscribers/project-access-requested.d.ts +11 -0
  161. package/dist/subscribers/project-access-requested.d.ts.map +1 -0
  162. package/dist/subscribers/project-access-requested.js +12 -0
  163. package/dist/subscribers/project-access-requested.js.map +1 -0
  164. package/dist/subscribers/workspace-access-request-resolved.d.ts +12 -0
  165. package/dist/subscribers/workspace-access-request-resolved.d.ts.map +1 -0
  166. package/dist/subscribers/workspace-access-request-resolved.js +60 -0
  167. package/dist/subscribers/workspace-access-request-resolved.js.map +1 -0
  168. package/dist/subscribers/workspace-access-requested.d.ts.map +1 -1
  169. package/dist/subscribers/workspace-access-requested.js +1 -0
  170. package/dist/subscribers/workspace-access-requested.js.map +1 -1
  171. package/package.json +19 -19
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/auth/register/route.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAYvC,eAAO,MAAM,IAAI,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAiDjD,CAAA"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/auth/register/route.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAavC,eAAO,MAAM,IAAI,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAiEjD,CAAA"}
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { consumeOtp } from "./_otp-store.js";
3
3
  import { validateEmailDomain } from "./_domain-check.js";
4
+ import { applyPendingInvites } from "../_apply-pending-invites.js";
4
5
  const registerSchema = z.object({
5
6
  email: z.string().email(),
6
7
  password: z.string().min(8, "Password must be at least 8 characters"),
@@ -51,6 +52,21 @@ export const POST = async (req, res) => {
51
52
  }
52
53
  const authService = req.scope.resolve("authModuleService");
53
54
  const response = await authService.register(result.data);
55
+ // Auto-apply any pending invitations for this email
56
+ if (response.user?.id) {
57
+ const applied = await applyPendingInvites(req.scope, response.user.id, result.data.email);
58
+ if (applied) {
59
+ // Re-sign the JWT with a fresh DB read so the token reflects the upgraded role/permissions
60
+ try {
61
+ const freshAuth = await authService.issueToken(response.user.id);
62
+ response.token = freshAuth.token;
63
+ response.user = freshAuth.user;
64
+ }
65
+ catch {
66
+ // Non-fatal — user still registered, they can log in to get the updated token
67
+ }
68
+ }
69
+ }
54
70
  res.status(201).json(response);
55
71
  };
56
72
  //# sourceMappingURL=route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/auth/register/route.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/auth/register/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAElE,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;IACzB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,wCAAwC,CAAC;IACrE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,EAAE;IACpD,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAQ,CAAA;IACjE,MAAM,CAAC,EAAE,SAAS,CAAC,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;IAC3E,MAAM,YAAY,GAAG,SAAS,KAAK,CAAC,CAAA;IAEpC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAQ,CAAA;QACjD,MAAM,SAAS,GAAG,MAAM,EAAE,aAAa,EAAE,YAAY,CAAA;QACrD,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC;YACxB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE,EAAE,OAAO,EAAE,sEAAsE,EAAE;aAC3F,CAAC,CAAA;YACF,OAAM;QACR,CAAC;QAED,4DAA4D;QAC5D,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,KAAK,CAAA;QAChC,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,mBAAmB,CAAC,QAAQ,EAAE,SAAS,CAAC,cAAc,CAAC,CAAA;YACzD,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;gBACvE,OAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC;YACnB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,+BAA+B,EAAE,EAAE,CAAC,CAAA;YAC7E,OAAM;QACR,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACjD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;QAC7G,OAAM;IACR,CAAC;IAED,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAI,CAAC,CAAA;QAClF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,sCAAsC,EAAE,EAAE,CAAC,CAAA;YACpF,OAAM;QACR,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAQ,CAAA;IACjE,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAExD,oDAAoD;IACpD,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACzF,IAAI,OAAO,EAAE,CAAC;YACZ,2FAA2F;YAC3F,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBAChE,QAAQ,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAA;gBAChC,QAAQ,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAA;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,8EAA8E;YAChF,CAAC;QACH,CAAC;IACH,CAAC;IAED,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AAChC,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Assigns the system "User" app-role to a user if no custom role is specified.
3
+ * Non-fatal — silently catches errors (e.g. app-role module not loaded).
4
+ */
5
+ export declare function assignDefaultUserRole(req: any, userId: string, appRoleId?: string): Promise<void>;
6
+ //# sourceMappingURL=assign-default-role.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign-default-role.d.ts","sourceRoot":"","sources":["../../../src/api/utils/assign-default-role.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAevG"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Assigns the system "User" app-role to a user if no custom role is specified.
3
+ * Non-fatal — silently catches errors (e.g. app-role module not loaded).
4
+ */
5
+ export async function assignDefaultUserRole(req, userId, appRoleId) {
6
+ try {
7
+ const userService = req.scope.resolve("userModuleService");
8
+ if (appRoleId) {
9
+ await userService.updateUser(userId, { app_role_id: appRoleId });
10
+ }
11
+ else {
12
+ const appRoleService = req.scope.resolve("appRoleModuleService");
13
+ const [userRoles] = await appRoleService.listAndCountAppRoles({ name: "User", is_system: true }, { limit: 1 });
14
+ if (userRoles.length > 0) {
15
+ await userService.updateUser(userId, { app_role_id: userRoles[0].id });
16
+ }
17
+ }
18
+ }
19
+ catch {
20
+ // Non-fatal — app-role module may not be loaded
21
+ }
22
+ }
23
+ //# sourceMappingURL=assign-default-role.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assign-default-role.js","sourceRoot":"","sources":["../../../src/api/utils/assign-default-role.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAQ,EAAE,MAAc,EAAE,SAAkB;IACtF,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAQ,CAAA;QACjE,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,WAAW,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAA;QAClE,CAAC;aAAM,CAAC;YACN,MAAM,cAAc,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,sBAAsB,CAAQ,CAAA;YACvE,MAAM,CAAC,SAAS,CAAC,GAAG,MAAM,cAAc,CAAC,oBAAoB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;YAC9G,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,WAAW,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;YACxE,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;AACH,CAAC"}
@@ -9,4 +9,13 @@ export declare function hasProjectAccess(req: any, project: {
9
9
  id: string;
10
10
  workspace_id: string;
11
11
  }): Promise<boolean>;
12
+ /**
13
+ * Resolves project and checks if caller is a project manager, workspace admin, or global admin.
14
+ * Returns null (and sends 404) if project doesn't exist.
15
+ * Returns { project, isAuthorized } otherwise.
16
+ */
17
+ export declare function resolveProjectAndAccess(req: any, res: import("express").Response): Promise<{
18
+ project: any;
19
+ isAuthorized: boolean;
20
+ } | null>;
12
21
  //# sourceMappingURL=project-access.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"project-access.d.ts","sourceRoot":"","sources":["../../../src/api/utils/project-access.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAgBhH"}
1
+ {"version":3,"file":"project-access.d.ts","sourceRoot":"","sources":["../../../src/api/utils/project-access.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAgBhH;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,OAAO,SAAS,EAAE,QAAQ,GAC9B,OAAO,CAAC;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAAC,CAsBzD"}
@@ -22,4 +22,31 @@ export async function hasProjectAccess(req, project) {
22
22
  const accessibleProjectIds = await projectMemberService.getAccessibleProjectIds(userId, userTeamIds);
23
23
  return accessibleProjectIds.includes(project.id);
24
24
  }
25
+ /**
26
+ * Resolves project and checks if caller is a project manager, workspace admin, or global admin.
27
+ * Returns null (and sends 404) if project doesn't exist.
28
+ * Returns { project, isAuthorized } otherwise.
29
+ */
30
+ export async function resolveProjectAndAccess(req, res) {
31
+ const projectService = req.scope.resolve("projectModuleService");
32
+ const project = await projectService.retrieveProject(req.params.id).catch(() => null);
33
+ if (!project) {
34
+ res.status(404).json({ error: { message: "Project not found" } });
35
+ return null;
36
+ }
37
+ const roles = req.user?.roles ?? [];
38
+ const isGlobalAdmin = roles.includes("super-admin") || roles.includes("admin");
39
+ if (isGlobalAdmin)
40
+ return { project, isAuthorized: true };
41
+ const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
42
+ const wsMembership = await workspaceMemberService.getMembership(project.workspace_id, req.user?.id);
43
+ if (wsMembership?.role === "admin")
44
+ return { project, isAuthorized: true };
45
+ const projectMemberService = req.scope.resolve("projectMemberModuleService");
46
+ const members = await projectMemberService.listProjectMembers(project.id);
47
+ const myMembership = members.find((m) => m.user_id === req.user?.id);
48
+ if (myMembership?.role === "manager")
49
+ return { project, isAuthorized: true };
50
+ return { project, isAuthorized: false };
51
+ }
25
52
  //# sourceMappingURL=project-access.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"project-access.js","sourceRoot":"","sources":["../../../src/api/utils/project-access.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAQ,EAAE,OAA6C;IAC5F,MAAM,KAAK,GAAa,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAA;IAC7C,IAAI,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IAEzE,MAAM,sBAAsB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,8BAA8B,CAAQ,CAAA;IACvF,MAAM,iBAAiB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,yBAAyB,CAAQ,CAAA;IAC7E,MAAM,oBAAoB,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,4BAA4B,CAAQ,CAAA;IACnF,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAA;IAE3B,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,aAAa,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;IAC3F,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAA;IAC7B,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,CAAA;IAE5C,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA;IAClE,MAAM,oBAAoB,GAAG,MAAM,oBAAoB,CAAC,uBAAuB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IACpG,OAAO,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;AAClD,CAAC"}
1
+ {"version":3,"file":"project-access.js","sourceRoot":"","sources":["../../../src/api/utils/project-access.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { Response } from "express";
2
+ /**
3
+ * Shared workspace access check. Verifies the workspace exists and the caller
4
+ * has access (public workspace for admins, or membership for private/members).
5
+ */
6
+ export declare function assertWorkspaceAccess(req: any, res: Response): Promise<boolean>;
7
+ /**
8
+ * Stricter workspace access check — requires workspace admin role (not just member).
9
+ */
10
+ export declare function assertWorkspaceAdmin(req: any, res: Response): Promise<boolean>;
11
+ export declare function isSuperAdminOrgScope(req: any): boolean;
12
+ /**
13
+ * Returns workspace IDs the caller can access (public + private where member).
14
+ * If wsIdHints are provided, only those workspaces are checked; otherwise all are fetched.
15
+ */
16
+ export declare function getAccessibleWorkspaceIds(req: any, wsIdHints?: string[]): Promise<string[]>;
17
+ //# sourceMappingURL=workspace-access.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-access.d.ts","sourceRoot":"","sources":["../../../src/api/utils/workspace-access.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAqBrF;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAoBpF;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAGtD;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAqBjG"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Shared workspace access check. Verifies the workspace exists and the caller
3
+ * has access (public workspace for admins, or membership for private/members).
4
+ */
5
+ export async function assertWorkspaceAccess(req, res) {
6
+ const workspaceService = req.scope.resolve("workspaceModuleService");
7
+ const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
8
+ const workspace = await workspaceService.retrieveWorkspace(req.params.id).catch(() => null);
9
+ if (!workspace) {
10
+ res.status(404).json({ error: { message: "Workspace not found" } });
11
+ return false;
12
+ }
13
+ const roles = req.user?.roles ?? [];
14
+ const isPrivileged = roles.includes("super-admin") || roles.includes("admin");
15
+ if (workspace.is_private || !isPrivileged) {
16
+ const membership = await workspaceMemberService.getMembership(req.params.id, req.user?.id);
17
+ if (!membership) {
18
+ res.status(403).json({ error: { message: "Forbidden — not a member of this workspace" } });
19
+ return false;
20
+ }
21
+ }
22
+ return true;
23
+ }
24
+ /**
25
+ * Stricter workspace access check — requires workspace admin role (not just member).
26
+ */
27
+ export async function assertWorkspaceAdmin(req, res) {
28
+ const workspaceService = req.scope.resolve("workspaceModuleService");
29
+ const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
30
+ const workspace = await workspaceService.retrieveWorkspace(req.params.id).catch(() => null);
31
+ if (!workspace) {
32
+ res.status(404).json({ error: { message: "Workspace not found" } });
33
+ return false;
34
+ }
35
+ const roles = req.user?.roles ?? [];
36
+ const isGlobalAdmin = roles.includes("super-admin") || roles.includes("admin");
37
+ if (isGlobalAdmin)
38
+ return true;
39
+ const membership = await workspaceMemberService.getMembership(req.params.id, req.user?.id);
40
+ if (!membership || membership.role !== "admin") {
41
+ res.status(403).json({ error: { message: "Workspace admin access required" } });
42
+ return false;
43
+ }
44
+ return true;
45
+ }
46
+ export function isSuperAdminOrgScope(req) {
47
+ const roles = req.user?.roles ?? [];
48
+ return roles.includes("super-admin") && req.query.org_scope === "true";
49
+ }
50
+ /**
51
+ * Returns workspace IDs the caller can access (public + private where member).
52
+ * If wsIdHints are provided, only those workspaces are checked; otherwise all are fetched.
53
+ */
54
+ export async function getAccessibleWorkspaceIds(req, wsIdHints) {
55
+ const workspaceService = req.scope.resolve("workspaceModuleService");
56
+ const workspaceMemberService = req.scope.resolve("workspaceMemberModuleService");
57
+ const userId = req.user?.id;
58
+ let workspaces;
59
+ if (wsIdHints && wsIdHints.length > 0) {
60
+ const [ws] = await workspaceService.listAndCountWorkspaces({ id: wsIdHints.length === 1 ? wsIdHints[0] : wsIdHints }, { limit: wsIdHints.length });
61
+ workspaces = ws;
62
+ }
63
+ else {
64
+ const [all] = await workspaceService.listAndCountWorkspaces({}, { limit: 1000 });
65
+ workspaces = all;
66
+ }
67
+ const memberWsIds = new Set(await workspaceMemberService.getWorkspaceIdsForUser(userId));
68
+ return workspaces
69
+ .filter((ws) => !ws.is_private || memberWsIds.has(ws.id))
70
+ .map((ws) => ws.id);
71
+ }
72
+ //# sourceMappingURL=workspace-access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-access.js","sourceRoot":"","sources":["../../../src/api/utils/workspace-access.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { SubscriberArgs, SubscriberConfig } from "@meridianjs/types";
2
+ interface ProjectAccessRequestResolvedData {
3
+ project_id: string;
4
+ project_name: string;
5
+ workspace_id: string;
6
+ user_id: string;
7
+ action: "approve" | "deny";
8
+ }
9
+ export default function handler({ event, container }: SubscriberArgs<ProjectAccessRequestResolvedData>): Promise<void>;
10
+ export declare const config: SubscriberConfig;
11
+ export {};
12
+ //# sourceMappingURL=project-access-request-resolved.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-access-request-resolved.d.ts","sourceRoot":"","sources":["../../src/subscribers/project-access-request-resolved.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzE,UAAU,gCAAgC;IACxC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,SAAS,GAAG,MAAM,CAAA;CAC3B;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,gCAAgC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAsD3H;AAED,eAAO,MAAM,MAAM,EAAE,gBAA+D,CAAA"}
@@ -0,0 +1,55 @@
1
+ import { sseManager } from "@meridianjs/framework";
2
+ import { buildEmail, buildProjectUrl, resolveTemplate } from "./_email-helper.js";
3
+ export default async function handler({ event, container }) {
4
+ const data = event.data;
5
+ // SSE: update the admin's access-requests badge and the requester's notification bell
6
+ sseManager.broadcast(data.workspace_id, "project.access_request_resolved", {
7
+ project_id: data.project_id,
8
+ action: data.action,
9
+ });
10
+ sseManager.broadcast(data.workspace_id, "notification.created", {});
11
+ try {
12
+ const emailService = container.resolve("emailService");
13
+ const userService = container.resolve("userModuleService");
14
+ const config = container.resolve("config");
15
+ const appUrl = config?.appUrl ?? process.env.APP_URL ?? "http://localhost:9001";
16
+ const user = await userService.retrieveUser(data.user_id).catch(() => null);
17
+ if (!user?.email)
18
+ return;
19
+ const approved = data.action === "approve";
20
+ const projectUrl = await buildProjectUrl(container, appUrl, data.project_id, data.workspace_id);
21
+ const tpl = resolveTemplate(container, "project.access_request_resolved", {
22
+ project: { name: data.project_name },
23
+ user,
24
+ approved,
25
+ });
26
+ await emailService.send({
27
+ to: user.email,
28
+ subject: tpl?.subject ?? (approved
29
+ ? `You've been granted access to "${data.project_name}"`
30
+ : `Your request to join "${data.project_name}" was not approved`),
31
+ text: tpl?.text ?? (approved
32
+ ? `Your request to join the project "${data.project_name}" has been approved. View it here: ${projectUrl}`
33
+ : `Your request to join the project "${data.project_name}" was reviewed and not approved at this time.`),
34
+ html: tpl?.html ?? buildEmail(approved ? {
35
+ preheader: `Your access to ${data.project_name} has been approved`,
36
+ heading: `Access granted to "${data.project_name}"`,
37
+ body: `Your request to join the project <strong>${data.project_name}</strong> has been approved. You can now view and collaborate on the project.`,
38
+ ctaText: "View Project",
39
+ ctaUrl: projectUrl,
40
+ } : {
41
+ preheader: `Your access request for ${data.project_name}`,
42
+ heading: `Access request for "${data.project_name}"`,
43
+ body: `Your request to join the project <strong>${data.project_name}</strong> was reviewed and not approved at this time. Please reach out to a project manager if you think this is a mistake.`,
44
+ ctaText: "Open Meridian",
45
+ ctaUrl: appUrl,
46
+ }),
47
+ });
48
+ }
49
+ catch (err) {
50
+ const logger = container.resolve("logger");
51
+ logger.error(`[email] project.access_request_resolved: ${err instanceof Error ? err.message : String(err)}`);
52
+ }
53
+ }
54
+ export const config = { event: "project.access_request_resolved" };
55
+ //# sourceMappingURL=project-access-request-resolved.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-access-request-resolved.js","sourceRoot":"","sources":["../../src/subscribers/project-access-request-resolved.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { SubscriberArgs, SubscriberConfig } from "@meridianjs/types";
2
+ interface ProjectAccessRequestedData {
3
+ project_id: string;
4
+ workspace_id: string;
5
+ user_id: string;
6
+ request_id: string;
7
+ }
8
+ export default function handler({ event }: SubscriberArgs<ProjectAccessRequestedData>): Promise<void>;
9
+ export declare const config: SubscriberConfig;
10
+ export {};
11
+ //# sourceMappingURL=project-access-requested.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-access-requested.d.ts","sourceRoot":"","sources":["../../src/subscribers/project-access-requested.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAGzE,UAAU,0BAA0B;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,cAAc,CAAC,0BAA0B,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAS1G;AAED,eAAO,MAAM,MAAM,EAAE,gBAAwD,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { sseManager } from "@meridianjs/framework";
2
+ export default async function handler({ event }) {
3
+ const data = event.data;
4
+ // SSE: update the project access-requests badge for managers/admins
5
+ sseManager.broadcast(data.workspace_id, "project.access_requested", {
6
+ project_id: data.project_id,
7
+ request_id: data.request_id,
8
+ });
9
+ sseManager.broadcast(data.workspace_id, "notification.created", {});
10
+ }
11
+ export const config = { event: "project.access_requested" };
12
+ //# sourceMappingURL=project-access-requested.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-access-requested.js","sourceRoot":"","sources":["../../src/subscribers/project-access-requested.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AASlD,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,KAAK,EAA8C;IACzF,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;IAEvB,oEAAoE;IACpE,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,EAAE,0BAA0B,EAAE;QAClE,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,UAAU,EAAE,IAAI,CAAC,UAAU;KAC5B,CAAC,CAAA;IACF,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,EAAE,sBAAsB,EAAE,EAAE,CAAC,CAAA;AACrE,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAqB,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAA"}
@@ -0,0 +1,12 @@
1
+ import type { SubscriberArgs, SubscriberConfig } from "@meridianjs/types";
2
+ interface WorkspaceAccessRequestResolvedData {
3
+ workspace_id: string;
4
+ workspace_name: string;
5
+ workspace_slug: string;
6
+ user_id: string;
7
+ action: "approve" | "deny";
8
+ }
9
+ export default function handler({ event, container }: SubscriberArgs<WorkspaceAccessRequestResolvedData>): Promise<void>;
10
+ export declare const config: SubscriberConfig;
11
+ export {};
12
+ //# sourceMappingURL=workspace-access-request-resolved.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-access-request-resolved.d.ts","sourceRoot":"","sources":["../../src/subscribers/workspace-access-request-resolved.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAIzE,UAAU,kCAAkC;IAC1C,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,SAAS,GAAG,MAAM,CAAA;CAC3B;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,kCAAkC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA4D7H;AAED,eAAO,MAAM,MAAM,EAAE,gBAAiE,CAAA"}
@@ -0,0 +1,60 @@
1
+ import { sseManager } from "@meridianjs/framework";
2
+ import { buildEmail, resolveTemplate } from "./_email-helper.js";
3
+ export default async function handler({ event, container }) {
4
+ const data = event.data;
5
+ // SSE: update the admin's access-requests badge and the requester's notification bell
6
+ sseManager.broadcast(data.workspace_id, "workspace.access_request_resolved", {
7
+ action: data.action,
8
+ });
9
+ sseManager.broadcast(data.workspace_id, "notification.created", {});
10
+ // SSE: notify the requester directly (they may be on /awaiting-access with no workspace SSE)
11
+ sseManager.broadcast(`user:${data.user_id}`, "workspace.access_request_resolved", {
12
+ action: data.action,
13
+ workspace_id: data.workspace_id,
14
+ workspace_slug: data.workspace_slug,
15
+ });
16
+ try {
17
+ const emailService = container.resolve("emailService");
18
+ const userService = container.resolve("userModuleService");
19
+ const config = container.resolve("config");
20
+ const appUrl = config?.appUrl ?? process.env.APP_URL ?? "http://localhost:9001";
21
+ const user = await userService.retrieveUser(data.user_id).catch(() => null);
22
+ if (!user?.email)
23
+ return;
24
+ const approved = data.action === "approve";
25
+ const workspaceUrl = `${appUrl}/${data.workspace_slug}/projects`;
26
+ const tpl = resolveTemplate(container, "workspace.access_request_resolved", {
27
+ workspace: { name: data.workspace_name },
28
+ user,
29
+ approved,
30
+ });
31
+ await emailService.send({
32
+ to: user.email,
33
+ subject: tpl?.subject ?? (approved
34
+ ? `You've been granted access to "${data.workspace_name}"`
35
+ : `Your request to join "${data.workspace_name}" was not approved`),
36
+ text: tpl?.text ?? (approved
37
+ ? `Your request to join "${data.workspace_name}" has been approved. You can now access the workspace here: ${workspaceUrl}`
38
+ : `Your request to join "${data.workspace_name}" was reviewed and not approved at this time.`),
39
+ html: tpl?.html ?? buildEmail(approved ? {
40
+ preheader: `Your access to ${data.workspace_name} has been approved`,
41
+ heading: `You're in — welcome to "${data.workspace_name}"`,
42
+ body: `Your request to join <strong>${data.workspace_name}</strong> has been approved. You can now access the workspace and collaborate with your team.`,
43
+ ctaText: "Open Workspace",
44
+ ctaUrl: workspaceUrl,
45
+ } : {
46
+ preheader: `Your access request for ${data.workspace_name}`,
47
+ heading: `Access request for "${data.workspace_name}"`,
48
+ body: `Your request to join <strong>${data.workspace_name}</strong> was reviewed and not approved at this time. Please reach out to a workspace admin if you think this is a mistake.`,
49
+ ctaText: "Open Meridian",
50
+ ctaUrl: appUrl,
51
+ }),
52
+ });
53
+ }
54
+ catch (err) {
55
+ const logger = container.resolve("logger");
56
+ logger.error(`[email] workspace.access_request_resolved: ${err instanceof Error ? err.message : String(err)}`);
57
+ }
58
+ }
59
+ export const config = { event: "workspace.access_request_resolved" };
60
+ //# sourceMappingURL=workspace-access-request-resolved.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-access-request-resolved.js","sourceRoot":"","sources":["../../src/subscribers/workspace-access-request-resolved.ts"],"names":[],"mappings":"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"}
@@ -1 +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"}
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,CA+CvH;AAED,eAAO,MAAM,MAAM,EAAE,gBAA0D,CAAA"}
@@ -6,6 +6,7 @@ export default async function handler({ event, container }) {
6
6
  sseManager.broadcast(data.workspace_id, "workspace.access_requested", {
7
7
  access_request_id: data.access_request_id,
8
8
  });
9
+ sseManager.broadcast(data.workspace_id, "notification.created", {});
9
10
  // Email all workspace admins
10
11
  if (data.admin_user_ids.length === 0)
11
12
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-access-requested.js","sourceRoot":"","sources":["../../src/subscribers/workspace-access-requested.ts"],"names":[],"mappings":"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"}
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.31.0",
3
+ "version": "2.1.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,24 +20,24 @@
20
20
  "prepublishOnly": "cd ../.. && npm run check:routes && cd packages/meridian && npm run build"
21
21
  },
22
22
  "dependencies": {
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
- "@meridianjs/workspace": "^1.2.0",
29
- "@meridianjs/auth": "^1.31.0",
30
- "@meridianjs/project": "^1.4.0",
31
- "@meridianjs/issue": "^1.8.0",
32
- "@meridianjs/sprint": "^1.0.0",
33
- "@meridianjs/activity": "^1.0.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
- "@meridianjs/app-role": "^1.0.0",
40
- "@meridianjs/org-calendar": "^1.0.0",
23
+ "@meridianjs/framework": "^2.1.0",
24
+ "@meridianjs/framework-utils": "^2.1.0",
25
+ "@meridianjs/workflow-engine": "^2.1.0",
26
+ "@meridianjs/types": "^2.1.0",
27
+ "@meridianjs/user": "^2.0.0",
28
+ "@meridianjs/workspace": "^1.2.1",
29
+ "@meridianjs/auth": "^2.1.0",
30
+ "@meridianjs/project": "^2.0.0",
31
+ "@meridianjs/issue": "^2.0.0",
32
+ "@meridianjs/sprint": "^1.0.1",
33
+ "@meridianjs/activity": "^1.0.1",
34
+ "@meridianjs/notification": "^2.0.0",
35
+ "@meridianjs/invitation": "^2.0.0",
36
+ "@meridianjs/workspace-member": "^2.0.0",
37
+ "@meridianjs/team-member": "^2.0.0",
38
+ "@meridianjs/project-member": "^2.0.0",
39
+ "@meridianjs/app-role": "^2.0.0",
40
+ "@meridianjs/org-calendar": "^1.0.1",
41
41
  "multer": "^1.4.5-lts.1",
42
42
  "zod": "^3.24.0"
43
43
  },