diff --git a/src/health/health-check.service.ts b/src/health/health-check.service.ts index 467020fbdd2db2b194d8d3aa195f755075cdabf4..22a25c29212c4204502b6d2feb95fa8d0b82ae03 100644 --- a/src/health/health-check.service.ts +++ b/src/health/health-check.service.ts @@ -3,18 +3,17 @@ import { TerminusOptionsFactory, TerminusModuleOptions, DNSHealthIndicator, - MicroserviceHealthIndicator, } from '@nestjs/terminus'; import { Injectable } from '@nestjs/common'; import { ConfigService } from '../configuration/config.service'; -import { Transport } from '@nestjs/microservices'; +import { RedisHealthIndicator } from './redis.healthIndicator'; @Injectable() export class HealthCheckService implements TerminusOptionsFactory { constructor( private _configService: ConfigService, private readonly _dnsHealthIndicator: DNSHealthIndicator, - private readonly _microserviceHealthIndicator: MicroserviceHealthIndicator, + private readonly _redisHealthIndicator: RedisHealthIndicator, ) { } createTerminusOptions(): TerminusModuleOptions { @@ -25,10 +24,7 @@ export class HealthCheckService implements TerminusOptionsFactory { healthIndicators: [ async () => this._dnsHealthIndicator.pingCheck('LegacyAuthService', `${config.legacyAuthServiceUrl}/get_services`), async () => this._dnsHealthIndicator.pingCheck('EmailService', `${config.serviceEmailUrl}/health`), - async () => this._microserviceHealthIndicator.pingCheck('Redis', { - transport: Transport.REDIS, - options: { url: `redis://${config.redis.host}:${config.redis.port}` }, - }), + async () => this._redisHealthIndicator.checkRedisConnection(config.redis), ], }; return { diff --git a/src/health/health.module.ts b/src/health/health.module.ts index 65e11125bf7f2da484760a668b1f46d6305cc9e3..6e3de01e8c67b4b06e58e32ae7ec555bdfab2da1 100644 --- a/src/health/health.module.ts +++ b/src/health/health.module.ts @@ -1,12 +1,19 @@ import { Module } from '@nestjs/common'; import { TerminusModule } from '@nestjs/terminus'; import { HealthCheckService } from './health-check.service'; +import { LegacyModule } from '../legacy/legacy.module'; +import { ConfigModule } from '../configuration/config.module'; +import { RedisHealthIndicator } from './redis.healthIndicator'; @Module({ imports: [ + ConfigModule, TerminusModule.forRootAsync({ + imports: [HealthModule], useClass: HealthCheckService, }), ], + providers: [RedisHealthIndicator], + exports: [RedisHealthIndicator], }) export class HealthModule { } \ No newline at end of file diff --git a/src/health/redis.healthIndicator.ts b/src/health/redis.healthIndicator.ts new file mode 100644 index 0000000000000000000000000000000000000000..733715852c837e1dc22aa8e7e03d595430df2221 --- /dev/null +++ b/src/health/redis.healthIndicator.ts @@ -0,0 +1,32 @@ +import { HealthIndicator } from '@nestjs/terminus/dist/health-indicators/abstract/health-indicator'; +import { HealthIndicatorResult } from '@nestjs/terminus'; +import * as redis from 'redis'; +import * as bluebird from 'bluebird'; +import { HealthCheckError } from '@godaddy/terminus'; +bluebird.promisifyAll(redis); + +export class RedisHealthIndicator extends HealthIndicator { + + async checkRedisConnection(redisConf: { host: string, port: number }): Promise<HealthIndicatorResult> { + + const client = redis.createClient({ + host: redisConf.host, port: redisConf.port, + }); + + await new Promise((resolve, reject) => { + client.on('ready', resolve); + client.on('error', reject); + }).catch((err) => { + client.quit(); + throw new HealthCheckError('Redis connection failed', { + Redis: { + err, + status: 'down', + message: 'Failed to connect to redis', + }, + }); + }); + + return this.getStatus('Redis', true); + } +} \ No newline at end of file diff --git a/src/legacy/encryptionHelpers.ts b/src/legacy/encryptionHelpers.ts index 83f3092cdf66c01270a5d2eb18fd119c24c54a48..23d76db206414de087a6217f3629235831834277 100644 --- a/src/legacy/encryptionHelpers.ts +++ b/src/legacy/encryptionHelpers.ts @@ -9,7 +9,7 @@ export const decrypt = (encrypted: string, privateKey) => { return decrypted; } catch (error) { const logger = new Logger(); - logger.error('Couldn\'t decrypt password', error, 'Decrypt password'); + logger.error('Couldn\'t decrypt password', `${error}`, 'Decrypt password'); throw new UnauthorizedException('Couldn\'t decrypt password'); } } else { diff --git a/src/legacy/legacy.model.ts b/src/legacy/legacy.model.ts index 06b1720d3171c1ba7bed77ba85b79d5397b428b0..48975cb6ca5d2ec6232be95a4fcb4f259c2164d2 100644 --- a/src/legacy/legacy.model.ts +++ b/src/legacy/legacy.model.ts @@ -15,12 +15,6 @@ export class LoginForm { export class UpdatePasswordForm { @ApiModelProperty() @IsString() - @MinLength(6) - @Matches(/^[\u0020-\u007e]*$/) - @Matches(/[~`!#$%\$\(@\)\^&*\.+=\-\[\]\\';,/{}|\\":<>\?]/) - @Matches(/[A-Z]/) - @Matches(/[a-z]/) - @Matches(/[0-9]/) newPassword: string; @ApiModelProperty() @@ -31,12 +25,6 @@ export class UpdatePasswordForm { export class ResetPasswordForm { @ApiModelProperty() @IsString() - @MinLength(6) - @Matches(/^[\u0020-\u007e]*$/) - @Matches(/[~`!#$%\$\(@\)\^&*\.+=\-\[\]\\';,/{}|\\":<>\?]/) - @Matches(/[A-Z]/) - @Matches(/[a-z]/) - @Matches(/[0-9]/) password: string; @ApiModelProperty() @@ -188,12 +176,6 @@ export class UserCreationForm { @ApiModelProperty() @IsString() - @MinLength(6) - @Matches(/^[\u0020-\u007e]*$/) - @Matches(/[~`!#$%\$\(@\)\^&*\.+=\-\[\]\\';,/{}|\\":<>\?]/) - @Matches(/[A-Z]/) - @Matches(/[a-z]/) - @Matches(/[0-9]/) password: string; @ApiModelProperty() @@ -525,12 +507,6 @@ export class PasswordResetForm { @ApiModelProperty() @IsString() - @MinLength(6) - @Matches(/^[\u0020-\u007e]*$/) - @Matches(/[~`!#$%\$\(@\)\^&*\.+=\-\[\]\\';,/{}|\\":<>\?]/) - @Matches(/[A-Z]/) - @Matches(/[a-z]/) - @Matches(/[0-9]/) password: string; } diff --git a/src/legacy/legacy.service.ts b/src/legacy/legacy.service.ts index 471f48d93a89df2850537be6a5c54ca50bc269d0..6af18137c49c46e9e18fb1ada657cc753ada24eb 100644 --- a/src/legacy/legacy.service.ts +++ b/src/legacy/legacy.service.ts @@ -40,12 +40,12 @@ export class LegacyService { try { const decryptedPassword = decrypt(loginForm.password, this.conf.privateKey); let res = await request.post(`${this.conf.legacyAuthServiceUrl}/get_user/`).form( - { + { username: loginForm.username, password: decryptedPassword, } ).catch((error) => { - this.logger.error('Couldn\'t get the user', error, `${LegacyService.name} - ${this.getUser.name}`); + this.logger.error('Couldn\'t get the user', `${error}`, `${LegacyService.name} - ${this.getUser.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t get the user.' }); }); @@ -54,7 +54,7 @@ export class LegacyService { const userInfo = new UserInfoWithEcryptedPassword(res.user, loginForm.password); return userInfo; } else { - this.logger.error('Couldn\'t get the user', res.message, `${LegacyService.name} - ${this.getUser.name}`); + this.logger.error('Couldn\'t get the user', `${res.message}`, `${LegacyService.name} - ${this.getUser.name}`); throw new BadRequestException(res.message); } } catch (err) { @@ -75,9 +75,9 @@ export class LegacyService { username, password, }).catch((error) => { - this.logger.error('Couldn\'t get the user info', error, `${LegacyService.name} - ${this.getUserInfo.name}`); - throw new InternalServerErrorException({ error, message: 'Couldn\'t get the user info.' }); - }); + this.logger.error('Couldn\'t get the user info', `${error}`, `${LegacyService.name} - ${this.getUserInfo.name}`); + throw new InternalServerErrorException({ error, message: 'Couldn\'t get the user info.' }); + }); res = JSON.parse(res); @@ -85,7 +85,7 @@ export class LegacyService { const userInfo = new UserInfo(res.user); return userInfo; } else { - this.logger.error('Couldn\'t get the user info', res.message, `${LegacyService.name} - ${this.getUserInfo.name}`); + this.logger.error('Couldn\'t get the user info', `${res.message}`, `${LegacyService.name} - ${this.getUserInfo.name}`); throw new BadRequestException(res.message); } } catch (err) { @@ -106,10 +106,10 @@ export class LegacyService { { username, password: decryptedOldPassword, - }).catch((error) => { - this.logger.error('Couldn\'t get user.', error, `${LegacyService.name} - ${this.updateUserPassword.name}`); - throw new InternalServerErrorException({ error, message: 'Couldn\'t get user.' }); - }); + }).catch((error) => { + this.logger.error('Couldn\'t get user.', `${error}`, `${LegacyService.name} - ${this.updateUserPassword.name}`); + throw new InternalServerErrorException({ error, message: 'Couldn\'t get user.' }); + }); res = JSON.parse(res); @@ -121,7 +121,7 @@ export class LegacyService { admin_username: this.conf.adminUsername, admin_password: this.conf.adminPassword, }).catch((error) => { - this.logger.error('Couldn\'t update user password.', error, `${LegacyService.name} - ${this.updateUserPassword.name}`); + this.logger.error('Couldn\'t update user password.', `${error}`, `${LegacyService.name} - ${this.updateUserPassword.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t update user password.' }); }); @@ -130,11 +130,11 @@ export class LegacyService { if (res.server_response && res.server_response === 'Success') { return; } else { - this.logger.error('Couldn\'t update user password.', res.message, `${LegacyService.name} - ${this.updateUserPassword.name}`); + this.logger.error('Couldn\'t update user password.', `${res.message}`, `${LegacyService.name} - ${this.updateUserPassword.name}`); throw new BadRequestException(res.message); } } else { - this.logger.error('Couldn\'t update user password.', res.message, `${LegacyService.name} - ${this.updateUserPassword.name}`); + this.logger.error('Couldn\'t update user password.', `${res.message}`, `${LegacyService.name} - ${this.updateUserPassword.name}`); if (res.message === 'Unidentified user') { throw new BadRequestException('unidentifiedUser'); } else { @@ -183,7 +183,6 @@ export class LegacyService { return; } catch (err) { - Logger.error(err); handleError(err, new InternalServerErrorException('Something went wrong.')); } } @@ -202,12 +201,12 @@ export class LegacyService { Logger.log(`User account validation for : ${userInfo.email}`, `${LegacyService.name} - ${this.validateUserAccount.name}`); let res = await request.post(`${this.conf.legacyAuthServiceUrl}/add_user/`).form(userInfo).catch((error) => { - this.logger.error('Couldn\'t create user.', error, `${LegacyService.name} - ${this.validateUserAccount.name}`); + this.logger.error('Couldn\'t create user.', `${error}`, `${LegacyService.name} - ${this.validateUserAccount.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t create user.' }); }); res = JSON.parse(res); - + if (res.server_response && res.server_response === 'Success') { Logger.log(`User account created.`, `${LegacyService.name} - ${this.validateUserAccount.name}`); @@ -215,7 +214,7 @@ export class LegacyService { this.deleteRedisKey(token); return; } else { - this.logger.error('Couldn\'t create user.', res, `${LegacyService.name} - ${this.validateUserAccount.name}`); + this.logger.error('Couldn\'t create user.', `${res}`, `${LegacyService.name} - ${this.validateUserAccount.name}`); if (res.message === 'Error during account creation') { throw new InternalServerErrorException(res.message); } @@ -243,7 +242,7 @@ export class LegacyService { const legacyForm = new LegacyUserUpdateForm(form, token.username, decrypt(token.authzKey, this.conf.privateKey)); let res = await request.post(`${this.conf.legacyAuthServiceUrl}/update_user/`).form(legacyForm).catch((error) => { - this.logger.error('Couldn\'t update user info.', error, `${LegacyService.name} - ${this.updateUserInfo.name}`); + this.logger.error('Couldn\'t update user info.', `${error}`, `${LegacyService.name} - ${this.updateUserInfo.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t update user info.' }); }); @@ -252,7 +251,7 @@ export class LegacyService { if (res.server_response && res.server_response === 'Success') { return; } else { - this.logger.error('Couldn\'t update user.', res.message, `${LegacyService.name} - ${this.updateUserInfo.name}`); + this.logger.error('Couldn\'t update user.', `${res.message}`, `${LegacyService.name} - ${this.updateUserInfo.name}`); if (res.message === 'Unidentified user') { throw new BadRequestException('unidentifiedUser'); } @@ -287,9 +286,9 @@ export class LegacyService { admin_username: this.conf.adminUsername, admin_password: this.conf.adminPassword, }).catch((error) => { - this.logger.error('Couldn\'t update user password.', error, `${LegacyService.name} - ${this.resetPassword.name}`); + this.logger.error('Couldn\'t update user password.', `${error}`, `${LegacyService.name} - ${this.resetPassword.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t update user password.' }); - }); + }); res = JSON.parse(res); @@ -298,7 +297,7 @@ export class LegacyService { await this.deleteRedisKey(form.token); return; } else { - this.logger.error('Couldn\'t update user password.', res.message, `${LegacyService.name} - ${this.resetPassword.name}`); + this.logger.error('Couldn\'t update user password.', `${res.message}`, `${LegacyService.name} - ${this.resetPassword.name}`); throw new BadRequestException(res.message); } } else { @@ -359,9 +358,9 @@ export class LegacyService { this.logger.log('Entering function', `${LegacyService.name} - ${this.getServices.name}`); try { let res = await request.get(`${this.conf.legacyAuthServiceUrl}/get_modes/`).catch((error) => { - this.logger.error('Couldn\'t get the services list.', error, `${LegacyService.name} - ${this.getServices.name}`); + this.logger.error('Couldn\'t get the services list.', `${error}`, `${LegacyService.name} - ${this.getServices.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t get the services list.' }); - }); + }); res = JSON.parse(res); @@ -373,7 +372,7 @@ export class LegacyService { }); return modes; } else { - this.logger.error('Couldn\'t get the services list.', res, `${LegacyService.name} - ${this.getServices.name}`); + this.logger.error('Couldn\'t get the services list.', `${res}`, `${LegacyService.name} - ${this.getServices.name}`); throw new InternalServerErrorException('Couldn\'t get the different modes'); } } catch (err) { @@ -397,9 +396,9 @@ export class LegacyService { // Get the list of the accessible services by the user let res = await request.post(`${this.conf.legacyAuthServiceUrl}/get_user_service/`).form({ username, password }).catch((error) => { - this.logger.error('Couldn\'t get the user`\'s services list.', error, `${LegacyService.name} - ${this.getUserResources.name}`); + this.logger.error('Couldn\'t get the user`\'s services list.', `${error}`, `${LegacyService.name} - ${this.getUserResources.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t get the user`\'s services list.' }); - }); + }); res = JSON.parse(res); @@ -414,7 +413,7 @@ export class LegacyService { } return services; } else { - this.logger.error('Couldn\'t get the user`\'s services list.', res.message, `${LegacyService.name} - ${this.getUserResources.name}`); + this.logger.error('Couldn\'t get the user`\'s services list.', `${res.message}`, `${LegacyService.name} - ${this.getUserResources.name}`); throw new BadRequestException(res.message); } } catch (err) { @@ -430,7 +429,7 @@ export class LegacyService { this.logger.log('Entering function', `${LegacyService.name} - ${this.getRestrictedAccessDatasets.name}`); try { let rawRestrictedService = await request.get(`${this.conf.legacyAuthServiceUrl}/get_services/`).catch((error) => { - this.logger.error('Couldn\'t get the services list.', error, `${LegacyService.name} - ${this.getRestrictedAccessDatasets.name}`); + this.logger.error('Couldn\'t get the services list.', `${error}`, `${LegacyService.name} - ${this.getRestrictedAccessDatasets.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t get the services list.' }); }); @@ -446,7 +445,7 @@ export class LegacyService { return restrictedServices; } else { - this.logger.error('Couldn\'t get the different restricted services.', rawRestrictedService, `${LegacyService.name} - ${this.getRestrictedAccessDatasets.name}`); + this.logger.error('Couldn\'t get the different restricted services.', `${rawRestrictedService}`, `${LegacyService.name} - ${this.getRestrictedAccessDatasets.name}`); throw new InternalServerErrorException('Couldn\'t get the different restricted services.'); } } catch (err) { @@ -487,7 +486,7 @@ export class LegacyService { modes: accessRequest.servicesId.toString(), } ).catch((error) => { - this.logger.error('Couldn\'t request access to the resource.', error, `${LegacyService.name} - ${this.addUserResource.name}`); + this.logger.error('Couldn\'t request access to the resource.', `${error}`, `${LegacyService.name} - ${this.addUserResource.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t request access to the resource.' }); }); @@ -512,7 +511,7 @@ export class LegacyService { accessSuccessfullyRequested.push(`${dataset.datasetName} (${servicesName.toString()})`); } } else { - this.logger.error('Couldn\'t request access to the resource.', res.message, `${LegacyService.name} - ${this.addUserResource.name}`); + this.logger.error('Couldn\'t request access to the resource.', `${res.message}`, `${LegacyService.name} - ${this.addUserResource.name}`); accessUnsuccessfullyRequested.push(`${dataset.datasetName} (${servicesName.toString()})`); } } @@ -693,7 +692,7 @@ export class LegacyService { modes: accessRequest.servicesId.toString(), }, ).catch((error) => { - this.logger.error('Couldn\'t remove access to the resource.', error, `${LegacyService.name} - ${this.deleteUserResource.name}`); + this.logger.error('Couldn\'t remove access to the resource.', `${error}`, `${LegacyService.name} - ${this.deleteUserResource.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t remove access to the resource.' }); }); @@ -781,7 +780,7 @@ export class LegacyService { username: token.username, }, ).catch((error) => { - this.logger.error('Couldn\'t delete user account.', error, `${LegacyService.name} - ${this.deleteUserAccount.name}`); + this.logger.error('Couldn\'t delete user account.', `${error}`, `${LegacyService.name} - ${this.deleteUserAccount.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t delete user account.' }); }); @@ -790,7 +789,7 @@ export class LegacyService { if (res.server_response && res.server_response === 'Success') { return; } else { - this.logger.error('Couldn\'t delete user account.', res.message, `${LegacyService.name} - ${this.deleteUserAccount.name}`); + this.logger.error('Couldn\'t delete user account.', `${res.message}`, `${LegacyService.name} - ${this.deleteUserAccount.name}`); throw new BadRequestException(res.message); } } catch (err) { @@ -816,13 +815,13 @@ export class LegacyService { private async setRedisKeyValue(key: string, value: string, ttl: number): Promise<any> { this.logger.log(`Entering function with params ${key} ${value} ${ttl}`, `${LegacyService.name} - ${this.setRedisKeyValue.name}`); - - const client = this.connectToRedis(); - + let client; try { + client = this.connectToRedis(); + // Set key value with expiration time in seconds const res = await client.setAsync(key, value, 'EX', ttl).catch((error) => { - this.logger.error('Couldn\'t set redis key/value.', error, `${LegacyService.name} - ${this.setRedisKeyValue.name}`); + this.logger.error('Couldn\'t set redis key/value.', `${error}`, `${LegacyService.name} - ${this.setRedisKeyValue.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t set redis key/value.' }); }); @@ -837,13 +836,12 @@ export class LegacyService { private async deleteRedisKey(key: string): Promise<any> { this.logger.log(`Entering function with params ${key}`, `${LegacyService.name} - ${this.deleteRedisKey.name}`); - - const client = this.connectToRedis(); - + let client; try { + client = this.connectToRedis(); // Set key value with expiration time in seconds const res = await client.delAsync(key).catch((error) => { - this.logger.error('Couldn\'t delete redis key/value.', error, `${LegacyService.name} - ${this.deleteRedisKey.name}`); + this.logger.error('Couldn\'t delete redis key/value.', `${error}`, `${LegacyService.name} - ${this.deleteRedisKey.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t delete redis key/value.' }); }); Logger.log(`Removing key/pair, result is: ${res}`, `${LegacyService.name} - ${this.deleteRedisKey.name}`); @@ -857,12 +855,13 @@ export class LegacyService { private async getRedisValueByKey(key: string): Promise<string> { this.logger.log(`Entering function with params ${key}`, `${LegacyService.name} - ${this.getRedisValueByKey.name}`); - - const client = this.connectToRedis(); + let client; try { + client = this.connectToRedis(); + const res = await client.getAsync(key).catch((error) => { - this.logger.error('Couldn\'t get redis value.', error, `${LegacyService.name} - ${this.getRedisValueByKey.name}`); + this.logger.error('Couldn\'t get redis value.', `${error}`, `${LegacyService.name} - ${this.getRedisValueByKey.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t get redis value.' }); }); Logger.log(`Value found: ${res}`, `${LegacyService.name} - ${this.getRedisValueByKey.name}`); @@ -880,7 +879,7 @@ export class LegacyService { const client = redis.createClient({ host: this.conf.redis.host, port: this.conf.redis.port }); client.on('error', (error) => { - this.logger.error('Redis client error.', error, `${LegacyService.name} - ${this.connectToRedis.name}`); + this.logger.error('Redis client error.', `${error}`, `${LegacyService.name} - ${this.connectToRedis.name}`); client.quit(); }); @@ -898,10 +897,10 @@ export class LegacyService { }, }, ).form(emailBody).catch((error) => { - this.logger.error('Couldn\'t send email.', error, `${LegacyService.name} - ${this.sendEmail.name}`); + this.logger.error('Couldn\'t send email.', `${error}`, `${LegacyService.name} - ${this.sendEmail.name}`); throw new InternalServerErrorException({ error, message: 'Couldn\'t send email.' }); }); - } catch(error) { + } catch (error) { handleError(error, new InternalServerErrorException('Couldn\'t send email.')); } } diff --git a/template.env b/template.env index dae0ac0cd45b652a9efa8e96c2163a0dad6a9214..0e0dea673e43dc507679a16c8118bfa521e21426 100644 --- a/template.env +++ b/template.env @@ -8,4 +8,6 @@ USER_SUPPORT_MAILBOX=<user support email address> FRONT_END_URL=<web app url> API_KEY=<api key of the of the service (generated in kong)> ACCESS_TOKEN_COOKIE_KEY=<cookie key where the access token will be stored> -IMAGE_HOST=<host of the images present in the emails body> \ No newline at end of file +IMAGE_HOST=<host of the images present in the emails body> +REDIS_HOST=<redis host> +REDIS_PORT=<redis port> \ No newline at end of file