# Admin Login URL – Old Project Analysis

**URL:** `admin/home/login`  
**Full URL example:** `http://php74.gwl.com/cmmschool/admin/home/login` (or project base + `admin/home/login`)

This document covers the login flow for **both Admin and School Owner**. School owners use the same URL and form; after login they are identified by session and `school_id` and have access to the same admin dashboard (scoped to their school).

---

## 1. Route (CI3)

- **Segment 1:** `admin` → controller directory/folder  
- **Segment 2:** `home` → controller class  
- **Segment 3:** `login` → method  

**Controller file:** `application/controllers/admin/home.php`  
**Class:** `Home` (extends `CI_Controller`)  
**Method:** `login()`

CI3 default routing: no custom route in `application/config/routes.php` for this URL; it uses the standard `controller/method` pattern.

---

## 2. Controller: `admin/home.php` → `login()`

### Constructor

- Loads: `form_validation`, `session`, `encryption`, `encrypt`, `email`, `pagination`
- Loads models: `securities`, `admin`, `utility`, `prospect`, `student`, `enrollments`
- Sets `$this->data['basepath']` = base_url
- Excluded methods for timezone: `index`, `login`, `logout`, `default_db`, `forgotPassword`, `newPassword`, `testMail`
- `$this->data['loginUser']` = `$this->securities->getLoginUserDetail()`

### `index()`

- Calls `$this->securities->session_exist_redirect('admin')`  
  - If admin or school-owner session exists → redirect to `admin/home/dashboard`
- Then redirects to `admin/home/login`  
So `admin/home/index` always ends at either dashboard (if logged in) or login.

### `login()` – GET (show form)

1. **Session check:** `$this->securities->session_exist_redirect('admin')`  
   - If `admin_user_id` or `school_owner_user_id` in session → redirect to `admin/home/dashboard`.
2. **No POST:** Load view `admin/login` with `$this->data` and stop.

### `login()` – POST (submit credentials)

1. **Session check:** Same `session_exist_redirect('admin')`; if already logged in → redirect to dashboard.
2. **Sanitize:** `$this->securities->avoid_mysql_injection(false)`.
3. **Validation:** `$this->form_validation->set_rules($this->admin->loginRules())`  
   - **admin model `loginRules()`:**  
     - `username`: trim, required  
     - `password`: trim, required (label “passcode”)
4. **If validation fails:** No redirect; execution continues and the login view is loaded again (with errors).
5. **If validation passes:**  
   - **Username:** From `$_POST['username']` or `$_POST['email']` (view only sends `username`).  
   - **Auth:** `$this->securities->authenticateLogin($username, $_POST['password'], array(ADMIN_ROLE_ID, SCHOOL_OWNER_ROLE_ID))`.
6. **If `$info` empty:**  
   - `session->set_flashdata('login_fail', 'Invalid username or passcode.')`  
   - No redirect; view is loaded again (shows flash).
7. **If `$info` present but `$info->status != 1`:**  
   - Flash: `'Blocked by admin. Please contact to administrator.'`  
   - Redirect to `admin/home/login`.
8. **If `$info` present and `status == 1`:**  
   - **Admin (`role_id == ADMIN_ROLE_ID`):**  
     - Session: `admin_time_zone`, `admin_user_id`, `school_id` = `"admin"`.  
   - **School owner (`role_id == SCHOOL_OWNER_ROLE_ID`):**  
     - Load `school_staff` by `user_id`, update `last_logged_in`.  
     - Session: `school_owner_time_zone`, `school_owner_user_id`, `school_id` = `$school_staff->school_id`.  
   - **Both:**  
     - `$this->utility->insert_user_login_detail($tempUserData)`.  
     - Redirect to `admin/home/index` (which then sends to `admin/home/dashboard` via `session_exist_redirect`).

---

## 3. Related: `session_exist_redirect('admin')`

**Location:** `application/models/securities.php` → `session_exist_redirect($moduleName)`

- If `admin_user_id` in session → redirect to `admin/home/dashboard`.
- If `school_owner_user_id` in session → redirect to `admin/home/dashboard`.
- (Other session types redirect to tp/ur or tp/pp as applicable.)

So for the admin module, “session exists” means either admin or school-owner is logged in → user is sent to dashboard, not login.

---

## 4. View: `admin/login.php`

**Path:** `application/views/admin/login.php`

- **Layout:** Centered login box on blue background (`#006699`).
- **Includes:** `admin/include/headScripts.php`.
- **Form:**  
  - **Action:** `home/login` (relative to admin: `admin/home/login`).  
  - **Method:** POST.  
  - **Fields:**  
    - `username` (text, placeholder “Username”).  
    - `password` (password, placeholder “Passcode”).  
  - **Buttons/links:**  
    - Submit: “Login” (validates with `$('#frmlogin').valid()`).  
    - Link: `home/forgotPassword` → “FORGOT PASSCODE?”.
