feat(core): Admin-driven customer verification and password reset#4763
feat(core): Admin-driven customer verification and password reset#4763tbouliere-datasolution wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdds two admin GraphQL mutations: verifyCustomerAccountAsAdmin and resetCustomerPasswordAsAdmin, with new types/unions and a CustomerAccountStateError. Implements resolver handlers and service logic including admin password reset, random password generation, verification history/event emission, and a RequestContext bridge for password reset emails. Updates generated types and introspection. Extends admin error resolvers. Adds E2E tests covering success and error states. Wires dashboard UI: action button, GraphQL documents, and conditional actions on the customer page. Updates translations across locales. Possibly related PRs
Suggested reviewers
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/dashboard/src/i18n/locales/bg.po (1)
2546-2548:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix the actor in the verification history entry.
Проверен от клиентаmeans “verified by the customer”, not “customer verified”. With the new admin-triggered verification flow, this history line will read backwards. Something likeКлиентът е верифициранorПрофилът е верифициранwould match the event.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/dashboard/src/i18n/locales/bg.po` around lines 2546 - 2548, Replace the Bulgarian translation for the "Customer verified" history entry in packages/dashboard/src/i18n/locales/bg.po (msgid "Customer verified") so it reflects that the customer was verified (not that they verified someone); update msgstr from "Проверен от клиента" to a passive/agent-less phrase such as "Клиентът е верифициран" or "Профилът е верифициран" to match the admin-triggered verification flow referenced by customer-history-utils.tsx (the history entry text).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/core/src/service/services/customer.service.ts`:
- Around line 662-664: The Fisher–Yates shuffle in the loop that iterates "for
(let i = combined.length - 1; i > 0; i--)" is using randomInt(0, i) which
excludes i and creates an off-by-one bias; update the call to allow j to equal i
by using randomInt(0, i + 1) (or otherwise make the upper bound inclusive) so
the swap "[combined[i], combined[j]] = [combined[j], combined[i]]" implements a
correct unbiased Fisher–Yates shuffle.
In `@packages/dashboard/src/i18n/locales/ar.po`:
- Around line 2911-2914: The Arabic translation for the msgid beginning "This
marks the account as verified..." uses "موثوق" which is inconsistent with other
entries; update the msgstr to use the same term used elsewhere (e.g., "تم
التحقق" or "مُتحقق منه") to match status and success messages. Edit the msgstr
in packages/dashboard/src/i18n/locales/ar.po for the entry whose msgid matches
that sentence (found in customer-credential-action-button.tsx) and replace
"موثوق" with the project's chosen verified term so all related strings are
consistent.
In `@packages/dashboard/src/i18n/locales/bg.po`:
- Around line 2523-2525: Update the Bulgarian translation for the msgid "Send
reset email" so the CTA explicitly mentions password reset; in the locales file
change the msgstr to include "парола" (e.g. "Изпрати имейл за нулиране на
парола") to match the button in customer-credential-action-button.tsx and make
the action unambiguous.
In `@packages/dashboard/src/i18n/locales/cs.po`:
- Around line 1281-1284: The Czech ICU plural for the cancellation label is
missing the "few" form; update the msgstr for the ICU key used in
cancel-jobs-bulk-action.tsx (the msgid "{cancellableCount, plural, one {Cancel
{cancellableCount} job} other {Cancel {cancellableCount} jobs}}") to include a
few branch so counts 2–4 use "úlohy" (e.g. one {Zrušit {cancellableCount} úlohu}
few {Zrušit {cancellableCount} úlohy} other {Zrušit {cancellableCount} úloh});
apply the same change to the other occurrence mentioned (around lines 5487-5490)
so both pluralized strings use one/few/other Czech forms.
- Around line 2505-2508: Update the Czech translation for the "Send reset email"
string used in customer-credential-action-button.tsx: replace the current msgstr
"Odeslat e-mail pro obnovení" with the fuller label "Odeslat e-mail pro obnovení
hesla" so the UI clearly states that a password reset email will be sent and
matches nearby translations.
In `@packages/dashboard/src/i18n/locales/es.po`:
- Around line 5189-5190: The translation drops pluralization: update the PO
entry for msgid "Select {0}s" so plural intent is preserved — either provide a
proper plural Spanish translation or convert the entry to use gettext plural
forms (add msgid_plural "Select {0}s" and supply msgstr[0]/msgstr[1] with
singular and plural Spanish variants). Locate the existing msgid "Select {0}s"
and its msgstr and replace the msgstr with the correct plural-aware translations
(e.g., add msgid_plural and both msgstr indexes) matching Spanish grammar.
In `@packages/dashboard/src/i18n/locales/fa.po`:
- Line 3584: The pluralization for the "jobs" failure message currently uses
singular phrasing in the plural branch ("{rejected, plural, one {لغو {rejected}
کار با شکست مواجه شد} other {لغو {rejected} کار با شکست مواجه شد}}"); update the
plural-specific form (the "other" branch) to use the plural verb form (e.g.,
"...کار ... شدند") so plural counts read correctly, and apply the same change to
the second identical occurrence of this msgstr elsewhere in the file.
In `@packages/dashboard/src/i18n/locales/nl.po`:
- Around line 5184-5185: This entry currently loses plural semantics: replace
the single msgid/msgstr pair for "Select {0}s" with a proper pluralizable PO
entry by adding msgid_plural and providing msgstr[0] (singular) and msgstr[1]
(plural) translations, preserving the {0} placeholder and using correct Dutch
wording (e.g., singular "Selecteer {0}" and an appropriate plural form) so
plural rendering matches the original msgid's intent.
In `@packages/dashboard/src/i18n/locales/ro.po`:
- Around line 97-99: Replace the English heading labels in the ro.po entries
(msgid "Heading 1" ... "Heading 6") with their Romanian equivalents (e.g.,
"Titlu 1", "Titlu 2", ..., "Titlu 6") so the rich-text editor toolbar strings
from responsive-toolbar.tsx are localized; update every occurrence noted (the
other msgid repeats) to keep translations consistent across the file.
---
Outside diff comments:
In `@packages/dashboard/src/i18n/locales/bg.po`:
- Around line 2546-2548: Replace the Bulgarian translation for the "Customer
verified" history entry in packages/dashboard/src/i18n/locales/bg.po (msgid
"Customer verified") so it reflects that the customer was verified (not that
they verified someone); update msgstr from "Проверен от клиента" to a
passive/agent-less phrase such as "Клиентът е верифициран" or "Профилът е
верифициран" to match the admin-triggered verification flow referenced by
customer-history-utils.tsx (the history entry text).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: be3a1a0d-c532-48ab-885c-e48ebfc8cfa9
📒 Files selected for processing (50)
packages/admin-ui/src/lib/core/src/common/generated-types.tspackages/admin-ui/src/lib/core/src/common/introspection-result.tspackages/asset-server-plugin/e2e/graphql/graphql-admin.tspackages/asset-server-plugin/e2e/graphql/graphql-env-admin.d.tspackages/asset-server-plugin/e2e/graphql/graphql-env-shop.d.tspackages/asset-server-plugin/e2e/graphql/graphql-shop.tspackages/common/src/generated-shop-types.tspackages/common/src/generated-types.tspackages/core/e2e/customer.e2e-spec.tspackages/core/e2e/graphql/admin-definitions.tspackages/core/e2e/graphql/graphql-admin.tspackages/core/e2e/graphql/graphql-env-admin.d.tspackages/core/e2e/graphql/graphql-env-shop.d.tspackages/core/e2e/graphql/graphql-shop.tspackages/core/src/api/resolvers/admin/customer.resolver.tspackages/core/src/api/schema/admin-api/customer.api.graphqlpackages/core/src/common/error/generated-graphql-admin-errors.tspackages/core/src/service/services/customer.service.tspackages/core/src/service/services/user.service.tspackages/dashboard/src/app/routes/_authenticated/_customers/components/customer-credential-action-button.tsxpackages/dashboard/src/app/routes/_authenticated/_customers/customers.graphql.tspackages/dashboard/src/app/routes/_authenticated/_customers/customers_.$id.tsxpackages/dashboard/src/i18n/locales/ar.popackages/dashboard/src/i18n/locales/bg.popackages/dashboard/src/i18n/locales/cs.popackages/dashboard/src/i18n/locales/de.popackages/dashboard/src/i18n/locales/en.popackages/dashboard/src/i18n/locales/es.popackages/dashboard/src/i18n/locales/fa.popackages/dashboard/src/i18n/locales/fr.popackages/dashboard/src/i18n/locales/he.popackages/dashboard/src/i18n/locales/hr.popackages/dashboard/src/i18n/locales/hu.popackages/dashboard/src/i18n/locales/it.popackages/dashboard/src/i18n/locales/ja.popackages/dashboard/src/i18n/locales/nb.popackages/dashboard/src/i18n/locales/ne.popackages/dashboard/src/i18n/locales/nl.popackages/dashboard/src/i18n/locales/pl.popackages/dashboard/src/i18n/locales/pt_BR.popackages/dashboard/src/i18n/locales/pt_PT.popackages/dashboard/src/i18n/locales/ro.popackages/dashboard/src/i18n/locales/ru.popackages/dashboard/src/i18n/locales/sv.popackages/dashboard/src/i18n/locales/tr.popackages/dashboard/src/i18n/locales/uk.popackages/dashboard/src/i18n/locales/zh_Hans.popackages/dashboard/src/i18n/locales/zh_Hant.popackages/dashboard/src/lib/graphql/graphql-env.d.tsschema-admin.json
| for (let i = combined.length - 1; i > 0; i--) { | ||
| const j = randomInt(0, i); | ||
| [combined[i], combined[j]] = [combined[j], combined[i]]; |
There was a problem hiding this comment.
Off-by-one error in Fisher-Yates shuffle.
Similarly, randomInt(0, i) excludes index i from the swap candidates. The correct Fisher-Yates implementation should allow j to equal i (the element can stay in place), so the upper bound should be i + 1.
🐛 Proposed fix
for (let i = combined.length - 1; i > 0; i--) {
- const j = randomInt(0, i);
+ const j = randomInt(0, i + 1);
[combined[i], combined[j]] = [combined[j], combined[i]];
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for (let i = combined.length - 1; i > 0; i--) { | |
| const j = randomInt(0, i); | |
| [combined[i], combined[j]] = [combined[j], combined[i]]; | |
| for (let i = combined.length - 1; i > 0; i--) { | |
| const j = randomInt(0, i + 1); | |
| [combined[i], combined[j]] = [combined[j], combined[i]]; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/core/src/service/services/customer.service.ts` around lines 662 -
664, The Fisher–Yates shuffle in the loop that iterates "for (let i =
combined.length - 1; i > 0; i--)" is using randomInt(0, i) which excludes i and
creates an off-by-one bias; update the call to allow j to equal i by using
randomInt(0, i + 1) (or otherwise make the upper bound inclusive) so the swap
"[combined[i], combined[j]] = [combined[j], combined[i]]" implements a correct
unbiased Fisher–Yates shuffle.
| #: src/app/routes/_authenticated/_customers/components/customer-credential-action-button.tsx:81 | ||
| msgid "This marks the account as verified and sets a new random password, bypassing the email verification flow. The password will be displayed once — the customer will not receive any notification." | ||
| msgstr "يحدد هذا الإجراء الحساب كموثوق ويعين كلمة مرور عشوائية جديدة، متجاوزًا تدفق التحقق عبر البريد الإلكتروني. سيتم عرض كلمة المرور مرة واحدة — لن يتلقى العميل أي إشعار." | ||
|
|
There was a problem hiding this comment.
Use consistent term for “verified” in Arabic copy.
Line 2913 uses "موثوق" for “verified”, but other related entries in this file use "مُتحقق منه/تم التحقق" (e.g., status and success messages). Please align this string to the same term to avoid UX inconsistency in the new account-verification flow.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/dashboard/src/i18n/locales/ar.po` around lines 2911 - 2914, The
Arabic translation for the msgid beginning "This marks the account as
verified..." uses "موثوق" which is inconsistent with other entries; update the
msgstr to use the same term used elsewhere (e.g., "تم التحقق" or "مُتحقق منه")
to match status and success messages. Edit the msgstr in
packages/dashboard/src/i18n/locales/ar.po for the entry whose msgid matches that
sentence (found in customer-credential-action-button.tsx) and replace "موثوق"
with the project's chosen verified term so all related strings are consistent.
| #: src/app/routes/_authenticated/_customers/components/customer-credential-action-button.tsx:70 | ||
| msgid "Send reset email" | ||
| msgstr "Изпращане на имейл за нулиране" |
There was a problem hiding this comment.
Make the CTA explicit about password reset.
Изпращане на имейл за нулиране drops what is being reset, so the button reads vague in Bulgarian. Please keep парола in the label, e.g. Изпрати имейл за нулиране на парола.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/dashboard/src/i18n/locales/bg.po` around lines 2523 - 2525, Update
the Bulgarian translation for the msgid "Send reset email" so the CTA explicitly
mentions password reset; in the locales file change the msgstr to include
"парола" (e.g. "Изпрати имейл за нулиране на парола") to match the button in
customer-credential-action-button.tsx and make the action unambiguous.
| #: src/app/routes/_authenticated/_system/components/cancel-jobs-bulk-action.tsx:63 | ||
| msgid "{cancellableCount, plural, one {Cancel {cancellableCount} job} other {Cancel {cancellableCount} jobs}}" | ||
| msgstr "" | ||
| msgstr "{cancellableCount, plural, one {Zrušit {cancellableCount} úlohu} other {Zrušit {cancellableCount} úloh}}" | ||
|
|
There was a problem hiding this comment.
Use Czech plural categories for job counts.
These ICU plurals currently use one/other, with other rendered as úloh. In Czech, counts 2–4 should use a different form (e.g. úlohy). Please add a few branch to avoid grammatically incorrect UI text for common counts.
Suggested ICU update
-msgstr "{cancellableCount, plural, one {Zrušit {cancellableCount} úlohu} other {Zrušit {cancellableCount} úloh}}"
+msgstr "{cancellableCount, plural, one {Zrušit {cancellableCount} úlohu} few {Zrušit {cancellableCount} úlohy} other {Zrušit {cancellableCount} úloh}}"
-msgstr "{cancellableCount, plural, one {Opravdu chcete zrušit {cancellableCount} úlohu? Tuto akci nelze vrátit zpět.} other {Opravdu chcete zrušit {cancellableCount} úloh? Tuto akci nelze vrátit zpět.}}"
+msgstr "{cancellableCount, plural, one {Opravdu chcete zrušit {cancellableCount} úlohu? Tuto akci nelze vrátit zpět.} few {Opravdu chcete zrušit {cancellableCount} úlohy? Tuto akci nelze vrátit zpět.} other {Opravdu chcete zrušit {cancellableCount} úloh? Tuto akci nelze vrátit zpět.}}"Also applies to: 5487-5490
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/dashboard/src/i18n/locales/cs.po` around lines 1281 - 1284, The
Czech ICU plural for the cancellation label is missing the "few" form; update
the msgstr for the ICU key used in cancel-jobs-bulk-action.tsx (the msgid
"{cancellableCount, plural, one {Cancel {cancellableCount} job} other {Cancel
{cancellableCount} jobs}}") to include a few branch so counts 2–4 use "úlohy"
(e.g. one {Zrušit {cancellableCount} úlohu} few {Zrušit {cancellableCount}
úlohy} other {Zrušit {cancellableCount} úloh}); apply the same change to the
other occurrence mentioned (around lines 5487-5490) so both pluralized strings
use one/few/other Czech forms.
| #: src/app/routes/_authenticated/_customers/components/customer-credential-action-button.tsx:70 | ||
| msgid "Send reset email" | ||
| msgstr "Odeslat e-mail pro obnovení" | ||
|
|
There was a problem hiding this comment.
Clarify the reset action label for users.
"Odeslat e-mail pro obnovení" is understandable but incomplete in Czech UI context (missing what is being reset). Use a fuller label like "Odeslat e-mail pro obnovení hesla" for consistency with nearby strings.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/dashboard/src/i18n/locales/cs.po` around lines 2505 - 2508, Update
the Czech translation for the "Send reset email" string used in
customer-credential-action-button.tsx: replace the current msgstr "Odeslat
e-mail pro obnovení" with the fuller label "Odeslat e-mail pro obnovení hesla"
so the UI clearly states that a password reset email will be sent and matches
nearby translations.
| msgid "Select {0}s" | ||
| msgstr "Seleccionar {0}" |
There was a problem hiding this comment.
Plural meaning is dropped in Spanish translation.
Line 5189 uses msgid "Select {0}s" but Line 5190 translates to singular ("Seleccionar {0}"). This loses the plural intent in the UI.
Suggested fix
msgid "Select {0}s"
-msgstr "Seleccionar {0}"
+msgstr "Seleccionar {0}s"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| msgid "Select {0}s" | |
| msgstr "Seleccionar {0}" | |
| msgid "Select {0}s" | |
| msgstr "Seleccionar {0}s" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/dashboard/src/i18n/locales/es.po` around lines 5189 - 5190, The
translation drops pluralization: update the PO entry for msgid "Select {0}s" so
plural intent is preserved — either provide a proper plural Spanish translation
or convert the entry to use gettext plural forms (add msgid_plural "Select {0}s"
and supply msgstr[0]/msgstr[1] with singular and plural Spanish variants).
Locate the existing msgid "Select {0}s" and its msgstr and replace the msgstr
with the correct plural-aware translations (e.g., add msgid_plural and both
msgstr indexes) matching Spanish grammar.
| #: src/app/routes/_authenticated/_system/components/cancel-jobs-bulk-action.tsx:41 | ||
| msgid "{rejected, plural, one {{0}} other {{1}}}" | ||
| msgstr "" | ||
| msgstr "{rejected, plural, one {لغو {rejected} کار با شکست مواجه شد} other {لغو {rejected} کار با شکست مواجه شد}}" |
There was a problem hiding this comment.
Plural failure message should use plural phrasing in the “jobs” branch.
At Line 3584 and Line 4867, the “jobs” failure text still uses singular phrasing (...کار ... شد). For counts > 1, this reads incorrectly in UI notifications. Update the plural branch / plural-specific string to plural wording (e.g., ...کار ... شدند).
Also applies to: 4867-4867
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/dashboard/src/i18n/locales/fa.po` at line 3584, The pluralization
for the "jobs" failure message currently uses singular phrasing in the plural
branch ("{rejected, plural, one {لغو {rejected} کار با شکست مواجه شد} other {لغو
{rejected} کار با شکست مواجه شد}}"); update the plural-specific form (the
"other" branch) to use the plural verb form (e.g., "...کار ... شدند") so plural
counts read correctly, and apply the same change to the second identical
occurrence of this msgstr elsewhere in the file.
| msgid "Select {0}s" | ||
| msgstr "Selecteer {0}" |
There was a problem hiding this comment.
Plural meaning is lost in translation for this label.
At Line 5184, msgid is plural (Select {0}s) but msgstr is singular (Selecteer {0}), which can render misleading text in multi-item contexts.
Suggested fix
msgid "Select {0}s"
-msgstr "Selecteer {0}"
+msgstr "Selecteer {0}s"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| msgid "Select {0}s" | |
| msgstr "Selecteer {0}" | |
| msgid "Select {0}s" | |
| msgstr "Selecteer {0}s" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/dashboard/src/i18n/locales/nl.po` around lines 5184 - 5185, This
entry currently loses plural semantics: replace the single msgid/msgstr pair for
"Select {0}s" with a proper pluralizable PO entry by adding msgid_plural and
providing msgstr[0] (singular) and msgstr[1] (plural) translations, preserving
the {0} placeholder and using correct Dutch wording (e.g., singular "Selecteer
{0}" and an appropriate plural form) so plural rendering matches the original
msgid's intent.
| #: src/lib/components/shared/rich-text-editor/responsive-toolbar.tsx:100 | ||
| msgid "Heading 5" | ||
| msgstr "Heading 5" |
There was a problem hiding this comment.
Localize rich-text heading labels instead of leaving English copy.
These entries remain in English (Heading 1…Heading 6) while nearby UI strings are Romanian, causing inconsistent localization in the editor toolbar.
Suggested update
msgid "Heading 1"
-msgstr "Heading 1"
+msgstr "Titlu 1"
msgid "Heading 2"
-msgstr "Heading 2"
+msgstr "Titlu 2"
msgid "Heading 3"
-msgstr "Heading 3"
+msgstr "Titlu 3"
msgid "Heading 4"
-msgstr "Heading 4"
+msgstr "Titlu 4"
msgid "Heading 5"
-msgstr "Heading 5"
+msgstr "Titlu 5"
msgid "Heading 6"
-msgstr "Heading 6"
+msgstr "Titlu 6"Also applies to: 1731-1733, 3362-3364, 3593-3595, 4615-4617, 5569-5571
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/dashboard/src/i18n/locales/ro.po` around lines 97 - 99, Replace the
English heading labels in the ro.po entries (msgid "Heading 1" ... "Heading 6")
with their Romanian equivalents (e.g., "Titlu 1", "Titlu 2", ..., "Titlu 6") so
the rich-text editor toolbar strings from responsive-toolbar.tsx are localized;
update every occurrence noted (the other msgid repeats) to keep translations
consistent across the file.
|
I identified this same issue and implemented a fix locally. Happy to share my approach or help review if useful. |
|
I think this might already be covered by the existing admin customer creation flow in resolver/service layer. (password is missing in the dashboard ui) `CustomerService.create() is documented as:
and it already immediately verifies the customer when a password is provided by calling the existing verification flow internally. So from my understanding, admins can already create a verified customer account through the existing API/service behavior, previous angular admin ui already had this behaviour so maybe adding password in the dashboard ui may be the appropriate way to go ahead ( i am not a maintainer so , you should probably wait for maintainer take on it ), |
Description
This PR adds two administrator-driven actions on the Customer detail to handle the cases where a customer can no longer self-serve their account state — either because they never confirmed their verification email or because they've lost access to their inbox.
Two new admin-API mutations are exposed on the Customer namespace:
(via the new AdminGeneratedPassword type) so the administrator can communicate it to the customer; it is not persisted anywhere else. A CUSTOMER_VERIFIED history entry is written and an AccountVerifiedEvent is published.
customer a reset link. No password is generated or returned — the customer chooses their new password through the standard reset flow.
A new CustomerAccountStateError (with an accountState: String field — "guest", "registered", or "verified") surfaces the cases where the action does not apply to the current account state. Under the hood, a new UserService.resetPasswordAsAdmin(ctx, userId, newPassword)
primitive performs the direct password reset without a token (also marking the user as verified if it wasn't already), and a getUserByIdWithPasswordHash helper consolidates the passwordHash-selecting query previously inlined in setPassword.
The Vendure Dashboard customer detail page gains a corresponding action button to invoke either mutation depending on the customer's current state.
Breaking changes
No breaking changes. This PR is purely additive:
Screenshot
Need help on this PR? Tag
@codesmithwith what you need. Autofix is disabled.