feat: implement account settings and API tokens management
- Added SettingsComponent for user profile management, including display name and password change functionality. - Introduced TokensComponent for managing API tokens, including creation and revocation. - Created LayoutComponent for consistent application layout with navigation and user information. - Established main application structure in index.html and main.ts. - Integrated Tailwind CSS for styling and responsive design. - Configured TypeScript settings for strict type checking and module resolution.
This commit is contained in:
171
ts/models/auditlog.ts
Normal file
171
ts/models/auditlog.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* AuditLog model for Stack.Gallery Registry
|
||||
*/
|
||||
|
||||
import * as plugins from '../plugins.ts';
|
||||
import type { IAuditLog, TAuditAction, TAuditResourceType } from '../interfaces/audit.interfaces.ts';
|
||||
import { getDb } from './db.ts';
|
||||
|
||||
@plugins.smartdata.Collection(() => getDb())
|
||||
export class AuditLog
|
||||
extends plugins.smartdata.SmartDataDbDoc<AuditLog, AuditLog>
|
||||
implements IAuditLog
|
||||
{
|
||||
@plugins.smartdata.unI()
|
||||
public id: string = '';
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
@plugins.smartdata.index()
|
||||
public actorId?: string;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
@plugins.smartdata.index()
|
||||
public actorType: 'user' | 'api_token' | 'system' | 'anonymous' = 'anonymous';
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public actorTokenId?: string;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public actorIp?: string;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public actorUserAgent?: string;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
@plugins.smartdata.index()
|
||||
public action: TAuditAction = 'USER_CREATED';
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
@plugins.smartdata.index()
|
||||
public resourceType: TAuditResourceType = 'user';
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
@plugins.smartdata.index()
|
||||
public resourceId?: string;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public resourceName?: string;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
@plugins.smartdata.index()
|
||||
public organizationId?: string;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
@plugins.smartdata.index()
|
||||
public repositoryId?: string;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public metadata: Record<string, unknown> = {};
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
@plugins.smartdata.index()
|
||||
public success: boolean = true;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public errorCode?: string;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public errorMessage?: string;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
public durationMs?: number;
|
||||
|
||||
@plugins.smartdata.svDb()
|
||||
@plugins.smartdata.index()
|
||||
public timestamp: Date = new Date();
|
||||
|
||||
/**
|
||||
* Create an audit log entry
|
||||
*/
|
||||
public static async log(data: {
|
||||
actorId?: string;
|
||||
actorType?: 'user' | 'api_token' | 'system' | 'anonymous';
|
||||
actorTokenId?: string;
|
||||
actorIp?: string;
|
||||
actorUserAgent?: string;
|
||||
action: TAuditAction;
|
||||
resourceType: TAuditResourceType;
|
||||
resourceId?: string;
|
||||
resourceName?: string;
|
||||
organizationId?: string;
|
||||
repositoryId?: string;
|
||||
metadata?: Record<string, unknown>;
|
||||
success?: boolean;
|
||||
errorCode?: string;
|
||||
errorMessage?: string;
|
||||
durationMs?: number;
|
||||
}): Promise<AuditLog> {
|
||||
const log = new AuditLog();
|
||||
log.id = await AuditLog.getNewId();
|
||||
log.actorId = data.actorId;
|
||||
log.actorType = data.actorType || (data.actorId ? 'user' : 'anonymous');
|
||||
log.actorTokenId = data.actorTokenId;
|
||||
log.actorIp = data.actorIp;
|
||||
log.actorUserAgent = data.actorUserAgent;
|
||||
log.action = data.action;
|
||||
log.resourceType = data.resourceType;
|
||||
log.resourceId = data.resourceId;
|
||||
log.resourceName = data.resourceName;
|
||||
log.organizationId = data.organizationId;
|
||||
log.repositoryId = data.repositoryId;
|
||||
log.metadata = data.metadata || {};
|
||||
log.success = data.success ?? true;
|
||||
log.errorCode = data.errorCode;
|
||||
log.errorMessage = data.errorMessage;
|
||||
log.durationMs = data.durationMs;
|
||||
log.timestamp = new Date();
|
||||
await log.save();
|
||||
return log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query audit logs with filters
|
||||
*/
|
||||
public static async query(filters: {
|
||||
actorId?: string;
|
||||
organizationId?: string;
|
||||
repositoryId?: string;
|
||||
resourceType?: TAuditResourceType;
|
||||
action?: TAuditAction[];
|
||||
success?: boolean;
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
offset?: number;
|
||||
limit?: number;
|
||||
}): Promise<{ logs: AuditLog[]; total: number }> {
|
||||
const query: Record<string, unknown> = {};
|
||||
|
||||
if (filters.actorId) query.actorId = filters.actorId;
|
||||
if (filters.organizationId) query.organizationId = filters.organizationId;
|
||||
if (filters.repositoryId) query.repositoryId = filters.repositoryId;
|
||||
if (filters.resourceType) query.resourceType = filters.resourceType;
|
||||
if (filters.action) query.action = { $in: filters.action };
|
||||
if (filters.success !== undefined) query.success = filters.success;
|
||||
|
||||
if (filters.startDate || filters.endDate) {
|
||||
query.timestamp = {};
|
||||
if (filters.startDate) (query.timestamp as Record<string, unknown>).$gte = filters.startDate;
|
||||
if (filters.endDate) (query.timestamp as Record<string, unknown>).$lte = filters.endDate;
|
||||
}
|
||||
|
||||
// Get total count
|
||||
const allLogs = await AuditLog.getInstances(query);
|
||||
const total = allLogs.length;
|
||||
|
||||
// Apply pagination
|
||||
const offset = filters.offset || 0;
|
||||
const limit = filters.limit || 100;
|
||||
const logs = allLogs.slice(offset, offset + limit);
|
||||
|
||||
return { logs, total };
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle hook
|
||||
*/
|
||||
public async beforeSave(): Promise<void> {
|
||||
if (!this.id) {
|
||||
this.id = await AuditLog.getNewId();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user