@lenne.tech/nest-server 8.6.27 → 8.6.28

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 (45) hide show
  1. package/dist/core/common/helpers/input.helper.d.ts +10 -1
  2. package/dist/core/common/helpers/input.helper.js +46 -4
  3. package/dist/core/common/helpers/input.helper.js.map +1 -1
  4. package/dist/core/common/helpers/model.helper.d.ts +4 -0
  5. package/dist/core/common/helpers/model.helper.js +10 -3
  6. package/dist/core/common/helpers/model.helper.js.map +1 -1
  7. package/dist/core/common/helpers/service.helper.d.ts +12 -0
  8. package/dist/core/common/helpers/service.helper.js +13 -5
  9. package/dist/core/common/helpers/service.helper.js.map +1 -1
  10. package/dist/core/common/services/config.service.d.ts +75 -5
  11. package/dist/core/common/services/config.service.js +168 -4
  12. package/dist/core/common/services/config.service.js.map +1 -1
  13. package/dist/core/common/services/email.service.js +2 -2
  14. package/dist/core/common/services/email.service.js.map +1 -1
  15. package/dist/core/common/services/mailjet.service.js +4 -4
  16. package/dist/core/common/services/mailjet.service.js.map +1 -1
  17. package/dist/core/common/services/template.service.js +1 -1
  18. package/dist/core/common/services/template.service.js.map +1 -1
  19. package/dist/core/modules/user/core-user.service.d.ts +5 -3
  20. package/dist/core/modules/user/core-user.service.js +3 -3
  21. package/dist/core/modules/user/core-user.service.js.map +1 -1
  22. package/dist/server/common/services/cron-jobs.service.d.ts +3 -1
  23. package/dist/server/common/services/cron-jobs.service.js +5 -4
  24. package/dist/server/common/services/cron-jobs.service.js.map +1 -1
  25. package/dist/server/modules/auth/auth.service.d.ts +3 -1
  26. package/dist/server/modules/auth/auth.service.js +9 -4
  27. package/dist/server/modules/auth/auth.service.js.map +1 -1
  28. package/dist/server/modules/user/user.service.js +5 -3
  29. package/dist/server/modules/user/user.service.js.map +1 -1
  30. package/dist/server/server.controller.js +2 -2
  31. package/dist/server/server.controller.js.map +1 -1
  32. package/dist/tsconfig.build.tsbuildinfo +1 -1
  33. package/package.json +4 -3
  34. package/src/core/common/helpers/input.helper.ts +68 -4
  35. package/src/core/common/helpers/model.helper.ts +14 -3
  36. package/src/core/common/helpers/service.helper.ts +25 -5
  37. package/src/core/common/services/config.service.ts +378 -12
  38. package/src/core/common/services/email.service.ts +2 -2
  39. package/src/core/common/services/mailjet.service.ts +4 -4
  40. package/src/core/common/services/template.service.ts +1 -1
  41. package/src/core/modules/user/core-user.service.ts +5 -4
  42. package/src/server/common/services/cron-jobs.service.ts +3 -3
  43. package/src/server/modules/auth/auth.service.ts +7 -3
  44. package/src/server/modules/user/user.service.ts +5 -3
  45. package/src/server/server.controller.ts +2 -2
@@ -1,35 +1,401 @@
1
1
  import * as _ from 'lodash';
2
+ import { cloneDeep } from 'lodash';
3
+ import { BehaviorSubject, firstValueFrom } from 'rxjs';
4
+ import { filter, map } from 'rxjs/operators';
5
+ import { merge } from '../helpers/config.helper';
6
+ import { clone, deepFreeze } from '../helpers/input.helper';
2
7
  import { IServerOptions } from '../interfaces/server-options.interface';
3
8
 
