116 lines
3.2 KiB
TypeScript
116 lines
3.2 KiB
TypeScript
// lib/auth-options.ts
|
|
import type { NextAuthOptions } from 'next-auth';
|
|
import CredentialsProvider from 'next-auth/providers/credentials';
|
|
import { prisma } from './prisma';
|
|
import { compare } from 'bcryptjs';
|
|
|
|
export const authOptions: NextAuthOptions = {
|
|
providers: [
|
|
CredentialsProvider({
|
|
name: 'Credentials',
|
|
credentials: {
|
|
email: {
|
|
label: 'NW-Kennung oder E-Mail',
|
|
type: 'text',
|
|
},
|
|
password: {
|
|
label: 'Passwort',
|
|
type: 'password',
|
|
},
|
|
},
|
|
async authorize(credentials) {
|
|
if (!credentials?.email || !credentials.password) {
|
|
return null;
|
|
}
|
|
|
|
const identifier = credentials.email.trim();
|
|
|
|
const user = await prisma.user.findFirst({
|
|
where: {
|
|
OR: [
|
|
{
|
|
email: {
|
|
equals: identifier,
|
|
mode: 'insensitive',
|
|
},
|
|
},
|
|
{
|
|
nwkennung: {
|
|
equals: identifier,
|
|
mode: 'insensitive',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
include: {
|
|
group: true, // <-- wichtig, damit user.group da ist
|
|
// roles: { include: { role: true } }, // falls du das auch brauchst
|
|
},
|
|
});
|
|
|
|
if (!user || !user.passwordHash) return null;
|
|
|
|
const isValid = await compare(credentials.password, user.passwordHash);
|
|
if (!isValid) return null;
|
|
|
|
const displayName =
|
|
user.arbeitsname ??
|
|
(user.firstName && user.lastName
|
|
? `${user.firstName} ${user.lastName}`
|
|
: user.email ?? user.nwkennung ?? 'Unbekannt');
|
|
|
|
const canEditDevices = !!user.group?.canEditDevices;
|
|
|
|
return {
|
|
id: user.nwkennung,
|
|
name: displayName,
|
|
email: user.email,
|
|
nwkennung: user.nwkennung,
|
|
avatarUrl: user.avatarUrl ?? null,
|
|
groupCanEditDevices: canEditDevices, // <-- hier mitgeben
|
|
} as any;
|
|
},
|
|
}),
|
|
],
|
|
pages: {
|
|
signIn: '/login',
|
|
},
|
|
session: {
|
|
strategy: 'jwt',
|
|
maxAge: 60 * 60 * 24 * 30,
|
|
},
|
|
callbacks: {
|
|
async jwt({ token, user, trigger, session }) {
|
|
// Wenn wir clientseitig `update({ avatarUrl })` aufrufen,
|
|
// kommt das hier als `trigger === 'update'` an.
|
|
if (trigger === 'update' && session) {
|
|
if ('avatarUrl' in session) {
|
|
(token as any).avatarUrl = (session as any).avatarUrl ?? null;
|
|
}
|
|
}
|
|
|
|
// Login-Fall
|
|
if (user) {
|
|
token.id = (user as any).id;
|
|
token.nwkennung = (user as any).nwkennung;
|
|
(token as any).avatarUrl = (user as any).avatarUrl ?? null;
|
|
(token as any).groupCanEditDevices =
|
|
(user as any).groupCanEditDevices ?? false;
|
|
}
|
|
|
|
return token;
|
|
},
|
|
|
|
async session({ session, token }) {
|
|
if (session.user && token.id) {
|
|
(session.user as any).id = token.id;
|
|
(session.user as any).nwkennung = (token as any).nwkennung;
|
|
(session.user as any).avatarUrl = (token as any).avatarUrl ?? null;
|
|
(session.user as any).groupCanEditDevices =
|
|
(token as any).groupCanEditDevices ?? false;
|
|
}
|
|
return session;
|
|
},
|
|
}
|
|
};
|