initial commit
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
51
src/middleware/auth.ts
Normal file
51
src/middleware/auth.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { FastifyRequest, FastifyReply } from 'fastify';
|
||||
import { verifyAccessToken } from '../services/auth';
|
||||
import { error } from '../utils/response';
|
||||
import { AuthData } from '../types';
|
||||
|
||||
export async function requireAuth(
|
||||
request: FastifyRequest,
|
||||
reply: FastifyReply,
|
||||
): Promise<void> {
|
||||
const authHeader = request.headers.authorization;
|
||||
if (!authHeader?.startsWith('Bearer ')) {
|
||||
return error(reply, 'Vyžadována autentizace', 401);
|
||||
}
|
||||
|
||||
const token = authHeader.slice(7);
|
||||
const authData = await verifyAccessToken(token);
|
||||
|
||||
if (!authData) {
|
||||
return error(reply, 'Neplatný nebo expirovaný token', 401);
|
||||
}
|
||||
|
||||
request.authData = authData;
|
||||
}
|
||||
|
||||
export async function optionalAuth(
|
||||
request: FastifyRequest,
|
||||
_reply: FastifyReply,
|
||||
): Promise<void> {
|
||||
const authHeader = request.headers.authorization;
|
||||
if (!authHeader?.startsWith('Bearer ')) return;
|
||||
|
||||
const token = authHeader.slice(7);
|
||||
request.authData = (await verifyAccessToken(token)) ?? undefined;
|
||||
}
|
||||
|
||||
export function requirePermission(...permissionNames: string[]) {
|
||||
return async (request: FastifyRequest, reply: FastifyReply): Promise<void> => {
|
||||
await requireAuth(request, reply);
|
||||
if (reply.sent) return;
|
||||
|
||||
const authData = request.authData!;
|
||||
|
||||
// Admin has all permissions
|
||||
if (authData.roleName === 'admin') return;
|
||||
|
||||
const hasAll = permissionNames.every((p) => authData.permissions.includes(p));
|
||||
if (!hasAll) {
|
||||
return error(reply, 'Nedostatečná oprávnění', 403);
|
||||
}
|
||||
};
|
||||
}
|
||||
15
src/middleware/security.ts
Normal file
15
src/middleware/security.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { FastifyReply, FastifyRequest } from 'fastify';
|
||||
import { config } from '../config/env';
|
||||
|
||||
export async function securityHeaders(
|
||||
_request: FastifyRequest,
|
||||
reply: FastifyReply,
|
||||
): Promise<void> {
|
||||
reply.header('X-Content-Type-Options', 'nosniff');
|
||||
reply.header('X-Frame-Options', 'DENY');
|
||||
reply.header('Referrer-Policy', 'strict-origin-when-cross-origin');
|
||||
|
||||
if (config.isProduction) {
|
||||
reply.header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user