@ladjs/web 16.0.2 → 17.0.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.
Files changed (2) hide show
  1. package/index.js +36 -68
  2. package/package.json +6 -7
package/index.js CHANGED
@@ -38,7 +38,6 @@ const koaCash = require('koa-cash');
38
38
  const koaConnect = require('koa-connect');
39
39
  const methodOverride = require('koa-methodoverride');
40
40
  const ms = require('ms');
41
- const multimatch = require('multimatch');
42
41
  const ratelimit = require('@ladjs/koa-simple-ratelimit');
43
42
  const redisStore = require('koa-redis');
44
43
  const removeTrailingSlashes = require('koa-no-trailing-slash');
@@ -67,13 +66,13 @@ const reportUri = isSANB(process.env.WEB_URL)
67
66
  : null;
68
67
 
69
68
  const INVALID_TOKEN_MESSAGE = 'Invalid CSRF token.';
70
- const RATE_LIMIT_EXCEEDED = `Rate limit exceeded, retry in %s.`;
71
69
 
72
70
  class Web {
73
71
  // eslint-disable-next-line complexity
74
72
  constructor(config, Users) {
73
+ const sharedWebConfig = sharedConfig('WEB');
75
74
  this.config = {
76
- ...sharedConfig('WEB'),
75
+ ...sharedWebConfig,
77
76
  meta: {},
78
77
  views: {
79
78
  root: path.resolve('./app/views'),
@@ -82,9 +81,23 @@ class Web {
82
81
  extension: 'pug'
83
82
  }
84
83
  },
85
- csrf: {},
86
- csrfIgnoredGlobs: ['/report'],
87
- rateLimitIgnoredGlobs: ['/report'],
84
+ csrf: {
85
+ ...sharedWebConfig.csrf,
86
+ ignoredPathGlobs: ['/report'],
87
+ errorHandler(ctx) {
88
+ return ctx.throw(
89
+ Boom.forbidden(
90
+ typeof ctx.request.t === 'function'
91
+ ? ctx.request.t(INVALID_TOKEN_MESSAGE)
92
+ : INVALID_TOKEN_MESSAGE
93
+ )
94
+ );
95
+ }
96
+ },
97
+ rateLimit: {
98
+ ...sharedWebConfig.rateLimit,
99
+ ignoredPathGlobs: ['/report']
100
+ },
88
101
  sessionKeys: process.env.SESSION_KEYS
89
102
  ? process.env.SESSION_KEYS.split(',')
90
103
  : ['lad'],
@@ -242,30 +255,14 @@ class Web {
242
255
  if (this.config.auth) app.use(auth(this.config.auth));
243
256
 
244
257
  // rate limiting
245
- if (this.config.rateLimit) {
246
- app.use((ctx, next) => {
247
- // check against ignored/whitelisted paths
248
- if (
249
- Array.isArray(this.config.rateLimitIgnoredGlobs) &&
250
- this.config.rateLimitIgnoredGlobs.length > 0
251
- ) {
252
- const match = multimatch(ctx.path, this.config.rateLimitIgnoredGlobs);
253
- if (Array.isArray(match) && match.length > 0) return next();
254
- }
255
-
256
- return ratelimit({
258
+ if (this.config.rateLimit)
259
+ app.use(
260
+ ratelimit({
257
261
  ...this.config.rateLimit,
258
262
  db: this.client,
259
- logger: this.logger,
260
- errorMessage(exp) {
261
- const fn =
262
- typeof ctx.request.t === 'function' ? ctx.request.t : util.format;
263
- // NOTE: ms does not support i18n localization
264
- return fn(RATE_LIMIT_EXCEEDED, ms(exp, { long: true }));
265
- }
266
- })(ctx, next);
267
- });
268
- }
263
+ logger: this.logger
264
+ })
265
+ );
269
266
 
270
267
  // remove trailing slashes
271
268
  app.use(removeTrailingSlashes());
@@ -364,9 +361,7 @@ class Web {
364
361
  ctx.state.ctx.path = ctx.path;
365
362
  ctx.state.ctx.pathWithoutLocale = ctx.pathWithoutLocale;
366
363
  ctx.state.ctx.query = ctx.query;
367
- ctx.state.ctx.session = ctx.session;
368
364
  ctx.state.ctx.sessionId = ctx.sessionId;
369
- ctx.state.ctx.translate = ctx.translate;
370
365
  ctx.state.ctx.url = ctx.url;
371
366
 
372
367
  return next();
@@ -374,23 +369,15 @@ class Web {
374
369
 
375
370
  // session store
376
371
  app.keys = this.config.sessionKeys;
377
- app.use(async (ctx, next) => {
378
- try {
379
- await session({
380
- store: redisStore({ client: this.client }),
381
- key: this.config.cookiesKey,
382
- cookie: this.config.cookies,
383
- genSid: this.config.genSid,
384
- ...this.config.session
385
- })(ctx, () => Promise.resolve());
386
- } catch (err) {
387
- // this would indicate that redis is down
388
- ctx.logger.error(err);
389
- delete ctx.session;
390
- }
391
-
392
- return next();
393
- });
372
+ app.use(
373
+ session({
374
+ store: redisStore({ client: this.client }),
375
+ key: this.config.cookiesKey,
376
+ cookie: this.config.cookies,
377
+ genSid: this.config.genSid,
378
+ ...this.config.session
379
+ })
380
+ );
394
381
 
395
382
  // redirect loop (must come after sessions added)
396
383
  if (this.config.redirectLoop) {
@@ -415,34 +402,15 @@ class Web {
415
402
  if (this.config.methodOverride)
416
403
  app.use(methodOverride(...this.config.methodOverride));
417
404
 
418
- // TODO: move this into `@ladjs/csrf`
419
405
  // csrf (with added localization support)
420
406
  if (this.config.csrf && process.env.NODE_ENV !== 'test') {
421
- const csrf = new CSRF({
422
- ...this.config.csrf,
423
- invalidTokenMessage: (ctx) =>
424
- typeof ctx.request.t === 'function'
425
- ? ctx.request.t(INVALID_TOKEN_MESSAGE)
426
- : INVALID_TOKEN_MESSAGE
427
- });
407
+ const csrf = new CSRF(this.config.csrf);
428
408
  app.use(async (ctx, next) => {
429
- // check against ignored/whitelisted redirect middleware paths
430
- if (
431
- Array.isArray(this.config.csrfIgnoredGlobs) &&
432
- this.config.csrfIgnoredGlobs.length > 0
433
- ) {
434
- const match = multimatch(ctx.path, this.config.csrfIgnoredGlobs);
435
- if (Array.isArray(match) && match.length > 0) return next();
436
- }
437
-
438
409
  try {
439
410
  await csrf(ctx, next);
440
411
  } catch (err) {
441
- ctx.logger.error(err);
442
412
  let error = err;
443
- // this would indicate that redis is down
444
- if (!ctx.session) error = Boom.clientTimeout();
445
- else if (err.name && err.name === 'ForbiddenError')
413
+ if (err.name && err.name === 'ForbiddenError')
446
414
  error = Boom.forbidden(err.message);
447
415
 
448
416
  ctx.throw(error);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ladjs/web",
3
3
  "description": "Web server for Lad",
4
- "version": "16.0.2",
4
+ "version": "17.0.0",
5
5
  "author": "Nick Baugh <niftylettuce@gmail.com> (http://niftylettuce.com/)",
6
6
  "bugs": {
7
7
  "url": "https://github.com/ladjs/web/issues",
@@ -17,10 +17,10 @@
17
17
  "@ladjs/koa-better-static": "^2.0.1",
18
18
  "@ladjs/koa-cache-responses": "^0.0.3",
19
19
  "@ladjs/koa-isajax": "^2.0.0",
20
- "@ladjs/koa-simple-ratelimit": "^3.0.0",
20
+ "@ladjs/koa-simple-ratelimit": "^4.0.1",
21
21
  "@ladjs/redis": "^1.0.7",
22
- "@ladjs/shared-config": "^7.0.3",
23
- "@ladjs/state-helper": "^2.0.0",
22
+ "@ladjs/shared-config": "^8.0.0",
23
+ "@ladjs/state-helper": "^2.0.2",
24
24
  "@ladjs/store-ip-address": "^0.0.7",
25
25
  "boolean": "^3.2.0",
26
26
  "cabin": "^9.1.2",
@@ -39,7 +39,7 @@
39
39
  "koa-compress": "^5.1.0",
40
40
  "koa-conditional-get": "^3.0.0",
41
41
  "koa-connect": "^2.1.0",
42
- "koa-csrf": "^4.0.0",
42
+ "koa-csrf": "^5.0.0",
43
43
  "koa-etag": "^4.0.0",
44
44
  "koa-favicon": "^2.1.0",
45
45
  "koa-generic-session": "^2.3.0",
@@ -53,7 +53,6 @@
53
53
  "koa-views": "^8.0.0",
54
54
  "lodash": "^4.17.21",
55
55
  "ms": "^2.1.3",
56
- "multimatch": "5",
57
56
  "request-received": "^0.0.3",
58
57
  "response-time": "^2.3.2"
59
58
  },
@@ -63,7 +62,7 @@
63
62
  "@ladjs/passport": "^5.0.2",
64
63
  "ava": "^4.3.0",
65
64
  "cross-env": "^7.0.3",
66
- "eslint": "^8.18.0",
65
+ "eslint": "^8.19.0",
67
66
  "eslint-config-xo-lass": "^2.0.1",
68
67
  "fixpack": "^4.0.0",
69
68
  "husky": "^8.0.1",