@lenne.tech/nest-server 8.3.0 → 8.5.0

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.
Files changed (58) hide show
  1. package/dist/core/common/decorators/restricted.decorator.d.ts +12 -5
  2. package/dist/core/common/decorators/restricted.decorator.js +91 -29
  3. package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
  4. package/dist/core/common/enums/process-type.enum.d.ts +4 -0
  5. package/dist/core/common/enums/process-type.enum.js +9 -0
  6. package/dist/core/common/enums/process-type.enum.js.map +1 -0
  7. package/dist/core/common/enums/role.enum.d.ts +1 -2
  8. package/dist/core/common/enums/role.enum.js +0 -1
  9. package/dist/core/common/enums/role.enum.js.map +1 -1
  10. package/dist/core/common/helpers/db.helper.d.ts +3 -3
  11. package/dist/core/common/helpers/db.helper.js +25 -25
  12. package/dist/core/common/helpers/db.helper.js.map +1 -1
  13. package/dist/core/common/helpers/input.helper.d.ts +6 -5
  14. package/dist/core/common/helpers/input.helper.js +4 -15
  15. package/dist/core/common/helpers/input.helper.js.map +1 -1
  16. package/dist/core/common/helpers/service.helper.d.ts +1 -0
  17. package/dist/core/common/helpers/service.helper.js +18 -2
  18. package/dist/core/common/helpers/service.helper.js.map +1 -1
  19. package/dist/core/common/interfaces/service-options.interface.d.ts +1 -3
  20. package/dist/core/common/models/core-persistence.model.d.ts +0 -1
  21. package/dist/core/common/models/core-persistence.model.js +0 -10
  22. package/dist/core/common/models/core-persistence.model.js.map +1 -1
  23. package/dist/core/common/services/module.service.d.ts +3 -3
  24. package/dist/core/common/services/module.service.js +27 -26
  25. package/dist/core/common/services/module.service.js.map +1 -1
  26. package/dist/core/common/types/require-only-one.type.d.ts +3 -0
  27. package/dist/core/common/types/require-only-one.type.js +3 -0
  28. package/dist/core/common/types/require-only-one.type.js.map +1 -0
  29. package/dist/core/common/types/required-at-least-one.type.d.ts +3 -0
  30. package/dist/core/common/types/required-at-least-one.type.js +3 -0
  31. package/dist/core/common/types/required-at-least-one.type.js.map +1 -0
  32. package/dist/core.module.js +0 -5
  33. package/dist/core.module.js.map +1 -1
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.js +3 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/server/modules/user/user.model.d.ts +1 -1
  38. package/dist/server/modules/user/user.model.js +1 -1
  39. package/dist/server/modules/user/user.model.js.map +1 -1
  40. package/dist/server/modules/user/user.service.js +1 -1
  41. package/dist/server/modules/user/user.service.js.map +1 -1
  42. package/dist/tsconfig.build.tsbuildinfo +1 -1
  43. package/package.json +5 -5
  44. package/src/core/common/decorators/restricted.decorator.ts +150 -53
  45. package/src/core/common/enums/process-type.enum.ts +7 -0
  46. package/src/core/common/enums/role.enum.ts +6 -9
  47. package/src/core/common/helpers/db.helper.ts +43 -51
  48. package/src/core/common/helpers/input.helper.ts +24 -15
  49. package/src/core/common/helpers/service.helper.ts +17 -2
  50. package/src/core/common/interfaces/service-options.interface.ts +4 -8
  51. package/src/core/common/models/core-persistence.model.ts +0 -11
  52. package/src/core/common/services/module.service.ts +32 -31
  53. package/src/core/common/types/require-only-one.type.ts +6 -0
  54. package/src/core/common/types/required-at-least-one.type.ts +6 -0
  55. package/src/core.module.ts +1 -19
  56. package/src/index.ts +3 -0
  57. package/src/server/modules/user/user.model.ts +2 -2
  58. package/src/server/modules/user/user.service.ts +3 -3
@@ -1,11 +1,11 @@
1
1
  import { Document, Model, Types } from 'mongoose';
2
+ import { ProcessType } from '../enums/process-type.enum';
2
3
  import { getStringIds, popAndMap } from '../helpers/db.helper';
3
4
  import { check } from '../helpers/input.helper';
4
5
  import { prepareInput, prepareOutput } from '../helpers/service.helper';
5
6
  import { ServiceOptions } from '../interfaces/service-options.interface';
6
7
  import { CoreModel } from '../models/core-model.model';
7
8
  import { FieldSelection } from '../types/field-selection.type';
8
- import { IdsType } from '../types/ids.type';
9
9
 