4
9
  /**
5
- * Config service
10
+ * Config service can be used as provider (after initialization in CoreModule.forRoot)
11
+ *
12
+ * Note:
13
+ *
14
+ * Direct access to the global configuration is not intended, since all objects in JavaScript interact by reference
15
+ * it can come to unintentional changes. Two protected properties are available for access `config` and
16
+ * `configFastButReadOnly`, as well as several methods that use these properties.
17
+ *
18
+ * The return value of `configFastButReadOnly` is a cached deep frozen object to speed up access and to avoid unwanted
19
+ * side effects (like accidentally changing the global configuration). However, this results in the object and all its
20
+ * contents being read-only. Attempts to change the configuration will result in the
21
+ * `TypeError: Cannot assign to read only property ...` If this error occurs during further processing of the
22
+ * configuration, `config` should be used instead of `configFastButReadOnly`. The access via `config` is substantially
23
+ * slower, but offers the advantage that the clone can be processed further (also without changing the
24
+ * global configuration).
25
+ *
26
+ * `configFastButReadOnly` => fast read only copy of global configuration
27
+ * (return value of getFastButReadOnly, observableFastButReadOnly and promiseFastButReadOnly)
28
+ *
29
+ * `config` => slower read and writeable copy of global configuration
30
+ * (return value of get, observable and promise)
6
31
  */
