Security Reference Public

Reference

Technical reference for the ERPat Security module — controllers, routes, models, views, migrations, database tables and columns, permission keys, menu entries, and system-audit-log event keys for Device Management, Offsite Access, Locked Accounts, Active Sessions, and Access Device Logs.

Guide version: r2 Module version: 1.4.0 Updated: 2026-08-28 Estimated time: 14 min 10 views 0% helpful
You are viewing version r2 of this guide. View the current version
Administration & Reference

Reference

The data-and-screen reference for the Security module's four admin tools — controllers, routes, models, views, migrations, tables, permission keys, menu entries, and audit-log events. Everything here is drawn from the live module source; see Research for the exact files.

Controllers

ControllerToolKey methods
Device_management Device Management — Entries tab (page shell) index (tabbed shell), list_data, ban_device_modal_form, ban_device, restore_device_modal_form, restore_device
Device_management_groups Device Management — Groups tab index (ajax-tab partial), list_data, modal_form, save, delete
OffsiteAccess Offsite Access index, modalForm, save, listData, delete
Locked_Accounts Locked Accounts + Active Sessions index, locked_accounts_view, active_sessions_view, list_data, clear_attempts, list_sessions_data, view_sessions_modal, logout_user_all_devices, delete_session, get_session_statistics
Access_logs Access Device Logs — Logs tab (page shell) index (tabbed shell), view, list_data, log_action, delete
Access_devices Access Device Logs — Devices tab index, list_data, modal_form, modal_form_credential, generate_new_secret, save, delete, pass_list
Access_device_categories Access Device Logs — Categories tab index, list_data, modal_form, save, delete

All seven extend App_Controller (staff, session-authenticated). Every constructor opens with the module's single always-on guard with_module('security') — there are no per-tool module_* sub-toggles left — and then applies its own permission: Device Management on device_management; its Groups tab on device_management_groups; Offsite Access on offsite_access; all three Access Device controllers on access_logs; Locked Accounts on locked_accounts (or the core staff_support).

Per-action gates sit on the individual methods: block_device on ban_device_modal_form + ban_device, and unblock_device on restore_device_modal_form + restore_device. The row builder (make_row) checks the same two keys, so a user without them sees the row but no action button.

⚠️
Device_management::__construct() is a new gate. The core version of this controller had no permission check on direct URL access — any signed-in staff member could open /device_management by typing the address, and only the sidebar link was gated, on a device_management key that no catalog row ever declared (so it was ungrantable and the item was effectively admin-only). The key is now declared by this module and enforced in the constructor, so it can be granted to a role and it actually blocks direct access.

Routes

Declared in modules/Security/config/routes.php (mixed-case/underscore controllers need explicit lowercase routes). The (:any) catch-alls map to controller methods.

URLResolves to
device_managementDevice_management/index
device_management/(:any)Device_management/$1
device_management_groupsDevice_management_groups/index
device_management_groups/(:any)Device_management_groups/$1
offsite_accessOffsiteAccess/index
offsite_access/(:any)OffsiteAccess/$1
locked_accountsLocked_Accounts/index
locked_accounts/(:any) · /(:any)/(:any)Locked_Accounts/$1 · $1/$2
access_logs · access_logs/(:any)Access_logs/index · $1
access_devices · access_devices/(:any)Access_devices/index · $1
access_device_categories · …/(:any)Access_device_categories/index · $1
ℹ️
The Device Management URLs are unchanged. /device_management and /device_management_groups are byte-for-byte the addresses the core version used — only the file that declares them moved (from application/config/routes.php into modules/Security/config/routes.php). Existing links, bookmarks and in-view get_uri() calls keep resolving. device_management_groups cannot be swallowed by device_management/(:any) — CodeIgniter anchors each route key and (:any) never matches across the missing /.

Models

Six models, all extending Crud_model and living in modules/Security/models/. All SQL lives here — never in a controller or view.

ModelTool / tableNotes
Banned_devices_model Device Management — banned_devices get_details, get_devices_with_ban_status. Also read by CORE application/models/Users_model::authenticate() on every sign-in attempt — do not rename or move it (see the callout below).
Device_management_groups_model Device Management — device_management_groups get_details. Backs the Groups tab list and the group filter dropdown on the Entries tab.
OffsiteAccessModel Offsite Access — offsite_access Also read by the core IP-restriction middleware when deciding whether to allow an off-network request.
Access_logs_model Access Device Logs — access_logs The access-event history.
Access_devices_model Access Device Logs — access_devices Registered physical devices and their API credentials.
Access_device_categories_model Access Device Logs — access_device_categories Device categories.
⚠️
Core depends on Banned_devices_model by name. The sign-in check in core Users_model::authenticate() loads this module's model and looks up the (user + user agent) pair on every sign-in attempt — that is what actually rejects a banned device. Renaming the model, its get_details() signature, or the banned_devices table would break sign-in for the whole tenant. In the other direction the coupling was removed: get_devices_with_ban_status() absorbed core's System_logs_model::get_system_logs_data_per_device(), so core no longer queries this module's tables to build the list.

