Skip to content

Add employee management with email invites and last-admin protection - #2

Merged
navaneeth06 merged 18 commits into
mainfrom
feature/employee-management
Nov 9, 2026
Merged

navaneeth06 merged 18 commits into
mainfrom
feature/employee-management

Conversation

@navaneeth06

@navaneeth06 navaneeth06 commented Nov 9, 2026 •

Copy link
Copy Markdown
Owner

Summary

Administrators can now manage their distributor's employees end to end:
invite by email, set password, edit, change roles, deactivate and reactivate.
Completes build step 2 (login and users).

Endpoints

Method Route Who
GET /api/v1/employees, /api/v1/employees/{id} Administrator
POST /api/v1/employees (invite) Administrator
POST /api/v1/employees/{id}/resend-invite Administrator
PUT /api/v1/employees/{id} (profile) Administrator
PUT /api/v1/employees/{id}/roles Administrator
POST /api/v1/employees/{id}/deactivate, /reactivate Administrator
POST /api/v1/auth/set-password Public (invite token)

Notable design decisions

  • Invites: login is created without a password; a signed, single-use,
    3-day token is emailed (MailKit over SMTP; Mailpit for local dev).
    Email is sent after commit; failure is logged and reported, with resend available.
  • Last administrator: role changes and deactivation lock the tenant row
    (SELECT ... FOR UPDATE) so two admins demoting each other concurrently
    always leave exactly one. Concurrency tests fail when the lock is removed.
  • Email reuse: one active account per email, enforced by a partial unique
    index; reactivation returns 409 if the email is now active elsewhere.
  • Tenant isolation: another distributor's employee returns 404, not 403.
  • Unique violations are translated in UnitOfWork to a provider-neutral
    exception, so the Application layer has no EF/Npgsql dependency.

Testing

  • 132 tests (24 unit, 108 integration on real PostgreSQL via Testcontainers).
  • SMTP sender tested against a Mailpit container.

@navaneeth06
navaneeth06 merged commit 7d01677 into main Nov 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant