Neah version calendar fix 3 debuger sec chance danger debug 7
This commit is contained in:
parent
f331080d39
commit
d767ee9510
BIN
backup oldversion for help/.DS_Store
vendored
Normal file
BIN
backup oldversion for help/.DS_Store
vendored
Normal file
Binary file not shown.
166
backup oldversion for help/api-calendar/route.ts
Normal file
166
backup oldversion for help/api-calendar/route.ts
Normal file
@ -0,0 +1,166 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { getServerSession } from "next-auth/next";
|
||||
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
// GET events
|
||||
export async function GET(req: Request) {
|
||||
try {
|
||||
const session = await getServerSession(authOptions);
|
||||
if (!session) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const { searchParams } = new URL(req.url);
|
||||
const start = searchParams.get("start");
|
||||
const end = searchParams.get("end");
|
||||
|
||||
// First get all calendars for the user
|
||||
const calendars = await prisma.calendar.findMany({
|
||||
where: {
|
||||
userId: session.user.id,
|
||||
},
|
||||
});
|
||||
|
||||
// Then get events with calendar information
|
||||
const events = await prisma.event.findMany({
|
||||
where: {
|
||||
calendarId: {
|
||||
in: calendars.map(cal => cal.id)
|
||||
},
|
||||
...(start && end
|
||||
? {
|
||||
start: {
|
||||
gte: new Date(start),
|
||||
},
|
||||
end: {
|
||||
lte: new Date(end),
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
include: {
|
||||
calendar: true,
|
||||
},
|
||||
orderBy: {
|
||||
start: "asc",
|
||||
},
|
||||
});
|
||||
|
||||
// Map the events to include calendar color and name
|
||||
const eventsWithCalendarInfo = events.map(event => ({
|
||||
...event,
|
||||
calendarColor: event.calendar.color,
|
||||
calendarName: event.calendar.name,
|
||||
calendar: undefined, // Remove the full calendar object
|
||||
}));
|
||||
|
||||
return NextResponse.json(eventsWithCalendarInfo);
|
||||
} catch (error) {
|
||||
console.error("Error fetching events:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors du chargement des événements" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// POST new event
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const session = await getServerSession(authOptions);
|
||||
if (!session?.user) {
|
||||
return NextResponse.json(
|
||||
{ error: "Non autorisé" },
|
||||
{ status: 401 }
|
||||
);
|
||||
}
|
||||
|
||||
const data = await req.json();
|
||||
const { title, description, start, end, location, calendarId } = data;
|
||||
|
||||
const event = await prisma.event.create({
|
||||
data: {
|
||||
title,
|
||||
description,
|
||||
start: new Date(start),
|
||||
end: new Date(end),
|
||||
isAllDay: data.allDay || false,
|
||||
location: location || null,
|
||||
calendarId,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(event);
|
||||
} catch (error) {
|
||||
console.error("Error creating event:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la création de l'événement" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// PUT update event
|
||||
export async function PUT(req: Request) {
|
||||
try {
|
||||
const session = await getServerSession(authOptions);
|
||||
if (!session) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const body = await req.json();
|
||||
const { id, ...data } = body;
|
||||
|
||||
const event = await prisma.event.update({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
data,
|
||||
});
|
||||
|
||||
return NextResponse.json(event);
|
||||
} catch (error) {
|
||||
console.error("Error updating event:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Error updating event" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE event
|
||||
export async function DELETE(req: Request) {
|
||||
try {
|
||||
const session = await getServerSession(authOptions);
|
||||
if (!session) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const { searchParams } = new URL(req.url);
|
||||
const id = searchParams.get("id");
|
||||
|
||||
if (!id) {
|
||||
return NextResponse.json(
|
||||
{ error: "Event ID is required" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
await prisma.event.delete({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
} catch (error) {
|
||||
console.error("Error deleting event:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Error deleting event" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
129
backup oldversion for help/flow.tsx
Normal file
129
backup oldversion for help/flow.tsx
Normal file
@ -0,0 +1,129 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
interface Task {
|
||||
id: string;
|
||||
headline: string;
|
||||
projectName: string;
|
||||
projectId: number;
|
||||
status: number;
|
||||
dueDate: string | null;
|
||||
milestone: string | null;
|
||||
details: string | null;
|
||||
createdOn: string;
|
||||
editedOn: string | null;
|
||||
assignedTo: number[];
|
||||
}
|
||||
|
||||
export default function Flow() {
|
||||
const [tasks, setTasks] = useState<Task[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const getStatusLabel = (status: number): string => {
|
||||
switch (status) {
|
||||
case 1:
|
||||
return 'New';
|
||||
case 2:
|
||||
return 'In Progress';
|
||||
case 3:
|
||||
return 'Done';
|
||||
case 4:
|
||||
return 'In Progress';
|
||||
case 5:
|
||||
return 'Done';
|
||||
default:
|
||||
return 'Unknown';
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusColor = (status: number): string => {
|
||||
switch (status) {
|
||||
case 1:
|
||||
return 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300';
|
||||
case 2:
|
||||
case 4:
|
||||
return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300';
|
||||
case 3:
|
||||
case 5:
|
||||
return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300';
|
||||
default:
|
||||
return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300';
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const fetchTasks = async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const response = await fetch('/api/leantime/tasks');
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch tasks');
|
||||
}
|
||||
const data = await response.json();
|
||||
if (data.tasks && Array.isArray(data.tasks)) {
|
||||
// Sort tasks by creation date (oldest first)
|
||||
const sortedTasks = data.tasks.sort((a: Task, b: Task) => {
|
||||
const dateA = new Date(a.createdOn).getTime();
|
||||
const dateB = new Date(b.createdOn).getTime();
|
||||
return dateA - dateB;
|
||||
});
|
||||
setTasks(sortedTasks);
|
||||
} else {
|
||||
console.error('Invalid tasks data format:', data);
|
||||
setError('Invalid tasks data format');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error fetching tasks:', err);
|
||||
setError(err instanceof Error ? err.message : 'An error occurred');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchTasks();
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <div>Error: {error}</div>;
|
||||
}
|
||||
|
||||
if (tasks.length === 0) {
|
||||
return <div>No tasks found</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 gap-4">
|
||||
{tasks.map((task) => (
|
||||
<div
|
||||
key={task.id}
|
||||
className="bg-white dark:bg-gray-800 rounded-lg shadow p-4"
|
||||
>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex-1">
|
||||
<h3 className="text-sm font-medium text-gray-900 dark:text-gray-100">
|
||||
{task.headline}
|
||||
</h3>
|
||||
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
{task.projectName}
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(
|
||||
task.status
|
||||
)}`}
|
||||
>
|
||||
{getStatusLabel(task.status)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
13
backup oldversion for help/prisma-news.ts
Normal file
13
backup oldversion for help/prisma-news.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { PrismaClient } from '@prisma/client/news'
|
||||
|
||||
const globalForPrisma = globalThis as unknown as {
|
||||
prismaNews: PrismaClient | undefined;
|
||||
}
|
||||
|
||||
export const prismaNews =
|
||||
globalForPrisma.prismaNews ||
|
||||
new PrismaClient({
|
||||
log: ['query'],
|
||||
})
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') globalForPrisma.prismaNews = prismaNews
|
||||
14
backup oldversion for help/prisma.ts
Normal file
14
backup oldversion for help/prisma.ts
Normal file
@ -0,0 +1,14 @@
|
||||
// front/lib/prisma.ts
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
const globalForPrisma = globalThis as unknown as {
|
||||
prisma: PrismaClient | undefined;
|
||||
}
|
||||
|
||||
export const prisma =
|
||||
globalForPrisma.prisma ||
|
||||
new PrismaClient({
|
||||
log: ['query'],
|
||||
})
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
|
||||
144
backup oldversion for help/route.ts
Normal file
144
backup oldversion for help/route.ts
Normal file
@ -0,0 +1,144 @@
|
||||
import NextAuth, { NextAuthOptions } from "next-auth";
|
||||
import KeycloakProvider from "next-auth/providers/keycloak";
|
||||
|
||||
declare module "next-auth" {
|
||||
interface Session {
|
||||
user: {
|
||||
id: string;
|
||||
name?: string | null;
|
||||
email?: string | null;
|
||||
image?: string | null;
|
||||
username: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
role: string[];
|
||||
};
|
||||
accessToken: string;
|
||||
}
|
||||
|
||||
interface JWT {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
accessTokenExpires: number;
|
||||
role: string[];
|
||||
username: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
}
|
||||
}
|
||||
|
||||
function getRequiredEnvVar(name: string): string {
|
||||
const value = process.env[name];
|
||||
if (!value) {
|
||||
throw new Error(`Missing required environment variable: ${name}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export const authOptions: NextAuthOptions = {
|
||||
providers: [
|
||||
KeycloakProvider({
|
||||
clientId: getRequiredEnvVar("KEYCLOAK_CLIENT_ID"),
|
||||
clientSecret: getRequiredEnvVar("KEYCLOAK_CLIENT_SECRET"),
|
||||
issuer: getRequiredEnvVar("KEYCLOAK_ISSUER"),
|
||||
profile(profile) {
|
||||
return {
|
||||
id: profile.sub,
|
||||
name: profile.name ?? profile.preferred_username,
|
||||
email: profile.email,
|
||||
first_name: profile.given_name ?? '',
|
||||
last_name: profile.family_name ?? '',
|
||||
username: profile.preferred_username ?? profile.email?.split('@')[0] ?? '',
|
||||
role: profile.groups ?? [],
|
||||
}
|
||||
},
|
||||
}),
|
||||
],
|
||||
session: {
|
||||
strategy: "jwt",
|
||||
maxAge: 30 * 24 * 60 * 60, // 30 days
|
||||
},
|
||||
callbacks: {
|
||||
async jwt({ token, account, profile }) {
|
||||
if (account && profile) {
|
||||
token.accessToken = account.access_token;
|
||||
token.refreshToken = account.refresh_token;
|
||||
token.accessTokenExpires = account.expires_at! * 1000;
|
||||
token.role = (profile as any).groups ?? [];
|
||||
token.username = (profile as any).preferred_username ?? profile.email?.split('@')[0] ?? '';
|
||||
token.first_name = (profile as any).given_name ?? '';
|
||||
token.last_name = (profile as any).family_name ?? '';
|
||||
}
|
||||
|
||||
// Return previous token if not expired
|
||||
if (Date.now() < (token.accessTokenExpires as number)) {
|
||||
return token;
|
||||
}
|
||||
|
||||
try {
|
||||
const clientId = getRequiredEnvVar("KEYCLOAK_CLIENT_ID");
|
||||
const clientSecret = getRequiredEnvVar("KEYCLOAK_CLIENT_SECRET");
|
||||
|
||||
const response = await fetch(
|
||||
`${process.env.KEYCLOAK_BASE_URL}/realms/${process.env.KEYCLOAK_REALM}/protocol/openid-connect/token`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
grant_type: "refresh_token",
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret,
|
||||
refresh_token: token.refreshToken as string,
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
const tokens = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("RefreshAccessTokenError");
|
||||
}
|
||||
|
||||
return {
|
||||
...token,
|
||||
accessToken: tokens.access_token,
|
||||
refreshToken: tokens.refresh_token ?? token.refreshToken,
|
||||
accessTokenExpires: Date.now() + tokens.expires_in * 1000,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
...token,
|
||||
error: "RefreshAccessTokenError",
|
||||
};
|
||||
}
|
||||
},
|
||||
async session({ session, token }) {
|
||||
if (token.error) {
|
||||
throw new Error("RefreshAccessTokenError");
|
||||
}
|
||||
|
||||
session.accessToken = token.accessToken;
|
||||
session.user = {
|
||||
...session.user,
|
||||
id: token.sub as string,
|
||||
first_name: token.first_name ?? '',
|
||||
last_name: token.last_name ?? '',
|
||||
username: token.username ?? '',
|
||||
role: token.role ?? [],
|
||||
};
|
||||
|
||||
return session;
|
||||
}
|
||||
},
|
||||
pages: {
|
||||
signIn: '/signin',
|
||||
error: '/signin',
|
||||
},
|
||||
debug: process.env.NODE_ENV === 'development',
|
||||
};
|
||||
|
||||
const handler = NextAuth(authOptions);
|
||||
export { handler as GET, handler as POST };
|
||||
|
||||
20
backup oldversion for help/utils.ts
Normal file
20
backup oldversion for help/utils.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
||||
export function formatDate(dateString: string): string {
|
||||
try {
|
||||
const date = new Date(dateString);
|
||||
return new Intl.DateTimeFormat('en-US', {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
year: 'numeric'
|
||||
}).format(date);
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
150
lib/auth.ts
150
lib/auth.ts
@ -1,123 +1,96 @@
|
||||
import { NextAuthOptions } from 'next-auth';
|
||||
import KeycloakProvider from 'next-auth/providers/keycloak';
|
||||
import NextAuth, { NextAuthOptions } from "next-auth";
|
||||
import KeycloakProvider from "next-auth/providers/keycloak";
|
||||
|
||||
declare module 'next-auth' {
|
||||
interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
name?: string | null;
|
||||
role: string[];
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
username: string;
|
||||
}
|
||||
declare module "next-auth" {
|
||||
interface Session {
|
||||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
name?: string | null;
|
||||
role: string[];
|
||||
email?: string | null;
|
||||
image?: string | null;
|
||||
username: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
username: string;
|
||||
role: string[];
|
||||
};
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
}
|
||||
interface Profile {
|
||||
sub?: string;
|
||||
email?: string;
|
||||
name?: string;
|
||||
roles?: string[];
|
||||
given_name?: string;
|
||||
family_name?: string;
|
||||
preferred_username?: string;
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'next-auth/jwt' {
|
||||
interface JWT {
|
||||
id: string;
|
||||
email: string;
|
||||
name?: string;
|
||||
role: string[];
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
username: string;
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
accessTokenExpires: number;
|
||||
error?: string;
|
||||
role: string[];
|
||||
username: string;
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
}
|
||||
}
|
||||
|
||||
function getRequiredEnvVar(name: string): string {
|
||||
const value = process.env[name];
|
||||
if (!value) {
|
||||
throw new Error(`Missing required environment variable: ${name}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export const authOptions: NextAuthOptions = {
|
||||
providers: [
|
||||
KeycloakProvider({
|
||||
clientId: process.env.KEYCLOAK_CLIENT_ID!,
|
||||
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET!,
|
||||
issuer: process.env.KEYCLOAK_ISSUER,
|
||||
authorization: {
|
||||
params: {
|
||||
scope: 'openid email profile',
|
||||
response_type: 'code',
|
||||
clientId: getRequiredEnvVar("KEYCLOAK_CLIENT_ID"),
|
||||
clientSecret: getRequiredEnvVar("KEYCLOAK_CLIENT_SECRET"),
|
||||
issuer: getRequiredEnvVar("KEYCLOAK_ISSUER"),
|
||||
profile(profile) {
|
||||
return {
|
||||
id: profile.sub,
|
||||
name: profile.name ?? profile.preferred_username,
|
||||
email: profile.email,
|
||||
first_name: profile.given_name ?? '',
|
||||
last_name: profile.family_name ?? '',
|
||||
username: profile.preferred_username ?? profile.email?.split('@')[0] ?? '',
|
||||
role: profile.groups ?? [],
|
||||
}
|
||||
},
|
||||
}),
|
||||
],
|
||||
debug: false,
|
||||
session: {
|
||||
strategy: 'jwt',
|
||||
strategy: "jwt",
|
||||
maxAge: 30 * 24 * 60 * 60, // 30 days
|
||||
},
|
||||
pages: {
|
||||
signIn: '/signin',
|
||||
error: '/signin',
|
||||
},
|
||||
callbacks: {
|
||||
async jwt({ token, account, profile }) {
|
||||
if (account && profile) {
|
||||
if (!profile.sub) {
|
||||
throw new Error('No user ID (sub) provided by Keycloak');
|
||||
}
|
||||
if (!account.access_token || !account.refresh_token || !account.expires_at) {
|
||||
throw new Error('Missing required token fields from Keycloak');
|
||||
}
|
||||
token.id = profile.sub;
|
||||
token.email = profile.email || '';
|
||||
token.name = profile.name;
|
||||
token.role = profile.roles || ['user'];
|
||||
token.first_name = profile.given_name || '';
|
||||
token.last_name = profile.family_name || '';
|
||||
token.username = profile.preferred_username || '';
|
||||
token.accessToken = account.access_token;
|
||||
token.refreshToken = account.refresh_token;
|
||||
token.accessTokenExpires = account.expires_at * 1000;
|
||||
token.accessToken = account.access_token!;
|
||||
token.refreshToken = account.refresh_token!;
|
||||
token.accessTokenExpires = account.expires_at! * 1000;
|
||||
token.role = (profile as any).groups ?? [];
|
||||
token.username = (profile as any).preferred_username ?? profile.email?.split('@')[0] ?? '';
|
||||
token.first_name = (profile as any).given_name ?? '';
|
||||
token.last_name = (profile as any).family_name ?? '';
|
||||
}
|
||||
|
||||
// Return previous token if not expired
|
||||
if (token.accessTokenExpires && Date.now() < token.accessTokenExpires) {
|
||||
if (Date.now() < (token.accessTokenExpires as number)) {
|
||||
return token;
|
||||
}
|
||||
|
||||
// Token expired, try to refresh
|
||||
if (!token.refreshToken) {
|
||||
throw new Error('No refresh token available');
|
||||
}
|
||||
|
||||
try {
|
||||
const clientId = getRequiredEnvVar("KEYCLOAK_CLIENT_ID");
|
||||
const clientSecret = getRequiredEnvVar("KEYCLOAK_CLIENT_SECRET");
|
||||
|
||||
const response = await fetch(
|
||||
`${process.env.KEYCLOAK_BASE_URL}/realms/${process.env.KEYCLOAK_REALM}/protocol/openid-connect/token`,
|
||||
{
|
||||
method: 'POST',
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'refresh_token',
|
||||
client_id: process.env.KEYCLOAK_CLIENT_ID!,
|
||||
client_secret: process.env.KEYCLOAK_CLIENT_SECRET!,
|
||||
refresh_token: token.refreshToken,
|
||||
grant_type: "refresh_token",
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret,
|
||||
refresh_token: token.refreshToken as string,
|
||||
}),
|
||||
}
|
||||
);
|
||||
@ -125,7 +98,7 @@ export const authOptions: NextAuthOptions = {
|
||||
const tokens = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('RefreshAccessTokenError');
|
||||
throw new Error("RefreshAccessTokenError");
|
||||
}
|
||||
|
||||
return {
|
||||
@ -137,26 +110,31 @@ export const authOptions: NextAuthOptions = {
|
||||
} catch (error) {
|
||||
return {
|
||||
...token,
|
||||
error: 'RefreshAccessTokenError',
|
||||
error: "RefreshAccessTokenError",
|
||||
};
|
||||
}
|
||||
},
|
||||
async session({ session, token }) {
|
||||
if (token.error) {
|
||||
throw new Error('RefreshAccessTokenError');
|
||||
throw new Error("RefreshAccessTokenError");
|
||||
}
|
||||
|
||||
session.accessToken = token.accessToken;
|
||||
session.user = {
|
||||
id: token.sub ?? token.id ?? '',
|
||||
email: token.email ?? '',
|
||||
name: token.name ?? '',
|
||||
role: token.role ?? ['user'],
|
||||
...session.user,
|
||||
id: token.sub as string,
|
||||
first_name: token.first_name ?? '',
|
||||
last_name: token.last_name ?? '',
|
||||
username: token.username ?? ''
|
||||
username: token.username ?? '',
|
||||
role: token.role ?? [],
|
||||
};
|
||||
|
||||
|
||||
return session;
|
||||
},
|
||||
}
|
||||
},
|
||||
pages: {
|
||||
signIn: '/signin',
|
||||
error: '/signin',
|
||||
},
|
||||
debug: process.env.NODE_ENV === 'development',
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user