Clone
1
Feature: Audit Log
jramos edited this page 2026-01-29 15:19:16 -07:00

Audit Logging Feature - User Acceptance Test Plan

Test Environment Setup

Prerequisites:

  • Fresh database via node backend/setup.js, OR existing database migrated via node backend/migrate-audit-log.js
  • Backend running on port 3001
  • Frontend running on port 3000
  • Three test accounts created:
    • admin / admin123 (role: admin)
    • editor1 (role: editor)
    • viewer1 (role: viewer)

Verify setup: Run sqlite3 backend/cve_database.db ".tables" and confirm audit_logs is listed.


1. Database & Schema

# Test Case Steps Expected Result Pass/Fail
1.1 Fresh install creates table Run node setup.js on a new DB. Query SELECT sql FROM sqlite_master WHERE name='audit_logs' Table exists with columns: id, user_id, username, action, entity_type, entity_id, details, ip_address, created_at
1.2 Indexes created Query SELECT name FROM sqlite_master WHERE type='index' AND name LIKE 'idx_audit%' Four indexes: idx_audit_user_id, idx_audit_action, idx_audit_entity_type, idx_audit_created_at
1.3 Migration is idempotent Run node migrate-audit-log.js twice on the same DB Second run prints "already exists, nothing to do". No errors. Backup file created each run.
1.4 Migration backs up DB Run node migrate-audit-log.js Backup file cve_database_backup_<timestamp>.db created in backend directory
1.5 Setup summary updated Run node setup.js Console output lists audit_logs in the tables line

2. Authentication Audit Logging

# Test Case Steps Expected Result Pass/Fail
2.1 Successful login logged Log in as admin. Query SELECT * FROM audit_logs WHERE action='login' ORDER BY id DESC LIMIT 1 Row with user_id=admin's ID, username='admin', action='login', entity_type='auth', details contains {"role":"admin"}, ip_address populated
2.2 Failed login - wrong password Attempt login with admin / wrongpass. Query audit_logs. Row with action='login_failed', username='admin', details contains {"reason":"invalid_password"}
2.3 Failed login - unknown user Attempt login with nonexistent / anypass. Query audit_logs. Row with action='login_failed', user_id=NULL, username='nonexistent', details contains {"reason":"user_not_found"}
2.4 Failed login - disabled account Disable a user account via admin, then attempt login as that user. Query audit_logs. Row with action='login_failed', details contains {"reason":"account_disabled"}
2.5 Logout logged Log in as admin, then log out. Query audit_logs. Row with action='logout', entity_type='auth', username='admin'
2.6 Login does not block on audit error Verify login succeeds even if audit_logs table had issues (non-critical path) Login response returns normally regardless of audit insert result

3. CVE Operation Audit Logging

# Test Case Steps Expected Result Pass/Fail
3.1 CVE create logged Log in as editor or admin. Add a new CVE (e.g., CVE-2025-TEST-1 / Microsoft / Critical). Query audit_logs. Row with action='cve_create', entity_type='cve', entity_id='CVE-2025-TEST-1', details contains {"vendor":"Microsoft","severity":"Critical"}
3.2 CVE status update logged Update a CVE's status to "Addressed" via the API (PATCH /api/cves/CVE-2025-TEST-1/status). Query audit_logs. Row with action='cve_update_status', entity_id='CVE-2025-TEST-1', details contains {"status":"Addressed"}
3.3 CVE status update bug fix Update a CVE's status. Verify the CVE record in the cves table. Status is correctly updated. No SQL error (the old vendor reference bug is fixed).
3.4 Audit captures acting user Log in as editor1, create a CVE. Query audit_logs. username='editor1' on the cve_create row

4. Document Operation Audit Logging

# Test Case Steps Expected Result Pass/Fail
4.1 Document upload logged Upload a document to a CVE via the UI. Query audit_logs. Row with action='document_upload', entity_type='document', entity_id=CVE ID, details contains vendor, type, and filename
4.2 Document delete logged Delete a document (admin only) via the UI. Query audit_logs. Row with action='document_delete', entity_type='document', entity_id=document DB ID, details contains file_path
4.3 Upload captures file metadata Upload a file named advisory.pdf of type advisory for vendor Cisco. Query audit_logs. details = {"vendor":"Cisco","type":"advisory","filename":"advisory.pdf"}

5. User Management Audit Logging

# Test Case Steps Expected Result Pass/Fail
5.1 User create logged As admin, create a new user testuser with role viewer. Query audit_logs. Row with action='user_create', entity_type='user', entity_id=new user's ID, details contains {"created_username":"testuser","role":"viewer"}
5.2 User update logged As admin, change testuser's role to editor. Query audit_logs. Row with action='user_update', entity_id=testuser's ID, details contains {"role":"editor"}
5.3 User update - password change As admin, change testuser's password. Query audit_logs. details contains {"password_changed":true} (password itself is NOT logged)
5.4 User update - multiple fields Change username and role at the same time. Query audit_logs. details contains both changed fields
5.5 User delete logged As admin, delete testuser. Query audit_logs. Row with action='user_delete', details contains {"deleted_username":"testuser"}
5.6 User deactivation logged As admin, set a user's is_active to false. Query audit_logs. Row with action='user_update', details contains {"is_active":false}
5.7 Self-delete prevented, no log As admin, attempt to delete your own account. Query audit_logs. 400 error returned. NO audit_log entry created for the attempt.

