feat(admin): archive users and their profiles permanently
All checks were successful
Build and Release FEDEO / verify (push) Successful in 1m5s
Build and Release FEDEO / build-and-release (push) Successful in 6m53s

This commit is contained in:
2026-10-15 14:22:12 +02:00
parent 5dc9e686fc
commit 4ffafef3f1
26 changed files with 519 additions and 75 deletions

View File

@@ -70,7 +70,7 @@ export async function rotateRefreshToken(
const [user] = await server.db
.select({ id: authUsers.id, email: authUsers.email })
.from(authUsers)
.where(eq(authUsers.id, session.userId))
.where(and(eq(authUsers.id, session.userId), isNull(authUsers.archived_at)))
.limit(1)
if (!user) return null

View File

@@ -1,5 +1,5 @@
import crypto from "crypto"
import { and, asc, eq, sql } from "drizzle-orm"
import { and, asc, eq, isNull, sql } from "drizzle-orm"
import { FastifyInstance } from "fastify"
import { authProfiles, events } from "../../db/schema"
@@ -105,7 +105,8 @@ export async function generateProfileCalendarSubscriptionToken(server: FastifyIn
.where(
and(
eq(authProfiles.id, profileId),
eq(authProfiles.tenant_id, tenantId)
eq(authProfiles.tenant_id, tenantId),
isNull(authProfiles.archived_at)
)
)
.returning()

View File

@@ -1,5 +1,5 @@
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
import { eq } from "drizzle-orm";
import { and, eq, isNull } from "drizzle-orm";
import { authUsers } from "../../db/schema/auth_users";
export async function requireSystemAdmin(server: FastifyInstance, req: FastifyRequest, reply: FastifyReply) {
@@ -9,7 +9,7 @@ export async function requireSystemAdmin(server: FastifyInstance, req: FastifyRe
}
// Read the current global role; tenant roles and stale JWT claims do not grant access.
const [user] = await server.db.select({ id: authUsers.id, email: authUsers.email, is_admin: authUsers.is_admin })
.from(authUsers).where(eq(authUsers.id, req.user.user_id)).limit(1);
.from(authUsers).where(and(eq(authUsers.id, req.user.user_id), isNull(authUsers.archived_at))).limit(1);
if (!user?.is_admin) {
reply.code(403).send({ error: "Admin access required" });
return null;