diff --git a/backend/src/data/ApiAuditLog.ts b/backend/src/data/ApiAuditLog.ts new file mode 100644 index 00000000..199747ef --- /dev/null +++ b/backend/src/data/ApiAuditLog.ts @@ -0,0 +1,28 @@ +import { BaseRepository } from "./BaseRepository"; +import { getRepository, Repository } from "typeorm/index"; +import { ApiAuditLogEntry } from "./entities/ApiAuditLogEntry"; +import { ApiLogin } from "./entities/ApiLogin"; +import { AuditLogEventData, AuditLogEventType } from "./apiAuditLogTypes"; + +export class ApiAuditLog extends BaseRepository { + private auditLog: Repository>; + + constructor() { + super(); + this.auditLog = getRepository(ApiAuditLogEntry); + } + + addEntry( + guildId: string, + authorId: string, + eventType: TEventType, + eventData: AuditLogEventData[TEventType], + ) { + this.auditLog.insert({ + guild_id: guildId, + author_id: authorId, + event_type: eventType as any, + event_data: eventData as any, + }); + } +} diff --git a/backend/src/data/apiAuditLogTypes.ts b/backend/src/data/apiAuditLogTypes.ts new file mode 100644 index 00000000..c50cc06d --- /dev/null +++ b/backend/src/data/apiAuditLogTypes.ts @@ -0,0 +1,35 @@ +export const AuditLogEventTypes = { + ADD_API_PERMISSION: "ADD_API_PERMISSION", + REMOVE_API_PERMISSION: "REMOVE_API_PERMISSION", + EDIT_CONFIG: "EDIT_CONFIG", +}; + +export type AuditLogEventType = keyof typeof AuditLogEventTypes; + +export type AddApiPermissionEventData = { + target_id: string; + permissions: string[]; + expires_at: string | null; +}; + +export type RemoveApiPermissionEventData = { + target_id: string; +}; + +export type EditConfigEventData = {}; + +export interface AuditLogEventData extends Record { + ADD_API_PERMISSION: { + target_id: string; + permissions: string[]; + expires_at: string | null; + }; + + REMOVE_API_PERMISSION: { + target_id: string; + }; + + EDIT_CONFIG: {}; +} + +export type AnyAuditLogEventData = AuditLogEventData[AuditLogEventType]; diff --git a/backend/src/data/entities/ApiAuditLogEntry.ts b/backend/src/data/entities/ApiAuditLogEntry.ts new file mode 100644 index 00000000..9c613353 --- /dev/null +++ b/backend/src/data/entities/ApiAuditLogEntry.ts @@ -0,0 +1,25 @@ +import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from "typeorm"; +import { ApiUserInfo } from "./ApiUserInfo"; +import { AuditLogEventData, AuditLogEventType } from "../apiAuditLogTypes"; + +@Entity("api_audit_log") +export class ApiAuditLogEntry { + @Column() + @PrimaryColumn() + id: number; + + @Column() + guild_id: string; + + @Column() + author_id: string; + + @Column() + event_type: TEventType; + + @Column("simple-json") + event_data: AuditLogEventData[TEventType]; + + @Column() + created_at: string; +} diff --git a/backend/src/migrations/1630837718830-CreateApiAuditLogTable.ts b/backend/src/migrations/1630837718830-CreateApiAuditLogTable.ts new file mode 100644 index 00000000..a9f6faea --- /dev/null +++ b/backend/src/migrations/1630837718830-CreateApiAuditLogTable.ts @@ -0,0 +1,58 @@ +import { MigrationInterface, QueryRunner, Table, TableIndex } from "typeorm"; + +export class CreateApiAuditLogTable1630837718830 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.createTable( + new Table({ + name: "api_audit_log", + columns: [ + { + name: "id", + type: "int", + unsigned: true, + isPrimary: true, + isGenerated: true, + generationStrategy: "increment", + }, + { + name: "guild_id", + type: "bigint", + }, + { + name: "author_id", + type: "bigint", + }, + { + name: "event_type", + type: "varchar", + length: "255", + }, + { + name: "event_data", + type: "longtext", + }, + { + name: "created_at", + type: "datetime", + default: "(NOW())", + }, + ], + indices: [ + new TableIndex({ + columnNames: ["guild_id", "author_id"], + }), + new TableIndex({ + columnNames: ["guild_id", "event_type"], + }), + new TableIndex({ + columnNames: ["created_at"], + }), + ], + }), + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropTable("api_audit_log"); + } +}