feat: add authentication support and user model

- Updated `env.example` to include NextAuth configuration for authentication.
- Added `next-auth` dependency to manage user sessions.
- Introduced `User` model in Prisma schema with fields for user details and password hashing.
- Integrated `AuthProvider` in layout for session management across the app.
- Enhanced `Header` component with `AuthButton` for user authentication controls.
This commit is contained in:
Julien Froidefond
2025-09-30 21:49:52 +02:00
parent 43c141d3cd
commit 17b86b6087
20 changed files with 1418 additions and 13 deletions

150
src/services/users.ts Normal file
View File

@@ -0,0 +1,150 @@
import { prisma } from './core/database'
import bcrypt from 'bcryptjs'
export interface CreateUserData {
email: string
name?: string
firstName?: string
lastName?: string
avatar?: string
role?: string
password: string
}
export interface User {
id: string
email: string
name: string | null
firstName: string | null
lastName: string | null
avatar: string | null
role: string
isActive: boolean
lastLoginAt: Date | null
createdAt: Date
updatedAt: Date
}
export const usersService = {
async createUser(data: CreateUserData): Promise<User> {
const hashedPassword = await bcrypt.hash(data.password, 12)
const user = await prisma.user.create({
data: {
email: data.email,
name: data.name,
firstName: data.firstName,
lastName: data.lastName,
avatar: data.avatar,
role: data.role || 'user',
password: hashedPassword,
},
select: {
id: true,
email: true,
name: true,
firstName: true,
lastName: true,
avatar: true,
role: true,
isActive: true,
lastLoginAt: true,
createdAt: true,
updatedAt: true,
}
})
return user
},
async getUserByEmail(email: string) {
return await prisma.user.findUnique({
where: { email },
select: {
id: true,
email: true,
name: true,
firstName: true,
lastName: true,
avatar: true,
role: true,
isActive: true,
lastLoginAt: true,
password: true,
createdAt: true,
updatedAt: true,
}
})
},
async getUserById(id: string): Promise<User | null> {
return await prisma.user.findUnique({
where: { id },
select: {
id: true,
email: true,
name: true,
firstName: true,
lastName: true,
avatar: true,
role: true,
isActive: true,
lastLoginAt: true,
createdAt: true,
updatedAt: true,
}
})
},
async verifyPassword(password: string, hashedPassword: string): Promise<boolean> {
return await bcrypt.compare(password, hashedPassword)
},
async emailExists(email: string): Promise<boolean> {
const user = await prisma.user.findUnique({
where: { email },
select: { id: true }
})
return !!user
},
async updateLastLogin(userId: string): Promise<void> {
await prisma.user.update({
where: { id: userId },
data: { lastLoginAt: new Date() }
})
},
async updateUser(userId: string, data: {
name?: string | null
firstName?: string | null
lastName?: string | null
avatar?: string | null
}): Promise<User> {
const user = await prisma.user.update({
where: { id: userId },
data: {
name: data.name,
firstName: data.firstName,
lastName: data.lastName,
avatar: data.avatar,
updatedAt: new Date(),
},
select: {
id: true,
email: true,
name: true,
firstName: true,
lastName: true,
avatar: true,
role: true,
isActive: true,
lastLoginAt: true,
createdAt: true,
updatedAt: true,
}
})
return user
}
}