Cập nhật avatar hồ sơ trên web
Feature URL
Module
user
Status
in-development
Priority
P1
Platforms
fe · be
AC progress
8 / 12
Last reviewed
2026-05-29
Mục tiêu
Cho phép user đổi ảnh đại diện trên web để profile, header menu và các public card dễ nhận diện hơn. User module chỉ nhận và lưu avatarUrl đã upload hợp lệ, còn việc upload file thuộc module upload/R2.
Phạm vi
Trong phạm vi (In scope):
- UI chọn ảnh avatar từ trang profile.
- Upload ảnh bằng presigned URL của module upload/R2.
- Lấy public
avatarUrlsau upload thành công. - Gọi
PATCH /api/v1/users/me/avatarđể lưu URL vào profile. - Cập nhật Redux profile và menu avatar sau khi lưu.
- Validate URL phía backend theo R2 public domain cấu hình.
Ngoài phạm vi (Out of scope):
- Crop/chỉnh sửa ảnh nâng cao.
- Lưu binary file trực tiếp ở user module.
- Quản lý xoá file avatar cũ trên R2.
- Avatar cho admin chỉnh sửa user khác.
User Stories
- Là user, tôi muốn đổi avatar để tài khoản dễ nhận biết hơn.
- Là user vừa upload ảnh, tôi muốn thấy avatar mới trên header/menu ngay sau khi lưu.
- Là hệ thống, tôi muốn chỉ chấp nhận avatar URL thuộc storage domain hợp lệ để tránh URL độc hại.
Luồng chức năng
sequenceDiagram
actor User
participant Web
participant Upload as Upload/R2
participant BE
User->>Web: Chọn ảnh avatar
Web->>Upload: Xin presigned URL và upload file
Upload-->>Web: Public avatarUrl
Web->>BE: PATCH /api/v1/users/me/avatar {avatarUrl}
BE->>BE: Validate avatarUrl không blank
BE->>BE: Validate URL thuộc R2 public domain
BE->>BE: Lưu user.avatarUrl
BE-->>Web: UserProfileResponse mới
Web->>User: Hiển thị avatar mớiAcceptance Criteria
- AC-1: Backend có
PATCH /api/v1/users/me/avataryêu cầu quyềnuser:update:self. - AC-2: Request body gồm
avatarUrlbắt buộc. - AC-3:
avatarUrlkhông được blank. - AC-4: Backend validate URL bắt đầu bằng R2 public URL cấu hình.
- AC-5: URL có scheme và host hợp lệ.
- AC-6: URL chứa
..bị từ chối để tránh path traversal. - AC-7: Backend chỉ cập nhật avatar của user hiện tại từ JWT principal.
- AC-8: Backend trả
UserProfileResponsesau khi cập nhật avatar thành công. - AC-9: FE cần thêm flow upload avatar qua module upload/R2.
- AC-10: FE cần gọi
ROUTES_API_USER.AVATAR_UPLOADsau khi có public URL. - AC-11: Sau khi lưu thành công, FE phải cập nhật
profile.current.avatarUrlđể header/menu đổi avatar ngay. - AC-12: FE cần xử lý lỗi upload thất bại và lỗi avatar URL không hợp lệ.
Quy tắc nghiệp vụ
- User module không nhận file upload trực tiếp, chỉ nhận URL sau khi upload hoàn tất.
- Avatar URL phải thuộc public domain storage được backend cấu hình.
- Không được chấp nhận URL ngoài domain để tránh tracking, mixed content hoặc nội dung không kiểm soát.
- Nếu upload R2 thành công nhưng lưu profile thất bại, FE phải báo lỗi và cho user thử lại lưu avatar URL.
- Avatar mới ảnh hưởng đến profile cá nhân, menu tài khoản và public profile/listing owner card.
Dữ liệu & Trạng thái
Entity nghiệp vụ:
User.avatarUrl: URL avatar hiện tại.UpdateAvatarRequest: payload{avatarUrl}.UserProfileResponse: response chứa avatar mới.R2Properties.publicUrl: domain/prefix hợp lệ cho avatar.
Trạng thái user-facing:
selecting-file— user chọn ảnh.uploading— đang upload file lên R2.saving-avatar— đang lưu URL vào user profile.avatar-updated— avatar mới đã được lưu và render.upload-error— upload file thất bại.invalid-avatar-url— URL bị backend từ chối.
Liên quan
- Phụ thuộc: user-profile-view-web
- Ảnh hưởng: user-profile-view-web, user-public-profile-listings-web