nodester 0.0.8 → 0.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/Readme.md +18 -59
- package/lib/application/index.js +28 -7
- package/lib/controllers/methods/index.js +34 -10
- package/lib/controllers/mixins/index.js +14 -5
- package/lib/database/connection.js +34 -0
- package/lib/database/migration.js +42 -0
- package/lib/database/utils.js +19 -0
- package/lib/facades/methods/index.js +173 -0
- package/lib/facades/mixins/index.js +111 -0
- package/lib/middlewares/formidable/index.js +37 -0
- package/lib/middlewares/ql/sequelize/interpreter/ModelsTree.js +2 -2
- package/lib/middlewares/ql/sequelize/interpreter/QueryLexer.js +3 -3
- package/lib/models/associate.js +17 -0
- package/lib/models/define.js +50 -1
- package/lib/models/mixins.js +81 -72
- package/lib/params/Params.js +10 -7
- package/lib/queries/Colander.js +84 -0
- package/lib/queries/traverse.js +311 -0
- package/lib/router/handlers.util.js +22 -2
- package/lib/router/index.js +96 -75
- package/lib/router/markers.js +78 -0
- package/lib/router/route.js +4 -4
- package/lib/router/routes.util.js +35 -5
- package/lib/router/utils.js +30 -0
- package/package.json +20 -7
- package/tests/nql.test.js +3 -3
- package/lib/_/n_controllers/Controller.js +0 -474
- package/lib/_/n_controllers/JWTController.js +0 -240
- package/lib/_/n_controllers/ServiceController.js +0 -109
- package/lib/_/n_controllers/WebController.js +0 -75
- package/lib/_facades/Facade.js +0 -388
- package/lib/_facades/FacadeParams.js +0 -11
- package/lib/_facades/ServiceFacade.js +0 -17
- package/lib/_facades/jwt.facade.js +0 -273
- package/lib/models/DisabledRefreshToken.js +0 -68
- package/lib/models/Extractor.js +0 -320
- package/lib/utils/forms.util.js +0 -22
package/lib/_facades/Facade.js
DELETED
|
@@ -1,388 +0,0 @@
|
|
|
1
|
-
const Params = require('nodester/facades/FacadeParams');
|
|
2
|
-
// Utils:
|
|
3
|
-
const { lowerCaseFirstLetter } = require('nodester/utils/strings.util');
|
|
4
|
-
const { parseIncludesQuery } = require('nodester/services/includes.service');
|
|
5
|
-
const { parseQueryParams } = require('nodester/utils/queries.util');
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
module.exports = class Facade {
|
|
9
|
-
constructor(modelDefinition) {
|
|
10
|
-
if (!modelDefinition)
|
|
11
|
-
throw new Error('"modelDefinition" argument is invalid.');
|
|
12
|
-
|
|
13
|
-
this.model = modelDefinition;
|
|
14
|
-
this.nameSingular = lowerCaseFirstLetter(modelDefinition?.options?.name?.singular);
|
|
15
|
-
this.namePlural = lowerCaseFirstLetter(modelDefinition?.options?.name?.plural);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/*
|
|
19
|
-
* @param <Object> data
|
|
20
|
-
*/
|
|
21
|
-
async createOne(params) {
|
|
22
|
-
try {
|
|
23
|
-
const {
|
|
24
|
-
data,
|
|
25
|
-
includes,
|
|
26
|
-
} = Params(params, {
|
|
27
|
-
data: null,
|
|
28
|
-
includes: null,
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
// Parse includes string to array.
|
|
32
|
-
const _includes = typeof includes === 'string' ? parseIncludesQuery(this.model, includes) : null;
|
|
33
|
-
|
|
34
|
-
const instance = await this.model.create({ ...data }, {
|
|
35
|
-
include: this.model.getIncludesList(data)
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
// If includes are set, "find" this record with includes:
|
|
39
|
-
if (!!_includes && _includes?.length > 0) {
|
|
40
|
-
await instance.reload({ include: _includes });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const result = {
|
|
44
|
-
[this.nameSingular]: instance,
|
|
45
|
-
count: 1
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
// Call after create.
|
|
49
|
-
await this.afterCreate(instance, params, result);
|
|
50
|
-
|
|
51
|
-
// Send output.
|
|
52
|
-
return Promise.resolve(result);
|
|
53
|
-
}
|
|
54
|
-
catch(error) {
|
|
55
|
-
return Promise.reject(error);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/*
|
|
60
|
-
* @param <Object> data
|
|
61
|
-
*/
|
|
62
|
-
async getOrCreateOne(params) {
|
|
63
|
-
try {
|
|
64
|
-
const {
|
|
65
|
-
id,
|
|
66
|
-
query,
|
|
67
|
-
data,
|
|
68
|
-
includes,
|
|
69
|
-
} = Params(params, {
|
|
70
|
-
id: null,
|
|
71
|
-
query: null,
|
|
72
|
-
data: null,
|
|
73
|
-
includes: null,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// Parse includes string to array.
|
|
77
|
-
const _includes = typeof includes === 'string' ? parseIncludesQuery(this.model, includes) : null;
|
|
78
|
-
|
|
79
|
-
let instance, isNewRecord;
|
|
80
|
-
|
|
81
|
-
if (!!id) {
|
|
82
|
-
const [ _instance, _isNewRecord ] = await this.model.findOrCreate({
|
|
83
|
-
where: {
|
|
84
|
-
id: parseInt(id)
|
|
85
|
-
},
|
|
86
|
-
defaults: data
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// Find this model again with passed includes.
|
|
90
|
-
instance = await this.model.findById(id, _includes);
|
|
91
|
-
|
|
92
|
-
isNewRecord = _isNewRecord;
|
|
93
|
-
}
|
|
94
|
-
else if (!!query) {
|
|
95
|
-
// New sequilize query.
|
|
96
|
-
const modelQuery = {};
|
|
97
|
-
|
|
98
|
-
// If includes are set:
|
|
99
|
-
if (!!_includes) {
|
|
100
|
-
modelQuery.include = [ ..._includes ];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
parseQueryParams(query, modelQuery);
|
|
104
|
-
|
|
105
|
-
let _instance = await this.model.findOne(modelQuery);
|
|
106
|
-
|
|
107
|
-
// Define "isNewRecord".
|
|
108
|
-
isNewRecord = !instance;
|
|
109
|
-
|
|
110
|
-
// If no record in DB, create new one:
|
|
111
|
-
if (!_instance) {
|
|
112
|
-
_instance = await this.model.create({ ...data }, {
|
|
113
|
-
include: this.model.getIncludesList(data)
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
instance = _instance;
|
|
117
|
-
|
|
118
|
-
// If includes are set, "find" this record with includes:
|
|
119
|
-
if (!!_includes && _includes?.length > 0) {
|
|
120
|
-
await instance.reload({ include: _includes });
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
instance = _instance;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const result = {
|
|
129
|
-
[this.nameSingular]: instance,
|
|
130
|
-
count: 1,
|
|
131
|
-
isNewRecord: isNewRecord
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
// If new record, call "after create":
|
|
135
|
-
if (!!isNewRecord) {
|
|
136
|
-
await this.afterCreate(instance, params, result);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Send output.
|
|
140
|
-
return Promise.resolve(result);
|
|
141
|
-
}
|
|
142
|
-
catch(error) {
|
|
143
|
-
return Promise.reject(error);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/*
|
|
148
|
-
* @param <ModelInstance> instance
|
|
149
|
-
* @param <Array> params
|
|
150
|
-
*/
|
|
151
|
-
async afterCreate(
|
|
152
|
-
instance,
|
|
153
|
-
params,
|
|
154
|
-
result
|
|
155
|
-
) {
|
|
156
|
-
// This method is empty, as it should be overwritten.
|
|
157
|
-
return Promise.resolve();
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/*
|
|
161
|
-
* @param <UInt> id
|
|
162
|
-
* @param <Object> query
|
|
163
|
-
* @param <Array> includes
|
|
164
|
-
*/
|
|
165
|
-
async getOne(params) {
|
|
166
|
-
try {
|
|
167
|
-
const {
|
|
168
|
-
id,
|
|
169
|
-
query,
|
|
170
|
-
includes,
|
|
171
|
-
} = Params(params, {
|
|
172
|
-
id: null,
|
|
173
|
-
query: null,
|
|
174
|
-
includes: null,
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
// Parse includes string to array.
|
|
178
|
-
const _includes = typeof includes === 'string' ? parseIncludesQuery(this.model, includes) : null;
|
|
179
|
-
|
|
180
|
-
let instance = null;
|
|
181
|
-
|
|
182
|
-
if (!!id || !!query?.id) {
|
|
183
|
-
instance = await this.model.findById(( id ?? query.id ), _includes);
|
|
184
|
-
}
|
|
185
|
-
else if (!!query) {
|
|
186
|
-
// New sequilize query.
|
|
187
|
-
const modelQuery = {};
|
|
188
|
-
|
|
189
|
-
// If includes are set:
|
|
190
|
-
if (!!_includes) {
|
|
191
|
-
modelQuery.include = [ ..._includes ];
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
parseQueryParams(query, modelQuery);
|
|
195
|
-
|
|
196
|
-
instance = await this.model.findOne(modelQuery);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const result = {
|
|
200
|
-
[this.nameSingular]: instance,
|
|
201
|
-
count: !!instance ? 1 : 0
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
// Send output.
|
|
205
|
-
return Promise.resolve(result);
|
|
206
|
-
}
|
|
207
|
-
catch(error) {
|
|
208
|
-
return Promise.reject(error);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/*
|
|
213
|
-
* @param <Object> query
|
|
214
|
-
* @param <Array> includes
|
|
215
|
-
*/
|
|
216
|
-
async getMany(params) {
|
|
217
|
-
try {
|
|
218
|
-
const {
|
|
219
|
-
query,
|
|
220
|
-
includes,
|
|
221
|
-
} = Params(params, {
|
|
222
|
-
query: {},
|
|
223
|
-
includes: null
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
// Parse includes string to array.
|
|
227
|
-
const _includes = typeof includes === 'string' ? parseIncludesQuery(this.model, includes) : null;
|
|
228
|
-
|
|
229
|
-
// New sequilize query.
|
|
230
|
-
const modelQuery = {};
|
|
231
|
-
|
|
232
|
-
// If includes are set:
|
|
233
|
-
if (!!_includes) {
|
|
234
|
-
modelQuery.include = [ ..._includes ];
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
parseQueryParams(query, modelQuery);
|
|
238
|
-
|
|
239
|
-
// Get instances for current limits
|
|
240
|
-
// and total number (Int) of such instances.
|
|
241
|
-
const [
|
|
242
|
-
instances,
|
|
243
|
-
totalCount
|
|
244
|
-
] = await Promise.all([
|
|
245
|
-
this.model.findAll(modelQuery),
|
|
246
|
-
this.model.count(modelQuery)
|
|
247
|
-
]);
|
|
248
|
-
|
|
249
|
-
const result = {
|
|
250
|
-
[this.namePlural]: instances,
|
|
251
|
-
|
|
252
|
-
count: instances.length,
|
|
253
|
-
total_count: totalCount,
|
|
254
|
-
|
|
255
|
-
limit: modelQuery.limit,
|
|
256
|
-
skip: modelQuery.offset
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
// Send output.
|
|
260
|
-
return Promise.resolve(result);
|
|
261
|
-
}
|
|
262
|
-
catch(error) {
|
|
263
|
-
return Promise.reject(error);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/*
|
|
268
|
-
* @param <UInt> id
|
|
269
|
-
* @param <Object> data
|
|
270
|
-
* @param <Array> includes
|
|
271
|
-
*/
|
|
272
|
-
async updateOne(params) {
|
|
273
|
-
try {
|
|
274
|
-
const {
|
|
275
|
-
id,
|
|
276
|
-
query,
|
|
277
|
-
data,
|
|
278
|
-
includes,
|
|
279
|
-
} = Params(params, {
|
|
280
|
-
id: null,
|
|
281
|
-
query: {},
|
|
282
|
-
data: null,
|
|
283
|
-
includes: null,
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
// Parse includes string to array.
|
|
287
|
-
const _includes = typeof includes === 'string' ? parseIncludesQuery(this.model, includes) : null;
|
|
288
|
-
|
|
289
|
-
let updateResult = null;
|
|
290
|
-
|
|
291
|
-
if (!!id || !!query.id) {
|
|
292
|
-
updateResult = await this.model.updateById(( id ?? query.id ), data, _includes);
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
// New sequilize query.
|
|
296
|
-
const modelQuery = {};
|
|
297
|
-
parseQueryParams(query, modelQuery);
|
|
298
|
-
|
|
299
|
-
updateResult = await this.model.updateOne(modelQuery.where, data, _includes);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
const [ isNewRecord, instance ] = updateResult;
|
|
303
|
-
|
|
304
|
-
const result = {
|
|
305
|
-
success: isNewRecord === false,
|
|
306
|
-
[this.nameSingular]: instance
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
// Send output.
|
|
310
|
-
return Promise.resolve(result);
|
|
311
|
-
}
|
|
312
|
-
catch(error) {
|
|
313
|
-
return Promise.reject(error);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// TODO: finish updateMany:
|
|
318
|
-
/*
|
|
319
|
-
* @param <UInt> id
|
|
320
|
-
* @param <Object> data
|
|
321
|
-
* @param <Array> includes
|
|
322
|
-
*/
|
|
323
|
-
// async updateMany(params) {
|
|
324
|
-
// try {
|
|
325
|
-
// const {
|
|
326
|
-
// query,
|
|
327
|
-
// data,
|
|
328
|
-
// includes,
|
|
329
|
-
// } = Params(params, {
|
|
330
|
-
// query: {},
|
|
331
|
-
// data: null,
|
|
332
|
-
// includes: null,
|
|
333
|
-
// });
|
|
334
|
-
|
|
335
|
-
// const _includes = typeof includes === 'string' ? parseIncludesQuery(this.model, includes) : null;
|
|
336
|
-
|
|
337
|
-
// let updateResult = null;
|
|
338
|
-
|
|
339
|
-
// if (!!query.id) {
|
|
340
|
-
// updateResult = await this.model.updateById(query.id, data, _includes);
|
|
341
|
-
// }
|
|
342
|
-
// else {
|
|
343
|
-
// // New sequilize query.
|
|
344
|
-
// const modelQuery = {};
|
|
345
|
-
// parseQueryParams(query, modelQuery);
|
|
346
|
-
|
|
347
|
-
// updateResult = await this.model.update(modelQuery.where, data, _includes);
|
|
348
|
-
|
|
349
|
-
// console.log({ updateResult });
|
|
350
|
-
// }
|
|
351
|
-
|
|
352
|
-
// const result = {
|
|
353
|
-
// success:isNewRecord === false,
|
|
354
|
-
// [this.nameSingular]:instance
|
|
355
|
-
// };
|
|
356
|
-
|
|
357
|
-
// // Send output.
|
|
358
|
-
// return Promise.resolve(result);
|
|
359
|
-
// }
|
|
360
|
-
// catch(error) {
|
|
361
|
-
// return Promise.reject(error);
|
|
362
|
-
// }
|
|
363
|
-
// }
|
|
364
|
-
|
|
365
|
-
/*
|
|
366
|
-
* @param <UInt> id
|
|
367
|
-
*/
|
|
368
|
-
async deleteOne(params) {
|
|
369
|
-
try {
|
|
370
|
-
const { id } = Params(params, {
|
|
371
|
-
id: null
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
const count = await this.model.deleteById(id);
|
|
375
|
-
|
|
376
|
-
const result = {
|
|
377
|
-
success: count > 0,
|
|
378
|
-
count: count
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
// Send output.
|
|
382
|
-
return Promise.resolve(result);
|
|
383
|
-
}
|
|
384
|
-
catch(error) {
|
|
385
|
-
return Promise.reject(error);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// Utils:
|
|
2
|
-
const { lowerCaseFirstLetter } = require('nodester/utils/strings.util');
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
module.exports = class ServiceFacade {
|
|
6
|
-
constructor(
|
|
7
|
-
nameSingular,
|
|
8
|
-
namePlural,
|
|
9
|
-
) {
|
|
10
|
-
if (!nameSingular || !namePlural) {
|
|
11
|
-
throw new Error('"nameSingular" and "namePlural" arguments must be set.');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
this.nameSingular = lowerCaseFirstLetter(nameSingular);
|
|
15
|
-
this.namePlural = lowerCaseFirstLetter(namePlural);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,273 +0,0 @@
|
|
|
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
|
-
}
|