- Added `auditLogEdge.js` for Edge Runtime compatible audit logging, including console logging and API fallback. - Introduced `auditLogSafe.js` for safe audit logging without direct database imports, ensuring compatibility across runtimes. - Enhanced `auth.js` to integrate safe audit logging for login actions, including success and failure cases. - Created middleware `auditLog.js` to facilitate audit logging for API routes with predefined configurations. - Updated `middleware.js` to allow API route access without authentication checks. - Added tests for audit logging functionality and Edge compatibility in `test-audit-logging.mjs` and `test-edge-compatibility.mjs`. - Implemented safe audit logging tests in `test-safe-audit-logging.mjs` to verify functionality across environments.
9.0 KiB
Audit Logging Implementation
This document describes the audit logging system implemented for the panel application. The system provides comprehensive tracking of user actions and system events for security, compliance, and monitoring purposes.
Features
- Comprehensive Action Tracking: Logs all CRUD operations on projects, tasks, contracts, notes, and user management
- Authentication Events: Tracks login attempts, successes, and failures
- Detailed Context: Captures IP addresses, user agents, and request details
- Flexible Filtering: Query logs by user, action, resource type, date range, and more
- Statistics Dashboard: Provides insights into system usage patterns
- Role-based Access: Only admins and project managers can view audit logs
- Performance Optimized: Uses database indexes for efficient querying
Architecture
Core Components
-
Audit Log Utility (
src/lib/auditLog.js)- Core logging functions
- Query and statistics functions
- Action and resource type constants
-
API Endpoints (
src/app/api/audit-logs/)/api/audit-logs- Query audit logs with filtering/api/audit-logs/stats- Get audit log statistics
-
UI Components (
src/components/AuditLogViewer.js)- Interactive audit log viewer
- Advanced filtering interface
- Statistics dashboard
-
Admin Pages (
src/app/admin/audit-logs/)- Admin interface for viewing audit logs
- Role-based access control
Database Schema
The audit logs are stored in the audit_logs table:
CREATE TABLE audit_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT, -- User who performed the action
action TEXT NOT NULL, -- Action performed (see AUDIT_ACTIONS)
resource_type TEXT, -- Type of resource affected
resource_id TEXT, -- ID of the affected resource
ip_address TEXT, -- IP address of the user
user_agent TEXT, -- Browser/client information
timestamp TEXT DEFAULT CURRENT_TIMESTAMP,
details TEXT, -- Additional details (JSON)
FOREIGN KEY (user_id) REFERENCES users(id)
);
Usage
Basic Logging
import { logAuditEvent, AUDIT_ACTIONS, RESOURCE_TYPES } from "@/lib/auditLog";
// Log a simple action
logAuditEvent({
action: AUDIT_ACTIONS.PROJECT_CREATE,
userId: "user123",
resourceType: RESOURCE_TYPES.PROJECT,
resourceId: "proj-456",
ipAddress: req.ip,
userAgent: req.headers["user-agent"],
details: {
project_name: "New Project",
project_number: "NP-001",
},
});
API Route Integration
import { logApiAction, AUDIT_ACTIONS, RESOURCE_TYPES } from "@/lib/auditLog";
export async function POST(req) {
const data = await req.json();
// Perform the operation
const result = createProject(data);
// Log the action
logApiAction(
req,
AUDIT_ACTIONS.PROJECT_CREATE,
RESOURCE_TYPES.PROJECT,
result.id.toString(),
req.session,
{ projectData: data }
);
return NextResponse.json({ success: true, id: result.id });
}
Querying Audit Logs
import { getAuditLogs, getAuditLogStats } from "@/lib/auditLog";
// Get recent logs
const recentLogs = getAuditLogs({
limit: 50,
orderBy: "timestamp",
orderDirection: "DESC",
});
// Get logs for a specific user
const userLogs = getAuditLogs({
userId: "user123",
startDate: "2025-01-01T00:00:00Z",
endDate: "2025-12-31T23:59:59Z",
});
// Get statistics
const stats = getAuditLogStats({
startDate: "2025-01-01T00:00:00Z",
endDate: "2025-12-31T23:59:59Z",
});
Available Actions
Authentication Actions
login- Successful user loginlogout- User logoutlogin_failed- Failed login attempt
Project Actions
project_create- Project creationproject_update- Project modificationproject_delete- Project deletionproject_view- Project viewing
Task Actions
task_create- Task creationtask_update- Task modificationtask_delete- Task deletiontask_status_change- Task status modification
Project Task Actions
project_task_create- Project task assignmentproject_task_update- Project task modificationproject_task_delete- Project task removalproject_task_status_change- Project task status change
Contract Actions
contract_create- Contract creationcontract_update- Contract modificationcontract_delete- Contract deletion
Note Actions
note_create- Note creationnote_update- Note modificationnote_delete- Note deletion
Admin Actions
user_create- User account creationuser_update- User account modificationuser_delete- User account deletionuser_role_change- User role modification
System Actions
data_export- Data export operationsbulk_operation- Bulk data operations
Resource Types
project- Project resourcestask- Task templatesproject_task- Project-specific taskscontract- Contractsnote- Notes and commentsuser- User accountssession- Authentication sessionssystem- System-level operations
API Endpoints
GET /api/audit-logs
Query audit logs with optional filtering.
Query Parameters:
userId- Filter by user IDaction- Filter by action typeresourceType- Filter by resource typeresourceId- Filter by resource IDstartDate- Filter from date (ISO string)endDate- Filter to date (ISO string)limit- Maximum results (default: 100)offset- Results offset (default: 0)orderBy- Order by field (default: timestamp)orderDirection- ASC or DESC (default: DESC)includeStats- Include statistics (true/false)
Response:
{
"success": true,
"data": [
{
"id": 1,
"user_id": "user123",
"user_name": "John Doe",
"user_email": "john@example.com",
"action": "project_create",
"resource_type": "project",
"resource_id": "proj-456",
"ip_address": "192.168.1.100",
"user_agent": "Mozilla/5.0...",
"timestamp": "2025-07-09T10:30:00Z",
"details": {
"project_name": "New Project",
"project_number": "NP-001"
}
}
],
"stats": {
"total": 150,
"actionBreakdown": [...],
"userBreakdown": [...],
"resourceBreakdown": [...]
}
}
GET /api/audit-logs/stats
Get audit log statistics.
Query Parameters:
startDate- Filter from date (ISO string)endDate- Filter to date (ISO string)
Response:
{
"success": true,
"data": {
"total": 150,
"actionBreakdown": [
{ "action": "project_view", "count": 45 },
{ "action": "login", "count": 23 }
],
"userBreakdown": [
{ "user_id": "user123", "user_name": "John Doe", "count": 67 }
],
"resourceBreakdown": [{ "resource_type": "project", "count": 89 }]
}
}
Access Control
Audit logs are restricted to users with the following roles:
admin- Full access to all audit logsproject_manager- Full access to all audit logs
Other users cannot access audit logs.
Testing
Run the audit logging test script:
node test-audit-logging.mjs
This will:
- Create sample audit events
- Test querying and filtering
- Verify statistics generation
- Test date range filtering
Integration Status
The audit logging system has been integrated into the following API routes:
✅ Authentication (src/lib/auth.js)
- Login success/failure tracking
- Account lockout logging
✅ Projects (src/app/api/projects/)
- Project CRUD operations
- List view access
✅ Notes (src/app/api/notes/)
- Note creation, updates, and deletion
🔄 Pending Integration:
- Tasks API
- Project Tasks API
- Contracts API
- User management API
Performance Considerations
- Database indexes are created on frequently queried fields
- Large result sets are paginated
- Statistics queries are optimized for common use cases
- Failed operations are logged to prevent data loss
Security Features
- IP address tracking for forensic analysis
- User agent logging for client identification
- Failed authentication attempt tracking
- Detailed change logging for sensitive operations
- Role-based access control for audit log viewing
Maintenance
Log Retention
Consider implementing log retention policies:
-- Delete audit logs older than 1 year
DELETE FROM audit_logs
WHERE timestamp < datetime('now', '-1 year');
Monitoring
Monitor audit log growth and performance:
-- Check audit log table size
SELECT COUNT(*) as total_logs,
MIN(timestamp) as oldest_log,
MAX(timestamp) as newest_log
FROM audit_logs;
-- Check most active users
SELECT user_id, COUNT(*) as activity_count
FROM audit_logs
WHERE timestamp > datetime('now', '-30 days')
GROUP BY user_id
ORDER BY activity_count DESC
LIMIT 10;
Future Enhancements
- Real-time audit log streaming
- Advanced analytics and reporting
- Integration with external SIEM systems
- Automatic anomaly detection
- Compliance reporting templates
- Log export functionality