Administrator — User Management Documentation

Version: 1.0
Last updated: December 10, 2025

Table of Contents


1. Overview

User Management is the core administrative module for managing employee and system user accounts in the DTR System. Administrators can:

  • Create, read, update and delete user accounts
  • Assign roles, permissions and departmental affiliations
  • Manage user profiles (avatar, contact info, position details)
  • Reset passwords and manage account status
  • Audit user actions and track login history
  • Integrate user data with DTR, payroll and scheduling systems

Key files involved:

  • Admin views: resources/views/users/admin/user/ (index, create, edit, show)
  • Controllers: UserController.php, ProfileController.php, SettingController.php
  • Models: App\Models\User, App\Models\Profile, App\Models\Role, App\Models\Permission
  • User-facing views: resources/views/user/ (profile, settings)

2. Purpose & Scope

Purpose:

  • Centralized user account administration (employees, contractors, service accounts)
  • Role-based access control (RBAC) management
  • User profile and contact information maintenance
  • Account lifecycle management (onboarding to offboarding)
  • Compliance and audit trail generation

Scope:

  • Create / read / update / delete user records
  • Assign roles and permissions
  • Manage user status (active, inactive, suspended, terminated)
  • Upload profile photos and documents
  • Reset passwords and manage security
  • Export user data for payroll/HR systems
  • Track login history and audit user actions

Out of scope:

  • Active Directory / LDAP synchronization (documented separately)
  • Advanced identity verification (documented separately)
  • Custom user fields beyond standard schema

3. Access & Permissions

Required permissions:

  • view_users — view user list and details
  • create_users — create new user accounts
  • edit_users — edit user information
  • delete_users — delete user records
  • manage_roles — assign/modify roles
  • manage_permissions — assign/modify permissions
  • reset_password — reset user password
  • view_audit_logs — view user audit trail

Recommended roles:

  • Super Admin — full CRUD, role management, audit access, can impersonate users
  • HR Manager — create/edit users, assign basic roles, view profiles
  • Department Lead — view and request user changes for own department
  • IT Admin — manage account status, reset passwords, manage security
  • User — view own profile, update own settings (limited)

Implementation note:

  • Enforce RBAC server-side in UserController via middleware or gate checks
  • UI hides sensitive actions (delete, reset password) for non-admin roles
  • Use authorize() in controller methods or Gate policies

4. How to Access

Admin URLs:

  • Users index: /admin/user
  • Create user: /admin/user/create
  • Edit user: /admin/user/{id}/edit
  • Show user: /admin/user/{id}
  • User roles/permissions: /admin/user/{id}/roles

Employee URLs:

  • My profile: /user/profile
  • Account settings: /user/settings
  • Change password: /user/settings/password

Browser requirements: Modern Chromium-based browsers, recent Safari/Firefox. Mobile viewing supported; recommend desktop for full management.


5. Interface Layout & Views

5.1 Index (Users List)

Purpose: Display all users with filtering, search and bulk actions.

UI elements:

  • Search bar: filter by name, email, employee ID, department
  • Filters:
    • Status (active, inactive, suspended, terminated)
    • Department / Team
    • Role (admin, employee, hr-manager, etc.)
    • Date range (created, last login)
  • Table columns:
    • Avatar / Name
    • Email / Employee ID
    • Department / Position
    • Role(s)
    • Status (badge)
    • Last Login
    • Actions (View | Edit | Reset Password | Suspend | Delete)
  • Pagination: 25 items per page (configurable)
  • Bulk actions: Assign role, Deactivate, Export, Delete selected

Key features:

  • Inline status badge (green=active, gray=inactive, red=suspended)
  • Quick actions dropdown per row
  • Export to CSV/Excel with configurable columns
  • Advanced filter panel for complex queries

5.2 Create User

Purpose: Register a new user account (employee, contractor, system account).

Form fields:

  • Basic info:

    • First Name (required, string, max 255)
    • Last Name (required, string, max 255)
    • Email (required, unique, valid email)
    • Phone Number (optional, valid phone format)
    • Date of Birth (optional, date picker)
  • Employment info:

    • Employee ID (optional, unique, string)
    • Department (required, dropdown)
    • Position / Job Title (required, dropdown/text)
    • Employment Type (Full-time, Part-time, Contract, Temporary)
    • Start Date (required, date picker)
    • Manager (optional, user dropdown)
  • Credentials:

    • Password (required, min 8 chars, must include upper/lower/number/symbol)
    • Confirm Password (required, match validation)
    • Send welcome email (checkbox, default true)
  • Settings:

    • Status (Active / Inactive / Suspended, radio)
    • Roles (multi-select checkbox)
    • Avatar (optional, image, max 2MB)
    • Two-factor authentication (optional, checkbox)

On submit (store method):

  1. Validate all inputs
  2. Check email uniqueness
  3. Hash password using bcrypt
  4. Create User record + Profile record
  5. Assign roles and default permissions
  6. Upload avatar if provided
  7. Create audit log entry
  8. Send welcome email (if checked) with temp password or reset link
  9. Redirect to edit view with success message

Controller method overview:

public function store(Request $request)
{
    $validated = $request->validate([
        'first_name' => 'required|string|max:255',
        'last_name' => 'required|string|max:255',
        'email' => 'required|email|unique:users',
        'password' => 'required|min:8|confirmed|password_rules',
        'department_id' => 'required|exists:departments,id',
        'position_id' => 'required|exists:positions,id',
        'employment_type' => 'required|in:full-time,part-time,contract,temporary',
        'start_date' => 'required|date|before_or_equal:today',
        'roles' => 'nullable|array|exists:roles,id',
        'avatar' => 'nullable|image|mimes:png,jpg,jpeg|max:2048',
    ]);

    $user = new User([
        'first_name' => $validated['first_name'],
        'last_name' => $validated['last_name'],
        'email' => $validated['email'],
        'password' => Hash::make($validated['password']),
    ]);
    $user->save();

    $user->profile()->create([
        'department_id' => $validated['department_id'],
        'position_id' => $validated['position_id'],
        'employment_type' => $validated['employment_type'],
        'start_date' => $validated['start_date'],
        'manager_id' => $validated['manager_id'] ?? null,
    ]);

    if ($request->has('roles')) {
        $user->assignRole($validated['roles']);
    }

    if ($request->hasFile('avatar')) {
        $path = $request->file('avatar')->store('avatars', 'public');
        $user->update(['avatar' => $path]);
    }

    return redirect()->route('admin.user.edit', $user->id)
        ->with('message', 'User created successfully');
}

5.3 Edit User

Purpose: Modify existing user account and profile information.

Editable fields:

  • First Name, Last Name
  • Email (can change if not in use)
  • Phone Number
  • Department, Position, Manager
  • Employment Type, Start Date, End Date (if terminated)
  • Status (active/inactive/suspended)
  • Roles (multi-select)
  • Avatar (replace)
  • Two-factor authentication toggle

Non-editable fields:

  • Employee ID (immutable for audit)
  • Password (via separate form)
  • User ID (immutable)
  • Created timestamp

UI behaviors:

  • Show change history (who changed what, when)
  • Warn if changing email (verify confirmation)
  • Inline validation with helpful error messages
  • Save button triggers comprehensive validation
  • "Reset Password" button (separate action, requires confirmation)
  • "Suspend Account" / "Reactivate Account" buttons

Controller method overview:

public function edit(string $id)
{
    $user = User::with(['profile', 'roles'])->findOrFail($id);
    return view('users.admin.user.edit', compact('user'));
}

public function update(Request $request, string $id)
{
    $user = User::findOrFail($id);

    $validated = $request->validate([
        'first_name' => 'required|string|max:255',
        'last_name' => 'required|string|max:255',
        'email' => "required|email|unique:users,email,{$id}",
        'phone_number' => 'nullable|phone:AUTO',
        'status' => 'required|in:active,inactive,suspended,terminated',
        'roles' => 'nullable|array|exists:roles,id',
        'avatar' => 'nullable|image|mimes:png,jpg,jpeg|max:2048',
    ]);

    $user->update([
        'first_name' => $validated['first_name'],
        'last_name' => $validated['last_name'],
        'email' => $validated['email'],
        'phone_number' => $validated['phone_number'],
        'status' => $validated['status'],
    ]);

    if ($request->has('roles')) {
        $user->syncRoles($validated['roles']);
    }

    if ($request->hasFile('avatar')) {
        $path = $request->file('avatar')->store('avatars', 'public');
        $user->update(['avatar' => $path]);
    }

    return redirect()->back()->with('message', 'User updated successfully');
}

5.4 Show / User Details

Purpose: View complete user profile and activity history.

Sections:

  • Header: Avatar, name, email, status badge, last login
  • Personal info: DOB, phone, address, emergency contact
  • Employment: Department, position, manager, start date, employment type
  • System info: User ID, created date, last updated
  • Roles & Permissions: Current roles, assigned permissions (list/table)
  • Activity log:
    • Last 10 login attempts (date, time, IP, device)
    • Last 10 actions (create/update records, what changed)
  • Documents: Attached files (employment contract, NDA, certifications)
  • Quick actions: Edit, Reset Password, Reset 2FA, Suspend, Delete

Controller method:

public function show(string $id)
{
    $user = User::with([
        'profile.department',
        'profile.position',
        'roles.permissions',
        'loginHistory' => fn($q) => $q->orderBy('created_at', 'desc')->limit(10),
        'auditLog' => fn($q) => $q->orderBy('created_at', 'desc')->limit(10),
    ])->findOrFail($id);

    return view('users.admin.user.show', compact('user'));
}

5.5 User Profile & Settings

Purpose: Allow users to view and update their own profile (employee-facing).

Employee Profile View (/user/profile):

  • Avatar (editable)
  • Name, email, phone (mostly view-only, some editable per policy)
  • Department, position, manager (read-only)
  • Timezone (editable, affects DTR/schedule times)
  • Language preference (editable dropdown)

Employee Settings (/user/settings):

  • Change password (current password + new password + confirm)
  • Two-factor authentication (enable/disable, show recovery codes)
  • Email notifications (toggle per category: shift, leave approval, DTR issues)
  • Calendar preferences (default view, work hours display)
  • Time tracking preferences (geo-fence, mobile app tracking)
  • Connected apps (linked SSO apps, revoke access)

Controller method:

public function showProfile()
{
    return view('user.profile', ['user' => auth()->user()->load('profile')]);
}

public function updateProfile(Request $request)
{
    $validated = $request->validate([
        'phone_number' => 'nullable|phone:AUTO',
        'timezone' => 'required|timezone',
        'language' => 'required|in:en,es,fr,tl',
        'avatar' => 'nullable|image|mimes:png,jpg,jpeg|max:2048',
    ]);

    $user = auth()->user();
    $user->update($validated);

    if ($request->hasFile('avatar')) {
        $path = $request->file('avatar')->store('avatars', 'public');
        $user->update(['avatar' => $path]);
    }

    return back()->with('message', 'Profile updated successfully');
}