- **Errors:**  
  - `form_error('username')`, `form_error('password')`.  
  - `$this->session->flashdata('login_fail')` for server-side message (invalid credentials, blocked, etc.).
- **Scripts:** jQuery, `jquery.validate`, `js/inlines/login.js`.

---

## 5. Authentication (securities + admin model)

- **Validation rules:** From `admin->loginRules()` (username + password required).
- **Auth:** `securities->authenticateLogin($username, $password, [ADMIN_ROLE_ID, SCHOOL_OWNER_ROLE_ID])`  
  - Verifies user exists, role is admin or school owner, and password matches (legacy/encrypted as in securities).
- **Session:**  
  - Admin: `admin_user_id`, `admin_time_zone`, `school_id` = `"admin"`.  
  - School owner: `school_owner_user_id`, `school_owner_time_zone`, `school_id` = staff’s school.

---

## 6. Flow summary

| Step | Action |
|------|--------|
| 1 | User opens `admin/home/login` (GET). |
| 2 | `login()` runs; `session_exist_redirect('admin')` → if admin/school_owner session exists, redirect to `admin/home/dashboard`. |
| 3 | Otherwise load `admin/login` view (form with username, passcode, Login, Forgot passcode). |
| 4 | User submits form (POST to `admin/home/login`). |
| 5 | `login()`: session check again; avoid_mysql_injection; validate with admin loginRules. |
| 6 | If invalid: set flash and re-show login view. |
| 7 | If valid: authenticateLogin(username, password, [ADMIN_ROLE_ID, SCHOOL_OWNER_ROLE_ID]). |
| 8 | If auth fails: flash “Invalid username or passcode.” and re-show login. |
| 9 | If auth success but status != 1: flash “Blocked by admin…” and redirect to `admin/home/login`. |
| 10 | If auth success and status == 1: set session (admin or school_owner), insert_user_login_detail, redirect to `admin/home/index` → then to `admin/home/dashboard`. |

---

## 7. After school owner login (detailed)

When a **school owner** logs in via `admin/home/login`, the following applies. The same form and URL are used; the role is determined by `authenticateLogin` (role_id = `SCHOOL_OWNER_ROLE_ID`).

### 7.1 Login POST – school owner branch (controller)

In `Home::login()` after successful auth with `$info->role_id == SCHOOL_OWNER_ROLE_ID`:

1. **`$tempUserData['role_name']`** = `'school_owner'`.
2. **Load staff record:**  
   `$this->db->where('school_staff.user_id', $info->user_id);`  
   `$school_staff = $this->utility->getRowByField('school_staff');`
3. **Update last login:**  
   `school_staff.last_logged_in` = `$this->utility->GmDateTime(date("Y-m-d H:i:s"))` for that `school_staff_id`.
4. **Session set:**
   - `school_owner_time_zone` = `$info->timezone`
   - `school_owner_user_id` = `$info->user_id`
   - `school_id` = `$school_staff->school_id` (numeric school ID, **not** `"admin"`)
5. **Common:** `$tempUserData['user_id']` = `$info->user_id`, then `$this->utility->insert_user_login_detail($tempUserData)`.
6. **Redirect:** `admin/home/index` → `session_exist_redirect('admin')` sees `school_owner_user_id` → redirect to **`admin/home/dashboard`**.

So after school owner login, the user lands on the **same dashboard URL** as admin (`admin/home/dashboard`).

### 7.2 Session keys: Admin vs school owner

| Session key              | Admin (role_id = ADMIN_ROLE_ID) | School owner (role_id = SCHOOL_OWNER_ROLE_ID) |
|--------------------------|----------------------------------|-----------------------------------------------|
| User ID                  | `admin_user_id`                  | `school_owner_user_id`                        |
| Timezone                 | `admin_time_zone`                | `school_owner_time_zone`                       |
| `school_id`              | `"admin"` (string)               | `$school_staff->school_id` (numeric)           |
| Other                    | —                                | `school_staff.last_logged_in` updated in DB    |

### 7.3 Identifying the logged-in user: `getLoginUserDetail('admin')`

**Location:** `application/models/securities.php` → `getLoginUserDetail($loginType = 'admin')`

