Files
dss/admin-ui/js/services/audit-service.js
Digital Production Factory 276ed71f31 Initial commit: Clean DSS implementation
Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm

Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)

Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability

Migration completed: $(date)
🤖 Clean migration with full functionality preserved
2025-12-09 18:45:48 -03:00

194 lines
4.8 KiB
JavaScript

/**
* Audit Log Service - User action history tracking
*/
import api from '../core/api.js';
import logger from '../core/logger.js';
class AuditService {
constructor() {
this.cache = {
categories: null,
actions: null
};
}
/**
* Get audit log with filters
*/
async getAuditLog(filters = {}) {
const params = new URLSearchParams();
if (filters.project_id) params.append('project_id', filters.project_id);
if (filters.user_id) params.append('user_id', filters.user_id);
if (filters.action) params.append('action', filters.action);
if (filters.category) params.append('category', filters.category);
if (filters.entity_type) params.append('entity_type', filters.entity_type);
if (filters.severity) params.append('severity', filters.severity);
if (filters.start_date) params.append('start_date', filters.start_date);
if (filters.end_date) params.append('end_date', filters.end_date);
if (filters.limit) params.append('limit', filters.limit);
if (filters.offset) params.append('offset', filters.offset);
try {
const response = await api.get(`/audit?${params.toString()}`);
return response;
} catch (error) {
logger.error('AuditService', 'Failed to fetch audit log', error);
throw error;
}
}
/**
* Get audit statistics
*/
async getStats() {
try {
return await api.get('/audit/stats');
} catch (error) {
logger.error('AuditService', 'Failed to fetch audit stats', error);
return {
by_category: {},
by_user: {},
total_count: 0
};
}
}
/**
* Get all categories
*/
async getCategories() {
if (this.cache.categories) {
return this.cache.categories;
}
try {
this.cache.categories = await api.get('/audit/categories');
return this.cache.categories;
} catch (error) {
logger.error('AuditService', 'Failed to fetch categories', error);
return [];
}
}
/**
* Get all actions
*/
async getActions() {
if (this.cache.actions) {
return this.cache.actions;
}
try {
this.cache.actions = await api.get('/audit/actions');
return this.cache.actions;
} catch (error) {
logger.error('AuditService', 'Failed to fetch actions', error);
return [];
}
}
/**
* Create audit entry
*/
async logAction(entry) {
try {
await api.post('/audit', entry);
logger.info('AuditService', 'Action logged', { action: entry.action });
} catch (error) {
logger.error('AuditService', 'Failed to log action', error);
}
}
/**
* Export audit log
*/
async export(filters = {}, format = 'json') {
const params = new URLSearchParams({ format });
if (filters.project_id) params.append('project_id', filters.project_id);
if (filters.category) params.append('category', filters.category);
if (filters.start_date) params.append('start_date', filters.start_date);
if (filters.end_date) params.append('end_date', filters.end_date);
try {
const url = `${api.baseUrl}/audit/export?${params.toString()}`;
window.open(url, '_blank');
logger.info('AuditService', 'Export initiated', { format });
} catch (error) {
logger.error('AuditService', 'Failed to export', error);
throw error;
}
}
/**
* Get severity badge class
*/
getSeverityClass(severity) {
const classes = {
'info': 'badge--primary',
'warning': 'badge--warning',
'critical': 'badge--destructive'
};
return classes[severity] || 'badge--secondary';
}
/**
* Get category icon
*/
getCategoryIcon(category) {
const icons = {
'design_system': '🎨',
'code': '⚛️',
'configuration': '⚙️',
'project': '📁',
'team': '👥',
'storybook': '📚',
'other': '📌'
};
return icons[category] || '📌';
}
/**
* Format timestamp
*/
formatTimestamp(timestamp) {
const date = new Date(timestamp);
const now = new Date();
const diff = now - date;
// Less than 1 minute
if (diff < 60000) {
return 'Just now';
}
// Less than 1 hour
if (diff < 3600000) {
const minutes = Math.floor(diff / 60000);
return `${minutes} minute${minutes > 1 ? 's' : ''} ago`;
}
// Less than 1 day
if (diff < 86400000) {
const hours = Math.floor(diff / 3600000);
return `${hours} hour${hours > 1 ? 's' : ''} ago`;
}
// Less than 7 days
if (diff < 604800000) {
const days = Math.floor(diff / 86400000);
return `${days} day${days > 1 ? 's' : ''} ago`;
}
// Show full date
return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
}
}
// Singleton instance
const auditService = new AuditService();
export default auditService;
export { AuditService };