2025-12-11 10:40:55 +01:00
|
|
|
/*
|
2026-01-12 15:00:36 +01:00
|
|
|
* Copyright (c) 2026 by Christian Kellner.
|
2025-12-11 10:40:55 +01:00
|
|
|
* Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause
|
|
|
|
|
*/
|
|
|
|
|
|
2023-03-13 13:42:43 +01:00
|
|
|
import * as userStorage from '../services/storage/userStorage.js';
|
2026-04-27 16:56:04 +02:00
|
|
|
|
2026-03-31 13:33:01 +02:00
|
|
|
const SESSION_MAX_AGE = 2 * 60 * 60 * 1000; // 2 hours
|
2026-04-27 16:56:04 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true when the request has no valid, non-expired session.
|
|
|
|
|
* @param {import('fastify').FastifyRequest} request
|
|
|
|
|
* @returns {boolean}
|
|
|
|
|
*/
|
|
|
|
|
export function isUnauthorized(request) {
|
|
|
|
|
if (!request.session?.currentUser) return true;
|
|
|
|
|
if (Date.now() - (request.session.createdAt || 0) > SESSION_MAX_AGE) return true;
|
2026-03-31 13:33:01 +02:00
|
|
|
return false;
|
2026-04-27 16:56:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true when the session belongs to an admin user.
|
|
|
|
|
* @param {import('fastify').FastifyRequest} request
|
|
|
|
|
* @returns {boolean}
|
|
|
|
|
*/
|
|
|
|
|
export function isAdmin(request) {
|
|
|
|
|
if (isUnauthorized(request)) return false;
|
|
|
|
|
const user = userStorage.getUser(request.session.currentUser);
|
|
|
|
|
return user != null && user.isAdmin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fastify preHandler hook - rejects unauthenticated requests with 401.
|
|
|
|
|
* @param {import('fastify').FastifyRequest} request
|
|
|
|
|
* @param {import('fastify').FastifyReply} reply
|
|
|
|
|
*/
|
|
|
|
|
export async function authHook(request, reply) {
|
|
|
|
|
if (isUnauthorized(request)) {
|
|
|
|
|
reply.code(401).send();
|
2021-01-21 16:09:23 +01:00
|
|
|
}
|
2026-04-27 16:56:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fastify preHandler hook - rejects non-admin requests with 401.
|
|
|
|
|
* Apply after authHook.
|
|
|
|
|
* @param {import('fastify').FastifyRequest} request
|
|
|
|
|
* @param {import('fastify').FastifyReply} reply
|
|
|
|
|
*/
|
|
|
|
|
export async function adminHook(request, reply) {
|
|
|
|
|
if (!isAdmin(request)) {
|
|
|
|
|
reply.code(401).send();
|
|
|
|
|
}
|
|
|
|
|
}
|