@lenne.tech/nest-server 10.0.2 → 10.0.4
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/README.md +9 -0
- package/dist/config.env.js +47 -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 +28 -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/model-doc.service.d.ts +16 -0
- package/dist/core/common/services/model-doc.service.js +107 -0
- package/dist/core/common/services/model-doc.service.js.map +1 -0
- 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 +5 -5
- 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 +14 -5
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -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 +32 -26
- package/src/config.env.ts +50 -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 +109 -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/model-doc.service.ts +140 -0
- 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 +62 -0
- package/src/core/modules/user/core-user.model.ts +6 -6
- 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 +23 -12
- package/src/index.ts +11 -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,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,8 @@ 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';
|
|
17
|
+
import { ModelDocService } from './core/common/services/model-doc.service';
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Core module (dynamic)
|
|
@@ -36,6 +38,7 @@ export class CoreModule implements NestModule {
|
|
|
36
38
|
configure(consumer: MiddlewareConsumer) {
|
|
37
39
|
consumer.apply(graphqlUploadExpress()).forRoutes('graphql');
|
|
38
40
|
}
|
|
41
|
+
|
|
39
42
|
/**
|
|
40
43
|
* Dynamic module
|
|
41
44
|
* see https://docs.nestjs.com/modules#dynamic-modules
|
|
@@ -75,7 +78,7 @@ export class CoreModule implements NestModule {
|
|
|
75
78
|
const payload = authService.decodeJwt(authToken);
|
|
76
79
|
const user = await authService.validateUser(payload);
|
|
77
80
|
// the user/jwtPayload object found will be available as context.currentUser/jwtPayload in your GraphQL resolvers
|
|
78
|
-
return { user
|
|
81
|
+
return { user, headers: connectionParams };
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
throw new UnauthorizedException('Missing authentication token');
|
|
@@ -105,7 +108,7 @@ export class CoreModule implements NestModule {
|
|
|
105
108
|
},
|
|
106
109
|
},
|
|
107
110
|
},
|
|
108
|
-
options?.graphQl?.driver
|
|
111
|
+
options?.graphQl?.driver,
|
|
109
112
|
),
|
|
110
113
|
},
|
|
111
114
|
enableSubscriptionAuth: true,
|
|
@@ -115,25 +118,24 @@ export class CoreModule implements NestModule {
|
|
|
115
118
|
uri: 'mongodb://localhost/nest-server-default',
|
|
116
119
|
options: {
|
|
117
120
|
connectionFactory: (connection) => {
|
|
118
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
119
121
|
connection.plugin(require('./core/common/plugins/mongoose-id.plugin'));
|
|
120
122
|
return connection;
|
|
121
123
|
},
|
|
122
124
|
},
|
|
123
125
|
},
|
|
124
126
|
} as IServerOptions,
|
|
125
|
-
options
|
|
127
|
+
options,
|
|
126
128
|
);
|
|
127
129
|
|
|
128
130
|
// Set providers
|
|
129
|
-
const providers = [
|
|
131
|
+
const providers: any[] = [
|
|
130
132
|
// The ConfigService provides access to the current configuration of the module
|
|
131
133
|
{
|
|
132
134
|
provide: ConfigService,
|
|
133
135
|
useValue: new ConfigService(config),
|
|
134
136
|
},
|
|
135
137
|
|
|
136
|
-
// [Global] Map plain objects to
|
|
138
|
+
// [Global] Map plain objects to meta-type and validate
|
|
137
139
|
{
|
|
138
140
|
provide: APP_PIPE,
|
|
139
141
|
useClass: MapAndValidatePipe,
|
|
@@ -148,15 +150,24 @@ export class CoreModule implements NestModule {
|
|
|
148
150
|
ComplexityPlugin,
|
|
149
151
|
];
|
|
150
152
|
|
|
153
|
+
if (config.mongoose?.modelDocumentation) {
|
|
154
|
+
providers.push(ModelDocService);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const imports: any[] = [
|
|
158
|
+
MongooseModule.forRoot(config.mongoose.uri, config.mongoose.options),
|
|
159
|
+
GraphQLModule.forRootAsync<ApolloDriverConfig>(
|
|
160
|
+
Object.assign({ driver: ApolloDriver }, config.graphQl.driver, config.graphQl.options),
|
|
161
|
+
),
|
|
162
|
+
];
|
|
163
|
+
if (config.healthCheck) {
|
|
164
|
+
imports.push(CoreHealthCheckModule);
|
|
165
|
+
}
|
|
166
|
+
|
|
151
167
|
// Return dynamic module
|
|
152
168
|
return {
|
|
153
169
|
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
|
-
],
|
|
170
|
+
imports,
|
|
160
171
|
providers,
|
|
161
172
|
exports: [ConfigService, EmailService, TemplateService, MailjetService, ComplexityPlugin],
|
|
162
173
|
};
|
package/src/index.ts
CHANGED
|
@@ -64,6 +64,7 @@ export * from './core/common/services/core-cron-jobs.service';
|
|
|
64
64
|
export * from './core/common/services/crud.service';
|
|
65
65
|
export * from './core/common/services/email.service';
|
|
66
66
|
export * from './core/common/services/mailjet.service';
|
|
67
|
+
export * from './core/common/services/model-doc.service';
|
|
67
68
|
export * from './core/common/services/module.service';
|
|
68
69
|
export * from './core/common/services/template.service';
|
|
69
70
|
export * from './core/common/types/core-model-constructor.type';
|
|
@@ -125,6 +126,16 @@ export * from './core/modules/user/inputs/core-user-create.input';
|
|
|
125
126
|
export * from './core/modules/user/core-user.model';
|
|
126
127
|
export * from './core/modules/user/core-user.service';
|
|
127
128
|
|
|
129
|
+
// =====================================================================================================================
|
|
130
|
+
// Core - Modules - HealthCheck
|
|
131
|
+
// =====================================================================================================================
|
|
132
|
+
|
|
133
|
+
export * from './core/modules/health-check/core-health-check.controller';
|
|
134
|
+
export * from './core/modules/health-check/core-health-check.module';
|
|
135
|
+
export * from './core/modules/health-check/core-health-check.resolver';
|
|
136
|
+
export * from './core/modules/health-check/core-health-check.service';
|
|
137
|
+
export * from './core/modules/health-check/core-health-check-result.model';
|
|
138
|
+
|
|
128
139
|
// =====================================================================================================================
|
|
129
140
|
// Tests
|
|
130
141
|
// =====================================================================================================================
|
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';
|
|
@@ -46,7 +46,7 @@ export class UserResolver {
|
|
|
46
46
|
@Query(() => FindAndCountUsersResult, { description: 'Find users (via filter)' })
|
|
47
47
|
async findAndCountUsers(
|
|
48
48
|
@GraphQLServiceOptions({ gqlPath: 'findAndCountUsers.items' }) serviceOptions: ServiceOptions,
|
|
49
|
-
@Args() args?: FilterArgs
|
|
49
|
+
@Args() args?: FilterArgs,
|
|
50
50
|
) {
|
|
51
51
|
return await this.userService.findAndCount(args, {
|
|
52
52
|
...serviceOptions,
|
|
@@ -95,7 +95,7 @@ export class UserResolver {
|
|
|
95
95
|
@Mutation(() => User, { description: 'Create a new user' })
|
|
96
96
|
async createUser(
|
|
97
97
|
@GraphQLServiceOptions() serviceOptions: ServiceOptions,
|
|
98
|
-
@Args('input') input: UserCreateInput
|
|
98
|
+
@Args('input') input: UserCreateInput,
|
|
99
99
|
): Promise<User> {
|
|
100
100
|
return await this.userService.create(input, {
|
|
101
101
|
...serviceOptions,
|
|
@@ -132,7 +132,7 @@ export class UserResolver {
|
|
|
132
132
|
async updateUser(
|
|
133
133
|
@GraphQLServiceOptions() serviceOptions: ServiceOptions,
|
|
134
134
|
@Args('input') input: UserInput,
|
|
135
|
-
@Args('id') id: string
|
|
135
|
+
@Args('id') id: string,
|
|
136
136
|
): Promise<User> {
|
|
137
137
|
// Update user
|
|
138
138
|
return await this.userService.update(id, input, {
|
|
@@ -162,7 +162,7 @@ export class UserResolver {
|
|
|
162
162
|
filter(this: UserResolver, payload, variables, context) {
|
|
163
163
|
return context?.user?.hasRole?.(RoleEnum.ADMIN);
|
|
164
164
|
},
|
|
165
|
-
resolve:
|
|
165
|
+
resolve: user => user,
|
|
166
166
|
})
|
|
167
167
|
async userCreated() {
|
|
168
168
|
return this.pubSub.asyncIterator('userCreated');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import fs = require('fs');
|
|
1
2
|
import { Inject, Injectable, UnauthorizedException, UnprocessableEntityException } from '@nestjs/common';
|
|
2
3
|
import { InjectModel } from '@nestjs/mongoose';
|
|
3
|
-
import fs = require('fs');
|
|
4
4
|
import { PubSub } from 'graphql-subscriptions';
|
|
5
5
|
import { Model } from 'mongoose';
|
|
6
6
|
import { ServiceOptions } from '../../../core/common/interfaces/service-options.interface';
|
|
@@ -29,7 +29,7 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
|
|
|
29
29
|
protected override readonly emailService: EmailService,
|
|
30
30
|
@Inject('USER_CLASS') protected override readonly mainModelConstructor: CoreModelConstructor<User>,
|
|
31
31
|
@InjectModel('User') protected override readonly mainDbModel: Model<UserDocument>,
|
|
32
|
-
@Inject('PUB_SUB') protected readonly pubSub: PubSub
|
|
32
|
+
@Inject('PUB_SUB') protected readonly pubSub: PubSub,
|
|
33
33
|
) {
|
|
34
34
|
super(configService, emailService, mainDbModel, mainModelConstructor);
|
|
35
35
|
}
|
|
@@ -73,7 +73,7 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
|
|
|
73
73
|
htmlTemplate: 'password-reset',
|
|
74
74
|
templateData: {
|
|
75
75
|
name: user.username,
|
|
76
|
-
link: this.configService.configFastButReadOnly.email.passwordResetLink
|
|
76
|
+
link: `${this.configService.configFastButReadOnly.email.passwordResetLink}/${user.passwordResetToken}`,
|
|
77
77
|
},
|
|
78
78
|
});
|
|
79
79
|
|
|
@@ -98,7 +98,7 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
|
|
|
98
98
|
|
|
99
99
|
// Remove old avatar image
|
|
100
100
|
if (user.avatar) {
|
|
101
|
-
fs.unlink(this.configService.configFastButReadOnly.staticAssets.path
|
|
101
|
+
fs.unlink(`${this.configService.configFastButReadOnly.staticAssets.path}/avatars/${user.avatar}`, (err) => {
|
|
102
102
|
if (err) {
|
|
103
103
|
console.error(err);
|
|
104
104
|
}
|
package/src/test/test.helper.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { INestApplication } from '@nestjs/common';
|
|
2
1
|
import { Blob } from 'buffer';
|
|
2
|
+
import util = require('util');
|
|
3
|
+
import { INestApplication } from '@nestjs/common';
|
|
3
4
|
import { createClient } from 'graphql-ws';
|
|
4
5
|
import { jsonToGraphQLQuery } from 'json-to-graphql-query';
|
|
5
6
|
import { Types } from 'mongoose';
|
|
6
7
|
import supertest = require('supertest');
|
|
7
|
-
import util = require('util');
|
|
8
8
|
import ws = require('ws');
|
|
9
9
|
import { getStringIds } from '../core/common/helpers/db.helper';
|
|
10
10
|
|
|
@@ -158,7 +158,7 @@ export class TestHelper {
|
|
|
158
158
|
return new Promise((resolve, reject) => {
|
|
159
159
|
const request = supertest((this.app as INestApplication).getHttpServer()).get(url);
|
|
160
160
|
if (token) {
|
|
161
|
-
request.set('Authorization',
|
|
161
|
+
request.set('Authorization', `bearer ${token}`);
|
|
162
162
|
}
|
|
163
163
|
let data = '';
|
|
164
164
|
request
|
|
@@ -220,7 +220,7 @@ export class TestHelper {
|
|
|
220
220
|
name: null,
|
|
221
221
|
type: TestGraphQLType.QUERY,
|
|
222
222
|
},
|
|
223
|
-
graphql
|
|
223
|
+
graphql,
|
|
224
224
|
) as TestGraphQLConfig;
|
|
225
225
|
|
|
226
226
|
// Init request
|
|
@@ -256,7 +256,7 @@ export class TestHelper {
|
|
|
256
256
|
if (config.convertEnums) {
|
|
257
257
|
if (Array.isArray(config.convertEnums)) {
|
|
258
258
|
for (const key of Object.values(config.convertEnums)) {
|
|
259
|
-
const regExpStr =
|
|
259
|
+
const regExpStr = `(${key}: )\\"([_A-Z][_0-9A-Z]*)\\"`;
|
|
260
260
|
const regExp = new RegExp(regExpStr, 'g');
|
|
261
261
|
query = query.replace(regExp, '$1$2');
|
|
262
262
|
}
|
|
@@ -362,7 +362,7 @@ export class TestHelper {
|
|
|
362
362
|
}
|
|
363
363
|
if (Array.isArray(args)) {
|
|
364
364
|
objects.set(args, args);
|
|
365
|
-
return args.map(
|
|
365
|
+
return args.map(item => this.prepareArguments(item, objects));
|
|
366
366
|
}
|
|
367
367
|
if (typeof args === 'object') {
|
|
368
368
|
objects.set(args, args);
|
|
@@ -429,7 +429,7 @@ export class TestHelper {
|
|
|
429
429
|
log: boolean,
|
|
430
430
|
logError: boolean,
|
|
431
431
|
variables?: Record<string, TestGraphQLVariable>,
|
|
432
|
-
attachments?: Record<string, string
|
|
432
|
+
attachments?: Record<string, string>,
|
|
433
433
|
): Promise<any> {
|
|
434
434
|
// Token
|
|
435
435
|
if (token) {
|
|
@@ -460,7 +460,7 @@ export class TestHelper {
|
|
|
460
460
|
const method: string = requestConfig.method.toLowerCase();
|
|
461
461
|
let request = supertest((this.app as INestApplication).getHttpServer())[method](requestConfig.url as string);
|
|
462
462
|
if (token) {
|
|
463
|
-
request.set('Authorization',
|
|
463
|
+
request.set('Authorization', `bearer ${token}`);
|
|
464
464
|
}
|
|
465
465
|
|
|
466
466
|
// Process variables (incl. attachments for GraphQL)
|
|
@@ -508,7 +508,7 @@ export class TestHelper {
|
|
|
508
508
|
}
|
|
509
509
|
const map = {};
|
|
510
510
|
mapArray.forEach((item, index) => {
|
|
511
|
-
map[index] = [
|
|
511
|
+
map[index] = [`variables.${item.key}${'index' in item ? `.${item.index}` : ''}`];
|
|
512
512
|
});
|
|
513
513
|
|
|
514
514
|
// Add operations
|
|
@@ -565,7 +565,7 @@ export class TestHelper {
|
|
|
565
565
|
async getSubscription(graphql: TestGraphQLConfig, query: string, options?: TestGraphQLOptions) {
|
|
566
566
|
// Check url
|
|
567
567
|
if (!this.subscriptionUrl) {
|
|
568
|
-
throw new Error(
|
|
568
|
+
throw new Error('Missing subscriptionUrl in TestHelper: new TestHelper(app, \'ws://localhost:3030/graphql\')');
|
|
569
569
|
}
|
|
570
570
|
|
|
571
571
|
// Prepare subscription
|
|
@@ -599,7 +599,7 @@ export class TestHelper {
|
|
|
599
599
|
next: onNext,
|
|
600
600
|
error: reject,
|
|
601
601
|
complete: resolve as any,
|
|
602
|
-
}
|
|
602
|
+
},
|
|
603
603
|
);
|
|
604
604
|
});
|
|
605
605
|
|