History (Audit Log) — Backend Documentation
Overview
The platform keeps a lightweight audit trail of CRUD-style actions in thehistory table. Whenever a controller performs a tracked action it calls the global helper insert_in_history_table($action, $row_id, $table_name) (app/Helpers/helpers.php), which stamps a row with the acting user, a free-text action label, the affected row id and table name.
This endpoint exposes that trail for reading:
auth:sanctum, check_if_user_is_blocked_middleware, company_policy_middleware.
Headers (for all requests):
SuperAdminController@index.
How It Works
- The request hits
SuperAdminController@index. - Query params are validated (pagination, filters, sorting).
- A
history↔usersleft-join query is built, selecting the entry plus the user’s full name and email. Soft-deleted entries (deleted_at) are excluded. - Visibility scoping is applied based on the caller’s role:
- Admin / Super-Admin → can see everyone’s entries, and may filter by
user_id. - Any other role (Student, Instructor, Content Manager) → forcibly restricted to their own entries; the
user_idfilter is ignored for them.
- Admin / Super-Admin → can see everyone’s entries, and may filter by
- Optional filters (
table_name,row_id,search) are applied. - Results are sorted and returned as a standard Laravel paginator.
Note: entries are not company-scoped in the query itself — visibility is driven by role + ownership as described above (admins see all rows).
The history Table
Query Parameters
All parameters are optional.
Validation failures return 422 with Laravel’s standard validation error shape.
Response
Standard Laravel paginator. Each item indata includes the joined user info:
Postman Examples
1. Latest activity (defaults)
2. Admin: a specific user’s actions
3. Filter by table + search the action text
4. Audit a single record
Notes & Gotchas
- Role-based visibility is enforced server-side — a non-admin cannot read another user’s history even by passing
user_id; that filter only applies to admins/super-admins. - Soft-deleted entries are hidden — rows with a
deleted_atare never returned. per_pageis capped at 100 to protect the join query.- Entries are write-once via
insert_in_history_table(...); this endpoint is read-only (no create/update/delete routes for history). actionis free-text, sosearchmatches whatever label the calling controller chose to log — labels are not standardized across modules.