@lenne.tech/nest-server 8.0.2 → 8.3.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 (166) hide show
  1. package/dist/config.env.js +3 -2
  2. package/dist/config.env.js.map +1 -1
  3. package/dist/core/common/args/pagination.args.js +1 -1
  4. package/dist/core/common/args/pagination.args.js.map +1 -1
  5. package/dist/core/common/decorators/restricted.decorator.d.ts +3 -0
  6. package/dist/core/common/decorators/restricted.decorator.js +14 -8
  7. package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
  8. package/dist/core/common/enums/role.enum.d.ts +3 -2
  9. package/dist/core/common/enums/role.enum.js +3 -2
  10. package/dist/core/common/enums/role.enum.js.map +1 -1
  11. package/dist/core/common/helpers/config.helper.d.ts +2 -1
  12. package/dist/core/common/helpers/config.helper.js +11 -7
  13. package/dist/core/common/helpers/config.helper.js.map +1 -1
  14. package/dist/core/common/helpers/context.helper.d.ts +7 -1
  15. package/dist/core/common/helpers/context.helper.js +33 -29
  16. package/dist/core/common/helpers/context.helper.js.map +1 -1
  17. package/dist/core/common/helpers/db.helper.d.ts +37 -0
  18. package/dist/core/common/helpers/db.helper.js +356 -0
  19. package/dist/core/common/helpers/db.helper.js.map +1 -0
  20. package/dist/core/common/helpers/file.helper.d.ts +8 -1
  21. package/dist/core/common/helpers/file.helper.js +43 -31
  22. package/dist/core/common/helpers/file.helper.js.map +1 -1
  23. package/dist/core/common/helpers/filter.helper.d.ts +3 -0
  24. package/dist/core/common/helpers/filter.helper.js +93 -81
  25. package/dist/core/common/helpers/filter.helper.js.map +1 -1
  26. package/dist/core/common/helpers/graphql.helper.d.ts +24 -1
  27. package/dist/core/common/helpers/graphql.helper.js +144 -96
  28. package/dist/core/common/helpers/graphql.helper.js.map +1 -1
  29. package/dist/core/common/helpers/input.helper.d.ts +42 -4
  30. package/dist/core/common/helpers/input.helper.js +256 -97
  31. package/dist/core/common/helpers/input.helper.js.map +1 -1
  32. package/dist/core/common/helpers/model.helper.d.ts +11 -0
  33. package/dist/core/common/helpers/model.helper.js +41 -29
  34. package/dist/core/common/helpers/model.helper.js.map +1 -1
  35. package/dist/core/common/helpers/service.helper.d.ts +21 -1
  36. package/dist/core/common/helpers/service.helper.js +80 -72
  37. package/dist/core/common/helpers/service.helper.js.map +1 -1
  38. package/dist/core/common/inputs/combined-filter.input.js +1 -1
  39. package/dist/core/common/inputs/combined-filter.input.js.map +1 -1
  40. package/dist/core/common/inputs/core-input.input.js +1 -1
  41. package/dist/core/common/inputs/core-input.input.js.map +1 -1
  42. package/dist/core/common/interceptors/check-response.interceptor.js +1 -1
  43. package/dist/core/common/interceptors/check-response.interceptor.js.map +1 -1
  44. package/dist/core/common/interfaces/resolve-selector.interface.d.ts +5 -0
  45. package/dist/core/common/interfaces/resolve-selector.interface.js +3 -0
  46. package/dist/core/common/interfaces/resolve-selector.interface.js.map +1 -0
  47. package/dist/core/common/interfaces/service-options.interface.d.ts +36 -0
  48. package/dist/core/common/interfaces/service-options.interface.js +3 -0
  49. package/dist/core/common/interfaces/service-options.interface.js.map +1 -0
  50. package/dist/core/common/models/core-model.model.d.ts +5 -1
  51. package/dist/core/common/models/core-model.model.js +1 -1
  52. package/dist/core/common/models/core-model.model.js.map +1 -1
  53. package/dist/core/common/pipes/check-input.pipe.js +2 -2
  54. package/dist/core/common/pipes/check-input.pipe.js.map +1 -1
  55. package/dist/core/common/pipes/map-and-validate.pipe.js +1 -1
  56. package/dist/core/common/pipes/map-and-validate.pipe.js.map +1 -1
  57. package/dist/core/common/services/crud.service.d.ts +13 -0
  58. package/dist/core/common/services/crud.service.js +57 -0
  59. package/dist/core/common/services/crud.service.js.map +1 -0
  60. package/dist/core/common/services/email.service.js +8 -8
  61. package/dist/core/common/services/email.service.js.map +1 -1
  62. package/dist/core/common/services/module.service.d.ts +40 -0
  63. package/dist/core/common/services/module.service.js +80 -0
  64. package/dist/core/common/services/module.service.js.map +1 -0
  65. package/dist/core/common/types/core-model-constructor.type.d.ts +21 -0
  66. package/dist/core/common/types/core-model-constructor.type.js +3 -0
  67. package/dist/core/common/types/core-model-constructor.type.js.map +1 -0
  68. package/dist/core/common/types/field-selection.type.d.ts +4 -0
  69. package/dist/core/common/types/field-selection.type.js +3 -0
  70. package/dist/core/common/types/field-selection.type.js.map +1 -0
  71. package/dist/core/common/types/ids.type.d.ts +8 -0
  72. package/dist/core/common/types/ids.type.js +3 -0
  73. package/dist/core/common/types/ids.type.js.map +1 -0
  74. package/dist/core/common/types/string-or-object-id.type.d.ts +2 -0
  75. package/dist/core/common/types/string-or-object-id.type.js +3 -0
  76. package/dist/core/common/types/string-or-object-id.type.js.map +1 -0
  77. package/dist/core/modules/auth/core-auth.resolver.d.ts +2 -1
  78. package/dist/core/modules/auth/core-auth.resolver.js +4 -3
  79. package/dist/core/modules/auth/core-auth.resolver.js.map +1 -1
  80. package/dist/core/modules/auth/guards/roles.guard.js +1 -2
  81. package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
  82. package/dist/core/modules/auth/services/core-auth-user.service.d.ts +3 -1
  83. package/dist/core/modules/auth/services/core-auth-user.service.js.map +1 -1
  84. package/dist/core/modules/auth/services/core-auth.service.d.ts +2 -1
  85. package/dist/core/modules/auth/services/core-auth.service.js +6 -4
  86. package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
  87. package/dist/core/modules/user/core-user.model.js +1 -1
  88. package/dist/core/modules/user/core-user.model.js.map +1 -1
  89. package/dist/core/modules/user/core-user.service.d.ts +16 -25
  90. package/dist/core/modules/user/core-user.service.js +69 -90
  91. package/dist/core/modules/user/core-user.service.js.map +1 -1
  92. package/dist/core.module.js +1 -1
  93. package/dist/core.module.js.map +1 -1
  94. package/dist/index.d.ts +9 -1
  95. package/dist/index.js +9 -1
  96. package/dist/index.js.map +1 -1
  97. package/dist/server/modules/auth/auth.resolver.d.ts +2 -1
  98. package/dist/server/modules/auth/auth.resolver.js +4 -3
  99. package/dist/server/modules/auth/auth.resolver.js.map +1 -1
  100. package/dist/server/modules/file/file.controller.js +1 -1
  101. package/dist/server/modules/file/file.controller.js.map +1 -1
  102. package/dist/server/modules/user/avatar.controller.js +2 -2
  103. package/dist/server/modules/user/avatar.controller.js.map +1 -1
  104. package/dist/server/modules/user/user.model.d.ts +2 -1
  105. package/dist/server/modules/user/user.module.js +7 -3
  106. package/dist/server/modules/user/user.module.js.map +1 -1
  107. package/dist/server/modules/user/user.resolver.d.ts +8 -7
  108. package/dist/server/modules/user/user.resolver.js +85 -49
  109. package/dist/server/modules/user/user.resolver.js.map +1 -1
  110. package/dist/server/modules/user/user.service.d.ts +9 -18
  111. package/dist/server/modules/user/user.service.js +23 -30
  112. package/dist/server/modules/user/user.service.js.map +1 -1
  113. package/dist/test/test.helper.d.ts +1 -2
  114. package/dist/test/test.helper.js +1 -16
  115. package/dist/test/test.helper.js.map +1 -1
  116. package/dist/tsconfig.build.tsbuildinfo +1 -1
  117. package/package.json +58 -59
  118. package/src/config.env.ts +3 -2
  119. package/src/core/common/args/pagination.args.ts +2 -2
  120. package/src/core/common/decorators/restricted.decorator.ts +24 -12
  121. package/src/core/common/enums/role.enum.ts +23 -5
  122. package/src/core/common/helpers/config.helper.ts +26 -6
  123. package/src/core/common/helpers/context.helper.ts +42 -33
  124. package/src/core/common/helpers/db.helper.ts +595 -0
  125. package/src/core/common/helpers/file.helper.ts +76 -49
  126. package/src/core/common/helpers/filter.helper.ts +119 -96
  127. package/src/core/common/helpers/graphql.helper.ts +219 -117
  128. package/src/core/common/helpers/input.helper.ts +349 -108
  129. package/src/core/common/helpers/model.helper.ts +102 -57
  130. package/src/core/common/helpers/service.helper.ts +149 -117
  131. package/src/core/common/inputs/combined-filter.input.ts +2 -2
  132. package/src/core/common/inputs/core-input.input.ts +2 -2
  133. package/src/core/common/interceptors/check-response.interceptor.ts +2 -2
  134. package/src/core/common/interfaces/resolve-selector.interface.ts +9 -0
  135. package/src/core/common/interfaces/service-options.interface.ts +71 -0
  136. package/src/core/common/models/core-model.model.ts +7 -3
  137. package/src/core/common/pipes/check-input.pipe.ts +4 -4
  138. package/src/core/common/pipes/map-and-validate.pipe.ts +2 -2
  139. package/src/core/common/services/crud.service.ts +100 -0
  140. package/src/core/common/services/email.service.ts +9 -9
  141. package/src/core/common/services/module.service.ts +188 -0
  142. package/src/core/common/types/core-model-constructor.type.ts +30 -0
  143. package/src/core/common/types/field-selection.type.ts +8 -0
  144. package/src/core/common/types/ids.type.ts +7 -0
  145. package/src/core/common/types/string-or-object-id.type.ts +3 -0
  146. package/src/core/modules/auth/core-auth.module.ts +1 -1
  147. package/src/core/modules/auth/core-auth.resolver.ts +8 -3
  148. package/src/core/modules/auth/guards/roles.guard.ts +5 -7
  149. package/src/core/modules/auth/services/core-auth-user.service.ts +7 -1
  150. package/src/core/modules/auth/services/core-auth.service.ts +14 -4
  151. package/src/core/modules/user/core-user.model.ts +2 -1
  152. package/src/core/modules/user/core-user.service.ts +115 -185
  153. package/src/core.module.ts +2 -2
  154. package/src/index.ts +9 -1
  155. package/src/main.ts +1 -1
  156. package/src/server/modules/auth/auth.resolver.ts +8 -3
  157. package/src/server/modules/file/file.controller.ts +2 -2
  158. package/src/server/modules/user/avatar.controller.ts +3 -3
  159. package/src/server/modules/user/user.module.ts +7 -3
  160. package/src/server/modules/user/user.resolver.ts +74 -43
  161. package/src/server/modules/user/user.service.ts +30 -53
  162. package/src/test/test.helper.ts +31 -30
  163. package/dist/core/modules/user/core-basic-user.service.d.ts +0 -17
  164. package/dist/core/modules/user/core-basic-user.service.js +0 -73
  165. package/dist/core/modules/user/core-basic-user.service.js.map +0 -1
  166. package/src/core/modules/user/core-basic-user.service.ts +0 -138
