Add admin page overhaul and compliance schema drift check specs, compliance upload improvements, drift checker helper
This commit is contained in:
1
.kiro/specs/admin-page-overhaul/.config.kiro
Normal file
1
.kiro/specs/admin-page-overhaul/.config.kiro
Normal file
@@ -0,0 +1 @@
|
||||
{"specId": "30e46443-e636-4df1-bb98-886f403b2e32", "workflowType": "requirements-first", "specType": "feature"}
|
||||
423
.kiro/specs/admin-page-overhaul/design.md
Normal file
423
.kiro/specs/admin-page-overhaul/design.md
Normal 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
|
||||
108
.kiro/specs/admin-page-overhaul/requirements.md
Normal file
108
.kiro/specs/admin-page-overhaul/requirements.md
Normal 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
|
||||
160
.kiro/specs/admin-page-overhaul/tasks.md
Normal file
160
.kiro/specs/admin-page-overhaul/tasks.md
Normal 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
|
||||
Reference in New Issue
Block a user