6. Key Features

  • Centralized user registry: Single source of truth for all users in DTR system
  • Flexible role assignment: Support for multiple roles per user with inheritance
  • Permission-based access: Fine-grained control via permissions attached to roles
  • Profile enrichment: Store extended attributes (avatar, department, position, manager)
  • Status lifecycle: Active, inactive, suspended, terminated states with audit
  • Bulk operations: Create, import, assign roles to multiple users at once
  • Two-factor authentication: Optional 2FA with TOTP (Google Authenticator) support
  • Login history: Track successful and failed login attempts
  • Audit trail: Record all changes to user records with who/when/why
  • Integration hooks: API to sync with payroll, HRIS, directory systems
  • Export & reports: Generate user rosters, role matrices, audit reports

7. Data Model & Database

User model fields:

id                 — Primary key
first_name         — String (max 255)
last_name          — String (max 255)
email              — String (unique, max 255)
phone_number       — String (nullable)
date_of_birth      — Date (nullable)
password           — String (hashed)
avatar             — String/path (nullable, image URL)
status             — Enum: active, inactive, suspended, terminated
timezone           — String (default 'UTC')
language           — String (default 'en')
last_login_at      — Timestamp (nullable)
email_verified_at  — Timestamp (nullable)
two_factor_enabled — Boolean (default false)
created_at         — Timestamp
updated_at         — Timestamp
deleted_at         — Timestamp (soft delete)

Profile model fields:

id                 — Primary key
user_id            — Foreign key to users
employee_id        — String (unique, nullable)
department_id      — Foreign key to departments
position_id        — Foreign key to positions
employment_type    — Enum: full-time, part-time, contract, temporary
start_date         — Date
end_date           — Date (nullable, for terminations)
manager_id         — Foreign key to users (nullable, self-referencing)
bio                — Text (nullable)
emergency_contact  — String (nullable)
emergency_phone    — String (nullable)
address            — Text (nullable)
city               — String (nullable)
country            — String (nullable)
created_at         — Timestamp
updated_at         — Timestamp

Role model (Spatie Laravel-permission):

id                 — Primary key
name               — String (unique, e.g., 'admin', 'hr-manager')
guard_name         — String (default 'web')
created_at         — Timestamp

Permission model:

id                 — Primary key
name               — String (unique, e.g., 'view_users', 'edit_users')
guard_name         — String (default 'web')
created_at         — Timestamp

Sample records:

User:

id: 1
first_name: "Jane"
last_name: "Doe"
email: "jane.doe@company.com"
phone_number: "+1-555-0100"
date_of_birth: "1990-05-15"
password: "y$..." (bcrypt hash)
status: "active"
avatar: "storage/avatars/jane_doe.jpg"
last_login_at: "2025-12-10 09:45:00"

Profile:

id: 1
user_id: 1
employee_id: "EMP-00001"
department_id: 5 (HR)
position_id: 12 (HR Manager)
employment_type: "full-time"
start_date: "2020-03-01"
manager_id: null (no manager, reports to director)

Role:

id: 1
name: "hr-manager"

Permission:

id: 1
name: "view_users"

8. User Roles & Permissions

Predefined roles (suggested):

  1. Super Admin

    • Permissions: : (all)
    • Can create/delete users, manage roles, access audit logs, impersonate users
  2. Admin

    • Permissions: manage_users, manage_roles, manage_permissions, view_audit_logs
    • Full user management (CRUD) + role assignments
  3. HR Manager

    • Permissions: view_users, create_users, edit_users, view_audit_logs
    • Can manage employees but not admins; no delete permission
  4. IT Admin

    • Permissions: reset_password, manage_account_status, view_audit_logs
    • Password resets, account suspensions; no user creation/deletion
  5. Department Lead

    • Permissions: view_users (department-filtered), request_user_changes
    • View own team; request changes for admin approval
  6. Employee

    • Permissions: view_own_profile, edit_own_profile, view_own_audit_logs
    • Limited to own account only

Permission matrix example:

Permission Super Admin Admin HR Manager IT Admin Dept Lead Employee
view_users ✓ (own dept) ✓ (own)
create_users
edit_users ✓ (own)
delete_users
reset_password ✓ (own)
manage_roles
manage_permissions
view_audit_logs ✓ (own)

9. API Endpoints

9.1 Admin API (User Management)

GET /api/admin/users

  • Returns paginated list of all users
  • Query params: page, search, department_id, status, role
  • Response:
    {
        "data": [
            {
                "id": 1,
                "first_name": "Jane",
                "last_name": "Doe",
                "email": "jane@example.com",
                "phone_number": "+1-555-0100",
                "status": "active",
                "department": "HR",
                "position": "HR Manager",
                "roles": ["hr-manager"],
                "avatar_url": "https://cdn.../avatar.jpg",
                "last_login_at": "2025-12-10T09:45:00Z"
            }
        ],
        "pagination": { "total": 150, "per_page": 25, "current_page": 1 }
    }

GET /api/admin/users/{id}

  • Returns single user with full details (including profile, roles, permissions)
  • Response:
    {
      "id": 1,
      "first_name": "Jane",
      "last_name": "Doe",
      "email": "jane@example.com",
      "phone_number": "+1-555-0100",
      "date_of_birth": "1990-05-15",
      "status": "active",
      "timezone": "Asia/Manila",
      "language": "en",
      "last_login_at": "2025-12-10T09:45:00Z",
      "two_factor_enabled": true,
      "profile": {
        "employee_id": "EMP-00001",
        "department": "HR",
        "position": "HR Manager",
        "employment_type": "full-time",
        "start_date": "2020-03-01",
        "manager": "John Smith"
      },
      "roles": [
        {
          "id": 3,
          "name": "hr-manager",
          "permissions": ["view_users", "create_users", "edit_users", ...]
        }
      ]
    }