6. API Access Control

# Test Case Steps Expected Result Pass/Fail
6.1 Admin can query audit logs Log in as admin. GET /api/audit-logs. 200 response with logs array and pagination object
6.2 Editor denied audit logs Log in as editor. GET /api/audit-logs. 403 response with {"error":"Insufficient permissions"}
6.3 Viewer denied audit logs Log in as viewer. GET /api/audit-logs. 403 response
6.4 Unauthenticated denied Without a session cookie, GET /api/audit-logs. 401 response
6.5 Admin can get actions list GET /api/audit-logs/actions as admin. 200 response with array of distinct action strings
6.6 Non-admin denied actions list GET /api/audit-logs/actions as editor. 403 response

7. API Filtering & Pagination

# Test Case Steps Expected Result Pass/Fail
7.1 Default pagination GET /api/audit-logs (no params). Returns up to 25 entries, page=1, correct total count and totalPages
7.2 Custom page size GET /api/audit-logs?limit=5. Returns exactly 5 entries (if >= 5 exist). Pagination reflects limit=5.
7.3 Page size capped at 100 GET /api/audit-logs?limit=999. Returns at most 100 entries per page
7.4 Navigate to page 2 GET /api/audit-logs?page=2&limit=5. Returns entries 6-10 (offset=5). Entries differ from page 1.
7.5 Filter by username GET /api/audit-logs?user=admin. Only entries where username contains "admin"
7.6 Partial username match GET /api/audit-logs?user=adm. Matches "admin" (LIKE search)
7.7 Filter by action GET /api/audit-logs?action=login. Only entries with action='login' (exact match)
7.8 Filter by entity type GET /api/audit-logs?entityType=auth. Only auth-related entries
7.9 Filter by date range GET /api/audit-logs?startDate=2025-01-01&endDate=2025-12-31. Only entries within the date range (inclusive)
7.10 Combined filters GET /api/audit-logs?user=admin&action=login&entityType=auth. Only entries matching ALL filters simultaneously
7.11 Empty result set GET /api/audit-logs?user=nonexistentuser. {"logs":[],"pagination":{"page":1,"limit":25,"total":0,"totalPages":0}}
7.12 Ordering Query audit logs without filters. Entries ordered by created_at DESC (newest first)

8. Frontend - Audit Log Menu Access

# Test Case Steps Expected Result Pass/Fail
8.1 Admin sees Audit Log menu item Log in as admin. Click user avatar to open dropdown menu. "Audit Log" option visible with clock icon, positioned between "Manage Users" and "Sign Out"
8.2 Editor does NOT see Audit Log Log in as editor. Click user avatar. No "Audit Log" or "Manage Users" options visible
8.3 Viewer does NOT see Audit Log Log in as viewer. Click user avatar. No "Audit Log" or "Manage Users" options visible
8.4 Clicking Audit Log opens modal As admin, click "Audit Log" in the menu. Modal overlay appears with audit log table. Menu dropdown closes.
8.5 Menu closes on outside click Open the user menu, then click outside the dropdown. Dropdown closes

9. Frontend - Audit Log Modal

# Test Case Steps Expected Result Pass/Fail
9.1 Modal displays header Open the Audit Log modal. Title "Audit Log", subtitle "Track all user actions across the system", X close button visible
9.2 Close button works Click the X button on the modal. Modal closes, returns to dashboard
9.3 Loading state shown Open the modal (observe briefly). Spinner with "Loading audit logs..." appears before data loads
9.4 Table columns correct Open modal with data present. Six columns visible: Time, User, Action, Entity, Details, IP Address
9.5 Time formatting Check the Time column. Dates display in local format (e.g., "1/29/2026, 3:45:00 PM"), not raw ISO strings
9.6 Action badges color-coded View entries with different action types. login=green, logout=gray, login_failed=red, cve_create=blue, cve_update_status=yellow, document_upload=purple, document_delete=red, user_create=blue, user_update=yellow, user_delete=red
9.7 Entity column format View entries with entity_type and entity_id. Shows "cve CVE-2025-TEST-1" or "auth" (no ID for auth entries)
9.8 Details column formatting View an entry with JSON details. Displays "key: value, key: value" format, not raw JSON
9.9 Details truncation View entry with long details. Text truncated with ellipsis. Full text visible on hover (title attribute).
9.10 IP address display View entries. IP addresses shown in monospace font. Null IPs show "-"
9.11 Empty state Apply filters that return no results. "No audit log entries found." message displayed
9.12 Error state (Simulate: stop backend while modal is open, then apply filters.) Error icon with error message displayed