@@ -1,14 +1,14 @@
1
1
  import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
2
2
  import { plainToInstance } from 'class-transformer';
3
3
  import { validate } from 'class-validator';
4
- import { InputHelper } from '../helpers/input.helper';
4
+ import { isBasicType } from '../helpers/input.helper';
5
5
 
6
6
  @Injectable()
7
7
  export class MapAndValidatePipe implements PipeTransform {
8
8
  async transform(value: any, metadata: ArgumentMetadata) {
9
9
  const { metatype } = metadata;
10
10
 
11
- if (typeof value !== 'object' || !metatype || InputHelper.isBasicType(metatype)) {
11
+ if (typeof value !== 'object' || !metatype || isBasicType(metatype)) {
12
12
  return value;
13
13
  }
14
14
 
@@ -0,0 +1,100 @@
1
+ import { NotFoundException } from '@nestjs/common';
2
+ import { FilterArgs } from '../args/filter.args';
3
+ import { merge } from '../helpers/config.helper';
4
+ import { convertFilterArgsToQuery } from '../helpers/filter.helper';
5
+ import { ServiceOptions } from '../interfaces/service-options.interface';
6
+ import { CoreModel } from '../models/core-model.model';
7
+ import { ModuleService } from './module.service';
8
+
9
+ export abstract class CrudService<T extends CoreModel = any> extends ModuleService<T> {
10
+ /**
11
+ * Create item
12
+ */
13
+ async create(input: any, serviceOptions?: ServiceOptions): Promise<T> {
14
+ merge({ prepareInput: { create: true } }, serviceOptions);
15
+ return this.process(
16
+ async (data) => {
17
+ return new this.mainDbModel({ ...data.input }).save();
18
+ },
19
+ { input, serviceOptions }
20
+ );
21
+ }
22
+
23
+ /**
24
+ * Get item by ID
25
+ */
26
+ async get(id: string, serviceOptions?: ServiceOptions): Promise<T> {
27
+ const dbObject = await this.mainDbModel.findById(id).exec();
28
+ if (!dbObject) {
29
+ throw new NotFoundException(`No ${this.mainModelConstructor.name} found with ID: ${id}`);
30
+ }
31
+ return this.process(async () => dbObject, { dbObject, serviceOptions });
32
+ }
33
+
34
+ /**
35
+ * Get items via filter
36
+ */
37
+ async find(filterArgs?: FilterArgs, serviceOptions?: ServiceOptions): Promise<T[]> {
38
+ return this.process(
39
+ async (data) => {
40
+ const filterQuery = convertFilterArgsToQuery(data.input);
41
+ return this.mainDbModel.find(filterQuery[0], null, filterQuery[1]).exec();
42
+ },
43
+ { input: filterArgs, serviceOptions }
44
+ );
45
+ }
46
+
47
+ /**
48
+ * CRUD alias for get
49
+ */
50
+ async read(id: string, serviceOptions?: ServiceOptions): Promise<T>;
51
+
52
+ /**
53
+ * CRUD alias for find
54
+ */
55
+ async read(filterArgs?: FilterArgs, serviceOptions?: ServiceOptions): Promise<T[]>;
56
+
57
+ /**
58
+ * CRUD alias for get or find
59
+ */
60
+ async read(input: string | FilterArgs, serviceOptions?: ServiceOptions): Promise<T | T[]> {
61
+ if (typeof input === 'string') {
62
+ return this.get(input, serviceOptions);
63
+ } else {
64
+ return this.find(input, serviceOptions);
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Update item via ID
70
+ */
71
+ async update(id: string, input: any, serviceOptions?: ServiceOptions): Promise<T> {
72
+ const dbObject = await this.mainDbModel.findById(id).exec();
73
+ if (!dbObject) {
74
+ throw new NotFoundException(`No ${this.mainModelConstructor.name} found with ID: ${id}`);
75
+ }
76
+ return this.process(
77
+ async (data) => {
78
+ return await Object.assign(dbObject, data.input).save();
79
+ },
80
+ { dbObject, input, serviceOptions }
81
+ );
82
+ }
83
+
84
+ /**
85
+ * Delete item via ID
86
+ */
87
+ async delete(id: string, serviceOptions?: ServiceOptions): Promise<T> {
88
+ const dbObject = await this.mainDbModel.findById(id).exec();
89
+ if (!dbObject) {
90
+ throw new NotFoundException(`No ${this.mainModelConstructor.name} found with ID: ${id}`);
91
+ }
92
+ return this.process(
93
+ async (data) => {
94
+ await this.mainDbModel.findByIdAndDelete(id).exec();
95
+ return dbObject;
96
+ },
97
+ { dbObject, input: id, serviceOptions }
98
+ );
99
+ }
100
+ }
@@ -1,7 +1,7 @@
1
1
  import { Injectable } from '@nestjs/common';
2
2
  import * as nodemailer from 'nodemailer';
3
3
  import { Attachment } from 'nodemailer/lib/mailer';
4
- import { InputHelper } from '../helpers/input.helper';
4
+ import { isNonEmptyString, isTrue, returnFalse } from '../helpers/input.helper';
5
5
  import { ConfigService } from './config.service';
6
6
  import { TemplateService } from './template.service';
7
7
 
@@ -43,10 +43,10 @@ export class EmailService {
43
43
  let text = config.text;
44
44
 
45
45
  // Check parameter
46
- InputHelper.isTrue(recipients);
47
- InputHelper.isNonEmptyString(subject);
48
- InputHelper.isNonEmptyString(senderName);
49
- InputHelper.isNonEmptyString(senderEmail);
46
+ isTrue(recipients);
47
+ isNonEmptyString(subject);
48
+ isNonEmptyString(senderName);
49
+ isNonEmptyString(senderEmail);
50
50
 
51
51
  // Process text template
52
52
  if (htmlTemplate) {
@@ -59,11 +59,11 @@ export class EmailService {
59
59
  }
60
60
 
61
61
  // Check if at lest one of text or html is set
62
- if (!InputHelper.isNonEmptyString(html, InputHelper.returnFalse)) {
63
- InputHelper.isNonEmptyString(text);
62
+ if (!isNonEmptyString(html, returnFalse)) {
63
+ isNonEmptyString(text);
64
64
  }
65
- if (!InputHelper.isNonEmptyString(text, InputHelper.returnFalse)) {
66
- InputHelper.isNonEmptyString(html);
65
+ if (!isNonEmptyString(text, returnFalse)) {
66
+ isNonEmptyString(html);
67
67
  }
68
68
 
69
69
  // Init transporter
@@ -0,0 +1,188 @@
1
+ import { Document, Model, Types } from 'mongoose';
2
+ import { getStringIds, popAndMap } from '../helpers/db.helper';
3
+ import { check } from '../helpers/input.helper';
4
+ import { prepareInput, prepareOutput } from '../helpers/service.helper';
5
+ import { ServiceOptions } from '../interfaces/service-options.interface';
6
+ import { CoreModel } from '../models/core-model.model';
7
+ import { FieldSelection } from '../types/field-selection.type';
8
+ import { IdsType } from '../types/ids.type';
9
+
10
+ /**
11
+ * Module service class to be extended by concrete module services
12
+ */
13
+ export abstract class ModuleService<T extends CoreModel = any> {
14
+ /**
15
+ * Main model constructor of the service, will be used as default for populate and mapping
16
+ */
17
+ protected mainModelConstructor: new (...args: any[]) => T;
18
+
19
+ /**
20
+ * Main DB model of the service, will be used as default for populate and mapping
21
+ */
22
+ protected mainDbModel: Model<T & Document>;
23
+
24
+ /**
25
+ * Set main properties
26
+ */
27
+ protected constructor(options?: {
28
+ mainDbModel: Model<T & Document>;
29
+ mainModelConstructor?: new (...args: any[]) => T;
30
+ }) {
31
+ this.mainDbModel = options?.mainDbModel;
32
+ this.mainModelConstructor = options?.mainModelConstructor;
33
+ }
34
+
35
+ /**
36
+ * Check rights of current user for input
37
+ */
38
+ checkRights(
39
+ input: any,
40
+ currentUser: { id: any; hasRole: (roles: string[]) => boolean },
41
+ options?: {
42
+ creator?: IdsType;
43
+ metatype?: any;
44
+ ownerIds?: IdsType;
45
+ roles?: string | string[];
46
+ throwError?: boolean;
47
+ }
48
+ ): Promise<any> {
49
+ const config = {
50
+ metatype: this.mainModelConstructor,
51
+ ...options,
52
+ };
53
+ return check(input, currentUser, config);
54
+ }
55
+
56
+ /**
57
+ * Get function to get Object via ID, necessary for checkInput
58
+ */
59
+ abstract get(id: any, ...args: any[]): any;
60
+
61
+ /**
62
+ * Run service function with pre- and post-functions
63
+ */
64
+ async process(
65
+ serviceFunc: (options?: { [key: string]: any; input?: any; serviceOptions?: ServiceOptions }) => any,
66
+ options?: {
67
+ [key: string]: any;
68
+ dbObject?: string | Types.ObjectId | any;
69
+ input?: any;
70
+ serviceOptions?: ServiceOptions;
71
+ }
72
+ ) {
73
+ // Configuration with default values
74
+ const config = {
75
+ checkRights: true,
76
+ dbObject: options?.dbObject,
77
+ input: options?.input,
78
+ processFieldSelection: {},
79
+ prepareInput: {},
80
+ prepareOutput: {},
81
+ pubSub: true,
82
+ ...options?.serviceOptions,
83
+ };
84
+
85
+ // Prepare input
86
+ if (config.prepareInput && this.prepareInput) {
87
+ await this.prepareInput(config.input, config.prepareInput);
88
+ }
89
+
90
+ // 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
+ }
98
+ }
99
+ }
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
+ }
111
+
112
+ // Check rights for input
113
+ if (config.input && config.checkRights && this.checkRights) {
114
+ const opts: any = { creator: (await getDbObject())?.createdBy, ownerIds, roles: config.roles };
115
+ if (config.inputType) {
116
+ opts.metatype = config.resultType;
117
+ }
118
+ config.input = await this.checkRights(config.input, config.currentUser as any, opts);
119
+ }
120
+
121
+ // Run service function
122
+ let result = await serviceFunc(config);
123
+
124
+ // Pop and map main model
125
+ if (config.processFieldSelection && config.fieldSelection && this.processFieldSelection) {
126
+ await this.processFieldSelection(result, config.fieldSelection, config.processFieldSelection);
127
+ }
128
+
129
+ // Prepare output
130
+ 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;
134
+ }
135
+ result = await this.prepareOutput(result, config.prepareOutput);
136
+ }
137
+
138
+ // Check output rights
139
+ 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;
143
+ }
144
+ result = await this.checkRights(result, config.currentUser as any, opts);
145
+ }
146
+
147
+ // Return (prepared) result
148
+ return result;
149
+ }
150
+
151
+ /**
152
+ * Prepare input before save
153
+ */
154
+ async prepareInput(input: Record<string, any>, options: ServiceOptions = {}) {
155
+ return prepareInput(input, options.currentUser, options.prepareInput);
156
+ }
157
+
158
+ /**
159
+ * Prepare output before return
160
+ */
161
+ async prepareOutput(output: any, options: ServiceOptions = {}) {
162
+ const config = {
163
+ targetModel: this.mainModelConstructor,
164
+ ...options?.prepareOutput,
165
+ };
166
+ return prepareOutput(output, config);
167
+ }
168
+
169
+ /**
170
+ * Process fieldSelection
171
+ * @protected
172
+ */
173
+ async processFieldSelection(
174
+ data: any,
175
+ fieldsSelection: FieldSelection,
176
+ options: {
177
+ model?: new (...args: any[]) => T;
178
+ dbModel?: Model<T & Document>;
179
+ } = {}
180
+ ) {
181
+ const config = {
182
+ model: this.mainModelConstructor,
183
+ dbModel: this.mainDbModel,
184
+ ...options,
185
+ };
186
+ return popAndMap(data, fieldsSelection, config.model, config.dbModel);
187
+ }
188
+ }
@@ -0,0 +1,30 @@
1
+ import { CoreModel } from '../models/core-model.model';
2
+
3
+ export type CoreModelConstructor<T extends CoreModel> = {
4
+ new (): T;
5
+ init(this: new (...args: any[]) => T, ...args: any[]): T;
6
+ map(
7
+ this: new (...args: any[]) => T,
8
+ data: Partial<T> | Record<string, any>,
9
+ options?: {
10
+ [key: string]: any;
11
+ cloneDeep?: boolean;
12
+ funcAllowed?: boolean;
13
+ init?: any;
14
+ item?: T;
15
+ mapId?: boolean;
16
+ }
17
+ ): T;
18
+ mapDeep(
19
+ this: new (...args: any[]) => T,
20
+ data: Partial<T> | Record<string, any>,
21
+ options: {
22
+ [key: string]: any;
23
+ cloneDeep?: boolean;
24
+ funcAllowed?: boolean;
25
+ init?: any;
26
+ item?: T;
27
+ mapId?: boolean;
28
+ }
29
+ ): T;
30
+ };
@@ -0,0 +1,8 @@
1
+ import { SelectionNode } from 'graphql';
2
+ import { PopulateOptions } from 'mongoose';
3
+ import { ResolveSelector } from '../interfaces/resolve-selector.interface';
4
+
5
+ /**
6
+ * Field selection to set fields of (populated) result
7
+ */
8
+ export type FieldSelection = PopulateOptions[] | SelectionNode[] | ResolveSelector;
@@ -0,0 +1,7 @@
1
+ import { Types } from 'mongoose';
2
+
3
+ export type IdsType =
4
+ | string
5
+ | Types.ObjectId
6
+ | { id?: string | Types.ObjectId; _id?: string | Types.ObjectId }
7
+ | (string | Types.ObjectId | { id?: string | Types.ObjectId; _id?: string | Types.ObjectId })[];
@@ -0,0 +1,3 @@
1
+ import { Types } from 'mongoose';
2
+
3
+ export type StringOrObjectId = string | Types.ObjectId | any;
@@ -25,7 +25,7 @@ export class CoreAuthModule {
25
25
  providers?: Provider[];
26
26
  }
27
27
  ): DynamicModule {
28
- // Porcess imports
28
+ // Process imports
29
29
  let imports: any[] = [UserModule, PassportModule.register({ defaultStrategy: 'jwt' }), JwtModule.register(options)];
30
30
  if (Array.isArray(options?.imports)) {
31
31
  imports = imports.concat(options.imports);
@@ -1,4 +1,5 @@
1
- import { Args, Query, Resolver } from '@nestjs/graphql';
1
+ import { Args, Info, Query, Resolver } from '@nestjs/graphql';
2
+ import { GraphQLResolveInfo } from 'graphql';
2
3
  import { CoreAuthModel } from './core-auth.model';
3
4
  import { CoreAuthService } from './services/core-auth.service';
4
5
 
@@ -20,7 +21,11 @@ export class CoreAuthResolver {
20
21
  * Get user via ID
21
22
  */
22
23
  @Query((returns) => CoreAuthModel, { description: 'Get JWT token' })
23
- async signIn(@Args('email') email: string, @Args('password') password: string): Promise<Partial<CoreAuthModel>> {
24
- return await this.authService.signIn(email, password);
24
+ async signIn(
25
+ @Args('email') email: string,
26
+ @Args('password') password: string,
27
+ @Info() info: GraphQLResolveInfo
28
+ ): Promise<Partial<CoreAuthModel>> {
29
+ return await this.authService.signIn(email, password, { fieldSelection: { info, select: 'signIn' } });
25
30
  }
26
31
  }
@@ -1,4 +1,4 @@
1
- import { ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
1
+ import { ExecutionContext, Inject, Injectable, UnauthorizedException } from '@nestjs/common';
2
2
  import { Reflector } from '@nestjs/core';
3
3
  import { GqlExecutionContext } from '@nestjs/graphql';
4
4
  import { RoleEnum } from '../../../common/enums/role.enum';
@@ -8,7 +8,8 @@ import { AuthGuard } from './auth.guard';
8
8
  * Role guard
9
9
  *
10
10
  * The RoleGuard is activated by the Role decorator. It checks whether the current user has at least one of the
11
- * specified roles. If this is not the case, an UnauthorizedException is thrown.
11
+ * specified roles or is logged in when the S_USER role is set.
12
+ * If this is not the case, an UnauthorizedException is thrown.
12
13
  */
13
14
  @Injectable()
14
15
  export class RolesGuard extends AuthGuard('jwt') {
@@ -41,11 +42,8 @@ export class RolesGuard extends AuthGuard('jwt') {
41
42
  // Get args
42
43
  const args: any = GqlExecutionContext.create(context).getArgs();
43
44
 
44
- // Check special role for user or owner
45
- if (
46
- user &&
47
- (roles.includes(RoleEnum.USER) || (roles.includes(RoleEnum.OWNER) && user.id.toString() === args.id))
48
- ) {
45
+ // Check special user role (user is logged in)
46
+ if (user && roles.includes(RoleEnum.S_USER)) {
49
47
  return user;
50
48
  }
51
49
 
@@ -1,3 +1,4 @@
1
+ import { ServiceOptions } from '../../../common/interfaces/service-options.interface';
1
2
  import { ICoreAuthUser } from '../interfaces/core-auth-user.interface';
2
3
 
3
4
  /**
@@ -7,5 +8,10 @@ export abstract class CoreAuthUserService {
7
8
  /**
8
9
  * Get user via email
9
10
  */
10
- abstract getViaEmail(email: string): Promise<ICoreAuthUser>;
11
+ abstract getViaEmail(email: string, serviceOptions?: ServiceOptions): Promise<ICoreAuthUser>;
12
+
13
+ /**
14
+ * Prepare output
15
+ */
16
+ abstract prepareOutput(output: any, options?: ServiceOptions): Promise<ICoreAuthUser>;
11
17
  }
@@ -1,6 +1,8 @@
1
1
  import { Injectable, UnauthorizedException } from '@nestjs/common';
2
2
  import { JwtService } from '@nestjs/jwt';
3
3
  import * as bcrypt from 'bcrypt';
4
+ import { merge } from '../../../common/helpers/config.helper';
5
+ import { ServiceOptions } from '../../../common/interfaces/service-options.interface';
4
6
  import { ICoreAuthUser } from '../interfaces/core-auth-user.interface';
5
7
  import { JwtPayload } from '../interfaces/jwt-payload.interface';
6
8
  import { CoreAuthUserService } from './core-auth-user.service';
@@ -15,15 +17,20 @@ export class CoreAuthService {
15
17
  /**
16
18
  * User sign in via email
17
19
  */
18
- async signIn(email: string, password: string): Promise<{ token: string; user: ICoreAuthUser }> {
19
- const user = await this.userService.getViaEmail(email);
20
- if (!(await bcrypt.compare(password, user.password))) {
20
+ async signIn(
21
+ email: string,
22
+ password: string,
23
+ serviceOptions?: ServiceOptions
24
+ ): Promise<{ token: string; user: ICoreAuthUser }> {
25
+ serviceOptions = merge(serviceOptions || {}, { prepareOutput: null });
26
+ const user = await this.userService.getViaEmail(email, serviceOptions);
27
+ if (!user || !(await bcrypt.compare(password, user.password))) {
21
28
  throw new UnauthorizedException();
22
29
  }
23
30
  const payload: JwtPayload = { email: user.email };
24
31
  return {
25
32
  token: this.jwtService.sign(payload),
26
- user,
33
+ user: await this.userService.prepareOutput(user),
27
34
  };
28
35
  }
29
36
 
@@ -34,6 +41,9 @@ export class CoreAuthService {
34
41
  return await this.userService.getViaEmail(payload.email);
35
42
  }
36
43
 
44
+ /**
45
+ * Decode JWT
46
+ */
37
47
  decodeJwt(token: string): JwtPayload {
38
48
  return this.jwtService.decode(token) as JwtPayload;
39
49
  }
@@ -1,8 +1,9 @@
1
1
  import { Field, ObjectType } from '@nestjs/graphql';
2
+ import { Prop, Schema as MongooseSchema } from '@nestjs/mongoose';
2
3
  import { IsEmail, IsOptional } from 'class-validator';
3
4
  import { Document } from 'mongoose';
5
+ import { User } from '../../../server/modules/user/user.model';
4
6
  import { CorePersistenceModel } from '../../common/models/core-persistence.model';
5
- import { Prop, Schema as MongooseSchema } from '@nestjs/mongoose';
6
7
 
7
8
  export type CoreUserModelDocument = CoreUserModel & Document;
8
9