52 lines
2.4 KiB
TypeScript
52 lines
2.4 KiB
TypeScript
import type { FastifyInstance } from "fastify"
|
|
import { eq } from "drizzle-orm"
|
|
import { authProfiles, authRefreshTokens, authUsers, m2mApiKeys } from "../../db/schema"
|
|
import { requireSystemAdmin } from "../utils/requireSystemAdmin"
|
|
|
|
export default async function adminUserArchiveRoutes(server: FastifyInstance) {
|
|
server.post("/admin/users/:user_id/archive", {
|
|
schema: {
|
|
params: {
|
|
type: "object",
|
|
required: ["user_id"],
|
|
properties: { user_id: { type: "string", format: "uuid" } },
|
|
},
|
|
},
|
|
}, async (req, reply) => {
|
|
const currentUser = await requireSystemAdmin(server, req, reply)
|
|
if (!currentUser) return
|
|
|
|
const { user_id } = req.params as { user_id: string }
|
|
if (user_id === currentUser.id) {
|
|
return reply.code(409).send({ error: "Das eigene Benutzerkonto kann nicht archiviert werden." })
|
|
}
|
|
|
|
const user = await server.db.transaction(async (tx) => {
|
|
// Serialize repeated archive requests and keep the original archive date.
|
|
const [target] = await tx.select({ id: authUsers.id, archived_at: authUsers.archived_at })
|
|
.from(authUsers).where(eq(authUsers.id, user_id)).limit(1).for("update")
|
|
if (!target) return null
|
|
|
|
const archivedAt = target.archived_at || new Date()
|
|
const [archivedUser] = await tx.update(authUsers)
|
|
.set({ archived_at: archivedAt, updatedAt: archivedAt })
|
|
.where(eq(authUsers.id, user_id))
|
|
.returning({ id: authUsers.id, archived_at: authUsers.archived_at })
|
|
|
|
// Keep links intact so existing documents and time records retain their authors.
|
|
await tx.update(authProfiles)
|
|
.set({ active: false, archived_at: archivedAt, token_id: null, calendar_subscription_token: null })
|
|
.where(eq(authProfiles.user_id, user_id))
|
|
await tx.update(authRefreshTokens).set({ revokedAt: archivedAt })
|
|
.where(eq(authRefreshTokens.userId, user_id))
|
|
await tx.update(m2mApiKeys).set({ active: false, updatedAt: archivedAt })
|
|
.where(eq(m2mApiKeys.userId, user_id))
|
|
|
|
return archivedUser
|
|
})
|
|
|
|
if (!user) return reply.code(404).send({ error: "Benutzer nicht gefunden." })
|
|
return { user }
|
|
})
|
|
}
|