@lenne.tech/nest-server 10.0.0 → 10.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.env.js +29 -17
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/args/filter.args.js +3 -3
- package/dist/core/common/args/filter.args.js.map +1 -1
- package/dist/core/common/args/pagination.args.js +6 -6
- package/dist/core/common/args/pagination.args.js.map +1 -1
- package/dist/core/common/decorators/restricted.decorator.js +15 -17
- package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
- package/dist/core/common/filters/http-exception-log.filter.js +1 -3
- package/dist/core/common/filters/http-exception-log.filter.js.map +1 -1
- package/dist/core/common/helpers/db.helper.js +14 -14
- package/dist/core/common/helpers/db.helper.js.map +1 -1
- package/dist/core/common/helpers/file.helper.js +2 -2
- package/dist/core/common/helpers/file.helper.js.map +1 -1
- package/dist/core/common/helpers/filter.helper.d.ts +2 -2
- package/dist/core/common/helpers/filter.helper.js +1 -1
- package/dist/core/common/helpers/filter.helper.js.map +1 -1
- package/dist/core/common/helpers/graphql.helper.js +1 -1
- package/dist/core/common/helpers/graphql.helper.js.map +1 -1
- package/dist/core/common/helpers/input.helper.js +31 -38
- package/dist/core/common/helpers/input.helper.js.map +1 -1
- package/dist/core/common/helpers/model.helper.js +7 -7
- package/dist/core/common/helpers/model.helper.js.map +1 -1
- package/dist/core/common/helpers/service.helper.js +2 -2
- package/dist/core/common/helpers/service.helper.js.map +1 -1
- package/dist/core/common/inputs/combined-filter.input.js +3 -3
- package/dist/core/common/inputs/combined-filter.input.js.map +1 -1
- package/dist/core/common/inputs/core-input.input.js +1 -1
- package/dist/core/common/inputs/core-input.input.js.map +1 -1
- package/dist/core/common/inputs/filter.input.js +3 -3
- package/dist/core/common/inputs/filter.input.js.map +1 -1
- package/dist/core/common/inputs/single-filter.input.js +4 -4
- package/dist/core/common/inputs/single-filter.input.js.map +1 -1
- package/dist/core/common/inputs/sort.input.js +1 -1
- package/dist/core/common/inputs/sort.input.js.map +1 -1
- package/dist/core/common/interceptors/check-security.interceptor.d.ts +1 -1
- package/dist/core/common/interceptors/check-security.interceptor.js +2 -2
- package/dist/core/common/interceptors/check-security.interceptor.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +27 -0
- package/dist/core/common/models/core-model.model.js.map +1 -1
- package/dist/core/common/models/core-persistence.model.js +3 -3
- package/dist/core/common/models/core-persistence.model.js.map +1 -1
- package/dist/core/common/pipes/map-and-validate.pipe.d.ts +1 -1
- package/dist/core/common/pipes/map-and-validate.pipe.js +1 -1
- package/dist/core/common/pipes/map-and-validate.pipe.js.map +1 -1
- package/dist/core/common/scalars/any.scalar.js +2 -2
- package/dist/core/common/scalars/any.scalar.js.map +1 -1
- package/dist/core/common/scalars/date-timestamp.scalar.js +1 -1
- package/dist/core/common/scalars/date-timestamp.scalar.js.map +1 -1
- package/dist/core/common/scalars/date.scalar.js +1 -1
- package/dist/core/common/scalars/date.scalar.js.map +1 -1
- package/dist/core/common/scalars/json.scalar.js +2 -2
- package/dist/core/common/scalars/json.scalar.js.map +1 -1
- package/dist/core/common/services/config.service.js +7 -7
- package/dist/core/common/services/config.service.js.map +1 -1
- package/dist/core/common/services/core-cron-jobs.service.js +5 -5
- package/dist/core/common/services/core-cron-jobs.service.js.map +1 -1
- package/dist/core/common/services/crud.service.js +1 -1
- package/dist/core/common/services/crud.service.js.map +1 -1
- package/dist/core/common/services/mailjet.service.js +5 -5
- package/dist/core/common/services/mailjet.service.js.map +1 -1
- package/dist/core/common/services/module.service.js.map +1 -1
- package/dist/core/common/services/template.service.js +3 -3
- package/dist/core/common/services/template.service.js.map +1 -1
- package/dist/core/common/types/core-model-constructor.type.d.ts +2 -2
- package/dist/core/modules/auth/core-auth.module.js +3 -3
- package/dist/core/modules/auth/core-auth.module.js.map +1 -1
- package/dist/core/modules/auth/core-auth.resolver.js +5 -5
- package/dist/core/modules/auth/core-auth.resolver.js.map +1 -1
- package/dist/core/modules/auth/guards/auth.guard.js +4 -4
- package/dist/core/modules/auth/guards/auth.guard.js.map +1 -1
- package/dist/core/modules/auth/guards/roles.guard.js +1 -1
- package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
- package/dist/core/modules/auth/services/core-auth.service.js +5 -5
- package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
- package/dist/core/modules/auth/strategies/jwt.strategy.js.map +1 -1
- package/dist/core/modules/auth/tokens.decorator.js +2 -2
- package/dist/core/modules/auth/tokens.decorator.js.map +1 -1
- package/dist/core/modules/file/core-file-info.model.js +2 -2
- package/dist/core/modules/file/core-file-info.model.js.map +1 -1
- package/dist/core/modules/file/core-file.controller.d.ts +1 -2
- package/dist/core/modules/file/core-file.controller.js +3 -6
- package/dist/core/modules/file/core-file.controller.js.map +1 -1
- package/dist/core/modules/file/core-file.service.js +1 -1
- package/dist/core/modules/file/core-file.service.js.map +1 -1
- package/dist/core/modules/file/interfaces/file-upload.interface.d.ts +1 -1
- package/dist/core/modules/health-check/core-health-check-result.model.d.ts +8 -0
- package/dist/core/modules/health-check/core-health-check-result.model.js +53 -0
- package/dist/core/modules/health-check/core-health-check-result.model.js.map +1 -0
- package/dist/core/modules/health-check/core-health-check.controller.d.ts +6 -0
- package/dist/core/modules/health-check/core-health-check.controller.js +33 -0
- package/dist/core/modules/health-check/core-health-check.controller.js.map +1 -0
- package/dist/core/modules/health-check/core-health-check.module.d.ts +2 -0
- package/dist/core/modules/health-check/core-health-check.module.js +24 -0
- package/dist/core/modules/health-check/core-health-check.module.js.map +1 -0
- package/dist/core/modules/health-check/core-health-check.resolver.d.ts +6 -0
- package/dist/core/modules/health-check/core-health-check.resolver.js +38 -0
- package/dist/core/modules/health-check/core-health-check.resolver.js.map +1 -0
- package/dist/core/modules/health-check/core-health-check.service.d.ts +11 -0
- package/dist/core/modules/health-check/core-health-check.service.js +52 -0
- package/dist/core/modules/health-check/core-health-check.service.js.map +1 -0
- package/dist/core/modules/user/core-user.model.js +4 -4
- package/dist/core/modules/user/core-user.model.js.map +1 -1
- package/dist/core/modules/user/core-user.service.js +2 -2
- package/dist/core/modules/user/core-user.service.js.map +1 -1
- package/dist/core/modules/user/inputs/core-user.input.js +1 -1
- package/dist/core/modules/user/inputs/core-user.input.js.map +1 -1
- package/dist/core.module.js +10 -5
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/server/modules/auth/auth.service.js +1 -1
- package/dist/server/modules/auth/auth.service.js.map +1 -1
- package/dist/server/modules/file/file.controller.js +1 -1
- package/dist/server/modules/file/file.controller.js.map +1 -1
- package/dist/server/modules/file/file.resolver.js +2 -2
- package/dist/server/modules/file/file.resolver.js.map +1 -1
- package/dist/server/modules/file/file.service.js +1 -1
- package/dist/server/modules/file/file.service.js.map +1 -1
- package/dist/server/modules/file/multer-config.service.js +1 -1
- package/dist/server/modules/file/multer-config.service.js.map +1 -1
- package/dist/server/modules/user/avatar.controller.js +1 -1
- package/dist/server/modules/user/avatar.controller.js.map +1 -1
- package/dist/server/modules/user/user.resolver.js +1 -1
- package/dist/server/modules/user/user.resolver.js.map +1 -1
- package/dist/server/modules/user/user.service.js +3 -3
- package/dist/server/modules/user/user.service.js.map +1 -1
- package/dist/templates/index.ejs +2 -0
- package/dist/templates/password-reset.ejs +3 -0
- package/dist/templates/welcome.ejs +3 -0
- package/dist/test/test.helper.d.ts +1 -1
- package/dist/test/test.helper.js +7 -7
- package/dist/test/test.helper.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +28 -25
- package/src/config.env.ts +32 -20
- package/src/core/common/args/filter.args.ts +4 -4
- package/src/core/common/args/pagination.args.ts +7 -7
- package/src/core/common/decorators/graphql-service-options.decorator.ts +2 -2
- package/src/core/common/decorators/graphql-user.decorator.ts +1 -1
- package/src/core/common/decorators/rest-user.decorator.ts +1 -1
- package/src/core/common/decorators/restricted.decorator.ts +18 -18
- package/src/core/common/filters/http-exception-log.filter.ts +4 -4
- package/src/core/common/helpers/db.helper.ts +35 -40
- package/src/core/common/helpers/decorator.helper.ts +1 -1
- package/src/core/common/helpers/file.helper.ts +2 -2
- package/src/core/common/helpers/filter.helper.ts +7 -8
- package/src/core/common/helpers/graphql.helper.ts +6 -6
- package/src/core/common/helpers/input.helper.ts +54 -61
- package/src/core/common/helpers/model.helper.ts +33 -41
- package/src/core/common/helpers/service.helper.ts +8 -8
- package/src/core/common/inputs/combined-filter.input.ts +4 -4
- package/src/core/common/inputs/core-input.input.ts +2 -2
- package/src/core/common/inputs/filter.input.ts +4 -4
- package/src/core/common/inputs/single-filter.input.ts +4 -4
- package/src/core/common/inputs/sort.input.ts +1 -1
- package/src/core/common/interceptors/check-response.interceptor.ts +1 -1
- package/src/core/common/interceptors/check-security.interceptor.ts +5 -5
- package/src/core/common/interfaces/server-options.interface.ts +31 -0
- package/src/core/common/models/core-model.model.ts +6 -4
- package/src/core/common/models/core-persistence.model.ts +3 -3
- package/src/core/common/pipes/map-and-validate.pipe.ts +2 -2
- package/src/core/common/scalars/any.scalar.ts +2 -2
- package/src/core/common/scalars/date-timestamp.scalar.ts +1 -2
- package/src/core/common/scalars/date.scalar.ts +1 -2
- package/src/core/common/scalars/json.scalar.ts +4 -4
- package/src/core/common/services/config.service.ts +16 -16
- package/src/core/common/services/core-cron-jobs.service.ts +7 -7
- package/src/core/common/services/crud.service.ts +22 -22
- package/src/core/common/services/email.service.ts +1 -1
- package/src/core/common/services/mailjet.service.ts +8 -8
- package/src/core/common/services/module.service.ts +5 -6
- package/src/core/common/services/template.service.ts +4 -4
- package/src/core/common/types/core-model-constructor.type.ts +2 -2
- package/src/core/modules/auth/core-auth.controller.ts +2 -2
- package/src/core/modules/auth/core-auth.module.ts +4 -4
- package/src/core/modules/auth/core-auth.resolver.ts +9 -9
- package/src/core/modules/auth/guards/auth.guard.ts +8 -7
- package/src/core/modules/auth/guards/roles.guard.ts +1 -1
- package/src/core/modules/auth/services/core-auth.service.ts +9 -9
- package/src/core/modules/auth/strategies/jwt-refresh.strategy.ts +1 -1
- package/src/core/modules/auth/strategies/jwt.strategy.ts +1 -1
- package/src/core/modules/auth/tokens.decorator.ts +6 -7
- package/src/core/modules/file/core-file-info.model.ts +2 -2
- package/src/core/modules/file/core-file.controller.ts +2 -4
- package/src/core/modules/file/core-file.service.ts +6 -5
- package/src/core/modules/file/interfaces/file-upload.interface.ts +1 -1
- package/src/core/modules/health-check/core-health-check-result.model.ts +46 -0
- package/src/core/modules/health-check/core-health-check.controller.ts +24 -0
- package/src/core/modules/health-check/core-health-check.module.ts +17 -0
- package/src/core/modules/health-check/core-health-check.resolver.ts +32 -0
- package/src/core/modules/health-check/core-health-check.service.ts +60 -0
- package/src/core/modules/user/core-user.model.ts +5 -5
- package/src/core/modules/user/core-user.service.ts +10 -9
- package/src/core/modules/user/inputs/core-user.input.ts +1 -2
- package/src/core.module.ts +16 -10
- package/src/index.ts +10 -0
- package/src/main.ts +2 -2
- package/src/server/modules/auth/auth.controller.ts +1 -1
- package/src/server/modules/auth/auth.resolver.ts +3 -3
- package/src/server/modules/auth/auth.service.ts +2 -2
- package/src/server/modules/file/file.controller.ts +1 -2
- package/src/server/modules/file/file.module.ts +1 -1
- package/src/server/modules/file/file.resolver.ts +4 -3
- package/src/server/modules/file/file.service.ts +1 -1
- package/src/server/modules/file/multer-config.service.ts +1 -1
- package/src/server/modules/user/avatar.controller.ts +3 -3
- package/src/server/modules/user/user.model.ts +1 -1
- package/src/server/modules/user/user.resolver.ts +4 -4
- package/src/server/modules/user/user.service.ts +4 -4
- package/src/test/test.helper.ts +11 -11
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NotFoundException } from '@nestjs/common';
|
|
2
2
|
import { GridFSBucket, GridFSBucketReadStream, GridFSBucketReadStreamOptions } from 'mongodb';
|
|
3
3
|
import { Connection, Types } from 'mongoose';
|
|
4
|
-
import {
|
|
4
|
+
import { MongoGridFSOptions, MongooseGridFS, createBucket } from 'mongoose-gridfs';
|
|
5
5
|
import { FilterArgs } from '../../common/args/filter.args';
|
|
6
6
|
import { getObjectIds, getStringIds } from '../../common/helpers/db.helper';
|
|
7
7
|
import { convertFilterArgsToQuery } from '../../common/helpers/filter.helper';
|
|
@@ -38,6 +38,7 @@ export abstract class CoreFileService {
|
|
|
38
38
|
return null;
|
|
39
39
|
}
|
|
40
40
|
return await new Promise(async (resolve, reject) => {
|
|
41
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
41
42
|
const { filename, mimetype, encoding, createReadStream } = await file;
|
|
42
43
|
const readStream = createReadStream();
|
|
43
44
|
const options: MongoGridFSOptions = { filename, contentType: mimetype };
|
|
@@ -123,7 +124,7 @@ export abstract class CoreFileService {
|
|
|
123
124
|
*/
|
|
124
125
|
async getFileStreamByName(
|
|
125
126
|
filename: string,
|
|
126
|
-
serviceOptions?: FileServiceOptions
|
|
127
|
+
serviceOptions?: FileServiceOptions,
|
|
127
128
|
): Promise<GridFSBucketReadStreamOptions> {
|
|
128
129
|
if (!(await this.checkRights(filename, { ...serviceOptions, checkInputType: 'filename' }))) {
|
|
129
130
|
return null;
|
|
@@ -182,7 +183,7 @@ export abstract class CoreFileService {
|
|
|
182
183
|
}
|
|
183
184
|
const fileInfo = await this.getFileInfoByName(filename);
|
|
184
185
|
if (!fileInfo) {
|
|
185
|
-
throw new NotFoundException(
|
|
186
|
+
throw new NotFoundException(`File not found with filename ${filename}`);
|
|
186
187
|
}
|
|
187
188
|
return await this.deleteFile(fileInfo.id, serviceOptions);
|
|
188
189
|
}
|
|
@@ -196,8 +197,8 @@ export abstract class CoreFileService {
|
|
|
196
197
|
* Can throw an exception if the rights do not fit
|
|
197
198
|
*/
|
|
198
199
|
protected checkRights(
|
|
199
|
-
input: any,
|
|
200
|
-
options?: FileServiceOptions & { checkInputType: FileInputCheckType }
|
|
200
|
+
input: any, // eslint-disable-line unused-imports/no-unused-vars
|
|
201
|
+
options?: FileServiceOptions & { checkInputType: FileInputCheckType }, // eslint-disable-line unused-imports/no-unused-vars
|
|
201
202
|
): MaybePromise<boolean> {
|
|
202
203
|
return true;
|
|
203
204
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Field, ObjectType } from '@nestjs/graphql';
|
|
2
|
+
import { CoreModel } from '../../common/models/core-model.model';
|
|
3
|
+
import { JSON } from '../../common/scalars/json.scalar';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* User model
|
|
7
|
+
*/
|
|
8
|
+
@ObjectType({ description: 'Health check result' })
|
|
9
|
+
export abstract class CoreHealthCheckResult extends CoreModel {
|
|
10
|
+
// ===================================================================================================================
|
|
11
|
+
// Properties
|
|
12
|
+
// ===================================================================================================================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The overall status of the Health Check
|
|
16
|
+
*/
|
|
17
|
+
@Field({ description: 'The overall status of the Health Check', nullable: false })
|
|
18
|
+
status: 'error' | 'ok' | 'shutting_down' = undefined;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The info object contains information of each health indicator which is of status “up”
|
|
22
|
+
*/
|
|
23
|
+
@Field(type => JSON, {
|
|
24
|
+
description: 'The info object contains information of each health indicator which is of status “up”',
|
|
25
|
+
nullable: true,
|
|
26
|
+
})
|
|
27
|
+
info: JSON = undefined;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The error object contains information of each health indicator which is of status “down”
|
|
31
|
+
*/
|
|
32
|
+
@Field(type => JSON, {
|
|
33
|
+
description: 'The error object contains information of each health indicator which is of status “down”',
|
|
34
|
+
nullable: true,
|
|
35
|
+
})
|
|
36
|
+
error: JSON = undefined;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The details object contains information of every health indicator
|
|
40
|
+
*/
|
|
41
|
+
@Field(type => JSON, {
|
|
42
|
+
description: 'The details object contains information of every health indicator',
|
|
43
|
+
nullable: false,
|
|
44
|
+
})
|
|
45
|
+
details: JSON = undefined;
|
|
46
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Controller, Get } from '@nestjs/common';
|
|
2
|
+
import { CoreHealthCheckService } from './core-health-check.service';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The HealthController class checks the health of various components including the database, memory, and disk.
|
|
6
|
+
* Inspired by https://mobileappcircular.com/marketplace-backend-creating-a-health-check-endpoint-in-nestjs-app-using-terminus-25727e96c7d2
|
|
7
|
+
*/
|
|
8
|
+
@Controller()
|
|
9
|
+
export class CoreHealthCheckController {
|
|
10
|
+
constructor(protected readonly healthCheckService: CoreHealthCheckService) {}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The function checks the health of various components including the database, memory, and storage.
|
|
14
|
+
* @returns The function is returning the result of calling the `healthCheck()` method
|
|
15
|
+
* with an array of functions as arguments. Each function in the array is a check for a different
|
|
16
|
+
* aspect of the system's health, including the status of the database, memory usage, and disk
|
|
17
|
+
* storage. The `healthCheck()` method will return a Promise that resolves with an array of objects
|
|
18
|
+
* representing the results of each check
|
|
19
|
+
*/
|
|
20
|
+
@Get('health-check')
|
|
21
|
+
async healthCheck() {
|
|
22
|
+
return this.healthCheckService.healthCheck();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { TerminusModule } from '@nestjs/terminus';
|
|
3
|
+
import { CoreHealthCheckController } from './core-health-check.controller';
|
|
4
|
+
import { CoreHealthCheckResolver } from './core-health-check.resolver';
|
|
5
|
+
import { CoreHealthCheckService } from './core-health-check.service';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* This is a module that imports the TerminusModule and includes a HealthController.
|
|
9
|
+
* Inspired by https://mobileappcircular.com/marketplace-backend-creating-a-health-check-endpoint-in-nestjs-app-using-terminus-25727e96c7d2
|
|
10
|
+
*/
|
|
11
|
+
@Module({
|
|
12
|
+
imports: [TerminusModule],
|
|
13
|
+
controllers: [CoreHealthCheckController],
|
|
14
|
+
providers: [CoreHealthCheckService, CoreHealthCheckResolver],
|
|
15
|
+
})
|
|
16
|
+
export class CoreHealthCheckModule {
|
|
17
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Query, Resolver } from '@nestjs/graphql';
|
|
2
|
+
import { RoleEnum } from '../../common/enums/role.enum';
|
|
3
|
+
import { Roles } from '../../common/decorators/roles.decorator';
|
|
4
|
+
import { CoreHealthCheckResult } from './core-health-check-result.model';
|
|
5
|
+
import { CoreHealthCheckService } from './core-health-check.service';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Resolver to process with user data
|
|
10
|
+
*/
|
|
11
|
+
@Resolver(() => CoreHealthCheckResult)
|
|
12
|
+
@Roles(RoleEnum.ADMIN)
|
|
13
|
+
export class CoreHealthCheckResolver {
|
|
14
|
+
/**
|
|
15
|
+
* Import services
|
|
16
|
+
*/
|
|
17
|
+
constructor(protected readonly healthCheckService: CoreHealthCheckService) {
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ===========================================================================
|
|
21
|
+
// Queries
|
|
22
|
+
// ===========================================================================
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get heath check result
|
|
26
|
+
*/
|
|
27
|
+
@Roles(RoleEnum.S_EVERYONE)
|
|
28
|
+
@Query(() => CoreHealthCheckResult, { description: 'Get health check result' })
|
|
29
|
+
async healthCheck() {
|
|
30
|
+
return this.healthCheckService.healthCheck();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import {
|
|
3
|
+
DiskHealthIndicator, HealthCheckResult,
|
|
4
|
+
HealthCheckService,
|
|
5
|
+
MemoryHealthIndicator,
|
|
6
|
+
MongooseHealthIndicator,
|
|
7
|
+
} from '@nestjs/terminus';
|
|
8
|
+
import { MongoosePingCheckSettings } from '@nestjs/terminus/dist/health-indicator/database/mongoose.health';
|
|
9
|
+
import { DiskHealthIndicatorOptions } from '@nestjs/terminus/dist/health-indicator/disk/disk-health-options.type';
|
|
10
|
+
import { ConfigService } from '../../common/services/config.service';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Core health check service
|
|
14
|
+
* Inspired by https://mobileappcircular.com/marketplace-backend-creating-a-health-check-endpoint-in-nestjs-app-using-terminus-25727e96c7d2
|
|
15
|
+
*/
|
|
16
|
+
@Injectable()
|
|
17
|
+
export class CoreHealthCheckService {
|
|
18
|
+
|
|
19
|
+
constructor(
|
|
20
|
+
protected config: ConfigService,
|
|
21
|
+
protected db: MongooseHealthIndicator,
|
|
22
|
+
protected disk: DiskHealthIndicator,
|
|
23
|
+
protected health: HealthCheckService,
|
|
24
|
+
protected memory: MemoryHealthIndicator,
|
|
25
|
+
) {
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
healthCheck(): Promise<HealthCheckResult> {
|
|
29
|
+
const healthIndicatorFunctions = [];
|
|
30
|
+
if (!this.config.get<boolean>('healthCheck.configs.database.disabled')) {
|
|
31
|
+
healthIndicatorFunctions.push(() =>
|
|
32
|
+
this.db.pingCheck(
|
|
33
|
+
this.config.get<string>('healthCheck.configs.database.key') ?? 'database',
|
|
34
|
+
this.config.get<MongoosePingCheckSettings>('healthCheck.configs.database.options') ?? { timeout: 300 },
|
|
35
|
+
));
|
|
36
|
+
}
|
|
37
|
+
if (!this.config.get<boolean>('healthCheck.configs.memoryHeap.disabled')) {
|
|
38
|
+
healthIndicatorFunctions.push(() => this.memory.checkHeap(
|
|
39
|
+
this.config.get<string>('healthCheck.configs.memoryHeap.key') ?? 'memoryHeap',
|
|
40
|
+
this.config.get<number>('healthCheck.configs.memoryHeap.heapUsedThreshold') ?? 150 * 1024 * 1024,
|
|
41
|
+
));
|
|
42
|
+
}
|
|
43
|
+
if (!this.config.get<boolean>('healthCheck.configs.memoryRss.disabled')) {
|
|
44
|
+
healthIndicatorFunctions.push(() => this.memory.checkRSS(
|
|
45
|
+
this.config.get<string>('healthCheck.configs.memoryRss.key') ?? 'memoryRss',
|
|
46
|
+
this.config.get<number>('healthCheck.configs.memoryRss.rssThreshold') ?? 150 * 1024 * 1024,
|
|
47
|
+
));
|
|
48
|
+
}
|
|
49
|
+
if (!this.config.get<boolean>('healthCheck.configs.storage.disabled')) {
|
|
50
|
+
healthIndicatorFunctions.push(() => this.disk.checkStorage(
|
|
51
|
+
this.config.get<string>('healthCheck.configs.storage.key') ?? 'storage',
|
|
52
|
+
this.config.get<DiskHealthIndicatorOptions>('healthCheck.configs.storage.options') ?? {
|
|
53
|
+
thresholdPercent: 0.8,
|
|
54
|
+
path: '/',
|
|
55
|
+
},
|
|
56
|
+
));
|
|
57
|
+
}
|
|
58
|
+
return this.health.check(healthIndicatorFunctions);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Field, ObjectType } from '@nestjs/graphql';
|
|
2
|
-
import {
|
|
2
|
+
import { Schema as MongooseSchema, Prop, raw } from '@nestjs/mongoose';
|
|
3
3
|
import { IsEmail, IsOptional } from 'class-validator';
|
|
4
4
|
import { Document } from 'mongoose';
|
|
5
5
|
import { CorePersistenceModel } from '../../common/models/core-persistence.model';
|
|
@@ -50,7 +50,7 @@ export abstract class CoreUserModel extends CorePersistenceModel {
|
|
|
50
50
|
/**
|
|
51
51
|
* Roles of the user
|
|
52
52
|
*/
|
|
53
|
-
@Field(
|
|
53
|
+
@Field(type => [String], { description: 'Roles of the user', nullable: true })
|
|
54
54
|
@IsOptional()
|
|
55
55
|
@Prop()
|
|
56
56
|
roles: string[] = undefined;
|
|
@@ -89,7 +89,7 @@ export abstract class CoreUserModel extends CorePersistenceModel {
|
|
|
89
89
|
/**
|
|
90
90
|
* Verification of the user
|
|
91
91
|
*/
|
|
92
|
-
@Field(
|
|
92
|
+
@Field(type => Boolean, { description: 'Verification state of the user', nullable: true })
|
|
93
93
|
@Prop({ type: Boolean })
|
|
94
94
|
verified: boolean = undefined;
|
|
95
95
|
|
|
@@ -114,7 +114,7 @@ export abstract class CoreUserModel extends CorePersistenceModel {
|
|
|
114
114
|
if (!this.roles || this.roles.length < 1) {
|
|
115
115
|
return false;
|
|
116
116
|
}
|
|
117
|
-
return !roles || roles.length < 1 ? true : this.roles.some(
|
|
117
|
+
return !roles || roles.length < 1 ? true : this.roles.some(role => roles.includes(role));
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
/**
|
|
@@ -127,7 +127,7 @@ export abstract class CoreUserModel extends CorePersistenceModel {
|
|
|
127
127
|
if (!this.roles || this.roles.length < 1) {
|
|
128
128
|
return false;
|
|
129
129
|
}
|
|
130
|
-
return !roles ? true : roles.every(
|
|
130
|
+
return !roles ? true : roles.every(role => this.roles.includes(role));
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import crypto = require('crypto');
|
|
1
2
|
import { BadRequestException, NotFoundException, UnprocessableEntityException } from '@nestjs/common';
|
|
2
3
|
import bcrypt = require('bcrypt');
|
|
3
|
-
import crypto = require('crypto');
|
|
4
4
|
import { sha256 } from 'js-sha256';
|
|
5
5
|
import { Document, Model } from 'mongoose';
|
|
6
6
|
import { assignPlain, prepareServiceOptionsForCreate } from '../../common/helpers/input.helper';
|
|
@@ -19,13 +19,13 @@ import { CoreUserInput } from './inputs/core-user.input';
|
|
|
19
19
|
export abstract class CoreUserService<
|
|
20
20
|
TUser extends CoreUserModel,
|
|
21
21
|
TUserInput extends CoreUserInput,
|
|
22
|
-
TUserCreateInput extends CoreUserCreateInput
|
|
22
|
+
TUserCreateInput extends CoreUserCreateInput,
|
|
23
23
|
> extends CrudService<TUser, TUserCreateInput, TUserInput> {
|
|
24
24
|
protected constructor(
|
|
25
25
|
protected override readonly configService: ConfigService,
|
|
26
26
|
protected readonly emailService: EmailService,
|
|
27
27
|
protected override readonly mainDbModel: Model<TUser & Document>,
|
|
28
|
-
protected override readonly mainModelConstructor: CoreModelConstructor<TUser
|
|
28
|
+
protected override readonly mainModelConstructor: CoreModelConstructor<TUser>,
|
|
29
29
|
) {
|
|
30
30
|
super();
|
|
31
31
|
}
|
|
@@ -64,7 +64,7 @@ export abstract class CoreUserService<
|
|
|
64
64
|
// Return created user
|
|
65
65
|
return createdUser;
|
|
66
66
|
},
|
|
67
|
-
{ input, serviceOptions }
|
|
67
|
+
{ input, serviceOptions },
|
|
68
68
|
);
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -82,6 +82,7 @@ export abstract class CoreUserService<
|
|
|
82
82
|
/**
|
|
83
83
|
* Get verified state of user by token
|
|
84
84
|
*/
|
|
85
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
85
86
|
async getVerifiedState(token: string, serviceOptions?: ServiceOptions): Promise<boolean> {
|
|
86
87
|
const user = await this.mainDbModel.findOne({ verificationToken: token }).exec();
|
|
87
88
|
|
|
@@ -115,7 +116,7 @@ export abstract class CoreUserService<
|
|
|
115
116
|
// Update and return user
|
|
116
117
|
return await assignPlain(dbObject, { verified: true, verifiedAt: new Date() }).save();
|
|
117
118
|
},
|
|
118
|
-
{ dbObject, serviceOptions }
|
|
119
|
+
{ dbObject, serviceOptions },
|
|
119
120
|
);
|
|
120
121
|
}
|
|
121
122
|
|
|
@@ -143,7 +144,7 @@ export abstract class CoreUserService<
|
|
|
143
144
|
passwordResetToken: null,
|
|
144
145
|
}).save();
|
|
145
146
|
},
|
|
146
|
-
{ dbObject, serviceOptions }
|
|
147
|
+
{ dbObject, serviceOptions },
|
|
147
148
|
);
|
|
148
149
|
}
|
|
149
150
|
|
|
@@ -168,7 +169,7 @@ export abstract class CoreUserService<
|
|
|
168
169
|
// Return new user
|
|
169
170
|
return dbObject;
|
|
170
171
|
},
|
|
171
|
-
{ dbObject, serviceOptions }
|
|
172
|
+
{ dbObject, serviceOptions },
|
|
172
173
|
);
|
|
173
174
|
}
|
|
174
175
|
|
|
@@ -182,7 +183,7 @@ export abstract class CoreUserService<
|
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
// Check roles values
|
|
185
|
-
if (roles.some(
|
|
186
|
+
if (roles.some(role => typeof role !== 'string')) {
|
|
186
187
|
throw new BadRequestException('Roles contains invalid values');
|
|
187
188
|
}
|
|
188
189
|
|
|
@@ -191,7 +192,7 @@ export abstract class CoreUserService<
|
|
|
191
192
|
async () => {
|
|
192
193
|
return await this.mainDbModel.findByIdAndUpdate(userId, { roles }).exec();
|
|
193
194
|
},
|
|
194
|
-
{ serviceOptions }
|
|
195
|
+
{ serviceOptions },
|
|
195
196
|
);
|
|
196
197
|
}
|
|
197
198
|
}
|
|
@@ -4,7 +4,6 @@ import { Restricted } from '../../../common/decorators/restricted.decorator';
|
|
|
4
4
|
import { ProcessType } from '../../../common/enums/process-type.enum';
|
|
5
5
|
import { RoleEnum } from '../../../common/enums/role.enum';
|
|
6
6
|
import { CoreInput } from '../../../common/inputs/core-input.input';
|
|
7
|
-
import { toLowerCase } from '../../../common/middlewares/to-lower-case.middleware';
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* User input to update a user
|
|
@@ -41,7 +40,7 @@ export abstract class CoreUserInput extends CoreInput {
|
|
|
41
40
|
* Roles of the user
|
|
42
41
|
*/
|
|
43
42
|
@Restricted({ roles: RoleEnum.ADMIN, processType: ProcessType.INPUT })
|
|
44
|
-
@Field(
|
|
43
|
+
@Field(type => [String], { description: 'Roles of the user', nullable: true })
|
|
45
44
|
@IsOptional()
|
|
46
45
|
roles?: string[] = undefined;
|
|
47
46
|
|
package/src/core.module.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { ConfigService } from './core/common/services/config.service';
|
|
|
13
13
|
import { EmailService } from './core/common/services/email.service';
|
|
14
14
|
import { MailjetService } from './core/common/services/mailjet.service';
|
|
15
15
|
import { TemplateService } from './core/common/services/template.service';
|
|
16
|
+
import { CoreHealthCheckModule } from './core/modules/health-check/core-health-check.module';
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Core module (dynamic)
|
|
@@ -36,6 +37,7 @@ export class CoreModule implements NestModule {
|
|
|
36
37
|
configure(consumer: MiddlewareConsumer) {
|
|
37
38
|
consumer.apply(graphqlUploadExpress()).forRoutes('graphql');
|
|
38
39
|
}
|
|
40
|
+
|
|
39
41
|
/**
|
|
40
42
|
* Dynamic module
|
|
41
43
|
* see https://docs.nestjs.com/modules#dynamic-modules
|
|
@@ -75,7 +77,7 @@ export class CoreModule implements NestModule {
|
|
|
75
77
|
const payload = authService.decodeJwt(authToken);
|
|
76
78
|
const user = await authService.validateUser(payload);
|
|
77
79
|
// the user/jwtPayload object found will be available as context.currentUser/jwtPayload in your GraphQL resolvers
|
|
78
|
-
return { user
|
|
80
|
+
return { user, headers: connectionParams };
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
throw new UnauthorizedException('Missing authentication token');
|
|
@@ -105,7 +107,7 @@ export class CoreModule implements NestModule {
|
|
|
105
107
|
},
|
|
106
108
|
},
|
|
107
109
|
},
|
|
108
|
-
options?.graphQl?.driver
|
|
110
|
+
options?.graphQl?.driver,
|
|
109
111
|
),
|
|
110
112
|
},
|
|
111
113
|
enableSubscriptionAuth: true,
|
|
@@ -115,14 +117,13 @@ export class CoreModule implements NestModule {
|
|
|
115
117
|
uri: 'mongodb://localhost/nest-server-default',
|
|
116
118
|
options: {
|
|
117
119
|
connectionFactory: (connection) => {
|
|
118
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
119
120
|
connection.plugin(require('./core/common/plugins/mongoose-id.plugin'));
|
|
120
121
|
return connection;
|
|
121
122
|
},
|
|
122
123
|
},
|
|
123
124
|
},
|
|
124
125
|
} as IServerOptions,
|
|
125
|
-
options
|
|
126
|
+
options,
|
|
126
127
|
);
|
|
127
128
|
|
|
128
129
|
// Set providers
|
|
@@ -148,15 +149,20 @@ export class CoreModule implements NestModule {
|
|
|
148
149
|
ComplexityPlugin,
|
|
149
150
|
];
|
|
150
151
|
|
|
152
|
+
const imports: any[] = [
|
|
153
|
+
MongooseModule.forRoot(config.mongoose.uri, config.mongoose.options),
|
|
154
|
+
GraphQLModule.forRootAsync<ApolloDriverConfig>(
|
|
155
|
+
Object.assign({ driver: ApolloDriver }, config.graphQl.driver, config.graphQl.options),
|
|
156
|
+
),
|
|
157
|
+
];
|
|
158
|
+
if (config.healthCheck) {
|
|
159
|
+
imports.push(CoreHealthCheckModule);
|
|
160
|
+
}
|
|
161
|
+
|
|
151
162
|
// Return dynamic module
|
|
152
163
|
return {
|
|
153
164
|
module: CoreModule,
|
|
154
|
-
imports
|
|
155
|
-
MongooseModule.forRoot(config.mongoose.uri, config.mongoose.options),
|
|
156
|
-
GraphQLModule.forRootAsync<ApolloDriverConfig>(
|
|
157
|
-
Object.assign({ driver: ApolloDriver }, config.graphQl.driver, config.graphQl.options)
|
|
158
|
-
),
|
|
159
|
-
],
|
|
165
|
+
imports,
|
|
160
166
|
providers,
|
|
161
167
|
exports: [ConfigService, EmailService, TemplateService, MailjetService, ComplexityPlugin],
|
|
162
168
|
};
|
package/src/index.ts
CHANGED
|
@@ -125,6 +125,16 @@ export * from './core/modules/user/inputs/core-user-create.input';
|
|
|
125
125
|
export * from './core/modules/user/core-user.model';
|
|
126
126
|
export * from './core/modules/user/core-user.service';
|
|
127
127
|
|
|
128
|
+
// =====================================================================================================================
|
|
129
|
+
// Core - Modules - HealthCheck
|
|
130
|
+
// =====================================================================================================================
|
|
131
|
+
|
|
132
|
+
export * from './core/modules/health-check/core-health-check.controller';
|
|
133
|
+
export * from './core/modules/health-check/core-health-check.module';
|
|
134
|
+
export * from './core/modules/health-check/core-health-check.resolver';
|
|
135
|
+
export * from './core/modules/health-check/core-health-check.service';
|
|
136
|
+
export * from './core/modules/health-check/core-health-check-result.model';
|
|
137
|
+
|
|
128
138
|
// =====================================================================================================================
|
|
129
139
|
// Tests
|
|
130
140
|
// =====================================================================================================================
|
package/src/main.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
1
2
|
import { NestFactory } from '@nestjs/core';
|
|
2
3
|
import { NestExpressApplication } from '@nestjs/platform-express';
|
|
3
|
-
import { exec } from 'child_process';
|
|
4
4
|
import compression = require('compression');
|
|
5
5
|
import cookieParser = require('cookie-parser');
|
|
6
6
|
import envConfig from './config.env';
|
|
@@ -14,7 +14,7 @@ async function bootstrap() {
|
|
|
14
14
|
// Create a new server based on express
|
|
15
15
|
const server = await NestFactory.create<NestExpressApplication>(
|
|
16
16
|
// Include server module, with all necessary modules for the project
|
|
17
|
-
ServerModule
|
|
17
|
+
ServerModule,
|
|
18
18
|
);
|
|
19
19
|
|
|
20
20
|
// Log exceptions
|
|
@@ -10,7 +10,7 @@ export class AuthController extends CoreAuthController {
|
|
|
10
10
|
*/
|
|
11
11
|
constructor(
|
|
12
12
|
protected override readonly authService: AuthService,
|
|
13
|
-
protected override readonly configService: ConfigService
|
|
13
|
+
protected override readonly configService: ConfigService,
|
|
14
14
|
) {
|
|
15
15
|
super(authService, configService);
|
|
16
16
|
}
|
|
@@ -19,7 +19,7 @@ export class AuthResolver extends CoreAuthResolver {
|
|
|
19
19
|
*/
|
|
20
20
|
constructor(
|
|
21
21
|
protected override readonly authService: AuthService,
|
|
22
|
-
protected override readonly configService: ConfigService
|
|
22
|
+
protected override readonly configService: ConfigService,
|
|
23
23
|
) {
|
|
24
24
|
super(authService, configService);
|
|
25
25
|
}
|
|
@@ -31,7 +31,7 @@ export class AuthResolver extends CoreAuthResolver {
|
|
|
31
31
|
override async signIn(
|
|
32
32
|
@GraphQLServiceOptions({ gqlPath: 'signIn.user' }) serviceOptions: ServiceOptions,
|
|
33
33
|
@Context() ctx: { res: ResponseType },
|
|
34
|
-
@Args('input') input: AuthSignInInput
|
|
34
|
+
@Args('input') input: AuthSignInInput,
|
|
35
35
|
): Promise<Auth> {
|
|
36
36
|
const result = await this.authService.signIn(input, {
|
|
37
37
|
...serviceOptions,
|
|
@@ -49,7 +49,7 @@ export class AuthResolver extends CoreAuthResolver {
|
|
|
49
49
|
override async signUp(
|
|
50
50
|
@GraphQLServiceOptions({ gqlPath: 'signUp.user' }) serviceOptions: ServiceOptions,
|
|
51
51
|
@Context() ctx: { res: ResponseType },
|
|
52
|
-
@Args('input') input: AuthSignUpInput
|
|
52
|
+
@Args('input') input: AuthSignUpInput,
|
|
53
53
|
): Promise<Auth> {
|
|
54
54
|
const result = await this.authService.signUp(input, serviceOptions);
|
|
55
55
|
return this.processCookies(ctx, result);
|
|
@@ -15,7 +15,7 @@ export class AuthService extends CoreAuthService {
|
|
|
15
15
|
protected override readonly jwtService: JwtService,
|
|
16
16
|
protected readonly emailService: EmailService,
|
|
17
17
|
protected override readonly userService: UserService,
|
|
18
|
-
protected override readonly configService: ConfigService
|
|
18
|
+
protected override readonly configService: ConfigService,
|
|
19
19
|
) {
|
|
20
20
|
super(userService, jwtService, configService);
|
|
21
21
|
}
|
|
@@ -43,7 +43,7 @@ export class AuthService extends CoreAuthService {
|
|
|
43
43
|
htmlTemplate: 'welcome',
|
|
44
44
|
templateData: {
|
|
45
45
|
name: user.username,
|
|
46
|
-
link: this.configService.configFastButReadOnly.email.verificationLink
|
|
46
|
+
link: `${this.configService.configFastButReadOnly.email.verificationLink}/${user.verificationToken}`,
|
|
47
47
|
},
|
|
48
48
|
});
|
|
49
49
|
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
Param,
|
|
8
8
|
Post,
|
|
9
9
|
Res,
|
|
10
|
-
UnprocessableEntityException,
|
|
11
10
|
UploadedFile,
|
|
12
11
|
UseInterceptors,
|
|
13
12
|
} from '@nestjs/common';
|
|
@@ -57,7 +56,7 @@ export class FileController {
|
|
|
57
56
|
}
|
|
58
57
|
const filestream = await this.fileService.getFileStream(id);
|
|
59
58
|
res.header('Content-Type', file.contentType);
|
|
60
|
-
res.header('Content-Disposition',
|
|
59
|
+
res.header('Content-Disposition', `attachment; filename=${file.filename}`);
|
|
61
60
|
res.header('Cache-Control', 'max-age=31536000');
|
|
62
61
|
return filestream.pipe(res);
|
|
63
62
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Module, forwardRef } from '@nestjs/common';
|
|
2
2
|
import { MulterModule } from '@nestjs/platform-express';
|
|
3
3
|
import { UserModule } from '../user/user.module';
|
|
4
4
|
import { FileController } from './file.controller';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
|
|
2
1
|
import fs = require('fs');
|
|
3
2
|
import { createWriteStream } from 'fs';
|
|
3
|
+
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
|
|
4
4
|
import GraphQLUpload = require('graphql-upload/GraphQLUpload.js');
|
|
5
5
|
import { Roles } from '../../../core/common/decorators/roles.decorator';
|
|
6
6
|
import { RoleEnum } from '../../../core/common/enums/role.enum';
|
|
@@ -63,6 +63,7 @@ export class FileResolver {
|
|
|
63
63
|
// Save files in filesystem
|
|
64
64
|
const promises: Promise<any>[] = [];
|
|
65
65
|
for (const file of files) {
|
|
66
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
66
67
|
const { filename, mimetype, encoding, createReadStream } = await file;
|
|
67
68
|
await fs.promises.mkdir('./uploads', { recursive: true });
|
|
68
69
|
promises.push(
|
|
@@ -70,8 +71,8 @@ export class FileResolver {
|
|
|
70
71
|
createReadStream()
|
|
71
72
|
.pipe(createWriteStream(`./uploads/${filename}`))
|
|
72
73
|
.on('finish', () => resolve(true))
|
|
73
|
-
.on('error',
|
|
74
|
-
)
|
|
74
|
+
.on('error', error => reject(error)),
|
|
75
|
+
),
|
|
75
76
|
);
|
|
76
77
|
}
|
|
77
78
|
await Promise.allSettled(promises);
|
|
@@ -16,7 +16,7 @@ export class FileService extends CoreFileService {
|
|
|
16
16
|
* Duplicate file by name
|
|
17
17
|
*/
|
|
18
18
|
async duplicate(fileName: string, newName: string): Promise<any> {
|
|
19
|
-
return new Promise(async (resolve
|
|
19
|
+
return new Promise(async (resolve) => {
|
|
20
20
|
resolve(this.files.openDownloadStreamByName(fileName).pipe(this.files.openUploadStream(newName)));
|
|
21
21
|
});
|
|
22
22
|
}
|
|
@@ -28,9 +28,9 @@ export class AvatarController {
|
|
|
28
28
|
FileInterceptor(
|
|
29
29
|
'file',
|
|
30
30
|
multerOptionsForImageUpload({
|
|
31
|
-
destination: envConfig.staticAssets.path
|
|
32
|
-
})
|
|
33
|
-
)
|
|
31
|
+
destination: `${envConfig.staticAssets.path}/avatars`,
|
|
32
|
+
}),
|
|
33
|
+
),
|
|
34
34
|
)
|
|
35
35
|
uploadFile(@UploadedFile() file: Express.Multer.File, @CurrentUser() user: User): Promise<string> {
|
|
36
36
|
return this.usersService.setAvatar(file, user);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Field, ObjectType } from '@nestjs/graphql';
|
|
2
|
-
import {
|
|
2
|
+
import { Schema as MongooseSchema, Prop, SchemaFactory } from '@nestjs/mongoose';
|
|
3
3
|
import { Document, Schema } from 'mongoose';
|
|
4
4
|
import { RoleEnum } from '../../../core/common/enums/role.enum';
|
|
5
5
|
import { CoreUserModel } from '../../../core/modules/user/core-user.model';
|