10
10
  /**
11
11
  * Module service class to be extended by concrete module services
@@ -39,9 +39,9 @@ export abstract class ModuleService<T extends CoreModel = any> {
39
39
  input: any,
40
40
  currentUser: { id: any; hasRole: (roles: string[]) => boolean },
41
41
  options?: {
42
- creator?: IdsType;
42
+ dbObject?: any;
43
43
  metatype?: any;
44
- ownerIds?: IdsType;
44
+ processType?: ProcessType;
45
45
  roles?: string | string[];
46
46
  throwError?: boolean;
47
47
  }
@@ -84,36 +84,28 @@ export abstract class ModuleService<T extends CoreModel = any> {
84
84
 
85
85
  // Prepare input
86
86
  if (config.prepareInput && this.prepareInput) {
87
- await this.prepareInput(config.input, config.prepareInput);
87
+ const opts = config.prepareInput;
88
+ if (!opts.targetModel && config.inputType) {
89
+ opts.targetModel = config.inputType;
90
+ }
91
+ await this.prepareInput(config.input, opts);
88
92
  }
89
93
 
90
94
  // Get DB object
91
- const getDbObject = async () => {
92
- if (config.dbObject) {
93
- if (typeof config.dbObject === 'string' || config.dbObject instanceof Types.ObjectId) {
94
- const dbObject = await this.get(getStringIds(config.dbObject));
95
- if (dbObject) {
96
- config.dbObject = dbObject;
97
- }
95
+ if (config.dbObject && config.checkRights && this.checkRights) {
96
+ if (typeof config.dbObject === 'string' || config.dbObject instanceof Types.ObjectId) {
97
+ const dbObject = await this.get(getStringIds(config.dbObject));
98
+ if (dbObject) {
99
+ config.dbObject = dbObject;
98
100
  }
99
101
  }
100
- return config.dbObject;
101
- };
102
-
103
- // Get owner IDs
104
- let ownerIds = undefined;
105
- if (config.checkRights && this.checkRights) {
106
- ownerIds = getStringIds(config.ownerIds);
107
- if (!ownerIds?.length) {
108
- ownerIds = (await getDbObject())?.ownerIds;
109
- }
110
102
  }
111
103
 
112
104
  // Check rights for input
113
105
  if (config.input && config.checkRights && this.checkRights) {
114
- const opts: any = { creator: (await getDbObject())?.createdBy, ownerIds, roles: config.roles };
106
+ const opts: any = { dbObject: config.dbObject, processType: ProcessType.INPUT, roles: config.roles };
115
107
  if (config.inputType) {
116
- opts.metatype = config.resultType;
108
+ opts.metatype = config.inputType;
117
109
  }
118
110
  config.input = await this.checkRights(config.input, config.currentUser as any, opts);
119
111
  }
@@ -128,18 +120,23 @@ export abstract class ModuleService<T extends CoreModel = any> {
128
120
 
129
121
  // Prepare output
130
122
  if (config.prepareOutput && this.prepareOutput) {
131
- // Check if mapping is already done by processFieldSelection
132
- if (config.processFieldSelection && config.fieldSelection && this.processFieldSelection) {
133
- config.prepareOutput.targetModel = null;
123
+ const opts = config.prepareOutput;
124
+ if (!opts.targetModel && config.outputType) {
125
+ opts.targetModel = config.outputType;
134
126
  }
135
- result = await this.prepareOutput(result, config.prepareOutput);
127
+ result = await this.prepareOutput(result, opts);
136
128
  }
137
129
 
138
130
  // Check output rights
139
131
  if (config.checkRights && this.checkRights) {
140
- const opts: any = { creator: (await getDbObject())?.createdBy, ownerIds, roles: config.roles, throwError: false };
141
- if (config.resultType) {
142
- opts.metatype = config.resultType;
132
+ const opts: any = {
133
+ dbObject: config.dbObject,
134
+ processType: ProcessType.OUTPUT,
135
+ roles: config.roles,
136
+ throwError: false,
137
+ };
138
+ if (config.outputType) {
139
+ opts.metatype = config.outputType;
143
140
  }
144
141
  result = await this.checkRights(result, config.currentUser as any, opts);
145
142
  }
@@ -152,7 +149,11 @@ export abstract class ModuleService<T extends CoreModel = any> {
152
149
  * Prepare input before save
153
150
  */
154
151
  async prepareInput(input: Record<string, any>, options: ServiceOptions = {}) {
155
- return prepareInput(input, options.currentUser, options.prepareInput);
152
+ const config = {
153
+ targetModel: this.mainModelConstructor,
154
+ ...options?.prepareInput,
155
+ };
156
+ return prepareInput(input, options.currentUser, config);
156
157
  }
157
158
 
