feat: vendor admin management and shared account settings #59

Merged
hsiegeln merged 19 commits from feature/vendor-admin-account-settings into main 2026-04-27 15:20:23 +02:00
Owner

Summary

  • Multi-vendor admin management — new /vendor/admins page lets platform admins invite/create additional administrators, remove them, reset their password or MFA. Uses the saas-vendor global Logto role. Invite via email when connector is configured, create with temporary credentials when not.
  • Shared account settings page — new /settings/account accessible to any authenticated user (vendor or tenant). Manage display name, change password (with current-password verification + confirmation email), TOTP MFA setup/removal, backup codes, passkey list/rename/delete. Reached via user dropdown menu in the TopBar.
  • AccountService extraction — new account/ package centralizes all user-level identity operations previously scattered across TenantPortalService and OnboardingService. TenantPortalService now delegates to AccountService (129 lines removed). Tenant SettingsPage imports shared components (467 lines removed).
  • LogtoManagementClient additions — password verification via Management API, global role CRUD methods, null orgId guard fix for vendor admin creation.
  • Security/api/account/** endpoints require authenticated(), MFA enforcement exemptions for account management paths, vendor admin reset operations verify target is actually a platform admin.

Changes

  • 23 files changed, +1,901 / -685 lines
  • New backend: AccountService, AccountController, VendorAdminService, VendorAdminController
  • New frontend: AccountSettingsPage, VendorAdminsPage, 4 shared components in components/account/
  • Refactored: TenantPortalService (delegation), SettingsPage (shared imports), tenant-hooks.ts (re-exports)

Test plan

  • Sign in as vendor, click username dropdown → "Account Settings" → verify profile, password change, MFA setup all work
  • Navigate to Vendor → Administrators → verify current admin listed with "You" badge
  • Add a new administrator (with temp credentials if no email connector)
  • Test Reset Password, Reset MFA, Remove actions on the new admin
  • Verify self-removal is blocked
  • Sign in as tenant admin → /tenant/settings → verify MFA, passkey, password sections still work
  • Verify forgot password link visible on sign-in page when email connector is active
## Summary - **Multi-vendor admin management** — new `/vendor/admins` page lets platform admins invite/create additional administrators, remove them, reset their password or MFA. Uses the `saas-vendor` global Logto role. Invite via email when connector is configured, create with temporary credentials when not. - **Shared account settings page** — new `/settings/account` accessible to any authenticated user (vendor or tenant). Manage display name, change password (with current-password verification + confirmation email), TOTP MFA setup/removal, backup codes, passkey list/rename/delete. Reached via user dropdown menu in the TopBar. - **AccountService extraction** — new `account/` package centralizes all user-level identity operations previously scattered across `TenantPortalService` and `OnboardingService`. `TenantPortalService` now delegates to `AccountService` (129 lines removed). Tenant `SettingsPage` imports shared components (467 lines removed). - **LogtoManagementClient additions** — password verification via Management API, global role CRUD methods, null orgId guard fix for vendor admin creation. - **Security** — `/api/account/**` endpoints require `authenticated()`, MFA enforcement exemptions for account management paths, vendor admin reset operations verify target is actually a platform admin. ## Changes - 23 files changed, +1,901 / -685 lines - New backend: `AccountService`, `AccountController`, `VendorAdminService`, `VendorAdminController` - New frontend: `AccountSettingsPage`, `VendorAdminsPage`, 4 shared components in `components/account/` - Refactored: `TenantPortalService` (delegation), `SettingsPage` (shared imports), `tenant-hooks.ts` (re-exports) ## Test plan - [ ] Sign in as vendor, click username dropdown → "Account Settings" → verify profile, password change, MFA setup all work - [ ] Navigate to Vendor → Administrators → verify current admin listed with "You" badge - [ ] Add a new administrator (with temp credentials if no email connector) - [ ] Test Reset Password, Reset MFA, Remove actions on the new admin - [ ] Verify self-removal is blocked - [ ] Sign in as tenant admin → /tenant/settings → verify MFA, passkey, password sections still work - [ ] Verify forgot password link visible on sign-in page when email connector is active
claude added 18 commits 2026-04-27 15:10:22 +02:00
Two features: multi-vendor admin management (invite/create, remove,
reset password/MFA) and shared account settings page (profile, password
change with current-password verification, MFA self-service). Includes
consolidation plan extracting user-level identity operations from
TenantPortalService into new AccountService.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
16 tasks covering: LogtoManagementClient additions, AccountService
extraction, AccountController, VendorAdminService/Controller,
SecurityConfig updates, frontend component extraction, shared
AccountSettingsPage, VendorAdminsPage, and Layout user menu.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds verifyUserPassword (for current-password check before password change) and
four global role methods (listRoleUsers, getRoleByName, assignGlobalRole,
revokeGlobalRole) needed by the upcoming AccountService and VendorAdminService.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Permit /settings/** SPA route, gate /api/account/** as authenticated,
and exempt account MFA/profile/password paths from MFA enforcement filter.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Vendor admins use global roles, not org roles — passing null orgId
would previously cause addUserToOrganization to call
/api/organizations/null/users and fail.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove dead IllegalArgumentException catch blocks in TenantPortalController
  (delegated methods now throw ResponseStatusException, handled by Spring)
- Add password reset notification email in VendorAdminService.resetAdminPassword
- Add verifyIsVendorAdmin guard to resetAdminPassword and resetAdminMfa
  to prevent platform admins from resetting arbitrary non-admin users

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
docs: update CLAUDE.md for account package, vendor admins, and shared components
Some checks failed
CI / build (push) Failing after 2m1s
CI / docker (push) Has been skipped
CI / build (pull_request) Failing after 1m46s
CI / docker (pull_request) Has been skipped
e9e18f6c38
- Add account/ package to Key Packages table
- Add VendorAdminService/Controller to vendor/ package
- Note TenantPortalService delegation to AccountService
- Update ui/CLAUDE.md: AccountSettingsPage, VendorAdminsPage,
  Administrators sidebar, user menu dropdown, shared components

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
claude added 1 commit 2026-04-27 15:15:23 +02:00
fix: add AccountService mock to TenantPortalServiceTest constructor
All checks were successful
CI / build (push) Successful in 3m9s
CI / build (pull_request) Successful in 3m8s
CI / docker (pull_request) Has been skipped
CI / docker (push) Successful in 1m43s
f823a409d0
The TenantPortalService constructor gained an AccountService parameter
in the consolidation refactor — the test was missing it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
hsiegeln merged commit 0b4d0e3b2f into main 2026-04-27 15:20:23 +02:00
Sign in to join this conversation.