Views

19 view files under modules/Security/views/, namespaced one directory deep so the loader cascade cannot collide with another module.

ViewScreen
device_management/index.phpDevice Management page shell + the Entries tab (filters, list, action buttons)
device_management/ban_device_modal_form.phpBan-device modal — the required Remarks/reason field
device_management/restore_device_modal_form.phpRestore (unban) confirmation modal
device_management/groups/index.phpGroups tab list (loaded as an ajax-tab partial)
device_management/groups/modal_form.phpGroup add / edit modal — Title, User Agent, Status
offsite_access/index.php · modal_form.phpOffsite Access list and grant form
locked_accounts/index.php · locked_accounts_tab.php · active_sessions_tab.phpLocked Accounts page shell and its two tabs
active_sessions/view_sessions_modal.phpPer-user session detail modal
access/index.php · logs/index.php · devices/* · categories/*Access Device Logs shell and its Logs · Devices · Categories tabs (8 files)

Database tables

Six tables, all shipping in the base-install schema and re-created idempotently by the module migrations (tracked in migrations_security). All carry the standard updated_at + deleted audit columns.

banned_devices

One row per active ban — a person plus the browser (user agent) they may no longer sign in from. Restoring a device soft-deletes its row.

ColumnTypeNotes
idint unsignedPK
user_idintThe person who is blocked from this device
http_agenttextThe browser / user-agent string being banned
ip_addressvarchar(45)IP captured at the time of the ban
remarkstextThe reason — required on the ban form
created_byintAdministrator who applied the ban
date_createddatetimeUTC ban time
updated_at · deletedtimestamp · tinyintAudit + soft delete (a restore sets deleted)

Indexed (user_id, http_agent(191), deleted) — that exact triple is the lookup core Users_model::authenticate() runs on every sign-in attempt, so it carries a covering index.

device_management_groups

Named user-agent groups used to label and filter the Entries list. A group grants nothing and blocks nothing.

ColumnTypeNotes
idint unsignedPK
uuidvarchar(64)Per-group UUID
titlevarchar(150)Group name (e.g. "Company Chromebooks")
user_agenttextThe user-agent string the group matches
statusvarchar(20)active / inactive
created_byintWho created the group
date_createddatetimeUTC create time
updated_at · deletedtimestamp · tinyintAudit + soft delete

Indexed on (status, deleted) and on user_agent(191), which is joined against system_logs.http_agent to bucket sign-in devices.

ℹ️
The Device Management list is DERIVED — there is no stored "is banned" flag. Each row on the Entries tab is built at read time by taking the most recent sign-in log per person per user agent (from the core system_logs sign-in rows) and joining it to banned_devices. The Active / Banned status is simply "does a live ban row exist for this person + user agent". Nothing is written to any table when a device merely appears in the list — only banning and restoring write, and they write to banned_devices alone.

offsite_access

ColumnTypeNotes
idint unsignedPK
uuidvarchar(36)Per-grant UUID (v4)
user_idintStaff member granted the window
start_date / end_datedateThe exception window
date_createddatetimeUTC create time
created_byintGranting admin
updated_at · deletedtimestamp · tinyintAudit + soft delete

access_device_categories

ColumnTypeNotes
idint unsignedPK
titlevarchar(150)Category name
detailtextOptional description
statustinyint1 = active
updated_at · deletedtimestamp · tinyintAudit + soft delete

access_devices

ColumnTypeNotes
idint unsignedPK
api_keyvarchar(36)UUID the device presents
api_secretvarchar(120)Hashed secret (never shown/logged in clear)
device_namevarchar(36)Display name
passestextComma-separated staff user IDs allowed through
remarkstextOptional notes
category_idintFK-by-value to access_device_categories
labelstextLabels
statustinyint1 = active
updated_at · deletedtimestamp · tinyintAudit + soft delete

access_logs

ColumnTypeNotes
idint unsignedPK
device_idintWhich device recorded the event
user_idintWho accessed
remarkstextOptional (e.g. entry / exit)
timestampdatetimeUTC event time (shown local)
updated_at · deletedtimestamp · tinyintAudit + soft delete
ℹ️
Locked Accounts / Active Sessions has no dedicated table. The Locked Accounts tab reads the failed-attempt columns on users (disable_login, login_attempts, last_login_attempts); the Active Sessions tab reads the core session store (ci_sessions) through the core session helper.

Migrations

Six module migrations in modules/Security/migrations/, run by php erpat migrate:modules against the per-module migrations_security version table. Every one is an idempotent guard: the tables already ship in the base-install schema, so on an existing database each migration is a no-op (table_exists() → return, then CREATE TABLE IF NOT EXISTS). They exist so the module is self-contained for fresh installs and newly provisioned tenants. All are reversible.

MigrationCreates
20260727100254_create_offsite_access_table.phpoffsite_access
20260727100255_create_access_device_categories_table.phpaccess_device_categories
20260727100256_create_access_devices_table.phpaccess_devices
20260727100257_create_access_logs_table.phpaccess_logs
20260730213155_create_banned_devices_table.phpbanned_devices (+ the covering sign-in index)
20260730213156_create_device_management_groups_table.phpdevice_management_groups

Retirement migrations live in CORE (they touch the shared settings table, so they belong in application/migrations/, not here): 20260730213157_retire_device_management_setting.php carries any module_device_management = 1 forward onto module_security and then drops the orphaned row; 20260730204800_retire_core_submodule_settings.php did the same for module_offsite_access and module_access in the previous release. Nothing is lost — the tools simply stop having their own on/off rows.

Permission keys

KeyRoles-editor group / actionStyle
device_managementDevice Management: Module / AccessModule-level — new in 3.0.0
device_management_groupsDevice Management: Groups / EnabledModule-level
device_management_groups_create · _update · _deleteDevice Management: Groups / Create · Edit · RemoveChild
block_deviceDevice Management: Block Device / EnabledSimple (no children)
unblock_deviceDevice Management: Unblock Device / EnabledSimple (no children)
offsite_accessSecurity: Offsite Access / AccessDropdown (all / specific)
offsite_access_create · _update · _deleteSecurity: Offsite Access / Create · Edit · RemoveChild
locked_accountsSecurity: Locked Accounts / ViewSimple (no children)
active_sessionsSecurity: Active Sessions / ManageModule-level
active_sessions_create · _update · _deleteSecurity: Active Sessions / Create · Edit · RemoveChild
access_logsSecurity: Access Logs / EnabledModule-level
access_logs_create · _update · _deleteSecurity: Access Logs / Create · Edit · RemoveChild

Keys are unchanged from the core declaration. device_management_groups, block_device and unblock_device keep the exact key names, categories and actions they had as core rows, so serialized grants already stored in users.permissions / roles.permissions keep resolving with no data migration. The legacy rows were deleted from application/helpers/permission_catalog_helper.php in the same change — a core row shadows a module declaration, so leaving them would have kept the module's block inert. Admins bypass every permission check.

Not owned here: staff_support (Staffing) and api_clients (Security: API Clients) remain core-owned; the core IP-restriction block event offsite_access:ip_security is emitted by core middleware, not this module.

Settings & menu

SettingRole
module_securityThe module's one and only enable setting — seeded on, can_disable=false, so it never appears as a switchable row in Manage Modules
module_device_managementRetired in 3.0.0 — carried forward onto module_security, then dropped
module_offsite_accessRetired in 2.0.0 — dropped
module_accessRetired in 2.0.0 — dropped
⚠️
There are no per-tool on/off switches. Every retired module_* row above is gone from Settings → Manage Modules; the module has exactly one always-on setting, module_security. Who sees Device Management, Offsite Access, Locked Accounts or Access Logs is purely a permissions decision in Settings → Roles. Device Management used to ship off for a brand-new tenant, so nobody could open it; it now ships reachable by admins and by roles explicitly granted device_management. No non-admin gains access on upgrade.

Menu entries (config/menu.php), in rendered order: Device Management (fa-mobile, position 160) · Offsite Access (fa-globe, 161) · Locked Accounts (fa-shield, 162) · Access Logs (fa-history, 163). Since Device Management moved in, this module owns the whole Security sidebar section — the core slice in application/config/left_menu.php was emptied and removed, so there is no longer a core group to coalesce with (default_menu.php, position 160).

Audit-log events

Keyed action:component in config/system_logs.php, merged into the core audit-log config. Written on every sensitive mutation.

Event keySeverityMeaning
banned:banned_devicecriticalA user's sign-in device was banned
unbanned:banned_devicewarningA user's sign-in device ban was lifted
created:device_management_groupinfoDevice group created
updated:device_management_groupinfoDevice group updated
deleted:device_management_groupwarningDevice group deleted
created:offsite_accesswarningOffsite window granted
updated:offsite_accesswarningOffsite window updated
deleted:offsite_accesswarningOffsite window revoked
unlocked:locked_accountwarningAccount unlocked (attempts cleared)
logout:active_sessionwarningAll sessions terminated for a user
deleted:active_sessionwarningSingle session terminated
created:access_deviceinfoDevice registered
updated:access_deviceinfoDevice updated
deleted:access_devicewarningDevice deleted
rotated_secret:access_devicecriticalDevice API secret regenerated
created:access_device_categoryinfoCategory created
updated:access_device_categoryinfoCategory updated
deleted:access_device_categorywarningCategory deleted
deleted:access_logwarningAccess log entry deleted
The five Device Management events are new in 3.0.0. Banning and restoring a device were completely unaudited in the core version of this feature — banning locks a person out of ERPat from that browser, so it now leaves a row in the tenant's own audit log (banned:banned_device is rated critical). They appear in Settings → System Logs under category Security, module Device Management.

Next steps

Report a content problem