feat(v1.1.8): invitations flow (migration 0030 + accept_invite returns session)
migration 0030: app_user_invitations table — surrogate id PK + unique token_hash, app_id FK cascading, pre-stages email + display_name + roles for a user that doesn't exist yet. One-shot via atomic UPDATE SET accepted_at = NOW() WHERE accepted_at IS NULL. UsersServiceImpl gains invitations: Arc<dyn AppUserInvitationRepo> plus a mint_session() helper factored from login() and reused by accept_invite(). users::invite(email, opts) is gated on AppUsersAdmin (per brief — the most senior of the three new capabilities). Optional EmailTemplateOpts inside InviteOpts: omitting the template skips the email send so an admin can stamp invitations for out-of-band delivery (mailers, printed onboarding letters, etc.). If the template is present and the email service isn't configured, surfaces as NotConfigured; non-NotConfigured failures are logged but kept silent so the invitation row remains valid for retry. users::accept_invite(token, password, display_name?) atomically consumes the invitation, validates the new password, creates the user (returning () on DuplicateEmail — sign-up beat acceptance, they'll log in normally), and mints a fresh session via mint_session so the caller can return both the user and a working session token in one round trip. Pre-staged roles are stored on the invitation row but not yet applied — the app_user_roles table arrives in commit 8 (migration 0031). For commit 7 the staged-but-not-applied case logs an info record so an operator can audit the gap. list_invitations + revoke_invitation (admin-mediated, gated on AppUsersAdmin) ship in this commit and become reachable from the HTTP surface later in the series. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ pub mod app_members_api;
|
||||
pub mod app_members_repo;
|
||||
pub mod app_repo;
|
||||
pub mod app_secrets_repo;
|
||||
pub mod app_user_invitation_repo;
|
||||
pub mod app_user_password_reset_repo;
|
||||
pub mod app_user_repo;
|
||||
pub mod app_user_session_repo;
|
||||
@@ -89,6 +90,10 @@ pub use app_user_session_repo::{
|
||||
AppUserSessionLookup, AppUserSessionRepository, AppUserSessionRepositoryError,
|
||||
PostgresAppUserSessionRepository,
|
||||
};
|
||||
pub use app_user_invitation_repo::{
|
||||
AppUserInvitationRepo, AppUserInvitationRepoError, ConsumedInvitation, InvitationRow,
|
||||
PostgresAppUserInvitationRepo,
|
||||
};
|
||||
pub use app_user_password_reset_repo::{
|
||||
AppUserPasswordResetRepo, AppUserPasswordResetRepoError, PostgresAppUserPasswordResetRepo,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user