Add admin page overhaul and compliance schema drift check specs, compliance upload improvements, drift checker helper

This commit is contained in:
root
2026-04-20 20:12:12 +00:00
parent 6082721452
commit 043c85cc69
20 changed files with 56814 additions and 59 deletions

View File

@@ -0,0 +1 @@
{"specId": "30e46443-e636-4df1-bb98-886f403b2e32", "workflowType": "requirements-first", "specType": "feature"}

View File

@@ -0,0 +1,423 @@
# Design Document: Admin Page Overhaul
## Overview
The Admin Page Overhaul replaces the current inline `UserManagement` modal rendering on the admin page with a full-page, themed admin panel. The new `AdminPage` component follows the same layout conventions as `CompliancePage`, `ExportsPage`, and `KnowledgeBasePage` — a top-level page component rendered in the main content area of `App.js` when `currentPage === 'admin'`.
The page consolidates three admin functions into a single tabbed interface:
1. **User Management** — themed table with inline add/edit forms, group badges, and active status toggles
2. **Audit Log** — paginated, filterable log table with action-type badges and date range filters
3. **System Info** — stat cards showing user counts, audit log totals, and recent activity
All sections use the dark tactical intelligence theme defined in `DESIGN_SYSTEM.md` and `App.css``intel-card` containers, `intel-button` controls, `intel-input` form fields, `status-badge` action labels, and `stat-card` stat displays.
### Design Decisions
- **New component, not a wrapper.** The existing `UserManagement.js` and `AuditLog.js` are white-background modals with Tailwind utility classes. Wrapping them would create visual inconsistency. The `AdminPage` component builds themed versions of both panels from scratch, reusing the same backend API endpoints.
- **Existing modals preserved.** The `UserMenu` quick-access links ("Manage Users", "Audit Log") continue to open the existing modal components. This keeps the quick-access workflow intact while the admin page provides the full-featured experience.
- **No new backend endpoints.** All data comes from existing routes: `GET /api/users`, `POST/PATCH/DELETE /api/users/:id`, `GET /api/audit-logs`, `GET /api/audit-logs/actions`.
- **Inline styles + App.css classes.** Follows the project convention of defining style constants in the component file and referencing `App.css` classes (`intel-card`, `intel-button`, `data-row`, etc.) where available.
## Architecture
```mermaid
graph TD
A[App.js] -->|currentPage === 'admin' && isAdmin| B[AdminPage]
B --> C[Tab Navigation]
C -->|"User Management"| D[UserManagementPanel]
C -->|"Audit Log"| E[AuditLogPanel]
C -->|"System Info"| F[SystemInfoPanel]
D -->|GET /api/users| G[Backend: users.js]
D -->|POST /api/users| G
D -->|PATCH /api/users/:id| G
D -->|DELETE /api/users/:id| G
E -->|GET /api/audit-logs| H[Backend: auditLog.js]
E -->|GET /api/audit-logs/actions| H
F -->|GET /api/users| G
F -->|GET /api/audit-logs?limit=10| H
```
### Component Hierarchy
```
AdminPage
├── PageHeader (title + accent glow)
├── TabNavigation (User Management | Audit Log | System Info)
├── UserManagementPanel
│ ├── AddUserButton / InlineForm
│ ├── UserTable
│ │ └── UserRow (group badge, status toggle, edit/delete actions)
│ ├── ErrorBanner
│ └── SuccessToast
├── AuditLogPanel
│ ├── FilterBar (username, action, entity type, start date, end date)
│ ├── LogTable
│ │ └── LogRow (timestamp, user, action badge, entity, details, IP)
│ ├── Pagination
│ ├── EmptyState
│ └── ErrorBanner
└── SystemInfoPanel
├── StatCards (total users, active users, audit entries, recent logins)
└── RecentActivityList (10 most recent audit entries)
```
### Data Flow
1. `App.js` renders `<AdminPage />` when `currentPage === 'admin'` and `isAdmin()` returns true. Non-admin users are redirected to home.
2. `AdminPage` manages the active tab in local state (default: `'users'`).
3. Each panel fetches its own data on mount using `fetch()` with `credentials: 'include'`.
4. Mutations (create, update, delete user) trigger a re-fetch of the user list. Success/error feedback is shown inline.
5. Audit log panel manages its own pagination and filter state, re-fetching on filter apply or page change.
6. System info panel fetches user list and recent audit logs on mount, computing derived stats client-side.
## Components and Interfaces
### AdminPage (main component)
```javascript
// frontend/src/components/pages/AdminPage.js
export default function AdminPage() {
// Props: none (reads auth context internally)
// State:
// activeTab: 'users' | 'audit' | 'system'
// Renders: PageHeader, TabNavigation, conditional panel
}
```
### TabNavigation
```javascript
// Internal to AdminPage
// Props:
// activeTab: string
// onTabChange: (tab: string) => void
// Tabs: [
// { id: 'users', label: 'User Management', icon: Shield },
// { id: 'audit', label: 'Audit Log', icon: Clock },
// { id: 'system', label: 'System Info', icon: Activity },
// ]
```
Styling: monospace uppercase text, `--intel-accent` border and background on active tab, transparent with muted text on inactive tabs. Matches the tab pattern used in `CompliancePage` (team tabs).
### UserManagementPanel
```javascript
// Internal to AdminPage
// State:
// users: Array<User>
// loading: boolean
// error: string | null
// showForm: boolean
// editingUser: User | null
// formData: { username, email, password, group }
// formError: string
// successMessage: string
//
// API calls:
// GET /api/users → fetch all users
// POST /api/users → create user
// PATCH /api/users/:id → update user (fields, group, is_active)
// DELETE /api/users/:id → delete user
//
// Group badge colors (themed):
// Admin: --intel-danger (#EF4444)
// Standard_User: --intel-accent (#0EA5E9)
// Leadership: --intel-warning (#F59E0B)
// Read_Only: --text-muted (#94A3B8)
```
### AuditLogPanel
```javascript
// Internal to AdminPage
// State:
// logs: Array<AuditLogEntry>
// loading: boolean
// error: string | null
// pagination: { page, limit, total, totalPages }
// filters: { user, action, entityType, startDate, endDate }
// actions: string[] (populated from /api/audit-logs/actions)
//
// API calls:
// GET /api/audit-logs?page=&limit=25&user=&action=&entityType=&startDate=&endDate=
// GET /api/audit-logs/actions
//
// Action badge colors (themed):
// login/logout: --intel-success (#10B981)
// *_create: --intel-accent (#0EA5E9)
// *_update/*_edit: --intel-warning (#F59E0B)
// *_delete: --intel-danger (#EF4444)
// default: --text-muted (#94A3B8)
```
### SystemInfoPanel
```javascript
// Internal to AdminPage
// State:
// users: Array<User>
// recentLogs: Array<AuditLogEntry>
// loading: boolean
// errors: { users: string | null, logs: string | null }
//
// Derived stats:
// totalUsers: users.length
// activeUsers: users.filter(u => u.is_active).length
// recentLogins: users.filter(u => u.last_login && withinLast7Days(u.last_login)).length
// totalAuditEntries: fetched from audit-logs pagination.total
//
// API calls:
// GET /api/users
// GET /api/audit-logs?limit=10&page=1
```
### Integration with App.js
```javascript
// In App.js, replace:
// {currentPage === 'admin' && isAdmin() && (
// <div className="space-y-6">
// <UserManagement onClose={() => setCurrentPage('home')} />
// </div>
// )}
//
// With:
// {currentPage === 'admin' && isAdmin() && <AdminPage />}
// {currentPage === 'admin' && !isAdmin() && /* redirect to home */}
//
// Keep existing modal triggers:
// {showUserManagement && <UserManagement onClose={...} />}
// {showAuditLog && <AuditLog onClose={...} />}
```
## Data Models
### User (from GET /api/users)
```javascript
{
id: number,
username: string,
email: string,
group: 'Admin' | 'Standard_User' | 'Leadership' | 'Read_Only',
is_active: 0 | 1,
created_at: string, // ISO datetime
last_login: string | null // ISO datetime
}
```
### AuditLogEntry (from GET /api/audit-logs)
```javascript
{
id: number,
user_id: number,
username: string,
action: string, // e.g. 'login', 'user_create', 'cve_delete'
entity_type: string, // e.g. 'auth', 'user', 'cve', 'document'
entity_id: string | null,
details: string | null, // JSON string
ip_address: string | null,
created_at: string // ISO datetime
}
```
### AuditLogPagination (from GET /api/audit-logs response)
```javascript
{
logs: AuditLogEntry[],
pagination: {
page: number,
limit: number,
total: number,
totalPages: number
}
}
```
### Tab Configuration
```javascript
const TABS = [
{ id: 'users', label: 'User Management', icon: Shield },
{ id: 'audit', label: 'Audit Log', icon: Clock },
{ id: 'system', label: 'System Info', icon: Activity },
];
```
### Group Badge Theme Map
```javascript
const GROUP_BADGE_THEMED = {
Admin: { bg: 'rgba(239,68,68,0.15)', border: '#EF4444', text: '#FCA5A5' },
Standard_User: { bg: 'rgba(14,165,233,0.15)', border: '#0EA5E9', text: '#7DD3FC' },
Leadership: { bg: 'rgba(245,158,11,0.15)', border: '#F59E0B', text: '#FCD34D' },
Read_Only: { bg: 'rgba(148,163,184,0.15)', border: '#94A3B8', text: '#CBD5E1' },
};
```
### Action Badge Theme Map
```javascript
const ACTION_BADGE_THEMED = {
login: { bg: 'rgba(16,185,129,0.15)', border: '#10B981', text: '#6EE7B7' },
logout: { bg: 'rgba(148,163,184,0.15)', border: '#94A3B8', text: '#CBD5E1' },
login_failed: { bg: 'rgba(239,68,68,0.15)', border: '#EF4444', text: '#FCA5A5' },
user_create: { bg: 'rgba(14,165,233,0.15)', border: '#0EA5E9', text: '#7DD3FC' },
user_update: { bg: 'rgba(245,158,11,0.15)', border: '#F59E0B', text: '#FCD34D' },
user_delete: { bg: 'rgba(239,68,68,0.15)', border: '#EF4444', text: '#FCA5A5' },
cve_create: { bg: 'rgba(14,165,233,0.15)', border: '#0EA5E9', text: '#7DD3FC' },
cve_edit: { bg: 'rgba(245,158,11,0.15)', border: '#F59E0B', text: '#FCD34D' },
cve_delete: { bg: 'rgba(239,68,68,0.15)', border: '#EF4444', text: '#FCA5A5' },
document_upload: { bg: 'rgba(139,92,246,0.15)', border: '#8B5CF6', text: '#C4B5FD' },
document_delete: { bg: 'rgba(239,68,68,0.15)', border: '#EF4444', text: '#FCA5A5' },
};
```
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system — essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
### Property 1: Group badge color mapping is total and correct
*For any* valid user group string (`Admin`, `Standard_User`, `Leadership`, `Read_Only`), the group badge styling function SHALL return a non-null object with `bg`, `border`, and `text` fields matching the themed color for that group. *For any* string that is not one of the four valid groups, the function SHALL return the default muted styling.
**Validates: Requirements 3.3**
### Property 2: Edit form population preserves user data
*For any* user object with arbitrary `username`, `email`, and `group` values, populating the edit form from that user SHALL result in `formData.username === user.username`, `formData.email === user.email`, and `formData.group === user.group`, with `formData.password` set to an empty string.
**Validates: Requirements 3.5**
### Property 3: Self-modification prevention
*For any* user list that contains the currently authenticated admin user, the admin user's own row SHALL have the group dropdown disabled and the active status toggle disabled. *For any* other user in the list, those controls SHALL be enabled.
**Validates: Requirements 3.8**
### Property 4: Action badge color mapping is total and correct
*For any* known audit log action string (from the set of defined actions: `login`, `logout`, `login_failed`, `user_create`, `user_update`, `user_delete`, `cve_create`, `cve_edit`, `cve_delete`, `document_upload`, `document_delete`), the action badge styling function SHALL return the correct themed color object. *For any* unknown action string, the function SHALL return the default muted styling.
**Validates: Requirements 4.4**
### Property 5: Applying filters resets pagination to page 1
*For any* combination of filter values (username text, action type, entity type, start date, end date) and *for any* current page number, applying the filters SHALL result in a fetch call with `page=1`.
**Validates: Requirements 4.7**
### Property 6: Recent login count computation
*For any* list of user objects with random `last_login` timestamps (including null values), the computed "recent logins" count SHALL equal the number of users whose `last_login` is non-null and falls within the last 7 days from the current time.
**Validates: Requirements 5.1**
### Property 7: Admin-only access control
*For any* user object, the admin page content SHALL be rendered if and only if `user.group === 'Admin'`. When `user.group` is any value other than `'Admin'`, the system SHALL redirect to the home page.
**Validates: Requirements 6.1, 6.2**
## Error Handling
### User Management Panel
| Error Scenario | Handling |
|---|---|
| `GET /api/users` fails | Display error banner with `--intel-danger` styling. User table is hidden. Retry on next tab switch or manual refresh. |
| `POST /api/users` fails (validation) | Display `formError` message below the form in danger color. Form remains open for correction. |
| `POST /api/users` fails (409 conflict) | Display "Username or email already exists" in `formError`. |
| `PATCH /api/users/:id` fails | Display inline error. Revert optimistic UI changes if any. |
| `DELETE /api/users/:id` fails | Display alert with error message. User list unchanged. |
| Self-demotion attempt | Group dropdown disabled for current user. Backend returns 400 if bypassed. |
| Self-deactivation attempt | Toggle disabled for current user. Backend returns 400 if bypassed. |
### Audit Log Panel
| Error Scenario | Handling |
|---|---|
| `GET /api/audit-logs` fails | Display error banner with `--intel-danger` styling. Table hidden. |
| `GET /api/audit-logs/actions` fails | Action filter dropdown shows no options. Non-critical — silently ignored. |
| Invalid date range (start > end) | Client-side: no validation needed — backend handles gracefully by returning empty results. |
| Empty result set | Display "No audit log entries found" message in `--text-muted` color. |
### System Info Panel
| Error Scenario | Handling |
|---|---|
| `GET /api/users` fails | Affected stat cards (total users, active users, recent logins) show "Unable to load" fallback text. |
| `GET /api/audit-logs` fails | Audit entries stat card and recent activity list show "Unable to load" fallback. |
| Partial failure (one endpoint fails) | Only the affected cards show fallback. Successfully loaded cards display normally. |
### Success Feedback
- Create user: green success toast "User created successfully" auto-dismisses after 2 seconds.
- Update user: green success toast "User updated successfully" auto-dismisses after 2 seconds.
- Delete user: green success toast "User deleted" auto-dismisses after 2 seconds.
- Toggle active status: immediate UI update, no toast (inline visual feedback is sufficient).
## Testing Strategy
### Unit Tests (Example-Based)
Unit tests cover specific rendering, interaction, and integration scenarios:
**AdminPage structure:**
- Renders page header with "Admin Panel" title
- Defaults to User Management tab on mount
- Switches panels when tabs are clicked
- Only renders when user is admin (access control)
**UserManagementPanel:**
- Renders user table with all required columns
- Displays themed group badges for each group type
- Shows inline form when "Add User" is clicked
- Populates form with user data when edit is clicked
- Shows confirmation dialog on delete
- Disables self-modification controls for current user
- Displays error banner on API failure
- Displays success toast on successful operations
**AuditLogPanel:**
- Renders log table with all required columns
- Displays themed action badges
- Renders filter controls (username, action, entity type, dates)
- Fetches page 1 when filters are applied
- Navigates pages with pagination controls
- Shows empty state when no results
- Shows error banner on API failure
**SystemInfoPanel:**
- Renders four stat cards with correct labels
- Computes derived stats correctly from mock data
- Shows recent activity list with up to 10 entries
- Shows fallback message when an API call fails
### Property-Based Tests
Property-based tests use [fast-check](https://github.com/dubzzz/fast-check) to verify universal properties across generated inputs. Each test runs a minimum of 100 iterations.
| Property | Test Description | Tag |
|---|---|---|
| Property 1 | Generate random group strings (valid + invalid), verify badge function returns correct colors | Feature: admin-page-overhaul, Property 1: Group badge color mapping is total and correct |
| Property 2 | Generate random user objects, verify edit form population matches user fields exactly | Feature: admin-page-overhaul, Property 2: Edit form population preserves user data |
| Property 3 | Generate random user lists containing the current admin, verify self-edit controls are disabled | Feature: admin-page-overhaul, Property 3: Self-modification prevention |
| Property 4 | Generate random action strings (known + unknown), verify badge function returns correct colors | Feature: admin-page-overhaul, Property 4: Action badge color mapping is total and correct |
| Property 5 | Generate random filter states and current page numbers, verify fetch is called with page=1 | Feature: admin-page-overhaul, Property 5: Applying filters resets pagination to page 1 |
| Property 6 | Generate random user lists with random last_login timestamps, verify recent login count matches manual computation | Feature: admin-page-overhaul, Property 6: Recent login count computation |
| Property 7 | Generate random user objects with random groups, verify admin page renders iff group === 'Admin' | Feature: admin-page-overhaul, Property 7: Admin-only access control |
### Test Configuration
- **Library:** fast-check (JavaScript property-based testing)
- **Runner:** Jest (via react-scripts test)
- **Iterations:** Minimum 100 per property test (`fc.assert(property, { numRuns: 100 })`)
- **Tag format:** Comment at top of each property test referencing the design property

View File

@@ -0,0 +1,108 @@
# Requirements Document
## Introduction
The STEAM Security Dashboard currently has an Admin page (`currentPage === 'admin'`) that renders the `UserManagement` modal component inline — the same modal triggered from the top-right `UserMenu`. The page does not follow the dashboard's dark "tactical intelligence" theme and provides no audit log viewing or other administrative capabilities. This feature overhauls the admin page into a dedicated, full-page admin panel that matches the design system and consolidates user management, audit log viewing, and system administration into a single cohesive interface accessible only to Admin-group users.
## Glossary
- **Admin_Page**: The full-page admin panel rendered when `currentPage === 'admin'`, replacing the current inline modal rendering
- **Dashboard**: The STEAM Security Dashboard application
- **Design_System**: The color palette, typography, component specs, and interaction patterns defined in `DESIGN_SYSTEM.md` and `App.css`
- **Audit_Log_Panel**: The section of the Admin_Page that displays paginated, filterable audit log entries
- **User_Management_Panel**: The section of the Admin_Page that displays the user list and provides create, edit, delete, and activate/deactivate operations
- **Admin_User**: A user whose `user_group` is `Admin`
- **Tab_Navigation**: The in-page navigation component that switches between Admin_Page sections (User Management, Audit Log, System Info)
- **System_Info_Panel**: The section of the Admin_Page that displays system metadata such as active user count, recent login activity, and database statistics
## Requirements
### Requirement 1: Admin Page Layout and Theme Compliance
**User Story:** As an admin, I want the admin page to follow the same dark tactical intelligence theme as the rest of the dashboard, so that the experience is visually consistent.
#### Acceptance Criteria
1. THE Admin_Page SHALL use the Design_System color palette — `--intel-darkest` for the page background, `--intel-dark` and `--intel-medium` for card backgrounds, and `--intel-accent` for interactive elements
2. THE Admin_Page SHALL render as a full-page view within the main content area, matching the layout pattern used by other page components (CompliancePage, ExportsPage, KnowledgeBasePage)
3. THE Admin_Page SHALL display a page header with the title "Admin Panel" styled in monospace uppercase with the accent text glow defined in the Design_System
4. THE Admin_Page SHALL use `intel-card` styled containers for each content section, with the standard gradient backgrounds, border glow, and shadow depth defined in the Design_System
5. THE Admin_Page SHALL use `intel-button` styled controls for all interactive buttons, with primary, danger, and success variants as appropriate
6. THE Admin_Page SHALL use `intel-input` styled form fields for all text inputs, selects, and date pickers
### Requirement 2: Tab-Based Section Navigation
**User Story:** As an admin, I want to navigate between admin sections using tabs, so that I can quickly switch between user management, audit logs, and system information without leaving the page.
#### Acceptance Criteria
1. THE Admin_Page SHALL display a Tab_Navigation component with tabs for "User Management", "Audit Log", and "System Info"
2. WHEN an Admin_User clicks a tab, THE Tab_Navigation SHALL switch the visible content section to the selected tab and visually indicate the active tab using the `--intel-accent` color
3. THE Admin_Page SHALL default to the "User Management" tab when first loaded
4. THE Tab_Navigation SHALL use monospace uppercase text with letter spacing consistent with the Design_System label typography
### Requirement 3: Themed User Management Panel
**User Story:** As an admin, I want to manage users directly within the themed admin page instead of a white modal overlay, so that user management feels integrated into the dashboard.
#### Acceptance Criteria
1. THE User_Management_Panel SHALL display a table of all users with columns for username, email, group, active status, and last login
2. THE User_Management_Panel SHALL style the user table with dark theme rows using `data-row` hover effects and `--text-primary` / `--text-secondary` text colors from the Design_System
3. THE User_Management_Panel SHALL display group badges using severity-style badge coloring — Admin in danger color, Standard_User in accent color, Leadership in warning color, Read_Only in muted color
4. WHEN an Admin_User clicks "Add User", THE User_Management_Panel SHALL display an inline form styled with `intel-input` fields and `intel-button` controls
5. WHEN an Admin_User clicks the edit action on a user row, THE User_Management_Panel SHALL populate the inline form with that user's current data for editing
6. WHEN an Admin_User clicks the delete action on a user row, THE User_Management_Panel SHALL display a confirmation prompt before sending the delete request
7. WHEN an Admin_User toggles a user's active status, THE User_Management_Panel SHALL send a PATCH request and update the displayed status without a full page reload
8. THE User_Management_Panel SHALL prevent an Admin_User from changing their own group or deactivating their own account
9. IF a user management API request fails, THEN THE User_Management_Panel SHALL display an error message styled with the `--intel-danger` color
### Requirement 4: Themed Audit Log Panel
**User Story:** As an admin, I want to view audit logs in a themed, filterable table within the admin page, so that I can monitor system activity without opening a separate modal.
#### Acceptance Criteria
1. THE Audit_Log_Panel SHALL fetch and display paginated audit log entries from the `/api/audit-logs` endpoint
2. THE Audit_Log_Panel SHALL display columns for timestamp, username, action, entity type, entity ID, details, and IP address
3. THE Audit_Log_Panel SHALL style the log table with dark theme rows, monospace font for timestamps and IP addresses, and `data-row` hover effects
4. THE Audit_Log_Panel SHALL display action type badges using color-coded `status-badge` styling — login actions in success color, delete actions in danger color, create actions in accent color, update actions in warning color
5. THE Audit_Log_Panel SHALL provide filter controls for username (text search), action type (dropdown populated from `/api/audit-logs/actions`), entity type (dropdown), start date, and end date
6. THE Audit_Log_Panel SHALL style all filter controls using `intel-input` and `intel-button` components from the Design_System
7. WHEN an Admin_User applies filters, THE Audit_Log_Panel SHALL re-fetch audit logs from page 1 with the selected filter parameters
8. WHEN an Admin_User clicks a pagination control, THE Audit_Log_Panel SHALL fetch the requested page and display a page indicator showing current page, total pages, and total entry count
9. THE Audit_Log_Panel SHALL display a "No audit log entries found" message styled with `--text-muted` color when the query returns zero results
10. IF the audit log API request fails, THEN THE Audit_Log_Panel SHALL display an error message styled with the `--intel-danger` color
### Requirement 5: System Info Panel
**User Story:** As an admin, I want to see a summary of system health and usage statistics, so that I can quickly assess the state of the dashboard.
#### Acceptance Criteria
1. THE System_Info_Panel SHALL display stat cards showing: total user count, active user count, total audit log entries, and count of users who logged in within the last 7 days
2. THE System_Info_Panel SHALL style each stat card using the `stat-card` pattern from the Design_System with the accent-colored top bar and hover lift effect
3. THE System_Info_Panel SHALL display a "Recent Activity" section showing the 10 most recent audit log entries in a compact list format
4. WHEN the System_Info_Panel loads, THE System_Info_Panel SHALL fetch statistics from the existing `/api/users` and `/api/audit-logs` endpoints
5. IF any statistics API request fails, THEN THE System_Info_Panel SHALL display a fallback "Unable to load" message in the affected stat card
### Requirement 6: Access Control
**User Story:** As a non-admin user, I want to be prevented from accessing the admin page, so that sensitive administrative functions are protected.
#### Acceptance Criteria
1. THE Dashboard SHALL render the Admin_Page content only when the authenticated user belongs to the Admin group
2. WHEN a non-admin user navigates to the admin page, THE Dashboard SHALL redirect the user to the home page
3. THE NavDrawer SHALL continue to display the "Admin Panel" navigation item only for Admin-group users
4. THE UserMenu SHALL continue to provide "Manage Users" and "Audit Log" quick-access links for Admin-group users, opening the respective modals as before
### Requirement 7: Loading and Error States
**User Story:** As an admin, I want to see clear loading indicators and error messages, so that I know when data is being fetched and when something goes wrong.
#### Acceptance Criteria
1. WHILE data is being fetched for any Admin_Page section, THE Admin_Page SHALL display a loading spinner styled with the `loading-spinner` class and `--intel-accent` color
2. IF an API request returns an error, THEN THE Admin_Page SHALL display the error message in a container styled with `--intel-danger` border and text color
3. WHEN an Admin_User performs a successful create, update, or delete operation, THE Admin_Page SHALL display a brief success notification styled with `--intel-success` color

View File

@@ -0,0 +1,160 @@
# Implementation Plan: Admin Page Overhaul
## Overview
Replace the current inline `UserManagement` modal rendering on the admin page with a full-page, themed `AdminPage` component. The new component lives at `frontend/src/components/pages/AdminPage.js` and provides three tabbed panels — User Management, Audit Log, and System Info — all styled with the dark tactical intelligence theme. No new backend endpoints are needed; the component reuses existing `/api/users` and `/api/audit-logs` routes. Existing modal components (`UserManagement`, `AuditLog`) are preserved for quick-access from `UserMenu`.
## Tasks
- [ ] 1. Create AdminPage component with page header and tab navigation
- [ ] 1.1 Create `frontend/src/components/pages/AdminPage.js` with the page shell
- Import React, useState, useAuth from AuthContext, and lucide-react icons (Shield, Clock, Activity)
- Define `API_BASE` constant matching project convention
- Define `TABS` array: `[{ id: 'users', label: 'User Management', icon: Shield }, { id: 'audit', label: 'Audit Log', icon: Clock }, { id: 'system', label: 'System Info', icon: Activity }]`
- Render page header with "Admin Panel" title in monospace uppercase with `--intel-accent` text glow
- Render tab navigation bar with monospace uppercase text, `--intel-accent` active styling, and muted inactive styling matching the CompliancePage team-tab pattern
- Manage `activeTab` state defaulting to `'users'`
- Conditionally render placeholder `<div>` for each panel based on `activeTab`
- _Requirements: 1.1, 1.2, 1.3, 2.1, 2.2, 2.3, 2.4_
- [ ] 1.2 Integrate AdminPage into App.js
- Import `AdminPage` from `./components/pages/AdminPage`
- Replace the existing `{currentPage === 'admin' && isAdmin() && (<div className="space-y-6"><UserManagement onClose={() => setCurrentPage('home')} /></div>)}` block with `{currentPage === 'admin' && isAdmin() && <AdminPage />}`
- Add non-admin redirect: `{currentPage === 'admin' && !isAdmin() && setCurrentPage('home')}` (or useEffect equivalent)
- Keep existing `{showUserManagement && <UserManagement onClose={...} />}` and `{showAuditLog && <AuditLog onClose={...} />}` modal triggers unchanged
- _Requirements: 1.2, 6.1, 6.2, 6.3, 6.4_
- [ ] 2. Implement UserManagementPanel
- [ ] 2.1 Build the themed user table and group badges
- Define `GROUP_BADGE_THEMED` map with themed colors: Admin → danger, Standard_User → accent, Leadership → warning, Read_Only → muted
- Fetch users from `GET /api/users` with `credentials: 'include'` on panel mount
- Render user table with columns: username, email, group, active status, last login
- Style table with dark theme rows using `data-row` hover effects and `--text-primary` / `--text-secondary` text colors
- Render group badges using the themed color map with severity-style badge coloring
- Display loading spinner (`loading-spinner` class, `--intel-accent` color) while fetching
- Display error banner with `--intel-danger` styling on fetch failure
- _Requirements: 3.1, 3.2, 3.3, 7.1, 7.2_
- [ ] 2.2 Implement inline add/edit form and CRUD operations
- Add "Add User" button styled with `intel-button` primary variant
- Show inline form with `intel-input` styled fields for username, email, password, and group dropdown
- On edit action: populate form with selected user's data (username, email, group; password blank)
- On form submit: POST (create) or PATCH (update) to `/api/users` or `/api/users/:id`
- On delete action: show confirmation prompt, then DELETE to `/api/users/:id`
- On active status toggle: PATCH to `/api/users/:id` with `is_active` toggled, update UI without full reload
- Prevent self-modification: disable group dropdown and active toggle for the current authenticated user's row
- Display form validation errors with `--intel-danger` color
- Display success toast with `--intel-success` color, auto-dismiss after 2 seconds
- _Requirements: 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 7.3_
- [ ]* 2.3 Write property test: Group badge color mapping is total and correct
- **Property 1: Group badge color mapping is total and correct**
- Install `fast-check` as a dev dependency in `frontend/`
- Create test file `frontend/src/components/pages/__tests__/AdminPage.property.test.js`
- Generate random strings including the four valid groups and arbitrary invalid strings
- Verify the badge function returns correct themed colors for valid groups and default muted styling for invalid groups
- Use `fc.assert(property, { numRuns: 100 })`
- **Validates: Requirements 3.3**
- [ ]* 2.4 Write property test: Edit form population preserves user data
- **Property 2: Edit form population preserves user data**
- Generate random user objects with arbitrary username, email, and group values
- Verify that populating the edit form results in `formData.username === user.username`, `formData.email === user.email`, `formData.group === user.group`, and `formData.password === ''`
- Use `fc.assert(property, { numRuns: 100 })`
- **Validates: Requirements 3.5**
- [ ]* 2.5 Write property test: Self-modification prevention
- **Property 3: Self-modification prevention**
- Generate random user lists that include a user matching the current admin's ID
- Verify the admin's own row has group dropdown disabled and active toggle disabled
- Verify all other users have those controls enabled
- Use `fc.assert(property, { numRuns: 100 })`
- **Validates: Requirements 3.8**
- [ ] 3. Checkpoint — Verify user management panel
- Ensure all tests pass, ask the user if questions arise.
- [ ] 4. Implement AuditLogPanel
- [ ] 4.1 Build the themed audit log table with action badges and filters
- Define `ACTION_BADGE_THEMED` map with themed colors: login/success → green, delete → danger, create → accent, update → warning, default → muted
- Fetch audit logs from `GET /api/audit-logs?page=1&limit=25` with `credentials: 'include'` on panel mount
- Fetch action types from `GET /api/audit-logs/actions` for the action filter dropdown
- Render log table with columns: timestamp, username, action, entity type, entity ID, details, IP address
- Style timestamps and IP addresses with monospace font
- Render action type badges using the themed color map
- Style table with dark theme rows and `data-row` hover effects
- Display loading spinner while fetching, error banner on failure
- Display "No audit log entries found" message with `--text-muted` color when results are empty
- _Requirements: 4.1, 4.2, 4.3, 4.4, 4.9, 4.10, 7.1, 7.2_
- [ ] 4.2 Implement filter controls and pagination
- Render filter bar with: username text input, action type dropdown, entity type dropdown, start date picker, end date picker
- Style all filter controls with `intel-input` and `intel-button` components
- On filter apply: re-fetch audit logs from page 1 with selected filter parameters
- Render pagination controls showing current page, total pages, and total entry count
- On page change: fetch the requested page
- _Requirements: 4.5, 4.6, 4.7, 4.8_
- [ ]* 4.3 Write property test: Action badge color mapping is total and correct
- **Property 4: Action badge color mapping is total and correct**
- Generate random action strings including all known actions and arbitrary unknown strings
- Verify the badge function returns correct themed colors for known actions and default muted styling for unknown actions
- Use `fc.assert(property, { numRuns: 100 })`
- **Validates: Requirements 4.4**
- [ ]* 4.4 Write property test: Applying filters resets pagination to page 1
- **Property 5: Applying filters resets pagination to page 1**
- Generate random filter combinations (username text, action type, entity type, start date, end date) and random current page numbers
- Verify that applying filters results in a fetch call with `page=1`
- Use `fc.assert(property, { numRuns: 100 })`
- **Validates: Requirements 4.7**
- [ ] 5. Implement SystemInfoPanel
- [ ] 5.1 Build stat cards and recent activity list
- Fetch users from `GET /api/users` and recent audit logs from `GET /api/audit-logs?limit=10&page=1` on panel mount
- Compute derived stats: total users (`users.length`), active users (`users.filter(u => u.is_active)`), recent logins (users with `last_login` within last 7 days), total audit entries (from pagination.total)
- Render four stat cards using the `stat-card` pattern with accent-colored top bar and hover lift effect
- Render "Recent Activity" section showing the 10 most recent audit log entries in a compact list format
- Show "Unable to load" fallback in affected stat cards when individual API requests fail
- Display loading spinner while fetching
- _Requirements: 5.1, 5.2, 5.3, 5.4, 5.5, 7.1_
- [ ]* 5.2 Write property test: Recent login count computation
- **Property 6: Recent login count computation**
- Generate random user lists with random `last_login` timestamps (including null values)
- Verify the computed "recent logins" count equals the number of users whose `last_login` is non-null and falls within the last 7 days
- Use `fc.assert(property, { numRuns: 100 })`
- **Validates: Requirements 5.1**
- [ ] 6. Checkpoint — Verify all panels and integration
- Ensure all tests pass, ask the user if questions arise.
- [ ] 7. Access control and final wiring
- [ ] 7.1 Verify access control integration
- Confirm `AdminPage` reads auth context via `useAuth()` and only renders content for Admin-group users
- Confirm `App.js` redirects non-admin users to home when `currentPage === 'admin'`
- Confirm `NavDrawer` continues to show "Admin Panel" only for Admin-group users (no changes needed — verify existing behavior)
- Confirm `UserMenu` quick-access links ("Manage Users", "Audit Log") continue to open existing modal components (no changes needed — verify existing behavior)
- _Requirements: 6.1, 6.2, 6.3, 6.4_
- [ ]* 7.2 Write property test: Admin-only access control
- **Property 7: Admin-only access control**
- Generate random user objects with random group values
- Verify admin page content renders if and only if `user.group === 'Admin'`
- Verify non-Admin groups trigger redirect to home
- Use `fc.assert(property, { numRuns: 100 })`
- **Validates: Requirements 6.1, 6.2**
- [ ] 8. Final checkpoint — Ensure all tests pass
- Ensure all tests pass, ask the user if questions arise.
## Notes
- Tasks marked with `*` are optional and can be skipped for faster MVP
- Each task references specific requirements for traceability
- Checkpoints ensure incremental validation
- Property tests validate universal correctness properties from the design document using fast-check
- Unit tests validate specific examples and edge cases
- Existing `UserManagement.js` and `AuditLog.js` modal components are not modified — they remain for UserMenu quick-access
- All styling follows the project convention of inline styles + App.css classes (no Tailwind in the new component)
- The `fast-check` library must be installed as a dev dependency before running property tests