customer-registration 0.0.114 → 0.0.116
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/.medusa/server/src/api/auth/customer/emailpass/register/route.js +34 -0
- package/.medusa/server/src/api/auth/customer/emailpass/route.js +9 -127
- package/.medusa/server/src/api/auth/customer/shared/__tests__/build-unified-login-auth-data.test.js +54 -0
- package/.medusa/server/src/api/auth/customer/shared/__tests__/parse-login-body.test.js +79 -0
- package/.medusa/server/src/api/auth/customer/shared/__tests__/parse-register-body.test.js +87 -0
- package/.medusa/server/src/api/auth/customer/shared/build-unified-login-auth-data.js +47 -0
- package/.medusa/server/src/api/auth/customer/shared/complete-customer-login.js +79 -0
- package/.medusa/server/src/api/auth/customer/shared/complete-registration-token.js +34 -0
- package/.medusa/server/src/api/auth/customer/shared/customer-login-post.js +142 -0
- package/.medusa/server/src/api/auth/customer/shared/enforce-registration-verification.js +44 -0
- package/.medusa/server/src/api/auth/customer/shared/parse-login-body.js +42 -0
- package/.medusa/server/src/api/auth/customer/shared/parse-register-body.js +58 -0
- package/.medusa/server/vitest.config.mjs +8 -0
- package/README.md +33 -17
- package/package.json +1 -1
- package/.medusa/server/src/api/auth/customer/phonepass/register/route.js +0 -50
- package/.medusa/server/src/api/auth/customer/phonepass/route.js +0 -105
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.POST = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const config_1 = require("../../../../../config");
|
|
6
|
+
const complete_registration_token_1 = require("../../shared/complete-registration-token");
|
|
7
|
+
const parse_register_body_1 = require("../../shared/parse-register-body");
|
|
8
|
+
/**
|
|
9
|
+
* Unified registration: emailpass and/or phonepass via `service.register`, depending on
|
|
10
|
+
* plugin `registration.identifier` and JSON body. Response: `{ token }` (Medusa default).
|
|
11
|
+
*/
|
|
12
|
+
const POST = async (req, res) => {
|
|
13
|
+
const config = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
|
|
14
|
+
const options = (0, config_1.resolveCustomerRegistrationOptions)(config);
|
|
15
|
+
const registrationIdentifier = options.registration
|
|
16
|
+
.identifier;
|
|
17
|
+
const parsed = (0, parse_register_body_1.parseCustomerRegisterBody)(req.body, registrationIdentifier);
|
|
18
|
+
const service = req.scope.resolve(utils_1.Modules.AUTH);
|
|
19
|
+
const authData = {
|
|
20
|
+
url: req.url,
|
|
21
|
+
headers: req.headers,
|
|
22
|
+
query: req.query,
|
|
23
|
+
body: req.body,
|
|
24
|
+
protocol: req.protocol,
|
|
25
|
+
};
|
|
26
|
+
const provider = parsed.mode === "email" ? "emailpass" : "phonepass";
|
|
27
|
+
const { success, error, authIdentity } = await service.register(provider, authData);
|
|
28
|
+
if (!success || !authIdentity) {
|
|
29
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, error || "Registration failed");
|
|
30
|
+
}
|
|
31
|
+
await (0, complete_registration_token_1.respondWithRegistrationToken)(req, res, authIdentity);
|
|
32
|
+
};
|
|
33
|
+
exports.POST = POST;
|
|
34
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvY3VzdG9tZXIvZW1haWxwYXNzL3JlZ2lzdGVyL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLHFEQUlrQztBQUNsQyxrREFHOEI7QUFDOUIsMEZBQXVGO0FBQ3ZGLDBFQUd5QztBQUV6Qzs7O0dBR0c7QUFDSSxNQUFNLElBQUksR0FBRyxLQUFLLEVBQUUsR0FBa0IsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDcEUsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsYUFBYSxDQUFDLENBQUE7SUFDekUsTUFBTSxPQUFPLEdBQUcsSUFBQSwyQ0FBa0MsRUFBQyxNQUEyQixDQUFDLENBQUE7SUFDL0UsTUFBTSxzQkFBc0IsR0FBRyxPQUFPLENBQUMsWUFBWTtTQUNoRCxVQUEwQyxDQUFBO0lBRTdDLE1BQU0sTUFBTSxHQUFHLElBQUEsK0NBQXlCLEVBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxzQkFBc0IsQ0FBQyxDQUFBO0lBRTFFLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUUvQyxNQUFNLFFBQVEsR0FBRztRQUNmLEdBQUcsRUFBRSxHQUFHLENBQUMsR0FBRztRQUNaLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTztRQUNwQixLQUFLLEVBQUUsR0FBRyxDQUFDLEtBQUs7UUFDaEIsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJO1FBQ2QsUUFBUSxFQUFFLEdBQUcsQ0FBQyxRQUFRO0tBQ0EsQ0FBQTtJQUN4QixNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsSUFBSSxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUE7SUFFcEUsTUFBTSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEdBQUcsTUFBTSxPQUFPLENBQUMsUUFBUSxDQUM3RCxRQUFRLEVBQ1IsUUFBUSxDQUNULENBQUE7SUFFRCxJQUFJLENBQUMsT0FBTyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDOUIsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsS0FBSyxJQUFJLHFCQUFxQixDQUMvQixDQUFBO0lBQ0gsQ0FBQztJQUVELE1BQU0sSUFBQSwwREFBNEIsRUFBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLFlBQXVDLENBQUMsQ0FBQTtBQUN2RixDQUFDLENBQUE7QUFoQ1ksUUFBQSxJQUFJLFFBZ0NoQiJ9
|
|
@@ -1,132 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.POST =
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const config = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
|
|
11
|
-
const loginOptions = (0, config_1.resolveCustomerRegistrationOptions)(config);
|
|
12
|
-
if (loginOptions.login.identifier === "phone") {
|
|
13
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Email login is not enabled. Please log in with your phone number.");
|
|
14
|
-
}
|
|
15
|
-
const service = req.scope.resolve(utils_1.Modules.AUTH);
|
|
16
|
-
const authData = {
|
|
17
|
-
url: req.url,
|
|
18
|
-
headers: req.headers,
|
|
19
|
-
query: req.query,
|
|
20
|
-
body: req.body,
|
|
21
|
-
protocol: req.protocol,
|
|
22
|
-
};
|
|
23
|
-
const { success, error, authIdentity, location } = await service.authenticate("emailpass", authData);
|
|
24
|
-
if (location) {
|
|
25
|
-
return res.status(200).json({ location });
|
|
26
|
-
}
|
|
27
|
-
if (success && authIdentity) {
|
|
28
|
-
const email = authIdentity.provider_identities?.[0]?.entity_id ?? "";
|
|
29
|
-
// Ensure authIdentity has customer_id in app_metadata
|
|
30
|
-
// The generateJwtTokenForAuthIdentity function requires app_metadata.customer_id
|
|
31
|
-
let customerId = authIdentity.app_metadata?.customer_id;
|
|
32
|
-
if (!customerId) {
|
|
33
|
-
// Try to get customer_id from provider_identity entity_id (email)
|
|
34
|
-
// and look up the customer
|
|
35
|
-
const customerModule = req.scope.resolve(utils_1.Modules.CUSTOMER);
|
|
36
|
-
const customers = await customerModule.listCustomers({
|
|
37
|
-
email: email.toLowerCase(),
|
|
38
|
-
});
|
|
39
|
-
if (customers && customers.length > 0) {
|
|
40
|
-
customerId = customers[0].id;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
const resolvedCustomerId = typeof customerId === "string" && customerId.trim().length > 0
|
|
44
|
-
? customerId
|
|
45
|
-
: undefined;
|
|
46
|
-
if (!resolvedCustomerId) {
|
|
47
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Unable to determine customer ID for authentication");
|
|
48
|
-
}
|
|
49
|
-
await enforceEmailAndPhoneVerification({
|
|
50
|
-
customerId: resolvedCustomerId,
|
|
51
|
-
email,
|
|
52
|
-
req,
|
|
53
|
-
});
|
|
54
|
-
const accountDeletionService = req.scope.resolve(account_deletion_request_1.ACCOUNT_DELETION_REQUEST_MODULE);
|
|
55
|
-
if (await accountDeletionService.hasPendingRequest(resolvedCustomerId)) {
|
|
56
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Customer has an active account deletion request");
|
|
57
|
-
}
|
|
58
|
-
// Ensure app_metadata has customer_id
|
|
59
|
-
const authIdentityWithCustomerId = {
|
|
60
|
-
...authIdentity,
|
|
61
|
-
app_metadata: {
|
|
62
|
-
...authIdentity.app_metadata,
|
|
63
|
-
customer_id: resolvedCustomerId,
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
const { http } = config.projectConfig;
|
|
67
|
-
if (!http.jwtSecret) {
|
|
68
|
-
console.error("[emailpass-auth] JWT secret is not configured", {
|
|
69
|
-
email,
|
|
70
|
-
customerId: resolvedCustomerId,
|
|
71
|
-
hasJwtSecret: !!http.jwtSecret,
|
|
72
|
-
});
|
|
73
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "JWT secret is not configured");
|
|
74
|
-
}
|
|
75
|
-
let token;
|
|
76
|
-
try {
|
|
77
|
-
token = await (0, generate_jwt_token_1.generateJwtTokenForAuthIdentity)({
|
|
78
|
-
authIdentity: authIdentityWithCustomerId,
|
|
79
|
-
actorType: "customer",
|
|
80
|
-
}, {
|
|
81
|
-
secret: http.jwtSecret,
|
|
82
|
-
expiresIn: http.jwtExpiresIn || "7d",
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
catch (jwtError) {
|
|
86
|
-
console.error("[emailpass-auth] JWT generation threw an exception", {
|
|
87
|
-
email,
|
|
88
|
-
customerId: resolvedCustomerId,
|
|
89
|
-
error: jwtError instanceof Error ? jwtError.message : String(jwtError),
|
|
90
|
-
stack: jwtError instanceof Error ? jwtError.stack : undefined,
|
|
91
|
-
jwtSecretExists: !!http.jwtSecret,
|
|
92
|
-
});
|
|
93
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `JWT generation failed: ${jwtError instanceof Error ? jwtError.message : "Unknown error"}`);
|
|
94
|
-
}
|
|
95
|
-
// Validate token was generated successfully
|
|
96
|
-
if (!token || typeof token !== "string") {
|
|
97
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to generate authentication token for customer ${resolvedCustomerId}. Token type: ${typeof token}, Token value: ${token}`);
|
|
98
|
-
}
|
|
99
|
-
return res.status(200).json({ token });
|
|
100
|
-
}
|
|
101
|
-
console.error("[emailpass-auth] Authentication failed", {
|
|
102
|
-
success,
|
|
103
|
-
error,
|
|
104
|
-
hasAuthIdentity: !!authIdentity,
|
|
105
|
-
});
|
|
106
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, error || "Authentication failed");
|
|
107
|
-
};
|
|
108
|
-
exports.GET = GET;
|
|
3
|
+
exports.POST = void 0;
|
|
4
|
+
const customer_login_post_1 = require("../shared/customer-login-post");
|
|
5
|
+
/**
|
|
6
|
+
* Customer login (unified): delegates to `handleCustomerLogin`.
|
|
7
|
+
* - POST + JSON body: `{ email, password }` **or** `{ phone, password }` (exactly one of email/phone), gated by plugin `login.identifier`.
|
|
8
|
+
* - Optional query params can fill missing fields on POST (see `buildUnifiedLoginAuthData`); prefer JSON body for credentials.
|
|
9
|
+
*/
|
|
109
10
|
const POST = async (req, res) => {
|
|
110
|
-
await (0,
|
|
11
|
+
await (0, customer_login_post_1.handleCustomerLogin)(req, res);
|
|
111
12
|
};
|
|
112
13
|
exports.POST = POST;
|
|
113
|
-
|
|
114
|
-
// Read identifier + require_verification from plugin config
|
|
115
|
-
const configModule = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
|
|
116
|
-
const options = (0, config_1.resolveCustomerRegistrationOptions)(configModule);
|
|
117
|
-
const { identifier, require_verification } = options.registration;
|
|
118
|
-
// If verification is disabled entirely, skip all checks
|
|
119
|
-
if (!require_verification) {
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
const otpService = req.scope.resolve(otp_verification_1.OTP_VERIFICATION_MODULE);
|
|
123
|
-
const verificationStatus = await otpService.getCustomerVerificationByCustomerId(req.scope, customerId);
|
|
124
|
-
if ((identifier === "email" || identifier === "both") && !verificationStatus.email_verified) {
|
|
125
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Email not verified.");
|
|
126
|
-
}
|
|
127
|
-
if ((identifier === "phone" || identifier === "both") && !verificationStatus.phone_verified) {
|
|
128
|
-
console.error("[emailpass-auth] Phone not verified", { email });
|
|
129
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Phone not verified.");
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvY3VzdG9tZXIvZW1haWxwYXNzL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQU1BLHFEQUlrQztBQUNsQywyRkFBb0c7QUFDcEcsMkZBQThGO0FBRTlGLDJFQUE4RTtBQUk5RSwrQ0FHMkI7QUFFcEIsTUFBTSxHQUFHLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ25FLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUM5QixpQ0FBeUIsQ0FBQyxhQUFhLENBQ3hDLENBQUE7SUFFRCxNQUFNLFlBQVksR0FBRyxJQUFBLDJDQUFrQyxFQUFDLE1BQTJCLENBQUMsQ0FBQTtJQUNwRixJQUFJLFlBQVksQ0FBQyxLQUFLLENBQUMsVUFBVSxLQUFLLE9BQU8sRUFBRSxDQUFDO1FBQzlDLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLG1FQUFtRSxDQUNwRSxDQUFBO0lBQ0gsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUUvQyxNQUFNLFFBQVEsR0FBRztRQUNmLEdBQUcsRUFBRSxHQUFHLENBQUMsR0FBRztRQUNaLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTztRQUNwQixLQUFLLEVBQUUsR0FBRyxDQUFDLEtBQUs7UUFDaEIsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJO1FBQ2QsUUFBUSxFQUFFLEdBQUcsQ0FBQyxRQUFRO0tBQ0EsQ0FBQTtJQUV4QixNQUFNLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLEdBQzlDLE1BQU0sT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVB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
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvY3VzdG9tZXIvZW1haWxwYXNzL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHVFQUFtRTtBQUVuRTs7OztHQUlHO0FBRUksTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ3BFLE1BQU0sSUFBQSx5Q0FBbUIsRUFBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUE7QUFDckMsQ0FBQyxDQUFBO0FBRlksUUFBQSxJQUFJLFFBRWhCIn0=
|
package/.medusa/server/src/api/auth/customer/shared/__tests__/build-unified-login-auth-data.test.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const build_unified_login_auth_data_1 = require("../build-unified-login-auth-data");
|
|
5
|
+
function makeReq(partial) {
|
|
6
|
+
return {
|
|
7
|
+
url: "/auth/customer/emailpass",
|
|
8
|
+
headers: {},
|
|
9
|
+
query: partial.query ?? {},
|
|
10
|
+
body: partial.body,
|
|
11
|
+
protocol: "http",
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
(0, vitest_1.describe)("buildUnifiedLoginAuthData", () => {
|
|
15
|
+
const cases = [
|
|
16
|
+
{
|
|
17
|
+
name: "POST body only",
|
|
18
|
+
req: makeReq({
|
|
19
|
+
body: { email: "a@b.co", password: "x" },
|
|
20
|
+
}),
|
|
21
|
+
wantBody: { email: "a@b.co", password: "x" },
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: "GET query fills missing body fields",
|
|
25
|
+
req: makeReq({
|
|
26
|
+
body: {},
|
|
27
|
+
query: { phone: "+1555", password: "secret" },
|
|
28
|
+
}),
|
|
29
|
+
wantBody: { phone: "+1555", password: "secret" },
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: "body overrides query for same key",
|
|
33
|
+
req: makeReq({
|
|
34
|
+
body: { email: "primary@x.com", password: "p1" },
|
|
35
|
+
query: { email: "ignored@x.com", password: "p2" },
|
|
36
|
+
}),
|
|
37
|
+
wantBody: { email: "primary@x.com", password: "p1" },
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "array query param takes first string",
|
|
41
|
+
req: makeReq({
|
|
42
|
+
body: {},
|
|
43
|
+
query: { email: ["x@y.com", "z@y.com"], password: "pw" },
|
|
44
|
+
}),
|
|
45
|
+
wantBody: { email: "x@y.com", password: "pw" },
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
vitest_1.it.each(cases)("$name", ({ req, wantBody }) => {
|
|
49
|
+
const auth = (0, build_unified_login_auth_data_1.buildUnifiedLoginAuthData)(req);
|
|
50
|
+
(0, vitest_1.expect)(auth.body).toEqual(wantBody);
|
|
51
|
+
(0, vitest_1.expect)(auth.query).toBe(req.query);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQtdW5pZmllZC1sb2dpbi1hdXRoLWRhdGEudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcGkvYXV0aC9jdXN0b21lci9zaGFyZWQvX190ZXN0c19fL2J1aWxkLXVuaWZpZWQtbG9naW4tYXV0aC1kYXRhLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxtQ0FBNkM7QUFFN0Msb0ZBQTRFO0FBRTVFLFNBQVMsT0FBTyxDQUFDLE9BR2hCO0lBQ0MsT0FBTztRQUNMLEdBQUcsRUFBRSwwQkFBMEI7UUFDL0IsT0FBTyxFQUFFLEVBQUU7UUFDWCxLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUssSUFBSSxFQUFFO1FBQzFCLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtRQUNsQixRQUFRLEVBQUUsTUFBTTtLQUNBLENBQUE7QUFDcEIsQ0FBQztBQUVELElBQUEsaUJBQVEsRUFBQywyQkFBMkIsRUFBRSxHQUFHLEVBQUU7SUFDekMsTUFBTSxLQUFLLEdBSU47UUFDSDtZQUNFLElBQUksRUFBRSxnQkFBZ0I7WUFDdEIsR0FBRyxFQUFFLE9BQU8sQ0FBQztnQkFDWCxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUU7YUFDekMsQ0FBQztZQUNGLFFBQVEsRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRTtTQUM3QztRQUNEO1lBQ0UsSUFBSSxFQUFFLHFDQUFxQztZQUMzQyxHQUFHLEVBQUUsT0FBTyxDQUFDO2dCQUNYLElBQUksRUFBRSxFQUFFO2dCQUNSLEtBQUssRUFBRSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRTthQUM5QyxDQUFDO1lBQ0YsUUFBUSxFQUFFLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFO1NBQ2pEO1FBQ0Q7WUFDRSxJQUFJLEVBQUUsbUNBQW1DO1lBQ3pDLEdBQUcsRUFBRSxPQUFPLENBQUM7Z0JBQ1gsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO2dCQUNoRCxLQUFLLEVBQUUsRUFBRSxLQUFLLEVBQUUsZUFBZSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7YUFDbEQsQ0FBQztZQUNGLFFBQVEsRUFBRSxFQUFFLEtBQUssRUFBRSxlQUFlLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRTtTQUNyRDtRQUNEO1lBQ0UsSUFBSSxFQUFFLHNDQUFzQztZQUM1QyxHQUFHLEVBQUUsT0FBTyxDQUFDO2dCQUNYLElBQUksRUFBRSxFQUFFO2dCQUNSLEtBQUssRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO2FBQ3pELENBQUM7WUFDRixRQUFRLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7U0FDL0M7S0FDRixDQUFBO0lBRUQsV0FBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFO1FBQzVDLE1BQU0sSUFBSSxHQUFHLElBQUEseURBQXlCLEVBQUMsR0FBRyxDQUFDLENBQUE7UUFDM0MsSUFBQSxlQUFNLEVBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUNuQyxJQUFBLGVBQU0sRUFBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUNwQyxDQUFDLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FBQyxDQUFBIn0=
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const parse_login_body_1 = require("../parse-login-body");
|
|
6
|
+
(0, vitest_1.describe)("parseCustomerLoginBody", () => {
|
|
7
|
+
const cases = [
|
|
8
|
+
{
|
|
9
|
+
name: "both config + email only",
|
|
10
|
+
body: { email: "a@b.co", password: "x" },
|
|
11
|
+
loginIdentifier: "both",
|
|
12
|
+
want: { mode: "email" },
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: "both config + phone only",
|
|
16
|
+
body: { phone: "+15550001", password: "x" },
|
|
17
|
+
loginIdentifier: "both",
|
|
18
|
+
want: { mode: "phone" },
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: "email config + email (trim)",
|
|
22
|
+
body: { email: " u@v.com ", password: "x" },
|
|
23
|
+
loginIdentifier: "email",
|
|
24
|
+
want: { mode: "email" },
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: "phone config + phone",
|
|
28
|
+
body: { phone: "7428730894", password: "x" },
|
|
29
|
+
loginIdentifier: "phone",
|
|
30
|
+
want: { mode: "phone" },
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
vitest_1.it.each(cases)("$name", ({ body, loginIdentifier, want }) => {
|
|
34
|
+
(0, vitest_1.expect)((0, parse_login_body_1.parseCustomerLoginBody)(body, loginIdentifier)).toEqual(want);
|
|
35
|
+
});
|
|
36
|
+
const errorCases = [
|
|
37
|
+
{
|
|
38
|
+
name: "both present",
|
|
39
|
+
body: { email: "a@b.co", phone: "+1", password: "x" },
|
|
40
|
+
loginIdentifier: "both",
|
|
41
|
+
wantType: utils_1.MedusaError.Types.INVALID_DATA,
|
|
42
|
+
wantMessageSubstring: "not both",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "neither present",
|
|
46
|
+
body: { password: "x" },
|
|
47
|
+
loginIdentifier: "both",
|
|
48
|
+
wantType: utils_1.MedusaError.Types.INVALID_DATA,
|
|
49
|
+
wantMessageSubstring: "Either email or phone",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "email config rejects phone-only body",
|
|
53
|
+
body: { phone: "+1555", password: "x" },
|
|
54
|
+
loginIdentifier: "email",
|
|
55
|
+
wantType: utils_1.MedusaError.Types.UNAUTHORIZED,
|
|
56
|
+
wantMessageSubstring: "Email login is not enabled",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "phone config rejects email-only body",
|
|
60
|
+
body: { email: "a@b.co", password: "x" },
|
|
61
|
+
loginIdentifier: "phone",
|
|
62
|
+
wantType: utils_1.MedusaError.Types.UNAUTHORIZED,
|
|
63
|
+
wantMessageSubstring: "Phone login is not enabled",
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
vitest_1.it.each(errorCases)("$name", ({ body, loginIdentifier, wantType, wantMessageSubstring }) => {
|
|
67
|
+
try {
|
|
68
|
+
(0, parse_login_body_1.parseCustomerLoginBody)(body, loginIdentifier);
|
|
69
|
+
vitest_1.expect.fail("expected MedusaError");
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
(0, vitest_1.expect)(e).toBeInstanceOf(utils_1.MedusaError);
|
|
73
|
+
const err = e;
|
|
74
|
+
(0, vitest_1.expect)(err.type).toBe(wantType);
|
|
75
|
+
(0, vitest_1.expect)(err.message).toContain(wantMessageSubstring);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2UtbG9naW4tYm9keS50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwaS9hdXRoL2N1c3RvbWVyL3NoYXJlZC9fX3Rlc3RzX18vcGFyc2UtbG9naW4tYm9keS50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbUNBQTZDO0FBQzdDLHFEQUF1RDtBQUN2RCwwREFHNEI7QUFFNUIsSUFBQSxpQkFBUSxFQUFDLHdCQUF3QixFQUFFLEdBQUcsRUFBRTtJQUN0QyxNQUFNLEtBQUssR0FLTjtRQUNIO1lBQ0UsSUFBSSxFQUFFLDBCQUEwQjtZQUNoQyxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUU7WUFDeEMsZUFBZSxFQUFFLE1BQU07WUFDdkIsSUFBSSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRTtTQUN4QjtRQUNEO1lBQ0UsSUFBSSxFQUFFLDBCQUEwQjtZQUNoQyxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUU7WUFDM0MsZUFBZSxFQUFFLE1BQU07WUFDdkIsSUFBSSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRTtTQUN4QjtRQUNEO1lBQ0UsSUFBSSxFQUFFLDZCQUE2QjtZQUNuQyxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUU7WUFDN0MsZUFBZSxFQUFFLE9BQU87WUFDeEIsSUFBSSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRTtTQUN4QjtRQUNEO1lBQ0UsSUFBSSxFQUFFLHNCQUFzQjtZQUM1QixJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUU7WUFDNUMsZUFBZSxFQUFFLE9BQU87WUFDeEIsSUFBSSxFQUFFLEVBQUUsSUFBSSxFQUFF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
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const parse_register_body_1 = require("../parse-register-body");
|
|
6
|
+
(0, vitest_1.describe)("parseCustomerRegisterBody", () => {
|
|
7
|
+
const okCases = [
|
|
8
|
+
{
|
|
9
|
+
name: "email config",
|
|
10
|
+
body: { email: "a@b.co", password: "x" },
|
|
11
|
+
registrationIdentifier: "email",
|
|
12
|
+
want: { mode: "email" },
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: "phone config",
|
|
16
|
+
body: { phone: "+15551", password: "x" },
|
|
17
|
+
registrationIdentifier: "phone",
|
|
18
|
+
want: { mode: "phone" },
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: "both config email only",
|
|
22
|
+
body: { email: "u@v.com", password: "Secret1!" },
|
|
23
|
+
registrationIdentifier: "both",
|
|
24
|
+
want: { mode: "email" },
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
vitest_1.it.each(okCases)("$name", ({ body, registrationIdentifier, want }) => {
|
|
28
|
+
(0, vitest_1.expect)((0, parse_register_body_1.parseCustomerRegisterBody)(body, registrationIdentifier)).toEqual(want);
|
|
29
|
+
});
|
|
30
|
+
const errCases = [
|
|
31
|
+
{
|
|
32
|
+
name: "missing password",
|
|
33
|
+
body: { email: "a@b.co" },
|
|
34
|
+
registrationIdentifier: "email",
|
|
35
|
+
wantType: utils_1.MedusaError.Types.INVALID_DATA,
|
|
36
|
+
wantSubstring: "Password is required",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "both rejects phone-only",
|
|
40
|
+
body: { phone: "+1", password: "x" },
|
|
41
|
+
registrationIdentifier: "both",
|
|
42
|
+
wantType: utils_1.MedusaError.Types.INVALID_DATA,
|
|
43
|
+
wantSubstring: "email and password is required first",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "both rejects email+phone",
|
|
47
|
+
body: { email: "a@b.co", phone: "+1", password: "x" },
|
|
48
|
+
registrationIdentifier: "both",
|
|
49
|
+
wantType: utils_1.MedusaError.Types.INVALID_DATA,
|
|
50
|
+
wantSubstring: "only email and password",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "email rejects phone-only",
|
|
54
|
+
body: { phone: "+1", password: "x" },
|
|
55
|
+
registrationIdentifier: "email",
|
|
56
|
+
wantType: utils_1.MedusaError.Types.INVALID_DATA,
|
|
57
|
+
wantSubstring: "Register with your email",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "phone rejects email-only",
|
|
61
|
+
body: { email: "a@b.co", password: "x" },
|
|
62
|
+
registrationIdentifier: "phone",
|
|
63
|
+
wantType: utils_1.MedusaError.Types.INVALID_DATA,
|
|
64
|
+
wantSubstring: "Register with your phone",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "email XOR violated",
|
|
68
|
+
body: { email: "a@b.co", phone: "+1", password: "x" },
|
|
69
|
+
registrationIdentifier: "email",
|
|
70
|
+
wantType: utils_1.MedusaError.Types.INVALID_DATA,
|
|
71
|
+
wantSubstring: "not both",
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
vitest_1.it.each(errCases)("$name", ({ body, registrationIdentifier, wantType, wantSubstring }) => {
|
|
75
|
+
try {
|
|
76
|
+
(0, parse_register_body_1.parseCustomerRegisterBody)(body, registrationIdentifier);
|
|
77
|
+
vitest_1.expect.fail("expected MedusaError");
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
(0, vitest_1.expect)(e).toBeInstanceOf(utils_1.MedusaError);
|
|
81
|
+
const err = e;
|
|
82
|
+
(0, vitest_1.expect)(err.type).toBe(wantType);
|
|
83
|
+
(0, vitest_1.expect)(err.message).toContain(wantSubstring);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2UtcmVnaXN0ZXItYm9keS50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwaS9hdXRoL2N1c3RvbWVyL3NoYXJlZC9fX3Rlc3RzX18vcGFyc2UtcmVnaXN0ZXItYm9keS50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsbUNBQTZDO0FBQzdDLHFEQUF1RDtBQUN2RCxnRUFHK0I7QUFFL0IsSUFBQSxpQkFBUSxFQUFDLDJCQUEyQixFQUFFLEdBQUcsRUFBRTtJQUN6QyxNQUFNLE9BQU8sR0FLUjtRQUNIO1lBQ0UsSUFBSSxFQUFFLGNBQWM7WUFDcEIsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFO1lBQ3hDLHNCQUFzQixFQUFFLE9BQU87WUFDL0IsSUFBSSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRTtTQUN4QjtRQUNEO1lBQ0UsSUFBSSxFQUFFLGNBQWM7WUFDcEIsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFO1lBQ3hDLHNCQUFzQixFQUFFLE9BQU87WUFDL0IsSUFBSSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRTtTQUN4QjtRQUNEO1lBQ0UsSUFBSSxFQUFFLHdCQUF3QjtZQUM5QixJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUU7WUFDaEQsc0JBQXNCLEVBQUUsTUFBTTtZQUM5QixJQUFJLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFO1NBQ3hCO0tBQ0YsQ0FBQTtJQUVELFdBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsc0JBQXNCLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRTtRQUNuRSxJQUFBLGVBQU0sRUFB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
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildUnifiedLoginAuthData = buildUnifiedLoginAuthData;
|
|
4
|
+
function firstQueryValue(value) {
|
|
5
|
+
if (typeof value === "string") {
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
if (Array.isArray(value) && typeof value[0] === "string") {
|
|
9
|
+
return value[0];
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Builds `AuthenticationInput` for customer login with credentials from the JSON body
|
|
15
|
+
* and, for missing fields, from query string (supports GET with `?email&password` or `?phone&password`).
|
|
16
|
+
* Body keys take precedence over query when both are present.
|
|
17
|
+
*/
|
|
18
|
+
function buildUnifiedLoginAuthData(req) {
|
|
19
|
+
const bodyRaw = req.body;
|
|
20
|
+
const body = bodyRaw !== null && typeof bodyRaw === "object" && !Array.isArray(bodyRaw)
|
|
21
|
+
? { ...bodyRaw }
|
|
22
|
+
: {};
|
|
23
|
+
const q = req.query !== null && typeof req.query === "object" && !Array.isArray(req.query)
|
|
24
|
+
? req.query
|
|
25
|
+
: {};
|
|
26
|
+
const merged = { ...body };
|
|
27
|
+
const qEmail = firstQueryValue(q.email);
|
|
28
|
+
const qPhone = firstQueryValue(q.phone);
|
|
29
|
+
const qPassword = firstQueryValue(q.password);
|
|
30
|
+
if (merged.email === undefined && qEmail !== undefined) {
|
|
31
|
+
merged.email = qEmail;
|
|
32
|
+
}
|
|
33
|
+
if (merged.phone === undefined && qPhone !== undefined) {
|
|
34
|
+
merged.phone = qPhone;
|
|
35
|
+
}
|
|
36
|
+
if (merged.password === undefined && qPassword !== undefined) {
|
|
37
|
+
merged.password = qPassword;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
url: req.url,
|
|
41
|
+
headers: req.headers,
|
|
42
|
+
query: req.query,
|
|
43
|
+
body: merged,
|
|
44
|
+
protocol: req.protocol,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQtdW5pZmllZC1sb2dpbi1hdXRoLWRhdGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvY3VzdG9tZXIvc2hhcmVkL2J1aWxkLXVuaWZpZWQtbG9naW4tYXV0aC1kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBa0JBLDhEQW1DQztBQWxERCxTQUFTLGVBQWUsQ0FBQyxLQUFjO0lBQ3JDLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDOUIsT0FBTyxLQUFLLENBQUE7SUFDZCxDQUFDO0lBQ0QsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ3pELE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ2pCLENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQTtBQUNsQixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQWdCLHlCQUF5QixDQUFDLEdBQWtCO0lBQzFELE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUE7SUFDeEIsTUFBTSxJQUFJLEdBQ1IsT0FBTyxLQUFLLElBQUksSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxDQUFDLENBQUMsRUFBRSxHQUFJLE9BQW1DLEVBQUU7UUFDN0MsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtJQUVSLE1BQU0sQ0FBQyxHQUNMLEdBQUcsQ0FBQyxLQUFLLEtBQUssSUFBSSxJQUFJLE9BQU8sR0FBRyxDQUFDLEtBQUssS0FBSyxRQUFRLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUM7UUFDOUUsQ0FBQyxDQUFFLEdBQUcsQ0FBQyxLQUFpQztRQUN4QyxDQUFDLENBQUMsRUFBRSxDQUFBO0lBRVIsTUFBTSxNQUFNLEdBQTRCLEVBQUUsR0FBRyxJQUFJLEVBQUUsQ0FBQTtJQUVuRCxNQUFNLE1BQU0sR0FBRyxlQUFlLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQ3ZDLE1BQU0sTUFBTSxHQUFHLGVBQWUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDdkMsTUFBTSxTQUFTLEdBQUcsZUFBZSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUU3QyxJQUFJLE1BQU0sQ0FBQyxLQUFLLEtBQUssU0FBUyxJQUFJLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUN2RCxNQUFNLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQTtJQUN2QixDQUFDO0lBQ0QsSUFBSSxNQUFNLENBQUMsS0FBSyxLQUFLLFNBQVMsSUFBSSxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDdkQsTUFBTSxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUE7SUFDdkIsQ0FBQztJQUNELElBQUksTUFBTSxDQUFDLFFBQVEsS0FBSyxTQUFTLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzdELE1BQU0sQ0FBQyxRQUFRLEdBQUcsU0FBUyxDQUFBO0lBQzdCLENBQUM7SUFFRCxPQUFPO1FBQ0wsR0FBRyxFQUFFLEdBQUcsQ0FBQyxHQUFHO1FBQ1osT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPO1FBQ3BCLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSztRQUNoQixJQUFJLEVBQUUsTUFBTTtRQUNaLFFBQVEsRUFBRSxHQUFHLENBQUMsUUFBUTtLQUNBLENBQUE7QUFDMUIsQ0FBQyJ9
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.completeCustomerLogin = completeCustomerLogin;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const generate_jwt_token_1 = require("@medusajs/medusa/api/auth/utils/generate-jwt-token");
|
|
6
|
+
const account_deletion_request_1 = require("../../../../modules/account-deletion-request");
|
|
7
|
+
/**
|
|
8
|
+
* Pending deletion check, merge customer_id into app_metadata, issue JWT, respond 200 `{ token }`.
|
|
9
|
+
*/
|
|
10
|
+
async function completeCustomerLogin(req, res, config, authIdentity, customerId, logContext) {
|
|
11
|
+
const accountDeletionService = req.scope.resolve(account_deletion_request_1.ACCOUNT_DELETION_REQUEST_MODULE);
|
|
12
|
+
if (await accountDeletionService.hasPendingRequest(customerId)) {
|
|
13
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Customer has an active account deletion request");
|
|
14
|
+
}
|
|
15
|
+
const authIdentityWithCustomerId = {
|
|
16
|
+
...authIdentity,
|
|
17
|
+
app_metadata: {
|
|
18
|
+
...authIdentity.app_metadata,
|
|
19
|
+
customer_id: customerId,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
const { http } = config.projectConfig ?? {};
|
|
23
|
+
if (!http?.jwtSecret) {
|
|
24
|
+
if (logContext.kind === "email") {
|
|
25
|
+
console.error("[customer-auth] JWT secret is not configured", {
|
|
26
|
+
email: logContext.email,
|
|
27
|
+
customerId,
|
|
28
|
+
hasJwtSecret: !!http?.jwtSecret,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
console.error("[customer-auth] JWT secret is not configured", {
|
|
33
|
+
phone: logContext.phone,
|
|
34
|
+
customerId,
|
|
35
|
+
hasJwtSecret: !!http?.jwtSecret,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "JWT secret is not configured");
|
|
39
|
+
}
|
|
40
|
+
let token;
|
|
41
|
+
try {
|
|
42
|
+
token = await (0, generate_jwt_token_1.generateJwtTokenForAuthIdentity)({
|
|
43
|
+
authIdentity: authIdentityWithCustomerId,
|
|
44
|
+
actorType: "customer",
|
|
45
|
+
}, {
|
|
46
|
+
secret: http.jwtSecret,
|
|
47
|
+
expiresIn: http.jwtExpiresIn || "7d",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch (jwtError) {
|
|
51
|
+
if (logContext.kind === "email") {
|
|
52
|
+
console.error("[customer-auth] JWT generation threw an exception", {
|
|
53
|
+
email: logContext.email,
|
|
54
|
+
customerId,
|
|
55
|
+
error: jwtError instanceof Error ? jwtError.message : String(jwtError),
|
|
56
|
+
stack: jwtError instanceof Error ? jwtError.stack : undefined,
|
|
57
|
+
jwtSecretExists: !!http.jwtSecret,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
console.error("[customer-auth] JWT generation threw an exception", {
|
|
62
|
+
phone: logContext.phone,
|
|
63
|
+
customerId,
|
|
64
|
+
error: jwtError instanceof Error ? jwtError.message : String(jwtError),
|
|
65
|
+
stack: jwtError instanceof Error ? jwtError.stack : undefined,
|
|
66
|
+
jwtSecretExists: !!http.jwtSecret,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `JWT generation failed: ${jwtError instanceof Error ? jwtError.message : "Unknown error"}`);
|
|
70
|
+
}
|
|
71
|
+
if (!token || typeof token !== "string") {
|
|
72
|
+
if (logContext.kind === "email") {
|
|
73
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to generate authentication token for customer ${customerId}. Token type: ${typeof token}, Token value: ${token}`);
|
|
74
|
+
}
|
|
75
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Failed to generate authentication token");
|
|
76
|
+
}
|
|
77
|
+
res.status(200).json({ token });
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcGxldGUtY3VzdG9tZXItbG9naW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvY3VzdG9tZXIvc2hhcmVkL2NvbXBsZXRlLWN1c3RvbWVyLWxvZ2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBcUJBLHNEQW1HQztBQXRIRCxxREFBdUQ7QUFDdkQsMkZBQW9HO0FBQ3BHLDJGQUE4RjtBQWM5Rjs7R0FFRztBQUNJLEtBQUssVUFBVSxxQkFBcUIsQ0FDekMsR0FBa0IsRUFDbEIsR0FBbUIsRUFDbkIsTUFBMEIsRUFDMUIsWUFBK0IsRUFDL0IsVUFBa0IsRUFDbEIsVUFBK0U7SUFFL0UsTUFBTSxzQkFBc0IsR0FDMUIsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQ2YsMERBQStCLENBQ2hDLENBQUE7SUFDSCxJQUFJLE1BQU0sc0JBQXNCLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUMvRCxNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5QixpREFBaUQsQ0FDbEQsQ0FBQTtJQUNILENBQUM7SUFFRCxNQUFNLDBCQUEwQixHQUFHO1FBQ2pDLEdBQUcsWUFBWTtRQUNmLFlBQVksRUFBRTtZQUNaLEdBQUcsWUFBWSxDQUFDLFlBQVk7WUFDNUIsV0FBVyxFQUFFLFVBQVU7U0FDeEI7S0FDRixDQUFBO0lBRUQsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLE1BQU0sQ0FBQyxhQUFhLElBQUksRUFBRSxDQUFBO0lBRTNDLElBQUksQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUM7UUFDckIsSUFBSSxVQUFVLENBQUMsSUFBSSxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQ2hDLE9BQU8sQ0FBQyxLQUFLLENBQUMsOENBQThDLEVBQUU7Z0JBQzVELEtBQUssRUFBRSxVQUFVLENBQUMsS0FBSztnQkFDdkIsVUFB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
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.respondWithRegistrationToken = respondWithRegistrationToken;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const generate_jwt_token_1 = require("@medusajs/medusa/api/auth/utils/generate-jwt-token");
|
|
6
|
+
/**
|
|
7
|
+
* After a successful `authModuleService.register(...)`, issues the standard
|
|
8
|
+
* Medusa registration JWT and responds with `{ token }`.
|
|
9
|
+
*/
|
|
10
|
+
async function respondWithRegistrationToken(req, res, authIdentity) {
|
|
11
|
+
const config = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
|
|
12
|
+
const { http } = config.projectConfig ?? {};
|
|
13
|
+
if (!http?.jwtSecret) {
|
|
14
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "JWT secret is not configured");
|
|
15
|
+
}
|
|
16
|
+
let token;
|
|
17
|
+
try {
|
|
18
|
+
token = await (0, generate_jwt_token_1.generateJwtTokenForAuthIdentity)({
|
|
19
|
+
authIdentity: authIdentity,
|
|
20
|
+
actorType: "customer",
|
|
21
|
+
}, {
|
|
22
|
+
secret: http.jwtSecret,
|
|
23
|
+
expiresIn: http.jwtExpiresIn || "7d",
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch (jwtError) {
|
|
27
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `JWT generation failed: ${jwtError instanceof Error ? jwtError.message : "Unknown error"}`);
|
|
28
|
+
}
|
|
29
|
+
if (!token || typeof token !== "string") {
|
|
30
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Failed to generate registration token");
|
|
31
|
+
}
|
|
32
|
+
res.status(200).json({ token });
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcGxldGUtcmVnaXN0cmF0aW9uLXRva2VuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwaS9hdXRoL2N1c3RvbWVyL3NoYXJlZC9jb21wbGV0ZS1yZWdpc3RyYXRpb24tdG9rZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFjQSxvRUE2Q0M7QUF6REQscURBR2tDO0FBQ2xDLDJGQUFvRztBQUlwRzs7O0dBR0c7QUFDSSxLQUFLLFVBQVUsNEJBQTRCLENBQ2hELEdBQWtCLEVBQ2xCLEdBQW1CLEVBQ25CLFlBQXFDO0lBRXJDLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLGFBQWEsQ0FFcEQsQ0FBQTtJQUVwQixNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsTUFBTSxDQUFDLGFBQWEsSUFBSSxFQUFFLENBQUE7SUFFM0MsSUFBSSxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUUsQ0FBQztRQUNyQixNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5Qiw4QkFBOEIsQ0FDL0IsQ0FBQTtJQUNILENBQUM7SUFFRCxJQUFJLEtBQXlCLENBQUE7SUFDN0IsSUFBSSxDQUFDO1FBQ0gsS0FBSyxHQUFHLE1BQU0sSUFBQSxvREFBK0IsRUFDM0M7WUFDRSxZQUFZLEVBQUUsWUFBMEM7WUFDeEQsU0FBUyxFQUFFLFVBQVU7U0FDdEIsRUFDRDtZQUNFLE1BQU0sRUFBRSxJQUFJLENBQUMsU0FBUztZQUN0QixTQUFTLEVBQUUsSUFBSSxDQUFDLFlBQVksSUFBSSxJQUFJO1NBQ3JDLENBQ0YsQ0FBQTtJQUNILENBQUM7SUFBQyxPQUFPLFFBQVEsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFDbEMsMEJBQTBCLFFBQVEsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLGVBQWUsRUFBRSxDQUMzRixDQUFBO0lBQ0gsQ0FBQztJQUVELElBQUksQ0FBQyxLQUFLLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDeEMsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUNsQyx1Q0FBdUMsQ0FDeEMsQ0FBQTtJQUNILENBQUM7SUFFRCxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUE7QUFDakMsQ0FBQyJ9
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runEmailPassAuthFlow = runEmailPassAuthFlow;
|
|
4
|
+
exports.runPhonePassAuthFlow = runPhonePassAuthFlow;
|
|
5
|
+
exports.handleCustomerLogin = handleCustomerLogin;
|
|
6
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
7
|
+
const config_1 = require("../../../../config");
|
|
8
|
+
const complete_customer_login_1 = require("./complete-customer-login");
|
|
9
|
+
const enforce_registration_verification_1 = require("./enforce-registration-verification");
|
|
10
|
+
const build_unified_login_auth_data_1 = require("./build-unified-login-auth-data");
|
|
11
|
+
const parse_login_body_1 = require("./parse-login-body");
|
|
12
|
+
function firstKnexRow(result) {
|
|
13
|
+
const fromRows = result.rows?.[0];
|
|
14
|
+
if (fromRows && typeof fromRows === "object" && !Array.isArray(fromRows)) {
|
|
15
|
+
return fromRows;
|
|
16
|
+
}
|
|
17
|
+
const batch = result[0];
|
|
18
|
+
if (Array.isArray(batch)) {
|
|
19
|
+
const first = batch[0];
|
|
20
|
+
if (first && typeof first === "object" && !Array.isArray(first)) {
|
|
21
|
+
return first;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Email-only login (used when unified parse selects email).
|
|
28
|
+
*/
|
|
29
|
+
async function runEmailPassAuthFlow(req, res, config, authData) {
|
|
30
|
+
const service = req.scope.resolve(utils_1.Modules.AUTH);
|
|
31
|
+
const { success, error, authIdentity, location } = await service.authenticate("emailpass", authData);
|
|
32
|
+
if (location) {
|
|
33
|
+
res.status(200).json({ location });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (success && authIdentity) {
|
|
37
|
+
const email = authIdentity.provider_identities?.[0]
|
|
38
|
+
?.entity_id ?? "";
|
|
39
|
+
const appMeta = authIdentity.app_metadata;
|
|
40
|
+
let customerId = typeof appMeta?.customer_id === "string" ? appMeta.customer_id : undefined;
|
|
41
|
+
if (!customerId) {
|
|
42
|
+
const customerModule = req.scope.resolve(utils_1.Modules.CUSTOMER);
|
|
43
|
+
const customers = await customerModule.listCustomers({
|
|
44
|
+
email: email.toLowerCase(),
|
|
45
|
+
});
|
|
46
|
+
if (customers && customers.length > 0) {
|
|
47
|
+
customerId = customers[0].id;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const resolvedCustomerId = typeof customerId === "string" && customerId.trim().length > 0
|
|
51
|
+
? customerId
|
|
52
|
+
: undefined;
|
|
53
|
+
if (!resolvedCustomerId) {
|
|
54
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Unable to determine customer ID for authentication");
|
|
55
|
+
}
|
|
56
|
+
await (0, enforce_registration_verification_1.enforceRegistrationVerification)({
|
|
57
|
+
customerId: resolvedCustomerId,
|
|
58
|
+
req,
|
|
59
|
+
logLabel: email,
|
|
60
|
+
loginChannel: "email",
|
|
61
|
+
});
|
|
62
|
+
await (0, complete_customer_login_1.completeCustomerLogin)(req, res, config, authIdentity, resolvedCustomerId, {
|
|
63
|
+
kind: "email",
|
|
64
|
+
email,
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
console.error("[customer-auth] Email authentication failed", {
|
|
69
|
+
success,
|
|
70
|
+
error,
|
|
71
|
+
hasAuthIdentity: !!authIdentity,
|
|
72
|
+
});
|
|
73
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, error || "Authentication failed");
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Phone-only login (phonepass provider).
|
|
77
|
+
*/
|
|
78
|
+
async function runPhonePassAuthFlow(req, res, config, authData) {
|
|
79
|
+
const service = req.scope.resolve(utils_1.Modules.AUTH);
|
|
80
|
+
const { success, error, authIdentity } = await service.authenticate("phonepass", authData);
|
|
81
|
+
if (!success || !authIdentity) {
|
|
82
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, error || "Authentication failed");
|
|
83
|
+
}
|
|
84
|
+
const phone = authIdentity.provider_identities?.[0]
|
|
85
|
+
?.entity_id ?? "";
|
|
86
|
+
const appMetaPhone = authIdentity.app_metadata;
|
|
87
|
+
let customerId = typeof appMetaPhone?.customer_id === "string"
|
|
88
|
+
? appMetaPhone.customer_id
|
|
89
|
+
: undefined;
|
|
90
|
+
if (!customerId) {
|
|
91
|
+
const knex = req.scope.resolve(utils_1.ContainerRegistrationKeys.PG_CONNECTION);
|
|
92
|
+
if (knex) {
|
|
93
|
+
const result = await knex.raw(`SELECT id FROM customer WHERE phone = ? LIMIT 1`, [phone]);
|
|
94
|
+
const row = firstKnexRow(result);
|
|
95
|
+
if (row?.id) {
|
|
96
|
+
customerId = row.id;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!customerId) {
|
|
101
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Unable to determine customer ID for authentication");
|
|
102
|
+
}
|
|
103
|
+
let logLabel = phone;
|
|
104
|
+
const knexEmail = req.scope.resolve(utils_1.ContainerRegistrationKeys.PG_CONNECTION);
|
|
105
|
+
if (knexEmail) {
|
|
106
|
+
const rowResult = await knexEmail.raw(`SELECT email FROM customer WHERE id = ? LIMIT 1`, [customerId]);
|
|
107
|
+
const row = firstKnexRow(rowResult);
|
|
108
|
+
const e = row?.email;
|
|
109
|
+
if (typeof e === "string" && e.trim()) {
|
|
110
|
+
logLabel = e.trim();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
await (0, enforce_registration_verification_1.enforceRegistrationVerification)({
|
|
114
|
+
customerId,
|
|
115
|
+
req,
|
|
116
|
+
logLabel,
|
|
117
|
+
loginChannel: "phone",
|
|
118
|
+
});
|
|
119
|
+
await (0, complete_customer_login_1.completeCustomerLogin)(req, res, config, authIdentity, customerId, {
|
|
120
|
+
kind: "phone",
|
|
121
|
+
phone,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Unified customer login: POST (JSON body) or GET (query `email`|`phone` + `password`).
|
|
126
|
+
* Credentials are merged with body taking precedence over query (see `buildUnifiedLoginAuthData`).
|
|
127
|
+
*/
|
|
128
|
+
async function handleCustomerLogin(req, res) {
|
|
129
|
+
const config = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
|
|
130
|
+
const loginOptions = (0, config_1.resolveCustomerRegistrationOptions)(config);
|
|
131
|
+
const loginIdentifier = loginOptions.login.identifier;
|
|
132
|
+
const authData = (0, build_unified_login_auth_data_1.buildUnifiedLoginAuthData)(req);
|
|
133
|
+
const parseSource = authData.body !== null && typeof authData.body === "object" && !Array.isArray(authData.body)
|
|
134
|
+
? authData.body
|
|
135
|
+
: {};
|
|
136
|
+
const parsed = (0, parse_login_body_1.parseCustomerLoginBody)(parseSource, loginIdentifier);
|
|
137
|
+
if (parsed.mode === "email") {
|
|
138
|
+
return runEmailPassAuthFlow(req, res, config, authData);
|
|
139
|
+
}
|
|
140
|
+
return runPhonePassAuthFlow(req, res, config, authData);
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VzdG9tZXItbG9naW4tcG9zdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcGkvYXV0aC9jdXN0b21lci9zaGFyZWQvY3VzdG9tZXItbG9naW4tcG9zdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQWlEQSxvREE0RUM7QUFLRCxvREF3RkM7QUFNRCxrREF3QkM7QUF0UEQscURBSWtDO0FBRWxDLCtDQUF1RTtBQUN2RSx1RUFBMEY7QUFDMUYsMkZBQXFGO0FBQ3JGLG1GQUEyRTtBQUMzRSx5REFHMkI7QUFFM0IsU0FBUyxZQUFZLENBQ25CLE1BQW1DO0lBRW5DLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUNqQyxJQUFJLFFBQVEsSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDekUsT0FBTyxRQUFRLENBQUE7SUFDakIsQ0FBQztJQUNELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUN2QixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN6QixNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDdEIsSUFBSSxLQUFLLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ2hFLE9BQU8sS0FBVSxDQUFBO1FBQ25CLENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxTQUFTLENBQUE7QUFDbEIsQ0FBQztBQWNEOztHQUVHO0FBQ0ksS0FBSyxVQUFVLG9CQUFvQixDQUN4QyxHQUFrQixFQUNsQixHQUFtQixFQUNuQixNQUE4QyxFQUM5QyxRQUE2QjtJQUU3QixNQUFNLE9B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
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.enforceRegistrationVerification = enforceRegistrationVerification;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const otp_verification_1 = require("../../../../modules/otp-verification");
|
|
6
|
+
const config_1 = require("../../../../config");
|
|
7
|
+
/**
|
|
8
|
+
* Enforces OTP verification for login according to `registration.identifier` and `require_verification`.
|
|
9
|
+
*
|
|
10
|
+
* - `email` / `phone`: only that channel must be verified.
|
|
11
|
+
* - `both`: only the channel used to log in must be verified (`loginChannel`).
|
|
12
|
+
*
|
|
13
|
+
* When phone is enforced but unverified, includes `pending_phone` UX for pending number changes.
|
|
14
|
+
*/
|
|
15
|
+
async function enforceRegistrationVerification({ customerId, req, logLabel, loginChannel, }) {
|
|
16
|
+
const configModule = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
|
|
17
|
+
const options = (0, config_1.resolveCustomerRegistrationOptions)(configModule);
|
|
18
|
+
const { identifier, require_verification } = options.registration;
|
|
19
|
+
if (!require_verification) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const otpService = req.scope.resolve(otp_verification_1.OTP_VERIFICATION_MODULE);
|
|
23
|
+
const verificationStatus = await otpService.getCustomerVerificationByCustomerId(req.scope, customerId);
|
|
24
|
+
const enforceEmail = identifier === "email" ||
|
|
25
|
+
(identifier === "both" && loginChannel === "email");
|
|
26
|
+
const enforcePhone = identifier === "phone" ||
|
|
27
|
+
(identifier === "both" && loginChannel === "phone");
|
|
28
|
+
if (enforceEmail && !verificationStatus.email_verified) {
|
|
29
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Email not verified.");
|
|
30
|
+
}
|
|
31
|
+
if (enforcePhone && !verificationStatus.phone_verified) {
|
|
32
|
+
const knex = req.scope.resolve(utils_1.ContainerRegistrationKeys.PG_CONNECTION);
|
|
33
|
+
const row = await knex.raw(`SELECT metadata->>'pending_phone' AS pending_phone FROM customer WHERE id = ? LIMIT 1`, [customerId]);
|
|
34
|
+
const pendingPhone = (row.rows?.[0] ?? row[0]?.[0])?.pending_phone ?? null;
|
|
35
|
+
console.error("[customer-auth] Phone not verified", {
|
|
36
|
+
logLabel,
|
|
37
|
+
customerId,
|
|
38
|
+
});
|
|
39
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, pendingPhone
|
|
40
|
+
? "Your new phone number is pending verification. Please verify it to continue."
|
|
41
|
+
: "Phone not verified.");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW5mb3JjZS1yZWdpc3RyYXRpb24tdmVyaWZpY2F0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwaS9hdXRoL2N1c3RvbWVyL3NoYXJlZC9lbmZvcmNlLXJlZ2lzdHJhdGlvbi12ZXJpZmljYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFzQkEsMEVBb0VDO0FBekZELHFEQUdrQztBQUdsQywyRUFBOEU7QUFFOUUsK0NBRzJCO0FBRTNCOzs7Ozs7O0dBT0c7QUFDSSxLQUFLLFVBQVUsK0JBQStCLENBQUMsRUFDcEQsVUFBVSxFQUNWLEdBQUcsRUFDSCxRQUFRLEVBQ1IsWUFBWSxHQVFiO0lBQ0MsTUFBTSxZQUFZLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQ3BDLGlDQUF5QixDQUFDLGFBQWEsQ0FDeEMsQ0FBQTtJQUNELE1BQU0sT0FBTyxHQUFHLElBQUEsMkNBQWtDLEVBQUMsWUFBWSxDQUFDLENBQUE7SUFDaEUsTUFBTSxFQUFFLFVBQVUsRUFBRSxvQkFBb0IsRUFBRSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUE7SUFFakUsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDMUIsT0FBTTtJQUNSLENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FDbEMsMENBQXVCLENBQ3hCLENBQUE7SUFFRCxNQUFNLGtCQUFrQixHQUFHLE1BQU0sVUFBVSxDQUFDLG1DQUFtQyxDQUM3RSxHQUFHLENBQUMsS0FBK0IsRUFDbkMsVUFBVSxDQUNYLENBQUE7SUFFRCxNQUFNLFlBQVksR0FDaEIsVUFBVSxLQUFLLE9BQU87UUFDdEIsQ0FBQyxVQUFVLEtBQUssTUFBTSxJQUFJLFlBQVksS0FBSyxPQUFPLENBQUMsQ0FBQTtJQUVyRCxNQUFNLFlBQVksR0FDaEIsVUFBVSxLQUFLLE9BQU87UUFDdEIsQ0FBQyxVQUFVLEtBQUssTUFBTSxJQUFJLFlBQVksS0FBSyxPQUFPLENBQUMsQ0FBQTtJQUVyRCxJQUFJLFlBQVksSUFBSSxDQUFDLGtCQUFrQixDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZELE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLHFCQUFxQixDQUN0QixDQUFBO0lBQ0gsQ0FBQztJQUVELElBQUksWUFBWSxJQUFJLENBQUMsa0JBQWtCLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdkQsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsYUFBYSxDQUFDLENBQUE7UUFDdkUsTUFBTSxHQUFHLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUN4Qix1RkFBdUYsRUFDdkYsQ0FBQyxVQUFVLENBQUMsQ0FDYixDQUFBO1FBQ0QsTUFBTSxZQUFZLEdBQ2hCLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsYUFBYSxJQUFJLElBQUksQ0FBQTtRQUV2RCxPQUFPLENBQUMsS0FBSyxDQUFDLG9DQUFvQyxFQUFFO1lBQ2xELFFBQVE7WUFDUixVQUFVO1NBQ1gsQ0FBQyxDQUFBO1FBRUYsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsWUFBWTtZQUNWLENBQUMsQ0FBQyw4RUFBOEU7WUFDaEYsQ0FBQyxDQUFDLHFCQUFxQixDQUMxQixDQUFBO0lBQ0gsQ0FBQztBQUNILENBQUMifQ==
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseCustomerLoginBody = parseCustomerLoginBody;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
function nonEmptyString(value) {
|
|
6
|
+
if (typeof value !== "string") {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
const t = value.trim();
|
|
10
|
+
return t.length > 0 ? t : undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Determines email vs phone login from the request body and enforces `login.identifier` from plugin config.
|
|
14
|
+
* Requires exactly one identifier: XOR on non-empty `email` / `phone` (plus `password` for auth).
|
|
15
|
+
*/
|
|
16
|
+
function parseCustomerLoginBody(body, loginIdentifier) {
|
|
17
|
+
const record = body !== null && typeof body === "object"
|
|
18
|
+
? body
|
|
19
|
+
: {};
|
|
20
|
+
const email = nonEmptyString(record.email);
|
|
21
|
+
const phone = nonEmptyString(record.phone);
|
|
22
|
+
if (email && phone) {
|
|
23
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Provide either email or phone, not both.");
|
|
24
|
+
}
|
|
25
|
+
if (!email && !phone) {
|
|
26
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Either email or phone is required.");
|
|
27
|
+
}
|
|
28
|
+
if (loginIdentifier === "email") {
|
|
29
|
+
if (phone && !email) {
|
|
30
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Email login is not enabled. Please log in with your email.");
|
|
31
|
+
}
|
|
32
|
+
return { mode: "email" };
|
|
33
|
+
}
|
|
34
|
+
if (loginIdentifier === "phone") {
|
|
35
|
+
if (email && !phone) {
|
|
36
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Phone login is not enabled. Please log in with your phone number.");
|
|
37
|
+
}
|
|
38
|
+
return { mode: "phone" };
|
|
39
|
+
}
|
|
40
|
+
return email ? { mode: "email" } : { mode: "phone" };
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2UtbG9naW4tYm9keS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcGkvYXV0aC9jdXN0b21lci9zaGFyZWQvcGFyc2UtbG9naW4tYm9keS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQW9CQSx3REErQ0M7QUFuRUQscURBQXVEO0FBUXZELFNBQVMsY0FBYyxDQUFDLEtBQWM7SUFDcEMsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUM5QixPQUFPLFNBQVMsQ0FBQTtJQUNsQixDQUFDO0lBQ0QsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFBO0lBQ3RCLE9BQU8sQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFBO0FBQ3JDLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFnQixzQkFBc0IsQ0FDcEMsSUFBYSxFQUNiLGVBQXNDO0lBRXRDLE1BQU0sTUFBTSxHQUNWLElBQUksS0FBSyxJQUFJLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUTtRQUN2QyxDQUFDLENBQUUsSUFBZ0M7UUFDbkMsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtJQUVSLE1BQU0sS0FBSyxHQUFHLGNBQWMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDMUMsTUFBTSxLQUFLLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUUxQyxJQUFJLEtBQUssSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUNuQixNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5QiwwQ0FBMEMsQ0FDM0MsQ0FBQTtJQUNILENBQUM7SUFFRCxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDckIsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsb0NBQW9DLENBQ3JDLENBQUE7SUFDSCxDQUFDO0lBRUQsSUFBSSxlQUFlLEtBQUssT0FBTyxFQUFFLENBQUM7UUFDaEMsSUFBSSxLQUFLLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNwQixNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5Qiw0REFBNEQsQ0FDN0QsQ0FBQTtRQUNILENBQUM7UUFDRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxDQUFBO0lBQzFCLENBQUM7SUFFRCxJQUFJLGVBQWUsS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUNoQyxJQUFJLEtBQUssSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3BCLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLG1FQUFtRSxDQUNwRSxDQUFBO1FBQ0gsQ0FBQztRQUNELE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUE7SUFDMUIsQ0FBQztJQUVELE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUE7QUFDdEQsQ0FBQyJ9
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseCustomerRegisterBody = parseCustomerRegisterBody;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
function nonEmptyString(value) {
|
|
6
|
+
if (typeof value !== "string") {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
const t = value.trim();
|
|
10
|
+
return t.length > 0 ? t : undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Chooses email vs phone registration from the JSON body and enforces `registration.identifier`.
|
|
14
|
+
* Requires `password` (non-empty string). For `"both"`, only `email` + `password` is allowed (no phone-only; no extra phone field).
|
|
15
|
+
*/
|
|
16
|
+
function parseCustomerRegisterBody(body, registrationIdentifier) {
|
|
17
|
+
const record = body !== null && typeof body === "object"
|
|
18
|
+
? body
|
|
19
|
+
: {};
|
|
20
|
+
const password = nonEmptyString(record.password);
|
|
21
|
+
if (!password) {
|
|
22
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Password is required.");
|
|
23
|
+
}
|
|
24
|
+
const email = nonEmptyString(record.email);
|
|
25
|
+
const phone = nonEmptyString(record.phone);
|
|
26
|
+
if (registrationIdentifier === "both") {
|
|
27
|
+
if (phone && !email) {
|
|
28
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Registration with email and password is required first. Use email and password only on this step.");
|
|
29
|
+
}
|
|
30
|
+
if (!email) {
|
|
31
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Email and password are required.");
|
|
32
|
+
}
|
|
33
|
+
if (phone) {
|
|
34
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Provide only email and password. Add your phone when creating the customer.");
|
|
35
|
+
}
|
|
36
|
+
return { mode: "email" };
|
|
37
|
+
}
|
|
38
|
+
if (email && phone) {
|
|
39
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Provide either email or phone, not both.");
|
|
40
|
+
}
|
|
41
|
+
if (!email && !phone) {
|
|
42
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Either email or phone is required.");
|
|
43
|
+
}
|
|
44
|
+
if (registrationIdentifier === "email") {
|
|
45
|
+
if (phone && !email) {
|
|
46
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Phone registration is not enabled for this store. Register with your email.");
|
|
47
|
+
}
|
|
48
|
+
return { mode: "email" };
|
|
49
|
+
}
|
|
50
|
+
if (registrationIdentifier === "phone") {
|
|
51
|
+
if (email && !phone) {
|
|
52
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Email registration is not enabled for this store. Register with your phone number.");
|
|
53
|
+
}
|
|
54
|
+
return { mode: "phone" };
|
|
55
|
+
}
|
|
56
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Invalid registration configuration.");
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2UtcmVnaXN0ZXItYm9keS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcGkvYXV0aC9jdXN0b21lci9zaGFyZWQvcGFyc2UtcmVnaXN0ZXItYm9keS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQW9CQSw4REFnRkM7QUFwR0QscURBQXVEO0FBUXZELFNBQVMsY0FBYyxDQUFDLEtBQWM7SUFDcEMsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUM5QixPQUFPLFNBQVMsQ0FBQTtJQUNsQixDQUFDO0lBQ0QsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFBO0lBQ3RCLE9BQU8sQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFBO0FBQ3JDLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFnQix5QkFBeUIsQ0FDdkMsSUFBYSxFQUNiLHNCQUFvRDtJQUVwRCxNQUFNLE1BQU0sR0FDVixJQUFJLEtBQUssSUFBSSxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVE7UUFDdkMsQ0FBQyxDQUFFLElBQWdDO1FBQ25DLENBQUMsQ0FBQyxFQUFFLENBQUE7SUFFUixNQUFNLFFBQVEsR0FBRyxjQUFjLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQ2hELElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNkLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLHVCQUF1QixDQUN4QixDQUFBO0lBQ0gsQ0FBQztJQUVELE1BQU0sS0FBSyxHQUFHLGNBQWMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDMUMsTUFBTSxLQUFLLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUUxQyxJQUFJLHNCQUFzQixLQUFLLE1BQU0sRUFBRSxDQUFDO1FBQ3RDLElBQUksS0FBSyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDcEIsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsbUdBQW1HLENBQ3BHLENBQUE7UUFDSCxDQUFDO1FBQ0QsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsa0NBQWtDLENBQ25DLENBQUE7UUFDSCxDQUFDO1FBQ0QsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUNWLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLDZFQUE2RSxDQUM5RSxDQUFBO1FBQ0gsQ0FBQztRQUNELE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUE7SUFDMUIsQ0FBQztJQUVELElBQUksS0FBSyxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ25CLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLDBDQUEwQyxDQUMzQyxDQUFBO0lBQ0gsQ0FBQztJQUVELElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNyQixNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5QixvQ0FBb0MsQ0FDckMsQ0FBQTtJQUNILENBQUM7SUFFRCxJQUFJLHNCQUFzQixLQUFLLE9BQU8sRUFBRSxDQUFDO1FBQ3ZDLElBQUksS0FBSyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDcEIsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsNkVBQTZFLENBQzlFLENBQUE7UUFDSCxDQUFDO1FBQ0QsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQTtJQUMxQixDQUFDO0lBRUQsSUFBSSxzQkFBc0IsS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUN2QyxJQUFJLEtBQUssSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3BCLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLG9GQUFvRixDQUNyRixDQUFBO1FBQ0gsQ0FBQztRQUNELE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUE7SUFDMUIsQ0FBQztJQUVELE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLHFDQUFxQyxDQUN0QyxDQUFBO0FBQ0gsQ0FBQyJ9
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { defineConfig } from "vitest/config";
|
|
2
|
+
export default defineConfig({
|
|
3
|
+
test: {
|
|
4
|
+
include: ["src/**/*.test.ts"],
|
|
5
|
+
exclude: ["node_modules", ".medusa/**", ".medusa/server/**"],
|
|
6
|
+
},
|
|
7
|
+
});
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidml0ZXN0LmNvbmZpZy5tanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi92aXRlc3QuY29uZmlnLm10cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBRTVDLGVBQWUsWUFBWSxDQUFDO0lBQzFCLElBQUksRUFBRTtRQUNKLE9BQU8sRUFBRSxDQUFDLGtCQUFrQixDQUFDO1FBQzdCLE9BQU8sRUFBRSxDQUFDLGNBQWMsRUFBRSxZQUFZLEVBQUUsbUJBQW1CLENBQUM7S0FDN0Q7Q0FDRixDQUFDLENBQUEifQ==
|
package/README.md
CHANGED
|
@@ -13,7 +13,8 @@ A comprehensive Medusa v2 plugin that provides OTP-based verification for email
|
|
|
13
13
|
- **Throttling & Rate Limiting**: Built-in protection against OTP spam
|
|
14
14
|
- **Database Migrations**: Automatic schema updates for verification columns
|
|
15
15
|
- **Account Deletion Request Flow**: Two-step OTP flow to request and confirm account deletion with optional cancel flow
|
|
16
|
-
- **
|
|
16
|
+
- **Unified registration & login**: **`POST /auth/customer/emailpass/register`** creates an **emailpass** or **phonepass** identity (from JSON body + `registration.identifier`); **`POST /auth/customer/emailpass`** logs in with `{ email, password }` or `{ phone, password }` per `login.identifier`
|
|
17
|
+
- **Per-channel OTP at login**: When `registration.identifier` is **`"both"`** and `require_verification` is on, **email login** only requires **email** verified; **phone login** only requires **phone** verified — you can use either method after completing that channel’s OTP
|
|
17
18
|
- **Authenticated Contact Change**: Dedicated OTP-verified routes for updating phone or email — new value is embedded in the signed JWT, no metadata staging required
|
|
18
19
|
|
|
19
20
|
## Quick Start
|
|
@@ -77,8 +78,6 @@ npx medusa db:migrate
|
|
|
77
78
|
|
|
78
79
|
4. **Use the API** — see [API Endpoints](#api-endpoints) below.
|
|
79
80
|
|
|
80
|
-
📖 **For complete documentation, see [USAGE.md](./USAGE.md)**
|
|
81
|
-
|
|
82
81
|
---
|
|
83
82
|
|
|
84
83
|
## Installation
|
|
@@ -131,9 +130,25 @@ Controls which auth providers are accepted at login. Defaults to `registration.i
|
|
|
131
130
|
|
|
132
131
|
| Value | Accepted login methods |
|
|
133
132
|
|---|---|
|
|
134
|
-
| `"email"` | `POST /auth/customer/emailpass` only |
|
|
135
|
-
| `"phone"` | `
|
|
136
|
-
| `"both"` |
|
|
133
|
+
| `"email"` | `POST /auth/customer/emailpass` with `{ "email", "password" }` only |
|
|
134
|
+
| `"phone"` | Same endpoint with `{ "phone", "password" }` only |
|
|
135
|
+
| `"both"` | Same endpoint; **either** email **or** phone (not both) plus `password` in the JSON body |
|
|
136
|
+
|
|
137
|
+
Login always uses **`POST /auth/customer/emailpass`** (single URL). There is **no** `/auth/customer/phonepass` route; phone registration uses the same **`POST /auth/customer/emailpass/register`** as email registration.
|
|
138
|
+
|
|
139
|
+
Credentials are normally sent in the **JSON body**; the same keys can be supplied on the **query string** for missing fields (see `buildUnifiedLoginAuthData`) — prefer **body** for passwords.
|
|
140
|
+
|
|
141
|
+
### `require_verification` and login
|
|
142
|
+
|
|
143
|
+
When **`registration.require_verification`** is **`true`** (default), login checks OTP flags **for the credential you use** (see [`enforce-registration-verification.ts`](src/api/auth/customer/shared/enforce-registration-verification.ts)):
|
|
144
|
+
|
|
145
|
+
- **`registration.identifier: "email"`** — signing in with **email** requires **`email_verified`**.
|
|
146
|
+
- **`registration.identifier: "phone"`** — signing in with **phone** requires **`phone_verified`**.
|
|
147
|
+
- **`registration.identifier: "both"`** — signing in with **email** requires **`email_verified`** only (phone may still be unverified). Signing in with **phone** requires **`phone_verified`** only (email may still be unverified).
|
|
148
|
+
|
|
149
|
+
So with **`both`**, a customer can **log in with email** after email OTP even if **phone** OTP is still pending, and the reverse for phone login.
|
|
150
|
+
|
|
151
|
+
When **`require_verification`** is **`false`**, these checks are skipped.
|
|
137
152
|
|
|
138
153
|
### Full options reference
|
|
139
154
|
|
|
@@ -223,14 +238,16 @@ POST /store/customers/otp/verify
|
|
|
223
238
|
|
|
224
239
|
---
|
|
225
240
|
|
|
226
|
-
### Login
|
|
241
|
+
### Login & registration (customer auth)
|
|
242
|
+
|
|
243
|
+
Implementation lives under [`src/api/auth/customer/`](src/api/auth/customer/): **`emailpass/`** (login, **register**, password reset), **`shared/`** (credential parsing, verification, JWT helpers).
|
|
227
244
|
|
|
228
245
|
| Endpoint | Method | Description |
|
|
229
246
|
|---|---|---|
|
|
230
|
-
| `/auth/customer/emailpass` | POST |
|
|
231
|
-
| `/auth/customer/
|
|
232
|
-
|
|
233
|
-
|
|
247
|
+
| `/auth/customer/emailpass/register` | POST | **Register.** JSON: `password` plus identifier per `registration.identifier` — **`email`** only for `"email"` and `"both"` (for `"both"`, phone is added on `POST /store/customers`); **`phone`** only for `"phone"`. Dispatches to `register("emailpass")` or `register("phonepass")`. Response: `{ "token" }` (pre-customer JWT). See [`emailpass/register/route.ts`](src/api/auth/customer/emailpass/register/route.ts), [`parse-register-body.ts`](src/api/auth/customer/shared/parse-register-body.ts), [`complete-registration-token.ts`](src/api/auth/customer/shared/complete-registration-token.ts). |
|
|
248
|
+
| `/auth/customer/emailpass` | POST | **Login.** JSON: `password` plus **exactly one** of `email` or `phone` (XOR), validated against `login.identifier`. Optional query params can fill missing keys (body wins). [`emailpass/route.ts`](src/api/auth/customer/emailpass/route.ts) → [`handleCustomerLogin`](src/api/auth/customer/shared/customer-login-post.ts). |
|
|
249
|
+
|
|
250
|
+
Password reset URLs are unchanged; see [Password Reset](#password-reset).
|
|
234
251
|
|
|
235
252
|
---
|
|
236
253
|
|
|
@@ -411,8 +428,8 @@ export default defineConfig({
|
|
|
411
428
|
### 2. Registration flow
|
|
412
429
|
|
|
413
430
|
```bash
|
|
414
|
-
# Step 1 — create phonepass auth identity
|
|
415
|
-
POST /auth/customer/
|
|
431
|
+
# Step 1 — create phonepass auth identity (unified register URL)
|
|
432
|
+
POST /auth/customer/emailpass/register
|
|
416
433
|
{ "phone": "+15551234567", "password": "SecretPass1!" }
|
|
417
434
|
# Response: { "token": "<pre-customer jwt>" }
|
|
418
435
|
|
|
@@ -435,7 +452,7 @@ POST /store/customers/otp/verify
|
|
|
435
452
|
### 3. Login flow
|
|
436
453
|
|
|
437
454
|
```bash
|
|
438
|
-
POST /auth/customer/
|
|
455
|
+
POST /auth/customer/emailpass
|
|
439
456
|
{ "phone": "+15551234567", "password": "SecretPass1!" }
|
|
440
457
|
# Response: { "token": "<jwt>" }
|
|
441
458
|
```
|
|
@@ -519,12 +536,11 @@ await completePasswordReset(
|
|
|
519
536
|
- Node.js >= 20
|
|
520
537
|
- Notification module configured with at least one provider (email/SMS)
|
|
521
538
|
- Database migrations applied (`npx medusa db:migrate`)
|
|
522
|
-
-
|
|
539
|
+
- **`phonepass`** auth provider registered in `medusa-config` (required when customers can **register** or **log in** with phone — i.e. `registration.identifier` and/or `login.identifier` is `"phone"` or `"both"`)
|
|
523
540
|
|
|
524
541
|
## Documentation
|
|
525
542
|
|
|
526
|
-
|
|
527
|
-
- **[README.md](./README.md)** — This file (overview and quick start)
|
|
543
|
+
This **README** is the main overview: configuration, auth routes, OTP behaviour, and API tables.
|
|
528
544
|
|
|
529
545
|
## Development
|
|
530
546
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "customer-registration",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.116",
|
|
4
4
|
"description": "Medusa plugin that overrides store customer registration, enforces email/phone verification flags, and provides OTP management module.",
|
|
5
5
|
"author": "Medusa (https://medusajs.com)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.POST = void 0;
|
|
4
|
-
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
-
const generate_jwt_token_1 = require("@medusajs/medusa/api/auth/utils/generate-jwt-token");
|
|
6
|
-
/**
|
|
7
|
-
* Register a new customer with phone + password.
|
|
8
|
-
*
|
|
9
|
-
* On success the caller receives a short-lived JWT token. Use it as the
|
|
10
|
-
* Bearer token when calling `POST /store/customers` to create the customer
|
|
11
|
-
* record and link it to this auth identity.
|
|
12
|
-
*/
|
|
13
|
-
const POST = async (req, res) => {
|
|
14
|
-
const config = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
|
|
15
|
-
const service = req.scope.resolve(utils_1.Modules.AUTH);
|
|
16
|
-
const authData = {
|
|
17
|
-
url: req.url,
|
|
18
|
-
headers: req.headers,
|
|
19
|
-
query: req.query,
|
|
20
|
-
body: req.body,
|
|
21
|
-
protocol: req.protocol,
|
|
22
|
-
};
|
|
23
|
-
const { success, error, authIdentity } = await service.register("phonepass", authData);
|
|
24
|
-
if (!success || !authIdentity) {
|
|
25
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, error || "Registration failed");
|
|
26
|
-
}
|
|
27
|
-
const { http } = config.projectConfig;
|
|
28
|
-
if (!http.jwtSecret) {
|
|
29
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "JWT secret is not configured");
|
|
30
|
-
}
|
|
31
|
-
let token;
|
|
32
|
-
try {
|
|
33
|
-
token = await (0, generate_jwt_token_1.generateJwtTokenForAuthIdentity)({
|
|
34
|
-
authIdentity,
|
|
35
|
-
actorType: "customer",
|
|
36
|
-
}, {
|
|
37
|
-
secret: http.jwtSecret,
|
|
38
|
-
expiresIn: http.jwtExpiresIn || "7d",
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
catch (jwtError) {
|
|
42
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `JWT generation failed: ${jwtError instanceof Error ? jwtError.message : "Unknown error"}`);
|
|
43
|
-
}
|
|
44
|
-
if (!token || typeof token !== "string") {
|
|
45
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Failed to generate registration token");
|
|
46
|
-
}
|
|
47
|
-
return res.status(200).json({ token });
|
|
48
|
-
};
|
|
49
|
-
exports.POST = POST;
|
|
50
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvY3VzdG9tZXIvcGhvbmVwYXNzL3JlZ2lzdGVyL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLHFEQUlrQztBQUNsQywyRkFBb0c7QUFFcEc7Ozs7OztHQU1HO0FBQ0ksTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ3BFLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLGFBQWEsQ0FBQyxDQUFBO0lBQ3pFLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGVBQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUUvQyxNQUFNLFFBQVEsR0FBRztRQUNmLEdBQUcsRUFBRSxHQUFHLENBQUMsR0FBRztRQUNaLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTztRQUNwQixLQUFLLEVBQUUsR0FBRyxDQUFDLEtBQUs7UUFDaEIsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJO1FBQ2QsUUFBUSxFQUFFLEdBQUcsQ0FBQyxRQUFRO0tBQ0EsQ0FBQTtJQUV4QixNQUFNLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsR0FBRyxNQUFNLE9BQU8sQ0FBQyxRQUFRLENBQzdELFdBQVcsRUFDWCxRQUFRLENBQ1QsQ0FBQTtJQUVELElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUM5QixNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5QixLQUFLLElBQUkscUJBQXFCLENBQy9CLENBQUE7SUFDSCxDQUFDO0lBRUQsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUE7SUFFckMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNwQixNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5Qiw4QkFBOEIsQ0FDL0IsQ0FBQTtJQUNILENBQUM7SUFFRCxJQUFJLEtBQXlCLENBQUE7SUFDN0IsSUFBSSxDQUFDO1FBQ0gsS0FBSyxHQUFHLE1BQU0sSUFBQSxvREFBK0IsRUFDM0M7WUFDRSxZQUFZO1lBQ1osU0FBUyxFQUFFLFVBQVU7U0FDdEIsRUFDRDtZQUNFLE1BQU0sRUFBRSxJQUFJLENBQUMsU0FBUztZQUN0QixTQUFTLEVBQUUsSUFBSSxDQUFDLFlBQVksSUFBSSxJQUFJO1NBQ3JDLENBQ0YsQ0FBQTtJQUNILENBQUM7SUFBQyxPQUFPLFFBQVEsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFDbEMsMEJBQTBCLFFBQVEsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLGVBQWUsRUFBRSxDQUMzRixDQUFBO0lBQ0gsQ0FBQztJQUVELElBQUksQ0FBQyxLQUFLLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDeEMsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUNsQyx1Q0FBdUMsQ0FDeEMsQ0FBQTtJQUNILENBQUM7SUFFRCxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQTtBQUN4QyxDQUFDLENBQUE7QUE1RFksUUFBQSxJQUFJLFFBNERoQiJ9
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.POST = void 0;
|
|
4
|
-
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
-
const generate_jwt_token_1 = require("@medusajs/medusa/api/auth/utils/generate-jwt-token");
|
|
6
|
-
const account_deletion_request_1 = require("../../../../modules/account-deletion-request");
|
|
7
|
-
const otp_verification_1 = require("../../../../modules/otp-verification");
|
|
8
|
-
const config_1 = require("../../../../config");
|
|
9
|
-
const POST = async (req, res) => {
|
|
10
|
-
const config = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
|
|
11
|
-
const loginOptions = (0, config_1.resolveCustomerRegistrationOptions)(config);
|
|
12
|
-
if (loginOptions.login.identifier === "email") {
|
|
13
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Phone login is not enabled. Please log in with your email.");
|
|
14
|
-
}
|
|
15
|
-
const service = req.scope.resolve(utils_1.Modules.AUTH);
|
|
16
|
-
const authData = {
|
|
17
|
-
url: req.url,
|
|
18
|
-
headers: req.headers,
|
|
19
|
-
query: req.query,
|
|
20
|
-
body: req.body,
|
|
21
|
-
protocol: req.protocol,
|
|
22
|
-
};
|
|
23
|
-
const { success, error, authIdentity } = await service.authenticate("phonepass", authData);
|
|
24
|
-
if (success && authIdentity) {
|
|
25
|
-
const phone = authIdentity.provider_identities?.[0]?.entity_id ?? "";
|
|
26
|
-
await enforcePhoneVerification({ authIdentity, req });
|
|
27
|
-
let customerId = authIdentity.app_metadata?.customer_id;
|
|
28
|
-
if (!customerId) {
|
|
29
|
-
const knex = req.scope.resolve(utils_1.ContainerRegistrationKeys.PG_CONNECTION);
|
|
30
|
-
if (knex) {
|
|
31
|
-
const result = await knex.raw(`SELECT id FROM customer WHERE phone = ? LIMIT 1`, [phone]);
|
|
32
|
-
const row = result.rows?.[0] ?? result[0]?.[0];
|
|
33
|
-
if (row?.id) {
|
|
34
|
-
customerId = row.id;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
if (!customerId) {
|
|
39
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Unable to determine customer ID for authentication");
|
|
40
|
-
}
|
|
41
|
-
const accountDeletionService = req.scope.resolve(account_deletion_request_1.ACCOUNT_DELETION_REQUEST_MODULE);
|
|
42
|
-
if (await accountDeletionService.hasPendingRequest(customerId)) {
|
|
43
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Customer has an active account deletion request");
|
|
44
|
-
}
|
|
45
|
-
const authIdentityWithCustomerId = {
|
|
46
|
-
...authIdentity,
|
|
47
|
-
app_metadata: {
|
|
48
|
-
...authIdentity.app_metadata,
|
|
49
|
-
customer_id: customerId,
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
const { http } = config.projectConfig;
|
|
53
|
-
if (!http.jwtSecret) {
|
|
54
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "JWT secret is not configured");
|
|
55
|
-
}
|
|
56
|
-
let token;
|
|
57
|
-
try {
|
|
58
|
-
token = await (0, generate_jwt_token_1.generateJwtTokenForAuthIdentity)({
|
|
59
|
-
authIdentity: authIdentityWithCustomerId,
|
|
60
|
-
actorType: "customer",
|
|
61
|
-
}, {
|
|
62
|
-
secret: http.jwtSecret,
|
|
63
|
-
expiresIn: http.jwtExpiresIn || "7d",
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
catch (jwtError) {
|
|
67
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `JWT generation failed: ${jwtError instanceof Error ? jwtError.message : "Unknown error"}`);
|
|
68
|
-
}
|
|
69
|
-
if (!token || typeof token !== "string") {
|
|
70
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Failed to generate authentication token");
|
|
71
|
-
}
|
|
72
|
-
return res.status(200).json({ token });
|
|
73
|
-
}
|
|
74
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, error || "Authentication failed");
|
|
75
|
-
};
|
|
76
|
-
exports.POST = POST;
|
|
77
|
-
const enforcePhoneVerification = async ({ authIdentity, req, }) => {
|
|
78
|
-
const configModule = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
|
|
79
|
-
const options = (0, config_1.resolveCustomerRegistrationOptions)(configModule);
|
|
80
|
-
const { require_verification } = options.registration;
|
|
81
|
-
if (!require_verification) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
// Use customer_id — not phone — for the verification lookup.
|
|
85
|
-
// Phone is mutable: after a phone update customer.phone becomes the NEW number
|
|
86
|
-
// while provider_identity.entity_id still holds the OLD one. Querying
|
|
87
|
-
// WHERE phone = entity_id would find no row and return phone_verified = false
|
|
88
|
-
// even when the customer's actual record is marked verified.
|
|
89
|
-
const customerId = authIdentity.app_metadata?.customer_id;
|
|
90
|
-
if (!customerId) {
|
|
91
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, "Phone not verified.");
|
|
92
|
-
}
|
|
93
|
-
const otpService = req.scope.resolve(otp_verification_1.OTP_VERIFICATION_MODULE);
|
|
94
|
-
const verificationStatus = await otpService.getCustomerVerificationByCustomerId(req.scope, customerId);
|
|
95
|
-
if (!verificationStatus.phone_verified) {
|
|
96
|
-
// Surface a helpful message when a phone change is pending verification
|
|
97
|
-
const knex = req.scope.resolve(utils_1.ContainerRegistrationKeys.PG_CONNECTION);
|
|
98
|
-
const row = await knex.raw(`SELECT metadata->>'pending_phone' AS pending_phone FROM customer WHERE id = ? LIMIT 1`, [customerId]);
|
|
99
|
-
const pendingPhone = (row.rows?.[0] ?? row[0]?.[0])?.pending_phone ?? null;
|
|
100
|
-
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNAUTHORIZED, pendingPhone
|
|
101
|
-
? "Your new phone number is pending verification. Please verify it to continue."
|
|
102
|
-
: "Phone not verified.");
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvY3VzdG9tZXIvcGhvbmVwYXNzL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUtBLHFEQUlrQztBQUNsQywyRkFBb0c7QUFDcEcsMkZBQThGO0FBRTlGLDJFQUE4RTtBQUc5RSwrQ0FHMkI7QUFFcEIsTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLEdBQWtCLEVBQUUsR0FBbUIsRUFBRSxFQUFFO0lBQ3BFLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLGFBQWEsQ0FBQyxDQUFBO0lBRXpFLE1BQU0sWUFBWSxHQUFHLElBQUEsMkNBQWtDLEVBQUMsTUFBMkIsQ0FBQyxDQUFBO0lBQ3BGLElBQUksWUFBWSxDQUFDLEtBQUssQ0FBQyxVQUFVLEtBQUssT0FBTyxFQUFFLENBQUM7UUFDOUMsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFDOUIsNERBQTRELENBQzdELENBQUE7SUFDSCxDQUFDO0lBRUQsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsZUFBTyxDQUFDLElBQUksQ0FBQyxDQUFBO0lBRS9DLE1BQU0sUUFBUSxHQUFHO1FBQ2YsR0FBRyxFQUFFLEdBQUcsQ0FBQyxHQUFHO1FBQ1osT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPO1FBQ3BCLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSztRQUNoQixJQUFJLEVBQUUsR0FBRyxDQUFDLElBQUk7UUFDZCxRQUFRLEVBQUUsR0FBRyxDQUFDLFFBQVE7S0FDQSxDQUFBO0lBRXhCLE1BQU0sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxHQUNwQyxNQUFNLE9BQU8sQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLFFBQVEsQ0FB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
|