feat(opsserver,web): replace the Angular UI and REST management layer with a TypedRequest-based ops server and bundled web frontend
This commit is contained in:
105
ts/opsserver/handlers/audit.handler.ts
Normal file
105
ts/opsserver/handlers/audit.handler.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import * as plugins from '../../plugins.ts';
|
||||
import * as interfaces from '../../../ts_interfaces/index.ts';
|
||||
import type { OpsServer } from '../classes.opsserver.ts';
|
||||
import { requireValidIdentity } from '../helpers/guards.ts';
|
||||
import { AuditLog } from '../../models/auditlog.ts';
|
||||
import { PermissionService } from '../../services/permission.service.ts';
|
||||
|
||||
export class AuditHandler {
|
||||
public typedrouter = new plugins.typedrequest.TypedRouter();
|
||||
private permissionService = new PermissionService();
|
||||
|
||||
constructor(private opsServerRef: OpsServer) {
|
||||
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
||||
this.registerHandlers();
|
||||
}
|
||||
|
||||
private registerHandlers(): void {
|
||||
// Query Audit Logs
|
||||
this.typedrouter.addTypedHandler(
|
||||
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_QueryAudit>(
|
||||
'queryAudit',
|
||||
async (dataArg) => {
|
||||
await requireValidIdentity(this.opsServerRef.authHandler, dataArg);
|
||||
|
||||
try {
|
||||
const {
|
||||
organizationId,
|
||||
repositoryId,
|
||||
resourceType,
|
||||
actions,
|
||||
success,
|
||||
startDate: startDateStr,
|
||||
endDate: endDateStr,
|
||||
limit: limitParam,
|
||||
offset: offsetParam,
|
||||
} = dataArg;
|
||||
|
||||
const limit = limitParam || 100;
|
||||
const offset = offsetParam || 0;
|
||||
const startDate = startDateStr ? new Date(startDateStr) : undefined;
|
||||
const endDate = endDateStr ? new Date(endDateStr) : undefined;
|
||||
|
||||
// Determine actor filter based on permissions
|
||||
let actorId: string | undefined;
|
||||
|
||||
if (dataArg.identity.isSystemAdmin) {
|
||||
// System admins can see all
|
||||
actorId = dataArg.actorId;
|
||||
} else if (organizationId) {
|
||||
// Check if user can manage this org
|
||||
const canManage = await this.permissionService.canManageOrganization(
|
||||
dataArg.identity.userId,
|
||||
organizationId,
|
||||
);
|
||||
if (!canManage) {
|
||||
// User can only see their own actions in this org
|
||||
actorId = dataArg.identity.userId;
|
||||
}
|
||||
} else {
|
||||
// Non-admins without org filter can only see their own actions
|
||||
actorId = dataArg.identity.userId;
|
||||
}
|
||||
|
||||
const result = await AuditLog.query({
|
||||
actorId,
|
||||
organizationId,
|
||||
repositoryId,
|
||||
resourceType: resourceType as any,
|
||||
action: actions as any[],
|
||||
success,
|
||||
startDate,
|
||||
endDate,
|
||||
limit,
|
||||
offset,
|
||||
});
|
||||
|
||||
return {
|
||||
logs: result.logs.map((log) => ({
|
||||
id: log.id,
|
||||
actorId: log.actorId,
|
||||
actorType: log.actorType as interfaces.data.IAuditEntry['actorType'],
|
||||
action: log.action as interfaces.data.TAuditAction,
|
||||
resourceType: log.resourceType as interfaces.data.TAuditResourceType,
|
||||
resourceId: log.resourceId,
|
||||
resourceName: log.resourceName,
|
||||
organizationId: log.organizationId,
|
||||
repositoryId: log.repositoryId,
|
||||
success: log.success,
|
||||
errorCode: log.errorCode,
|
||||
timestamp: log.timestamp instanceof Date ? log.timestamp.toISOString() : String(log.timestamp),
|
||||
metadata: log.metadata || {},
|
||||
})),
|
||||
total: result.total,
|
||||
limit,
|
||||
offset,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof plugins.typedrequest.TypedResponseError) throw error;
|
||||
throw new plugins.typedrequest.TypedResponseError('Failed to query audit logs');
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user