customer-registration 0.0.125 → 0.0.127

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.medusa/server/src/api/auth/customer/emailotp/__tests__/send-route.test.js +151 -0
  2. package/.medusa/server/src/api/auth/customer/emailotp/__tests__/verify-route.test.js +171 -0
  3. package/.medusa/server/src/api/auth/customer/emailotp/send/route.js +51 -0
  4. package/.medusa/server/src/api/auth/customer/emailotp/shared/email-auth-helpers.js +62 -0
  5. package/.medusa/server/src/api/auth/customer/emailotp/verify/route.js +54 -0
  6. package/.medusa/server/src/api/auth/customer/phoneotp/__tests__/send-route.test.js +153 -0
  7. package/.medusa/server/src/api/auth/customer/phoneotp/__tests__/verify-route.test.js +158 -0
  8. package/.medusa/server/src/api/auth/customer/phoneotp/send/route.js +51 -0
  9. package/.medusa/server/src/api/auth/customer/phoneotp/shared/phone-auth-helpers.js +63 -0
  10. package/.medusa/server/src/api/auth/customer/phoneotp/verify/route.js +54 -0
  11. package/.medusa/server/src/api/auth/customer/shared/complete-customer-login.js +11 -38
  12. package/.medusa/server/src/api/auth/customer/shared/customer-login-post.js +1 -6
  13. package/.medusa/server/src/api/auth/customer/shared/enforce-registration-verification.js +1 -5
  14. package/.medusa/server/src/api/middlewares.js +11 -1
  15. package/.medusa/server/src/api/store/customers/route.js +6 -120
  16. package/.medusa/server/src/api/store/customers/shared/referral-code.js +91 -0
  17. package/.medusa/server/src/config/__tests__/email-auth-config.test.js +37 -0
  18. package/.medusa/server/src/config/__tests__/phone-auth-config.test.js +37 -0
  19. package/.medusa/server/src/config.js +25 -1
  20. package/.medusa/server/src/modules/otp-verification/migrations/Migration20250603000000AddEmailAuthOtp.js +67 -0
  21. package/.medusa/server/src/modules/otp-verification/migrations/Migration20250603100000AddPhoneAuthOtp.js +61 -0
  22. package/.medusa/server/src/modules/otp-verification/models/otp-verification.js +8 -2
  23. package/.medusa/server/src/modules/otp-verification/service.js +248 -5
  24. package/.medusa/server/src/providers/emailotp/index.js +9 -0
  25. package/.medusa/server/src/providers/emailotp/service.js +68 -0
  26. package/.medusa/server/src/providers/phoneotp/index.js +9 -0
  27. package/.medusa/server/src/providers/phoneotp/service.js +68 -0
  28. package/.medusa/server/src/providers/phonepass/service.js +5 -5
  29. package/.medusa/server/src/utils/phone-validation.js +26 -0
  30. package/.medusa/server/src/workflows/send-email-auth-otp-workflow.js +42 -0
  31. package/.medusa/server/src/workflows/send-phone-auth-otp-workflow.js +42 -0
  32. package/.medusa/server/src/workflows/steps/generate-email-auth-otp-step.js +25 -0
  33. package/.medusa/server/src/workflows/steps/generate-phone-auth-otp-step.js +25 -0
  34. package/.medusa/server/src/workflows/steps/index.js +10 -2
  35. package/.medusa/server/src/workflows/steps/resolve-or-create-email-auth-customer-step.js +125 -0
  36. package/.medusa/server/src/workflows/steps/resolve-or-create-phone-auth-customer-step.js +151 -0
  37. package/.medusa/server/src/workflows/verify-email-auth-otp-workflow.js +20 -0
  38. package/.medusa/server/src/workflows/verify-phone-auth-otp-workflow.js +20 -0
  39. package/README.md +706 -426
  40. package/package.json +1 -1
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const vitest_1 = require("vitest");
8
+ const config_1 = require("../../../../../config");
9
+ const send_email_auth_otp_workflow_1 = __importDefault(require("../../../../../workflows/send-email-auth-otp-workflow"));
10
+ const email_auth_helpers_1 = require("../shared/email-auth-helpers");
11
+ const route_1 = require("../send/route");
12
+ vitest_1.vi.mock("../../../../../config", async (importOriginal) => {
13
+ const actual = await importOriginal();
14
+ return {
15
+ ...actual,
16
+ resolveCustomerRegistrationOptions: vitest_1.vi.fn(),
17
+ isEmailOtpAuthEnabled: vitest_1.vi.fn(),
18
+ };
19
+ });
20
+ vitest_1.vi.mock("../shared/email-auth-helpers", () => ({
21
+ lookupCustomerByEmail: vitest_1.vi.fn(),
22
+ normalizeAuthEmail: (email) => email.toLowerCase().trim(),
23
+ }));
24
+ vitest_1.vi.mock("../../../../../workflows/send-email-auth-otp-workflow", () => ({
25
+ default: vitest_1.vi.fn(),
26
+ }));
27
+ const mockedResolveOptions = vitest_1.vi.mocked(config_1.resolveCustomerRegistrationOptions);
28
+ const mockedIsOtpEnabled = vitest_1.vi.mocked(config_1.isEmailOtpAuthEnabled);
29
+ const mockedLookupCustomer = vitest_1.vi.mocked(email_auth_helpers_1.lookupCustomerByEmail);
30
+ const mockedWorkflow = vitest_1.vi.mocked(send_email_auth_otp_workflow_1.default);
31
+ (0, vitest_1.describe)("POST /auth/customer/emailotp/send table-driven tests", () => {
32
+ (0, vitest_1.beforeEach)(() => {
33
+ vitest_1.vi.clearAllMocks();
34
+ mockedResolveOptions.mockReturnValue({
35
+ ...(0, config_1.resolveCustomerRegistrationOptions)(undefined),
36
+ auth: {
37
+ email: { methods: ["otp"] },
38
+ phone: { methods: ["password"] },
39
+ },
40
+ });
41
+ mockedIsOtpEnabled.mockImplementation((opts) => opts.auth.email.methods.includes("otp"));
42
+ mockedWorkflow.mockReturnValue({
43
+ run: vitest_1.vi.fn().mockResolvedValue({
44
+ result: {
45
+ token: "otp_token",
46
+ expires_at: new Date("2025-06-03T12:00:00.000Z"),
47
+ },
48
+ }),
49
+ });
50
+ });
51
+ const cases = [
52
+ {
53
+ title: "rejects when OTP auth is disabled",
54
+ body: { email: "user@example.com" },
55
+ otpEnabled: false,
56
+ customer: null,
57
+ pendingDeletion: false,
58
+ shouldThrow: true,
59
+ errorType: utils_1.MedusaError.Types.NOT_ALLOWED,
60
+ },
61
+ {
62
+ title: "rejects invalid email format",
63
+ body: { email: "bad" },
64
+ otpEnabled: true,
65
+ customer: null,
66
+ pendingDeletion: false,
67
+ shouldThrow: true,
68
+ errorType: utils_1.MedusaError.Types.INVALID_DATA,
69
+ },
70
+ {
71
+ title: "blocks when pending account deletion",
72
+ body: { email: "user@example.com" },
73
+ otpEnabled: true,
74
+ customer: {
75
+ id: "cus_1",
76
+ email: "user@example.com",
77
+ has_account: true,
78
+ first_name: "A",
79
+ last_name: null,
80
+ },
81
+ pendingDeletion: true,
82
+ shouldThrow: true,
83
+ errorType: utils_1.MedusaError.Types.NOT_ALLOWED,
84
+ },
85
+ {
86
+ title: "returns token for new user",
87
+ body: { email: "new@example.com" },
88
+ otpEnabled: true,
89
+ customer: null,
90
+ pendingDeletion: false,
91
+ shouldThrow: false,
92
+ expectedStatus: 200,
93
+ expectedJson: {
94
+ token: "otp_token",
95
+ expires_at: new Date("2025-06-03T12:00:00.000Z"),
96
+ is_new_user: true,
97
+ },
98
+ },
99
+ {
100
+ title: "returns is_new_user false for existing account",
101
+ body: { email: "existing@example.com" },
102
+ otpEnabled: true,
103
+ customer: {
104
+ id: "cus_2",
105
+ email: "existing@example.com",
106
+ has_account: true,
107
+ first_name: "E",
108
+ last_name: "X",
109
+ },
110
+ pendingDeletion: false,
111
+ shouldThrow: false,
112
+ expectedStatus: 200,
113
+ expectedJson: {
114
+ token: "otp_token",
115
+ expires_at: new Date("2025-06-03T12:00:00.000Z"),
116
+ is_new_user: false,
117
+ },
118
+ },
119
+ ];
120
+ vitest_1.test.each(cases)("$title", async ({ body, otpEnabled, customer, pendingDeletion, shouldThrow, errorType, expectedStatus, expectedJson, }) => {
121
+ mockedIsOtpEnabled.mockReturnValue(otpEnabled);
122
+ mockedLookupCustomer.mockResolvedValue(customer);
123
+ const hasPendingRequest = vitest_1.vi.fn().mockResolvedValue(pendingDeletion);
124
+ const req = {
125
+ body,
126
+ scope: {
127
+ resolve: (token) => {
128
+ if (token === utils_1.ContainerRegistrationKeys.CONFIG_MODULE) {
129
+ return {};
130
+ }
131
+ if (String(token).includes("account_deletion")) {
132
+ return { hasPendingRequest };
133
+ }
134
+ return undefined;
135
+ },
136
+ },
137
+ };
138
+ const status = vitest_1.vi.fn().mockReturnThis();
139
+ const json = vitest_1.vi.fn();
140
+ const res = { status, json };
141
+ const exec = () => (0, route_1.POST)(req, res);
142
+ if (shouldThrow) {
143
+ await (0, vitest_1.expect)(exec()).rejects.toMatchObject({ type: errorType });
144
+ return;
145
+ }
146
+ await exec();
147
+ (0, vitest_1.expect)(status).toHaveBeenCalledWith(expectedStatus);
148
+ (0, vitest_1.expect)(json).toHaveBeenCalledWith(expectedJson);
149
+ });
150
+ });
151
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VuZC1yb3V0ZS50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwaS9hdXRoL2N1c3RvbWVyL2VtYWlsb3RwL19fdGVzdHNfXy9zZW5kLXJvdXRlLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFDQSxxREFBa0Y7QUFDbEYsbUNBQStEO0FBQy9ELGtEQUFpRztBQUNqRyx5SEFBNEY7QUFDNUYscUVBQW9FO0FBQ3BFLHlDQUFvQztBQUVwQyxXQUFFLENBQUMsSUFBSSxDQUFDLHVCQUF1QixFQUFFLEtBQUssRUFBRSxjQUFjLEVBQUUsRUFBRTtJQUN4RCxNQUFNLE1BQU0sR0FBRyxNQUFNLGNBQWMsRUFBMEMsQ0FBQTtJQUM3RSxPQUFPO1FBQ0wsR0FBRyxNQUFNO1FBQ1Qsa0NBQWtDLEVBQUUsV0FBRSxDQUFDLEVBQUUsRUFBRTtRQUMzQyxxQkFBcUIsRUFBRSxXQUFFLENBQUMsRUFBRSxFQUFFO0tBQy9CLENBQUE7QUFDSCxDQUFDLENBQUMsQ0FBQTtBQUVGLFdBQUUsQ0FBQyxJQUFJLENBQUMsOEJBQThCLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUM3QyxxQkFBcUIsRUFBRSxXQUFFLENBQUMsRUFBRSxFQUFFO0lBQzlCLGtCQUFrQixFQUFFLENBQUMsS0FBYSxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUMsSUFBSSxFQUFFO0NBQ2xFLENBQUMsQ0FBQyxDQUFBO0FBRUgsV0FBRSxDQUFDLElBQUksQ0FBQyx1REFBdUQsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ3RFLE9BQU8sRUFBRSxXQUFFLENBQUMsRUFBRSxFQUFFO0NBQ2pCLENBQUMsQ0FBQyxDQUFBO0FBRUgsTUFBTSxvQkFBb0IsR0FBRyxXQUFFLENBQUMsTUFBTSxDQUFDLDJDQUFrQyxDQUFDLENBQUE7QUFDMUUsTUFBTSxrQkFBa0IsR0FBRyxXQUFFLENBQUMsTUFB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
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const vitest_1 = require("vitest");
8
+ const config_1 = require("../../../../../config");
9
+ const otp_verification_1 = require("../../../../../modules/otp-verification/models/otp-verification");
10
+ const otp_verification_2 = require("../../../../../modules/otp-verification");
11
+ const verify_email_auth_otp_workflow_1 = __importDefault(require("../../../../../workflows/verify-email-auth-otp-workflow"));
12
+ const complete_customer_login_1 = require("../../shared/complete-customer-login");
13
+ const route_1 = require("../verify/route");
14
+ vitest_1.vi.mock("../../../../../config", async (importOriginal) => {
15
+ const actual = await importOriginal();
16
+ return {
17
+ ...actual,
18
+ resolveCustomerRegistrationOptions: vitest_1.vi.fn(),
19
+ isEmailOtpAuthEnabled: vitest_1.vi.fn(),
20
+ };
21
+ });
22
+ vitest_1.vi.mock("../../../../../workflows/verify-email-auth-otp-workflow", () => ({
23
+ default: vitest_1.vi.fn(),
24
+ }));
25
+ vitest_1.vi.mock("../../shared/complete-customer-login", () => ({
26
+ issueCustomerJwtToken: vitest_1.vi.fn(),
27
+ }));
28
+ vitest_1.vi.mock("../../../../store/customers/shared/referral-code", () => ({
29
+ assertReferralCodeReferrerExists: vitest_1.vi.fn().mockResolvedValue(undefined),
30
+ maybeCreateReferralLinkFromRequest: vitest_1.vi.fn().mockResolvedValue(undefined),
31
+ }));
32
+ const mockedIsOtpEnabled = vitest_1.vi.mocked(config_1.isEmailOtpAuthEnabled);
33
+ const mockedWorkflow = vitest_1.vi.mocked(verify_email_auth_otp_workflow_1.default);
34
+ const mockedIssueJwt = vitest_1.vi.mocked(complete_customer_login_1.issueCustomerJwtToken);
35
+ (0, vitest_1.describe)("POST /auth/customer/emailotp/verify table-driven tests", () => {
36
+ (0, vitest_1.beforeEach)(() => {
37
+ vitest_1.vi.clearAllMocks();
38
+ mockedIsOtpEnabled.mockReturnValue(true);
39
+ mockedIssueJwt.mockResolvedValue("customer_jwt");
40
+ mockedWorkflow.mockReturnValue({
41
+ run: vitest_1.vi.fn().mockResolvedValue({
42
+ result: {
43
+ customer: { id: "cus_new", email: "new@example.com" },
44
+ auth_identity: { id: "auth_1" },
45
+ is_new_user: true,
46
+ },
47
+ }),
48
+ });
49
+ });
50
+ const cases = [
51
+ {
52
+ title: "rejects when OTP auth is disabled",
53
+ body: { token: "t", code: "123456" },
54
+ otpEnabled: false,
55
+ shouldThrow: true,
56
+ errorType: utils_1.MedusaError.Types.NOT_ALLOWED,
57
+ },
58
+ {
59
+ title: "requires token",
60
+ body: { code: "123456" },
61
+ otpEnabled: true,
62
+ shouldThrow: true,
63
+ errorType: utils_1.MedusaError.Types.INVALID_DATA,
64
+ },
65
+ {
66
+ title: "requires code",
67
+ body: { token: "t" },
68
+ otpEnabled: true,
69
+ shouldThrow: true,
70
+ errorType: utils_1.MedusaError.Types.INVALID_DATA,
71
+ },
72
+ {
73
+ title: "rejects invalid OTP",
74
+ body: { token: "t", code: "000000" },
75
+ otpEnabled: true,
76
+ verifyOtpThrows: new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Invalid OTP code"),
77
+ shouldThrow: true,
78
+ errorType: utils_1.MedusaError.Types.INVALID_DATA,
79
+ },
80
+ {
81
+ title: "returns JWT and customer for new user",
82
+ body: {
83
+ token: "t",
84
+ code: "123456",
85
+ first_name: "New",
86
+ referral_code: "cus_ref",
87
+ },
88
+ otpEnabled: true,
89
+ verifyOtpResult: {
90
+ verified: true,
91
+ email: "new@example.com",
92
+ customer_id: null,
93
+ type: otp_verification_1.OtpPurpose.EMAIL_AUTH,
94
+ },
95
+ workflowResult: {
96
+ customer: { id: "cus_new", email: "new@example.com", first_name: "New" },
97
+ auth_identity: { id: "auth_1" },
98
+ is_new_user: true,
99
+ },
100
+ shouldThrow: false,
101
+ expectedStatus: 200,
102
+ expectedJson: {
103
+ token: "customer_jwt",
104
+ customer: { id: "cus_new", email: "new@example.com", first_name: "New" },
105
+ is_new_user: true,
106
+ },
107
+ },
108
+ {
109
+ title: "returns JWT for existing password user login",
110
+ body: { token: "t", code: "123456" },
111
+ otpEnabled: true,
112
+ verifyOtpResult: {
113
+ verified: true,
114
+ email: "existing@example.com",
115
+ customer_id: "cus_existing",
116
+ type: otp_verification_1.OtpPurpose.EMAIL_AUTH,
117
+ },
118
+ workflowResult: {
119
+ customer: { id: "cus_existing", email: "existing@example.com" },
120
+ auth_identity: { id: "auth_existing" },
121
+ is_new_user: false,
122
+ },
123
+ shouldThrow: false,
124
+ expectedStatus: 200,
125
+ expectedJson: {
126
+ token: "customer_jwt",
127
+ customer: { id: "cus_existing", email: "existing@example.com" },
128
+ is_new_user: false,
129
+ },
130
+ },
131
+ ];
132
+ vitest_1.test.each(cases)("$title", async ({ body, otpEnabled, verifyOtpResult, verifyOtpThrows, workflowResult, shouldThrow, errorType, expectedStatus, expectedJson, }) => {
133
+ mockedIsOtpEnabled.mockReturnValue(otpEnabled);
134
+ const verifyEmailAuthOtp = verifyOtpThrows
135
+ ? vitest_1.vi.fn().mockRejectedValue(verifyOtpThrows)
136
+ : vitest_1.vi.fn().mockResolvedValue(verifyOtpResult);
137
+ if (workflowResult) {
138
+ mockedWorkflow.mockReturnValue({
139
+ run: vitest_1.vi.fn().mockResolvedValue({ result: workflowResult }),
140
+ });
141
+ }
142
+ const req = {
143
+ body,
144
+ scope: {
145
+ resolve: (token) => {
146
+ if (token === utils_1.ContainerRegistrationKeys.CONFIG_MODULE) {
147
+ return {
148
+ projectConfig: { http: { jwtSecret: "secret", jwtExpiresIn: "7d" } },
149
+ };
150
+ }
151
+ if (token === otp_verification_2.OTP_VERIFICATION_MODULE) {
152
+ return { verifyEmailAuthOtp };
153
+ }
154
+ return undefined;
155
+ },
156
+ },
157
+ };
158
+ const status = vitest_1.vi.fn().mockReturnThis();
159
+ const json = vitest_1.vi.fn();
160
+ const res = { status, json };
161
+ const exec = () => (0, route_1.POST)(req, res);
162
+ if (shouldThrow) {
163
+ await (0, vitest_1.expect)(exec()).rejects.toMatchObject({ type: errorType });
164
+ return;
165
+ }
166
+ await exec();
167
+ (0, vitest_1.expect)(status).toHaveBeenCalledWith(expectedStatus);
168
+ (0, vitest_1.expect)(json).toHaveBeenCalledWith(expectedJson);
169
+ });
170
+ });
171
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyaWZ5LXJvdXRlLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvY3VzdG9tZXIvZW1haWxvdHAvX190ZXN0c19fL3ZlcmlmeS1yb3V0ZS50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQ0EscURBQWtGO0FBQ2xGLG1DQUErRDtBQUMvRCxrREFBaUc7QUFDakcsc0dBQTRGO0FBQzVGLDhFQUFpRjtBQUNqRiw2SEFBZ0c7QUFDaEcsa0ZBQTRFO0FBQzVFLDJDQUFzQztBQUV0QyxXQUFFLENBQUMsSUFBSSxDQUFDLHVCQUF1QixFQUFFLEtBQUssRUFBRSxjQUFjLEVBQUUsRUFBRTtJQUN4RCxNQUFNLE1BQU0sR0FBRyxNQUFNLGNBQWMsRUFBMEMsQ0FBQTtJQUM3RSxPQUFPO1FBQ0wsR0FBRyxNQUFNO1FBQ1Qsa0NBQWtDLEVBQUUsV0FBRSxDQUFDLEVBQUUsRUFBRTtRQUMzQyxxQkFBcUIsRUFBRSxXQUFFLENBQUMsRUFBRSxFQUFFO0tBQy9CLENBQUE7QUFDSCxDQUFDLENBQUMsQ0FBQTtBQUVGLFdBQUUsQ0FBQyxJQUFJLENBQUMseURBQXlELEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUN4RSxPQUFPLEVBQUUsV0FBRSxDQUFDLEVBQUUsRUFBRTtDQUNqQixDQUFDLENBQUMsQ0FBQTtBQUVILFdBQUUsQ0FBQyxJQUFJLENBQUMsc0NBQXNDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNyRCxxQkFBcUIsRUFBRSxXQUFFLENBQUMsRUFBRSxFQUFFO0NBQy9CLENBQUMsQ0FBQyxDQUFBO0FBRUgsV0FBRSxDQUFDLElBQUksQ0FBQyxrREFBa0QsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ2pFLGdDQUFnQyxFQUFFLFdBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUM7SUFDdEUsa0NBQWtDLEVBQUUsV0FB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
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.POST = void 0;
7
+ const utils_1 = require("@medusajs/framework/utils");
8
+ const config_1 = require("../../../../../config");
9
+ const account_deletion_request_1 = require("../../../../../modules/account-deletion-request");
10
+ const send_email_auth_otp_workflow_1 = __importDefault(require("../../../../../workflows/send-email-auth-otp-workflow"));
11
+ const email_validation_1 = require("../../../../../utils/email-validation");
12
+ const email_auth_helpers_1 = require("../shared/email-auth-helpers");
13
+ const POST = async (req, res) => {
14
+ const configModule = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
15
+ const options = (0, config_1.resolveCustomerRegistrationOptions)(configModule);
16
+ if (!(0, config_1.isEmailOtpAuthEnabled)(options)) {
17
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "Email OTP authentication is not enabled");
18
+ }
19
+ const body = req.body;
20
+ const rawEmail = body?.email;
21
+ if (!rawEmail || typeof rawEmail !== "string") {
22
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "email is required");
23
+ }
24
+ (0, email_validation_1.validateEmailFormat)(rawEmail);
25
+ const email = (0, email_auth_helpers_1.normalizeAuthEmail)(rawEmail);
26
+ const existingCustomer = await (0, email_auth_helpers_1.lookupCustomerByEmail)(req.scope, email);
27
+ const isNewUser = !existingCustomer?.has_account;
28
+ if (existingCustomer?.id) {
29
+ const accountDeletionService = req.scope.resolve(account_deletion_request_1.ACCOUNT_DELETION_REQUEST_MODULE);
30
+ if (await accountDeletionService.hasPendingRequest(existingCustomer.id)) {
31
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "This account has a pending deletion request");
32
+ }
33
+ }
34
+ const customerName = existingCustomer?.first_name ||
35
+ existingCustomer?.email ||
36
+ email;
37
+ const { result } = await (0, send_email_auth_otp_workflow_1.default)(req.scope).run({
38
+ input: {
39
+ email,
40
+ customer_id: existingCustomer?.id ?? null,
41
+ customer_name: customerName,
42
+ },
43
+ });
44
+ return res.status(200).json({
45
+ token: result.token,
46
+ expires_at: result.expires_at,
47
+ is_new_user: isNewUser,
48
+ });
49
+ };
50
+ exports.POST = POST;
51
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvY3VzdG9tZXIvZW1haWxvdHAvc2VuZC9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFDQSxxREFBa0Y7QUFDbEYsa0RBSThCO0FBQzlCLDhGQUFpRztBQUVqRyx5SEFBNEY7QUFDNUYsNEVBQTJFO0FBQzNFLHFFQUdxQztBQUU5QixNQUFNLElBQUksR0FBRyxLQUFLLEVBQUUsR0FBa0IsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDcEUsTUFBTSxZQUFZLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsYUFBYSxDQUFDLENBQUE7SUFDL0UsTUFBTSxPQUFPLEdBQUcsSUFBQSwyQ0FBa0MsRUFDaEQsWUFBaUMsQ0FDbEMsQ0FBQTtJQUVELElBQUksQ0FBQyxJQUFBLDhCQUFxQixFQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDcEMsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFDN0IseUNBQXlDLENBQzFDLENBQUE7SUFDSCxDQUFDO0lBRUQsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLElBQTBCLENBQUE7SUFDM0MsTUFBTSxRQUFRLEdBQUcsSUFBSSxFQUFFLEtBQUssQ0FBQTtJQUU1QixJQUFJLENBQUMsUUFBUSxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzlDLE1BQU0sSUFBSSxtQkFBVyxDQUFDLG1CQUFXLENBQUMsS0FBSyxDQUFDLFlBQVksRUFBRSxtQkFBbUIsQ0FBQyxDQUFBO0lBQzVFLENBQUM7SUFFRCxJQUFBLHNDQUFtQixFQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQzdCLE1BQU0sS0FBSyxHQUFHLElBQUEsdUNBQWtCLEVBQUMsUUFBUSxDQUFDLENBQUE7SUFFMUMsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLElBQUEsMENBQXFCLEVBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQTtJQUN0RSxNQUFNLFNBQVMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLFdBQVcsQ0FBQTtJQUVoRCxJQUFJLGdCQUFnQixFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQ3pCLE1BQU0sc0JBQXNCLEdBQzFCLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUNmLDBEQUErQixDQUNoQyxDQUFBO1FBQ0gsSUFBSSxNQUFNLHNCQUFzQixDQUFDLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFDeEUsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFDN0IsNkNBQTZDLENBQzlDLENBQUE7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sWUFBWSxHQUNoQixnQkFBZ0IsRUFBRSxVQUFVO1FBQzVCLGdCQUFnQixFQUFFLEtBQUs7UUFDdkIsS0FBSyxDQUFBO0lBRVAsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sSUFBQSxzQ0FBd0IsRUFBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQy9ELEtBQUssRUFBRTtZQUNMLEtBQUs7WUFDTCxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsRUFBRSxJQUFJLElBQUk7WUFDekMsYUFBYSxFQUFFLFlBQVk7U0FDNUI7S0FDRixDQUFDLENBQUE7SUFFRixPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQzFCLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSztRQUNuQixVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVU7UUFDN0IsV0FBVyxFQUFFLFNBQVM7S0FDdkIsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFBO0FBekRZLFFBQUEsSUFBSSxRQXlEaEIifQ==
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeAuthEmail = normalizeAuthEmail;
4
+ exports.lookupCustomerByEmail = lookupCustomerByEmail;
5
+ exports.findAnyAuthIdentityIdByEmail = findAnyAuthIdentityIdByEmail;
6
+ exports.findAuthIdentityIdByEmail = findAuthIdentityIdByEmail;
7
+ const utils_1 = require("@medusajs/framework/utils");
8
+ function firstKnexRow(result) {
9
+ const fromRows = result.rows?.[0];
10
+ if (fromRows && typeof fromRows === "object" && !Array.isArray(fromRows)) {
11
+ return fromRows;
12
+ }
13
+ const batch = result[0];
14
+ if (Array.isArray(batch)) {
15
+ const first = batch[0];
16
+ if (first && typeof first === "object" && !Array.isArray(first)) {
17
+ return first;
18
+ }
19
+ }
20
+ return undefined;
21
+ }
22
+ function normalizeAuthEmail(email) {
23
+ return email.toLowerCase().trim();
24
+ }
25
+ async function lookupCustomerByEmail(scope, email) {
26
+ const knex = scope.resolve(utils_1.ContainerRegistrationKeys.PG_CONNECTION);
27
+ const normalized = normalizeAuthEmail(email);
28
+ const result = await knex.raw(`SELECT id, email, has_account, first_name, last_name
29
+ FROM customer
30
+ WHERE lower(email) = lower(?)
31
+ ORDER BY created_at DESC
32
+ LIMIT 1`, [normalized]);
33
+ const row = firstKnexRow(result);
34
+ if (!row?.id) {
35
+ return null;
36
+ }
37
+ return row;
38
+ }
39
+ async function findAnyAuthIdentityIdByEmail(scope, email) {
40
+ const knex = scope.resolve(utils_1.ContainerRegistrationKeys.PG_CONNECTION);
41
+ const normalized = normalizeAuthEmail(email);
42
+ const result = await knex.raw(`SELECT pi.auth_identity_id
43
+ FROM provider_identity pi
44
+ WHERE lower(pi.entity_id) = lower(?)
45
+ ORDER BY pi.created_at DESC
46
+ LIMIT 1`, [normalized]);
47
+ const row = firstKnexRow(result);
48
+ return row?.auth_identity_id ?? null;
49
+ }
50
+ async function findAuthIdentityIdByEmail(scope, email) {
51
+ const knex = scope.resolve(utils_1.ContainerRegistrationKeys.PG_CONNECTION);
52
+ const normalized = normalizeAuthEmail(email);
53
+ const result = await knex.raw(`SELECT pi.auth_identity_id
54
+ FROM provider_identity pi
55
+ WHERE lower(pi.entity_id) = lower(?)
56
+ AND pi.provider IN ('emailpass', 'emailotp')
57
+ ORDER BY pi.created_at DESC
58
+ LIMIT 1`, [normalized]);
59
+ const row = firstKnexRow(result);
60
+ return row?.auth_identity_id ?? null;
61
+ }
62
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW1haWwtYXV0aC1oZWxwZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwaS9hdXRoL2N1c3RvbWVyL2VtYWlsb3RwL3NoYXJlZC9lbWFpbC1hdXRoLWhlbHBlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUE0QkEsZ0RBRUM7QUFFRCxzREEwQkM7QUFFRCxvRUF1QkM7QUFFRCw4REF3QkM7QUE1R0QscURBQXFFO0FBVXJFLFNBQVMsWUFBWSxDQUNuQixNQUFtQztJQUVuQyxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDakMsSUFBSSxRQUFRLElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1FBQ3pFLE9BQU8sUUFBUSxDQUFBO0lBQ2pCLENBQUM7SUFDRCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDdkIsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDekIsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3RCLElBQUksS0FBSyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNoRSxPQUFPLEtBQVUsQ0FBQTtRQUNuQixDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sU0FBUyxDQUFBO0FBQ2xCLENBQUM7QUFFRCxTQUFnQixrQkFBa0IsQ0FBQyxLQUFhO0lBQzlDLE9BQU8sS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFBO0FBQ25DLENBQUM7QUFFTSxLQUFLLFVBQVUscUJBQXFCLENBQ3pDLEtBQXNCLEVBQ3RCLEtBQWE7SUFFYixNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLGFBQWEsQ0FLakUsQ0FBQTtJQUVELE1BQU0sVUFBVSxHQUFHLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQzVDLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FDM0I7Ozs7YUFJUyxFQUNULENBQUMsVUFBVSxDQUFDLENBQ2IsQ0FBQTtJQUVELE1BQU0sR0FBRyxHQUFHLFlBQVksQ0FBc0IsTUFBTSxDQUFDLENBQUE7SUFDckQsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLEVBQUUsQ0FBQztRQUNiLE9BQU8sSUFBSSxDQUFBO0lBQ2IsQ0FBQztJQUNELE9BQU8sR0FBRyxDQUFBO0FBQ1osQ0FBQztBQUVNLEtBQUssVUFBVSw0QkFBNEIsQ0FDaEQsS0FBc0IsRUFDdEIsS0FBYTtJQUViLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsYUFBYSxDQUtqRSxDQUFBO0lBRUQsTUFBTSxVQUFVLEdBQUcsa0JBQWtCLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDNUMsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUMzQjs7OzthQUlTLEVBQ1QsQ0FBQyxVQUFVLENBQUMsQ0FDYixDQUFBO0lBRUQsTUFBTSxHQUFHLEdBQUcsWUFBWSxDQUFnQyxNQUFNLENBQUMsQ0FBQTtJQUMvRCxPQUFPLEdBQUcsRUFBRSxnQkFBZ0IsSUFBSSxJQUFJLENBQUE7QUFDdEMsQ0FBQztBQUVNLEtBQUssVUFBVSx5QkFBeUIsQ0FDN0MsS0FBc0IsRUFDdEIsS0FBYTtJQUViLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsYUFBYSxDQUtqRSxDQUFBO0lBRUQsTUFBTSxVQUFVLEdBQUcsa0JBQWtCLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDNUMsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUMzQjs7Ozs7YUFLUyxFQUNULENBQUMsVUFBVSxDQUFDLENBQ2IsQ0FBQTtJQUVELE1BQU0sR0FBRyxHQUFHLFlBQVksQ0FBZ0MsTUFBTSxDQUFDLENBQUE7SUFDL0QsT0FBTyxHQUFHLEVBQUUsZ0JBQWdCLElBQUksSUFBSSxDQUFBO0FBQ3RDLENBQUMifQ==
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.POST = void 0;
7
+ const utils_1 = require("@medusajs/framework/utils");
8
+ const config_1 = require("../../../../../config");
9
+ const otp_verification_1 = require("../../../../../modules/otp-verification");
10
+ const verify_email_auth_otp_workflow_1 = __importDefault(require("../../../../../workflows/verify-email-auth-otp-workflow"));
11
+ const referral_code_1 = require("../../../../store/customers/shared/referral-code");
12
+ const complete_customer_login_1 = require("../../shared/complete-customer-login");
13
+ const POST = async (req, res) => {
14
+ const configModule = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
15
+ const config = configModule;
16
+ const options = (0, config_1.resolveCustomerRegistrationOptions)(config);
17
+ if (!(0, config_1.isEmailOtpAuthEnabled)(options)) {
18
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "Email OTP authentication is not enabled");
19
+ }
20
+ const body = req.body;
21
+ if (!body?.token) {
22
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "token is required");
23
+ }
24
+ if (!body?.code) {
25
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "code is required");
26
+ }
27
+ await (0, referral_code_1.assertReferralCodeReferrerExists)(req);
28
+ const jwtSecret = config.projectConfig?.http?.jwtSecret || "supersecret";
29
+ const otpService = req.scope.resolve(otp_verification_1.OTP_VERIFICATION_MODULE);
30
+ const verifyResult = await otpService.verifyEmailAuthOtp({ token: body.token, code: body.code }, jwtSecret);
31
+ const { result } = await (0, verify_email_auth_otp_workflow_1.default)(req.scope).run({
32
+ input: {
33
+ email: verifyResult.email,
34
+ customer_id: verifyResult.customer_id,
35
+ first_name: body.first_name,
36
+ last_name: body.last_name,
37
+ },
38
+ });
39
+ const customerId = typeof result.customer.id === "string" ? result.customer.id : "";
40
+ if (!customerId) {
41
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, "Customer id missing after email OTP verification");
42
+ }
43
+ if (result.is_new_user) {
44
+ await (0, referral_code_1.maybeCreateReferralLinkFromRequest)(req, customerId);
45
+ }
46
+ const token = await (0, complete_customer_login_1.issueCustomerJwtToken)(req, config, result.auth_identity, customerId);
47
+ return res.status(200).json({
48
+ token,
49
+ customer: result.customer,
50
+ is_new_user: result.is_new_user,
51
+ });
52
+ };
53
+ exports.POST = POST;
54
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2F1dGgvY3VzdG9tZXIvZW1haWxvdHAvdmVyaWZ5L3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUNBLHFEQUFrRjtBQUNsRixrREFJOEI7QUFDOUIsOEVBQWlGO0FBRWpGLDZIQUFnRztBQUNoRyxvRkFHeUQ7QUFDekQsa0ZBRzZDO0FBRXRDLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFBRSxHQUFrQixFQUFFLEdBQW1CLEVBQUUsRUFBRTtJQUNwRSxNQUFNLFlBQVksR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxhQUFhLENBQUMsQ0FBQTtJQUMvRSxNQUFNLE1BQU0sR0FBRyxZQUFzRCxDQUFBO0lBQ3JFLE1BQU0sT0FBTyxHQUFHLElBQUEsMkNBQWtDLEVBQUMsTUFBTSxDQUFDLENBQUE7SUFFMUQsSUFBSSxDQUFDLElBQUEsOEJBQXFCLEVBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNwQyxNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUM3Qix5Q0FBeUMsQ0FDMUMsQ0FBQTtJQUNILENBQUM7SUFFRCxNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsSUFNaEIsQ0FBQTtJQUVELElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDakIsTUFBTSxJQUFJLG1CQUFXLENBQUMsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLG1CQUFtQixDQUFDLENBQUE7SUFDNUUsQ0FBQztJQUVELElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFDaEIsTUFBTSxJQUFJLG1CQUFXLENBQUMsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLGtCQUFrQixDQUFDLENBQUE7SUFDM0UsQ0FBQztJQUVELE1BQU0sSUFBQSxnREFBZ0MsRUFBQyxHQUFHLENBQUMsQ0FBQTtJQUUzQyxNQUFNLFNBQVMsR0FDWixNQUFNLENBQUMsYUFBYSxFQUFFLElBQUksRUFBRSxTQUFnQyxJQUFJLGFBQWEsQ0FBQTtJQUVoRixNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FDbEMsMENBQXVCLENBQ3hCLENBQUE7SUFFRCxNQUFNLFlBQVksR0FBRyxNQUFNLFVBQVUsQ0FBQyxrQkFBa0IsQ0FDdEQsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxFQUN0QyxTQUFTLENBQ1YsQ0FBQTtJQUVELE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxNQUFNLElBQUEsd0NBQTBCLEVBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUNqRSxLQUFLLEVBQUU7WUFDTCxLQUFLLEVBQUUsWUFBWSxDQUFDLEtBQUs7WUFDekIsV0FBVyxFQUFFLFlBQVksQ0FBQyxXQUFXO1lBQ3JDLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVTtZQUMzQixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7U0FDMUI7S0FDRixDQUFDLENBQUE7SUFFRixNQUFNLFVBQVUsR0FDZCxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtJQUVsRSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDaEIsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUNsQyxrREFBa0QsQ0FDbkQsQ0FBQTtJQUNILENBQUM7SUFFRCxJQUFJLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN2QixNQUFNLElBQUEsa0RBQWtDLEVBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxDQUFBO0lBQzNELENBQUM7SUFFRCxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUEsK0NBQXFCLEVBQ3ZDLEdBQUcsRUFDSCxNQUFNLEVBQ04sTUFBTSxDQUFDLGFBQWEsRUFDcEIsVUFBVSxDQUNYLENBQUE7SUFFRCxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQzFCLEtBQUs7UUFDTCxRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVE7UUFDekIsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXO0tBQ2hDLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FBQTtBQTdFWSxRQUFBLElBQUksUUE2RWhCIn0=