POST /api/admin/users

  • Create new user
  • Body:
    {
        "first_name": "John",
        "last_name": "Smith",
        "email": "john.smith@example.com",
        "phone_number": "+1-555-0200",
        "password": "SecurePass123!",
        "department_id": 5,
        "position_id": 12,
        "employment_type": "full-time",
        "start_date": "2025-01-01",
        "roles": [3],
        "send_welcome_email": true
    }
  • Response: 201 Created + user record

PUT /api/admin/users/{id}

  • Update user (name, email, status, roles, etc.)
  • Body: (any of create fields)
  • Response: 200 OK + updated user

DELETE /api/admin/users/{id}

  • Soft or hard delete user (requires confirmation)
  • Response: 200 OK + confirmation message

POST /api/admin/users/{id}/reset-password

  • Send password reset email or generate temporary password
  • Body: (optional) temporary_password: boolean
  • Response: 200 OK
    {
      "message": "Password reset email sent",
      "temporary_password": "TempPass123!" (if requested)
    }

POST /api/admin/users/{id}/suspend

  • Suspend user account (prevent login)
  • Body: reason: "string"
  • Response: 200 OK

POST /api/admin/users/{id}/reactivate

  • Reactivate suspended user
  • Response: 200 OK

POST /api/admin/users/bulk-import

  • Create multiple users from CSV
  • Body: file (CSV upload) or users (JSON array)
  • Response: 200 OK
    {
      "message": "Import successful",
      "created": 45,
      "failed": 2,
      "errors": [...]
    }

POST /api/admin/users/{id}/assign-roles

  • Update user roles
  • Body:
    {
        "roles": [3, 5, 7]
    }
  • Response: 200 OK + updated user

9.2 Profile API

GET /api/profile

  • Get current user's profile
  • Response: (same as /api/admin/users/{id})

PUT /api/profile

  • Update current user's profile (phone, timezone, language, avatar)
  • Body:
    {
        "phone_number": "+1-555-0100",
        "timezone": "Asia/Manila",
        "language": "en",
        "avatar": "<file upload>"
    }
  • Response: 200 OK + updated profile

POST /api/profile/avatar

  • Upload profile avatar
  • Body: avatar (file)
  • Response: 200 OK + avatar_url

9.3 Authentication API

POST /api/login

  • Authenticate user (email + password)
  • Body:
    {
        "email": "jane@example.com",
        "password": "SecurePass123!"
    }
  • Response: 200 OK
    {
      "token": "eyJhbGc...",
      "user": { ... }
    }

POST /api/logout

  • Revoke authentication token
  • Headers: Authorization: Bearer {token}
  • Response: 200 OK

POST /api/password/reset-request

  • Request password reset (email-based)
  • Body: email: "jane@example.com"
  • Response: 200 OK

POST /api/password/reset

  • Reset password with token
  • Body:
    {
        "token": "reset-token-123",
        "password": "NewPass456!",
        "password_confirmation": "NewPass456!"
    }
  • Response: 200 OK

10. Controller Implementation Details

10.1 UserController

Location: app/Http/Controllers/Web/Admin/UserController.php or app/Http/Controllers/API/UserController.php

Key methods:

index() — List all users

public function index(Request $request)
{
    $users = User::with('profile.department', 'roles')
        ->when($request->search, fn($q) =>
            $q->where('first_name', 'like', "%{$request->search}%")
             ->orWhere('last_name', 'like', "%{$request->search}%")
             ->orWhere('email', 'like', "%{$request->search}%")
        )
        ->when($request->status, fn($q) => $q->where('status', $request->status))
        ->when($request->department_id, fn($q) =>
            $q->whereHas('profile', fn($q) => $q->where('department_id', $request->department_id))
        )
        ->paginate(25);

    return view('users.admin.user.index', compact('users'));
}

store() — Create user

public function store(Request $request)
{
    $validated = $request->validate([
        'first_name' => 'required|string|max:255',
        'last_name' => 'required|string|max:255',
        'email' => 'required|email|unique:users',
        'phone_number' => 'nullable|phone:AUTO',
        'password' => 'required|min:8|confirmed|password_rules',
        'department_id' => 'required|exists:departments,id',
        'position_id' => 'required|exists:positions,id',
        'employment_type' => 'required|in:full-time,part-time,contract,temporary',
        'start_date' => 'required|date',
        'roles' => 'nullable|array|exists:roles,id',
        'avatar' => 'nullable|image|mimes:png,jpg,jpeg|max:2048',
    ]);

    $user = new User([
        'first_name' => $validated['first_name'],
        'last_name' => $validated['last_name'],
        'email' => $validated['email'],
        'phone_number' => $validated['phone_number'] ?? null,
        'password' => Hash::make($validated['password']),
    ]);
    $user->save();

    $user->profile()->create([
        'department_id' => $validated['department_id'],
        'position_id' => $validated['position_id'],
        'employment_type' => $validated['employment_type'],
        'start_date' => $validated['start_date'],
    ]);

    if ($request->has('roles')) {
        $user->assignRole($validated['roles']);
    }

    if ($request->hasFile('avatar')) {
        $path = $request->file('avatar')->store('avatars', 'public');
        $user->update(['avatar' => $path]);
    }

    if ($request->boolean('send_welcome_email', true)) {
        Mail::queue(new WelcomeUser($user));
    }

    return redirect()->route('admin.user.edit', $user->id)
        ->with('message', 'User created successfully');
}

update() — Modify user

