costco-grocery-list/docs/archive/ACCOUNT_MANAGEMENT_IMPLEMENTATION.md
2026-01-27 00:03:58 -08:00

199 lines
5.8 KiB
Markdown

# Account Management Implementation (Phase 4)
## Overview
Phase 4 adds account management features allowing users to:
- Change their display name (friendly name separate from username)
- Change their password with current password verification
## Database Changes
### Migration: `add_display_name_column.sql`
```sql
ALTER TABLE users
ADD COLUMN IF NOT EXISTS display_name VARCHAR(100);
UPDATE users
SET display_name = name
WHERE display_name IS NULL;
```
**To run migration:**
Connect to your PostgreSQL database and execute:
```bash
psql -U your_user -d your_database -f backend/migrations/add_display_name_column.sql
```
## Backend Implementation
### New Model Functions (`backend/models/user.model.js`)
- `getUserById(id)` - Fetch user by ID including display_name
- `updateUserProfile(id, updates)` - Update user profile (display_name)
- `updateUserPassword(id, hashedPassword)` - Update user password
- `getUserPasswordHash(id)` - Get current password hash for verification
### New Controllers (`backend/controllers/users.controller.js`)
- `getCurrentUser` - GET authenticated user's profile
- `updateCurrentUser` - PATCH user's display name
- Validates: 1-100 characters, trims whitespace
- `changePassword` - POST password change
- Validates: current password correct, new password min 6 chars, passwords match
- Uses bcrypt for password verification and hashing
### New Routes (`backend/routes/users.routes.js`)
All routes require authentication (`auth` middleware):
- `GET /api/users/me` - Get current user profile
- `PATCH /api/users/me` - Update display name
- `POST /api/users/me/change-password` - Change password
**Request bodies:**
```javascript
// Update display name
PATCH /api/users/me
{
"display_name": "New Display Name"
}
// Change password
POST /api/users/me/change-password
{
"current_password": "oldpass123",
"new_password": "newpass123"
}
```
## Frontend Implementation
### API Functions (`frontend/src/api/users.js`)
- `getCurrentUser()` - Fetch current user profile
- `updateCurrentUser(display_name)` - Update display name
- `changePassword(current_password, new_password)` - Change password
### Settings Page Updates (`frontend/src/pages/Settings.jsx`)
Added new "Account" tab with two sections:
**Display Name Section:**
- Input field with character counter (max 100)
- Real-time validation
- Save button with loading state
**Password Change Section:**
- Current password field
- New password field (min 6 chars)
- Confirm password field
- Client-side validation before submission
- Loading state during submission
**Features:**
- Success/error messages displayed at top of tab
- Form validation (character limits, password matching)
- Disabled buttons during API calls
- Auto-clears password fields on success
### Styling (`frontend/src/styles/pages/Settings.css`)
Added:
- `.account-form` - Form container styling
- `.account-message` - Success/error message styling
- `.account-message.success` - Green success messages
- `.account-message.error` - Red error messages
## Security Features
### Password Requirements
- **Backend validation:**
- Minimum 6 characters
- Current password verification before change
- bcrypt hashing (10 rounds)
- **Frontend validation:**
- HTML5 minlength attribute
- Client-side password matching check
- Current password required
### Display Name Validation
- **Backend:**
- 1-100 character limit
- Whitespace trimming
- **Frontend:**
- HTML5 maxlength attribute
- Character counter
## Usage
### For Users
1. Navigate to Settings → Account tab
2. **Change Display Name:**
- Enter new display name (1-100 chars)
- Click "Save Display Name"
3. **Change Password:**
- Enter current password
- Enter new password (min 6 chars)
- Confirm new password
- Click "Change Password"
### For Developers
**Testing the endpoints:**
```bash
# Get current user
curl -X GET http://localhost:5000/api/users/me \
-H "Authorization: Bearer YOUR_TOKEN"
# Update display name
curl -X PATCH http://localhost:5000/api/users/me \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"display_name": "New Name"}'
# Change password
curl -X POST http://localhost:5000/api/users/me/change-password \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"current_password": "oldpass",
"new_password": "newpass"
}'
```
## Next Steps
### Optional Enhancements
1. **Password strength indicator** - Visual feedback on password complexity
2. **Display name in navbar** - Show display_name instead of username in UI
3. **Email verification** - Add email field and verification
4. **2FA support** - Two-factor authentication option
5. **Password history** - Prevent reusing recent passwords
6. **Session management** - View/revoke active sessions
### Integration with AuthContext
Consider updating `AuthContext` to:
- Store and expose display_name
- Refresh user data after profile updates
- Show display_name in navbar/profile components
## Files Modified
### Backend
-`backend/migrations/add_display_name_column.sql` (NEW)
-`backend/models/user.model.js`
-`backend/controllers/users.controller.js`
-`backend/routes/users.routes.js`
### Frontend
-`frontend/src/api/users.js`
-`frontend/src/pages/Settings.jsx`
-`frontend/src/styles/pages/Settings.css`
## Testing Checklist
- [ ] Run database migration
- [ ] Test GET /api/users/me endpoint
- [ ] Test display name update with valid data
- [ ] Test display name update with invalid data (empty, too long)
- [ ] Test password change with correct current password
- [ ] Test password change with incorrect current password
- [ ] Test password change with mismatched new passwords
- [ ] Test password change with weak password (< 6 chars)
- [ ] Verify frontend validation prevents invalid submissions
- [ ] Verify success/error messages display correctly
- [ ] Test UI responsiveness on mobile