Files
mikicv 2d31c49235 Refactor production setup and database management
- Updated Dockerfile for production to ensure proper database permissions and improved startup script.
- Removed outdated PRODUCTION_README.md and consolidated relevant information into other documentation.
- Enhanced deploy.sh script to fix database permissions and streamline deployment process.
- Modified docker-compose configuration to use a dedicated production file and adjusted port mappings.
- Removed legacy docker-compose.yml file to avoid confusion.
- Improved session management by refining secure cookie settings based on environment variables.
- Deleted obsolete Nginx configuration and old seed scripts to clean up the project structure.
- Updated database setup scripts to reflect new structure and removed old seed data scripts.
- Adjusted reset-db script to use environment variable for database path.
- Enhanced setup-database script to provide dynamic admin credentials in the summary.
- Removed unnecessary backup file for SQLite database.
2025-09-28 16:32:31 +01:00

102 lines
2.7 KiB
TypeScript

import { SignJWT, jwtVerify } from 'jose';
import { cookies } from 'next/headers';
import { NextRequest } from 'next/server';
const secretKey = process.env.NEXTAUTH_SECRET;
const encodedKey = new TextEncoder().encode(secretKey);
export interface SessionPayload {
userId: string;
email: string;
role: 'user' | 'admin';
expiresAt: Date;
}
export async function encrypt(payload: SessionPayload) {
return new SignJWT({
userId: payload.userId,
email: payload.email,
role: payload.role,
expiresAt: payload.expiresAt.getTime(),
})
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime('7d')
.sign(encodedKey);
}
export async function decrypt(session: string | undefined = '') {
try {
const { payload } = await jwtVerify(session, encodedKey, {
algorithms: ['HS256'],
});
return {
userId: payload.userId as string,
email: payload.email as string,
role: payload.role as 'user' | 'admin',
expiresAt: new Date(payload.expiresAt as number),
};
} catch (error) {
console.log('Failed to verify session');
return null;
}
}
export async function createSession(payload: Omit<SessionPayload, 'expiresAt'>) {
const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
const session = await encrypt({ ...payload, expiresAt });
const cookieStore = await cookies();
cookieStore.set('session', session, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production' && process.env.NEXTAUTH_URL?.startsWith('https'),
expires: expiresAt,
sameSite: 'lax',
path: '/',
});
}
export async function updateSession() {
const cookieStore = await cookies();
const session = cookieStore.get('session')?.value;
const payload = await decrypt(session);
if (!session || !payload) {
return null;
}
const expires = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
const newSession = await encrypt({ ...payload, expiresAt: expires });
cookieStore.set('session', newSession, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production' && process.env.NEXTAUTH_URL?.startsWith('https'),
expires: expires,
sameSite: 'lax',
path: '/',
});
}
export async function deleteSession() {
const cookieStore = await cookies();
cookieStore.delete('session');
}
export async function getSession() {
const cookieStore = await cookies();
const session = cookieStore.get('session')?.value;
return await decrypt(session);
}
export async function verifySession() {
const cookieStore = await cookies();
const session = cookieStore.get('session')?.value;
const payload = await decrypt(session);
if (!payload) {
return { isAuth: false, userId: null, role: null };
}
return { isAuth: true, userId: payload.userId, role: payload.role };
}