public function update(Request $request, string $id)
{
    $user = User::findOrFail($id);

    $validated = $request->validate([
        'first_name' => 'required|string|max:255',
        'last_name' => 'required|string|max:255',
        'email' => "required|email|unique:users,email,{$id}",
        'phone_number' => 'nullable|phone:AUTO',
        'status' => 'required|in:active,inactive,suspended,terminated',
        'roles' => 'nullable|array|exists:roles,id',
        'avatar' => 'nullable|image|mimes:png,jpg,jpeg|max:2048',
    ]);

    $user->update([
        'first_name' => $validated['first_name'],
        'last_name' => $validated['last_name'],
        'email' => $validated['email'],
        'phone_number' => $validated['phone_number'],
        'status' => $validated['status'],
    ]);

    if ($request->has('roles')) {
        $user->syncRoles($validated['roles']);
    }

    if ($request->hasFile('avatar')) {
        $path = $request->file('avatar')->store('avatars', 'public');
        $user->update(['avatar' => $path]);
    }

    return redirect()->back()->with('message', 'User updated successfully');
}

destroy() — Delete user

public function destroy(string $id)
{
    $user = User::findOrFail($id);

    // Soft delete
    $user->delete();

    // Audit log
    activity()
        ->causedBy(auth()->user())
        ->performedOn($user)
        ->log('deleted');

    return redirect()->route('admin.user.index')
        ->with('message', 'User deleted successfully');
}

resetPassword() — Reset user password

public function resetPassword(Request $request, string $id)
{
    $user = User::findOrFail($id);

    // Send password reset email
    Password::sendResetLink([
        'email' => $user->email
    ]);

    return back()->with('message', 'Password reset email sent');
}

suspendAccount() — Suspend user

public function suspendAccount(Request $request, string $id)
{
    $request->validate(['reason' => 'required|string']);

    $user = User::findOrFail($id);
    $user->update(['status' => 'suspended']);

    activity()
        ->causedBy(auth()->user())
        ->performedOn($user)
        ->withProperties(['reason' => $request->reason])
        ->log('suspended');

    Mail::queue(new AccountSuspended($user, $request->reason));

    return back()->with('message', 'User account suspended');
}

10.2 ProfileController

Location: app/Http/Controllers/Web/ProfileController.php or app/Http/Controllers/API/ProfileController.php

showProfile() — Display current user's profile

public function showProfile()
{
    $user = auth()->user()->load('profile.department', 'profile.position', 'profile.manager');
    return view('user.profile', compact('user'));
}

updateProfile() — Update profile info

public function updateProfile(Request $request)
{
    $validated = $request->validate([
        'phone_number' => 'nullable|phone:AUTO',
        'timezone' => 'required|timezone',
        'language' => 'required|in:en,es,fr,tl',
        'avatar' => 'nullable|image|mimes:png,jpg,jpeg|max:2048',
    ]);

    $user = auth()->user();
    $user->update($validated);

    if ($request->hasFile('avatar')) {
        $path = $request->file('avatar')->store('avatars', 'public');
        $user->update(['avatar' => $path]);
    }

    return back()->with('message', 'Profile updated successfully');
}

10.3 SettingController

Location: app/Http/Controllers/Web/SettingController.php or app/Http/Controllers/API/SettingController.php

showSettings() — Display account settings

public function showSettings()
{
    $user = auth()->user();
    $settings = $user->settings;
    $loginHistory = $user->loginHistory()->latest()->limit(10)->get();

    return view('user.settings', compact('user', 'settings', 'loginHistory'));
}

changePassword() — Update password

public function changePassword(Request $request)
{
    $validated = $request->validate([
        'current_password' => ['required', 'current_password'],
        'password' => ['required', 'min:8', 'confirmed', 'password_rules'],
    ]);

    auth()->user()->update([
        'password' => Hash::make($validated['password']),
    ]);

    return back()->with('message', 'Password changed successfully');
}

enableTwoFactor() — Enable 2FA

public function enableTwoFactor(Request $request)
{
    $user = auth()->user();

    // Generate TOTP secret
    $secret = (new Google2FA())->generateSecretKey();
    $user->update(['two_factor_secret' => encrypt($secret)]);

    $qrCode = (new Google2FA())->getQRCodeInline(
        config('app.name'),
        $user->email,
        $secret
    );

    return view('user.enable-2fa', compact('qrCode', 'secret'));
}

11. User Lifecycle Management

11.1 User Onboarding

Scenario: New employee joins company.

Steps:

  1. HR creates user record in Admin → Users → Create

    • Fills personal & employment info
    • Selects department, position, manager
    • Assigns appropriate roles (e.g., "employee")
    • Sets start date to today or future date
    • Checks "Send welcome email"
  2. System actions:

    • Creates User record with hashed password
    • Creates Profile record linked to user
    • Assigns roles and default permissions
    • Sends welcome email with password reset link or temporary password
    • Logs audit entry: "user created by HR Manager"
  3. Employee receives email:

    • "Welcome to DTR System"
    • Password reset link (expires in 24 hours)
    • Link to onboarding checklist
  4. Employee completes setup:

    • Clicks reset link, sets own password
    • Updates profile photo (optional)
    • Accepts terms of service
    • System automatically enables:
      • DTR (clock-in/out)
      • Leave requests
      • Shift visibility
  5. Manager confirmation:

    • Manager receives notification: "New team member added"
    • Manager can assign team, special projects, training

11.2 User Profile Updates

Scenario: Employee changes department or updates personal info.

By employee (self-service):

  • /user/profile: edit phone, avatar, timezone, language
  • /user/settings: change password, enable 2FA, notification preferences

By HR/Admin:

  • /admin/user/{id}/edit: edit name, email, phone, department, position, manager, status
  • Changes trigger notifications (e.g., manager changed)
  • Audit logged: "Department changed: Sales → HR by HR Manager"

Effective date for changes:

  • Name, phone: effective immediately
  • Department/position: can be dated (effective future date)
  • Status: can be immediately effective or scheduled

11.3 Role & Permission Assignment

Scenario: Promote employee to team lead (add role).

