Tóm tắt
Tạo tài khoản giờ mặc định gửi email mời (người dùng tự đặt mật khẩu qua link) — form tạo tài khoản hiện tại
gửi password sẽ bị 400 cho tới khi FE sửa. Thêm luồng quên / đặt lại mật khẩu qua email, và tài khoản khách
(phân hệ Tài khoản khách) đăng nhập được với quyền tối thiểu. FE cần 3 trang mới. Spec: specs/002-account-email-links/.
Chi tiết
POST /users: body thêmsendInvite?: boolean(mặc địnhtrue),passwordthành tuỳ chọn.- Mời (mặc định, không
password) → 201status: "pending"+ email mời. - Tự đặt mật khẩu:
sendInvite: false+password→ 201status: "active", không email. passwordmà khôngsendInvite: false→ 400identity.user.invite_with_password;sendInvite: falsethiếupassword→ 400identity.user.password_required.
- Mời (mặc định, không
POST /users/:id/resend-invite,POST /guest-accounts/:id/resend-invite(owner/system_admin) → 204; tài khoản đã kích hoạt → 400identity.user.not_pending.- Công khai:
POST /auth/set-password {token,password}→ 204;POST /auth/forgot-password {email}→ luôn 202{ data: null };POST /auth/reset-password {token,password}→ 204. Link sai/hết hạn/đã dùng → 400identity.account_link.invalid. Tài khoảnpendingđăng nhập → 401. - Link trong email:
{APP_WEB_URL}/set-password?token=...(hạn 72 giờ),{APP_WEB_URL}/reset-password?token=...(hạn 30 phút). Đặt lại mật khẩu xong, refresh token cũ → 401 (thiết bị khác phải đăng nhập lại). POST /guest-accounts: tạo thêm tài khoản đăng nhập khách + email mời; response thêmuserId. Email/username đã dùng bởi nhân viên → 409.- Access token có claim
userType: "employee" | "guest". Phiên khách gọi bất kỳ API nào (cả 4 service) ngoàiGET /users/me,GET /notifications,PATCH /notifications/:id/read,GET/PUT /notifications/preferences→ 403identity.auth.guest_forbidden. GET /userskhông còn trả user loại khách (kể cả khách tạo quaPOST /usersvớiuserType: "guest").
Contract (trước → sau)
| Trước | Sau | |
|---|---|---|
| Endpoint | POST /users |
không đổi + mới: /auth/set-password, /auth/forgot-password, /auth/reset-password, /users/:id/resend-invite, /guest-accounts/:id/resend-invite |
| Request | POST /users { ..., password } |
{ ..., sendInvite?: boolean = true, password?: string } |
| Response | User active |
User pending khi mời; GuestAccount + userId; token có userType |
| Lỗi | — | 400 identity.user.invite_with_password / identity.user.password_required / identity.user.not_pending / identity.account_link.invalid; 403 identity.auth.guest_forbidden |
Việc bên nhận cần làm
- FE (chặn): form tạo tài khoản — checkbox "Gửi email mời" (mặc định bật); bỏ chọn mới hiện ô mật khẩu và gửi
sendInvite: false. - FE: trang
/set-password?token=và/reset-password?token=(nhập mật khẩu mới, ≥ 8 ký tự; lỗiidentity.account_link.invalid→ "Link đã hết hạn hoặc đã dùng"). - FE: link "Quên mật khẩu?" trên trang đăng nhập → form email → luôn hiện "Nếu email tồn tại, bạn sẽ nhận được link".
- FE: nút "Gửi lại lời mời" cho tài khoản
pending(thành viên và khách). - FE: phiên khách (
userType: "guest") — chỉ hiện hồ sơ + thông báo; không gọi API khác.
Cách kiểm tra
Xem specs/002-account-email-links/quickstart.md (MailHog http://localhost:8025).
Thảo luận
[BE] 2026-09-24 @ThaiThanhLuan — raised
Thay đổi phá vỡ ở POST /users là quyết định có chủ đích (mặc định gửi mời như tài liệu khảo sát). Mobile n/a: mobile/ chưa có code.
[FE] 2026-09-25 @NinelXram — acked
Làm trên branch feat/fe-identity-invite-iam, gộp chung với note IAM vì cùng sửa form tạo tài khoản: checkbox gửi mời,
trang set/reset password, quên mật khẩu, gửi lại lời mời, giới hạn phiên khách.
[FE] 2026-09-25 @NinelXram — applied
Commit e4e9c11 (branch feat/fe-identity-invite-iam). Đủ 5 việc. Lưu ý: GuestAccount không có trạng thái pending
của tài khoản đăng nhập nên nút "Gửi lại lời mời" hiện với mọi khách đang hoạt động; khách đã kích hoạt thì FE báo lỗi
identity.user.not_pending. Nếu BE trả thêm trạng thái đăng nhập của khách thì FE sẽ ẩn nút đúng lúc.