[CLAUDE] Auth: user tự đổi mật khẩu (self-service change-password) — BE + 2 FE + test
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m10s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m10s
Go-live request anh Kiệt FDC (Zalo "user chưa tự đổi pass được hả em"): trước đây chỉ admin
Reset hộ (POST users/{id}/reset-password), user KHÔNG tự đổi được. Thêm self-service:
- BE: ChangePasswordCommand + POST /api/auth/change-password ([Authorize]). Lấy user qua
ICurrentUser.UserId; UserManager.ChangePasswordAsync verify mật khẩu HIỆN TẠI; sai →
ValidationException field CurrentPassword "Mật khẩu hiện tại không đúng."; rule mật khẩu mới
≥ 12 + khác mật khẩu cũ (validator); sau đổi vô hiệu refresh token (mirror ResetPassword).
Qualify SolutionErp...ValidationException (tránh CS0104 clash với FluentValidation).
- FE 2 app (SHA-mirror): ChangePasswordDialog (3 ô current/new/confirm + validate client:
≥12, khớp, khác cũ) wire vào menu tài khoản TopBar — "Đổi mật khẩu" trên "Đăng xuất".
- Test: +ChangePasswordCommandTests (đúng/sai pass cũ keyed-field + msg, <12 boundary, ==cũ,
chưa-auth/UserId-null/user-not-found, RefreshToken cleared). Full suite 431 PASS (45D + 386I).
Build: BE 0 warn/0 err · fe-user + fe-admin build OK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -1,12 +1,14 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { ChevronDown, LogOut } from 'lucide-react'
|
||||
import { ChevronDown, LogOut, KeyRound } from 'lucide-react'
|
||||
import { useAuth } from '@/contexts/AuthContext'
|
||||
import { ChangePasswordDialog } from '@/components/ChangePasswordDialog'
|
||||
import { NotificationBell } from '@/components/NotificationBell'
|
||||
import { cn } from '@/lib/cn'
|
||||
|
||||
function UserMenu() {
|
||||
const { user, logout } = useAuth()
|
||||
const [open, setOpen] = useState(false)
|
||||
const [pwOpen, setPwOpen] = useState(false)
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
@ -53,6 +55,16 @@ function UserMenu() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
onClick={() => {
|
||||
setPwOpen(true)
|
||||
setOpen(false)
|
||||
}}
|
||||
className="flex w-full items-center gap-2 px-4 py-2 text-sm text-slate-600 transition hover:bg-slate-50"
|
||||
>
|
||||
<KeyRound className="h-4 w-4" />
|
||||
Đổi mật khẩu
|
||||
</button>
|
||||
<button
|
||||
onClick={logout}
|
||||
className="flex w-full items-center gap-2 px-4 py-2 text-sm text-slate-600 transition hover:bg-slate-50"
|
||||
@ -62,6 +74,7 @@ function UserMenu() {
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<ChangePasswordDialog open={pwOpen} onClose={() => setPwOpen(false)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user