Projektstart
This commit is contained in:
166
backend/src/admin/routes.ts
Normal file
166
backend/src/admin/routes.ts
Normal file
@@ -0,0 +1,166 @@
|
||||
import { FastifyInstance } from "fastify";
|
||||
import { z } from "zod";
|
||||
import { prisma } from "../db.js";
|
||||
|
||||
const roleSchema = z.object({
|
||||
role: z.enum(["USER", "ADMIN"])
|
||||
});
|
||||
|
||||
const activeSchema = z.object({
|
||||
isActive: z.boolean()
|
||||
});
|
||||
|
||||
const resetSchema = z.object({
|
||||
password: z.string().min(10)
|
||||
});
|
||||
|
||||
export async function adminRoutes(app: FastifyInstance) {
|
||||
app.addHook("preHandler", app.requireAdmin);
|
||||
|
||||
app.get("/tenants", async () => {
|
||||
const tenants = await prisma.tenant.findMany({
|
||||
include: { _count: { select: { users: true, mailboxAccounts: true, jobs: true } } },
|
||||
orderBy: { createdAt: "desc" }
|
||||
});
|
||||
return { tenants };
|
||||
});
|
||||
|
||||
app.put("/tenants/:id", async (request, reply) => {
|
||||
const params = request.params as { id: string };
|
||||
const input = activeSchema.parse(request.body);
|
||||
const tenant = await prisma.tenant.findUnique({ where: { id: params.id } });
|
||||
if (!tenant) return reply.code(404).send({ message: "Tenant not found" });
|
||||
|
||||
const updated = await prisma.tenant.update({
|
||||
where: { id: params.id },
|
||||
data: { isActive: input.isActive }
|
||||
});
|
||||
|
||||
return { tenant: updated };
|
||||
});
|
||||
|
||||
app.get("/users", async () => {
|
||||
const users = await prisma.user.findMany({
|
||||
include: { tenant: true },
|
||||
orderBy: { createdAt: "desc" }
|
||||
});
|
||||
const sanitized = users.map((user) => ({
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
role: user.role,
|
||||
isActive: user.isActive,
|
||||
tenant: user.tenant ? { id: user.tenant.id, name: user.tenant.name } : null
|
||||
}));
|
||||
return { users: sanitized };
|
||||
});
|
||||
|
||||
app.put("/users/:id/role", async (request, reply) => {
|
||||
const params = request.params as { id: string };
|
||||
const input = roleSchema.parse(request.body);
|
||||
|
||||
const user = await prisma.user.findUnique({ where: { id: params.id } });
|
||||
if (!user) return reply.code(404).send({ message: "User not found" });
|
||||
|
||||
const updated = await prisma.user.update({
|
||||
where: { id: params.id },
|
||||
data: { role: input.role }
|
||||
});
|
||||
|
||||
return { user: updated };
|
||||
});
|
||||
|
||||
app.put("/users/:id", async (request, reply) => {
|
||||
const params = request.params as { id: string };
|
||||
const input = activeSchema.parse(request.body);
|
||||
|
||||
const user = await prisma.user.findUnique({ where: { id: params.id } });
|
||||
if (!user) return reply.code(404).send({ message: "User not found" });
|
||||
|
||||
const updated = await prisma.user.update({
|
||||
where: { id: params.id },
|
||||
data: { isActive: input.isActive }
|
||||
});
|
||||
|
||||
return { user: updated };
|
||||
});
|
||||
|
||||
app.post("/users/:id/reset", async (request, reply) => {
|
||||
const params = request.params as { id: string };
|
||||
const input = resetSchema.parse(request.body);
|
||||
|
||||
const user = await prisma.user.findUnique({ where: { id: params.id } });
|
||||
if (!user) return reply.code(404).send({ message: "User not found" });
|
||||
|
||||
const argon2 = (await import("argon2")).default;
|
||||
const hashed = await argon2.hash(input.password);
|
||||
|
||||
const updated = await prisma.user.update({
|
||||
where: { id: params.id },
|
||||
data: { password: hashed }
|
||||
});
|
||||
|
||||
return { user: updated };
|
||||
});
|
||||
|
||||
app.get("/accounts", async () => {
|
||||
const accounts = await prisma.mailboxAccount.findMany({
|
||||
include: { tenant: true },
|
||||
orderBy: { createdAt: "desc" }
|
||||
});
|
||||
|
||||
const sanitized = accounts.map((account) => ({
|
||||
id: account.id,
|
||||
email: account.email,
|
||||
provider: account.provider,
|
||||
isActive: account.isActive,
|
||||
tenant: account.tenant ? { id: account.tenant.id, name: account.tenant.name } : null,
|
||||
imapHost: account.imapHost,
|
||||
imapPort: account.imapPort,
|
||||
imapTLS: account.imapTLS
|
||||
}));
|
||||
|
||||
return { accounts: sanitized };
|
||||
});
|
||||
|
||||
app.put("/accounts/:id", async (request, reply) => {
|
||||
const params = request.params as { id: string };
|
||||
const input = activeSchema.parse(request.body);
|
||||
|
||||
const account = await prisma.mailboxAccount.findUnique({ where: { id: params.id } });
|
||||
if (!account) return reply.code(404).send({ message: "Account not found" });
|
||||
|
||||
const updated = await prisma.mailboxAccount.update({
|
||||
where: { id: params.id },
|
||||
data: { isActive: input.isActive }
|
||||
});
|
||||
|
||||
return { account: updated };
|
||||
});
|
||||
|
||||
app.get("/jobs", async () => {
|
||||
const jobs = await prisma.cleanupJob.findMany({
|
||||
include: { tenant: true, mailboxAccount: true },
|
||||
orderBy: { createdAt: "desc" }
|
||||
});
|
||||
const sanitized = jobs.map((job) => ({
|
||||
id: job.id,
|
||||
status: job.status,
|
||||
createdAt: job.createdAt,
|
||||
tenant: job.tenant ? { id: job.tenant.id, name: job.tenant.name } : null,
|
||||
mailboxAccount: job.mailboxAccount ? { id: job.mailboxAccount.id, email: job.mailboxAccount.email } : null
|
||||
}));
|
||||
return { jobs: sanitized };
|
||||
});
|
||||
|
||||
app.get("/jobs/:id/events", async (request, reply) => {
|
||||
const params = request.params as { id: string };
|
||||
const job = await prisma.cleanupJob.findUnique({ where: { id: params.id } });
|
||||
if (!job) return reply.code(404).send({ message: "Job not found" });
|
||||
|
||||
const events = await prisma.cleanupJobEvent.findMany({
|
||||
where: { jobId: job.id },
|
||||
orderBy: { createdAt: "asc" }
|
||||
});
|
||||
return { events };
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user