Commit 013f5b8b authored by Grant's avatar Grant
Browse files

[admin] Add moderation/admin management endpoints

parent b755e878
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+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';
+6 −2
Original line number Diff line number Diff line
@@ -157,6 +157,10 @@ enum AuditLogAction {
  CANVAS_FREEZE
  CANVAS_UNFREEZE
  CANVAS_AREA_UNDO
  USER_MOD
  USER_UNMOD
  USER_ADMIN
  USER_UNADMIN
}

model AuditLog {
+152 −0
Original line number Diff line number Diff line
@@ -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