Steps:

  1. Admin opens user record → Roles tab
  2. Checks "Team Lead" role (multi-select)
  3. Clicks Save
  4. System:
    • Assigns role to user (via assignRole())
    • User now has all permissions tied to "Team Lead" role
    • Permission cache updated
    • Audit logged: "Role added: Team Lead"
    • Optional: send notification to user ("You've been promoted")

Role hierarchy (if using packages like larastan/role-permission):

  • Super Admin (parent) > Admin > HR Manager > Employee
  • Inheriting permissions flows down

11.4 User Deactivation / Termination

Scenario A: Resignation/Termination

  1. HR sets status to "Terminated"

    • Fills termination date, reason (optional)
    • Selects "Final Paycheck" date (for payroll integration)
  2. System actions:

    • User login disabled (status check)
    • No future DTR/shifts assigned
    • Audit logged: "User terminated" with reason
    • Notifications sent to manager, HR
    • Offboarding checklist triggered
  3. Offboarding tasks:

    • Equipment return checklist
    • Access revocation (badges, keys, accounts)
    • Knowledge transfer (assign documents)
    • Final review (optional)

Scenario B: Temporary Inactivity

  1. HR sets status to "Inactive" (e.g., leave of absence)

    • Reason, effective date, expected return date
  2. System:

    • User cannot login (optional policy)
    • DTR/shift assignments suspended
    • Re-activation date reminder sent to HR
  3. On reactivation:

    • Status set back to "Active"
    • User can login immediately
    • Audit logged: "User reactivated"

Scenario C: Account Suspension

  1. IT or Security suspends account

    • Reason: "Suspicious activity", "Password compromise", etc.
  2. System:

    • User cannot login
    • May require additional verification before unsuspend
    • Audit logged with IP that caused suspension
  3. Unsuspension:

    • After investigation or time period
    • User prompted to change password
    • 2FA reset may be required

11.5 Password Reset & Security

Admin-initiated password reset:

  1. Admin clicks "Reset Password" on user detail
  2. System sends password reset email (valid 24 hours)
  3. User receives link: /password/reset?token=abc123
  4. User sets new password (min 8 chars, complexity rules)
  5. Audit logged: "Password reset requested by Admin"

User-initiated password reset:

  1. At login page: "Forgot Password?"
  2. Enters email
  3. System sends reset link (if account exists)
  4. User clicks link, sets new password
  5. Login with new password
  6. Audit logged: "Password changed by user"

Password policies (configurable):

  • Minimum length: 8 chars
  • Required: uppercase, lowercase, number, symbol
  • Cannot reuse last N passwords (e.g., last 5)
  • Expiry: optional (e.g., every 90 days)
  • On expiry: prompt to change password

Two-Factor Authentication:

  • Optional enable/disable in settings
  • Method: TOTP (Google Authenticator, Authy)
  • Backup codes: 10 single-use codes for account recovery
  • On login with 2FA enabled:
    1. Enter email + password
    2. System prompts for 6-digit code from authenticator app
    3. Enter code, grant access
  • Recovery: use backup code if authenticator lost

12. Integrations (DTR / Payroll / Scheduling)

DTR Integration:

  • On user creation: automatically enable DTR for user
  • User can clock in/out immediately if assigned to shift
  • DTR respects user status: terminated users cannot clock in

Payroll Integration:

  • User record feeds into payroll (name, email, department, position)
  • Employee ID used as unique identifier in payroll
  • Changes synced: name, position, department
  • Termination triggers final paycheck processing

Scheduling Integration:

  • User linked to department for scheduling
  • Manager assignment determines approval chain for shifts
  • Employee can view assigned shifts once user activated
  • User status changes reflect in shift assignment availability

Audit/Logging Integration:

  • All user CRUD operations logged in activity_log table
  • Sensitive fields tracked: password change, status change
  • Integration audit: syncs to payroll, DTR logged
  • Retention: 1 year minimum (configurable)

13. Filters, Search & Reports

Index filters:

  • Status: active, inactive, suspended, terminated
  • Department / Team
  • Role (multi-select)
  • Date range: created, last login, start date
  • Search: name, email, employee ID

Reports:

  • User roster by department (Excel export)
  • Role matrix: users by role
  • Login history: last 30 days
  • Audit trail: changes to user records
  • New hires: by month
  • Terminations: by month
  • Role assignment history: track who had what roles when

Export formats: CSV, Excel, PDF (roster only)


14. Audit, Notifications & Compliance

Audit logging:

  • created_at, updated_at on User model
  • Activity log: using Laravel Activity / Spatie package
  • Events tracked:
    • created — new user
    • updated — field changes (name, email, status, roles)
    • deleted — user deleted (soft or hard)
    • password_reset — password changed
    • 2fa_enabled / 2fa_disabled
    • login_successful / login_failed
    • account_suspended / account_reactivated

Notifications:

  • New user created → send welcome email + reset link
  • Password reset → send reset email
  • Account suspended → notify user + manager
  • Role changed → notify user ("You've been promoted to Team Lead")
  • Login from new device → notify user (optional security feature)

Compliance:

  • GDPR: support data export (user requests all personal data)
  • Right to be forgotten: soft delete + full data wipe option
  • Data retention: configurable per compliance policy (default 1 year after termination)
  • Audit trail: immutable, retained for legal discovery

15. Security Considerations

Password security:

  • Always hash using bcrypt (configured in Laravel)
  • Never log or expose passwords
  • Enforce complexity: min 8 chars, mixed case, number, symbol
  • Optional expiry: every 90 days (configurable)
  • Session timeout: 30 mins idle (configurable per role)

Account security:

  • Rate limiting on login endpoint: 5 attempts/min per IP
  • Account lock after N failed attempts (e.g., 5)
  • Force password change after suspension
  • Require 2FA for admin roles (recommended)
  • IP whitelisting for admin accounts (optional)

