diff --git a/src/app.module.ts b/src/app.module.ts index c95d1bf..0b5fd4a 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -18,6 +18,8 @@ import { UserNotificationModule } from './user-notification/user-notification.mo import { DeviceMessagesSubscriptionModule } from './device-messages/device-messages.module'; import { SceneModule } from './scene/scene.module'; import { DoorLockModule } from './door-lock/door.lock.module'; +import { APP_INTERCEPTOR } from '@nestjs/core'; +import { LoggingInterceptor } from './interceptors/logging.interceptor'; @Module({ imports: [ ConfigModule.forRoot({ @@ -42,5 +44,11 @@ import { DoorLockModule } from './door-lock/door.lock.module'; DoorLockModule, ], controllers: [AuthenticationController], + providers: [ + { + provide: APP_INTERCEPTOR, + useClass: LoggingInterceptor, + }, + ], }) export class AuthModule {} diff --git a/src/interceptors/logging.interceptor.ts b/src/interceptors/logging.interceptor.ts new file mode 100644 index 0000000..9e06186 --- /dev/null +++ b/src/interceptors/logging.interceptor.ts @@ -0,0 +1,63 @@ +import { + Injectable, + NestInterceptor, + ExecutionContext, + CallHandler, +} from '@nestjs/common'; +import { Observable, throwError } from 'rxjs'; +import { map, catchError } from 'rxjs/operators'; + +@Injectable() +export class LoggingInterceptor implements NestInterceptor { + intercept(context: ExecutionContext, next: CallHandler): Observable { + const request = context.switchToHttp().getRequest(); + const { method, url, body } = request; + + return next.handle().pipe( + map((response) => { + // Filter out sensitive fields from the request body for logging + const filteredRequestBody = this.filterSensitiveFields(body); + console.log( + '-------------------------------------------------------------------', + ); + console.log(`Request Method: ${method}`); + console.log(`Request URL: ${url}`); + if ( + filteredRequestBody && + Object.keys(filteredRequestBody).length > 0 + ) { + console.log(`Request Body: ${JSON.stringify(filteredRequestBody)}`); + } + // Filter out sensitive fields from the response for logging + const filteredResponse = this.filterSensitiveFields(response); + console.log(`Response: ${JSON.stringify(filteredResponse)}`); + return response; // Return the actual response unmodified + }), + catchError((error) => { + // Do not log anything if there is an error + return throwError(error); + }), + ); + } + + private filterSensitiveFields(data: any): any { + const blacklist = ['password', 'refreshToken', 'accessToken', 'otp']; + + if (data && typeof data === 'object' && !Array.isArray(data)) { + return Object.keys(data).reduce((acc, key) => { + if (blacklist.includes(key)) { + acc[key] = '[FILTERED]'; + } else if (typeof data[key] === 'object' && data[key] !== null) { + acc[key] = this.filterSensitiveFields(data[key]); + } else { + acc[key] = data[key]; + } + return acc; + }, {}); + } else if (Array.isArray(data)) { + return data.map((item) => this.filterSensitiveFields(item)); + } + + return data; + } +}