10. Frontend - Filters

# Test Case Steps Expected Result Pass/Fail
10.1 Username filter Type "admin" in username field, click Apply Filters. Only entries with "admin" in username shown
10.2 Action dropdown populated Click the Action dropdown. Lists all distinct actions present in the database (from /api/audit-logs/actions)
10.3 Action filter Select "login" from Action dropdown, click Apply. Only login entries shown
10.4 Entity type dropdown Click the Entity Type dropdown. Lists: auth, cve, document, user
10.5 Entity type filter Select "cve", click Apply. Only CVE-related entries shown
10.6 Date range filter Set start date to today, set end date to today, click Apply. Only entries from today shown
10.7 Combined filters Set username="admin", action="login", click Apply. Only admin login entries shown
10.8 Reset button Set multiple filters, click Reset. All filter fields cleared. (Note: table does not auto-refresh until Apply is clicked again.)
10.9 Apply after reset Click Reset, then click Apply Filters. Full unfiltered results shown
10.10 Filter resets to page 1 Navigate to page 2, then apply a filter. Results start from page 1

11. Frontend - Pagination

# Test Case Steps Expected Result Pass/Fail
11.1 Pagination info displayed Open modal with >25 entries. Shows "Showing 1 - 25 of N entries" and "Page 1 of X"
11.2 Next page button Click the right chevron. Page advances. Entry range updates. "Page 2 of X" shown.
11.3 Previous page button Navigate to page 2, then click left chevron. Returns to page 1
11.4 First page - prev disabled On page 1, check left chevron. Button is disabled (grayed out, not clickable)
11.5 Last page - next disabled Navigate to the last page. Right chevron is disabled
11.6 Pagination hidden for few entries Open modal with <= 25 total entries. No pagination controls shown (totalPages <= 1)
11.7 Entry count accuracy Compare "Showing X - Y of Z" with actual table rows. Row count matches Y - X + 1. Total Z matches database count.

12. Fire-and-Forget Behavior

# Test Case Steps Expected Result Pass/Fail
12.1 Audit failure does not break login (Requires code-level test or corrupting audit_logs table temporarily.) Rename audit_logs table, attempt login. Login succeeds. Console shows "Audit log error:" message.
12.2 Audit failure does not break CVE create With corrupted audit table, create a CVE. CVE created successfully. Error logged to console only.
12.3 Response not delayed by audit Create a CVE and observe response time. Response returns immediately; audit insert is non-blocking.

13. Data Integrity

# Test Case Steps Expected Result Pass/Fail
13.1 Audit survives user deletion Create user, perform actions, delete user. Query audit_logs for that username. Audit entries remain with the username preserved (denormalized). No foreign key cascade.
13.2 Details stored as valid JSON Query SELECT details FROM audit_logs WHERE details IS NOT NULL LIMIT 5. Parse each. All non-null details values are valid JSON strings
13.3 IP address captured Query entries created via browser. ip_address field contains the client IP (e.g., ::1 for localhost or 127.0.0.1)
13.4 Timestamps auto-populated Query entries without explicitly setting created_at. All rows have a created_at value, not NULL
13.5 Null entity_id for auth actions Query SELECT * FROM audit_logs WHERE entity_type='auth'. entity_id is NULL for login/logout/login_failed entries

14. End-to-End Workflow

# Test Case Steps Expected Result Pass/Fail
14.1 Full user lifecycle 1. Admin logs in 2. Creates user "testuser2" 3. testuser2 logs in 4. testuser2 creates a CVE 5. Admin updates testuser2's role 6. Admin deletes testuser2 7. Open Audit Log and review All 6 actions visible in the audit log in reverse chronological order. Each entry has correct user, action, entity, and details.
14.2 Filter down to one user's actions Perform test 14.1, then filter by username="testuser2". Only testuser2's own actions shown (login, cve_create). Admin actions on testuser2 show admin as the actor.
14.3 Security audit trail Attempt 3 failed logins with wrong password, then succeed. Open Audit Log, filter action="login_failed". All 3 failed attempts visible with timestamps and IP addresses. Useful for detecting brute force.

Test Summary

Section Tests Description
1. Database & Schema 5 Table creation, indexes, migration idempotency
2. Auth Logging 6 Login success/failure variants, logout
3. CVE Logging 4 Create, status update, bug fix verification
4. Document Logging 3 Upload, delete, metadata capture
5. User Mgmt Logging 7 Create, update, delete, edge cases
6. API Access Control 6 Admin-only enforcement on all endpoints
7. API Filtering 12 Pagination, filters, combined queries
8. Menu Access 5 Role-based UI visibility
9. Modal Display 12 Table rendering, formatting, states
10. Frontend Filters 10 Filter UI interaction and behavior
11. Pagination UI 7 Navigation, boundary conditions
12. Fire-and-Forget 3 Non-blocking audit behavior
13. Data Integrity 5 Denormalization, JSON, timestamps
14. End-to-End 3 Full workflow validation
Total 88