Data security:

  • Store passwords hashed (bcrypt)
  • Store PII encrypted at rest if policy requires
  • Soft delete: preserved for audit, not visible to users
  • API: require Bearer token (Sanctum or Passport)
  • CORS: restrict to trusted domains

Access control:

  • RBAC enforced via middleware + Gate/Policy
  • Non-admin users can only view/edit their own record
  • Admin users scoped to permission level (e.g., HR Manager cannot delete)
  • Super Admin can impersonate users (audit logged)

Audit & logging:

  • All sensitive actions logged: login, password change, role change, delete
  • Logs immutable after creation
  • Logs retained per compliance policy
  • Admin access to audit logs restricted (view_audit_logs permission)

16. Practical Workflows & Examples

16.1 Create New Employee User

Scenario: HR hires new employee "Alice Johnson" for Sales department, starting Jan 1, 2025.

Steps:

  1. Navigate: Admin → Users → Create

  2. Fill form:

    • First Name: Alice
    • Last Name: Johnson
    • Email: alice.johnson@company.com
    • Phone: +1-555-0300
    • DOB: 1995-08-20
    • Employee ID: EMP-00150
    • Department: Sales
    • Position: Sales Representative
    • Employment Type: Full-time
    • Start Date: 2025-01-01
    • Manager: John Smith (Sales Lead)
    • Password: [system generates + prompts user to change]
    • Avatar: [optional upload]
    • Roles: employee (default)
    • Send welcome email: checked
    • Status: Active
  3. Click "Create"

  4. System:

    • Creates User record (alice.johnson@company.com, status=active)
    • Creates Profile record (dept=Sales, pos=Sales Rep, manager=John Smith)
    • Assigns "employee" role with default permissions
    • Sends welcome email to alice.johnson@company.com:
      Subject: Welcome to DTR System!
      Body: Click link to set your password: /password/reset?token=...
    • Logs audit: "User created by HR Manager Jane Doe"
  5. Alice receives email:

    • Clicks reset link
    • Sets her own password: "SecurePass456!"
    • Logs in successfully
    • Greeted with onboarding checklist:
      • Upload profile photo
      • Set timezone
      • Confirm manager assignment
      • Accept terms of service
  6. Result: Alice can now clock in/out, view shifts, request leaves ✓

16.2 Bulk Import Users

Scenario: Company acquired subsidiary; need to import 200 new employees.

Steps:

  1. Prepare CSV file:

    first_name,last_name,email,phone,employee_id,department,position,employment_type,start_date,manager
    Robert,Brown,robert.brown@subsidiary.com,+1-555-0400,SUB-001,Engineering,Software Engineer,full-time,2024-12-15,Michael Davis
    Sarah,White,sarah.white@subsidiary.com,+1-555-0500,SUB-002,Engineering,DevOps Engineer,full-time,2024-12-15,Michael Davis
    ...
  2. Navigate: Admin → Users → Bulk Import

  3. Upload CSV file

  4. System:

    • Validates 200 rows
    • Checks for duplicate emails (fails on dups, shows errors)
    • Creates users in batches (avoids timeout)
    • Shows progress: "Processing 200 users... 150 completed"
  5. Import completes:

    • Message: "Successfully imported 200 users"
    • 200 welcome emails queued (Mailer job)
    • Audit logged: "Bulk import 200 users by Admin Jane Doe"
  6. Employees receive:

    • Welcome email with password reset link
    • Onboarding checklist

16.3 Assign Roles & Permissions

Scenario: Promote Alice Johnson from "employee" to "team-lead" (Sales team).

Steps:

  1. Navigate: Admin → Users → Alice Johnson

  2. Open "Roles" tab

  3. Current roles: employee

  4. Click "Add Role" or checkbox "team-lead"

  5. Click "Save"

  6. System:

    • Updates model_has_roles table: assigns role "team-lead"
    • Alice now has all permissions tied to "team-lead":
      • view_team_members
      • approve_leaves
      • assign_shifts
      • view_payroll_summary
    • Permission cache cleared
    • Audit logged: "Role assigned: team-lead by Admin Jane Doe"
    • Email sent to Alice: "Congratulations on your promotion to Team Lead!"
  7. Result: Alice can now approve leaves, assign shifts for her team ✓

16.4 Reset User Password

Scenario: Alice forgot her password and cannot login.

Steps (via Admin):

  1. Navigate: Admin → Users → Alice Johnson

  2. Click "Reset Password" button

  3. System:

    • Sends password reset email to alice.johnson@company.com
    • Reset link valid for 24 hours
    • Audit logged: "Password reset requested for Alice Johnson by Admin Jane Doe"
  4. Alice receives email:

    • Subject: "Password Reset Request"
    • Link: /password/reset?token=abc123
  5. Alice clicks link:

    • Enters new password: "NewPass789!"
    • Confirms password
    • Submits
  6. System:

    • Hashes new password
    • Updates User record
    • Audit logged: "Password reset completed by Alice Johnson"
  7. Alice logs in: NewPass789! ✓

Steps (via self-service):

  1. At login page: Click "Forgot Password?"
  2. Enter email: alice.johnson@company.com
  3. System sends reset email (same as above)
  4. Alice follows steps 5–7

16.5 Deactivate User

Scenario: Alice resigns; HR needs to terminate her account.

