@lenne.tech/nest-server 8.0.2 → 8.1.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.
- package/dist/core/common/args/pagination.args.js +1 -1
- package/dist/core/common/args/pagination.args.js.map +1 -1
- package/dist/core/common/helpers/config.helper.d.ts +2 -1
- package/dist/core/common/helpers/config.helper.js +11 -7
- package/dist/core/common/helpers/config.helper.js.map +1 -1
- package/dist/core/common/helpers/context.helper.d.ts +7 -1
- package/dist/core/common/helpers/context.helper.js +33 -29
- package/dist/core/common/helpers/context.helper.js.map +1 -1
- package/dist/core/common/helpers/db.helper.d.ts +35 -0
- package/dist/core/common/helpers/db.helper.js +345 -0
- package/dist/core/common/helpers/db.helper.js.map +1 -0
- package/dist/core/common/helpers/file.helper.d.ts +8 -1
- package/dist/core/common/helpers/file.helper.js +43 -31
- package/dist/core/common/helpers/file.helper.js.map +1 -1
- package/dist/core/common/helpers/filter.helper.d.ts +3 -0
- package/dist/core/common/helpers/filter.helper.js +93 -81
- package/dist/core/common/helpers/filter.helper.js.map +1 -1
- package/dist/core/common/helpers/graphql.helper.d.ts +24 -1
- package/dist/core/common/helpers/graphql.helper.js +144 -96
- package/dist/core/common/helpers/graphql.helper.js.map +1 -1
- package/dist/core/common/helpers/input.helper.d.ts +29 -3
- package/dist/core/common/helpers/input.helper.js +222 -105
- package/dist/core/common/helpers/input.helper.js.map +1 -1
- package/dist/core/common/helpers/model.helper.d.ts +11 -0
- package/dist/core/common/helpers/model.helper.js +41 -29
- package/dist/core/common/helpers/model.helper.js.map +1 -1
- package/dist/core/common/helpers/service.helper.d.ts +21 -1
- package/dist/core/common/helpers/service.helper.js +80 -72
- package/dist/core/common/helpers/service.helper.js.map +1 -1
- package/dist/core/common/inputs/combined-filter.input.js +1 -1
- 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/interceptors/check-response.interceptor.js +1 -1
- package/dist/core/common/interceptors/check-response.interceptor.js.map +1 -1
- package/dist/core/common/interfaces/resolve-selector.interface.d.ts +5 -0
- package/dist/core/common/interfaces/resolve-selector.interface.js +3 -0
- package/dist/core/common/interfaces/resolve-selector.interface.js.map +1 -0
- package/dist/core/common/interfaces/service-options.interface.d.ts +30 -0
- package/dist/core/common/interfaces/service-options.interface.js +3 -0
- package/dist/core/common/interfaces/service-options.interface.js.map +1 -0
- package/dist/core/common/models/core-model.model.d.ts +4 -0
- package/dist/core/common/models/core-model.model.js +1 -1
- package/dist/core/common/models/core-model.model.js.map +1 -1
- package/dist/core/common/pipes/check-input.pipe.js +2 -2
- package/dist/core/common/pipes/check-input.pipe.js.map +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/services/crud.service.d.ts +13 -0
- package/dist/core/common/services/crud.service.js +59 -0
- package/dist/core/common/services/crud.service.js.map +1 -0
- package/dist/core/common/services/email.service.js +8 -8
- package/dist/core/common/services/email.service.js.map +1 -1
- package/dist/core/common/services/module.service.d.ts +27 -0
- package/dist/core/common/services/module.service.js +41 -0
- package/dist/core/common/services/module.service.js.map +1 -0
- package/dist/core/common/types/core-model-constructor.type.d.ts +21 -0
- package/dist/core/common/types/core-model-constructor.type.js +3 -0
- package/dist/core/common/types/core-model-constructor.type.js.map +1 -0
- package/dist/core/common/types/field-selection.type.d.ts +4 -0
- package/dist/core/common/types/field-selection.type.js +3 -0
- package/dist/core/common/types/field-selection.type.js.map +1 -0
- package/dist/core/common/types/string-or-object-id.type.d.ts +2 -0
- package/dist/core/common/types/string-or-object-id.type.js +3 -0
- package/dist/core/common/types/string-or-object-id.type.js.map +1 -0
- package/dist/core/modules/auth/core-auth.resolver.d.ts +2 -1
- package/dist/core/modules/auth/core-auth.resolver.js +4 -3
- package/dist/core/modules/auth/core-auth.resolver.js.map +1 -1
- package/dist/core/modules/auth/services/core-auth-user.service.d.ts +3 -1
- package/dist/core/modules/auth/services/core-auth-user.service.js.map +1 -1
- package/dist/core/modules/auth/services/core-auth.service.d.ts +2 -1
- package/dist/core/modules/auth/services/core-auth.service.js +6 -4
- package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
- package/dist/core/modules/user/core-user.model.js +1 -1
- package/dist/core/modules/user/core-user.model.js.map +1 -1
- package/dist/core/modules/user/core-user.service.d.ts +16 -25
- package/dist/core/modules/user/core-user.service.js +79 -98
- package/dist/core/modules/user/core-user.service.js.map +1 -1
- package/dist/core.module.js +1 -1
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/server/modules/auth/auth.resolver.d.ts +2 -1
- package/dist/server/modules/auth/auth.resolver.js +4 -3
- package/dist/server/modules/auth/auth.resolver.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/user/avatar.controller.js +1 -1
- package/dist/server/modules/user/avatar.controller.js.map +1 -1
- package/dist/server/modules/user/user.model.d.ts +1 -0
- package/dist/server/modules/user/user.module.js +7 -3
- package/dist/server/modules/user/user.module.js.map +1 -1
- package/dist/server/modules/user/user.resolver.d.ts +8 -7
- package/dist/server/modules/user/user.resolver.js +65 -45
- package/dist/server/modules/user/user.resolver.js.map +1 -1
- package/dist/server/modules/user/user.service.d.ts +9 -18
- package/dist/server/modules/user/user.service.js +19 -30
- package/dist/server/modules/user/user.service.js.map +1 -1
- package/dist/test/test.helper.d.ts +1 -2
- package/dist/test/test.helper.js +1 -16
- package/dist/test/test.helper.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +44 -45
- package/src/core/common/args/pagination.args.ts +2 -2
- package/src/core/common/helpers/config.helper.ts +26 -6
- package/src/core/common/helpers/context.helper.ts +42 -33
- package/src/core/common/helpers/db.helper.ts +580 -0
- package/src/core/common/helpers/file.helper.ts +76 -49
- package/src/core/common/helpers/filter.helper.ts +119 -96
- package/src/core/common/helpers/graphql.helper.ts +219 -117
- package/src/core/common/helpers/input.helper.ts +296 -106
- package/src/core/common/helpers/model.helper.ts +102 -57
- package/src/core/common/helpers/service.helper.ts +149 -117
- package/src/core/common/inputs/combined-filter.input.ts +2 -2
- package/src/core/common/inputs/core-input.input.ts +2 -2
- package/src/core/common/interceptors/check-response.interceptor.ts +2 -2
- package/src/core/common/interfaces/resolve-selector.interface.ts +9 -0
- package/src/core/common/interfaces/service-options.interface.ts +53 -0
- package/src/core/common/models/core-model.model.ts +6 -2
- package/src/core/common/pipes/check-input.pipe.ts +4 -4
- package/src/core/common/pipes/map-and-validate.pipe.ts +2 -2
- package/src/core/common/services/crud.service.ts +105 -0
- package/src/core/common/services/email.service.ts +9 -9
- package/src/core/common/services/module.service.ts +114 -0
- package/src/core/common/types/core-model-constructor.type.ts +30 -0
- package/src/core/common/types/field-selection.type.ts +8 -0
- package/src/core/common/types/string-or-object-id.type.ts +3 -0
- package/src/core/modules/auth/core-auth.module.ts +1 -1
- package/src/core/modules/auth/core-auth.resolver.ts +8 -3
- package/src/core/modules/auth/services/core-auth-user.service.ts +7 -1
- package/src/core/modules/auth/services/core-auth.service.ts +14 -4
- package/src/core/modules/user/core-user.model.ts +2 -1
- package/src/core/modules/user/core-user.service.ts +131 -194
- package/src/core.module.ts +2 -2
- package/src/index.ts +8 -1
- package/src/main.ts +1 -1
- package/src/server/modules/auth/auth.resolver.ts +8 -3
- package/src/server/modules/file/file.controller.ts +2 -2
- package/src/server/modules/user/avatar.controller.ts +2 -2
- package/src/server/modules/user/user.module.ts +7 -3
- package/src/server/modules/user/user.resolver.ts +62 -37
- package/src/server/modules/user/user.service.ts +23 -53
- package/src/test/test.helper.ts +31 -30
- package/dist/core/modules/user/core-basic-user.service.d.ts +0 -17
- package/dist/core/modules/user/core-basic-user.service.js +0 -73
- package/dist/core/modules/user/core-basic-user.service.js.map +0 -1
- package/src/core/modules/user/core-basic-user.service.ts +0 -138
|
@@ -0,0 +1,105 @@
|
|
|
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
|
+
return this.process(
|
|
28
|
+
async (data) => {
|
|
29
|
+
const item = await this.mainDbModel.findById(data.input).exec();
|
|
30
|
+
if (!item) {
|
|
31
|
+
throw new NotFoundException(`No ${this.mainModelConstructor.name} found with ID: ${id}`);
|
|
32
|
+
}
|
|
33
|
+
return item;
|
|
34
|
+
},
|
|
35
|
+
{ input: id, serviceOptions }
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get items via filter
|
|
41
|
+
*/
|
|
42
|
+
async find(filterArgs?: FilterArgs, serviceOptions?: ServiceOptions): Promise<T[]> {
|
|
43
|
+
return this.process(
|
|
44
|
+
async (data) => {
|
|
45
|
+
const filterQuery = convertFilterArgsToQuery(data.input);
|
|
46
|
+
return this.mainDbModel.find(filterQuery[0], null, filterQuery[1]).exec();
|
|
47
|
+
},
|
|
48
|
+
{ input: filterArgs, serviceOptions }
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* CRUD alias for get
|
|
54
|
+
*/
|
|
55
|
+
async read(id: string, serviceOptions?: ServiceOptions): Promise<T>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* CRUD alias for find
|
|
59
|
+
*/
|
|
60
|
+
async read(filterArgs?: FilterArgs, serviceOptions?: ServiceOptions): Promise<T[]>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* CRUD alias for get or find
|
|
64
|
+
*/
|
|
65
|
+
async read(input: string | FilterArgs, serviceOptions?: ServiceOptions): Promise<T | T[]> {
|
|
66
|
+
if (typeof input === 'string') {
|
|
67
|
+
return this.get(input, serviceOptions);
|
|
68
|
+
} else {
|
|
69
|
+
return this.find(input, serviceOptions);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Update item via ID
|
|
75
|
+
*/
|
|
76
|
+
async update(id: string, input: any, serviceOptions?: ServiceOptions): Promise<T> {
|
|
77
|
+
return this.process(
|
|
78
|
+
async (data) => {
|
|
79
|
+
const item = await this.mainDbModel.findById(id).exec();
|
|
80
|
+
if (!item) {
|
|
81
|
+
throw new NotFoundException(`No ${this.mainModelConstructor.name} found with ID: ${id}`);
|
|
82
|
+
}
|
|
83
|
+
return await Object.assign(item, data.input).save();
|
|
84
|
+
},
|
|
85
|
+
{ input, serviceOptions }
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Delete item via ID
|
|
91
|
+
*/
|
|
92
|
+
async delete(id: string, serviceOptions?: ServiceOptions): Promise<T> {
|
|
93
|
+
return this.process(
|
|
94
|
+
async (data) => {
|
|
95
|
+
const item = await this.mainDbModel.findById(id).exec();
|
|
96
|
+
if (!item) {
|
|
97
|
+
throw new NotFoundException(`No ${this.mainModelConstructor.name} found with ID: ${id}`);
|
|
98
|
+
}
|
|
99
|
+
await this.mainDbModel.findByIdAndDelete(id).exec();
|
|
100
|
+
return item;
|
|
101
|
+
},
|
|
102
|
+
{ input: id, serviceOptions }
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -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 {
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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 (!
|
|
63
|
-
|
|
62
|
+
if (!isNonEmptyString(html, returnFalse)) {
|
|
63
|
+
isNonEmptyString(text);
|
|
64
64
|
}
|
|
65
|
-
if (!
|
|
66
|
-
|
|
65
|
+
if (!isNonEmptyString(text, returnFalse)) {
|
|
66
|
+
isNonEmptyString(html);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
// Init transporter
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Document, Model } from 'mongoose';
|
|
2
|
+
import { popAndMap } from '../helpers/db.helper';
|
|
3
|
+
import { prepareInput, prepareOutput } from '../helpers/service.helper';
|
|
4
|
+
import { ServiceOptions } from '../interfaces/service-options.interface';
|
|
5
|
+
import { CoreModel } from '../models/core-model.model';
|
|
6
|
+
import { FieldSelection } from '../types/field-selection.type';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Module service class to be extended by concrete module services
|
|
10
|
+
*/
|
|
11
|
+
export abstract class ModuleService<T extends CoreModel = any> {
|
|
12
|
+
/**
|
|
13
|
+
* Main model constructor of the service, will be used as default for populate and mapping
|
|
14
|
+
*/
|
|
15
|
+
protected mainModelConstructor: new (...args: any[]) => T;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Main DB model of the service, will be used as default for populate and mapping
|
|
19
|
+
*/
|
|
20
|
+
protected mainDbModel: Model<T & Document>;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Set main properties
|
|
24
|
+
*/
|
|
25
|
+
protected constructor(options?: {
|
|
26
|
+
mainDbModel: Model<T & Document>;
|
|
27
|
+
mainModelConstructor?: new (...args: any[]) => T;
|
|
28
|
+
}) {
|
|
29
|
+
this.mainDbModel = options?.mainDbModel;
|
|
30
|
+
this.mainModelConstructor = options?.mainModelConstructor;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Run service function with pre- and post-functions
|
|
35
|
+
*/
|
|
36
|
+
async process(
|
|
37
|
+
serviceFunc: (options?: { [key: string]: any; input?: any; serviceOptions?: ServiceOptions }) => any,
|
|
38
|
+
options?: { [key: string]: any; input?: any; serviceOptions?: ServiceOptions }
|
|
39
|
+
) {
|
|
40
|
+
// Configuration with default values
|
|
41
|
+
const config = {
|
|
42
|
+
currentUser: null,
|
|
43
|
+
fieldSelection: null,
|
|
44
|
+
processFieldSelection: {},
|
|
45
|
+
prepareInput: {},
|
|
46
|
+
prepareOutput: {},
|
|
47
|
+
pubSub: true,
|
|
48
|
+
...options?.serviceOptions,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Prepare input
|
|
52
|
+
if (config.prepareInput && this.prepareInput) {
|
|
53
|
+
await this.prepareInput(options?.input, config.prepareInput);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Run service function
|
|
57
|
+
const result = await serviceFunc(options);
|
|
58
|
+
|
|
59
|
+
// Pop and map main model
|
|
60
|
+
if (config.processFieldSelection && config.fieldSelection && this.processFieldSelection) {
|
|
61
|
+
await this.processFieldSelection(result, config.fieldSelection, config.processFieldSelection);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Prepare output
|
|
65
|
+
if (config.prepareOutput && this.prepareOutput) {
|
|
66
|
+
// Check if mapping is already done by processFieldSelection
|
|
67
|
+
if (config.processFieldSelection && config.fieldSelection && this.processFieldSelection) {
|
|
68
|
+
config.prepareOutput.targetModel = null;
|
|
69
|
+
}
|
|
70
|
+
return this.prepareOutput(result, config.prepareOutput);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Return result without output preparation
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Prepare input before save
|
|
79
|
+
*/
|
|
80
|
+
async prepareInput(input: Record<string, any>, options: ServiceOptions = {}) {
|
|
81
|
+
return prepareInput(input, options.currentUser, options.prepareInput);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Prepare output before return
|
|
86
|
+
*/
|
|
87
|
+
async prepareOutput(output: any, options: ServiceOptions = {}) {
|
|
88
|
+
const config = {
|
|
89
|
+
targetModel: this.mainModelConstructor,
|
|
90
|
+
...options?.prepareOutput,
|
|
91
|
+
};
|
|
92
|
+
return prepareOutput(output, config);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Process fieldSelection
|
|
97
|
+
* @protected
|
|
98
|
+
*/
|
|
99
|
+
async processFieldSelection(
|
|
100
|
+
data: any,
|
|
101
|
+
fieldsSelection: FieldSelection,
|
|
102
|
+
options: {
|
|
103
|
+
model?: new (...args: any[]) => T;
|
|
104
|
+
dbModel?: Model<T & Document>;
|
|
105
|
+
} = {}
|
|
106
|
+
) {
|
|
107
|
+
const config = {
|
|
108
|
+
model: this.mainModelConstructor,
|
|
109
|
+
dbModel: this.mainDbModel,
|
|
110
|
+
...options,
|
|
111
|
+
};
|
|
112
|
+
return popAndMap(data, fieldsSelection, config.model, config.dbModel);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -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;
|
|
@@ -25,7 +25,7 @@ export class CoreAuthModule {
|
|
|
25
25
|
providers?: Provider[];
|
|
26
26
|
}
|
|
27
27
|
): DynamicModule {
|
|
28
|
-
//
|
|
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(
|
|
24
|
-
|
|
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,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(
|
|
19
|
-
|
|
20
|
-
|
|
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
|
|