- If `admin_user_id` is set: returns admin `user_id`, `role` = `'admin'`, `role_id` = `ADMIN_ROLE_ID`, `info` = user row (join `user_roles`).
- If `school_owner_user_id` is set (and no admin):  
  - Joins `school_staff` and `user_roles` (role_id = SCHOOL_OWNER_ROLE_ID).  
  - Returns `user_id`, `role` = `'school_owner'`, `role_id` = `SCHOOL_OWNER_ROLE_ID`, `info` = user + school_staff data.

So in admin views/controllers, `$this->data['loginUser']` (set in Home constructor) identifies school owner by `loginUser['role'] == 'school_owner'` and `loginUser['role_id'] == SCHOOL_OWNER_ROLE_ID`. Use `loginUser['user_id']` and `loginUser['info']` for school-scoped data.

### 7.4 Access control after login

- **`session_exist_redirect('admin')`:** If `school_owner_user_id` is in session → redirect to `admin/home/dashboard` (same as admin). So school owner is not shown the login page again when already logged in.
- **`AllowedRoles('admin', ['UserTypes' => [ADMIN_ROLE_ID, SCHOOL_OWNER_ROLE_ID]])`:** Used by `dashboard()`, `dashboard_ajax_data()`, etc. Both admin and school owner are allowed; school owner is recognized via `school_owner_user_id`. If neither session is present, user is redirected (guest).

### 7.5 Timezone and formatting (utility)

- **Timezone:** `utility->setUserTimeZone('admin', $excludedMethods)` uses `school_owner_time_zone` when set (e.g. in `application/models/utility.php`: `date_default_timezone_set($this->session->userdata('school_owner_time_zone'))`).
- **Date/date-time format:** Same utility uses `school_owner_time_zone` to choose `ADMIN_DATE_FORMAT` and `ADMIN_DATE_TIME_FORMAT` for school owner sessions.

### 7.6 Logout (school owner)

In `Home::logout()`:

- If `$loginUser['role_id'] == SCHOOL_OWNER_ROLE_ID` → `$this->securities->schoolOwnerLogout()`.
- **schoolOwnerLogout()** (in `securities.php`):  
  - `unset_userdata('school_owner_user_id')`  
  - `unset_userdata('school_owner_time_zone')`  
  - Does **not** unset `school_id` (admin logout unsets `admin_user_id`, `admin_time_zone`, `school_id`). So after schoolOwnerLogout the session has no school_owner identity; next request to admin will hit login.

Then `$this->utility->update_user_login_detail()` and redirect to `admin/home/login`.

### 7.7 Summary: school owner after login

| Aspect              | Behavior |
|---------------------|----------|
| Login URL           | Same: `admin/home/login` (GET/POST). |
| Redirect after login| `admin/home/index` → `admin/home/dashboard`. |
| Session             | `school_owner_user_id`, `school_owner_time_zone`, `school_id` = that school’s ID. |
| Dashboard           | Same `admin/home/dashboard` view; data should be filtered by `school_id` where applicable. |
| Identity in code    | `getLoginUserDetail()` → `role` = `'school_owner'`, `role_id` = SCHOOL_OWNER_ROLE_ID. |
| Logout              | `schoolOwnerLogout()` clears school_owner session; redirect to `admin/home/login`. |

---

## 8. Related admin/home URLs

| URL | Method | Purpose |
|-----|--------|--------|
| `admin/home/login` | GET | Show login form. |
| `admin/home/login` | POST | Process login. |
| `admin/home/index` | GET | Redirect to login or dashboard (via session_exist_redirect). |
| `admin/home/logout` | GET | Clear admin/school_owner session; redirect to `admin/home/login`. |
| `admin/home/dashboard` | GET | Admin dashboard (protected). |
| `admin/home/forgotPassword` | GET/POST | Forgot passcode. |
| `admin/home/newPassword/(:segment)` | GET/POST | Set new password from token. |
| `admin/home/changePassword` | GET/POST | Change passcode (logged-in admin). |

---

## 9. New project (CI4) – current state

- **Routes:** In `app/Config/Routes.php`, the `admin` group has only:  
  `$routes->get('home/dashboard', 'Home::dashboard');`  
  So **admin/home/login is not yet defined** in the new project.
- **Migration:** To support `admin/home/login` in CI4 you would:
  - Add routes: `admin/home/login` GET and POST → `App\Controllers\Admin\Home::login`.
  - Implement `Admin\Home::login()` with the same logic as above (session check, validation, authenticateLogin for admin/school_owner, session set, redirect).
  - Add `Admin\Home::index()` (redirect to login or dashboard) and use securities/utility equivalents for session_exist_redirect, avoid_mysql_injection, authenticateLogin, insert_user_login_detail.
  - Add view `app/Views/admin/login.php` (form action pointing to admin/home/login, same fields and messages).

This document describes the **old project** behavior of `admin/home/login` for analysis and migration reference.
