nodester 0.0.1
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/LICENSE +21 -0
- package/Readme.md +125 -0
- package/docs/App.md +13 -0
- package/docs/Queries.md +61 -0
- package/docs/Readme.md +2 -0
- package/docs/Routing.md +34 -0
- package/examples/goal/index.js +23 -0
- package/examples/rest/index.js +25 -0
- package/examples/rest/node_modules/.package-lock.json +40 -0
- package/examples/rest/package-lock.json +72 -0
- package/examples/rest/package.json +14 -0
- package/lib/application/MiddlewareStack.js +125 -0
- package/lib/application/http/request.js +462 -0
- package/lib/application/http/response.js +1107 -0
- package/lib/application/http/utils.js +254 -0
- package/lib/application/index.js +292 -0
- package/lib/constants/ConstantsEnum.js +13 -0
- package/lib/constants/ResponseFormats.js +7 -0
- package/lib/controllers/Controller.js +474 -0
- package/lib/controllers/JWTController.js +240 -0
- package/lib/controllers/ServiceController.js +109 -0
- package/lib/controllers/WebController.js +75 -0
- package/lib/facades/Facade.js +388 -0
- package/lib/facades/FacadeParams.js +11 -0
- package/lib/facades/ServiceFacade.js +17 -0
- package/lib/facades/jwt.facade.js +273 -0
- package/lib/factories/errors/CustomError.js +22 -0
- package/lib/factories/errors/index.js +9 -0
- package/lib/factories/responses/api.js +90 -0
- package/lib/factories/responses/html.js +55 -0
- package/lib/logger/console.js +24 -0
- package/lib/models/DisabledRefreshToken.js +68 -0
- package/lib/models/Extractor.js +320 -0
- package/lib/models/define.js +62 -0
- package/lib/models/mixins.js +369 -0
- package/lib/policies/Role.js +77 -0
- package/lib/policies/RoleExtracting.js +97 -0
- package/lib/preprocessors/BodyPreprocessor.js +61 -0
- package/lib/preprocessors/IncludesPreprocessor.js +55 -0
- package/lib/preprocessors/QueryPreprocessor.js +64 -0
- package/lib/routers/Default/index.js +143 -0
- package/lib/routers/Default/layer.js +50 -0
- package/lib/routers/Main/index.js +10 -0
- package/lib/routers/Roles/index.js +81 -0
- package/lib/services/includes.service.js +79 -0
- package/lib/services/jwt.service.js +147 -0
- package/lib/tools/sql.tool.js +82 -0
- package/lib/utils/dates.util.js +23 -0
- package/lib/utils/forms.util.js +22 -0
- package/lib/utils/json.util.js +49 -0
- package/lib/utils/mappers/Routes/index.js +100 -0
- package/lib/utils/mappers/Routes/utils.js +20 -0
- package/lib/utils/modelAssociations.util.js +44 -0
- package/lib/utils/objects.util.js +69 -0
- package/lib/utils/params.util.js +19 -0
- package/lib/utils/path.util.js +26 -0
- package/lib/utils/queries.util.js +240 -0
- package/lib/utils/sanitizations.util.js +111 -0
- package/lib/utils/sql.util.js +78 -0
- package/lib/utils/strings.util.js +43 -0
- package/lib/utils/types.util.js +26 -0
- package/package.json +63 -0
- package/tests/index.test.js +35 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
// Access to database.
|
|
2
|
+
const Sequelize = require('sequelize');
|
|
3
|
+
// JWT service.
|
|
4
|
+
const JWT = require('nodester/services/jwt.service');
|
|
5
|
+
// Utils:
|
|
6
|
+
const { lowerCaseFirstLetter } = require('nodester/utils/strings.util');
|
|
7
|
+
const { addSeconds } = require('nodester/utils/dates.util');
|
|
8
|
+
const Params = require('nodester/facades/FacadeParams');
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
module.exports = class JWTFacade {
|
|
12
|
+
constructor(
|
|
13
|
+
disabledRefreshToken,
|
|
14
|
+
roleModels=[],
|
|
15
|
+
accessTokenConfigs=null,
|
|
16
|
+
refreshTokenConfigs=null
|
|
17
|
+
) {
|
|
18
|
+
if (!disabledRefreshToken)
|
|
19
|
+
throw new Erroror('"disabledRefreshToken" argument is invalid.');
|
|
20
|
+
|
|
21
|
+
this.disabledRefreshToken = disabledRefreshToken;
|
|
22
|
+
|
|
23
|
+
this.roleModels = {};
|
|
24
|
+
roleModels.forEach(model => {
|
|
25
|
+
const name = lowerCaseFirstLetter(model?.options?.name?.singular);
|
|
26
|
+
this.roleModels[name] = model;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
this.service = new JWT(accessTokenConfigs, refreshTokenConfigs);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async login(params) {
|
|
33
|
+
try {
|
|
34
|
+
const {
|
|
35
|
+
email,
|
|
36
|
+
password,
|
|
37
|
+
role
|
|
38
|
+
} = Params(params, {
|
|
39
|
+
email: null,
|
|
40
|
+
password: null,
|
|
41
|
+
role: null
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (Object.keys(this.roleModels).indexOf(role) === -1)
|
|
45
|
+
throw new Error();
|
|
46
|
+
|
|
47
|
+
// Extract model difinition of this type.
|
|
48
|
+
const modelDefinition = this.roleModels[role];
|
|
49
|
+
const instance = await modelDefinition?.findOneByEmail(email);
|
|
50
|
+
|
|
51
|
+
if (!instance)
|
|
52
|
+
throw new Error();
|
|
53
|
+
|
|
54
|
+
const compareResult = await instance?.comparePasswords(password);
|
|
55
|
+
|
|
56
|
+
if (compareResult === false)
|
|
57
|
+
throw new Error();
|
|
58
|
+
|
|
59
|
+
const result = {
|
|
60
|
+
role: role,
|
|
61
|
+
[role]: instance.toJSON(),
|
|
62
|
+
tokens: await this.issueTokens({ modelInstance: instance, modelName: role })
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Send output.
|
|
66
|
+
return Promise.resolve(result);
|
|
67
|
+
}
|
|
68
|
+
catch(error) {
|
|
69
|
+
console.error(error);
|
|
70
|
+
|
|
71
|
+
// Unauthorized on any error:
|
|
72
|
+
const err = new Error();
|
|
73
|
+
err.name = 'Unauthorized';
|
|
74
|
+
return Promise.reject(err);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async issueAccessToken(params) {
|
|
79
|
+
try {
|
|
80
|
+
const {
|
|
81
|
+
parsedRefreshToken,
|
|
82
|
+
modelInstance,
|
|
83
|
+
modelName
|
|
84
|
+
} = Params(params, {
|
|
85
|
+
parsedRefreshToken: null,
|
|
86
|
+
modelInstance: null,
|
|
87
|
+
modelName: null,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
let newAccessToken = null;
|
|
91
|
+
|
|
92
|
+
if (!modelName && !parsedRefreshToken.role) {
|
|
93
|
+
const err = new Error('No "modelName" provided for JWT issue.');
|
|
94
|
+
err.name = "ValidationError";
|
|
95
|
+
err.status = 403;
|
|
96
|
+
throw err;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// If parsed refresh token was provided:
|
|
100
|
+
if (!!parsedRefreshToken) {
|
|
101
|
+
const payload = {
|
|
102
|
+
id: parsedRefreshToken?.id,
|
|
103
|
+
role: parsedRefreshToken.role,
|
|
104
|
+
};
|
|
105
|
+
newAccessToken = await this.service.issueAccessToken(payload);
|
|
106
|
+
}
|
|
107
|
+
// If modelInstance was provided:
|
|
108
|
+
else if (!!modelInstance) {
|
|
109
|
+
const payload = {
|
|
110
|
+
id: modelInstance?.id,
|
|
111
|
+
role: modelName
|
|
112
|
+
};
|
|
113
|
+
newAccessToken = await this.service.issueAccessToken(payload);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
const err = new Error('No "modelInstance" or "parsedRefreshToken" provided for JWT issue.');
|
|
117
|
+
err.name = "ValidationError";
|
|
118
|
+
err.status = 403;
|
|
119
|
+
throw err;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Check if issue was successful.
|
|
123
|
+
if (!newAccessToken) {
|
|
124
|
+
const err = new Error("Could not issue new access token.");
|
|
125
|
+
err.status = 401;
|
|
126
|
+
throw err;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Send output.
|
|
130
|
+
return Promise.resolve(newAccessToken);
|
|
131
|
+
}
|
|
132
|
+
catch(error) {
|
|
133
|
+
return Promise.reject(error);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async issueTokens(params) {
|
|
138
|
+
try {
|
|
139
|
+
const {
|
|
140
|
+
modelInstance,
|
|
141
|
+
modelName,
|
|
142
|
+
noAccessToken,
|
|
143
|
+
noRefreshToken
|
|
144
|
+
} = Params(params, {
|
|
145
|
+
modelInstance: null,
|
|
146
|
+
modelName: null,
|
|
147
|
+
noAccessToken: false,
|
|
148
|
+
noRefreshToken: false
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Prepare payload container.
|
|
152
|
+
let payload = {};
|
|
153
|
+
|
|
154
|
+
if (!!modelInstance && !!modelName) {
|
|
155
|
+
payload = {
|
|
156
|
+
id: modelInstance?.id,
|
|
157
|
+
role: modelName
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
const err = new Error('No "modelInstance" and "modelName" provided for JWT issue.');
|
|
162
|
+
err.name = "ValidationError";
|
|
163
|
+
err.status = 403;
|
|
164
|
+
throw err;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const accessToken = await this.service.issueAccessToken(payload);
|
|
168
|
+
const refreshToken = await this.service.issueRefreshToken(payload);
|
|
169
|
+
|
|
170
|
+
// Prepare output,
|
|
171
|
+
const tokens = {
|
|
172
|
+
accessToken,
|
|
173
|
+
refreshToken
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
if (noAccessToken)
|
|
177
|
+
delete tokens.accessToken;
|
|
178
|
+
|
|
179
|
+
if (noRefreshToken)
|
|
180
|
+
delete tokens.refreshToken;
|
|
181
|
+
|
|
182
|
+
// Send output.
|
|
183
|
+
return Promise.resolve(tokens);
|
|
184
|
+
}
|
|
185
|
+
catch(error) {
|
|
186
|
+
return Promise.reject(error);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async refreshAccessToken(params) {
|
|
191
|
+
try {
|
|
192
|
+
const {
|
|
193
|
+
refreshToken,
|
|
194
|
+
parsedRefreshToken
|
|
195
|
+
} = Params(params, {
|
|
196
|
+
refreshToken: null,
|
|
197
|
+
parsedRefreshToken: null
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// Check if token is not blocked:
|
|
201
|
+
const isActive = await this.isRefreshTokenActive({ refreshToken });
|
|
202
|
+
if (!isActive) {
|
|
203
|
+
const err = new Error('Invalid Token!');
|
|
204
|
+
err.name = 'InvalidToken';
|
|
205
|
+
throw err;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Issue new access token, based on refresh token:
|
|
209
|
+
const accessToken = await this.issueAccessToken({ parsedRefreshToken });
|
|
210
|
+
|
|
211
|
+
// Send output.
|
|
212
|
+
return Promise.resolve(accessToken);
|
|
213
|
+
}
|
|
214
|
+
catch(error) {
|
|
215
|
+
return Promise.reject(error);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async isRefreshTokenActive(params) {
|
|
220
|
+
try {
|
|
221
|
+
const {
|
|
222
|
+
refreshToken
|
|
223
|
+
} = Params(params, {
|
|
224
|
+
refreshToken: null
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const foundTokens = await this.disabledRefreshToken.selectAll({ token: refreshToken });
|
|
228
|
+
|
|
229
|
+
// Prepare output. Check if provided token was not disabled.
|
|
230
|
+
const isActive = foundTokens.length === 0;
|
|
231
|
+
|
|
232
|
+
// Send output.
|
|
233
|
+
return Promise.resolve(isActive);
|
|
234
|
+
}
|
|
235
|
+
catch(error) {
|
|
236
|
+
return Promise.reject(error);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async disableRefreshToken(params) {
|
|
241
|
+
try {
|
|
242
|
+
const {
|
|
243
|
+
refreshToken,
|
|
244
|
+
parsedToken
|
|
245
|
+
} = Params(params, {
|
|
246
|
+
refreshToken: null,
|
|
247
|
+
parsedToken: null
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Unwrap nessessary data.
|
|
251
|
+
const { id, role } = parsedToken;
|
|
252
|
+
|
|
253
|
+
// Find or create:
|
|
254
|
+
const cofParams = {
|
|
255
|
+
[`${ role }_id`]: id,
|
|
256
|
+
token: refreshToken
|
|
257
|
+
};
|
|
258
|
+
const [ disabledRefreshToken, created ] = await this.disabledRefreshToken.createOrFind(cofParams);
|
|
259
|
+
|
|
260
|
+
// Check result,
|
|
261
|
+
const createdStatus = created === true || !!disabledRefreshToken;
|
|
262
|
+
|
|
263
|
+
// Send output.
|
|
264
|
+
const result = {
|
|
265
|
+
status: createdStatus
|
|
266
|
+
}
|
|
267
|
+
return Promise.resolve(result);
|
|
268
|
+
}
|
|
269
|
+
catch(error) {
|
|
270
|
+
return Promise.reject(error);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class CustomError extends Error {
|
|
2
|
+
constructor(message) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = this.constructor.name;
|
|
5
|
+
this.status = 500;
|
|
6
|
+
|
|
7
|
+
// Remove constructor info from stack.
|
|
8
|
+
Error.captureStackTrace(this, this.constructor);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
replicate(originalError) {
|
|
12
|
+
this.name = originalError?.name ?? this.name;
|
|
13
|
+
this.code = originalError?.code ?? this.code;
|
|
14
|
+
this.status = originalError?.status ?? this.status;
|
|
15
|
+
|
|
16
|
+
// Append stack from original error.
|
|
17
|
+
const messageLines = (this.message.match(/\n/g)||[]).length + 1
|
|
18
|
+
this.stack = this.stack.split('\n').slice(0, messageLines+1).join('\n') + '\n' + originalError.stack;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = CustomError;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const ResponseFormats = require('nodester/constants/ResponseFormats');
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module.exports = class APIResponseFactory {
|
|
5
|
+
constructor() {}
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
Format for all API responses will be JSON
|
|
9
|
+
{
|
|
10
|
+
content: {...}
|
|
11
|
+
error: {...}
|
|
12
|
+
}
|
|
13
|
+
Status code is sent in header.
|
|
14
|
+
|
|
15
|
+
If error is not present, error should be null.
|
|
16
|
+
If error is present, content can be null (But it's not required).
|
|
17
|
+
*/
|
|
18
|
+
createGenericResponse(
|
|
19
|
+
options = {
|
|
20
|
+
res: null,
|
|
21
|
+
status: 200,
|
|
22
|
+
content: {},
|
|
23
|
+
error: null,
|
|
24
|
+
format: ResponseFormats.JSON
|
|
25
|
+
}
|
|
26
|
+
) {
|
|
27
|
+
try {
|
|
28
|
+
const data = {
|
|
29
|
+
content: options?.content ?? null,
|
|
30
|
+
error: options?.error ?? null
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
switch(options?.format) {
|
|
34
|
+
case ResponseFormats.JSON:
|
|
35
|
+
return options?.res.status(options?.status).json(data);
|
|
36
|
+
case ResponseFormats.XML:
|
|
37
|
+
break;
|
|
38
|
+
default: {
|
|
39
|
+
const err = new Error("No response format specified.");
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch(error) {
|
|
45
|
+
const err = new Error(`Could not create generic response: ${error.message}`);
|
|
46
|
+
err.name = error?.name;
|
|
47
|
+
err.code = error?.code;
|
|
48
|
+
|
|
49
|
+
console.error(err);
|
|
50
|
+
|
|
51
|
+
throw err;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Sends response with status code 200.
|
|
57
|
+
* Should be called on all successful respones.
|
|
58
|
+
*
|
|
59
|
+
* @param <Object> res
|
|
60
|
+
* @param <Object> content
|
|
61
|
+
* @param <String> format
|
|
62
|
+
*/
|
|
63
|
+
createOKResponse(options) {
|
|
64
|
+
|
|
65
|
+
return this.createGenericResponse({
|
|
66
|
+
...options,
|
|
67
|
+
status: 200,
|
|
68
|
+
format: options?.format ?? ResponseFormats.JSON
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Sends response with provided error code.
|
|
74
|
+
* Should be called on all failed respones.
|
|
75
|
+
*
|
|
76
|
+
* @param <Object> res
|
|
77
|
+
* @param <Object> error
|
|
78
|
+
* @param <Object> content (optional)
|
|
79
|
+
* @param <Int> status
|
|
80
|
+
* @param <String> format
|
|
81
|
+
*/
|
|
82
|
+
createErrorResponse(options) {
|
|
83
|
+
|
|
84
|
+
return this.createGenericResponse({
|
|
85
|
+
...options,
|
|
86
|
+
status: options?.status ?? 500,
|
|
87
|
+
format: options?.format ?? ResponseFormats.JSON
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const Params = require('nodester/facades/FacadeParams');
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module.exports = class WebResponseFactory {
|
|
5
|
+
constructor() {}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Sends rendererd HTML view with status code 200.
|
|
9
|
+
* Should be called on all successful respones.
|
|
10
|
+
*
|
|
11
|
+
* @param <Object> res
|
|
12
|
+
* @param <String> viewName
|
|
13
|
+
* @param <Object> params
|
|
14
|
+
*/
|
|
15
|
+
createOKResponse(params) {
|
|
16
|
+
const {
|
|
17
|
+
res,
|
|
18
|
+
viewName,
|
|
19
|
+
viewParams,
|
|
20
|
+
} = Params(params, {
|
|
21
|
+
res: null,
|
|
22
|
+
viewName: null,
|
|
23
|
+
viewParams: {},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return res.render(viewName, viewParams);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Sends response with provided error code.
|
|
31
|
+
* Should be called on all failed respones.
|
|
32
|
+
*
|
|
33
|
+
* @param <Object> res
|
|
34
|
+
* @param <Object> error
|
|
35
|
+
* @param <Int> code
|
|
36
|
+
*/
|
|
37
|
+
createErrorResponse(params) {
|
|
38
|
+
const {
|
|
39
|
+
res,
|
|
40
|
+
error,
|
|
41
|
+
code,
|
|
42
|
+
} = Params(params, {
|
|
43
|
+
res: null,
|
|
44
|
+
error: {},
|
|
45
|
+
code: 500,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const statusCode = error?.status ?? code;
|
|
49
|
+
const viewParams = {
|
|
50
|
+
title: `${statusCode} error`,
|
|
51
|
+
heading: `${statusCode} | ${error.message}.`
|
|
52
|
+
};
|
|
53
|
+
return res.render('error', viewParams);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* /nodester
|
|
3
|
+
* MIT Licensed
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
exports = module.exports = {
|
|
10
|
+
error: _error
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Log error using console.error.
|
|
15
|
+
*
|
|
16
|
+
* @param {Error} err
|
|
17
|
+
*
|
|
18
|
+
* @alias error
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
function _error(err) {
|
|
23
|
+
console.error(err.stack || err.toString());
|
|
24
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const defineModel = require('./define');
|
|
2
|
+
// ORM.
|
|
3
|
+
const { DataTypes } = require('sequelize');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
module.exports = _defineDisabledRefreshToken;
|
|
7
|
+
|
|
8
|
+
function _defineDisabledRefreshToken(
|
|
9
|
+
database,
|
|
10
|
+
roleIds=[],
|
|
11
|
+
options={}
|
|
12
|
+
) {
|
|
13
|
+
|
|
14
|
+
const fields = {
|
|
15
|
+
id: {
|
|
16
|
+
type: DataTypes.INTEGER.UNSIGNED,
|
|
17
|
+
allowNull: false,
|
|
18
|
+
primaryKey: true,
|
|
19
|
+
autoIncrement: true,
|
|
20
|
+
_autoGenerated: true
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
token: {
|
|
24
|
+
type: DataTypes.STRING,
|
|
25
|
+
required: true,
|
|
26
|
+
allowNull: false,
|
|
27
|
+
unique: true
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
roleIds.forEach(roleId => fields[roleId] = {
|
|
32
|
+
type: DataTypes.INTEGER.UNSIGNED,
|
|
33
|
+
allowNull: true
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const disabledRefreshToken = defineModel(database, 'DisabledRefreshToken',
|
|
37
|
+
(DataTypes) => ( fields ),
|
|
38
|
+
{ ...options }
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
disabledRefreshToken.createOrFind = function({
|
|
42
|
+
token,
|
|
43
|
+
...roleInfo
|
|
44
|
+
}) {
|
|
45
|
+
const where = {
|
|
46
|
+
token
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const defaults = {
|
|
50
|
+
token: token,
|
|
51
|
+
...roleInfo
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const query = {
|
|
55
|
+
where,
|
|
56
|
+
defaults
|
|
57
|
+
};
|
|
58
|
+
return this.findOrCreate(query);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
disabledRefreshToken.selectAll = function({ token }) {
|
|
62
|
+
const where = { token };
|
|
63
|
+
const query = { where };
|
|
64
|
+
return this.findAll(query);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return disabledRefreshToken;
|
|
68
|
+
}
|