Logging in
dashboard/login.php checks the submitted username/password against the users table with PHP's password_verify() against a bcrypt hash stored in password_hash. There is no password-reset-by-email flow - resetting a password means editing the row directly, via the Users page below or SQL.
A default account is seeded by database/schema.sql:
username: admin
password: TruPath@2026
dashboard/login.php and this guide - treat it as a known value, not a secret, until it's rotated.Session mechanics
All session handling lives in includes/dashboard_session.php:
| Function | Purpose |
|---|---|
dashboard_start_session() | Starts the PHP session if one isn't active yet. Called internally by the functions below. |
dashboard_current_user(): ?array | Returns the logged-in user's session data (id, username, full_name, role), or null if nobody is logged in. |
dashboard_require_login(): array | Redirects to login and exits if nobody is logged in; otherwise returns the current user. Every dashboard page calls this first. |
dashboard_require_role(string $role): array | Calls dashboard_require_login(), then responds 403 and exits if the user's role doesn't match. Only dashboard/users.php uses this today (gated to 'admin') - the only page with role-based access control. |
dashboard_login(array $user): void | Called by login.php after a successful password_verify(). Regenerates the session id first, to prevent session fixation. |
dashboard_logout(): void | Clears and destroys the session. dashboard/logout.php calls this then redirects to login. |
Dashboard pages
All pages share a common header/nav/footer via dashboard/_layout.php, and a common list+modal CRUD pattern (POST action=create|update|delete handled at the top of the same file, ?edit=<id>/?new=1 opening an add/edit dialog, a DataTables-enhanced list). dashboard/pathogens.php is the clearest example of this pattern.
| Page | Purpose |
|---|---|
dashboard/index.php | Overview - record counts and data-library metadata. |
dashboard/reports.php | Browse/filter previously generated reports (status, type, source, date range, and on this instance a Sample filter - see below), download their PDFs. |
dashboard/pathogens.php | Manage the pathogens table. |
dashboard/resistance_genes.php | Manage the resistance_genes table. |
dashboard/antimicrobials.php | Manage the antimicrobials table. |
dashboard/recommendations.php | Manage per-organism antimicrobial recommendation rankings. |
dashboard/users.php admin only | Manage dashboard accounts - see below. |
How this instance (tp7) differs from tpl6
This is the tpl7.robbiekohli.com instance, cloned from tpl6 with client-requested report-content changes per Dr. Sweazy's feedback. Two differences are relevant to dashboard admins:
- Pathogens and Resistance Genes Assessed panel. Unlike tpl6, this instance's generated reports show a dedicated panel, matching the client's own reference generator - which uses two different designs depending on report type, not one: PCR-only and negative-PCR reports show a flat listing (no dots, no legend), while the MAST report's page 2 shows a dotted/legend design (navy dot = undergoing PCR analysis, orange dot = eligible for MAST analysis). Both designs share the same pathogen list, controlled by the "Visible in Assessed Panel" checkbox on each pathogen's edit form in
dashboard/pathogens.php(the same page used for the Pathogens Identified / Resistance Genes Detected sections) - it defaults to the client's static v3.2.39 pathogen list, but is fully dashboard-editable from there; no separate page. Each design's resistance gene list is the client's own frozen data with its own wording (ClinicalEngine::PCR_ASSESSED_PANEL_GENESfor the flat design,ClinicalEngine::MAST_ASSESSED_PANEL_GENESfor the dotted one) and is not dashboard-editable. - Sample reports. The Report Generator's "Display SAMPLE - NOT FOR CLINICAL USE banner" checkbox is a real, tracked feature on this instance: checked reports are flagged
is_samplein thereportstable and shown as a red "Sample" badge with a dedicated filter ondashboard/reports.php- the generated report/PDF itself is unaffected, only its entry in the Report Dashboard.
Users (add/remove dashboard accounts)
dashboard/users.php is an admin-role-only page for managing who can log into the dashboard:
- Add - username, full name, role (
adminorstaff), and a password (minimum 8 characters, hashed withpassword_hash($password, PASSWORD_DEFAULT)before storage - never stored or logged in plaintext). - Edit - same fields; leave the password field blank to keep the existing password unchanged.
- Delete - removes the account. You cannot delete the account you're currently logged in as (hidden on your own row, and rejected server-side if attempted directly).
admin (can access the Users page) vs. everything else (cannot). No per-page/per-action granularity beyond that single check.What the Admin Dashboard does NOT do
- It does not provide an audit trail of who changed what reference data or when.
- It does not send password-reset emails or support any self-service account-recovery flow - a locked-out account has to be fixed by another
adminuser via the Users page, or directly in the database. - It does not rate-limit or lock out repeated failed login attempts.
- It does not manage the report-generation API's
X-API-Key- that's a separate config value covered in the API docs, unrelated to anyusersrow.