feat: 🗃️ Add event table to schema, add EventLogger class to server
This commit is contained in:
parent
68b65ab0e0
commit
e7f17dbe4d
@ -0,0 +1,12 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "event" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"time" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"type" TEXT NOT NULL,
|
||||||
|
"success" BOOLEAN NOT NULL,
|
||||||
|
"size_bytes" INTEGER,
|
||||||
|
"purge_count" INTEGER,
|
||||||
|
"host" TEXT,
|
||||||
|
"error" TEXT,
|
||||||
|
"expire_window_days" INTEGER
|
||||||
|
);
|
@ -17,3 +17,15 @@ model EncryptedNote {
|
|||||||
ciphertext String
|
ciphertext String
|
||||||
hmac String
|
hmac String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model event {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
time DateTime @default(now())
|
||||||
|
type String
|
||||||
|
success Boolean
|
||||||
|
size_bytes Int?
|
||||||
|
purge_count Int?
|
||||||
|
host String?
|
||||||
|
error String?
|
||||||
|
expire_window_days Int?
|
||||||
|
}
|
||||||
|
79
server/src/EventLogger.integration.test.ts
Normal file
79
server/src/EventLogger.integration.test.ts
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import { describe, it, expect } from "vitest";
|
||||||
|
import EventLogger, { EventType } from "./EventLogger";
|
||||||
|
import prisma from "./client";
|
||||||
|
|
||||||
|
describe("Logging write events", () => {
|
||||||
|
it("Should write a write event to database", async () => {
|
||||||
|
const testWriteEvent = {
|
||||||
|
host: "localhost",
|
||||||
|
size_bytes: 100,
|
||||||
|
success: true,
|
||||||
|
expire_window_days: 30,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is event written successfully?
|
||||||
|
const logged = await EventLogger.writeEvent(testWriteEvent);
|
||||||
|
expect(logged).not.toBeNull();
|
||||||
|
expect(logged).toMatchObject(testWriteEvent);
|
||||||
|
|
||||||
|
// Is event in database?
|
||||||
|
const results = await prisma.event.findMany({
|
||||||
|
where: { type: EventType.WRITE },
|
||||||
|
});
|
||||||
|
expect(results.length).toBe(1);
|
||||||
|
|
||||||
|
// Are default fields populated?
|
||||||
|
expect(logged.time).not.toBeNull();
|
||||||
|
expect(logged.id).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should log a read event to database", async () => {
|
||||||
|
const testReadEvent = {
|
||||||
|
host: "localhost",
|
||||||
|
size_bytes: 100,
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is event written successfully?
|
||||||
|
const logged = await EventLogger.readEvent({
|
||||||
|
host: "localhost",
|
||||||
|
size_bytes: 100,
|
||||||
|
success: true,
|
||||||
|
});
|
||||||
|
expect(logged).not.toBeNull();
|
||||||
|
expect(logged).toMatchObject(testReadEvent);
|
||||||
|
|
||||||
|
// Is event in database?
|
||||||
|
const results = await prisma.event.findMany({
|
||||||
|
where: { type: EventType.READ },
|
||||||
|
});
|
||||||
|
expect(results.length).toBe(1);
|
||||||
|
|
||||||
|
// Are default fields populated?
|
||||||
|
expect(logged.time).not.toBeNull();
|
||||||
|
expect(logged.id).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should log a purge event to database", async () => {
|
||||||
|
const testPurgeEvent = {
|
||||||
|
success: true,
|
||||||
|
purge_count: 1,
|
||||||
|
size_bytes: 100,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Is event written successfully?
|
||||||
|
const logged = await EventLogger.purgeEvent(testPurgeEvent);
|
||||||
|
expect(logged).not.toBeNull();
|
||||||
|
expect(logged).toMatchObject(testPurgeEvent);
|
||||||
|
|
||||||
|
// Is event in database?
|
||||||
|
const results = await prisma.event.findMany({
|
||||||
|
where: { type: EventType.PURGE },
|
||||||
|
});
|
||||||
|
expect(results.length).toBe(1);
|
||||||
|
|
||||||
|
// Are default fields populated?
|
||||||
|
expect(logged.time).not.toBeNull();
|
||||||
|
expect(logged.id).not.toBeNull();
|
||||||
|
});
|
||||||
|
});
|
51
server/src/EventLogger.ts
Normal file
51
server/src/EventLogger.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import prisma from "./client";
|
||||||
|
import { event } from "@prisma/client";
|
||||||
|
|
||||||
|
export enum EventType {
|
||||||
|
WRITE = "WRITE",
|
||||||
|
READ = "READ",
|
||||||
|
PURGE = "PURGE",
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Event {
|
||||||
|
success: boolean;
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ClientEvent extends Event {
|
||||||
|
host: string;
|
||||||
|
size_bytes: number;
|
||||||
|
success: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WriteEvent extends ClientEvent {
|
||||||
|
expire_window_days: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReadEvent extends ClientEvent {}
|
||||||
|
|
||||||
|
interface PurgeEvent extends Event {
|
||||||
|
success: boolean;
|
||||||
|
purge_count: number;
|
||||||
|
size_bytes: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class EventLogger {
|
||||||
|
public static writeEvent(event: WriteEvent): Promise<event> {
|
||||||
|
return prisma.event.create({
|
||||||
|
data: { type: EventType.WRITE, ...event },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readEvent(event: ReadEvent): Promise<event> {
|
||||||
|
return prisma.event.create({
|
||||||
|
data: { type: EventType.READ, ...event },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static purgeEvent(event: PurgeEvent): Promise<event> {
|
||||||
|
return prisma.event.create({
|
||||||
|
data: { type: EventType.PURGE, ...event },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user