@hartl-services/medusa-base 1.1.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/src/admin/index.js +3 -1
- package/.medusa/server/src/admin/index.mjs +3 -1
- package/.medusa/server/src/api/customer-verification-request-throttle.js +50 -0
- package/.medusa/server/src/api/middlewares.js +31 -1
- package/.medusa/server/src/api/store/customer-verification/resend/route.js +17 -0
- package/.medusa/server/src/documents/utils/document-merchant.js +5 -5
- package/.medusa/server/src/email/application/handle-customer-verification-event.js +341 -0
- package/.medusa/server/src/email/application/resend-customer-verification.js +65 -0
- package/.medusa/server/src/email/application/start-customer-verification-snapshot.js +21 -0
- package/.medusa/server/src/email/application/throttle-verification-request.js +49 -0
- package/.medusa/server/src/email/customer-verification-snapshot.js +144 -0
- package/.medusa/server/src/email/domain/business-keys.js +12 -2
- package/.medusa/server/src/email/domain/customer-verification-resend.js +37 -0
- package/.medusa/server/src/email/domain/event-schemas.js +18 -2
- package/.medusa/server/src/email/plugin-features.js +9 -2
- package/.medusa/server/src/email/rendering/default-templates.js +20 -1
- package/.medusa/server/src/email/rendering/resolve-shop-configuration.js +5 -1
- package/.medusa/server/src/email/types/email-kinds.js +14 -2
- package/.medusa/server/src/email/types/template-data.js +9 -1
- package/.medusa/server/src/modules/documents/domain/merchant.js +2 -33
- package/.medusa/server/src/modules/documents/domain/options.js +1 -7
- package/.medusa/server/src/modules/email/migrations/Migration20261001090000.js +16 -0
- package/.medusa/server/src/modules/email/service.js +30 -8
- package/.medusa/server/src/public/shop-master-data.js +6 -6
- package/.medusa/server/src/shop-config/build-food-shop-config.js +17 -6
- package/.medusa/server/src/shop-config/options.js +1 -15
- package/.medusa/server/src/subscribers/customer-verification.js +23 -0
- package/.medusa/server/src/workflows/documents/issue-cancellation-after-refund.js +2 -3
- package/.medusa/server/src/workflows/documents/issue-document.js +3 -4
- package/.medusa/server/src/workflows/documents/issue-packing-list.js +2 -2
- package/.medusa/server/src/workflows/email/dispatch-email-message.js +4 -2
- package/README.md +154 -49
- package/dist/documents/types/documents.d.ts +0 -22
- package/dist/email/customer-verification-snapshot.d.ts +53 -0
- package/dist/email/customer-verification-snapshot.js +143 -0
- package/dist/email/types/email-kinds.d.ts +9 -1
- package/dist/email/types/email-kinds.js +13 -1
- package/dist/email/types/shop-configuration.d.ts +8 -0
- package/dist/email/types/template-data.d.ts +9 -0
- package/dist/email/types/template-data.js +8 -0
- package/dist/modules/documents/domain/options.d.ts +1 -9
- package/dist/modules/documents/domain/options.js +0 -6
- package/dist/public/shop-master-data.d.ts +4 -5
- package/dist/public/shop-master-data.js +5 -5
- package/dist/shop-config/build-food-shop-config.js +16 -5
- package/dist/shop-config/options.d.ts +4 -6
- package/dist/shop-config/options.js +0 -14
- package/package.json +2 -2
- package/dist/modules/documents/domain/merchant.d.ts +0 -22
- package/dist/modules/documents/domain/merchant.js +0 -85
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resendCustomerVerification = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const core_flows_1 = require("@medusajs/medusa/core-flows");
|
|
6
|
+
const customer_verification_resend_1 = require("../domain/customer-verification-resend");
|
|
7
|
+
/**
|
|
8
|
+
* Requests a new confirmation mail for the customer account registered with
|
|
9
|
+
* `email`, if there is one that is not confirmed yet and was not asked for
|
|
10
|
+
* within the last minute. The caller answers the same way in every case, so
|
|
11
|
+
* the result is for tests and logs only. A failure is logged with a fixed
|
|
12
|
+
* message and the error's class only (its text can carry the address, a
|
|
13
|
+
* unique-index error does) and not rethrown: an error for existing accounts
|
|
14
|
+
* only would reveal them.
|
|
15
|
+
*/
|
|
16
|
+
const resendCustomerVerification = async (container, email, now = new Date()) => {
|
|
17
|
+
let requested = 0;
|
|
18
|
+
try {
|
|
19
|
+
const auth = container.resolve(utils_1.Modules.AUTH);
|
|
20
|
+
const providerIdentities = (await Promise.all((0, customer_verification_resend_1.verificationLookupEmails)(email).map((lookupEmail) => auth.listProviderIdentities({ provider: "emailpass", entity_id: lookupEmail }, { relations: ["auth_identity"], take: 1 })))).flat();
|
|
21
|
+
for (const providerIdentity of providerIdentities) {
|
|
22
|
+
const authIdentity = providerIdentity.auth_identity;
|
|
23
|
+
const customerId = authIdentity?.app_metadata?.customer_id;
|
|
24
|
+
// Admin users and identities no customer claimed get no mail.
|
|
25
|
+
if (!authIdentity || typeof customerId !== "string" || !customerId) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const [verification] = await auth.listAuthVerifications({
|
|
29
|
+
auth_identity_id: authIdentity.id,
|
|
30
|
+
entity_id: providerIdentity.entity_id,
|
|
31
|
+
entity_type: "email",
|
|
32
|
+
}, { take: 1 });
|
|
33
|
+
if ((0, customer_verification_resend_1.decideCustomerVerificationResend)({
|
|
34
|
+
now,
|
|
35
|
+
verification: verification ?? null,
|
|
36
|
+
}) !== "request") {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
await (0, core_flows_1.requestVerificationWorkflow)(container).run({
|
|
40
|
+
input: {
|
|
41
|
+
auth_identity_id: authIdentity.id,
|
|
42
|
+
entity_id: providerIdentity.entity_id,
|
|
43
|
+
entity_type: "email",
|
|
44
|
+
code_provider: "token",
|
|
45
|
+
metadata: {},
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
requested += 1;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
try {
|
|
53
|
+
container
|
|
54
|
+
.resolve(utils_1.ContainerRegistrationKeys.LOGGER)
|
|
55
|
+
.error(`Customer verification could not be requested again (${error instanceof Error ? error.name : "unknown error"}).`);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// The caller runs detached: a broken logger must not become an
|
|
59
|
+
// unhandled rejection.
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return { requested };
|
|
63
|
+
};
|
|
64
|
+
exports.resendCustomerVerification = resendCustomerVerification;
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzZW5kLWN1c3RvbWVyLXZlcmlmaWNhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9lbWFpbC9hcHBsaWNhdGlvbi9yZXNlbmQtY3VzdG9tZXItdmVyaWZpY2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUtBLHFEQUErRTtBQUMvRSw0REFBMEU7QUFFMUUseUZBR2dEO0FBT2hEOzs7Ozs7OztHQVFHO0FBQ0ksTUFBTSwwQkFBMEIsR0FBRyxLQUFLLEVBQzdDLFNBQTBCLEVBQzFCLEtBQWEsRUFDYixNQUFZLElBQUksSUFBSSxFQUFFLEVBQ3FCLEVBQUU7SUFDN0MsSUFBSSxTQUFTLEdBQUcsQ0FBQyxDQUFDO0lBQ2xCLElBQUksQ0FBQztRQUNILE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQXFCLGVBQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNqRSxNQUFNLGtCQUFrQixHQUFHLENBQ3pCLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FDZixJQUFBLHVEQUF3QixFQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQ2xELElBQUksQ0FBQyxzQkFBc0IsQ0FDekIsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsRUFDakQsRUFBRSxTQUFTLEVBQUUsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQzFDLENBQ0YsQ0FDRixDQUNGLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDVCxLQUFLLE1BQU0sZ0JBQWdCLElBQUksa0JBQWtCLEVBQUUsQ0FBQztZQUNsRCxNQUFNLFlBQVksR0FBRyxnQkFBZ0IsQ0FBQyxhQUFhLENBQUM7WUFDcEQsTUFBTSxVQUFVLEdBQ2QsWUFBWSxFQUFFLFlBQ2YsRUFBRSxXQUFXLENBQUM7WUFDZiw4REFBOEQ7WUFDOUQsSUFBSSxDQUFDLFlBQVksSUFBSSxPQUFPLFVBQVUsS0FBSyxRQUFRLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDbkUsU0FBUztZQUNYLENBQUM7WUFDRCxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQ3JEO2dCQUNFLGdCQUFnQixFQUFFLFlBQVksQ0FBQyxFQUFFO2dCQUNqQyxTQUFTLEVBQUUsZ0JBQWdCLENBQUMsU0FBUztnQkFDckMsV0FBVyxFQUFFLE9BQU87YUFDckIsRUFDRCxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FDWixDQUFDO1lBQ0YsSUFDRSxJQUFBLCtEQUFnQyxFQUFDO2dCQUMvQixHQUFHO2dCQUNILFlBQVksRUFBRSxZQUFZLElBQUksSUFBSTthQUNuQyxDQUFDLEtBQUssU0FBUyxFQUNoQixDQUFDO2dCQUNELFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxJQUFBLHdDQUEyQixFQUFDLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztnQkFDL0MsS0FBSyxFQUFFO29CQUNMLGdCQUFnQixFQUFFLFlBQVksQ0FBQyxFQUFFO29CQUNqQyxTQUFTLEVBQUUsZ0JBQWdCLENBQUMsU0FBUztvQkFDckMsV0FBVyxFQUFFLE9BQU87b0JBQ3BCLGFBQWEsRUFBRSxPQUFPO29CQUN0QixRQUFRLEVBQUUsRUFBRTtpQkFDYjthQUNGLENBQUMsQ0FBQztZQUNILFNBQVMsSUFBSSxDQUFDLENBQUM7UUFDakIsQ0FBQztJQUNILENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsSUFBSSxDQUFDO1lBQ0gsU0FBUztpQkFDTixPQUFPLENBQVMsaUNBQXlCLENBQUMsTUFBTSxDQUFDO2lCQUNqRCxLQUFLLENBQ0osdURBQ0UsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsZUFDeEMsSUFBSSxDQUNMLENBQUM7UUFDTixDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsK0RBQStEO1lBQy9ELHVCQUF1QjtRQUN6QixDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sRUFBRSxTQUFTLEVBQUUsQ0FBQztBQUN2QixDQUFDLENBQUM7QUFyRVcsUUFBQSwwQkFBMEIsOEJBcUVyQyJ9
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startCustomerVerification = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const public_1 = require("../../public");
|
|
6
|
+
const customer_verification_snapshot_1 = require("../customer-verification-snapshot");
|
|
7
|
+
const plugin_features_1 = require("../plugin-features");
|
|
8
|
+
/**
|
|
9
|
+
* Hands the snapshot behind `authVerificationsPerActor` its reader (the
|
|
10
|
+
* effective `customer_verification` toggle) and loads it once. Called when
|
|
11
|
+
* the application has started, with the application container: the config
|
|
12
|
+
* getter that needs the toggle has no container of its own.
|
|
13
|
+
*/
|
|
14
|
+
const startCustomerVerification = (container) => (0, customer_verification_snapshot_1.startCustomerVerificationSnapshot)({
|
|
15
|
+
read: () => (0, public_1.isPluginFeatureEnabled)(container, plugin_features_1.emailPluginFeatures, "account_mails", "customer_verification"),
|
|
16
|
+
warn: (message) => container
|
|
17
|
+
.resolve(utils_1.ContainerRegistrationKeys.LOGGER)
|
|
18
|
+
.warn(message),
|
|
19
|
+
});
|
|
20
|
+
exports.startCustomerVerification = startCustomerVerification;
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnQtY3VzdG9tZXItdmVyaWZpY2F0aW9uLXNuYXBzaG90LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2VtYWlsL2FwcGxpY2F0aW9uL3N0YXJ0LWN1c3RvbWVyLXZlcmlmaWNhdGlvbi1zbmFwc2hvdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxREFBc0U7QUFFdEUseUNBQXNEO0FBQ3RELHNGQUFzRjtBQUN0Rix3REFBeUQ7QUFFekQ7Ozs7O0dBS0c7QUFDSSxNQUFNLHlCQUF5QixHQUFHLENBQ3ZDLFNBQTBCLEVBQ1gsRUFBRSxDQUNqQixJQUFBLGtFQUFpQyxFQUFDO0lBQ2hDLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FDVCxJQUFBLCtCQUFzQixFQUNwQixTQUFTLEVBQ1QscUNBQW1CLEVBQ25CLGVBQWUsRUFDZix1QkFBdUIsQ0FDeEI7SUFDSCxJQUFJLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUNoQixTQUFTO1NBQ04sT0FBTyxDQUFTLGlDQUF5QixDQUFDLE1BQU0sQ0FBQztTQUNqRCxJQUFJLENBQUMsT0FBTyxDQUFDO0NBQ25CLENBQUMsQ0FBQztBQWZRLFFBQUEseUJBQXlCLDZCQWVqQyJ9
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findThrottledVerificationRequest = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const customer_verification_resend_1 = require("../domain/customer-verification-resend");
|
|
6
|
+
/**
|
|
7
|
+
* `POST /auth/verification/request` is Medusa's own route and the storefront
|
|
8
|
+
* calls it at every blocked login. Whether the request must be answered
|
|
9
|
+
* without sending a mail: for the identity's own e-mail address of a customer
|
|
10
|
+
* account whose last request is younger than the resend interval. Anything
|
|
11
|
+
* else (another actor, a foreign address, no row, a confirmed address) is
|
|
12
|
+
* left to Medusa. Never answers with the token hash Medusa stores in
|
|
13
|
+
* `provider_metadata`.
|
|
14
|
+
*/
|
|
15
|
+
const findThrottledVerificationRequest = async (container, input, now = new Date()) => {
|
|
16
|
+
const auth = container.resolve(utils_1.Modules.AUTH);
|
|
17
|
+
const identity = await auth.retrieveAuthIdentity(input.authIdentityId, {
|
|
18
|
+
select: ["id", "app_metadata"],
|
|
19
|
+
relations: ["provider_identities"],
|
|
20
|
+
});
|
|
21
|
+
const customerId = identity.app_metadata
|
|
22
|
+
?.customer_id;
|
|
23
|
+
const ownsAddress = (identity.provider_identities ?? []).some((providerIdentity) => providerIdentity.provider === "emailpass" &&
|
|
24
|
+
providerIdentity.entity_id === input.entityId);
|
|
25
|
+
if (!ownsAddress || typeof customerId !== "string" || !customerId) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const [verification] = await auth.listAuthVerifications({
|
|
29
|
+
auth_identity_id: identity.id,
|
|
30
|
+
entity_id: input.entityId,
|
|
31
|
+
entity_type: "email",
|
|
32
|
+
}, { take: 1 });
|
|
33
|
+
if (!verification ||
|
|
34
|
+
(0, customer_verification_resend_1.decideCustomerVerificationResend)({ now, verification }) !== "throttled") {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
auth_identity_id: identity.id,
|
|
39
|
+
code_provider: verification.code_provider,
|
|
40
|
+
entity_id: verification.entity_id,
|
|
41
|
+
entity_type: verification.entity_type,
|
|
42
|
+
id: verification.id,
|
|
43
|
+
metadata: verification.metadata ?? null,
|
|
44
|
+
requested_at: verification.requested_at,
|
|
45
|
+
verified_at: verification.verified_at ?? null,
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
exports.findThrottledVerificationRequest = findThrottledVerificationRequest;
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGhyb3R0bGUtdmVyaWZpY2F0aW9uLXJlcXVlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvZW1haWwvYXBwbGljYXRpb24vdGhyb3R0bGUtdmVyaWZpY2F0aW9uLXJlcXVlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEscURBQW9EO0FBRXBELHlGQUEwRjtBQWMxRjs7Ozs7Ozs7R0FRRztBQUNJLE1BQU0sZ0NBQWdDLEdBQUcsS0FBSyxFQUNuRCxTQUEwQixFQUMxQixLQUdFLEVBQ0YsTUFBWSxJQUFJLElBQUksRUFBRSxFQUNpQixFQUFFO0lBQ3pDLE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQXFCLGVBQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNqRSxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLENBQUMsY0FBYyxFQUFFO1FBQ3JFLE1BQU0sRUFBRSxDQUFDLElBQUksRUFBRSxjQUFjLENBQUM7UUFDOUIsU0FBUyxFQUFFLENBQUMscUJBQXFCLENBQUM7S0FDbkMsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxVQUFVLEdBQUksUUFBUSxDQUFDLFlBQStDO1FBQzFFLEVBQUUsV0FBVyxDQUFDO0lBQ2hCLE1BQU0sV0FBVyxHQUFHLENBQUMsUUFBUSxDQUFDLG1CQUFtQixJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FDM0QsQ0FBQyxnQkFBZ0IsRUFBRSxFQUFFLENBQ25CLGdCQUFnQixDQUFDLFFBQVEsS0FBSyxXQUFXO1FBQ3pDLGdCQUFnQixDQUFDLFNBQVMsS0FBSyxLQUFLLENBQUMsUUFBUSxDQUNoRCxDQUFDO0lBQ0YsSUFBSSxDQUFDLFdBQVcsSUFBSSxPQUFPLFVBQVUsS0FBSyxRQUFRLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNsRSxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFDRCxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQ3JEO1FBQ0UsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLEVBQUU7UUFDN0IsU0FBUyxFQUFFLEtBQUssQ0FBQyxRQUFRO1FBQ3pCLFdBQVcsRUFBRSxPQUFPO0tBQ3JCLEVBQ0QsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQ1osQ0FBQztJQUNGLElBQ0UsQ0FBQyxZQUFZO1FBQ2IsSUFBQSwrREFBZ0MsRUFBQyxFQUFFLEdBQUcsRUFBRSxZQUFZLEVBQUUsQ0FBQyxLQUFLLFdBQVcsRUFDdkUsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUNELE9BQU87UUFDTCxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsRUFBRTtRQUM3QixhQUFhLEVBQUUsWUFBWSxDQUFDLGFBQWE7UUFDekMsU0FBUyxFQUFFLFlBQVksQ0FBQyxTQUFTO1FBQ2pDLFdBQVcsRUFBRSxZQUFZLENBQUMsV0FBVztRQUNyQyxFQUFFLEVBQUUsWUFBWSxDQUFDLEVBQVk7UUFDN0IsUUFBUSxFQUFFLFlBQVksQ0FBQyxRQUFRLElBQUksSUFBSTtRQUN2QyxZQUFZLEVBQUUsWUFBWSxDQUFDLFlBQVk7UUFDdkMsV0FBVyxFQUFFLFlBQVksQ0FBQyxXQUFXLElBQUksSUFBSTtLQUM5QyxDQUFDO0FBQ0osQ0FBQyxDQUFDO0FBL0NXLFFBQUEsZ0NBQWdDLG9DQStDM0MifQ==
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setCustomerVerificationEnabledForTests = exports.customerVerificationActors = exports.isCustomerVerificationEnabled = exports.startCustomerVerificationSnapshot = exports.stopCustomerVerificationSnapshot = exports.refreshCustomerVerificationSnapshot = exports.CUSTOMER_VERIFICATION_REFRESH_MS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* In-memory copy of the effective `customer_verification` toggle for the one
|
|
6
|
+
* place that cannot await it: Medusa reads
|
|
7
|
+
* `projectConfig.http.authVerificationsPerActor.customer` synchronously on
|
|
8
|
+
* every login. The shop preset puts `customerVerificationActors()` behind a
|
|
9
|
+
* getter there, so a toggle change in the Admin takes effect without a
|
|
10
|
+
* restart.
|
|
11
|
+
*
|
|
12
|
+
* - Boot: `startCustomerVerificationSnapshot` loads the toggle once.
|
|
13
|
+
* - Afterwards an unref'd timer refreshes every 30 s, so a change reaches an
|
|
14
|
+
* idle instance too. A read that finds the copy older than 30 s (a blocked
|
|
15
|
+
* timer, say) also starts one refresh in the background
|
|
16
|
+
* (stale-while-revalidate) and still answers from the copy. A change thus
|
|
17
|
+
* reaches a running instance within about 30 s plus the duration of the
|
|
18
|
+
* read.
|
|
19
|
+
* - A failed read keeps the last value (initially "off") and is logged; the
|
|
20
|
+
* next attempt waits another 30 s.
|
|
21
|
+
*
|
|
22
|
+
* The state lives on `globalThis`: the preset (`dist`) and the Medusa-loaded
|
|
23
|
+
* plugin code (`.medusa/server`) are compiled separately and would otherwise
|
|
24
|
+
* each hold their own copy. Login is not on the cart path.
|
|
25
|
+
*/
|
|
26
|
+
exports.CUSTOMER_VERIFICATION_REFRESH_MS = 30_000;
|
|
27
|
+
const STATE_KEY = Symbol.for("@hartl-services/medusa-base/customer-verification-snapshot");
|
|
28
|
+
const state = () => {
|
|
29
|
+
const holder = globalThis;
|
|
30
|
+
holder[STATE_KEY] ??= {
|
|
31
|
+
enabled: false,
|
|
32
|
+
refreshedAt: null,
|
|
33
|
+
refreshing: null,
|
|
34
|
+
timer: null,
|
|
35
|
+
read: null,
|
|
36
|
+
warn: null,
|
|
37
|
+
};
|
|
38
|
+
return holder[STATE_KEY];
|
|
39
|
+
};
|
|
40
|
+
const logFailure = (current, error) => {
|
|
41
|
+
try {
|
|
42
|
+
current.warn?.(`Customer verification toggle could not be read, keeping "${current.enabled ? "on" : "off"}": ${error instanceof Error ? error.message : "unknown error"}`);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// A broken logger must not turn a failed refresh into a throw.
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
/** Reads the toggle once; never rejects. Concurrent calls share one read. */
|
|
49
|
+
const refreshCustomerVerificationSnapshot = () => {
|
|
50
|
+
const current = state();
|
|
51
|
+
if (!current.read) {
|
|
52
|
+
return Promise.resolve();
|
|
53
|
+
}
|
|
54
|
+
if (current.refreshing) {
|
|
55
|
+
return current.refreshing;
|
|
56
|
+
}
|
|
57
|
+
const read = current.read;
|
|
58
|
+
// Started from a microtask so the assignment below always precedes `finally`.
|
|
59
|
+
const refreshing = Promise.resolve().then(async () => {
|
|
60
|
+
try {
|
|
61
|
+
current.enabled = (await read()) === true;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
logFailure(current, error);
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
current.refreshedAt = Date.now();
|
|
68
|
+
current.refreshing = null;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
current.refreshing = refreshing;
|
|
72
|
+
return refreshing;
|
|
73
|
+
};
|
|
74
|
+
exports.refreshCustomerVerificationSnapshot = refreshCustomerVerificationSnapshot;
|
|
75
|
+
const stopTimer = (current) => {
|
|
76
|
+
if (current.timer) {
|
|
77
|
+
clearInterval(current.timer);
|
|
78
|
+
current.timer = null;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
/** Stops the periodic refresh (application shutdown). The value stays. */
|
|
82
|
+
const stopCustomerVerificationSnapshot = () => {
|
|
83
|
+
stopTimer(state());
|
|
84
|
+
};
|
|
85
|
+
exports.stopCustomerVerificationSnapshot = stopCustomerVerificationSnapshot;
|
|
86
|
+
/**
|
|
87
|
+
* Registers the reader, loads the toggle once and keeps it fresh every 30 s
|
|
88
|
+
* (application start). `read` returns the effective toggle; `warn` is the
|
|
89
|
+
* container logger. Starting again replaces the reader and the timer.
|
|
90
|
+
*/
|
|
91
|
+
const startCustomerVerificationSnapshot = (input) => {
|
|
92
|
+
const current = state();
|
|
93
|
+
current.read = input.read;
|
|
94
|
+
current.warn = input.warn;
|
|
95
|
+
stopTimer(current);
|
|
96
|
+
current.timer = setInterval(() => {
|
|
97
|
+
void (0, exports.refreshCustomerVerificationSnapshot)();
|
|
98
|
+
}, exports.CUSTOMER_VERIFICATION_REFRESH_MS);
|
|
99
|
+
// An idle timer must not keep the process (or a test run) alive.
|
|
100
|
+
current.timer.unref();
|
|
101
|
+
return (0, exports.refreshCustomerVerificationSnapshot)();
|
|
102
|
+
};
|
|
103
|
+
exports.startCustomerVerificationSnapshot = startCustomerVerificationSnapshot;
|
|
104
|
+
/** Synchronous; starts a background refresh when the copy is stale. Never throws. */
|
|
105
|
+
const isCustomerVerificationEnabled = () => {
|
|
106
|
+
const current = state();
|
|
107
|
+
if (current.read &&
|
|
108
|
+
!current.refreshing &&
|
|
109
|
+
(current.refreshedAt === null ||
|
|
110
|
+
Date.now() - current.refreshedAt >= exports.CUSTOMER_VERIFICATION_REFRESH_MS)) {
|
|
111
|
+
void (0, exports.refreshCustomerVerificationSnapshot)();
|
|
112
|
+
}
|
|
113
|
+
return current.enabled;
|
|
114
|
+
};
|
|
115
|
+
exports.isCustomerVerificationEnabled = isCustomerVerificationEnabled;
|
|
116
|
+
/**
|
|
117
|
+
* The value of `authVerificationsPerActor.customer`: Medusa's e-mail
|
|
118
|
+
* verification for the `emailpass` provider while the toggle is on, none
|
|
119
|
+
* while it is off. A fresh array per call.
|
|
120
|
+
*/
|
|
121
|
+
const customerVerificationActors = () => (0, exports.isCustomerVerificationEnabled)()
|
|
122
|
+
? [{ auth_provider: "emailpass", entity_type: "email" }]
|
|
123
|
+
: [];
|
|
124
|
+
exports.customerVerificationActors = customerVerificationActors;
|
|
125
|
+
/**
|
|
126
|
+
* Test hook: sets the value and counts as just refreshed, so it holds for
|
|
127
|
+
* 30 s without a reader; `null` forgets reader and value.
|
|
128
|
+
*/
|
|
129
|
+
const setCustomerVerificationEnabledForTests = (enabled) => {
|
|
130
|
+
const current = state();
|
|
131
|
+
if (enabled === null) {
|
|
132
|
+
stopTimer(current);
|
|
133
|
+
current.enabled = false;
|
|
134
|
+
current.refreshedAt = null;
|
|
135
|
+
current.refreshing = null;
|
|
136
|
+
current.read = null;
|
|
137
|
+
current.warn = null;
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
current.enabled = enabled;
|
|
141
|
+
current.refreshedAt = Date.now();
|
|
142
|
+
};
|
|
143
|
+
exports.setCustomerVerificationEnabledForTests = setCustomerVerificationEnabledForTests;
|
|
144
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VzdG9tZXItdmVyaWZpY2F0aW9uLXNuYXBzaG90LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2VtYWlsL2N1c3RvbWVyLXZlcmlmaWNhdGlvbi1zbmFwc2hvdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUJHO0FBQ1UsUUFBQSxnQ0FBZ0MsR0FBRyxNQUFNLENBQUM7QUFpQnZELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQzFCLDREQUE0RCxDQUM3RCxDQUFDO0FBRUYsTUFBTSxLQUFLLEdBQUcsR0FBa0IsRUFBRTtJQUNoQyxNQUFNLE1BQU0sR0FBRyxVQUFzRCxDQUFDO0lBQ3RFLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSztRQUNwQixPQUFPLEVBQUUsS0FBSztRQUNkLFdBQVcsRUFBRSxJQUFJO1FBQ2pCLFVBQVUsRUFBRSxJQUFJO1FBQ2hCLEtBQUssRUFBRSxJQUFJO1FBQ1gsSUFBSSxFQUFFLElBQUk7UUFDVixJQUFJLEVBQUUsSUFBSTtLQUNYLENBQUM7SUFDRixPQUFPLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUMzQixDQUFDLENBQUM7QUFFRixNQUFNLFVBQVUsR0FBRyxDQUFDLE9BQXNCLEVBQUUsS0FBYyxFQUFRLEVBQUU7SUFDbEUsSUFBSSxDQUFDO1FBQ0gsT0FBTyxDQUFDLElBQUksRUFBRSxDQUNaLDREQUNFLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FDM0IsTUFBTSxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxlQUFlLEVBQUUsQ0FDakUsQ0FBQztJQUNKLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCwrREFBK0Q7SUFDakUsQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLDZFQUE2RTtBQUN0RSxNQUFN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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.adminResendBusinessKey = exports.affiliateConsignmentBusinessKey = exports.userInviteBusinessKey = exports.passwordResetBusinessKey = exports.orderRefundedBusinessKey = exports.returnReceivedBusinessKey = exports.returnRequestedBusinessKey = exports.orderCanceledBusinessKey = exports.orderShippedBusinessKey = exports.orderReceivedAdminBusinessKey = exports.orderReceivedBusinessKey = void 0;
|
|
3
|
+
exports.adminResendBusinessKey = exports.affiliateConsignmentBusinessKey = exports.userInviteBusinessKey = exports.customerVerificationBusinessKey = exports.passwordResetBusinessKey = exports.orderRefundedBusinessKey = exports.returnReceivedBusinessKey = exports.returnRequestedBusinessKey = exports.orderCanceledBusinessKey = exports.orderShippedBusinessKey = exports.orderReceivedAdminBusinessKey = exports.orderReceivedBusinessKey = void 0;
|
|
4
4
|
const node_crypto_1 = require("node:crypto");
|
|
5
5
|
const affiliate_1 = require("@hartl-services/medusa-food-supplements-contracts/events/affiliate");
|
|
6
6
|
const normalizedIdentifier = (value, name) => {
|
|
@@ -32,6 +32,16 @@ const passwordResetBusinessKey = (token) => {
|
|
|
32
32
|
return `password-reset:${tokenHash}`;
|
|
33
33
|
};
|
|
34
34
|
exports.passwordResetBusinessKey = passwordResetBusinessKey;
|
|
35
|
+
const customerVerificationBusinessKey = (token) => {
|
|
36
|
+
if (!token) {
|
|
37
|
+
throw new Error("token must not be empty.");
|
|
38
|
+
}
|
|
39
|
+
// Keyed by the token's hash, never the token: every new request issues a
|
|
40
|
+
// new token and must produce a new message, as with password-reset.
|
|
41
|
+
const tokenHash = (0, node_crypto_1.createHash)("sha256").update(token, "utf8").digest("hex");
|
|
42
|
+
return `customer-verification:${tokenHash}`;
|
|
43
|
+
};
|
|
44
|
+
exports.customerVerificationBusinessKey = customerVerificationBusinessKey;
|
|
35
45
|
const userInviteBusinessKey = (token) => {
|
|
36
46
|
if (!token) {
|
|
37
47
|
throw new Error("token must not be empty.");
|
|
@@ -47,4 +57,4 @@ const affiliateConsignmentBusinessKey = (affiliateId, periodStart) => (0, affili
|
|
|
47
57
|
exports.affiliateConsignmentBusinessKey = affiliateConsignmentBusinessKey;
|
|
48
58
|
const adminResendBusinessKey = (originalMessageId, requestId) => `admin-resend:${normalizedIdentifier(originalMessageId, "originalMessageId")}:${normalizedIdentifier(requestId, "requestId")}`;
|
|
49
59
|
exports.adminResendBusinessKey = adminResendBusinessKey;
|
|
50
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
60
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVzaW5lc3Mta2V5cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9lbWFpbC9kb21haW4vYnVzaW5lc3Mta2V5cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2Q0FBeUM7QUFFekMsa0dBQTJIO0FBRTNILE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxLQUFhLEVBQUUsSUFBWSxFQUFVLEVBQUU7SUFDbkUsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2hDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsSUFBSSxxQkFBcUIsQ0FBQyxDQUFDO0lBQ2hELENBQUM7SUFDRCxPQUFPLFVBQVUsQ0FBQztBQUNwQixDQUFDLENBQUM7QUFFSyxNQUFNLHdCQUF3QixHQUFHLENBQUMsT0FBZSxFQUFVLEVBQUUsQ0FDbEUsa0JBQWtCLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsRUFBRSxDQUFDO0FBRGxELFFBQUEsd0JBQXdCLDRCQUMwQjtBQUV4RCxNQUFNLDZCQUE2QixHQUFHLENBQUMsT0FBZSxFQUFVLEVBQUUsQ0FDdkUsd0JBQXdCLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsRUFBRSxDQUFDO0FBRHhELFFBQUEsNkJBQTZCLGlDQUMyQjtBQUU5RCxNQUFNLHVCQUF1QixHQUFHLENBQUMsYUFBcUIsRUFBVSxFQUFFLENBQ3ZFLGlCQUFpQixvQkFBb0IsQ0FBQyxhQUFhLEVBQUUsZUFBZSxDQUFDLEVBQUUsQ0FBQztBQUQ3RCxRQUFBLHVCQUF1QiwyQkFDc0M7QUFFbkUsTUFBTSx3QkFBd0IsR0FBRyxDQUFDLE9BQWUsRUFBVSxFQUFFLENBQ2xFLGtCQUFrQixvQkFBb0IsQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLEVBQUUsQ0FBQztBQURsRCxRQUFBLHdCQUF3Qiw0QkFDMEI7QUFFeEQsTUFB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
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decideCustomerVerificationResend = exports.verificationLookupEmails = exports.CUSTOMER_VERIFICATION_RESEND_INTERVAL_MS = void 0;
|
|
4
|
+
/** Shortest time between two confirmation mails for the same account. */
|
|
5
|
+
exports.CUSTOMER_VERIFICATION_RESEND_INTERVAL_MS = 60_000;
|
|
6
|
+
/**
|
|
7
|
+
* Medusa's emailpass provider stores the e-mail exactly as it was registered
|
|
8
|
+
* (no lowercasing) and logs in by exact match, so the account is looked up by
|
|
9
|
+
* the address as typed and by its lowercase form.
|
|
10
|
+
*/
|
|
11
|
+
const verificationLookupEmails = (email) => {
|
|
12
|
+
const trimmed = email.trim();
|
|
13
|
+
return [...new Set([trimmed, trimmed.toLowerCase()])].filter(Boolean);
|
|
14
|
+
};
|
|
15
|
+
exports.verificationLookupEmails = verificationLookupEmails;
|
|
16
|
+
/**
|
|
17
|
+
* Whether a new confirmation mail may be requested: not for a confirmed
|
|
18
|
+
* address and not within a minute of the previous request (a missing row
|
|
19
|
+
* means none was requested yet).
|
|
20
|
+
*/
|
|
21
|
+
const decideCustomerVerificationResend = (input) => {
|
|
22
|
+
const { now, verification } = input;
|
|
23
|
+
if (!verification) {
|
|
24
|
+
return "request";
|
|
25
|
+
}
|
|
26
|
+
if (verification.verified_at) {
|
|
27
|
+
return "already_verified";
|
|
28
|
+
}
|
|
29
|
+
const requestedAt = new Date(verification.requested_at).getTime();
|
|
30
|
+
if (Number.isFinite(requestedAt) &&
|
|
31
|
+
now.getTime() - requestedAt < exports.CUSTOMER_VERIFICATION_RESEND_INTERVAL_MS) {
|
|
32
|
+
return "throttled";
|
|
33
|
+
}
|
|
34
|
+
return "request";
|
|
35
|
+
};
|
|
36
|
+
exports.decideCustomerVerificationResend = decideCustomerVerificationResend;
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VzdG9tZXItdmVyaWZpY2F0aW9uLXJlc2VuZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9lbWFpbC9kb21haW4vY3VzdG9tZXItdmVyaWZpY2F0aW9uLXJlc2VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5RUFBeUU7QUFDNUQsUUFBQSx3Q0FBd0MsR0FBRyxNQUFNLENBQUM7QUFPL0Q7Ozs7R0FJRztBQUNJLE1BQU0sd0JBQXdCLEdBQUcsQ0FBQyxLQUFhLEVBQVksRUFBRTtJQUNsRSxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDN0IsT0FBTyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUN4RSxDQUFDLENBQUM7QUFIVyxRQUFBLHdCQUF3Qiw0QkFHbkM7QUFFRjs7OztHQUlHO0FBQ0ksTUFBTSxnQ0FBZ0MsR0FBRyxDQUM5QyxLQU1FLEVBQ2tDLEVBQUU7SUFDdEMsTUFBTSxFQUFFLEdBQUcsRUFBRSxZQUFZLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFDcEMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ2xCLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFDRCxJQUFJLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUM3QixPQUFPLGtCQUFrQixDQUFDO0lBQzVCLENBQUM7SUFDRCxNQUFNLFdBQVcsR0FBRyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDbEUsSUFDRSxNQUFNLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQztRQUM1QixHQUFHLENBQUMsT0FBTyxFQUFFLEdBQUcsV0FBVyxHQUFHLGdEQUF3QyxFQUN0RSxDQUFDO1FBQ0QsT0FBTyxXQUFXLENBQUM7SUFDckIsQ0FBQztJQUNELE9BQU8sU0FBUyxDQUFDO0FBQ25CLENBQUMsQ0FBQztBQXhCVyxRQUFBLGdDQUFnQyxvQ0F3QjNDIn0=
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NativeInviteEventSchema = exports.NativePasswordResetEventSchema = exports.NativeShipmentCreatedEventSchema = exports.NativeReturnEventSchema = exports.NativeOrderEventSchema = void 0;
|
|
3
|
+
exports.NativeInviteEventSchema = exports.NativeVerificationRequestedEventSchema = exports.NativePasswordResetEventSchema = exports.NativeShipmentCreatedEventSchema = exports.NativeReturnEventSchema = exports.NativeOrderEventSchema = void 0;
|
|
4
4
|
const zod_1 = require("@medusajs/framework/zod");
|
|
5
5
|
const NonEmptyStringSchema = zod_1.z.string().trim().min(1);
|
|
6
6
|
exports.NativeOrderEventSchema = zod_1.z
|
|
@@ -28,9 +28,25 @@ exports.NativePasswordResetEventSchema = zod_1.z
|
|
|
28
28
|
metadata: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
|
|
29
29
|
})
|
|
30
30
|
.strict();
|
|
31
|
+
/**
|
|
32
|
+
* Medusa's `auth.verification_requested`. Not strict: the workflow emits
|
|
33
|
+
* more fields (`code_provider`, `auth_identity_id`, ...) than the mail
|
|
34
|
+
* needs, and a field added by Medusa later must not silence the mail.
|
|
35
|
+
* `code` is absent when the identity is already verified; `expires_at` is a
|
|
36
|
+
* `Date` on the local Event Bus and an ISO string after Redis.
|
|
37
|
+
*/
|
|
38
|
+
exports.NativeVerificationRequestedEventSchema = zod_1.z.object({
|
|
39
|
+
entity_id: NonEmptyStringSchema,
|
|
40
|
+
entity_type: NonEmptyStringSchema,
|
|
41
|
+
code_provider: NonEmptyStringSchema,
|
|
42
|
+
auth_identity_id: NonEmptyStringSchema,
|
|
43
|
+
code: NonEmptyStringSchema,
|
|
44
|
+
expires_at: zod_1.z.coerce.date(),
|
|
45
|
+
metadata: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).nullish(),
|
|
46
|
+
});
|
|
31
47
|
exports.NativeInviteEventSchema = zod_1.z
|
|
32
48
|
.object({
|
|
33
49
|
id: NonEmptyStringSchema,
|
|
34
50
|
})
|
|
35
51
|
.strict();
|
|
36
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
52
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnQtc2NoZW1hcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9lbWFpbC9kb21haW4vZXZlbnQtc2NoZW1hcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxpREFBNEM7QUFFNUMsTUFBTSxvQkFBb0IsR0FBRyxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRXpDLFFBQUEsc0JBQXNCLEdBQUcsT0FBQztLQUNwQyxNQUFNLENBQUM7SUFDTixFQUFFLEVBQUUsb0JBQW9CO0NBQ3pCLENBQUM7S0FDRCxNQUFNLEVBQUUsQ0FBQztBQUVDLFFBQUEsdUJBQXVCLEdBQUcsT0FBQztLQUNyQyxNQUFNLENBQUM7SUFDTixRQUFRLEVBQUUsb0JBQW9CO0lBQzlCLFNBQVMsRUFBRSxvQkFBb0I7Q0FDaEMsQ0FBQztLQUNELE1BQU0sRUFBRSxDQUFDO0FBRUMsUUFBQSxnQ0FBZ0MsR0FBRyxPQUFDO0tBQzlDLE1BQU0sQ0FBQztJQUNOLEVBQUUsRUFBRSxvQkFBb0I7SUFDeEIsZUFBZSxFQUFFLE9BQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxRQUFRLEVBQUU7Q0FDeEMsQ0FBQztLQUNELE1BQU0sRUFBRSxDQUFDO0FBRUMsUUFBQSw4QkFBOEIsR0FBRyxPQUFDO0tBQzVDLE1BQU0sQ0FBQztJQUNOLFNBQVMsRUFBRSxvQkFBb0I7SUFDL0IsVUFBVSxFQUFFLG9CQUFvQjtJQUNoQyxLQUFLLEVBQUUsb0JBQW9CO0lBQzNCLFFBQVEsRUFBRSxPQUFDLENBQUMsTUFBTSxDQUFDLE9BQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxPQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUU7Q0FDdkQsQ0FBQztLQUNELE1BQU0sRUFBRSxDQUFDO0FBRVo7Ozs7OztHQU1HO0FBQ1UsUUFBQSxzQ0FBc0MsR0FBRyxPQUFDLENBQUMsTUFBTSxDQUFDO0lBQzdELFNBQVMsRUFBRSxvQkFBb0I7SUFDL0IsV0FBVyxFQUFFLG9CQUFvQjtJQUNqQyxhQUFhLEVBQUUsb0JBQW9CO0lBQ25DLGdCQUFnQixFQUFFLG9CQUFvQjtJQUN0QyxJQUFJLEVBQUUsb0JBQW9CO0lBQzFCLFVBQVUsRUFBRSxPQUFDLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRTtJQUMzQixRQUFRLEVBQUUsT0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsT0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFO0NBQ3RELENBQUMsQ0FBQztBQUVVLFFBQUEsdUJBQXVCLEdBQUcsT0FBQztLQUNyQyxNQUFNLENBQUM7SUFDTixFQUFFLEVBQUUsb0JBQW9CO0NBQ3pCLENBQUM7S0FDRCxNQUFNLEVBQUUsQ0FBQyJ9
|
|
@@ -16,9 +16,16 @@ exports.emailPluginFeatures = (0, public_1.definePluginFeatures)({
|
|
|
16
16
|
{
|
|
17
17
|
key: "account_mails",
|
|
18
18
|
label: "Konto-Mails",
|
|
19
|
-
description: "Passwort-Zurücksetzen für Kunden
|
|
19
|
+
description: "Passwort-Zurücksetzen für Kunden, Einladungen neuer Admin-Benutzer und die Bestätigungsmail der Kontobestätigung. Aus: Für diese Ereignisse wird keine Mail erzeugt.",
|
|
20
20
|
default_enabled: true,
|
|
21
21
|
},
|
|
22
|
+
{
|
|
23
|
+
key: "customer_verification",
|
|
24
|
+
label: "Kontobestätigung per E-Mail",
|
|
25
|
+
description: "Neue und bestehende Kundenkonten müssen ihre E-Mail-Adresse über einen Link bestätigen, bevor die erste Anmeldung gelingt; bestehende Konten bekommen die Mail bei der nächsten Anmeldung. Voraussetzung: Konto-Mails sind eingeschaltet, sonst kommt keine Bestätigungsmail an. Eine Änderung wirkt innerhalb von etwa 30 Sekunden. Aus: Kunden melden sich ohne Bestätigung an.",
|
|
26
|
+
default_enabled: false,
|
|
27
|
+
parent_key: "account_mails",
|
|
28
|
+
},
|
|
22
29
|
{
|
|
23
30
|
key: "affiliate_reminders",
|
|
24
31
|
label: "Affiliate-Erinnerungen",
|
|
@@ -36,4 +43,4 @@ exports.emailPluginFeatures = (0, public_1.definePluginFeatures)({
|
|
|
36
43
|
],
|
|
37
44
|
admin_page: "/settings/hartl-services/email",
|
|
38
45
|
});
|
|
39
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
46
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWZlYXR1cmVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2VtYWlsL3BsdWdpbi1mZWF0dXJlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxzQ0FBaUQ7QUFFcEMsUUFBQSxtQkFBbUIsR0FBRyxJQUFBLDZCQUFvQixFQUFDO0lBQ3RELFVBQVUsRUFBRSxPQUFPO0lBQ25CLEtBQUssRUFBRSxRQUFRO0lBQ2YsV0FBVyxFQUNULDZhQUE2YTtJQUMvYSxRQUFRLEVBQUU7UUFDUjtZQUNFLEdBQUcsRUFBRSxhQUFhO1lBQ2xCLEtBQUssRUFBRSxlQUFlO1lBQ3RCLFdBQVcsRUFDVCxvWkFBb1o7WUFDdFosZUFBZSxFQUFFLElBQUk7U0FDdEI7UUFDRDtZQUNFLEdBQUcsRUFBRSxlQUFlO1lBQ3BCLEtBQUssRUFBRSxhQUFhO1lBQ3BCLFdBQVcsRUFDVCxzS0FBc0s7WUFDeEssZUFBZSxFQUFFLElBQUk7U0FDdEI7UUFDRDtZQUNFLEdBQUcsRUFBRSx1QkFBdUI7WUFDNUIsS0FBSyxFQUFFLDZCQUE2QjtZQUNwQyxXQUFXLEVBQ1QsbVhBQW1YO1lBQ3JYLGVBQWUsRUFBRSxLQUFLO1lBQ3RCLFVBQVUsRUFBRSxlQUFlO1NBQzVCO1FBQ0Q7WUFDRSxHQUFHLEVBQUUscUJBQXFCO1lBQzFCLEtBQUssRUFBRSx3QkFBd0I7WUFDL0IsV0FBVyxFQUNULHNIQUFzSDtZQUN4SCxlQUFlLEVBQUUsSUFBSTtTQUN0QjtLQUNGO0lBQ0QsUUFBUSxFQUFFO1FBQ1I7WUFDRSxHQUFHLEVBQUUsTUFBTTtZQUNYLEtBQUssRUFBRSxNQUFNO1lBQ2IsV0FBVyxFQUNULCtKQUErSjtZQUNqSyxJQUFJLEVBQUUsT0FBTztTQUNkO0tBQ0Y7SUFDRCxVQUFVLEVBQUUsZ0NBQWdDO0NBQzdDLENBQUMsQ0FBQyJ9
|