@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.
- package/dist/admin/base.admin.service.js +1 -1
- package/dist/admin/secureHeaderMiddleware.js +2 -1
- package/dist/deploy/deployGae.js +1 -1
- package/dist/server/basicAuthMiddleware.js +1 -1
- package/dist/server/serverStatsMiddleware.js +1 -1
- package/dist/server/serverStatusMiddleware.js +1 -1
- package/dist/server/startServer.js +1 -1
- package/package.json +1 -1
- package/src/admin/base.admin.service.ts +1 -1
- package/src/admin/secureHeaderMiddleware.ts +3 -1
- package/src/server/basicAuthMiddleware.ts +2 -2
- package/src/server/serverStatusMiddleware.ts +1 -1
|
@@ -126,7 +126,7 @@ class BaseAdminService {
|
|
|
126
126
|
const grantedPermissions = hasPermissions
|
|
127
127
|
? reqPermissions.filter(p => hasPermissions.has(p))
|
|
128
128
|
: [];
|
|
129
|
-
let granted
|
|
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
|
|
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,
|
package/dist/deploy/deployGae.js
CHANGED
|
@@ -35,7 +35,7 @@ async function deployGae(opt = {}) {
|
|
|
35
35
|
}, {
|
|
36
36
|
name: 'deploy',
|
|
37
37
|
maxAttempts: 2,
|
|
38
|
-
delay:
|
|
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]
|
|
12
|
+
if (login && password && (0, nodejs_lib_1.timingSafeStringEqual)(cfg.loginPasswordMap[login], password)) {
|
|
13
13
|
return next();
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -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)().
|
|
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 ??
|
|
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
|
@@ -191,7 +191,7 @@ export class BaseAdminService {
|
|
|
191
191
|
? reqPermissions.filter(p => hasPermissions.has(p))
|
|
192
192
|
: []
|
|
193
193
|
|
|
194
|
-
let granted
|
|
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
|
|
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]
|
|
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().
|
|
43
|
+
const started = localTimeNow().minus(process.uptime(), 'second')
|
|
44
44
|
return `${started.toPretty()} (${started.fromNow()})`
|
|
45
45
|
}
|