Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
8.5 kB ยท 285 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286import { db, eq } from "@openstatus/db";import { maintenance, maintenanceUpdate, maintenancesToPageComponents, page, pageComponent,} from "@openstatus/db/src/schema";import { clearAuditLogFor } from "@openstatus/services/test/helpers";import { expect } from "@std/expect";import { afterAll, beforeAll, test } from "@std/testing/bdd";import { TRPCError } from "@trpc/server";
import { edgeRouter } from "../edge";import { createInnerTRPCContext } from "../trpc";
let otherWorkspaceMaintenanceId: number;let otherWorkspacePageId: number;let otherWorkspaceComponentId: number;
// Track maintenance ids the tRPC service writes / mutates. Without this// the `maintenance.create` / `maintenance.update` audit rows outlive// the row itself and โ because INTEGER PRIMARY KEY recycles โ a later// test inserting into `maintenance` can land on the orphan's id and// inherit its actor attribution. See packages/services/AGENTS.md.const createdMaintenanceIds: number[] = [];const updatedMaintenanceIds: number[] = [];const createdMaintenanceUpdateIds: number[] = [];
beforeAll(async () => { const p = await db .insert(page) .values({ workspaceId: 3, title: "Maintenance IDOR Test Page", description: "Page for maintenance IDOR testing", slug: "maintenance-idor-test-page", customDomain: "", }) .returning() .get(); otherWorkspacePageId = p.id;
const component = await db .insert(pageComponent) .values({ workspaceId: 3, pageId: otherWorkspacePageId, name: "Other workspace component", type: "static", }) .returning() .get(); otherWorkspaceComponentId = component.id;
// Maintenance for workspace 2, referencing page 1 (page ownership is not // enforced at DB level, only at API level, so this insert works for testing) const m = await db .insert(maintenance) .values({ workspaceId: 3, title: "Other workspace maintenance", message: "Scheduled maintenance", pageId: 1, from: new Date(), to: new Date(Date.now() + 3_600_000), }) .returning() .get(); otherWorkspaceMaintenanceId = m.id;
await db .insert(maintenancesToPageComponents) .values({ maintenanceId: otherWorkspaceMaintenanceId, pageComponentId: otherWorkspaceComponentId, }) .run();});
afterAll(async () => { await db .delete(maintenancesToPageComponents) .where( eq( maintenancesToPageComponents.maintenanceId, otherWorkspaceMaintenanceId, ), ); await db .delete(maintenance) .where(eq(maintenance.id, otherWorkspaceMaintenanceId)); await db .delete(pageComponent) .where(eq(pageComponent.id, otherWorkspaceComponentId)); await db.delete(page).where(eq(page.id, otherWorkspacePageId));
if (createdMaintenanceIds.length > 0) { await clearAuditLogFor({ entityType: "maintenance", entityIds: createdMaintenanceIds, }); } if (updatedMaintenanceIds.length > 0) { await clearAuditLogFor({ entityType: "maintenance", entityIds: updatedMaintenanceIds, }); } if (createdMaintenanceUpdateIds.length > 0) { await clearAuditLogFor({ entityType: "maintenance_update", entityIds: createdMaintenanceUpdateIds, }); }});
test("maintenance.update rejects maintenance from another workspace", async () => { const ctx = createInnerTRPCContext({ req: undefined, session: { user: { id: "1" } }, // @ts-expect-error - minimal workspace for test workspace: { id: 1 }, }); const caller = edgeRouter.createCaller(ctx);
try { await caller.maintenance.update({ id: otherWorkspaceMaintenanceId, title: "Unauthorized Modification", startDate: new Date(), endDate: new Date(Date.now() + 3_600_000), pageComponents: [], }); throw new Error("Should have thrown"); } catch (e) { expect(e).toBeInstanceOf(TRPCError); expect((e as TRPCError).code).toBe("NOT_FOUND"); }
// Verify page component associations were NOT deleted const associations = await db.query.maintenancesToPageComponents.findMany({ where: eq( maintenancesToPageComponents.maintenanceId, otherWorkspaceMaintenanceId, ), }); expect(associations.length).toBe(1);});
test("maintenance.update succeeds for own workspace maintenance", async () => { const ctx = createInnerTRPCContext({ req: undefined, session: { user: { id: "1" } }, // @ts-expect-error - minimal workspace for test workspace: { id: 1 }, }); const caller = edgeRouter.createCaller(ctx);
// Seed maintenance 1 belongs to workspace 1 await caller.maintenance.update({ id: 1, title: "Updated Maintenance Title", startDate: new Date(), endDate: new Date(Date.now() + 7_200_000), pageComponents: [1], }); updatedMaintenanceIds.push(1);
const updated = await db.query.maintenance.findFirst({ where: eq(maintenance.id, 1), }); expect(updated?.title).toBe("Updated Maintenance Title");});
test("maintenance.new rejects pageId from another workspace", async () => { const ctx = createInnerTRPCContext({ req: undefined, session: { user: { id: "1" } }, // @ts-expect-error - minimal workspace for test workspace: { id: 1 }, }); const caller = edgeRouter.createCaller(ctx);
try { await caller.maintenance.new({ title: "Cross-workspace maintenance", message: "Should be rejected", pageId: otherWorkspacePageId, // page from workspace 2 startDate: new Date(), endDate: new Date(Date.now() + 3_600_000), pageComponents: [], }); throw new Error("Should have thrown"); } catch (e) { expect(e).toBeInstanceOf(TRPCError); expect((e as TRPCError).code).toBe("NOT_FOUND"); }});
test("maintenance.new succeeds for own workspace page", async () => { const ctx = createInnerTRPCContext({ req: undefined, session: { user: { id: "1" } }, // @ts-expect-error - minimal workspace for test workspace: { id: 1 }, }); const caller = edgeRouter.createCaller(ctx);
const result = await caller.maintenance.new({ title: "Valid Maintenance", message: "Own workspace maintenance", pageId: 1, // page 1 belongs to workspace 1 startDate: new Date(), endDate: new Date(Date.now() + 3_600_000), pageComponents: [1], });
expect(result).toBeDefined(); createdMaintenanceIds.push(result.id);
// Cleanup await db .delete(maintenancesToPageComponents) .where(eq(maintenancesToPageComponents.maintenanceId, result.id)); await db.delete(maintenance).where(eq(maintenance.id, result.id));});
test("maintenance update procedures provide full CRUD", async () => { const ctx = createInnerTRPCContext({ req: undefined, session: { user: { id: "1" } }, // @ts-expect-error - minimal workspace for test workspace: { id: 1 }, }); const caller = edgeRouter.createCaller(ctx); const created = await caller.maintenance.new({ title: "Maintenance update CRUD", message: "Initial update", pageId: 1, startDate: new Date(), endDate: new Date(Date.now() + 3_600_000), pageComponents: [1], }); createdMaintenanceIds.push(created.id);
const added = await caller.maintenance.createUpdate({ maintenanceId: created.id, message: "Second update", date: new Date(), notifySubscribers: true, }); createdMaintenanceUpdateIds.push(added.id); expect(added.notifySubscribers).toBe(true);
const edited = await caller.maintenance.updateUpdate({ id: added.id, message: "Edited update", }); expect(edited.message).toBe("Edited update");
const found = await caller.maintenance.get({ id: created.id }); expect(found.updates.map((u) => u.message)).toEqual([ "Edited update", "Initial update", ]); // `message` is the newest update expect(found.message).toBe("Edited update");
await caller.maintenance.deleteUpdate({ id: added.id }); const deleted = await db.query.maintenanceUpdate.findFirst({ where: eq(maintenanceUpdate.id, added.id), }); expect(deleted).toBeUndefined();
try { await caller.maintenance.deleteUpdate({ id: added.id }); throw new Error("Should have thrown"); } catch (error) { expect(error).toBeInstanceOf(TRPCError); expect((error as TRPCError).code).toBe("NOT_FOUND"); }
await caller.maintenance.delete({ id: created.id });});