feat(2FA): create API routes for admins

This commit is contained in:
Rudy B. committed 2026-04-25 01:40:06 +02:00
1 parent 7c51e1ce4a
commit ab73667d7b
7 files changed
+129 -2

No files matched your search

+29
View File
@@ -0,0 +1,29 @@
import { z } from 'zod';
import prisma from '@/lib/prisma';
import { parseRequest } from '@/lib/request';
import { json, unauthorized } from '@/lib/response';
import { canEnforceTwoFactorAuthForEveryone } from '@/permissions';
export async function POST(request: Request) {
const schema = z.object({ required: z.boolean() });
const { auth, body, error } = await parseRequest(request, schema);
if (error) {
return error();
}
if (!(await canEnforceTwoFactorAuthForEveryone(auth))) {
return unauthorized();
}
const { required } = body;
await prisma.client.appSetting.upsert({
where: { key: 'twoFactorRequiredGlobal' },
update: { value: String(required) },
create: { key: 'twoFactorRequiredGlobal', value: String(required) },
});
return json({ ok: true, required });
}
@@ -0,0 +1,29 @@
import { z } from 'zod';
import prisma from '@/lib/prisma';
import { parseRequest } from '@/lib/request';
import { json, unauthorized } from '@/lib/response';
import { canEnforceTwoFactorAuthForTeam } from '@/permissions';
export async function POST(request: Request, { params }: { params: Promise<{ teamId: string }> }) {
const schema = z.object({ required: z.boolean() });
const { auth, body, error } = await parseRequest(request, schema);
if (error) {
return error();
}
const { teamId } = await params;
if (!(await canEnforceTwoFactorAuthForTeam(auth, teamId))) {
return unauthorized();
}
const { required } = body;
await prisma.client.team.update({
where: { id: teamId },
data: { twoFactorRequired: required },
});
return json({ ok: true, teamId, twoFactorRequired: required });
}
@@ -0,0 +1,45 @@
import { z } from 'zod';
import prisma from '@/lib/prisma';
import { parseRequest } from '@/lib/request';
import { json, unauthorized } from '@/lib/response';
import { updateUser } from '@/queries/prisma/user';
import { canEnforceTwoFactorAuthForUser } from '@/permissions';
export async function GET(request: Request, { params }: { params: Promise<{ userId: string }> }) {
const { auth, error } = await parseRequest(request);
if (error) {
return error();
}
if (!(await canEnforceTwoFactorAuthForUser(auth))) {
return unauthorized();
}
const { userId } = await params;
const twoFactor = await prisma.client.twoFactorAuth.findUnique({ where: { userId } });
return json({ isEnabled: twoFactor?.isEnabled ?? false });
}
export async function POST(request: Request, { params }: { params: Promise<{ userId: string }> }) {
const schema = z.object({ required: z.boolean() });
const { auth, body, error } = await parseRequest(request, schema);
if (error) {
return error();
}
if (!(await canEnforceTwoFactorAuthForUser(auth))) {
return unauthorized();
}
const { userId } = await params;
const { required } = body;
const user = await updateUser(userId, { twoFactorRequired: required });
return json({ ok: true, userId: user.id, twoFactorRequired: required });
}
+5 -1
View File
@@ -8,7 +8,11 @@ export async function canViewLink({ user, shareToken }: Auth, linkId: string) {
return true;
}
if (shareToken?.linkId === linkId || shareToken?.websiteId === linkId || shareToken?.linkIds?.includes(linkId)) {
if (
shareToken?.linkId === linkId ||
shareToken?.websiteId === linkId ||
shareToken?.linkIds?.includes(linkId)
) {
return true;
}
+5 -1
View File
@@ -8,7 +8,11 @@ export async function canViewPixel({ user, shareToken }: Auth, pixelId: string)
return true;
}
if (shareToken?.pixelId === pixelId || shareToken?.websiteId === pixelId || shareToken?.pixelIds?.includes(pixelId)) {
if (
shareToken?.pixelId === pixelId ||
shareToken?.websiteId === pixelId ||
shareToken?.pixelIds?.includes(pixelId)
) {
return true;
}
+8
View File
@@ -90,3 +90,11 @@ export async function canCreateTeamWebsite({ user }: Auth, teamId: string) {
export async function canViewAllTeams({ user }: Auth) {
return user?.isAdmin ?? false;
}
export async function canEnforceTwoFactorAuthForTeam({ user }: Auth, teamId: string) {
if (!user) {
return false;
}
return user.isAdmin;
}
+8
View File
@@ -35,3 +35,11 @@ export async function canUpdateUser({ user }: Auth, viewedUserId: string) {
export async function canDeleteUser({ user }: Auth) {
return user?.isAdmin ?? false;
}
export async function canEnforceTwoFactorAuthForEveryone({ user }: Auth) {
return user?.isAdmin ?? false;
}
export async function canEnforceTwoFactorAuthForUser({ user }: Auth) {
return user?.isAdmin ?? false;
}