7
32
  export class ConfigService {
33
+ // ===================================================================================================================
34
+ // Properties
35
+ // ===================================================================================================================
36
+
8
37
  /**
9
- * Configuration on startup
38
+ * BehaviorSubject for config
10
39
  */
11
- protected readonly _config: { [key: string]: any } & Partial<IServerOptions>;
40
+ protected static _configSubject$: BehaviorSubject<{ [key: string]: any } & Partial<IServerOptions>> =
41
+ new BehaviorSubject(undefined);
12
42
 
13
43
  /**
14
- * Create config service
44
+ * BehaviorSubject for frozen config
15
45
  */
16
- constructor(config: { [key: string]: any } & Partial<IServerOptions>) {
17
- this._config = config || {};
46
+ protected static _frozenConfigSubject$: BehaviorSubject<{ [key: string]: any } & Partial<IServerOptions>> =
47
+ new BehaviorSubject(undefined);
48
+
49
+ /**
50
+ * Singleton instance of ConfigService
51
+ */
52
+ protected static _instance: ConfigService;
53
+
54
+ // ===================================================================================================================
55
+ // Constructor
56
+ // ===================================================================================================================
57
+
58
+ /**
59
+ * Create config service or return singleton instance if exists
60
+ */
61
+ constructor(
62
+ configObject?: { [key: string]: any } & Partial<IServerOptions>,
63
+ options?: { reInit?: boolean; warn?: boolean }
64
+ ) {
65
+ const config = {
66
+ reInit: false,
67
+ warn: true,
68
+ ...options,
69
+ };
70
+
71
+ // Check initialization status
72
+ const isInitialized = ConfigService.isInitialized;
73
+
74
+ // Init subject handling
75
+ if (!isInitialized) {
76
+ ConfigService._configSubject$.subscribe((config) => {
77
+ ConfigService._frozenConfigSubject$.next(deepFreeze(config));
78
+ });
79
+ }
80
+
81
+ // Set config before setting instance
82
+ if (typeof configObject === 'object') {
83
+ isInitialized
84
+ ? ConfigService.mergeConfig(configObject, { ...config, ...{ init: false } })
85
+ : ConfigService.setConfig(configObject, { ...config, ...{ init: false } });
86
+ }
87
+
88
+ // Set instance if not yet initialized
89
+ if (!isInitialized) {
90
+ ConfigService._instance = this;
91
+ }
92
+
93
+ // Return instance
94
+ return ConfigService._instance;
18
95
  }
19
96
 
97
+ // ===================================================================================================================
98
+ // Getter / Queries
99
+ // ===================================================================================================================
100
+
20
101
  /**
21
- * Get config (deep cloned to avoid unwanted side effects)
102
+ * Get readable and writable deep-cloned configuration
22
103
  */
23
104
  get config() {
24
- return _.cloneDeep(this._config);
105
+ return ConfigService.config;
25
106
  }
26
107
 
27
108
  /**
28
- * Get data from config (deep cloned to avoid unwanted side effects)
29
- * @param key Property name of config object, which is to be returned
30
- * @param defaultValue Default value which is to be returned if property doesn't exist
109
+ * Get readable and writable deep-cloned configuration
110
+ */
111
+ static get config() {
112
+ return clone(ConfigService._configSubject$.getValue(), { circles: false });
113
+ }
114
+
115
+ /**
116
+ * Get faster but read-only deep-frozen configuration
117
+ */
118
+ get configFastButReadOnly() {
119
+ return ConfigService.configFastButReadOnly;
120
+ }
121
+
122
+ /**
123
+ * Get faster but read-only deep-frozen configuration
124
+ */
125
+ static get configFastButReadOnly() {
126
+ return ConfigService._frozenConfigSubject$.getValue();
127
+ }
128
+
129
+ /**
130
+ * Get readable and writable deep-cloned property from configuration
31
131
  */
32
132
  get(key: string, defaultValue: any = undefined) {
33
- return _.cloneDeep(_.get(this._config, key, defaultValue));
133
+ return ConfigService.get(key, defaultValue);
134
+ }
135
+
136
+ /**
137
+ * Get readable and writable deep-cloned property from configuration
138
+ */
139
+ static get(key: string, defaultValue: any = undefined) {
140
+ return clone(_.get(ConfigService._configSubject$.getValue(), key, defaultValue), { circles: false });
141
+ }
142
+
143
+ /**
144
+ * Get faster but read-ony deep-frozen property from configuration
145
+ */
146
+ getFastButReadOnly(key: string, defaultValue: any = undefined) {
147
+ return ConfigService.getFastButReadOnly(key, defaultValue);
148
+ }
149
+
150
+ /**
151
+ * Get faster but read-ony deep-frozen property from configuration
152
+ */
153
+ static getFastButReadOnly(key: string, defaultValue: any = undefined) {
154
+ return _.get(ConfigService._frozenConfigSubject$.getValue(), key, defaultValue);
155
+ }
156
+
157
+ /**
158
+ * Whether the ConfigService is initialized
159
+ */
160
+ get isInitialized() {
161
+ return ConfigService.isInitialized;
162
+ }
163
+
164
+ /**
165
+ * Whether the ConfigService is initialized
166
+ */
167
+ static get isInitialized() {
168
+ return !!ConfigService._instance;
169
+ }
170
+
171
+ /**
172
+ * Get observable for readable and writable deep-cloned configuration
173
+ */
174
+ get observableClone() {
175
+ return ConfigService.observable;
176
+ }
177
+
178
+ /**
179
+ * Get observable for readable and writable deep-cloned configuration
180
+ */
181
+ static get observable() {
182
+ return ConfigService._configSubject$.asObservable().pipe(
183
+ filter((config) => !config),
184
+ map((config) => clone(config, { circles: false }))
185
+ );
186
+ }
187
+
188
+ /**
189
+ * Get observable for faster but read-only deep-frozen configuration
190
+ */
191
+ get observableFastButReadOnly() {
192
+ return ConfigService.observableFastButReadOnly;
193
+ }
194
+
195
+ /**
196
+ * Get observable for faster but read-only deep-frozen configuration
197
+ */
198
+ static get observableFastButReadOnly() {
199
+ return ConfigService._frozenConfigSubject$.asObservable().pipe(filter((config) => !config));
200
+ }
201
+
202
+ /**
203
+ * Get promise of first readable and writable deep-cloned configuration
204
+ */
205
+ get promise() {
206
+ return ConfigService.promise;
207
+ }
208
+
209
+ /**
210
+ * Get promise of first readable and writable deep-cloned configuration
211
+ */
212
+ static get promise() {
213
+ return firstValueFrom(ConfigService.observable);
214
+ }
215
+
216
+ /**
217
+ * Get promise of first faster but read-ony deep-frozen configuration
218
+ */
219
+ get promiseFastButReadOnly() {
220
+ return ConfigService.promiseFastButReadOnly;
221
+ }
222
+
223
+ /**
224
+ * Get promise of first faster but read-ony deep-frozen configuration
225
+ */
226
+ static get promiseFastButReadOnly() {
227
+ return firstValueFrom(ConfigService.observableFastButReadOnly);
228
+ }
229
+
230
+ // ===================================================================================================================
231
+ // Setter / Mutations
232
+ // ===================================================================================================================
233
+
234
+ /**
235
+ * Merge config and set in ConfigService
236
+ */
237
+ mergeConfig(configData: { [key: string]: any } & Partial<IServerOptions>, options?: { warn?: boolean }) {
238
+ return ConfigService.mergeConfig(configData, options);
239
+ }
240
+
241
+ /**
242
+ * Merge config and set in ConfigService
243
+ */
244
+ static mergeConfig(
245
+ configData: { [key: string]: any } & Partial<IServerOptions>,
246
+ options?: { init?: boolean; warn?: boolean }
247
+ ) {
248
+ const config = {
249
+ init: true,
250
+ warn: false,
251
+ ...options,
252
+ };
253
+
254
+ // Get initialization status
255
+ const isInitialized = ConfigService.isInitialized;
256
+
257
+ // Init config service instance, if not yet initialized
258
+ if (!isInitialized && config.init) {
259
+ new ConfigService();
260
+ }
261
+
262
+ // Merge config
263
+ const activity = isInitialized ? 'merged' : 'initialized';
264
+ const merged = merge(ConfigService._configSubject$.getValue() || {}, cloneDeep(configData));
265
+ ConfigService._configSubject$.next(merged);
266
+
267
+ // Warn if requested
268
+ if (config.warn) {
269
+ console.warn('ConfigService ' + activity, JSON.stringify(merged, null, 2));
270
+ }
271
+
272
+ // Return configuration
273
+ return ConfigService.config;
274
+ }
275
+
276
+ /**
277
+ * Merge config property and set in ConfigService
278
+ */
279
+ mergeProperty(key: string, value: any, options?: { warn?: boolean }) {
280
+ return ConfigService.mergeProperty(key, options);
281
+ }
282
+
283
+ /**
284
+ * Merge config property and set in ConfigService
285
+ */
286
+ static mergeProperty(key: string, value: any, options?: { warn?: boolean }) {
287
+ const config = {
288
+ warn: false,
289
+ ...options,
290
+ };
291
+
292
+ // Init config service instance, if not yet initialized
293
+ if (!ConfigService.isInitialized) {
294
+ new ConfigService();
295
+ }
296
+
297
+ // Merge property
298
+ const current = ConfigService._configSubject$.getValue() || {};
299
+ if (typeof value === 'object') {
300
+ current[key] = merge(current[key], cloneDeep(value));
301
+ } else {
302
+ current[key] = value;
303
+ }
304
+ ConfigService._configSubject$.next(current);
305
+
306
+ // Warn if requested
307
+ if (config.warn) {
308
+ console.warn('ConfigService ' + key + ':', JSON.stringify(current[key], null, 2));
309
+ }
310
+
311
+ // Return configuration
312
+ return ConfigService.config;
313
+ }
314
+
315
+ /**
316
+ * Set config in ConfigService
317
+ */
318
+ setConfig(
319
+ configData: { [key: string]: any } & Partial<IServerOptions>,
320
+ options?: { reInit?: boolean; warn?: boolean }
321
+ ) {
322
+ return ConfigService.setConfig(configData, options);
323
+ }
324
+
325
+ /**
326
+ * Set config in ConfigService
327
+ */
328
+ static setConfig(
329
+ configObject: { [key: string]: any } & Partial<IServerOptions>,
330
+ options?: { init?: boolean; reInit?: boolean; warn?: boolean }
331
+ ) {
332
+ const config = {
333
+ init: true,
334
+ reInit: true,
335
+ warn: false,
336
+ ...options,
337
+ };
338
+
339
+ // Check initialization
340
+ const firstInitialization = !ConfigService.isInitialized;
341
+
342
+ // Check for unintentional overwriting
343
+ if (!firstInitialization && !config.reInit) {
344
+ throw new Error(
345
+ 'Unintentional overwriting of the configuration. ' +
346
+ 'If overwriting is desired, please set `reInit` in setConfig of ConfigService to `true`.'
347
+ );
348
+ }
349
+
350
+ // Init config service instance, if not yet initialized
351
+ if (firstInitialization && config.init) {
352
+ new ConfigService();
353
+ }
354
+
355
+ // (Re)Init
356
+ if (firstInitialization || config.reInit) {
357
+ ConfigService._configSubject$.next(configObject || {});
358
+
359
+ // Warn if requested
360
+ if (config.warn && !firstInitialization) {
361
+ console.warn('ConfigService reinitialized', JSON.stringify(configObject, null, 2));
362
+ }
363
+ }
364
+
365
+ // Return configuration
366
+ return ConfigService.config;
367
+ }
368
+
369
+ /**
370
+ * Set config property in ConfigService
371
+ */
372
+ setProperty(key: string, value: any, options?: { warn?: boolean }) {
373
+ return ConfigService.setProperty(key, options);
374
+ }
375
+
376
+ /**
377
+ * Set config property in ConfigService
378
+ */
379
+ static setProperty(key: string, value: any, options?: { warn?: boolean }) {
380
+ const config = {
381
+ warn: false,
382
+ ...options,
383
+ };
384
+
385
+ // Init config service instance
386
+ if (!ConfigService.isInitialized) {
387
+ new ConfigService();
388
+ }
389
+
390
+ // Set property
391
+ const current = ConfigService._configSubject$.getValue() || {};
392
+ current[key] = value;
393
+ ConfigService._configSubject$.next(current);
394
+ if (config.warn) {
395
+ console.warn('ConfigService ' + key + ':', JSON.stringify(value, null, 2));
396
+ }
397
+
398
+ // Return config
399
+ return ConfigService.config;
34
400
  }
35
401
  }
@@ -34,8 +34,8 @@ export class EmailService {
34
34
  ): Promise<any> {
35
35
  // Process config
36
36
  const { attachments, htmlTemplate, senderName, senderEmail, templateData, textTemplate } = {
37
- senderEmail: this.configService.get('email.defaultSender.email'),
38
- senderName: this.configService.get('email.defaultSender.name'),
37
+ senderEmail: this.configService.getFastButReadOnly('email.defaultSender.email'),
38
+ senderName: this.configService.getFastButReadOnly('email.defaultSender.name'),
39
39
  ...config,
40
40
  };
41
41
 
@@ -34,8 +34,8 @@ export class MailjetService {
34
34
  ) {
35
35
  // Process config
36
36
  const { senderName, senderEmail, templateData, attachments, sandbox } = {
37
- senderEmail: this.configService.get('email.defaultSender.email'),
38
- senderName: this.configService.get('email.defaultSender.name'),
37
+ senderEmail: this.configService.getFastButReadOnly('email.defaultSender.email'),
38
+ senderName: this.configService.getFastButReadOnly('email.defaultSender.name'),
39
39
  sandbox: false,
40
40
  attachments: null,
41
41
  templateData: null,
@@ -76,8 +76,8 @@ export class MailjetService {
76
76
  try {
77
77
  // Connect to mailjet
78
78
  connection = new Mailjet({
79
- apiKey: this.configService.get('email.mailjet.api_key_public'),
80
- apiSecret: this.configService.get('email.mailjet.api_key_private'),
79
+ apiKey: this.configService.getFastButReadOnly('email.mailjet.api_key_public'),
80
+ apiSecret: this.configService.getFastButReadOnly('email.mailjet.api_key_private'),
81
81
  });
82
82
  } catch (e) {
83
83
  throw new Error('Cannot connect to mailjet.');
@@ -44,7 +44,7 @@ export class TemplateService {
44
44
 
45
45
  // Get template file
46
46
  fs.readFile(
47
- join(this.configService.get('templates.path'), filePath) + '.ejs',
47
+ join(this.configService.getFastButReadOnly('templates.path'), filePath) + '.ejs',
48
48
  { encoding: 'utf8' },
49
49
  (err, data) => {
50
50
  if (err) {
@@ -3,10 +3,10 @@ import * as bcrypt from 'bcrypt';
3
3
  import * as crypto from 'crypto';
4
4
  import { sha256 } from 'js-sha256';
5
5
  import { Document, Model } from 'mongoose';
6
- import envConfig from '../../../config.env';
7
6
  import { merge } from '../../common/helpers/config.helper';
8
7
  import { assignPlain } from '../../common/helpers/input.helper';
9
8
  import { ServiceOptions } from '../../common/interfaces/service-options.interface';
9
+ import { ConfigService } from '../../common/services/config.service';
10
10
  import { CrudService } from '../../common/services/crud.service';
11
11
  import { EmailService } from '../../common/services/email.service';
12
12
  import { CoreModelConstructor } from '../../common/types/core-model-constructor.type';
@@ -23,9 +23,10 @@ export abstract class CoreUserService<
23
23
  TUserCreateInput extends CoreUserCreateInput
24
24
  > extends CrudService<TUser> {
25
25
  protected constructor(
26
- protected emailService: EmailService,
26
+ protected readonly emailService: EmailService,
27
27
  protected readonly mainDbModel: Model<TUser & Document>,
28
- protected mainModelConstructor: CoreModelConstructor<TUser>
28
+ protected readonly mainModelConstructor: CoreModelConstructor<TUser>,
29
+ protected readonly configService?: ConfigService
29
30
  ) {
30
31
  super();
31
32
  }
@@ -132,7 +133,7 @@ export abstract class CoreUserService<
132
133
  async () => {
133
134
  // Check if the password was transmitted encrypted
134
135
  // If not, the password is encrypted to enable future encrypted and unencrypted transmissions
135
- if (envConfig.sha256 && !/^[a-f0-9]{64}$/i.test(newPassword)) {
136
+ if (this.configService.configFastButReadOnly.sha256 && !/^[a-f0-9]{64}$/i.test(newPassword)) {
136
137
  newPassword = sha256(newPassword);
137
138
  }
138
139
 
@@ -1,6 +1,6 @@
1
1
  import { Injectable } from '@nestjs/common';
2
2
  import { SchedulerRegistry } from '@nestjs/schedule';
3
- import envConfig from '../../../config.env';
3
+ import { ConfigService } from '../../../core/common/services/config.service';
4
4
  import { CoreCronJobs } from '../../../core/common/services/core-cron-jobs.service';
5
5
 
6
6
  @Injectable()
@@ -12,8 +12,8 @@ export class CronJobs extends CoreCronJobs {
12
12
  /**
13
13
  * Init cron jobs
14
14
  */
15
- constructor(protected schedulerRegistry: SchedulerRegistry) {
16
- super(schedulerRegistry, envConfig.cronJobs, { log: true });
15
+ constructor(protected schedulerRegistry: SchedulerRegistry, protected configService: ConfigService) {
16
+ super(schedulerRegistry, configService.config.cronJobs, { log: true });
17
17
  }
18
18
 
19
19
  // ===================================================================================================================
@@ -2,11 +2,11 @@ import { Injectable, UnauthorizedException } from '@nestjs/common';
2
2
  import { JwtService } from '@nestjs/jwt';
3
3
  import * as bcrypt from 'bcrypt';
4
4
  import { sha256 } from 'js-sha256';
5
- import envConfig from '../../../config.env';
6
5
  import { Roles } from '../../../core/common/decorators/roles.decorator';
7
6
  import { RoleEnum } from '../../../core/common/enums/role.enum';
8
7
  import { prepareServiceOptions } from '../../../core/common/helpers/service.helper';
9
8
  import { ServiceOptions } from '../../../core/common/interfaces/service-options.interface';
9
+ import { ConfigService } from '../../../core/common/services/config.service';
10
10
  import { EmailService } from '../../../core/common/services/email.service';
11
11
  import { JwtPayload } from '../../../core/modules/auth/interfaces/jwt-payload.interface';
12
12
  import { UserService } from '../user/user.service';
@@ -20,7 +20,8 @@ export class AuthService {
20
20
  constructor(
21
21
  protected readonly jwtService: JwtService,
22
22
  protected readonly emailService: EmailService,
23
- protected readonly userService: UserService
23
+ protected readonly userService: UserService,
24
+ protected readonly configService: ConfigService
24
25
  ) {}
25
26
 
26
27
  /**
@@ -77,7 +78,10 @@ export class AuthService {
77
78
  // Send email
78
79
  await this.emailService.sendMail(user.email, 'Welcome', {
79
80
  htmlTemplate: 'welcome',
80
- templateData: { name: user.username, link: envConfig.email.verificationLink + '/' + user.verificationToken },
81
+ templateData: {
82
+ name: user.username,
83
+ link: this.configService.configFastButReadOnly.email.verificationLink + '/' + user.verificationToken,
84
+ },
81
85
  });
82
86
 
83
87
  // Create JWT and return sign-in data
@@ -3,7 +3,6 @@ import { InjectModel } from '@nestjs/mongoose';
3
3
  import * as fs from 'fs';
4
4
  import { PubSub } from 'graphql-subscriptions';
5
5
  import { Model } from 'mongoose';
6
- import envConfig from '../../../config.env';
7
6
  import { ServiceOptions } from '../../../core/common/interfaces/service-options.interface';
8
7
  import { ConfigService } from '../../../core/common/services/config.service';
9
8
  import { EmailService } from '../../../core/common/services/email.service';
@@ -72,7 +71,10 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
72
71
  // Send email
73
72
  await this.emailService.sendMail(user.email, 'Password reset', {
74
73
  htmlTemplate: 'password-reset',
75
- templateData: { name: user.username, link: envConfig.email.passwordResetLink + '/' + user.passwordResetToken },
74
+ templateData: {
75
+ name: user.username,
76
+ link: this.configService.configFastButReadOnly.email.passwordResetLink + '/' + user.passwordResetToken,
77
+ },
76
78
  });
77
79
 
78
80
  // Return user
@@ -96,7 +98,7 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
96
98
 
97
99
  // Remove old avatar image
98
100
  if (user.avatar) {
99
- fs.unlink(envConfig.staticAssets.path + '/avatars/' + user.avatar, (err) => {
101
+ fs.unlink(this.configService.configFastButReadOnly.staticAssets.path + '/avatars/' + user.avatar, (err) => {
100
102
  if (err) {
101
103
  console.error(err);
102
104
  }
@@ -9,13 +9,13 @@ export class ServerController {
9
9
  @Render('index')
10
10
  root() {
11
11
  return {
12
- env: this.configService.get('env'),
12
+ env: this.configService.getFastButReadOnly('env'),
13
13
  };
14
14
  }
15
15
 
16
16
  @Get('config')
17
17
  @Roles(RoleEnum.ADMIN)
18
18
  config() {
19
- return this.configService.config;
19
+ return this.configService.configFastButReadOnly;
20
20
  }
21
21
  }