@meridianjs/meridian 1.19.0 → 1.21.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.
- package/dist/api/admin/issues/route.d.ts.map +1 -1
- package/dist/api/admin/issues/route.js +5 -38
- package/dist/api/admin/issues/route.js.map +1 -1
- package/dist/api/auth/google/callback/route.d.ts.map +1 -1
- package/dist/api/auth/google/callback/route.js +32 -0
- package/dist/api/auth/google/callback/route.js.map +1 -1
- package/dist/api/auth/register/_domain-check.d.ts +2 -0
- package/dist/api/auth/register/_domain-check.d.ts.map +1 -0
- package/dist/api/auth/register/_domain-check.js +9 -0
- package/dist/api/auth/register/_domain-check.js.map +1 -0
- package/dist/api/auth/register/_otp-store.d.ts +18 -0
- package/dist/api/auth/register/_otp-store.d.ts.map +1 -0
- package/dist/api/auth/register/_otp-store.js +56 -0
- package/dist/api/auth/register/_otp-store.js.map +1 -0
- package/dist/api/auth/register/route.d.ts.map +1 -1
- package/dist/api/auth/register/route.js +35 -7
- package/dist/api/auth/register/route.js.map +1 -1
- package/dist/api/auth/register/send-otp/route.d.ts +3 -0
- package/dist/api/auth/register/send-otp/route.d.ts.map +1 -0
- package/dist/api/auth/register/send-otp/route.js +57 -0
- package/dist/api/auth/register/send-otp/route.js.map +1 -0
- package/dist/api/auth/setup/route.d.ts.map +1 -1
- package/dist/api/auth/setup/route.js +9 -1
- package/dist/api/auth/setup/route.js.map +1 -1
- package/dist/subscribers/registration-otp-requested.d.ts +9 -0
- package/dist/subscribers/registration-otp-requested.d.ts.map +1 -0
- package/dist/subscribers/registration-otp-requested.js +25 -0
- package/dist/subscribers/registration-otp-requested.js.map +1 -0
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/admin/issues/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAKrD,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/admin/issues/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAKrD,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAyChD,CAAA;AAED,eAAO,MAAM,IAAI,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,kBAmCrE,CAAA"}
|
|
@@ -27,24 +27,6 @@ export const GET = async (req, res) => {
|
|
|
27
27
|
filters.task_list_id = null;
|
|
28
28
|
else if (req.query.task_list_id)
|
|
29
29
|
filters.task_list_id = req.query.task_list_id;
|
|
30
|
-
// parent_id filter: "none" = top-level only, else filter by specific parent
|
|
31
|
-
if (req.query.parent_id === "none")
|
|
32
|
-
filters.parent_id = null;
|
|
33
|
-
else if (req.query.parent_id)
|
|
34
|
-
filters.parent_id = req.query.parent_id;
|
|
35
|
-
// assignee_id — filter using raw SQL on the jsonb column
|
|
36
|
-
if (req.query.assignee_id) {
|
|
37
|
-
const aid = req.query.assignee_id;
|
|
38
|
-
filters.assignee_ids = { $contains: aid };
|
|
39
|
-
}
|
|
40
|
-
// search — text search on title and identifier
|
|
41
|
-
if (req.query.search) {
|
|
42
|
-
const term = `%${req.query.search}%`;
|
|
43
|
-
filters.$or = [
|
|
44
|
-
{ title: { $ilike: term } },
|
|
45
|
-
{ identifier: { $ilike: term } },
|
|
46
|
-
];
|
|
47
|
-
}
|
|
48
30
|
// When scoped to a project, verify the caller has access to that project
|
|
49
31
|
if (req.query.project_id) {
|
|
50
32
|
const projectService = req.scope.resolve("projectModuleService");
|
|
@@ -58,26 +40,11 @@ export const GET = async (req, res) => {
|
|
|
58
40
|
return;
|
|
59
41
|
}
|
|
60
42
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// When fetching top-level issues, enrich with child_count so the UI
|
|
67
|
-
// knows which rows have expandable children without a separate request.
|
|
68
|
-
if (req.query.parent_id === "none" && issues.length > 0) {
|
|
69
|
-
const issueIds = issues.map((i) => i.id);
|
|
70
|
-
const [children] = await issueService.listAndCountIssues({ parent_id: { $in: issueIds } }, { limit: 10000 });
|
|
71
|
-
const childCountMap = {};
|
|
72
|
-
for (const child of children) {
|
|
73
|
-
const pid = child.parent_id;
|
|
74
|
-
if (pid)
|
|
75
|
-
childCountMap[pid] = (childCountMap[pid] ?? 0) + 1;
|
|
76
|
-
}
|
|
77
|
-
for (const issue of issues) {
|
|
78
|
-
;
|
|
79
|
-
issue.child_count = childCountMap[issue.id] ?? 0;
|
|
80
|
-
}
|
|
43
|
+
let [issues, count] = await issueService.listAndCountIssues(filters, { limit, offset, orderBy: { created_at: "ASC" } });
|
|
44
|
+
if (req.query.assignee_id) {
|
|
45
|
+
const id = req.query.assignee_id;
|
|
46
|
+
issues = issues.filter((i) => (i.assignee_ids ?? []).includes(id));
|
|
47
|
+
count = issues.length;
|
|
81
48
|
}
|
|
82
49
|
res.json({ issues, count, limit, offset });
|
|
83
50
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/admin/issues/route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAEhE,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,EAAE;IACnD,MAAM,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAQ,CAAA;IACnE,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAA;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAA;IAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAC5C,MAAM,OAAO,GAA4B,EAAE,CAAA;IAE3C,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE;QACjC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAC5C,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAA;IACvD,CAAC,CAAA;IAED,IAAI,GAAG,CAAC,KAAK,CAAC,UAAU;QAAE,OAAO,CAAC,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,CAAA;IACnE,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,CAAC,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,MAAgB,CAAC,CAAA;IAC7E,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI;QAAE,OAAO,CAAC,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAc,CAAC,CAAA;IACvE,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ;QAAE,OAAO,CAAC,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,QAAkB,CAAC,CAAA;IACnF,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,KAAK,MAAM;QAAE,OAAO,CAAC,SAAS,GAAG,IAAI,CAAA;SACvD,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS;QAAE,OAAO,CAAC,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,SAAmB,CAAA;IAC/E,IAAI,GAAG,CAAC,KAAK,CAAC,YAAY,KAAK,MAAM;QAAE,OAAO,CAAC,YAAY,GAAG,IAAI,CAAA;SAC7D,IAAI,GAAG,CAAC,KAAK,CAAC,YAAY;QAAE,OAAO,CAAC,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,YAAsB,CAAA;IAExF,
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/admin/issues/route.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/api/auth/google/callback/route.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/api/auth/google/callback/route.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAIvC;;;GAGG;AACH,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAmMhD,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import jwt from "jsonwebtoken";
|
|
2
2
|
import { randomBytes } from "node:crypto";
|
|
3
3
|
import { storeExchangeCode } from "../_exchange-store.js";
|
|
4
|
+
import { validateEmailDomain } from "../../register/_domain-check.js";
|
|
4
5
|
/**
|
|
5
6
|
* GET /auth/google/callback?code=...&state=...
|
|
6
7
|
* Handles the Google OAuth redirect. Absent googleOAuthService → 501.
|
|
@@ -108,6 +109,25 @@ export const GET = async (req, res) => {
|
|
|
108
109
|
return;
|
|
109
110
|
}
|
|
110
111
|
}
|
|
112
|
+
// For register flow (non-invite), check if open registration is enabled before exchanging code
|
|
113
|
+
let regConfig;
|
|
114
|
+
let registerUserCount = 0;
|
|
115
|
+
if (flow === "register" && !inviteRecord) {
|
|
116
|
+
const cfg = req.scope.resolve("config");
|
|
117
|
+
regConfig = cfg?.projectConfig?.registration;
|
|
118
|
+
try {
|
|
119
|
+
const userService = req.scope.resolve("userModuleService");
|
|
120
|
+
const [, count] = await userService.listAndCountUsers({}, { limit: 1 });
|
|
121
|
+
registerUserCount = count;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// assume not first setup
|
|
125
|
+
}
|
|
126
|
+
if (registerUserCount > 0 && !regConfig?.enabled) {
|
|
127
|
+
errorRedirect("Registration is not open. Contact an admin for an invitation.");
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
111
131
|
// Exchange code for Google profile
|
|
112
132
|
let profile;
|
|
113
133
|
try {
|
|
@@ -117,12 +137,23 @@ export const GET = async (req, res) => {
|
|
|
117
137
|
errorRedirect(err.message ?? "Failed to authenticate with Google");
|
|
118
138
|
return;
|
|
119
139
|
}
|
|
140
|
+
// Domain check for open registration (after we have the profile email)
|
|
141
|
+
if (flow === "register" && !inviteRecord && registerUserCount > 0 && regConfig?.enabled) {
|
|
142
|
+
try {
|
|
143
|
+
validateEmailDomain(profile.email, regConfig.allowedDomains);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
errorRedirect("Your email domain is not allowed to register.");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
120
150
|
// Verify invite email matches Google email (if invite has a locked email)
|
|
121
151
|
if (inviteRecord?.email && profile.email.toLowerCase() !== inviteRecord.email.toLowerCase()) {
|
|
122
152
|
errorRedirect(`This invitation was sent to ${inviteRecord.email}. Please sign in with that Google account.`);
|
|
123
153
|
return;
|
|
124
154
|
}
|
|
125
155
|
// Perform login / register
|
|
156
|
+
const autoRegister = flow === "register" && !inviteRecord;
|
|
126
157
|
let authResult;
|
|
127
158
|
try {
|
|
128
159
|
const authService = req.scope.resolve("authModuleService");
|
|
@@ -133,6 +164,7 @@ export const GET = async (req, res) => {
|
|
|
133
164
|
lastName: profile.lastName,
|
|
134
165
|
picture: profile.picture,
|
|
135
166
|
inviteRecord,
|
|
167
|
+
autoRegister,
|
|
136
168
|
});
|
|
137
169
|
}
|
|
138
170
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../src/api/auth/google/callback/route.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAA;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../src/api/auth/google/callback/route.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_domain-check.d.ts","sourceRoot":"","sources":["../../../../src/api/auth/register/_domain-check.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,IAAI,CASjF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function validateEmailDomain(email, allowedDomains) {
|
|
2
|
+
if (allowedDomains.includes("*"))
|
|
3
|
+
return;
|
|
4
|
+
const domain = email.split("@")[1]?.toLowerCase();
|
|
5
|
+
if (!domain || !allowedDomains.map(d => d.toLowerCase()).includes(domain)) {
|
|
6
|
+
throw Object.assign(new Error(`Email domain not allowed. Allowed: ${allowedDomains.join(", ")}`), { status: 422 });
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=_domain-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_domain-check.js","sourceRoot":"","sources":["../../../../src/api/auth/register/_domain-check.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,cAAwB;IACzE,IAAI,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAM;IACxC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAA;IACjD,IAAI,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1E,MAAM,MAAM,CAAC,MAAM,CACjB,IAAI,KAAK,CAAC,sCAAsC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAC5E,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAA;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory OTP store for registration email verification flow.
|
|
3
|
+
*
|
|
4
|
+
* One active OTP per email address. 6-digit numeric code, 10-minute TTL.
|
|
5
|
+
* Rate-limited: rejects re-sends within 60 seconds.
|
|
6
|
+
*
|
|
7
|
+
* Uses globalThis to guarantee a single shared Map even when route files
|
|
8
|
+
* are loaded via separate dynamic import() calls by the route scanner.
|
|
9
|
+
*/
|
|
10
|
+
/** Generate and store a 6-digit OTP for an email address. Throws if rate-limited. */
|
|
11
|
+
export declare function generateAndStoreOtp(email: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Consume an OTP. Returns true if the code matches and is not expired.
|
|
14
|
+
* Tracks failed attempts — after MAX_ATTEMPTS failures the entry is invalidated.
|
|
15
|
+
* On success the entry is deleted (single-use).
|
|
16
|
+
*/
|
|
17
|
+
export declare function consumeOtp(email: string, otp: string): boolean;
|
|
18
|
+
//# sourceMappingURL=_otp-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_otp-store.d.ts","sourceRoot":"","sources":["../../../../src/api/auth/register/_otp-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuBH,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUzD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAiB9D"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory OTP store for registration email verification flow.
|
|
3
|
+
*
|
|
4
|
+
* One active OTP per email address. 6-digit numeric code, 10-minute TTL.
|
|
5
|
+
* Rate-limited: rejects re-sends within 60 seconds.
|
|
6
|
+
*
|
|
7
|
+
* Uses globalThis to guarantee a single shared Map even when route files
|
|
8
|
+
* are loaded via separate dynamic import() calls by the route scanner.
|
|
9
|
+
*/
|
|
10
|
+
import { randomInt } from "crypto";
|
|
11
|
+
const STORE_KEY = "__meridian_registration_otp_store__";
|
|
12
|
+
const OTP_TTL_MS = 10 * 60 * 1000; // 10 minutes
|
|
13
|
+
const RESEND_COOLDOWN_MS = 60 * 1000; // 60 seconds
|
|
14
|
+
const MAX_ATTEMPTS = 5;
|
|
15
|
+
function getStore() {
|
|
16
|
+
if (!globalThis[STORE_KEY]) {
|
|
17
|
+
;
|
|
18
|
+
globalThis[STORE_KEY] = new Map();
|
|
19
|
+
}
|
|
20
|
+
return globalThis[STORE_KEY];
|
|
21
|
+
}
|
|
22
|
+
/** Generate and store a 6-digit OTP for an email address. Throws if rate-limited. */
|
|
23
|
+
export function generateAndStoreOtp(email) {
|
|
24
|
+
const store = getStore();
|
|
25
|
+
const existing = store.get(email);
|
|
26
|
+
if (existing && Date.now() - existing.sentAt < RESEND_COOLDOWN_MS) {
|
|
27
|
+
throw Object.assign(new Error("Please wait before requesting a new code"), { status: 429 });
|
|
28
|
+
}
|
|
29
|
+
const otp = String(randomInt(100000, 999999));
|
|
30
|
+
store.set(email, { otp, expiresAt: Date.now() + OTP_TTL_MS, sentAt: Date.now(), attempts: 0 });
|
|
31
|
+
return otp;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Consume an OTP. Returns true if the code matches and is not expired.
|
|
35
|
+
* Tracks failed attempts — after MAX_ATTEMPTS failures the entry is invalidated.
|
|
36
|
+
* On success the entry is deleted (single-use).
|
|
37
|
+
*/
|
|
38
|
+
export function consumeOtp(email, otp) {
|
|
39
|
+
const store = getStore();
|
|
40
|
+
const entry = store.get(email);
|
|
41
|
+
if (!entry || entry.expiresAt < Date.now()) {
|
|
42
|
+
store.delete(email);
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
if (entry.otp === otp) {
|
|
46
|
+
store.delete(email);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
// Wrong code — increment attempt counter
|
|
50
|
+
entry.attempts += 1;
|
|
51
|
+
if (entry.attempts >= MAX_ATTEMPTS) {
|
|
52
|
+
store.delete(email);
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=_otp-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_otp-store.js","sourceRoot":"","sources":["../../../../src/api/auth/register/_otp-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AASlC,MAAM,SAAS,GAAG,qCAAqC,CAAA;AACvD,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA,CAAE,aAAa;AAChD,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,CAAA,CAAC,aAAa;AAClD,MAAM,YAAY,GAAG,CAAC,CAAA;AAEtB,SAAS,QAAQ;IACf,IAAI,CAAE,UAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,CAAC;QAAC,UAAkB,CAAC,SAAS,CAAC,GAAG,IAAI,GAAG,EAAoB,CAAA;IAC/D,CAAC;IACD,OAAQ,UAAkB,CAAC,SAAS,CAAC,CAAA;AACvC,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAA;IACxB,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACjC,IAAI,QAAQ,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;QAClE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,0CAA0C,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;IAC7F,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC7C,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAA;IAC9F,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,GAAW;IACnD,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAA;IACxB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAC9B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QAC3C,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACnB,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;QACtB,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACnB,OAAO,IAAI,CAAA;IACb,CAAC;IACD,yCAAyC;IACzC,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAA;IACnB,IAAI,KAAK,CAAC,QAAQ,IAAI,YAAY,EAAE,CAAC;QACnC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACrB,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
|
|
@@ -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;
|
|
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,26 +1,54 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { consumeOtp } from "./_otp-store.js";
|
|
3
|
+
import { validateEmailDomain } from "./_domain-check.js";
|
|
2
4
|
const registerSchema = z.object({
|
|
3
5
|
email: z.string().email(),
|
|
4
6
|
password: z.string().min(8, "Password must be at least 8 characters"),
|
|
5
7
|
first_name: z.string().optional(),
|
|
6
8
|
last_name: z.string().optional(),
|
|
9
|
+
otp: z.string().length(6).optional(),
|
|
7
10
|
});
|
|
8
11
|
export const POST = async (req, res) => {
|
|
9
|
-
// Registration is only open for the very first user (super-admin setup).
|
|
10
|
-
// All subsequent accounts must be created via an invitation link.
|
|
11
12
|
const userService = req.scope.resolve("userModuleService");
|
|
12
13
|
const [, userCount] = await userService.listAndCountUsers({}, { limit: 1 });
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
const isFirstSetup = userCount === 0;
|
|
15
|
+
if (!isFirstSetup) {
|
|
16
|
+
const config = req.scope.resolve("config");
|
|
17
|
+
const regConfig = config?.projectConfig?.registration;
|
|
18
|
+
if (!regConfig?.enabled) {
|
|
19
|
+
res.status(403).json({
|
|
20
|
+
error: { message: "Registration is closed. Ask an admin to send you an invitation link." },
|
|
21
|
+
});
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// Validate domain before parsing full body (fast rejection)
|
|
25
|
+
const emailRaw = req.body?.email;
|
|
26
|
+
if (emailRaw) {
|
|
27
|
+
try {
|
|
28
|
+
validateEmailDomain(emailRaw, regConfig.allowedDomains);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
res.status(err.status ?? 422).json({ error: { message: err.message } });
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (!req.body?.otp) {
|
|
36
|
+
res.status(400).json({ error: { message: "Verification code is required" } });
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
18
39
|
}
|
|
19
40
|
const result = registerSchema.safeParse(req.body);
|
|
20
41
|
if (!result.success) {
|
|
21
42
|
res.status(400).json({ error: { message: "Validation error", details: result.error.flatten().fieldErrors } });
|
|
22
43
|
return;
|
|
23
44
|
}
|
|
45
|
+
if (!isFirstSetup) {
|
|
46
|
+
const valid = consumeOtp(result.data.email.toLowerCase().trim(), result.data.otp);
|
|
47
|
+
if (!valid) {
|
|
48
|
+
res.status(400).json({ error: { message: "Invalid or expired verification code" } });
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
24
52
|
const authService = req.scope.resolve("authModuleService");
|
|
25
53
|
const response = await authService.register(result.data);
|
|
26
54
|
res.status(201).json(response);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/auth/register/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/auth/register/route.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/api/auth/register/send-otp/route.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAQvC,eAAO,MAAM,IAAI,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAqDjD,CAAA"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { generateAndStoreOtp } from "../_otp-store.js";
|
|
3
|
+
import { validateEmailDomain } from "../_domain-check.js";
|
|
4
|
+
const schema = z.object({
|
|
5
|
+
email: z.string().email(),
|
|
6
|
+
});
|
|
7
|
+
export const POST = async (req, res) => {
|
|
8
|
+
const config = req.scope.resolve("config");
|
|
9
|
+
const regConfig = config?.projectConfig?.registration;
|
|
10
|
+
if (!regConfig?.enabled) {
|
|
11
|
+
res.status(403).json({ error: { message: "Registration is closed." } });
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const result = schema.safeParse(req.body);
|
|
15
|
+
if (!result.success) {
|
|
16
|
+
res.status(400).json({ error: { message: "Invalid email address" } });
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const { email } = result.data;
|
|
20
|
+
try {
|
|
21
|
+
validateEmailDomain(email, regConfig.allowedDomains);
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
res.status(err.status ?? 422).json({ error: { message: err.message } });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// If user already exists, return 200 silently (no enumeration)
|
|
28
|
+
try {
|
|
29
|
+
const userService = req.scope.resolve("userModuleService");
|
|
30
|
+
const existing = await userService.retrieveUserByEmail(email.toLowerCase().trim());
|
|
31
|
+
if (existing) {
|
|
32
|
+
res.json({ ok: true });
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// user service error — fall through to OTP generation
|
|
38
|
+
}
|
|
39
|
+
let otp;
|
|
40
|
+
try {
|
|
41
|
+
otp = generateAndStoreOtp(email.toLowerCase().trim());
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Rate limited — still return 200 to avoid timing-based enumeration
|
|
45
|
+
res.json({ ok: true });
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const eventBus = req.scope.resolve("eventBus");
|
|
50
|
+
await eventBus.emit({ name: "registration.otp_requested", data: { email, otp } });
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Non-fatal — OTP is stored, email may not send
|
|
54
|
+
}
|
|
55
|
+
res.json({ ok: true });
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../src/api/auth/register/send-otp/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAEzD,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IACtB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;CAC1B,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,EAAE;IACpD,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAQ,CAAA;IACjD,MAAM,SAAS,GAAG,MAAM,EAAE,aAAa,EAAE,YAAY,CAAA;IAErD,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC;QACxB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE,CAAC,CAAA;QACvE,OAAM;IACR,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACzC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,uBAAuB,EAAE,EAAE,CAAC,CAAA;QACrE,OAAM;IACR,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,IAAI,CAAA;IAE7B,IAAI,CAAC;QACH,mBAAmB,CAAC,KAAK,EAAE,SAAS,CAAC,cAAc,CAAC,CAAA;IACtD,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,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;QACvE,OAAM;IACR,CAAC;IAED,+DAA+D;IAC/D,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAQ,CAAA;QACjE,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,mBAAmB,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;QAClF,IAAI,QAAQ,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;YACtB,OAAM;QACR,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,sDAAsD;IACxD,CAAC;IAED,IAAI,GAAW,CAAA;IACf,IAAI,CAAC;QACH,GAAG,GAAG,mBAAmB,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;QACpE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;QACtB,OAAM;IACR,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAQ,CAAA;QACrD,MAAM,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,4BAA4B,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAA;IACnF,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;AACxB,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/auth/setup/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEhD;;;;GAIG;AACH,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/api/auth/setup/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEhD;;;;GAIG;AACH,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBA2BhD,CAAA"}
|
|
@@ -21,6 +21,14 @@ export const GET = async (req, res) => {
|
|
|
21
21
|
catch {
|
|
22
22
|
// googleOAuthService not registered — feature disabled
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
let registrationEnabled = false;
|
|
25
|
+
try {
|
|
26
|
+
const config = req.scope.resolve("config");
|
|
27
|
+
registrationEnabled = config?.projectConfig?.registration?.enabled === true;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// config not available — default false
|
|
31
|
+
}
|
|
32
|
+
res.json({ needsSetup, googleOAuthEnabled, registrationEnabled });
|
|
25
33
|
};
|
|
26
34
|
//# sourceMappingURL=route.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/auth/setup/route.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,EAAE;IACnD,IAAI,UAAU,GAAG,KAAK,CAAA;IACtB,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAQ,CAAA;QACjE,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,UAAU,EAAE,CAAA;QAC5C,UAAU,GAAG,KAAK,KAAK,CAAC,CAAA;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;IAC/D,CAAC;IAED,IAAI,kBAAkB,GAAG,KAAK,CAAA;IAC9B,IAAI,CAAC;QACH,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;QACvC,kBAAkB,GAAG,IAAI,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,uDAAuD;IACzD,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../src/api/auth/setup/route.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAa,EAAE,EAAE;IACnD,IAAI,UAAU,GAAG,KAAK,CAAA;IACtB,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAQ,CAAA;QACjE,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,UAAU,EAAE,CAAA;QAC5C,UAAU,GAAG,KAAK,KAAK,CAAC,CAAA;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;IAC/D,CAAC;IAED,IAAI,kBAAkB,GAAG,KAAK,CAAA;IAC9B,IAAI,CAAC;QACH,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;QACvC,kBAAkB,GAAG,IAAI,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,uDAAuD;IACzD,CAAC;IAED,IAAI,mBAAmB,GAAG,KAAK,CAAA;IAC/B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAQ,CAAA;QACjD,mBAAmB,GAAG,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,KAAK,IAAI,CAAA;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,CAAC,CAAA;AACnE,CAAC,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SubscriberArgs, SubscriberConfig } from "@meridianjs/types";
|
|
2
|
+
interface RegistrationOtpRequestedData {
|
|
3
|
+
email: string;
|
|
4
|
+
otp: string;
|
|
5
|
+
}
|
|
6
|
+
export default function handler({ event, container }: SubscriberArgs<RegistrationOtpRequestedData>): Promise<void>;
|
|
7
|
+
export declare const config: SubscriberConfig;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=registration-otp-requested.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registration-otp-requested.d.ts","sourceRoot":"","sources":["../../src/subscribers/registration-otp-requested.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAGzE,UAAU,4BAA4B;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,wBAA8B,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,cAAc,CAAC,4BAA4B,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBvH;AAED,eAAO,MAAM,MAAM,EAAE,gBAA0D,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { emailHtml, resolveTemplate } from "./_email-helper.js";
|
|
2
|
+
export default async function handler({ event, container }) {
|
|
3
|
+
const data = event.data;
|
|
4
|
+
try {
|
|
5
|
+
const emailService = container.resolve("emailService");
|
|
6
|
+
const tpl = resolveTemplate(container, "registration.otp_requested", {
|
|
7
|
+
email: data.email,
|
|
8
|
+
otp: data.otp,
|
|
9
|
+
});
|
|
10
|
+
await emailService.send({
|
|
11
|
+
to: data.email,
|
|
12
|
+
subject: tpl?.subject ?? "Your Meridian verification code",
|
|
13
|
+
text: tpl?.text ?? `Your verification code is: ${data.otp}\n\nThis code expires in 10 minutes. If you didn't request this, you can safely ignore this email.`,
|
|
14
|
+
html: tpl?.html ?? emailHtml(`Your verification code is:<br/><br/>` +
|
|
15
|
+
`<div style="font-size:32px;font-weight:700;letter-spacing:8px;text-align:center;padding:16px 0;font-family:monospace;color:#4f46e5">${data.otp}</div><br/>` +
|
|
16
|
+
`This code expires in 10 minutes. If you didn't request this, you can safely ignore this email.`),
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
const logger = container.resolve("logger");
|
|
21
|
+
logger.error(`[email] registration.otp_requested: ${err instanceof Error ? err.message : String(err)}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export const config = { event: "registration.otp_requested" };
|
|
25
|
+
//# sourceMappingURL=registration-otp-requested.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registration-otp-requested.js","sourceRoot":"","sources":["../../src/subscribers/registration-otp-requested.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAO/D,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAgD;IACtG,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;IAEvB,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,cAAc,CAAQ,CAAA;QAE7D,MAAM,GAAG,GAAG,eAAe,CAAC,SAAS,EAAE,4BAA4B,EAAE;YACnE,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC,CAAA;QAEF,MAAM,YAAY,CAAC,IAAI,CAAC;YACtB,EAAE,EAAE,IAAI,CAAC,KAAK;YACd,OAAO,EAAE,GAAG,EAAE,OAAO,IAAI,iCAAiC;YAC1D,IAAI,EAAE,GAAG,EAAE,IAAI,IAAI,8BAA8B,IAAI,CAAC,GAAG,oGAAoG;YAC7J,IAAI,EAAE,GAAG,EAAE,IAAI,IAAI,SAAS,CAC1B,sCAAsC;gBACtC,uIAAuI,IAAI,CAAC,GAAG,aAAa;gBAC5J,gGAAgG,CACjG;SACF,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAQ,CAAA;QACjD,MAAM,CAAC,KAAK,CAAC,uCAAuC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACzG,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAqB,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meridianjs/meridian",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.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,13 +20,13 @@
|
|
|
20
20
|
"prepublishOnly": "cd ../.. && npm run check:routes && cd packages/meridian && npm run build"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@meridianjs/framework": "^1.
|
|
24
|
-
"@meridianjs/framework-utils": "^1.
|
|
25
|
-
"@meridianjs/workflow-engine": "^1.
|
|
26
|
-
"@meridianjs/types": "^1.
|
|
23
|
+
"@meridianjs/framework": "^1.21.0",
|
|
24
|
+
"@meridianjs/framework-utils": "^1.21.0",
|
|
25
|
+
"@meridianjs/workflow-engine": "^1.21.0",
|
|
26
|
+
"@meridianjs/types": "^1.21.0",
|
|
27
27
|
"@meridianjs/user": "^1.0.0",
|
|
28
28
|
"@meridianjs/workspace": "^1.2.0",
|
|
29
|
-
"@meridianjs/auth": "^1.
|
|
29
|
+
"@meridianjs/auth": "^1.21.0",
|
|
30
30
|
"@meridianjs/project": "^1.1.0",
|
|
31
31
|
"@meridianjs/issue": "^1.3.0",
|
|
32
32
|
"@meridianjs/sprint": "^1.0.0",
|