# DEPLOYMENT SUMMARY - Mandatory Password Change Feature

**Date**: September 1, 2026
**Feature**: Clients must change password on first login
**Current Status**: Implemented locally, needs fixing on live server

---

## FILES TO UPLOAD TO LIVE SERVER

### NEW FILES (3)

#### 1. Database Migration
```
LOCAL:  database/migrations/2026_09_01_141422_add_password_changed_to_users.php
LIVE:   database/migrations/2026_09_01_141422_add_password_changed_to_users.php
ACTION: COPY
```

#### 2. Middleware  
```
LOCAL:  app/Http/Middleware/CheckPasswordChanged.php
LIVE:   app/Http/Middleware/CheckPasswordChanged.php
ACTION: COPY
```

#### 3. View Template
```
LOCAL:  resources/views/client/change-password.blade.php
LIVE:   resources/views/client/change-password.blade.php
ACTION: COPY - **ENSURE CORRECT DIRECTORY PATH**
```

---

### UPDATED FILES (3)

#### 1. Controller
```
LOCAL:  app/Http/Controllers/ClientController.php
LIVE:   app/Http/Controllers/ClientController.php
ACTION: UPDATE - Add 2 methods (showChangePassword, updatePassword)
LINES:  Add around line 4373 (before closing brace)
```

#### 2. Model
```
LOCAL:  app/Models/User.php
LIVE:   app/Models/User.php
ACTION: UPDATE - Add 'password_changed_at' to 2 locations
LOCATION 1: $fillable array (add field name)
LOCATION 2: $casts array (add 'datetime' cast)
```

#### 3. Routes
```
LOCAL:  routes/web.php
LIVE:   routes/web.php
ACTION: UPDATE - Add 2 new routes (GET and POST)
LINES:  Around line 1105, inside client middleware group
```

---

## DATABASE MIGRATION

### Option 1: Via Artisan (Preferred)
```bash
cd /home/dextragr/public_html/will
php artisan migrate
```

### Option 2: Direct SQL
```sql
ALTER TABLE users ADD COLUMN password_changed_at TIMESTAMP NULL DEFAULT NULL AFTER password;
INSERT INTO migrations (migration, batch) VALUES ('2026_09_01_141422_add_password_changed_to_users', 1);
```

---

## DEPLOYMENT CHECKLIST

- [ ] Copy migration file to `database/migrations/`
- [ ] Copy middleware file to `app/Http/Middleware/`
- [ ] Copy view file to `resources/views/client/` **← CRITICAL**
- [ ] Update controller with 2 new methods
- [ ] Update model with fillable and casts
- [ ] Update routes with 2 new routes
- [ ] Run migration: `php artisan migrate`
- [ ] Clear cache: `php artisan view:clear && php artisan cache:clear`
- [ ] Test: Login with client account, should redirect to password change form

---

## WHAT EACH FILE DOES

### CheckPasswordChanged.php (Middleware)
- Intercepts all client requests
- Checks if `password_changed_at` is NULL
- If NULL, redirects to password change form
- Prevents skipping password change on first login

### change-password.blade.php (View)
- Password change form with validation UI
- Shows current password, new password, confirm password fields
- Password requirements display (8+ chars, uppercase, lowercase, numbers)
- JavaScript for password visibility toggle and match validation

### ClientController Methods (Controller)
- `showChangePassword()`: Displays the password change form
- `updatePassword()`: Processes password update, validates, saves to database

### User Model Changes
- Allows `password_changed_at` to be mass-assigned (fillable)
- Casts `password_changed_at` to datetime for database queries

### Routes
- `GET /client/change-password` → shows form
- `POST /client/change-password` → processes password update

### Migration
- Adds `password_changed_at` timestamp column to users table
- NULL by default (indicating never changed)
- Set to NOW when password is first changed

---

## EXACT CHANGES IN EACH FILE

### 1. app/Http/Controllers/ClientController.php

Add these 2 methods (around line 4373):

```php
    /**
     * Show password change form
     */
    public function showChangePassword()
    {
        return view('client.change-password');
    }

    /**
     * Update password
     */
    public function updatePassword(Request $request)
    {
        $user = auth()->user();

        // Validate input
        $validated = $request->validate([
            'current_password' => 'required|current_password',
            'password' => 'required|string|min:8|regex:/[A-Z]/|regex:/[a-z]/|regex:/[0-9]/|confirmed',
            'password_confirmation' => 'required',
        ]);

        // Update password
        $user->update([
            'password' => bcrypt($validated['password']),
            'password_changed_at' => now(),
        ]);

        // Log the password change
        \App\Models\Activity::create([
            'user_id' => $user->id,
            'action' => 'Password changed',
            'module' => 'Auth',
            'description' => 'Client changed password',
        ]);

        return redirect()->route('client.dashboard')->with('success', 'Password changed successfully!');
    }
```

---

### 2. app/Models/User.php

**Location 1 - Fillable array** (around line 30):
```php
protected $fillable = [
    'name',
    'email',
    'password',
    'password_changed_at',  // ← ADD THIS
    'role',
    'phone',
    'status',
    // ... rest of fields
];
```

**Location 2 - Casts array** (around line 45):
```php
protected $casts = [
    'email_verified_at' => 'datetime',
    'password_changed_at' => 'datetime',  // ← ADD THIS
    // ... rest of casts
];
```

---

### 3. routes/web.php

Add these routes around line 1105, inside the client group:

```php
    // Password Change Routes - Mandatory on first login
    Route::get('/change-password', [ClientController::class, 'showChangePassword'])->name('client.change-password');
    Route::post('/change-password', [ClientController::class, 'updatePassword'])->name('client.update-password');
```

---

## POST-DEPLOYMENT STEPS

### 1. Move view file to correct location
```bash
# If file is in wrong directory
find /home/dextragr/public_html/will -name "change-password.blade.php"

# Move to correct location
mv /old/path/change-password.blade.php /home/dextragr/public_html/will/resources/views/client/
```

### 2. Run migration
```bash
cd /home/dextragr/public_html/will
php artisan migrate
```

### 3. Clear cache
```bash
cd /home/dextragr/public_html/will
php artisan view:clear
php artisan cache:clear
php artisan config:clear
php artisan optimize
```

### 4. Test the feature
1. Open `https://will.dextragroups.com/client/login`
2. Login with client credentials (IC number as password)
3. Should redirect to `https://will.dextragroups.com/client/change-password`
4. Should see password change form
5. Submit form with new password (8+ chars, uppercase, lowercase, number)
6. Should redirect to dashboard after successful change

---

## IMPORTANT NOTES

1. **View file path is critical**: Must be exactly `resources/views/client/change-password.blade.php`
2. **Password validation**: Min 8 chars, uppercase, lowercase, digit required
3. **First login only**: Redirect only happens if `password_changed_at` is NULL
4. **No bypassing**: Middleware blocks access to portal until password is changed
5. **Database column**: Must be added to users table for feature to work

---

## SUPPORT

If you encounter issues during deployment:

1. **"View not found" error**: View file in wrong directory - move to `resources/views/client/`
2. **"Column doesn't exist" error**: Migration not run - run `php artisan migrate`
3. **"Route not defined" error**: Routes not added to web.php - check routes file
4. **Middleware not working**: Ensure CheckPasswordChanged is in Kernel.php or routes

See `LIVE_SERVER_FIX_GUIDE.md` for detailed troubleshooting.