Steps:

  1. Navigate: Admin → Users → Alice Johnson

  2. Click "Edit"

  3. Set Status: Terminated (or Inactive)

  4. Fill Termination Details:

    • Termination Date: 2025-02-28
    • Reason: Resignation (optional)
    • Final Paycheck Date: 2025-02-28
    • Documentation: Uploaded resignation letter
  5. Click "Save"

  6. System:

    • Updates User.status = "terminated"
    • Alice can no longer login (status check)
    • All future shifts unassigned
    • DTR automatically disabled
    • Audit logged: "User terminated: Alice Johnson by Admin Jane Doe, Reason: Resignation"
    • Notifications:
      • John Smith (manager): "Alice Johnson has been terminated"
      • HR: "Offboarding checklist initiated for Alice Johnson"
  7. Offboarding tasks (manual checklist):

    • Collect equipment: laptop, badge, keys
    • Revoke access: badges, building, systems
    • Knowledge transfer: assign documents to team
    • Final interview: optional
    • Reference: optional
    • Mark complete when done
  8. Result: Alice's account inactive; data preserved in DB for compliance ✓


17. Testing & QA Checklist

Unit tests:

  • ✓ User::create generates unique email
  • ✓ Password hashing (bcrypt)
  • ✓ User::assignRole assigns roles correctly
  • ✓ User::getPermissions returns merged permissions from roles
  • ✓ User::delete soft-deletes record

Integration tests:

  • ✓ Create user via form → User record + Profile record created
  • ✓ Send welcome email → Mailer queued + audit logged
  • ✓ Reset password → Email sent + token valid for 24 hrs
  • ✓ Assign role → User gains all role permissions
  • ✓ Terminate user → Status updated + login disabled + DTR disabled
  • ✓ Bulk import CSV → 200 users created in batch

E2E tests (manual):

  • ✓ Admin creates user → User receives welcome email → Clicks link → Sets password → Logs in successfully
  • ✓ User forgets password → Clicks "Forgot" → Receives reset email → Resets → Logs in
  • ✓ Admin assigns "team-lead" role → User now sees team management options
  • ✓ Admin terminates user → User cannot login → Shifts removed
  • ✓ Bulk import → 200 users created without errors

Security tests:

  • ✓ Password hashed in DB (never plaintext)
  • ✓ Reset token valid 24 hrs, expires after use
  • ✓ Failed login attempts rate-limited (5/min per IP)
  • ✓ Terminated user cannot clock in (DTR rejects)
  • ✓ Admin viewing user does not expose password

Performance tests:

  • ✓ Index page (500 users) loads < 500ms
  • ✓ Bulk import (200 users) completes < 30 secs
  • ✓ Login with 100,000 users in DB < 200ms
  • ✓ Permission check (via cache) < 10ms

18. Troubleshooting & FAQs

Q: "User created but welcome email not received"

  • A:
    • Check email is queued (check jobs table or logs)
    • Verify MAIL_* env vars are configured
    • Check user's spam folder
    • Resend manually via Admin → Users → {user} → Send Welcome Email

Q: "Terminated user can still login"

  • A:
    • Check user.status is actually "terminated" (not "active")
    • Verify login middleware checks status: if($user->status !== 'active') abort(401)
    • Clear user session cache

Q: "User assigned role but permissions not taking effect"

  • A:
    • Clear permission cache: php artisan cache:clear
    • Verify role exists in DB: roles table
    • Confirm role-permission link exists: role_has_permissions table
    • User may need to re-login to refresh token

Q: "Password reset link expired"

  • A:
    • Reset link valid for 24 hours (configurable in config/auth.php)
    • User can request new reset link
    • Admin can force password reset

Q: "Bulk import fails on row 50 of 200"

  • A:
    • Check CSV format at row 50 (email format, required fields)
    • Validate phone number format
    • Check for duplicate emails in CSV
    • Re-run import after fixing errors (skips previously created users)

Q: "How to export all users for payroll?"

  • A:
    • Admin → Users → Export → Select columns → Download CSV
    • Or via API: GET /api/admin/users?export=1
    • Include: first_name, last_name, email, employee_id, department, position

19. Appendix: SQL & Code Examples

SQL: Get active users in HR department

SELECT u.* FROM users u
JOIN profiles p ON u.id = p.user_id
JOIN departments d ON p.department_id = d.id
WHERE u.status = 'active' AND d.name = 'HR'
ORDER BY u.last_name;

SQL: Get users with specific role

SELECT u.* FROM users u
JOIN model_has_roles mhr ON u.id = mhr.model_id
JOIN roles r ON mhr.role_id = r.id
WHERE r.name = 'team-lead' AND mhr.model_type = 'App\Models\User';

SQL: Find login attempts (failed) in last 7 days

SELECT * FROM login_attempts
WHERE status = 'failed' AND created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
ORDER BY created_at DESC
LIMIT 100;

SQL: Audit log — user changes

SELECT * FROM activity_log
WHERE model_type = 'App\Models\User' AND model_id = {user_id}
ORDER BY created_at DESC
LIMIT 50;

Laravel Model Hook: Auto-create profile on user creation

// In User model
protected static function booted()
{
    static::created(function ($user) {
        $user->profile()->create();
    });
}

Laravel Blade: Display user avatar

@if($user->avatar)
    <img src="{{ asset('storage/' . $user->avatar) }}" alt="{{ $user->name }}" class="avatar">
@else
    <img src="/images/default-avatar.png" alt="Default" class="avatar">
@endif

Laravel API Resource: User response

namespace App\Http\Resources;

class UserResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'first_name' => $this->first_name,
            'last_name' => $this->last_name,
            'email' => $this->email,
            'full_name' => $this->first_name . ' ' . $this->last_name,
            'status' => $this->status,
            'avatar_url' => $this->avatar ? asset('storage/' . $this->avatar) : null,
            'profile' => ProfileResource::make($this->profile),
            'roles' => $this->roles->pluck('name'),
        ];
    }
}

Document version: 1.0
Maintainers: HR / Product / Engineering
Last updated: December 10, 2025