Compare commits
23 Commits
nico/28-no
...
staging
| Author | SHA1 | Date | |
|---|---|---|---|
| 26ae1dfb1b | |||
| 234a02e849 | |||
| 56df11419d | |||
| 8fed1dfda4 | |||
| 091c33a73c | |||
| ff9c3668fc | |||
| e2e8b47868 | |||
| a389e5ee32 | |||
| d7c694d237 | |||
| 4d3b2dd3f3 | |||
| 662dfc939e | |||
| fee1a6dfb2 | |||
| afe8c70cef | |||
| fb010bd05a | |||
| cfe60ed8fe | |||
| dc56a329dc | |||
| a9195d30bd | |||
| 569b0d408b | |||
| 40985f961a | |||
| 22424ef53e | |||
| 14b49334ac | |||
| 4a6829c502 | |||
| 60b035749d |
@@ -31,7 +31,7 @@ export default function Validasi() {
|
||||
useEffect(() => {
|
||||
const checkFlow = async () => {
|
||||
try {
|
||||
const res = await fetch('/api/auth/get-flow', {
|
||||
const res = await fetch('/api/get-flow', {
|
||||
credentials: 'include'
|
||||
});
|
||||
const data = await res.json();
|
||||
@@ -60,7 +60,7 @@ export default function Validasi() {
|
||||
setKodeId(storedKodeId);
|
||||
const loadOtpData = async () => {
|
||||
try {
|
||||
const res = await fetch(`/api/auth/otp-data?kodeId=${encodeURIComponent(storedKodeId)}`);
|
||||
const res = await fetch(`/api/otp-data?kodeId=${encodeURIComponent(storedKodeId)}`);
|
||||
const result = await res.json();
|
||||
|
||||
if (res.ok && result.data?.nomor) {
|
||||
@@ -124,7 +124,6 @@ export default function Validasi() {
|
||||
return;
|
||||
}
|
||||
|
||||
// ✅ Finalize registration
|
||||
const finalizeRes = await fetch('/api/auth/finalize-registration', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
@@ -149,7 +148,7 @@ export default function Validasi() {
|
||||
};
|
||||
|
||||
const handleLoginVerification = async () => {
|
||||
const loginRes = await fetch('/api/auth/verify-otp-login', {
|
||||
const loginRes = await fetch('/api/verify-otp-login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ nomor, otp, kodeId }),
|
||||
@@ -207,7 +206,7 @@ export default function Validasi() {
|
||||
|
||||
// Clear cookie
|
||||
try {
|
||||
await fetch('/api/auth/clear-flow', {
|
||||
await fetch('/api/clear-flow', {
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
});
|
||||
@@ -219,7 +218,7 @@ export default function Validasi() {
|
||||
const handleResend = async () => {
|
||||
if (!nomor) return;
|
||||
try {
|
||||
const res = await fetch('/api/auth/resend', {
|
||||
const res = await fetch('/api/resend', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ nomor }),
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// src/app/admin/_com/getMenuIdsByRoleId.ts
|
||||
import { navBar, role1, role2, role3 } from '@/app/admin/_com/list_PageAdmin';
|
||||
|
||||
/**
|
||||
* Mengembalikan daftar ID menu (string[]) berdasarkan roleId
|
||||
*/
|
||||
export function getMenuIdsByRoleId(roleId: string | number): string[] {
|
||||
const id = typeof roleId === 'string' ? parseInt(roleId, 10) : roleId;
|
||||
|
||||
switch (id) {
|
||||
case 0:
|
||||
// Asumsikan devBar ada dan punya struktur sama
|
||||
return []; // atau sesuaikan jika ada devBar
|
||||
case 1:
|
||||
return navBar.map(section => section.id);
|
||||
case 2:
|
||||
return role1.map(section => section.id);
|
||||
case 3:
|
||||
return role2.map(section => section.id);
|
||||
case 4:
|
||||
return role3.map(section => section.id);
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,6 @@ function ListUser({ search }: { search: string }) {
|
||||
const success = await stateUser.update.submit({
|
||||
id: userId,
|
||||
roleId: newRoleId,
|
||||
|
||||
});
|
||||
|
||||
if (success) {
|
||||
@@ -137,10 +136,9 @@ function ListUser({ search }: { search: string }) {
|
||||
}
|
||||
};
|
||||
|
||||
const filteredData = (data || []).filter((item) => {
|
||||
return item.roleId !== "0" && item.roleId !== "1";
|
||||
});
|
||||
|
||||
const filteredData = (data || []).filter(
|
||||
(item) => item.roleId !== "0" // asumsikan id role SUPERADMIN = "0"
|
||||
);
|
||||
|
||||
if (loading || !data) {
|
||||
return (
|
||||
@@ -185,7 +183,7 @@ function ListUser({ search }: { search: string }) {
|
||||
<Select
|
||||
placeholder="Pilih role"
|
||||
data={stateRole.findMany.data
|
||||
.filter(r => r.id !== "0" && r.id !== "1") // ❌ Sembunyikan SUPERADMIN dan DEVELOPER
|
||||
.filter(r => r.id !== "0") // ❌ Sembunyikan SUPERADMIN
|
||||
.map(r => ({
|
||||
label: r.name,
|
||||
value: r.id,
|
||||
|
||||
@@ -435,7 +435,6 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
const [desktopOpened, { toggle: toggleDesktop }] = useDisclosure(true);
|
||||
const router = useRouter();
|
||||
const segments = useSelectedLayoutSegments().map((s) => _.lowerCase(s));
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const fetchUser = async () => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { getMenuIdsByRoleId } from "@/app/admin/(dashboard)/user&role/_com/getMenuIdByRole";
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Context } from "elysia";
|
||||
|
||||
@@ -24,7 +23,7 @@ export default async function userUpdate(context: Context) {
|
||||
|
||||
const currentUser = await prisma.user.findUnique({
|
||||
where: { id },
|
||||
select: { roleId: true, isActive: true },
|
||||
select: { roleId: true, isActive: true }
|
||||
});
|
||||
|
||||
if (!currentUser) {
|
||||
@@ -32,29 +31,7 @@ export default async function userUpdate(context: Context) {
|
||||
}
|
||||
|
||||
const isRoleChanged = roleId && currentUser.roleId !== roleId;
|
||||
const isActiveChanged =
|
||||
isActive !== undefined && currentUser.isActive !== isActive;
|
||||
|
||||
// ✅ Jika role berubah, reset dan set ulang akses menu
|
||||
if (isRoleChanged && roleId) {
|
||||
// Hapus akses lama
|
||||
await prisma.userMenuAccess.deleteMany({
|
||||
where: { userId: id }
|
||||
});
|
||||
|
||||
// Ambil menu default untuk role baru
|
||||
const menuIds = getMenuIdsByRoleId(roleId);
|
||||
|
||||
if (menuIds.length > 0) {
|
||||
// Buat akses baru
|
||||
await prisma.userMenuAccess.createMany({
|
||||
data: menuIds.map(menuId => ({
|
||||
userId: id,
|
||||
menuId
|
||||
}))
|
||||
});
|
||||
}
|
||||
}
|
||||
const isActiveChanged = isActive !== undefined && currentUser.isActive !== isActive;
|
||||
|
||||
// Update user
|
||||
const updatedUser = await prisma.user.update({
|
||||
@@ -71,11 +48,10 @@ export default async function userUpdate(context: Context) {
|
||||
nomor: true,
|
||||
isActive: true,
|
||||
roleId: true,
|
||||
role: { select: { name: true } },
|
||||
},
|
||||
role: { select: { name: true } }
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// ✅ HAPUS SEMUA SESI USER DI DATABASE
|
||||
if (isRoleChanged) {
|
||||
await prisma.userSession.deleteMany({ where: { userId: id } });
|
||||
@@ -86,13 +62,11 @@ export default async function userUpdate(context: Context) {
|
||||
roleChanged: isRoleChanged,
|
||||
isActiveChanged,
|
||||
data: updatedUser,
|
||||
message: isRoleChanged
|
||||
message: isRoleChanged
|
||||
? `Role ${updatedUser.username} diubah. User akan logout otomatis.`
|
||||
: isActiveChanged
|
||||
? `${updatedUser.username} ${
|
||||
isActive ? "diaktifkan" : "dinonaktifkan"
|
||||
}.`
|
||||
: "User berhasil diupdate",
|
||||
? `${updatedUser.username} ${isActive ? 'diaktifkan' : 'dinonaktifkan'}.`
|
||||
: "User berhasil diupdate"
|
||||
};
|
||||
} catch (e: any) {
|
||||
console.error("❌ Error update user:", e);
|
||||
@@ -101,4 +75,4 @@ export default async function userUpdate(context: Context) {
|
||||
message: "Gagal mengupdate user: " + (e.message || "Unknown error"),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
144
src/app/api/[auth]/_lib/api_fetch_auth.ts
Normal file
144
src/app/api/[auth]/_lib/api_fetch_auth.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
// app/api/_lib/api_fetch_auth.ts
|
||||
|
||||
// app/api/_lib/api_fetch_auth.ts
|
||||
|
||||
export const apiFetchLogin = async ({ nomor }: { nomor: string }) => {
|
||||
if (!nomor || nomor.replace(/\D/g, '').length < 10) {
|
||||
throw new Error('Nomor tidak valid');
|
||||
}
|
||||
|
||||
const cleanPhone = nomor.replace(/\D/g, '');
|
||||
|
||||
const response = await fetch("/api/login", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ nomor: cleanPhone }),
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
// Pastikan respons bisa di-parse sebagai JSON
|
||||
let data;
|
||||
try {
|
||||
data = await response.json();
|
||||
} catch (e) {
|
||||
console.error("Non-JSON response from /api/login:", await response.text());
|
||||
throw new Error('Respons server tidak valid');
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.message || 'Gagal memproses login');
|
||||
}
|
||||
|
||||
// Validasi minimal respons
|
||||
if (typeof data.success !== 'boolean' || typeof data.isRegistered !== 'boolean') {
|
||||
throw new Error('Respons tidak sesuai format');
|
||||
}
|
||||
|
||||
if (data.success) {
|
||||
if (data.isRegistered && !data.kodeId) {
|
||||
throw new Error('Kode verifikasi tidak ditemukan untuk user terdaftar');
|
||||
}
|
||||
return data; // { success, isRegistered, kodeId? }
|
||||
} else {
|
||||
throw new Error(data.message || 'Login gagal');
|
||||
}
|
||||
};
|
||||
|
||||
export const apiFetchRegister = async ({
|
||||
username,
|
||||
nomor,
|
||||
}: {
|
||||
username: string;
|
||||
nomor: string;
|
||||
}) => {
|
||||
const cleanPhone = nomor.replace(/\D/g, '');
|
||||
if (cleanPhone.length < 10) throw new Error('Nomor tidak valid');
|
||||
|
||||
const response = await fetch("/api/register", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ username: username.trim(), nomor: cleanPhone }),
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (!response.ok) throw new Error(data.message || 'Gagal mengirim OTP');
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const apiFetchOtpData = async ({ kodeId }: { kodeId: string }) => {
|
||||
if (!kodeId) {
|
||||
throw new Error('Kode ID tidak valid');
|
||||
}
|
||||
|
||||
const response = await fetch("/api/otp-data", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ kodeId }),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data.message || 'Gagal memuat data OTP');
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
// Ganti endpoint ke verify-otp-login
|
||||
export const apiFetchVerifyOtp = async ({ nomor, otp, kodeId }: { nomor: string; otp: string; kodeId: string }) => {
|
||||
const response = await fetch('/api/verify-otp-login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ nomor, otp, kodeId }),
|
||||
});
|
||||
const data = await response.json();
|
||||
return {
|
||||
success: response.ok,
|
||||
...data,
|
||||
status: response.status,
|
||||
};
|
||||
};
|
||||
|
||||
// Di dalam api_fetch_auth.ts
|
||||
|
||||
export async function apiFetchUserMenuAccess(userId: string): Promise<{
|
||||
success: boolean;
|
||||
menuIds?: string[];
|
||||
message?: string;
|
||||
}> {
|
||||
try {
|
||||
const res = await fetch(`/api/admin/user-menu-access/${userId}`, {
|
||||
method: 'GET',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('API Fetch User Menu Access Error:', error);
|
||||
return { success: false, message: 'Gagal memuat menu akses' };
|
||||
}
|
||||
}
|
||||
|
||||
export async function apiUpdateUserMenuAccess(
|
||||
userId: string,
|
||||
menuIds: string[]
|
||||
): Promise<{ success: boolean; message?: string }> {
|
||||
try {
|
||||
const res = await fetch('/api/admin/user-menu-access', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ userId, menuIds }),
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('API Update User Menu Access Error:', error);
|
||||
return { success: false, message: 'Gagal menyimpan menu akses' };
|
||||
}
|
||||
}
|
||||
149
src/app/api/[auth]/finalize-registration/route.ts
Normal file
149
src/app/api/[auth]/finalize-registration/route.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
// src/app/api/auth/finalize-registration/route.ts
|
||||
import prisma from "@/lib/prisma";
|
||||
import { NextResponse } from "next/server";
|
||||
import { sessionCreate } from "../_lib/session_create";
|
||||
|
||||
// ✅ Gunakan STRING untuk roleId
|
||||
const DEFAULT_MENUS_BY_ROLE: Record<string, string[]> = {
|
||||
"0": [
|
||||
"Landing Page", "PPID", "Desa", "Kesehatan", "Keamanan",
|
||||
"Ekonomi", "Inovasi", "Lingkungan", "Pendidikan", "User & Role"
|
||||
],
|
||||
"1": [
|
||||
"Landing Page", "PPID", "Desa", "Keamanan",
|
||||
"Ekonomi", "Inovasi", "Lingkungan", "User & Role"
|
||||
],
|
||||
"2": ["Landing Page", "Desa", "Ekonomi", "Inovasi", "Lingkungan"],
|
||||
"3": ["Kesehatan"],
|
||||
"4": ["Pendidikan"],
|
||||
};
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const { nomor, username, kodeId } = await req.json();
|
||||
const cleanNomor = nomor.replace(/\D/g, "");
|
||||
|
||||
if (!cleanNomor || !username || !kodeId) {
|
||||
return NextResponse.json(
|
||||
{ success: false, message: "Data tidak lengkap" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Verify OTP
|
||||
const otpRecord = await prisma.kodeOtp.findUnique({
|
||||
where: { id: kodeId },
|
||||
select: { nomor: true, isActive: true }
|
||||
});
|
||||
|
||||
if (!otpRecord?.isActive || otpRecord.nomor !== cleanNomor) {
|
||||
return NextResponse.json(
|
||||
{ success: false, message: "OTP tidak valid" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Check duplicate username
|
||||
if (await prisma.user.findFirst({ where: { username } })) {
|
||||
return NextResponse.json(
|
||||
{ success: false, message: "Username sudah digunakan" },
|
||||
{ status: 409 }
|
||||
);
|
||||
}
|
||||
|
||||
// Check duplicate nomor
|
||||
if (await prisma.user.findUnique({ where: { nomor: cleanNomor } })) {
|
||||
return NextResponse.json(
|
||||
{ success: false, message: "Nomor sudah terdaftar" },
|
||||
{ status: 409 }
|
||||
);
|
||||
}
|
||||
|
||||
// 🔥 Tentukan roleId sebagai STRING
|
||||
const targetRoleId = "2"; // ✅ Default ADMIN_DESA (roleId "2")
|
||||
|
||||
// Validasi role exists
|
||||
const roleExists = await prisma.role.findUnique({
|
||||
where: { id: targetRoleId },
|
||||
select: { id: true }
|
||||
});
|
||||
|
||||
if (!roleExists) {
|
||||
return NextResponse.json(
|
||||
{ success: false, message: "Role tidak valid" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// ✅ Create user (inactive, waiting approval)
|
||||
const newUser = await prisma.user.create({
|
||||
data: {
|
||||
username,
|
||||
nomor: cleanNomor,
|
||||
roleId: targetRoleId,
|
||||
isActive: false, // Waiting for admin approval
|
||||
},
|
||||
});
|
||||
|
||||
// ✅ Berikan akses menu default based on role
|
||||
const menuIds = DEFAULT_MENUS_BY_ROLE[targetRoleId] || [];
|
||||
if (menuIds.length > 0) {
|
||||
await prisma.userMenuAccess.createMany({
|
||||
data: menuIds.map(menuId => ({
|
||||
userId: newUser.id,
|
||||
menuId,
|
||||
})),
|
||||
skipDuplicates: true, // ✅ Avoid duplicate errors
|
||||
});
|
||||
}
|
||||
|
||||
// ✅ Mark OTP as used
|
||||
await prisma.kodeOtp.update({
|
||||
where: { id: kodeId },
|
||||
data: { isActive: false },
|
||||
});
|
||||
|
||||
// ✅ Create session token
|
||||
const token = await sessionCreate({
|
||||
sessionKey: process.env.BASE_SESSION_KEY!,
|
||||
jwtSecret: process.env.BASE_TOKEN_KEY!,
|
||||
exp: "30 day",
|
||||
user: {
|
||||
id: newUser.id,
|
||||
nomor: newUser.nomor,
|
||||
username: newUser.username,
|
||||
roleId: newUser.roleId,
|
||||
isActive: false, // User belum aktif
|
||||
},
|
||||
invalidatePrevious: false,
|
||||
});
|
||||
|
||||
// ✅ PENTING: Return JSON response (bukan redirect)
|
||||
const response = NextResponse.json({
|
||||
success: true,
|
||||
message: "Registrasi berhasil. Menunggu persetujuan admin.",
|
||||
userId: newUser.id,
|
||||
});
|
||||
|
||||
// ✅ Set session cookie
|
||||
const cookieName = process.env.BASE_SESSION_KEY || 'session';
|
||||
response.cookies.set(cookieName, token, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
sameSite: 'lax',
|
||||
path: "/",
|
||||
maxAge: 30 * 24 * 60 * 60, // 30 days
|
||||
});
|
||||
|
||||
return response;
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ Finalize Registration Error:", error);
|
||||
return NextResponse.json(
|
||||
{ success: false, message: "Registrasi gagal. Silakan coba lagi." },
|
||||
{ status: 500 }
|
||||
);
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
59
src/app/api/[auth]/me/route.ts
Normal file
59
src/app/api/[auth]/me/route.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
// src/app/api/auth/me/route.ts
|
||||
import { NextResponse } from 'next/server';
|
||||
import { verifySession } from '../_lib/session_verify';
|
||||
import prisma from '@/lib/prisma';
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const sessionUser = await verifySession();
|
||||
if (!sessionUser) {
|
||||
return NextResponse.json(
|
||||
{ success: false, message: "Unauthorized", user: null },
|
||||
{ status: 401 }
|
||||
);
|
||||
}
|
||||
|
||||
const [dbUser, menuAccess] = await Promise.all([
|
||||
prisma.user.findUnique({
|
||||
where: { id: sessionUser.id },
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
nomor: true,
|
||||
roleId: true, // STRING!
|
||||
isActive: true, // BOOLEAN!
|
||||
},
|
||||
}),
|
||||
prisma.userMenuAccess.findMany({
|
||||
where: { userId: sessionUser.id },
|
||||
select: { menuId: true },
|
||||
}),
|
||||
]);
|
||||
|
||||
if (!dbUser) {
|
||||
return NextResponse.json(
|
||||
{ success: false, message: "User not found", user: null },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
user: {
|
||||
id: dbUser.id,
|
||||
name: dbUser.username,
|
||||
username: dbUser.username,
|
||||
nomor: dbUser.nomor,
|
||||
roleId: dbUser.roleId, // STRING!
|
||||
isActive: dbUser.isActive, // BOOLEAN!
|
||||
menuIds: menuAccess.map(m => m.menuId),
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("❌ Error in /api/me:", error);
|
||||
return NextResponse.json(
|
||||
{ success: false, message: "Internal server error", user: null },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
// src/app/api/auth/finalize-registration/route.ts
|
||||
import prisma from "@/lib/prisma";
|
||||
import { NextResponse } from "next/server";
|
||||
import { sessionCreate } from "../_lib/session_create";
|
||||
import { sessionCreate } from "../../[auth]/_lib/session_create";
|
||||
|
||||
|
||||
// ✅ Gunakan STRING untuk roleId
|
||||
const DEFAULT_MENUS_BY_ROLE: Record<string, string[]> = {
|
||||
|
||||
@@ -12,7 +12,6 @@ export async function GET() {
|
||||
{ status: 401 }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const [dbUser, menuAccess] = await Promise.all([
|
||||
prisma.user.findUnique({
|
||||
|
||||
@@ -48,7 +48,6 @@ export default function RootLayout({
|
||||
<ViewTransitions>
|
||||
<html lang="en" {...mantineHtmlProps}>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<ColorSchemeScript />
|
||||
<link
|
||||
rel="icon"
|
||||
|
||||
@@ -80,7 +80,7 @@ export default function WaitingRoom() {
|
||||
|
||||
// Force a session refresh
|
||||
try {
|
||||
const res = await fetch('/api/auth/refresh-session', {
|
||||
const res = await fetch('/api/refresh-session', {
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user