aboutsummaryrefslogtreecommitdiff
path: root/api/src/plugins/auth.plugin.ts
diff options
context:
space:
mode:
authorzwlucas <lucas.fariamo08@gmail.com>2026-07-25 21:23:29 +0000
committerzwlucas <lucas.fariamo08@gmail.com>2026-07-25 21:23:29 +0000
commitef55d9bb24430610b60c1b77821307cd72c08c55 (patch)
treee6935a810b34370b0a4c821e55f6397aac50c832 /api/src/plugins/auth.plugin.ts
downloadhelpdesk-ef55d9bb24430610b60c1b77821307cd72c08c55.tar.gz
helpdesk-ef55d9bb24430610b60c1b77821307cd72c08c55.zip
feat: upload of the projectHEADmaster
Signed-off-by: zwlucas <lucas.fariamo08@gmail.com>
Diffstat (limited to 'api/src/plugins/auth.plugin.ts')
-rw-r--r--api/src/plugins/auth.plugin.ts93
1 files changed, 93 insertions, 0 deletions
diff --git a/api/src/plugins/auth.plugin.ts b/api/src/plugins/auth.plugin.ts
new file mode 100644
index 0000000..0e6718a
--- /dev/null
+++ b/api/src/plugins/auth.plugin.ts
@@ -0,0 +1,93 @@
+/**
+ * auth.plugin.ts
+ *
+ * Registra o @fastify/jwt e expõe dois decoradores:
+ * fastify.authenticate → rejeita requests sem token válido (401)
+ * fastify.optionalAuthenticate → injeta o usuário se houver token, mas não falha
+ *
+ * Uso nas rotas:
+ * { preHandler: [fastify.authenticate] }
+ */
+
+import fp from 'fastify-plugin';
+import jwt from '@fastify/jwt';
+import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
+
+// ─── Payload do token ─────────────────────────────────────────────────────────
+
+export interface JwtPayload {
+ id: number;
+ email: string;
+ role: 'requester' | 'agent' | 'admin';
+}
+
+// ─── Augmentação de tipos Fastify ─────────────────────────────────────────────
+
+declare module 'fastify' {
+ interface FastifyInstance {
+ authenticate: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
+ optionalAuthenticate: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
+ }
+ interface FastifyRequest {
+ user: JwtPayload;
+ }
+}
+
+declare module '@fastify/jwt' {
+ interface FastifyJWT {
+ payload: JwtPayload;
+ user: JwtPayload;
+ }
+}
+
+// ─── Plugin ───────────────────────────────────────────────────────────────────
+
+async function authPlugin(fastify: FastifyInstance): Promise<void> {
+ const secret = process.env['JWT_SECRET'];
+ if (!secret) {
+ throw new Error('JWT_SECRET não definido. Verifique o arquivo .env');
+ }
+
+ await fastify.register(jwt, {
+ secret,
+ sign: {
+ expiresIn: process.env['JWT_EXPIRES_IN'] ?? '7d',
+ },
+ });
+
+ // ── authenticate ────────────────────────────────────────────────────────────
+ // Exige token válido — retorna 401 se ausente ou expirado
+ fastify.decorate(
+ 'authenticate',
+ async (request: FastifyRequest, reply: FastifyReply) => {
+ try {
+ // Suporte para SSE (EventSource não envia headers, envia via query string)
+ const query = request.query as { token?: string };
+ if (query.token && !request.headers.authorization) {
+ request.headers.authorization = `Bearer ${query.token}`;
+ }
+ await request.jwtVerify();
+ } catch {
+ await reply.unauthorized('Token inválido ou expirado. Faça login novamente.');
+ }
+ },
+ );
+
+ // ── optionalAuthenticate ────────────────────────────────────────────────────
+ // Tenta verificar o token mas não falha se ausente
+ fastify.decorate(
+ 'optionalAuthenticate',
+ async (request: FastifyRequest, _reply: FastifyReply) => {
+ try {
+ await request.jwtVerify();
+ } catch {
+ // Sem token → request.user fica undefined — trate no controller
+ }
+ },
+ );
+}
+
+export default fp(authPlugin, {
+ name: 'auth-plugin',
+ fastify: '4.x',
+});