@naturalcycles/backend-lib 5.3.0 → 5.4.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.
@@ -126,7 +126,7 @@ class BaseAdminService {
126
126
  const grantedPermissions = hasPermissions
127
127
  ? reqPermissions.filter(p => hasPermissions.has(p))
128
128
  : [];
129
- let granted = false;
129
+ let granted;
130
130
  if (andComparison) {
131
131
  granted = !!hasPermissions && grantedPermissions.length === reqPermissions.length; // All permissions granted
132
132
  void this.onPermissionCheck(req, email, reqPermissions, true, granted, meta);
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createSecureHeaderMiddleware = void 0;
4
4
  const js_lib_1 = require("@naturalcycles/js-lib");
5
+ const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
5
6
  const adminMiddleware_1 = require("./adminMiddleware");
6
7
  /**
7
8
  * Secures the endpoint by requiring a secret header to be present.
@@ -21,7 +22,7 @@ function requireSecureHeaderOrAdmin(cfg, reqPermissions) {
21
22
  return next();
22
23
  // Header provided - don't check for Admin
23
24
  if (providedHeader) {
24
- if (!secureHeaderValue || providedHeader === secureHeaderValue)
25
+ if (!secureHeaderValue || (0, nodejs_lib_1.timingSafeStringEqual)(providedHeader, secureHeaderValue))
25
26
  return next();
26
27
  return next(new js_lib_1.AppError('secureHeader or adminToken is required', {
27
28
  backendResponseStatusCode: 401,
@@ -35,7 +35,7 @@ async function deployGae(opt = {}) {
35
35
  }, {
36
36
  name: 'deploy',
37
37
  maxAttempts: 2,
38
- delay: 30000,
38
+ delay: 30_000,
39
39
  // todo: this doesn't work, as the error is different from what is logged.
40
40
  // We shoud somehow capture the logged text
41
41
  predicate: err => (0, js_lib_1._anyToError)(err).message.includes('operation is already in progress'),
@@ -9,7 +9,7 @@ function basicAuthMiddleware(cfg) {
9
9
  const hash = (req.headers.authorization || '').split(' ')[1];
10
10
  if (hash) {
11
11
  const [login, password] = (0, js_lib_1._split)((0, nodejs_lib_1.base64ToString)(hash), ':', 2);
12
- if (login && password && cfg.loginPasswordMap[login] === password) {
12
+ if (login && password && (0, nodejs_lib_1.timingSafeStringEqual)(cfg.loginPasswordMap[login], password)) {
13
13
  return next();
14
14
  }
15
15
  }
@@ -88,7 +88,7 @@ function serverStatsMiddleware() {
88
88
  if (res.statusCode) {
89
89
  serverStatsMap[endpoint][getStatusFamily(res.statusCode)]++;
90
90
  }
91
- if (now - lastCleanup > 60000) {
91
+ if (now - lastCleanup > 60_000) {
92
92
  lastCleanup = now;
93
93
  cleanupServerStats();
94
94
  }
@@ -36,6 +36,6 @@ function getServerStatusData(projectDir = process.cwd(), extra) {
36
36
  }
37
37
  exports.getServerStatusData = getServerStatusData;
38
38
  function getStartedStr() {
39
- const started = (0, js_lib_1.localTimeNow)().subtract(process.uptime(), 'second');
39
+ const started = (0, js_lib_1.localTimeNow)().minus(process.uptime(), 'second');
40
40
  return `${started.toPretty()} (${started.fromNow()})`;
41
41
  }
@@ -62,7 +62,7 @@ class BackendServer {
62
62
  const shutdownTimeout = setTimeout(() => {
63
63
  console.log((0, nodejs_lib_1.boldGrey)('Forceful shutdown after timeout'));
64
64
  process.exit(0);
65
- }, this.cfg.forceShutdownTimeout ?? 10000);
65
+ }, this.cfg.forceShutdownTimeout ?? 10_000);
66
66
  try {
67
67
  await Promise.all([
68
68
  this.server && new Promise(r => this.server.close(r)),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/backend-lib",
3
- "version": "5.3.0",
3
+ "version": "5.4.1",
4
4
  "scripts": {
5
5
  "prepare": "husky",
6
6
  "dev": "APP_ENV=dev nodemon",
@@ -191,7 +191,7 @@ export class BaseAdminService {
191
191
  ? reqPermissions.filter(p => hasPermissions.has(p))
192
192
  : []
193
193
 
194
- let granted = false
194
+ let granted: boolean
195
195
  if (andComparison) {
196
196
  granted = !!hasPermissions && grantedPermissions.length === reqPermissions.length // All permissions granted
197
197
  void this.onPermissionCheck(req, email, reqPermissions, true, granted, meta)
@@ -1,4 +1,5 @@
1
1
  import { AppError } from '@naturalcycles/js-lib'
2
+ import { timingSafeStringEqual } from '@naturalcycles/nodejs-lib'
2
3
  import { BackendRequestHandler } from '../server/server.model'
3
4
  import { AdminMiddleware, RequireAdminCfg, requireAdminPermissions } from './adminMiddleware'
4
5
  import { BaseAdminService } from './base.admin.service'
@@ -41,7 +42,8 @@ function requireSecureHeaderOrAdmin(
41
42
 
42
43
  // Header provided - don't check for Admin
43
44
  if (providedHeader) {
44
- if (!secureHeaderValue || providedHeader === secureHeaderValue) return next()
45
+ if (!secureHeaderValue || timingSafeStringEqual(providedHeader, secureHeaderValue))
46
+ return next()
45
47
 
46
48
  return next(
47
49
  new AppError('secureHeader or adminToken is required', {
@@ -1,5 +1,5 @@
1
1
  import { _split, StringMap } from '@naturalcycles/js-lib'
2
- import { base64ToString } from '@naturalcycles/nodejs-lib'
2
+ import { base64ToString, timingSafeStringEqual } from '@naturalcycles/nodejs-lib'
3
3
  import { BackendRequestHandler } from './server.model'
4
4
 
5
5
  export interface BasicAuthMiddlewareCfg {
@@ -21,7 +21,7 @@ export function basicAuthMiddleware(cfg: BasicAuthMiddlewareCfg): BackendRequest
21
21
  const hash = (req.headers.authorization || '').split(' ')[1]
22
22
  if (hash) {
23
23
  const [login, password] = _split(base64ToString(hash), ':', 2)
24
- if (login && password && cfg.loginPasswordMap[login] === password) {
24
+ if (login && password && timingSafeStringEqual(cfg.loginPasswordMap[login], password)) {
25
25
  return next()
26
26
  }
27
27
  }
@@ -40,6 +40,6 @@ export function getServerStatusData(
40
40
  }
41
41
 
42
42
  function getStartedStr(): string {
43
- const started = localTimeNow().subtract(process.uptime(), 'second')
43
+ const started = localTimeNow().minus(process.uptime(), 'second')
44
44
  return `${started.toPretty()} (${started.fromNow()})`
45
45
  }