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:
197
ts/services/audit.service.ts
Normal file
197
ts/services/audit.service.ts
Normal file
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* AuditService - Centralized audit logging
|
||||
*/
|
||||
|
||||
import type { TAuditAction, TAuditResourceType } from '../interfaces/audit.interfaces.ts';
|
||||
import { AuditLog } from '../models/index.ts';
|
||||
|
||||
export interface IAuditContext {
|
||||
actorId?: string;
|
||||
actorType?: 'user' | 'api_token' | 'system' | 'anonymous';
|
||||
actorTokenId?: string;
|
||||
actorIp?: string;
|
||||
actorUserAgent?: string;
|
||||
organizationId?: string;
|
||||
repositoryId?: string;
|
||||
}
|
||||
|
||||
export class AuditService {
|
||||
private context: IAuditContext;
|
||||
|
||||
constructor(context: IAuditContext = {}) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new audit service with context
|
||||
*/
|
||||
public static withContext(context: IAuditContext): AuditService {
|
||||
return new AuditService(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an audit event
|
||||
*/
|
||||
public async log(
|
||||
action: TAuditAction,
|
||||
resourceType: TAuditResourceType,
|
||||
options: {
|
||||
resourceId?: string;
|
||||
resourceName?: string;
|
||||
organizationId?: string;
|
||||
repositoryId?: string;
|
||||
metadata?: Record<string, unknown>;
|
||||
success?: boolean;
|
||||
errorCode?: string;
|
||||
errorMessage?: string;
|
||||
durationMs?: number;
|
||||
} = {}
|
||||
): Promise<AuditLog> {
|
||||
return await AuditLog.log({
|
||||
actorId: this.context.actorId,
|
||||
actorType: this.context.actorType,
|
||||
actorTokenId: this.context.actorTokenId,
|
||||
actorIp: this.context.actorIp,
|
||||
actorUserAgent: this.context.actorUserAgent,
|
||||
action,
|
||||
resourceType,
|
||||
resourceId: options.resourceId,
|
||||
resourceName: options.resourceName,
|
||||
organizationId: options.organizationId || this.context.organizationId,
|
||||
repositoryId: options.repositoryId || this.context.repositoryId,
|
||||
metadata: options.metadata,
|
||||
success: options.success,
|
||||
errorCode: options.errorCode,
|
||||
errorMessage: options.errorMessage,
|
||||
durationMs: options.durationMs,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a successful action
|
||||
*/
|
||||
public async logSuccess(
|
||||
action: TAuditAction,
|
||||
resourceType: TAuditResourceType,
|
||||
resourceId?: string,
|
||||
resourceName?: string,
|
||||
metadata?: Record<string, unknown>
|
||||
): Promise<AuditLog> {
|
||||
return await this.log(action, resourceType, {
|
||||
resourceId,
|
||||
resourceName,
|
||||
metadata,
|
||||
success: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a failed action
|
||||
*/
|
||||
public async logFailure(
|
||||
action: TAuditAction,
|
||||
resourceType: TAuditResourceType,
|
||||
errorCode: string,
|
||||
errorMessage: string,
|
||||
resourceId?: string,
|
||||
metadata?: Record<string, unknown>
|
||||
): Promise<AuditLog> {
|
||||
return await this.log(action, resourceType, {
|
||||
resourceId,
|
||||
metadata,
|
||||
success: false,
|
||||
errorCode,
|
||||
errorMessage,
|
||||
});
|
||||
}
|
||||
|
||||
// Convenience methods for common actions
|
||||
|
||||
public async logUserLogin(userId: string, success: boolean, errorMessage?: string): Promise<AuditLog> {
|
||||
if (success) {
|
||||
return await this.logSuccess('USER_LOGIN', 'user', userId);
|
||||
}
|
||||
return await this.logFailure('USER_LOGIN', 'user', 'LOGIN_FAILED', errorMessage || 'Login failed', userId);
|
||||
}
|
||||
|
||||
public async logUserLogout(userId: string): Promise<AuditLog> {
|
||||
return await this.logSuccess('USER_LOGOUT', 'user', userId);
|
||||
}
|
||||
|
||||
public async logTokenCreated(tokenId: string, tokenName: string): Promise<AuditLog> {
|
||||
return await this.logSuccess('TOKEN_CREATED', 'api_token', tokenId, tokenName);
|
||||
}
|
||||
|
||||
public async logTokenRevoked(tokenId: string, tokenName: string): Promise<AuditLog> {
|
||||
return await this.logSuccess('TOKEN_REVOKED', 'api_token', tokenId, tokenName);
|
||||
}
|
||||
|
||||
public async logPackagePublished(
|
||||
packageId: string,
|
||||
packageName: string,
|
||||
version: string,
|
||||
organizationId: string,
|
||||
repositoryId: string
|
||||
): Promise<AuditLog> {
|
||||
return await this.log('PACKAGE_PUBLISHED', 'package', {
|
||||
resourceId: packageId,
|
||||
resourceName: packageName,
|
||||
organizationId,
|
||||
repositoryId,
|
||||
metadata: { version },
|
||||
success: true,
|
||||
});
|
||||
}
|
||||
|
||||
public async logPackageDownloaded(
|
||||
packageId: string,
|
||||
packageName: string,
|
||||
version: string,
|
||||
organizationId: string,
|
||||
repositoryId: string
|
||||
): Promise<AuditLog> {
|
||||
return await this.log('PACKAGE_DOWNLOADED', 'package', {
|
||||
resourceId: packageId,
|
||||
resourceName: packageName,
|
||||
organizationId,
|
||||
repositoryId,
|
||||
metadata: { version },
|
||||
success: true,
|
||||
});
|
||||
}
|
||||
|
||||
public async logOrganizationCreated(orgId: string, orgName: string): Promise<AuditLog> {
|
||||
return await this.logSuccess('ORGANIZATION_CREATED', 'organization', orgId, orgName);
|
||||
}
|
||||
|
||||
public async logRepositoryCreated(
|
||||
repoId: string,
|
||||
repoName: string,
|
||||
organizationId: string
|
||||
): Promise<AuditLog> {
|
||||
return await this.log('REPOSITORY_CREATED', 'repository', {
|
||||
resourceId: repoId,
|
||||
resourceName: repoName,
|
||||
organizationId,
|
||||
success: true,
|
||||
});
|
||||
}
|
||||
|
||||
public async logPermissionChanged(
|
||||
resourceType: TAuditResourceType,
|
||||
resourceId: string,
|
||||
targetUserId: string,
|
||||
oldRole: string | null,
|
||||
newRole: string | null
|
||||
): Promise<AuditLog> {
|
||||
return await this.log('PERMISSION_CHANGED', resourceType, {
|
||||
resourceId,
|
||||
metadata: {
|
||||
targetUserId,
|
||||
oldRole,
|
||||
newRole,
|
||||
},
|
||||
success: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user