Added environment config. Added logging serializers. Updated logs to use serializers.
This commit is contained in:
@ -11,6 +11,7 @@ import { UsersModule } from './users/users.module';
|
|||||||
import { UserEntity } from './users/users.entity';
|
import { UserEntity } from './users/users.entity';
|
||||||
import { AuthModule } from './auth/auth.module';
|
import { AuthModule } from './auth/auth.module';
|
||||||
import { LoggerModule } from 'nestjs-pino';
|
import { LoggerModule } from 'nestjs-pino';
|
||||||
|
import { serialize_token, serialize_user_short, serialize_user_long, serialize_res, serialize_req } from './logging.serializers';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@ -30,6 +31,19 @@ import { LoggerModule } from 'nestjs-pino';
|
|||||||
pinoHttp: {
|
pinoHttp: {
|
||||||
level: config.get('LOG_LEVEL') ?? 'info',
|
level: config.get('LOG_LEVEL') ?? 'info',
|
||||||
autoLogging: true,
|
autoLogging: true,
|
||||||
|
serializers: config.get('ENVIRONMENT', 'production') == 'development' ? {
|
||||||
|
user: value => serialize_user_long(value),
|
||||||
|
access_token: value => serialize_token(value),
|
||||||
|
refresh_token: value => serialize_token(value),
|
||||||
|
req: value => serialize_req(value),
|
||||||
|
res: value => serialize_res(value),
|
||||||
|
} : {
|
||||||
|
user: value => serialize_user_short(value),
|
||||||
|
access_token: value => serialize_token(value),
|
||||||
|
refresh_token: value => serialize_token(value),
|
||||||
|
req: value => serialize_req(value),
|
||||||
|
res: value => serialize_res(value),
|
||||||
|
},
|
||||||
stream: pino.destination({
|
stream: pino.destination({
|
||||||
dest: path.join(config.get('LOG_DIRECTORY') ?? 'logs', 'backend.api.log'),
|
dest: path.join(config.get('LOG_DIRECTORY') ?? 'logs', 'backend.api.log'),
|
||||||
minLength: 512,
|
minLength: 512,
|
||||||
|
@ -34,7 +34,9 @@ export class AuthAccessService {
|
|||||||
this.logger.debug({
|
this.logger.debug({
|
||||||
class: AuthAccessService.name,
|
class: AuthAccessService.name,
|
||||||
method: this.generate.name,
|
method: this.generate.name,
|
||||||
user_login: user.userLogin,
|
user,
|
||||||
|
access_token: token,
|
||||||
|
exp: expiration,
|
||||||
msg: 'User generated an access token.',
|
msg: 'User generated an access token.',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ export class AuthController {
|
|||||||
this.logger.error({
|
this.logger.error({
|
||||||
class: AuthController.name,
|
class: AuthController.name,
|
||||||
method: this.login.name,
|
method: this.login.name,
|
||||||
|
user: req.user,
|
||||||
msg: 'Failed to login.',
|
msg: 'Failed to login.',
|
||||||
error: err,
|
error: err,
|
||||||
});
|
});
|
||||||
@ -62,7 +63,9 @@ export class AuthController {
|
|||||||
this.logger.info({
|
this.logger.info({
|
||||||
class: AuthController.name,
|
class: AuthController.name,
|
||||||
method: this.login.name,
|
method: this.login.name,
|
||||||
user_login: req.user.userLogin,
|
user: req.user,
|
||||||
|
access_token: data.access_token,
|
||||||
|
refresh_token: data.refresh_token,
|
||||||
msg: 'User logged in.',
|
msg: 'User logged in.',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -87,7 +90,7 @@ export class AuthController {
|
|||||||
this.logger.info({
|
this.logger.info({
|
||||||
class: AuthController.name,
|
class: AuthController.name,
|
||||||
method: this.logout.name,
|
method: this.logout.name,
|
||||||
user_login: req.user.userLogin,
|
user: req.user,
|
||||||
msg: 'User logged off',
|
msg: 'User logged off',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -112,6 +115,8 @@ export class AuthController {
|
|||||||
this.logger.debug({
|
this.logger.debug({
|
||||||
class: AuthController.name,
|
class: AuthController.name,
|
||||||
method: this.refresh.name,
|
method: this.refresh.name,
|
||||||
|
user: req.user,
|
||||||
|
access_token: data.access_token,
|
||||||
msg: 'Updated Authentication cookie for access token.',
|
msg: 'Updated Authentication cookie for access token.',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -124,6 +129,8 @@ export class AuthController {
|
|||||||
this.logger.debug({
|
this.logger.debug({
|
||||||
class: AuthController.name,
|
class: AuthController.name,
|
||||||
method: this.refresh.name,
|
method: this.refresh.name,
|
||||||
|
user: req.user,
|
||||||
|
refresh_token: data.refresh_token,
|
||||||
msg: 'Updated Refresh cookie for refresh token.',
|
msg: 'Updated Refresh cookie for refresh token.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -133,6 +140,7 @@ export class AuthController {
|
|||||||
this.logger.error({
|
this.logger.error({
|
||||||
class: AuthController.name,
|
class: AuthController.name,
|
||||||
method: this.refresh.name,
|
method: this.refresh.name,
|
||||||
|
user: req.user,
|
||||||
msg: 'Failed to refresh tokens.',
|
msg: 'Failed to refresh tokens.',
|
||||||
error: err,
|
error: err,
|
||||||
});
|
});
|
||||||
@ -158,7 +166,7 @@ export class AuthController {
|
|||||||
this.logger.info({
|
this.logger.info({
|
||||||
class: AuthController.name,
|
class: AuthController.name,
|
||||||
method: this.register.name,
|
method: this.register.name,
|
||||||
user_login: user.userLogin,
|
user: req.user,
|
||||||
msg: 'User registered',
|
msg: 'User registered',
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -167,6 +175,7 @@ export class AuthController {
|
|||||||
this.logger.warn({
|
this.logger.warn({
|
||||||
class: AuthController.name,
|
class: AuthController.name,
|
||||||
method: this.register.name,
|
method: this.register.name,
|
||||||
|
user: req.user,
|
||||||
msg: 'Failed to register due to duplicate userLogin.',
|
msg: 'Failed to register due to duplicate userLogin.',
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
@ -178,6 +187,7 @@ export class AuthController {
|
|||||||
this.logger.error({
|
this.logger.error({
|
||||||
class: AuthController.name,
|
class: AuthController.name,
|
||||||
method: this.register.name,
|
method: this.register.name,
|
||||||
|
user: req.user,
|
||||||
msg: 'Failed to register.',
|
msg: 'Failed to register.',
|
||||||
error: err,
|
error: err,
|
||||||
});
|
});
|
||||||
@ -190,6 +200,14 @@ export class AuthController {
|
|||||||
try {
|
try {
|
||||||
data = await this.auth.login(user);
|
data = await this.auth.login(user);
|
||||||
if (!data.access_token || !data.refresh_token || !data.refresh_exp) {
|
if (!data.access_token || !data.refresh_token || !data.refresh_exp) {
|
||||||
|
this.logger.error({
|
||||||
|
class: AuthController.name,
|
||||||
|
method: this.register.name,
|
||||||
|
user: req.user,
|
||||||
|
access_token: data.access_token,
|
||||||
|
refresh_token: data.refresh_token,
|
||||||
|
msg: 'Failed to generate tokens after registering.',
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error_message: 'Something went wrong with tokens while logging in.',
|
error_message: 'Something went wrong with tokens while logging in.',
|
||||||
@ -199,6 +217,7 @@ export class AuthController {
|
|||||||
this.logger.error({
|
this.logger.error({
|
||||||
class: AuthController.name,
|
class: AuthController.name,
|
||||||
method: this.register.name,
|
method: this.register.name,
|
||||||
|
user: req.user,
|
||||||
msg: 'Failed to login after registering.',
|
msg: 'Failed to login after registering.',
|
||||||
error: err,
|
error: err,
|
||||||
});
|
});
|
||||||
|
@ -29,6 +29,8 @@ export class AuthRefreshService {
|
|||||||
this.logger.warn({
|
this.logger.warn({
|
||||||
class: AuthRefreshService.name,
|
class: AuthRefreshService.name,
|
||||||
method: this.generate.name,
|
method: this.generate.name,
|
||||||
|
user,
|
||||||
|
refresh_token: refreshToken,
|
||||||
msg: 'Refresh token given is invalid.',
|
msg: 'Refresh token given is invalid.',
|
||||||
});
|
});
|
||||||
throw new UnauthorizedException('Invalid refresh token.');
|
throw new UnauthorizedException('Invalid refresh token.');
|
||||||
@ -37,6 +39,9 @@ export class AuthRefreshService {
|
|||||||
this.logger.warn({
|
this.logger.warn({
|
||||||
class: AuthRefreshService.name,
|
class: AuthRefreshService.name,
|
||||||
method: this.generate.name,
|
method: this.generate.name,
|
||||||
|
user,
|
||||||
|
refresh_token: refreshToken,
|
||||||
|
exp: expiration,
|
||||||
msg: 'Refresh token given has expired.',
|
msg: 'Refresh token given has expired.',
|
||||||
});
|
});
|
||||||
throw new UnauthorizedException('Invalid refresh token.');
|
throw new UnauthorizedException('Invalid refresh token.');
|
||||||
@ -61,6 +66,9 @@ export class AuthRefreshService {
|
|||||||
this.logger.debug({
|
this.logger.debug({
|
||||||
class: AuthRefreshService.name,
|
class: AuthRefreshService.name,
|
||||||
method: this.generate.name,
|
method: this.generate.name,
|
||||||
|
user,
|
||||||
|
refresh_token: refreshToken,
|
||||||
|
exp: expiration,
|
||||||
msg: 'Deleted previous refresh token.',
|
msg: 'Deleted previous refresh token.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -83,6 +91,9 @@ export class AuthRefreshService {
|
|||||||
this.logger.debug({
|
this.logger.debug({
|
||||||
class: AuthRefreshService.name,
|
class: AuthRefreshService.name,
|
||||||
method: this.generate.name,
|
method: this.generate.name,
|
||||||
|
user,
|
||||||
|
refresh_token: refreshToken,
|
||||||
|
exp: expiration,
|
||||||
msg: 'Generated a new refresh token.',
|
msg: 'Generated a new refresh token.',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -95,6 +106,9 @@ export class AuthRefreshService {
|
|||||||
this.logger.debug({
|
this.logger.debug({
|
||||||
class: AuthRefreshService.name,
|
class: AuthRefreshService.name,
|
||||||
method: this.generate.name,
|
method: this.generate.name,
|
||||||
|
user,
|
||||||
|
refresh_token: refreshToken,
|
||||||
|
exp: expiration,
|
||||||
msg: 'Inserted the new refresh token.',
|
msg: 'Inserted the new refresh token.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
64
backend/nestjs-seshat-api/src/logging.serializers.ts
Normal file
64
backend/nestjs-seshat-api/src/logging.serializers.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { UserEntity } from "./users/users.entity";
|
||||||
|
|
||||||
|
export function serialize_user_short(value: UserEntity) {
|
||||||
|
if (!value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.userLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function serialize_user_long(value: UserEntity) {
|
||||||
|
if (!value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
user_id: value.userId,
|
||||||
|
user_login: value.userLogin,
|
||||||
|
is_admin: value.isAdmin,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function serialize_token(value: string) {
|
||||||
|
return '...' + value.substring(Math.max(value.length - 12, value.length / 2) | 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function serialize_req(value) {
|
||||||
|
if (!value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete value['remoteAddress']
|
||||||
|
delete value['remotePort']
|
||||||
|
|
||||||
|
if (value.headers) {
|
||||||
|
const headers = value.headers;
|
||||||
|
if (headers['Authorization']) {
|
||||||
|
headers['Authorization'] = headers['Authorization'].substring(Math.max(0, headers['Authorization'].length - 12))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function serialize_res(value) {
|
||||||
|
if (!value || !value.headers) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = value.headers;
|
||||||
|
delete headers['x-powered-by'];
|
||||||
|
|
||||||
|
if (headers['set-cookie']) {
|
||||||
|
const cookies = headers['set-cookie'];
|
||||||
|
for (let i in cookies) {
|
||||||
|
const cookie: string = cookies[i];
|
||||||
|
if (cookie.startsWith('Authentication=')) {
|
||||||
|
cookies[i] = 'Authentication=...' + cookie.substring(Math.max(0, cookie.indexOf(';') - 12));
|
||||||
|
} else if (cookie.startsWith('Refresh=')) {
|
||||||
|
cookies[i] = 'Refresh=...' + cookie.substring(Math.max(0, cookie.indexOf(';') - 12));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
Reference in New Issue
Block a user