Loading packages/server/prisma/dbml/schema.dbml +4 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,10 @@ Enum AuditLogAction { CANVAS_FREEZE CANVAS_UNFREEZE CANVAS_AREA_UNDO USER_MOD USER_UNMOD USER_ADMIN USER_UNADMIN } Ref: Pixel.userId > User.sub Loading packages/server/prisma/migrations/20240713155333_add_mod_and_admin_audit_log_actions/migration.sql 0 → 100644 +12 −0 Original line number Diff line number Diff line -- AlterEnum -- This migration adds more than one value to an enum. -- With PostgreSQL versions 11 and earlier, this is not possible -- in a single migration. This can be worked around by creating -- multiple migrations, each migration adding only one value to -- the enum. ALTER TYPE "AuditLogAction" ADD VALUE 'USER_MOD'; ALTER TYPE "AuditLogAction" ADD VALUE 'USER_UNMOD'; ALTER TYPE "AuditLogAction" ADD VALUE 'USER_ADMIN'; ALTER TYPE "AuditLogAction" ADD VALUE 'USER_UNADMIN'; packages/server/prisma/schema.prisma +6 −2 Original line number Diff line number Diff line Loading @@ -157,6 +157,10 @@ enum AuditLogAction { CANVAS_FREEZE CANVAS_UNFREEZE CANVAS_AREA_UNDO USER_MOD USER_UNMOD USER_ADMIN USER_UNADMIN } model AuditLog { Loading packages/server/src/api/admin.ts +152 −0 Original line number Diff line number Diff line Loading @@ -679,6 +679,158 @@ app.post("/user/:sub/notice", async (req, res) => { res.json({ success: true }); }); /** * Mark a user as a moderator * * @param :sub User ID */ app.put("/user/:sub/moderator", async (req, res) => { let user: User; try { user = await User.fromSub(req.params.sub); } catch (e) { if (e instanceof UserNotFound) { res.status(404).json({ success: false, error: "User not found" }); } else { res.status(500).json({ success: false, error: "Internal error" }); } return; } await prisma.user.update({ where: { sub: user.sub }, data: { isModerator: true, }, }); await user.update(true); const adminUser = (await User.fromAuthSession(req.session.user!))!; const auditLog = await AuditLog.Factory(adminUser.sub) .doing("USER_MOD") .reason(req.header("X-Audit") || null) .withComment(`Made ${user.sub} a moderator`) .create(); res.json({ success: true, auditLog }); }); /** * Unmark a user as a moderator * * @param :sub User ID */ app.delete("/user/:sub/moderator", async (req, res) => { let user: User; try { user = await User.fromSub(req.params.sub); } catch (e) { if (e instanceof UserNotFound) { res.status(404).json({ success: false, error: "User not found" }); } else { res.status(500).json({ success: false, error: "Internal error" }); } return; } await prisma.user.update({ where: { sub: user.sub }, data: { isModerator: false, }, }); await user.update(true); const adminUser = (await User.fromAuthSession(req.session.user!))!; const auditLog = await AuditLog.Factory(adminUser.sub) .doing("USER_UNMOD") .reason(req.header("X-Audit") || null) .withComment(`Removed ${user.sub} as moderator`) .create(); res.json({ success: true, auditLog }); }); /** * Mark a user as an admin * * @param :sub User ID */ app.put("/user/:sub/admin", async (req, res) => { let user: User; try { user = await User.fromSub(req.params.sub); } catch (e) { if (e instanceof UserNotFound) { res.status(404).json({ success: false, error: "User not found" }); } else { res.status(500).json({ success: false, error: "Internal error" }); } return; } await prisma.user.update({ where: { sub: user.sub }, data: { isAdmin: true, }, }); await user.update(true); const adminUser = (await User.fromAuthSession(req.session.user!))!; const auditLog = await AuditLog.Factory(adminUser.sub) .doing("USER_ADMIN") .reason(req.header("X-Audit") || null) .withComment(`Added ${user.sub} as admin`) .create(); res.json({ success: true, auditLog }); }); /** * Unmark a user as an admin * * @param :sub User ID */ app.delete("/user/:sub/admin", async (req, res) => { let user: User; try { user = await User.fromSub(req.params.sub); } catch (e) { if (e instanceof UserNotFound) { res.status(404).json({ success: false, error: "User not found" }); } else { res.status(500).json({ success: false, error: "Internal error" }); } return; } await prisma.user.update({ where: { sub: user.sub }, data: { isAdmin: false, }, }); await user.update(true); const adminUser = (await User.fromAuthSession(req.session.user!))!; const auditLog = await AuditLog.Factory(adminUser.sub) .doing("USER_UNADMIN") .reason(req.header("X-Audit") || null) .withComment(`Removed ${user.sub} as admin`) .create(); res.json({ success: true, auditLog }); }); app.get("/instance/:domain/ban", async (req, res) => { // get ban information Loading Loading
packages/server/prisma/dbml/schema.dbml +4 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,10 @@ Enum AuditLogAction { CANVAS_FREEZE CANVAS_UNFREEZE CANVAS_AREA_UNDO USER_MOD USER_UNMOD USER_ADMIN USER_UNADMIN } Ref: Pixel.userId > User.sub Loading
packages/server/prisma/migrations/20240713155333_add_mod_and_admin_audit_log_actions/migration.sql 0 → 100644 +12 −0 Original line number Diff line number Diff line -- AlterEnum -- This migration adds more than one value to an enum. -- With PostgreSQL versions 11 and earlier, this is not possible -- in a single migration. This can be worked around by creating -- multiple migrations, each migration adding only one value to -- the enum. ALTER TYPE "AuditLogAction" ADD VALUE 'USER_MOD'; ALTER TYPE "AuditLogAction" ADD VALUE 'USER_UNMOD'; ALTER TYPE "AuditLogAction" ADD VALUE 'USER_ADMIN'; ALTER TYPE "AuditLogAction" ADD VALUE 'USER_UNADMIN';
packages/server/prisma/schema.prisma +6 −2 Original line number Diff line number Diff line Loading @@ -157,6 +157,10 @@ enum AuditLogAction { CANVAS_FREEZE CANVAS_UNFREEZE CANVAS_AREA_UNDO USER_MOD USER_UNMOD USER_ADMIN USER_UNADMIN } model AuditLog { Loading
packages/server/src/api/admin.ts +152 −0 Original line number Diff line number Diff line Loading @@ -679,6 +679,158 @@ app.post("/user/:sub/notice", async (req, res) => { res.json({ success: true }); }); /** * Mark a user as a moderator * * @param :sub User ID */ app.put("/user/:sub/moderator", async (req, res) => { let user: User; try { user = await User.fromSub(req.params.sub); } catch (e) { if (e instanceof UserNotFound) { res.status(404).json({ success: false, error: "User not found" }); } else { res.status(500).json({ success: false, error: "Internal error" }); } return; } await prisma.user.update({ where: { sub: user.sub }, data: { isModerator: true, }, }); await user.update(true); const adminUser = (await User.fromAuthSession(req.session.user!))!; const auditLog = await AuditLog.Factory(adminUser.sub) .doing("USER_MOD") .reason(req.header("X-Audit") || null) .withComment(`Made ${user.sub} a moderator`) .create(); res.json({ success: true, auditLog }); }); /** * Unmark a user as a moderator * * @param :sub User ID */ app.delete("/user/:sub/moderator", async (req, res) => { let user: User; try { user = await User.fromSub(req.params.sub); } catch (e) { if (e instanceof UserNotFound) { res.status(404).json({ success: false, error: "User not found" }); } else { res.status(500).json({ success: false, error: "Internal error" }); } return; } await prisma.user.update({ where: { sub: user.sub }, data: { isModerator: false, }, }); await user.update(true); const adminUser = (await User.fromAuthSession(req.session.user!))!; const auditLog = await AuditLog.Factory(adminUser.sub) .doing("USER_UNMOD") .reason(req.header("X-Audit") || null) .withComment(`Removed ${user.sub} as moderator`) .create(); res.json({ success: true, auditLog }); }); /** * Mark a user as an admin * * @param :sub User ID */ app.put("/user/:sub/admin", async (req, res) => { let user: User; try { user = await User.fromSub(req.params.sub); } catch (e) { if (e instanceof UserNotFound) { res.status(404).json({ success: false, error: "User not found" }); } else { res.status(500).json({ success: false, error: "Internal error" }); } return; } await prisma.user.update({ where: { sub: user.sub }, data: { isAdmin: true, }, }); await user.update(true); const adminUser = (await User.fromAuthSession(req.session.user!))!; const auditLog = await AuditLog.Factory(adminUser.sub) .doing("USER_ADMIN") .reason(req.header("X-Audit") || null) .withComment(`Added ${user.sub} as admin`) .create(); res.json({ success: true, auditLog }); }); /** * Unmark a user as an admin * * @param :sub User ID */ app.delete("/user/:sub/admin", async (req, res) => { let user: User; try { user = await User.fromSub(req.params.sub); } catch (e) { if (e instanceof UserNotFound) { res.status(404).json({ success: false, error: "User not found" }); } else { res.status(500).json({ success: false, error: "Internal error" }); } return; } await prisma.user.update({ where: { sub: user.sub }, data: { isAdmin: false, }, }); await user.update(true); const adminUser = (await User.fromAuthSession(req.session.user!))!; const auditLog = await AuditLog.Factory(adminUser.sub) .doing("USER_UNADMIN") .reason(req.header("X-Audit") || null) .withComment(`Removed ${user.sub} as admin`) .create(); res.json({ success: true, auditLog }); }); app.get("/instance/:domain/ban", async (req, res) => { // get ban information Loading