@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.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
- sendCommand: function () {
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 this.postInit();
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
- * @type {import('redis').RedisClientType}
596
- */_defineProperty(this, "client", void 0);this.init(options);common.TraceUtils.debug('RedisClientStore: Starting up and loading increment and get scripts.');
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;