@naturalcycles/backend-lib 8.0.3 → 9.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.
- package/cfg/tsconfig.json +2 -1
- package/dist/admin/adminMiddleware.d.ts +3 -3
- package/dist/admin/adminMiddleware.js +11 -18
- package/dist/admin/base.admin.service.d.ts +1 -1
- package/dist/admin/base.admin.service.js +11 -13
- package/dist/admin/firebase.shared.service.d.ts +3 -3
- package/dist/admin/firebase.shared.service.js +13 -15
- package/dist/admin/secureHeaderMiddleware.d.ts +2 -2
- package/dist/admin/secureHeaderMiddleware.js +7 -10
- package/dist/bin/deploy-gae.js +9 -11
- package/dist/bin/deploy-health-check.js +6 -8
- package/dist/bin/deploy-prepare.js +5 -7
- package/dist/bin/undeploy-gae.js +5 -7
- package/dist/db/httpDB.d.ts +4 -3
- package/dist/db/httpDB.js +19 -21
- package/dist/db/httpDBRequestHandler.d.ts +4 -3
- package/dist/db/httpDBRequestHandler.js +27 -29
- package/dist/db/index.d.ts +3 -2
- package/dist/db/index.js +3 -7
- package/dist/deploy/backend.cfg.util.d.ts +1 -1
- package/dist/deploy/backend.cfg.util.js +6 -9
- package/dist/deploy/deploy.model.js +1 -2
- package/dist/deploy/deploy.util.d.ts +2 -2
- package/dist/deploy/deploy.util.js +25 -33
- package/dist/deploy/deployGae.d.ts +2 -2
- package/dist/deploy/deployGae.js +23 -27
- package/dist/deploy/deployHealthCheck.js +16 -20
- package/dist/deploy/deployPrepare.d.ts +1 -1
- package/dist/deploy/deployPrepare.js +17 -21
- package/dist/deploy/index.d.ts +8 -6
- package/dist/deploy/index.js +6 -14
- package/dist/env/env.shared.service.d.ts +1 -1
- package/dist/env/env.shared.service.js +10 -12
- package/dist/index.d.ts +33 -33
- package/dist/index.js +34 -38
- package/dist/paths.cnst.js +5 -9
- package/dist/sentry/sentry.shared.service.d.ts +1 -1
- package/dist/sentry/sentry.shared.service.js +12 -15
- package/dist/server/asyncLocalStorageMiddleware.d.ts +2 -2
- package/dist/server/asyncLocalStorageMiddleware.js +9 -15
- package/dist/server/basicAuthMiddleware.d.ts +2 -2
- package/dist/server/basicAuthMiddleware.js +5 -8
- package/dist/server/bodyParserTimeoutMiddleware.d.ts +1 -1
- package/dist/server/bodyParserTimeoutMiddleware.js +5 -9
- package/dist/server/createDefaultApp.d.ts +3 -3
- package/dist/server/createDefaultApp.js +22 -23
- package/dist/server/createDefaultApp.model.d.ts +5 -5
- package/dist/server/createDefaultApp.model.js +1 -2
- package/dist/server/deployInfo.util.d.ts +1 -1
- package/dist/server/deployInfo.util.js +5 -8
- package/dist/server/genericErrorMiddleware.d.ts +3 -3
- package/dist/server/genericErrorMiddleware.js +6 -10
- package/dist/server/getDefaultRouter.d.ts +1 -1
- package/dist/server/getDefaultRouter.js +3 -6
- package/dist/server/logMiddleware.d.ts +2 -2
- package/dist/server/logMiddleware.js +12 -16
- package/dist/server/methodOverrideMiddleware.d.ts +1 -1
- package/dist/server/methodOverrideMiddleware.js +1 -4
- package/dist/server/notFoundMiddleware.d.ts +1 -1
- package/dist/server/notFoundMiddleware.js +3 -6
- package/dist/server/okMiddleware.d.ts +1 -1
- package/dist/server/okMiddleware.js +1 -4
- package/dist/server/request.log.util.d.ts +1 -1
- package/dist/server/request.log.util.js +7 -11
- package/dist/server/request.util.d.ts +1 -1
- package/dist/server/request.util.js +1 -4
- package/dist/server/requestTimeoutMiddleware.d.ts +2 -2
- package/dist/server/requestTimeoutMiddleware.js +9 -13
- package/dist/server/safeJsonMiddleware.d.ts +1 -1
- package/dist/server/safeJsonMiddleware.js +3 -6
- package/dist/server/server.model.js +1 -2
- package/dist/server/server.util.d.ts +1 -1
- package/dist/server/server.util.js +1 -4
- package/dist/server/serverStatsMiddleware.d.ts +1 -1
- package/dist/server/serverStatsMiddleware.js +19 -24
- package/dist/server/serverStatusMiddleware.d.ts +1 -1
- package/dist/server/serverStatusMiddleware.js +12 -16
- package/dist/server/simpleRequestLoggerMiddleware.d.ts +1 -1
- package/dist/server/simpleRequestLoggerMiddleware.js +8 -11
- package/dist/server/startServer.d.ts +2 -2
- package/dist/server/startServer.js +20 -22
- package/dist/server/startServer.model.d.ts +4 -4
- package/dist/server/startServer.model.js +1 -2
- package/dist/server/validation/validateMiddleware.d.ts +5 -4
- package/dist/server/validation/validateMiddleware.js +9 -15
- package/dist/server/validation/validateRequest.d.ts +2 -2
- package/dist/server/validation/validateRequest.js +6 -9
- package/dist/server/validation/zodValidateMiddleware.d.ts +3 -3
- package/dist/server/validation/zodValidateMiddleware.js +6 -8
- package/dist/testing/express.test.service.d.ts +6 -6
- package/dist/testing/express.test.service.js +16 -14
- package/dist/testing/index.d.ts +2 -1
- package/dist/testing/index.js +2 -5
- package/dist/util.js +2 -6
- package/package.json +7 -7
- package/src/admin/adminMiddleware.ts +3 -3
- package/src/admin/base.admin.service.ts +1 -1
- package/src/admin/firebase.shared.service.ts +7 -6
- package/src/admin/secureHeaderMiddleware.ts +4 -3
- package/src/bin/deploy-gae.ts +3 -3
- package/src/bin/deploy-health-check.ts +1 -1
- package/src/bin/deploy-prepare.ts +1 -1
- package/src/bin/undeploy-gae.ts +1 -1
- package/src/db/httpDB.ts +5 -6
- package/src/db/httpDBRequestHandler.ts +7 -10
- package/src/db/index.ts +3 -2
- package/src/deploy/backend.cfg.util.ts +2 -2
- package/src/deploy/deploy.util.ts +3 -4
- package/src/deploy/deployGae.ts +6 -4
- package/src/deploy/deployHealthCheck.ts +5 -10
- package/src/deploy/deployPrepare.ts +6 -5
- package/src/deploy/index.ts +8 -6
- package/src/env/env.shared.service.ts +2 -1
- package/src/index.ts +33 -33
- package/src/sentry/sentry.shared.service.ts +5 -10
- package/src/server/asyncLocalStorageMiddleware.ts +4 -3
- package/src/server/basicAuthMiddleware.ts +3 -2
- package/src/server/bodyParserTimeoutMiddleware.ts +2 -1
- package/src/server/createDefaultApp.model.ts +5 -5
- package/src/server/createDefaultApp.ts +17 -14
- package/src/server/deployInfo.util.ts +1 -1
- package/src/server/genericErrorMiddleware.ts +4 -10
- package/src/server/getDefaultRouter.ts +1 -1
- package/src/server/logMiddleware.ts +2 -2
- package/src/server/methodOverrideMiddleware.ts +1 -1
- package/src/server/notFoundMiddleware.ts +2 -2
- package/src/server/okMiddleware.ts +1 -1
- package/src/server/request.log.util.ts +2 -2
- package/src/server/request.util.ts +1 -1
- package/src/server/requestTimeoutMiddleware.ts +4 -9
- package/src/server/safeJsonMiddleware.ts +1 -1
- package/src/server/server.util.ts +3 -3
- package/src/server/serverStatsMiddleware.ts +4 -3
- package/src/server/serverStatusMiddleware.ts +2 -2
- package/src/server/simpleRequestLoggerMiddleware.ts +5 -3
- package/src/server/startServer.model.ts +4 -4
- package/src/server/startServer.ts +5 -8
- package/src/server/validation/validateMiddleware.ts +6 -4
- package/src/server/validation/validateRequest.ts +3 -2
- package/src/server/validation/zodValidateMiddleware.ts +5 -3
- package/src/testing/express.test.service.ts +24 -13
- package/src/testing/index.ts +2 -1
package/cfg/tsconfig.json
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
// Otherwise since es2022 it defaults to true
|
|
28
28
|
// and starts to produce different/unexpected behavior
|
|
29
29
|
// https://angular.schule/blog/2022-11-use-define-for-class-fields
|
|
30
|
-
"useDefineForClassFields":
|
|
30
|
+
"useDefineForClassFields": true,
|
|
31
31
|
"importHelpers": true,
|
|
32
32
|
|
|
33
33
|
// Strictness
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"suppressImplicitAnyIndexErrors": false,
|
|
39
39
|
"noImplicitOverride": true,
|
|
40
40
|
"noUncheckedIndexedAccess": true,
|
|
41
|
+
"noUncheckedSideEffectImports": true,
|
|
41
42
|
"noPropertyAccessFromIndexSignature": true,
|
|
42
43
|
|
|
43
44
|
// Enabled should be faster, but will catch less errors
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { BackendRequestHandler } from '../server/server.model';
|
|
2
|
-
import { BaseAdminService } from './base.admin.service';
|
|
3
|
-
import { FirebaseSharedServiceCfg } from './firebase.shared.service';
|
|
1
|
+
import type { BackendRequestHandler } from '../server/server.model.js';
|
|
2
|
+
import type { BaseAdminService } from './base.admin.service.js';
|
|
3
|
+
import type { FirebaseSharedServiceCfg } from './firebase.shared.service.js';
|
|
4
4
|
export interface RequireAdminCfg {
|
|
5
5
|
/**
|
|
6
6
|
* @default '/login.html'
|
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.loginHtml = loginHtml;
|
|
6
|
-
exports.getLoginHtmlRedirect = getLoginHtmlRedirect;
|
|
7
|
-
const tslib_1 = require("tslib");
|
|
8
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
9
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
10
|
-
const ejs_1 = tslib_1.__importDefault(require("ejs"));
|
|
11
|
-
function createAdminMiddleware(adminService, cfgDefaults = {}) {
|
|
1
|
+
import { _memoFn, AppError } from '@naturalcycles/js-lib';
|
|
2
|
+
import { fs2 } from '@naturalcycles/nodejs-lib';
|
|
3
|
+
import ejs from 'ejs';
|
|
4
|
+
export function createAdminMiddleware(adminService, cfgDefaults = {}) {
|
|
12
5
|
return (reqPermissions, cfg) => requireAdminPermissions(adminService, reqPermissions, {
|
|
13
6
|
...cfgDefaults,
|
|
14
7
|
...cfg,
|
|
@@ -20,7 +13,7 @@ function createAdminMiddleware(adminService, cfgDefaults = {}) {
|
|
|
20
13
|
* If authenticated, but not authorized - will throw 403.
|
|
21
14
|
* Otherwise will just pass.
|
|
22
15
|
*/
|
|
23
|
-
function requireAdminPermissions(adminService, reqPermissions = [], cfg = {}) {
|
|
16
|
+
export function requireAdminPermissions(adminService, reqPermissions = [], cfg = {}) {
|
|
24
17
|
const { loginHtmlPath = '/login.html', urlStartsWith, apiHost, autoLogin = true } = cfg;
|
|
25
18
|
return async function requireAdminPermissionsFn(req, res, next) {
|
|
26
19
|
if (urlStartsWith && !req.url.startsWith(urlStartsWith))
|
|
@@ -30,7 +23,7 @@ function requireAdminPermissions(adminService, reqPermissions = [], cfg = {}) {
|
|
|
30
23
|
return next();
|
|
31
24
|
}
|
|
32
25
|
catch (err) {
|
|
33
|
-
if (err instanceof
|
|
26
|
+
if (err instanceof AppError && err.data.adminAuthRequired) {
|
|
34
27
|
// Redirect to login.html
|
|
35
28
|
const href = `${loginHtmlPath}?${autoLogin ? 'autoLogin=1&' : ''}returnUrl=\${encodeURIComponent(location.href)}${apiHost ? '&apiHost=' + apiHost : ''}`;
|
|
36
29
|
res.status(401).send(getLoginHtmlRedirect(href));
|
|
@@ -41,7 +34,7 @@ function requireAdminPermissions(adminService, reqPermissions = [], cfg = {}) {
|
|
|
41
34
|
}
|
|
42
35
|
};
|
|
43
36
|
}
|
|
44
|
-
function loginHtml(firebaseServiceCfg) {
|
|
37
|
+
export function loginHtml(firebaseServiceCfg) {
|
|
45
38
|
const { apiKey: firebaseApiKey, authDomain: firebaseAuthDomain, adminAuthProvider: firebaseAuthProvider = 'GoogleAuthProvider', } = firebaseServiceCfg;
|
|
46
39
|
return (_req, res) => {
|
|
47
40
|
res.send(getLoginHtml({
|
|
@@ -51,12 +44,12 @@ function loginHtml(firebaseServiceCfg) {
|
|
|
51
44
|
}));
|
|
52
45
|
};
|
|
53
46
|
}
|
|
54
|
-
const getLoginHtml =
|
|
47
|
+
const getLoginHtml = _memoFn((cfg) => {
|
|
55
48
|
console.log(`reading login.html`);
|
|
56
|
-
const tmpl =
|
|
57
|
-
return
|
|
49
|
+
const tmpl = fs2.readText(`${__dirname}/login.html`);
|
|
50
|
+
return ejs.render(tmpl, cfg);
|
|
58
51
|
});
|
|
59
|
-
function getLoginHtmlRedirect(href) {
|
|
52
|
+
export function getLoginHtmlRedirect(href) {
|
|
60
53
|
return `
|
|
61
54
|
<html>
|
|
62
55
|
<body>401 Admin Authentication Required
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type FirebaseAdmin from 'firebase-admin';
|
|
2
|
-
import { BackendRequest, BackendRequestHandler } from '../server/server.model';
|
|
2
|
+
import type { BackendRequest, BackendRequestHandler } from '../server/server.model.js';
|
|
3
3
|
export interface AdminServiceCfg {
|
|
4
4
|
/**
|
|
5
5
|
* @default 'admin_token'
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.BaseAdminService = void 0;
|
|
4
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
1
|
+
import { _assert, AppError } from '@naturalcycles/js-lib';
|
|
2
|
+
import { dimGrey, green, red } from '@naturalcycles/nodejs-lib';
|
|
6
3
|
const adminInfoDisabled = () => ({
|
|
7
4
|
email: 'authDisabled',
|
|
8
5
|
permissions: [],
|
|
@@ -10,7 +7,8 @@ const adminInfoDisabled = () => ({
|
|
|
10
7
|
/**
|
|
11
8
|
* Base implementation based on Firebase Auth tokens passed as 'admin_token' cookie.
|
|
12
9
|
*/
|
|
13
|
-
class BaseAdminService {
|
|
10
|
+
export class BaseAdminService {
|
|
11
|
+
firebaseAuth;
|
|
14
12
|
constructor(firebaseAuth, cfg) {
|
|
15
13
|
this.firebaseAuth = firebaseAuth;
|
|
16
14
|
this.cfg = {
|
|
@@ -19,6 +17,7 @@ class BaseAdminService {
|
|
|
19
17
|
...cfg,
|
|
20
18
|
};
|
|
21
19
|
}
|
|
20
|
+
cfg;
|
|
22
21
|
adminInfoDisabled() {
|
|
23
22
|
return {
|
|
24
23
|
email: 'authDisabled',
|
|
@@ -35,7 +34,7 @@ class BaseAdminService {
|
|
|
35
34
|
async getEmailPermissions(email) {
|
|
36
35
|
if (!email)
|
|
37
36
|
return;
|
|
38
|
-
console.log(`getEmailPermissions (${
|
|
37
|
+
console.log(`getEmailPermissions (${dimGrey(email)}) returning undefined (please override the implementation)`);
|
|
39
38
|
return;
|
|
40
39
|
}
|
|
41
40
|
/**
|
|
@@ -43,7 +42,7 @@ class BaseAdminService {
|
|
|
43
42
|
*/
|
|
44
43
|
// eslint-disable-next-line max-params
|
|
45
44
|
async onPermissionCheck(req, email, reqPermissions, required, granted, meta = {}) {
|
|
46
|
-
req.log(`${
|
|
45
|
+
req.log(`${dimGrey(email)} ${required ? 'required' : 'optional'} permissions check [${dimGrey(reqPermissions.join(', '))}]: ${granted ? green('GRANTED') : red('DENIED')}`, meta);
|
|
47
46
|
}
|
|
48
47
|
async getEmailByToken(req, adminToken) {
|
|
49
48
|
if (!adminToken)
|
|
@@ -51,7 +50,7 @@ class BaseAdminService {
|
|
|
51
50
|
try {
|
|
52
51
|
const decodedToken = await this.firebaseAuth.verifyIdToken(adminToken);
|
|
53
52
|
const email = decodedToken?.email;
|
|
54
|
-
req.log(`admin email: ${
|
|
53
|
+
req.log(`admin email: ${dimGrey(email)}`);
|
|
55
54
|
return email;
|
|
56
55
|
}
|
|
57
56
|
catch (err) {
|
|
@@ -116,7 +115,7 @@ class BaseAdminService {
|
|
|
116
115
|
const adminToken = this.getAdminToken(req);
|
|
117
116
|
const email = await this.getEmailByToken(req, adminToken);
|
|
118
117
|
if (!email) {
|
|
119
|
-
throw new
|
|
118
|
+
throw new AppError('adminToken required', {
|
|
120
119
|
adminAuthRequired: true,
|
|
121
120
|
backendResponseStatusCode: 401,
|
|
122
121
|
userFriendly: true,
|
|
@@ -142,7 +141,7 @@ class BaseAdminService {
|
|
|
142
141
|
}
|
|
143
142
|
}
|
|
144
143
|
if (!granted) {
|
|
145
|
-
throw new
|
|
144
|
+
throw new AppError(`Admin permissions required: [${reqPermissions.join(', ')}]`, {
|
|
146
145
|
adminPermissionsRequired: reqPermissions,
|
|
147
146
|
email,
|
|
148
147
|
backendResponseStatusCode: 403,
|
|
@@ -173,7 +172,7 @@ class BaseAdminService {
|
|
|
173
172
|
getFirebaseAuthLoginHandler() {
|
|
174
173
|
return async (req, res) => {
|
|
175
174
|
const token = req.header('authentication');
|
|
176
|
-
|
|
175
|
+
_assert(token, `401 Unauthenticated`, {
|
|
177
176
|
userFriendly: true,
|
|
178
177
|
backendResponseStatusCode: 401,
|
|
179
178
|
});
|
|
@@ -196,4 +195,3 @@ class BaseAdminService {
|
|
|
196
195
|
};
|
|
197
196
|
}
|
|
198
197
|
}
|
|
199
|
-
exports.BaseAdminService = BaseAdminService;
|
|
@@ -31,7 +31,7 @@ export interface FirebaseSharedServiceCfg {
|
|
|
31
31
|
export declare class FirebaseSharedService {
|
|
32
32
|
cfg: FirebaseSharedServiceCfg;
|
|
33
33
|
constructor(cfg: FirebaseSharedServiceCfg);
|
|
34
|
-
init(): void
|
|
35
|
-
admin(): FirebaseAdmin.app.App
|
|
36
|
-
auth(): FirebaseAdmin.auth.Auth
|
|
34
|
+
init(): Promise<void>;
|
|
35
|
+
admin(): Promise<FirebaseAdmin.app.App>;
|
|
36
|
+
auth(): Promise<FirebaseAdmin.auth.Auth>;
|
|
37
37
|
}
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
6
|
-
class FirebaseSharedService {
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { _Memo } from '@naturalcycles/js-lib';
|
|
3
|
+
export class FirebaseSharedService {
|
|
4
|
+
cfg;
|
|
7
5
|
constructor(cfg) {
|
|
8
6
|
this.cfg = cfg;
|
|
9
7
|
}
|
|
10
|
-
init() {
|
|
11
|
-
this.admin();
|
|
8
|
+
async init() {
|
|
9
|
+
await this.admin();
|
|
12
10
|
}
|
|
13
|
-
admin() {
|
|
11
|
+
async admin() {
|
|
14
12
|
const { serviceAccount } = this.cfg;
|
|
15
13
|
// lazy loading
|
|
16
|
-
const admin =
|
|
14
|
+
const admin = await import('firebase-admin');
|
|
17
15
|
const credential = serviceAccount
|
|
18
16
|
? admin.credential.cert(serviceAccount)
|
|
19
17
|
: admin.credential.applicationDefault();
|
|
@@ -22,11 +20,11 @@ class FirebaseSharedService {
|
|
|
22
20
|
...this.cfg.opt,
|
|
23
21
|
}, this.cfg.appName);
|
|
24
22
|
}
|
|
25
|
-
auth() {
|
|
26
|
-
|
|
23
|
+
async auth() {
|
|
24
|
+
const admin = await this.admin();
|
|
25
|
+
return admin.auth();
|
|
27
26
|
}
|
|
28
27
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
(0, js_lib_1._Memo)()
|
|
28
|
+
__decorate([
|
|
29
|
+
_Memo()
|
|
32
30
|
], FirebaseSharedService.prototype, "admin", null);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AdminMiddleware, RequireAdminCfg } from './adminMiddleware';
|
|
2
|
-
import { BaseAdminService } from './base.admin.service';
|
|
1
|
+
import type { AdminMiddleware, RequireAdminCfg } from './adminMiddleware.js';
|
|
2
|
+
import type { BaseAdminService } from './base.admin.service.js';
|
|
3
3
|
export interface SecureHeaderMiddlewareCfg extends RequireAdminCfg {
|
|
4
4
|
adminService: BaseAdminService;
|
|
5
5
|
/**
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
5
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
6
|
-
const adminMiddleware_1 = require("./adminMiddleware");
|
|
1
|
+
import { AppError } from '@naturalcycles/js-lib';
|
|
2
|
+
import { timingSafeStringEqual } from '@naturalcycles/nodejs-lib';
|
|
3
|
+
import { requireAdminPermissions } from './adminMiddleware.js';
|
|
7
4
|
/**
|
|
8
5
|
* Secures the endpoint by requiring a secret header to be present.
|
|
9
6
|
* Throws Error401Admin otherwise.
|
|
10
7
|
*/
|
|
11
|
-
function createSecureHeaderMiddleware(cfg) {
|
|
8
|
+
export function createSecureHeaderMiddleware(cfg) {
|
|
12
9
|
return reqPermissions => requireSecureHeaderOrAdmin(cfg, reqPermissions);
|
|
13
10
|
}
|
|
14
11
|
function requireSecureHeaderOrAdmin(cfg, reqPermissions) {
|
|
15
12
|
const { secureHeaderKey = 'Authorization', secureHeaderValue } = cfg;
|
|
16
|
-
const requireAdmin =
|
|
13
|
+
const requireAdmin = requireAdminPermissions(cfg.adminService, reqPermissions, cfg);
|
|
17
14
|
return async (req, res, next) => {
|
|
18
15
|
const providedHeader = req.get(secureHeaderKey);
|
|
19
16
|
// pass
|
|
@@ -21,10 +18,10 @@ function requireSecureHeaderOrAdmin(cfg, reqPermissions) {
|
|
|
21
18
|
return next();
|
|
22
19
|
// Header provided - don't check for Admin
|
|
23
20
|
if (providedHeader) {
|
|
24
|
-
if (!secureHeaderValue ||
|
|
21
|
+
if (!secureHeaderValue || timingSafeStringEqual(providedHeader, secureHeaderValue)) {
|
|
25
22
|
return next();
|
|
26
23
|
}
|
|
27
|
-
return next(new
|
|
24
|
+
return next(new AppError('secureHeader or adminToken is required', {
|
|
28
25
|
backendResponseStatusCode: 401,
|
|
29
26
|
adminAuthRequired: true,
|
|
30
27
|
}));
|
package/dist/bin/deploy-gae.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
...deployPrepare_1.deployPrepareYargsOptions,
|
|
11
|
-
...deployHealthCheck_1.deployHealthCheckYargsOptions,
|
|
2
|
+
import { _yargs, runScript } from '@naturalcycles/nodejs-lib';
|
|
3
|
+
import { deployGae } from '../deploy/deployGae.js';
|
|
4
|
+
import { deployHealthCheckYargsOptions } from '../deploy/deployHealthCheck.js';
|
|
5
|
+
import { deployPrepareYargsOptions } from '../deploy/deployPrepare.js';
|
|
6
|
+
runScript(async () => {
|
|
7
|
+
const opt = _yargs().options({
|
|
8
|
+
...deployPrepareYargsOptions,
|
|
9
|
+
...deployHealthCheckYargsOptions,
|
|
12
10
|
}).argv;
|
|
13
|
-
await
|
|
11
|
+
await deployGae(opt);
|
|
14
12
|
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
2
|
/*
|
|
4
3
|
|
|
5
4
|
yarn deploy-health-check --url https://service-dot-yourproject.appspot.com
|
|
@@ -8,16 +7,15 @@ yarn deploy-health-check --url https://service-dot-yourproject.appspot.com
|
|
|
8
7
|
--intervalSec 2
|
|
9
8
|
|
|
10
9
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
...deployHealthCheck_1.deployHealthCheckYargsOptions,
|
|
10
|
+
import { _yargs, runScript } from '@naturalcycles/nodejs-lib';
|
|
11
|
+
import { deployHealthCheck, deployHealthCheckYargsOptions } from '../deploy/deployHealthCheck.js';
|
|
12
|
+
runScript(async () => {
|
|
13
|
+
const { url, ...opt } = _yargs().options({
|
|
14
|
+
...deployHealthCheckYargsOptions,
|
|
17
15
|
url: {
|
|
18
16
|
type: 'string',
|
|
19
17
|
demandOption: true,
|
|
20
18
|
},
|
|
21
19
|
}).argv;
|
|
22
|
-
await
|
|
20
|
+
await deployHealthCheck(url, opt);
|
|
23
21
|
});
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
2
|
/*
|
|
4
3
|
|
|
5
4
|
yarn deploy-prepare
|
|
6
5
|
|
|
7
6
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
await (0, deployPrepare_1.deployPrepare)(opt);
|
|
7
|
+
import { _yargs, runScript } from '@naturalcycles/nodejs-lib';
|
|
8
|
+
import { deployPrepare, deployPrepareYargsOptions } from '../deploy/deployPrepare.js';
|
|
9
|
+
runScript(async () => {
|
|
10
|
+
const opt = _yargs().options(deployPrepareYargsOptions).argv;
|
|
11
|
+
await deployPrepare(opt);
|
|
14
12
|
});
|
|
15
13
|
// deploy strategy
|
|
16
14
|
// gae project: from config
|
package/dist/bin/undeploy-gae.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
(0, nodejs_lib_1.runScript)(async () => {
|
|
7
|
-
const { branch } = (0, nodejs_lib_1._yargs)().options({
|
|
2
|
+
import { _yargs, runScript } from '@naturalcycles/nodejs-lib';
|
|
3
|
+
import { undeployGae } from '../deploy/deployGae.js';
|
|
4
|
+
runScript(async () => {
|
|
5
|
+
const { branch } = _yargs().options({
|
|
8
6
|
branch: {
|
|
9
7
|
type: 'string',
|
|
10
8
|
demandOption: true,
|
|
11
9
|
desc: `Because Github Actions delete event happens after the branch is already deleted - you need to pass it manually`,
|
|
12
10
|
},
|
|
13
11
|
}).argv;
|
|
14
|
-
await
|
|
12
|
+
await undeployGae(branch);
|
|
15
13
|
});
|
package/dist/db/httpDB.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type { CommonDB, CommonDBOptions, CommonDBSaveOptions, CommonDBStreamOptions, CommonDBSupport, DBQuery, RunQueryResult } from '@naturalcycles/db-lib';
|
|
2
|
+
import { BaseCommonDB } from '@naturalcycles/db-lib';
|
|
3
|
+
import type { FetcherOptions, JsonSchemaRootObject, ObjectWithId } from '@naturalcycles/js-lib';
|
|
4
|
+
import type { ReadableTyped } from '@naturalcycles/nodejs-lib';
|
|
4
5
|
export interface HttpDBCfg extends FetcherOptions {
|
|
5
6
|
baseUrl: string;
|
|
6
7
|
}
|
package/dist/db/httpDB.js
CHANGED
|
@@ -1,32 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const node_stream_1 = require("node:stream");
|
|
5
|
-
const db_lib_1 = require("@naturalcycles/db-lib");
|
|
6
|
-
const js_lib_1 = require("@naturalcycles/js-lib");
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
import { BaseCommonDB, commonDBFullSupport } from '@naturalcycles/db-lib';
|
|
3
|
+
import { getFetcher } from '@naturalcycles/js-lib';
|
|
7
4
|
/**
|
|
8
5
|
* Implementation of CommonDB that proxies all requests via HTTP to "httpDBRequestHandler".
|
|
9
6
|
*/
|
|
10
|
-
class HttpDB extends
|
|
7
|
+
export class HttpDB extends BaseCommonDB {
|
|
8
|
+
cfg;
|
|
9
|
+
support = {
|
|
10
|
+
...commonDBFullSupport,
|
|
11
|
+
streaming: false,
|
|
12
|
+
createTable: false,
|
|
13
|
+
bufferValues: false,
|
|
14
|
+
updateSaveMethod: false,
|
|
15
|
+
insertSaveMethod: false,
|
|
16
|
+
transactions: false,
|
|
17
|
+
patchByQuery: false,
|
|
18
|
+
increment: false,
|
|
19
|
+
};
|
|
11
20
|
constructor(cfg) {
|
|
12
21
|
super();
|
|
13
22
|
this.cfg = cfg;
|
|
14
|
-
this.support = {
|
|
15
|
-
...db_lib_1.commonDBFullSupport,
|
|
16
|
-
streaming: false,
|
|
17
|
-
createTable: false,
|
|
18
|
-
bufferValues: false,
|
|
19
|
-
updateSaveMethod: false,
|
|
20
|
-
insertSaveMethod: false,
|
|
21
|
-
transactions: false,
|
|
22
|
-
patchByQuery: false,
|
|
23
|
-
increment: false,
|
|
24
|
-
};
|
|
25
23
|
this.setCfg(cfg);
|
|
26
24
|
}
|
|
27
25
|
setCfg(cfg) {
|
|
28
|
-
this.fetcher =
|
|
26
|
+
this.fetcher = getFetcher(cfg);
|
|
29
27
|
}
|
|
28
|
+
fetcher;
|
|
30
29
|
async ping() {
|
|
31
30
|
await this.fetcher.getVoid(`ping`);
|
|
32
31
|
}
|
|
@@ -92,7 +91,6 @@ class HttpDB extends db_lib_1.BaseCommonDB {
|
|
|
92
91
|
}
|
|
93
92
|
streamQuery(_q, _opt) {
|
|
94
93
|
console.warn(`streamQuery not implemented`);
|
|
95
|
-
return
|
|
94
|
+
return Readable.from([]);
|
|
96
95
|
}
|
|
97
96
|
}
|
|
98
|
-
exports.HttpDB = HttpDB;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { CommonDB, CommonDBOptions, CommonDBSaveOptions
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type { CommonDB, CommonDBOptions, CommonDBSaveOptions } from '@naturalcycles/db-lib';
|
|
2
|
+
import { DBQuery } from '@naturalcycles/db-lib';
|
|
3
|
+
import type { ObjectWithId } from '@naturalcycles/js-lib';
|
|
4
|
+
import type { BackendRouter } from '../server/server.model.js';
|
|
4
5
|
export interface GetByIdsInput {
|
|
5
6
|
table: string;
|
|
6
7
|
ids: string[];
|
|
@@ -1,32 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
ids: (0, nodejs_lib_1.arraySchema)(nodejs_lib_1.stringSchema),
|
|
11
|
-
opt: validation_1.commonDBOptionsSchema.optional(),
|
|
1
|
+
import { DBQuery, InMemoryDB } from '@naturalcycles/db-lib';
|
|
2
|
+
import { commonDBOptionsSchema, commonDBSaveOptionsSchema, dbQuerySchema, } from '@naturalcycles/db-lib/dist/validation/index.js';
|
|
3
|
+
import { anyObjectSchema, arraySchema, objectSchema, stringSchema } from '@naturalcycles/nodejs-lib';
|
|
4
|
+
import { getDefaultRouter } from '../server/getDefaultRouter.js';
|
|
5
|
+
import { validateRequest } from '../server/validation/validateRequest.js';
|
|
6
|
+
const getByIdsInputSchema = objectSchema({
|
|
7
|
+
table: stringSchema,
|
|
8
|
+
ids: arraySchema(stringSchema),
|
|
9
|
+
opt: commonDBOptionsSchema.optional(),
|
|
12
10
|
});
|
|
13
|
-
const runQueryInputSchema =
|
|
14
|
-
query:
|
|
15
|
-
opt:
|
|
11
|
+
const runQueryInputSchema = objectSchema({
|
|
12
|
+
query: dbQuerySchema,
|
|
13
|
+
opt: commonDBOptionsSchema.optional(),
|
|
16
14
|
});
|
|
17
|
-
const saveBatchInputSchema =
|
|
18
|
-
table:
|
|
19
|
-
rows:
|
|
20
|
-
opt:
|
|
15
|
+
const saveBatchInputSchema = objectSchema({
|
|
16
|
+
table: stringSchema,
|
|
17
|
+
rows: arraySchema(anyObjectSchema),
|
|
18
|
+
opt: commonDBSaveOptionsSchema.optional(),
|
|
21
19
|
});
|
|
22
20
|
/**
|
|
23
21
|
* Exposes CommonDB interface from provided CommonDB as HTTP endpoint (Express RequestHandler).
|
|
24
22
|
*/
|
|
25
|
-
function httpDBRequestHandler(db) {
|
|
26
|
-
const router =
|
|
23
|
+
export function httpDBRequestHandler(db) {
|
|
24
|
+
const router = getDefaultRouter();
|
|
27
25
|
// resetCache, only applicable to InMemoryDB
|
|
28
26
|
router.put('/resetCache{/:table}', async (req, res) => {
|
|
29
|
-
if (db instanceof
|
|
27
|
+
if (db instanceof InMemoryDB) {
|
|
30
28
|
await db.resetCache(req.params['table']);
|
|
31
29
|
}
|
|
32
30
|
res.end();
|
|
@@ -50,24 +48,24 @@ function httpDBRequestHandler(db) {
|
|
|
50
48
|
// })
|
|
51
49
|
// getByIds
|
|
52
50
|
router.put('/getByIds', async (req, res) => {
|
|
53
|
-
const { table, ids, opt } =
|
|
51
|
+
const { table, ids, opt } = validateRequest.body(req, getByIdsInputSchema);
|
|
54
52
|
res.json(await db.getByIds(table, ids, opt));
|
|
55
53
|
});
|
|
56
54
|
// runQuery
|
|
57
55
|
router.put('/runQuery', async (req, res) => {
|
|
58
|
-
const { query, opt } =
|
|
59
|
-
const q =
|
|
56
|
+
const { query, opt } = validateRequest.body(req, runQueryInputSchema);
|
|
57
|
+
const q = DBQuery.fromPlainObject(query);
|
|
60
58
|
res.json(await db.runQuery(q, opt));
|
|
61
59
|
});
|
|
62
60
|
// runQueryCount
|
|
63
61
|
router.put('/runQueryCount', async (req, res) => {
|
|
64
|
-
const { query, opt } =
|
|
65
|
-
const q =
|
|
62
|
+
const { query, opt } = validateRequest.body(req, runQueryInputSchema);
|
|
63
|
+
const q = DBQuery.fromPlainObject(query);
|
|
66
64
|
res.json(await db.runQueryCount(q, opt));
|
|
67
65
|
});
|
|
68
66
|
// saveBatch
|
|
69
67
|
router.put('/saveBatch', async (req, res) => {
|
|
70
|
-
const { table, rows, opt } =
|
|
68
|
+
const { table, rows, opt } = validateRequest.body(req, saveBatchInputSchema);
|
|
71
69
|
await db.saveBatch(table, rows, opt);
|
|
72
70
|
res.end();
|
|
73
71
|
});
|
|
@@ -78,8 +76,8 @@ function httpDBRequestHandler(db) {
|
|
|
78
76
|
// })
|
|
79
77
|
// deleteByQuery
|
|
80
78
|
router.put('/deleteByQuery', async (req, res) => {
|
|
81
|
-
const { query, opt } =
|
|
82
|
-
const q =
|
|
79
|
+
const { query, opt } = validateRequest.body(req, runQueryInputSchema);
|
|
80
|
+
const q = DBQuery.fromPlainObject(query);
|
|
83
81
|
res.json(await db.deleteByQuery(q, opt));
|
|
84
82
|
});
|
|
85
83
|
return router;
|
package/dist/db/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { HttpDBCfg } from './httpDB.js';
|
|
2
|
+
import { HttpDB } from './httpDB.js';
|
|
3
|
+
import { httpDBRequestHandler } from './httpDBRequestHandler.js';
|
|
3
4
|
export type { HttpDBCfg };
|
|
4
5
|
export { HttpDB, httpDBRequestHandler };
|
package/dist/db/index.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const httpDB_1 = require("./httpDB");
|
|
5
|
-
Object.defineProperty(exports, "HttpDB", { enumerable: true, get: function () { return httpDB_1.HttpDB; } });
|
|
6
|
-
const httpDBRequestHandler_1 = require("./httpDBRequestHandler");
|
|
7
|
-
Object.defineProperty(exports, "httpDBRequestHandler", { enumerable: true, get: function () { return httpDBRequestHandler_1.httpDBRequestHandler; } });
|
|
1
|
+
import { HttpDB } from './httpDB.js';
|
|
2
|
+
import { httpDBRequestHandler } from './httpDBRequestHandler.js';
|
|
3
|
+
export { HttpDB, httpDBRequestHandler };
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
|
|
5
|
-
const paths_cnst_1 = require("../paths.cnst");
|
|
6
|
-
const backendCfgSchema = nodejs_lib_1.AjvSchema.readJsonSync(`${paths_cnst_1.resourcesDir}/backendCfg.schema.json`, {
|
|
1
|
+
import { AjvSchema, fs2, requireFileToExist } from '@naturalcycles/nodejs-lib';
|
|
2
|
+
import { resourcesDir } from '../paths.cnst.js';
|
|
3
|
+
const backendCfgSchema = AjvSchema.readJsonSync(`${resourcesDir}/backendCfg.schema.json`, {
|
|
7
4
|
objectName: 'backend.cfg.yaml',
|
|
8
5
|
});
|
|
9
|
-
function getBackendCfg(projectDir = '.') {
|
|
6
|
+
export function getBackendCfg(projectDir = '.') {
|
|
10
7
|
const backendCfgYamlPath = `${projectDir}/backend.cfg.yaml`;
|
|
11
|
-
|
|
8
|
+
requireFileToExist(backendCfgYamlPath);
|
|
12
9
|
const backendCfg = {
|
|
13
|
-
...
|
|
10
|
+
...fs2.readYaml(backendCfgYamlPath),
|
|
14
11
|
};
|
|
15
12
|
backendCfgSchema.validate(backendCfg);
|
|
16
13
|
return backendCfg;
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BackendCfg } from './backend.cfg.util';
|
|
2
|
-
import { AppYaml, DeployInfo } from './deploy.model';
|
|
1
|
+
import type { BackendCfg } from './backend.cfg.util.js';
|
|
2
|
+
import type { AppYaml, DeployInfo } from './deploy.model.js';
|
|
3
3
|
export declare function createAndSaveDeployInfo(backendCfg: BackendCfg, targetDir: string): Promise<DeployInfo>;
|
|
4
4
|
export declare function createDeployInfo(backendCfg: BackendCfg, overrideBranch?: string): Promise<DeployInfo>;
|
|
5
5
|
export declare function createAndSaveAppYaml(backendCfg: BackendCfg, deployInfo: DeployInfo, projectDir: string, targetDir: string, appYamlPassEnv?: string): AppYaml;
|