@universis/janitor 1.10.0 → 1.12.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/index.d.ts +132 -2
- package/dist/index.esm.js +168 -8
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +173 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/HttpBearerStategy.js +1 -1
- package/src/PassportService.d.ts +6 -0
- package/src/PassportService.js +27 -0
- package/src/RedisClientStore.js +15 -2
- package/src/index.d.ts +2 -0
- package/src/index.js +2 -0
package/dist/index.js
CHANGED
|
@@ -13,6 +13,8 @@ require('@themost/promise-sequence');
|
|
|
13
13
|
var url = require('url');
|
|
14
14
|
var superagent = require('superagent');
|
|
15
15
|
var jwt = require('jsonwebtoken');
|
|
16
|
+
var BearerStrategy = require('passport-http-bearer');
|
|
17
|
+
var passport = require('passport');
|
|
16
18
|
|
|
17
19
|
class RateLimitService extends common.ApplicationService {
|
|
18
20
|
/**
|
|
@@ -531,12 +533,21 @@ class RedisClientStore extends rateLimitRedis.RedisStore {
|
|
|
531
533
|
* @param {{windowMs: number}} options
|
|
532
534
|
*/
|
|
533
535
|
constructor(service, options) {
|
|
536
|
+
// IMPORTANT NOTE: call super with a dummy sendCommand()
|
|
537
|
+
// for implementing a custom sendCommand method
|
|
538
|
+
// which binds sendCommand to this instance
|
|
534
539
|
super({
|
|
535
|
-
|
|
540
|
+
sendCommand: function () {}
|
|
541
|
+
});
|
|
542
|
+
// create a custom sendCommand method
|
|
543
|
+
// noinspection JSCommentMatchesSignature,JSCheckFunctionSignatures
|
|
544
|
+
/**
|
|
545
|
+
* @type {import('redis').RedisClientType}
|
|
546
|
+
*/_defineProperty(this, "client", void 0);const opts = { /**
|
|
536
547
|
* @param {...string} args
|
|
537
548
|
* @returns {Promise<*>}
|
|
538
|
-
*/
|
|
539
|
-
|
|
549
|
+
*/sendCommand: function () {
|
|
550
|
+
|
|
540
551
|
const args = Array.from(arguments);
|
|
541
552
|
const [command] = args.splice(0, 1);
|
|
542
553
|
const self = this;
|
|
@@ -577,7 +588,7 @@ class RedisClientStore extends rateLimitRedis.RedisStore {
|
|
|
577
588
|
// send load script commands once
|
|
578
589
|
return (() => {
|
|
579
590
|
if (self.incrementScriptSha == null) {
|
|
580
|
-
return
|
|
591
|
+
return self.postInit();
|
|
581
592
|
}
|
|
582
593
|
return Promise.resolve();
|
|
583
594
|
})().then(() => {
|
|
@@ -591,9 +602,13 @@ class RedisClientStore extends rateLimitRedis.RedisStore {
|
|
|
591
602
|
});
|
|
592
603
|
});
|
|
593
604
|
}
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
|
|
605
|
+
};
|
|
606
|
+
// bind sendCommand to this instance, applying command array as arguments
|
|
607
|
+
// like rate-limit-redis expects
|
|
608
|
+
// noinspection JSCheckFunctionSignatures
|
|
609
|
+
this.sendCommand = async ({ command }) => opts.sendCommand.bind(this)(...command);
|
|
610
|
+
this.init(options);
|
|
611
|
+
common.TraceUtils.debug('RedisClientStore: Starting up and loading increment and get scripts.');
|
|
597
612
|
void this.postInit().then(() => {
|
|
598
613
|
common.TraceUtils.debug('RedisClientStore: Successfully loaded increment and get scripts.');
|
|
599
614
|
}).catch((err) => {
|
|
@@ -1184,13 +1199,164 @@ class AppSpeedLimitService extends SpeedLimitService {
|
|
|
1184
1199
|
}
|
|
1185
1200
|
}
|
|
1186
1201
|
|
|
1202
|
+
class HttpBearerTokenRequired extends common.HttpError {
|
|
1203
|
+
constructor() {
|
|
1204
|
+
super(499, 'A token is required to fulfill the request.');
|
|
1205
|
+
this.code = 'E_TOKEN_REQUIRED';
|
|
1206
|
+
this.title = 'Token Required';
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
class HttpBearerTokenNotFound extends common.HttpError {
|
|
1211
|
+
constructor() {
|
|
1212
|
+
super(498, 'Token was not found.');
|
|
1213
|
+
this.code = 'E_TOKEN_NOT_FOUND';
|
|
1214
|
+
this.title = 'Invalid token';
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
class HttpBearerTokenExpired extends common.HttpError {
|
|
1219
|
+
constructor() {
|
|
1220
|
+
super(498, 'Token was expired or is in invalid state.');
|
|
1221
|
+
this.code = 'E_TOKEN_EXPIRED';
|
|
1222
|
+
this.title = 'Invalid token';
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
class HttpAccountDisabled extends common.HttpForbiddenError {
|
|
1227
|
+
constructor() {
|
|
1228
|
+
super('Access is denied. User account is disabled.');
|
|
1229
|
+
this.code = 'E_ACCOUNT_DISABLED';
|
|
1230
|
+
this.statusCode = 403.2;
|
|
1231
|
+
this.title = 'Disabled account';
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
class HttpBearerStrategy extends BearerStrategy {
|
|
1236
|
+
constructor() {
|
|
1237
|
+
super({
|
|
1238
|
+
passReqToCallback: true
|
|
1239
|
+
},
|
|
1240
|
+
/**
|
|
1241
|
+
* @param {Request} req
|
|
1242
|
+
* @param {string} token
|
|
1243
|
+
* @param {Function} done
|
|
1244
|
+
*/
|
|
1245
|
+
function (req, token, done) {
|
|
1246
|
+
/**
|
|
1247
|
+
* Gets OAuth2 client services
|
|
1248
|
+
* @type {import('./OAuth2ClientService').OAuth2ClientService}
|
|
1249
|
+
*/
|
|
1250
|
+
let client = req.context.getApplication().getStrategy(function OAuth2ClientService() {});
|
|
1251
|
+
// if client cannot be found
|
|
1252
|
+
if (client == null) {
|
|
1253
|
+
// throw configuration error
|
|
1254
|
+
return done(new Error('Invalid application configuration. OAuth2 client service cannot be found.'));
|
|
1255
|
+
}
|
|
1256
|
+
if (token == null) {
|
|
1257
|
+
// throw 499 Token Required error
|
|
1258
|
+
return done(new HttpBearerTokenRequired());
|
|
1259
|
+
}
|
|
1260
|
+
// get token info
|
|
1261
|
+
client.getTokenInfo(req.context, token).then((info) => {
|
|
1262
|
+
if (info == null) {
|
|
1263
|
+
// the specified token cannot be found - 498 invalid token with specific code
|
|
1264
|
+
return done(new HttpBearerTokenNotFound());
|
|
1265
|
+
}
|
|
1266
|
+
// if the given token is not active throw token expired - 498 invalid token with specific code
|
|
1267
|
+
if (!info.active) {
|
|
1268
|
+
return done(new HttpBearerTokenExpired());
|
|
1269
|
+
}
|
|
1270
|
+
// find user from token info
|
|
1271
|
+
return function () {
|
|
1272
|
+
/**
|
|
1273
|
+
* @type {import('./services/user-provisioning-mapper-service').UserProvisioningMapperService}
|
|
1274
|
+
*/
|
|
1275
|
+
const mapper = req.context.getApplication().getService(function UserProvisioningMapperService() {});
|
|
1276
|
+
if (mapper == null) {
|
|
1277
|
+
return req.context.model('User').where('name').equal(info.username).silent().getItem();
|
|
1278
|
+
}
|
|
1279
|
+
return mapper.getUser(req.context, info);
|
|
1280
|
+
}().then((user) => {
|
|
1281
|
+
// check if userProvisioning service is installed and try to find related user only if user not found
|
|
1282
|
+
if (user == null) {
|
|
1283
|
+
/**
|
|
1284
|
+
* @type {import('./services/user-provisioning-service').UserProvisioningService}
|
|
1285
|
+
*/
|
|
1286
|
+
const service = req.context.getApplication().getService(function UserProvisioningService() {});
|
|
1287
|
+
if (service == null) {
|
|
1288
|
+
return user;
|
|
1289
|
+
}
|
|
1290
|
+
return service.validateUser(req.context, info);
|
|
1291
|
+
}
|
|
1292
|
+
return user;
|
|
1293
|
+
}).then((user) => {
|
|
1294
|
+
// user cannot be found and of course cannot be authenticated (throw forbidden error)
|
|
1295
|
+
if (user == null) {
|
|
1296
|
+
// write access log for forbidden
|
|
1297
|
+
return done(new common.HttpForbiddenError());
|
|
1298
|
+
}
|
|
1299
|
+
// check if user has enabled attribute
|
|
1300
|
+
if (Object.prototype.hasOwnProperty.call(user, 'enabled') && !user.enabled) {
|
|
1301
|
+
//if user.enabled is off throw forbidden error
|
|
1302
|
+
return done(new HttpAccountDisabled('Access is denied. User account is disabled.'));
|
|
1303
|
+
}
|
|
1304
|
+
// otherwise return user data
|
|
1305
|
+
return done(null, {
|
|
1306
|
+
'name': user.name,
|
|
1307
|
+
'authenticationProviderKey': user.id,
|
|
1308
|
+
'authenticationType': 'Bearer',
|
|
1309
|
+
'authenticationToken': token,
|
|
1310
|
+
'authenticationScope': info.scope
|
|
1311
|
+
});
|
|
1312
|
+
});
|
|
1313
|
+
}).catch((err) => {
|
|
1314
|
+
// end log token info request with error
|
|
1315
|
+
if (err && err.statusCode === 404) {
|
|
1316
|
+
// revert 404 not found returned by auth server to 498 invalid token
|
|
1317
|
+
return done(new HttpBearerTokenNotFound());
|
|
1318
|
+
}
|
|
1319
|
+
// otherwise continue with error
|
|
1320
|
+
return done(err);
|
|
1321
|
+
});
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
class PassportService extends common.ApplicationService {
|
|
1327
|
+
constructor(app) {
|
|
1328
|
+
super(app);
|
|
1329
|
+
const authenticator = new passport.Authenticator();
|
|
1330
|
+
Object.defineProperty(this, 'authenticator', {
|
|
1331
|
+
configurable: true,
|
|
1332
|
+
enumerable: false,
|
|
1333
|
+
writable: false,
|
|
1334
|
+
value: authenticator
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
/**
|
|
1339
|
+
* @returns {import('passport').Authenticator}
|
|
1340
|
+
*/
|
|
1341
|
+
getInstance() {
|
|
1342
|
+
return this.authenticator;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1187
1347
|
exports.AppRateLimitService = AppRateLimitService;
|
|
1188
1348
|
exports.AppSpeedLimitService = AppSpeedLimitService;
|
|
1189
1349
|
exports.DefaultScopeAccessConfiguration = DefaultScopeAccessConfiguration;
|
|
1190
1350
|
exports.EnableScopeAccessConfiguration = EnableScopeAccessConfiguration;
|
|
1191
1351
|
exports.ExtendScopeAccessConfiguration = ExtendScopeAccessConfiguration;
|
|
1352
|
+
exports.HttpAccountDisabled = HttpAccountDisabled;
|
|
1353
|
+
exports.HttpBearerStrategy = HttpBearerStrategy;
|
|
1354
|
+
exports.HttpBearerTokenExpired = HttpBearerTokenExpired;
|
|
1355
|
+
exports.HttpBearerTokenNotFound = HttpBearerTokenNotFound;
|
|
1356
|
+
exports.HttpBearerTokenRequired = HttpBearerTokenRequired;
|
|
1192
1357
|
exports.HttpRemoteAddrForbiddenError = HttpRemoteAddrForbiddenError;
|
|
1193
1358
|
exports.OAuth2ClientService = OAuth2ClientService;
|
|
1359
|
+
exports.PassportService = PassportService;
|
|
1194
1360
|
exports.RateLimitService = RateLimitService;
|
|
1195
1361
|
exports.RedisClientStore = RedisClientStore;
|
|
1196
1362
|
exports.RemoteAddressValidator = RemoteAddressValidator;
|