2025-03-02 17:15:57 +00:00

104 lines
3.3 KiB
TypeScript

import { SignJWT, jwtVerify } from 'jose';
import { v4 as uuidv4 } from 'uuid';
import bcrypt from 'bcryptjs';
import { cookies } from 'next/headers';
// Interface for member credentials
export interface MemberCredential {
memberNumber: string;
password: string; // Hashed password
hasVoted: boolean;
lastLogin?: string; // ISO date string
}
// These functions are now only used server-side in API routes
// Client components should use the API routes instead
// Generate a one-time use token for voting
export async function generateRandomToken(memberNumber?: string): Promise<string> {
// This function is used in API routes
const tokenId = uuidv4();
const payload: any = { tokenId };
// If memberNumber is provided, include it in the token
if (memberNumber) {
payload.memberNumber = memberNumber;
}
// Use a secret key from environment variable or a default one
const secretKey = process.env.JWT_SECRET_KEY || 'schafwaschener-segelverein-secret-key-for-jwt-signing';
const encoder = new TextEncoder();
const key = encoder.encode(secretKey);
const token = await new SignJWT(payload)
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime('7d') // Token expires in 7 days
.sign(key);
return token;
}
// Generate an admin token
async function generateAdminToken(): Promise<string> {
// Use a secret key from environment variable or a default one
const secretKey = process.env.JWT_SECRET_KEY || 'schafwaschener-segelverein-secret-key-for-jwt-signing';
const encoder = new TextEncoder();
const key = encoder.encode(secretKey);
const token = await new SignJWT({ role: 'admin' })
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime('24h') // Admin token expires in 24 hours
.sign(key);
return token;
}
// Verify an admin token
async function verifyAdminToken(): Promise<boolean> {
const token = (await cookies()).get('admin-token')?.value;
if (!token) return false;
try {
// Use a secret key from environment variable or a default one
const secretKey = process.env.JWT_SECRET_KEY || 'schafwaschener-segelverein-secret-key-for-jwt-signing';
const encoder = new TextEncoder();
const key = encoder.encode(secretKey);
const { payload } = await jwtVerify(token, key);
return payload.role === 'admin';
} catch (error) {
console.error('Admin token verification failed:', error);
return false;
}
}
export async function checkAdminAuth(password?: string): Promise<boolean> {
// Get admin password from environment variable or use default for development
const isAuthenticated = await verifyAdminToken();
if (isAuthenticated) return true;
if (password) {
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || 'schafwaschener-segelverein-admin';
if (password === ADMIN_PASSWORD) {
// Password is correct, generate and set admin token
const newAdminToken = await generateAdminToken();
(await cookies()).set('admin-token', newAdminToken);
return true;
}
}
return false;
}
// Hash a password
export function hashPassword(password: string): string {
return bcrypt.hashSync(password, 10);
}
// Compare a password with a hash
export function comparePassword(password: string, hash: string): boolean {
return bcrypt.compareSync(password, hash);
}