158
159
  /**
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Require only one of the optional properties
3
+ * See https://stackoverflow.com/a/49725198
4
+ */
5
+ export type RequireOnlyOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> &
6
+ { [K in Keys]-?: Required<Pick<T, K>> & Partial<Record<Exclude<Keys, K>, undefined>> }[Keys];
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Require at least on of optional properties
3
+ * See https://stackoverflow.com/a/49725198
4
+ */
5
+ export type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> &
6
+ { [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>> }[Keys];
@@ -1,8 +1,7 @@
1
1
  import { DynamicModule, Global, Module, UnauthorizedException } from '@nestjs/common';
2
- import { APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core';
2
+ import { APP_PIPE } from '@nestjs/core';
3
3
  import { GraphQLModule } from '@nestjs/graphql';
4
4
  import { merge } from './core/common/helpers/config.helper';
5
- import { CheckResponseInterceptor } from './core/common/interceptors/check-response.interceptor';
6
5
  import { IServerOptions } from './core/common/interfaces/server-options.interface';
7
6
  import { MapAndValidatePipe } from './core/common/pipes/map-and-validate.pipe';
8
7
  import { ConfigService } from './core/common/services/config.service';
@@ -19,8 +18,6 @@ import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
19
18
  * - MongooseModule
20
19
  * - GraphQL
21
20
  * - ConfigService
22
- * - CheckInput
23
- * - CheckResponse
24
21
  *
25
22
  * and sets the following services as globals:
26
23
  * - ConfigService
@@ -99,21 +96,6 @@ export class CoreModule {
99
96
  useValue: new ConfigService(config),
100
97
  },
101
98
 
102
- // [Global] The CheckResponseInterceptor restricts the response to the properties
103
- // that are permitted for the current user
104
- {
105
- provide: APP_INTERCEPTOR,
106
- useClass: CheckResponseInterceptor,
107
- },
108
-
109
- // [Global] The CheckInputPipe checks the permissibility of individual properties of inputs for the resolvers
110
- // in relation to the current user, replaces MapAndValidatePipe
111
- // Does not work yet, because context is missing: https://github.com/nestjs/graphql/issues/325
112
- // {
113
- // provide: APP_PIPE,
114
- // useClass: CheckInputPipe,
115
- // },
116
-
117
99
  // [Global] Map plain objects to metatype and validate
118
100
  {
119
101
  provide: APP_PIPE,
package/src/index.ts CHANGED
@@ -15,6 +15,7 @@ export * from './core/common/decorators/restricted.decorator';
15
15
  export * from './core/common/decorators/roles.decorator';
16
16
  export * from './core/common/enums/comparison-operator.enum';
17
17
  export * from './core/common/enums/logical-operator.enum';
18
+ export * from './core/common/enums/process-type.enum';
18
19
  export * from './core/common/enums/role.enum';
19
20
  export * from './core/common/enums/sort-order.emum';
20
21
  export * from './core/common/helpers/config.helper';
@@ -54,6 +55,8 @@ export * from './core/common/types/core-model-constructor.type';
54
55
  export * from './core/common/types/field-selection.type';
55
56
  export * from './core/common/types/ids.type';
56
57
  export * from './core/common/types/plain-input.type';
58
+ export * from './core/common/types/require-only-one.type';
59
+ export * from './core/common/types/required-at-least-one.type';
57
60
  export * from './core/common/types/string-or-object-id.type';
58
61
 
59
62
  // =====================================================================================================================
@@ -1,8 +1,8 @@
1
1
  import { Field, ObjectType } from '@nestjs/graphql';
2
+ import { Prop, Schema as MongooseSchema, SchemaFactory } from '@nestjs/mongoose';
3
+ import { Document, Schema } from 'mongoose';
2
4
  import { CoreUserModel } from '../../../core/modules/user/core-user.model';
3
5
  import { PersistenceModel } from '../../common/models/persistence.model';
4
- import { Prop, Schema as MongooseSchema, SchemaFactory } from '@nestjs/mongoose';
5
- import { Schema, Document } from 'mongoose';
6
6
 
7
7
  export type UserDocument = User & Document;
8
8
 
@@ -46,11 +46,11 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
46
46
  // Get prepared user
47
47
  let user = await super.create(input, serviceOptions);
48
48
 
49
- // Add the createdBy information in an additional step if it was not set by the system,
50
- // because the user created himself and could not exist as currentUser before
49
+ // Add the createdBy information in an extra step if it was not set by the system because the user created himself
50
+ // and could not exist as currentUser before
51
51
  if (!user.createdBy) {
52
52
  await this.mainDbModel.findByIdAndUpdate(user.id, { createdBy: user.id });
53
- user = await this.get(user.id, serviceOptions);
53
+ user = await this.get(user.id, { ...serviceOptions, currentUser: serviceOptions.currentUser || user });
54
54
  }
55
55
 
56
56
  // Publish action