Remove todos os logs e refina back-end
This commit is contained in:
@@ -12,11 +12,6 @@ services:
|
|||||||
DATABASE_URL: postgresql://leolitas:L@l321321321@postgres:5432/clipperia?schema=public
|
DATABASE_URL: postgresql://leolitas:L@l321321321@postgres:5432/clipperia?schema=public
|
||||||
networks:
|
networks:
|
||||||
- dokploy-network
|
- dokploy-network
|
||||||
labels:
|
|
||||||
- 'traefik.enable=true'
|
|
||||||
- 'traefik.http.routers.backend.rule=Host(`api.clipperia.com.br`)'
|
|
||||||
- 'traefik.http.routers.backend.entrypoints=websecure'
|
|
||||||
- 'traefik.http.routers.backend.tls.certresolver=letsencrypt'
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
dokploy-network:
|
dokploy-network:
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import { VideosController } from './videos/videos.controller';
|
|||||||
import { UsuariosModule } from './usuarios/usuarios.module';
|
import { UsuariosModule } from './usuarios/usuarios.module';
|
||||||
import { LoggerMiddleware } from './middleware/logger.middleware';
|
import { LoggerMiddleware } from './middleware/logger.middleware';
|
||||||
import { RolesGuard } from './auth/roles.guard';
|
import { RolesGuard } from './auth/roles.guard';
|
||||||
import { TestModule } from './test/test.module';
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -18,7 +17,6 @@ import { TestModule } from './test/test.module';
|
|||||||
VideosModule,
|
VideosModule,
|
||||||
AuthModule,
|
AuthModule,
|
||||||
UsuariosModule,
|
UsuariosModule,
|
||||||
TestModule,
|
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService, RolesGuard],
|
providers: [AppService, RolesGuard],
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
import { Injectable, Logger, UnauthorizedException } from '@nestjs/common';
|
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||||
import { AuthGuard } from '@nestjs/passport';
|
import { AuthGuard } from '@nestjs/passport';
|
||||||
|
|
||||||
import type { JwtPayload } from './keycloak.strategy';
|
import type { JwtPayload } from './keycloak.strategy';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class KeycloakAuthGuard extends AuthGuard('jwt') {
|
export class KeycloakAuthGuard extends AuthGuard('jwt') {
|
||||||
private readonly logger = new Logger(KeycloakAuthGuard.name);
|
|
||||||
|
|
||||||
handleRequest<TUser = JwtPayload>(
|
handleRequest<TUser = JwtPayload>(
|
||||||
err: unknown,
|
err: unknown,
|
||||||
user: JwtPayload | false,
|
user: JwtPayload | false,
|
||||||
info: unknown,
|
info: unknown,
|
||||||
context: import('@nestjs/common').ExecutionContext,
|
context: import('@nestjs/common').ExecutionContext,
|
||||||
): TUser {
|
): TUser {
|
||||||
this.logger.log(`KEYCLOAK_URL: ${process.env.KEYCLOAK_URL}`);
|
|
||||||
this.logger.log(`NODE_ENV: ${process.env.NODE_ENV}`);
|
|
||||||
|
|
||||||
if (err || !user) {
|
if (err || !user) {
|
||||||
if (err instanceof UnauthorizedException) {
|
if (err instanceof UnauthorizedException) {
|
||||||
throw err;
|
throw err;
|
||||||
|
|||||||
@@ -49,71 +49,23 @@ export class KeycloakJwtStrategy extends PassportStrategy(Strategy, 'jwt') {
|
|||||||
issuer: 'https://auth.clipperia.com.br/realms/clipperia',
|
issuer: 'https://auth.clipperia.com.br/realms/clipperia',
|
||||||
ignoreExpiration: false,
|
ignoreExpiration: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.logger.verbose(`Using Keycloak URL: ${baseUrl}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(payload: JwtPayload): JwtPayload {
|
validate(payload: JwtPayload) {
|
||||||
try {
|
try {
|
||||||
this.logger.verbose('=== JWT Validation Start ===');
|
|
||||||
|
|
||||||
this.logger.verbose(`Subject (sub): ${payload.sub}`);
|
|
||||||
this.logger.verbose(`Issuer (iss): ${payload.iss}`);
|
|
||||||
this.logger.verbose(`Audience (aud): ${JSON.stringify(payload.aud)}`);
|
|
||||||
this.logger.verbose(
|
|
||||||
`Issued At (iat): ${new Date(payload.iat * 1000).toISOString()}`,
|
|
||||||
);
|
|
||||||
this.logger.verbose(
|
|
||||||
`Expiration (exp): ${new Date(payload.exp * 1000).toISOString()}`,
|
|
||||||
);
|
|
||||||
this.logger.verbose('--- User Info ---');
|
|
||||||
this.logger.verbose(`Email: ${payload.email || 'N/A'}`);
|
|
||||||
this.logger.verbose(`Username: ${payload.preferred_username || 'N/A'}`);
|
|
||||||
this.logger.verbose(
|
|
||||||
`Name: ${payload.given_name || ''} ${payload.family_name || ''}`.trim() ||
|
|
||||||
'N/A',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Realm roles
|
|
||||||
this.logger.verbose('--- Realm Access ---');
|
|
||||||
if (payload.realm_access?.roles?.length) {
|
|
||||||
payload.realm_access.roles.forEach((role: string) => {
|
|
||||||
this.logger.verbose(`- ${role}`);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.logger.verbose('No realm roles found');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resource access
|
|
||||||
this.logger.verbose('--- Resource Access ---');
|
|
||||||
if (payload.resource_access) {
|
|
||||||
Object.entries(payload.resource_access).forEach(([resource, data]) => {
|
|
||||||
if (data?.roles?.length) {
|
|
||||||
this.logger.verbose(`${resource} roles:`);
|
|
||||||
data.roles.forEach((role: string) => {
|
|
||||||
this.logger.verbose(` - ${role}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.logger.verbose('No resource access found');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Token expiration check
|
|
||||||
const now = Math.floor(Date.now() / 1000);
|
const now = Math.floor(Date.now() / 1000);
|
||||||
|
|
||||||
if (payload.exp < now) {
|
if (payload.exp < now) {
|
||||||
const minutesAgo = Math.round((now - payload.exp) / 60);
|
|
||||||
this.logger.warn(`Token expired ${minutesAgo} minutes ago`);
|
|
||||||
throw new UnauthorizedException('Token expirado');
|
throw new UnauthorizedException('Token expirado');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.verbose('=== JWT Validation Successful ===');
|
|
||||||
return payload;
|
return payload;
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = error instanceof Error ? error.stack : String(error);
|
const errorMessage = error instanceof Error ? error.stack : String(error);
|
||||||
|
|
||||||
this.logger.error('JWT Validation Error:', errorMessage);
|
this.logger.error('JWT Validation Error:', errorMessage);
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
return payload;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
CanActivate,
|
CanActivate,
|
||||||
ExecutionContext,
|
ExecutionContext,
|
||||||
ForbiddenException,
|
ForbiddenException,
|
||||||
Logger,
|
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { Reflector } from '@nestjs/core';
|
import { Reflector } from '@nestjs/core';
|
||||||
import { ROLES_KEY } from './decorator/roles.decorator';
|
import { ROLES_KEY } from './decorator/roles.decorator';
|
||||||
@@ -14,38 +13,22 @@ import type { JwtPayload } from './keycloak.strategy';
|
|||||||
export class RolesGuard implements CanActivate {
|
export class RolesGuard implements CanActivate {
|
||||||
constructor(private reflector: Reflector) {}
|
constructor(private reflector: Reflector) {}
|
||||||
|
|
||||||
private readonly logger = new Logger(RolesGuard.name);
|
|
||||||
|
|
||||||
private extractRoles(user: JwtPayload): string[] {
|
private extractRoles(user: JwtPayload): string[] {
|
||||||
const roles: string[] = [];
|
const roles: string[] = [];
|
||||||
|
|
||||||
this.logger.log('Extracting roles from user object');
|
|
||||||
this.logger.log(`realm_access: ${JSON.stringify(user.realm_access)}`);
|
|
||||||
this.logger.log(`resource_access: ${JSON.stringify(user.resource_access)}`);
|
|
||||||
|
|
||||||
if (user.realm_access?.roles) {
|
if (user.realm_access?.roles) {
|
||||||
this.logger.log(
|
|
||||||
`Found realm roles: ${JSON.stringify(user.realm_access.roles)}`,
|
|
||||||
);
|
|
||||||
roles.push(...user.realm_access.roles);
|
roles.push(...user.realm_access.roles);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.resource_access) {
|
if (user.resource_access) {
|
||||||
this.logger.log('Processing resource_access');
|
Object.entries(user.resource_access).forEach(([, resource]) => {
|
||||||
Object.entries(user.resource_access).forEach(
|
if (resource?.roles) {
|
||||||
([resourceName, resource]) => {
|
roles.push(...resource.roles);
|
||||||
this.logger.log(
|
}
|
||||||
`Resource ${resourceName} roles: ${JSON.stringify(resource?.roles)}`,
|
});
|
||||||
);
|
|
||||||
if (resource?.roles) {
|
|
||||||
roles.push(...resource.roles);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const uniqueRoles = [...new Set(roles)];
|
const uniqueRoles = [...new Set(roles)];
|
||||||
this.logger.log(`Final extracted roles: ${JSON.stringify(uniqueRoles)}`);
|
|
||||||
return uniqueRoles;
|
return uniqueRoles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,22 +38,14 @@ export class RolesGuard implements CanActivate {
|
|||||||
[context.getHandler(), context.getClass()],
|
[context.getHandler(), context.getClass()],
|
||||||
);
|
);
|
||||||
|
|
||||||
this.logger.log(`Required roles: ${JSON.stringify(requiredRoles)}`);
|
|
||||||
|
|
||||||
if (!requiredRoles || !requiredRoles.length) {
|
if (!requiredRoles || !requiredRoles.length) {
|
||||||
this.logger.log('No roles required for this route');
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const request = context.switchToHttp().getRequest<{ user: JwtPayload }>();
|
const request = context.switchToHttp().getRequest<{ user: JwtPayload }>();
|
||||||
const user = request.user;
|
const user = request.user;
|
||||||
|
|
||||||
this.logger.log(
|
|
||||||
`User object from request: ${JSON.stringify(user, null, 2)}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
this.logger.error('No user found in request');
|
|
||||||
throw new ForbiddenException('Usuário não autenticado');
|
throw new ForbiddenException('Usuário não autenticado');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
import { Test, TestingModule } from '@nestjs/testing';
|
|
||||||
import { TestController } from './test.controller';
|
|
||||||
|
|
||||||
describe('TestController', () => {
|
|
||||||
let controller: TestController;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
|
||||||
controllers: [TestController],
|
|
||||||
}).compile();
|
|
||||||
|
|
||||||
controller = module.get<TestController>(TestController);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be defined', () => {
|
|
||||||
expect(controller).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import { Controller, Get, Req } from '@nestjs/common';
|
|
||||||
import type { Request } from 'express';
|
|
||||||
|
|
||||||
@Controller('test')
|
|
||||||
export class TestController {
|
|
||||||
@Get()
|
|
||||||
debug(@Req() req: Request): string {
|
|
||||||
console.log('HEADERS:', req.headers);
|
|
||||||
|
|
||||||
return JSON.stringify(req.headers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { TestController } from './test.controller';
|
|
||||||
import { TestService } from './test.service';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
controllers: [TestController],
|
|
||||||
providers: [TestService]
|
|
||||||
})
|
|
||||||
export class TestModule {}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import { Test, TestingModule } from '@nestjs/testing';
|
|
||||||
import { TestService } from './test.service';
|
|
||||||
|
|
||||||
describe('TestService', () => {
|
|
||||||
let service: TestService;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
|
||||||
providers: [TestService],
|
|
||||||
}).compile();
|
|
||||||
|
|
||||||
service = module.get<TestService>(TestService);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be defined', () => {
|
|
||||||
expect(service).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class TestService {}
|
|
||||||
Reference in New Issue
Block a user