@balena/pinejs 16.0.0-build--batch-f2ffc3d6bcb9f3294fd4fc9de3c21bfe167e100d-1 → 16.0.0-build-fisehara-update-sbvr-types-b58e72aca3193964afac96c955fde178fe39d077-1
Sign up to get free protection for your applications and to get access to all the features.
- package/.pinejs-cache.json +1 -1
- package/.versionbot/CHANGELOG.yml +2168 -11
- package/CHANGELOG.md +815 -2
- package/Gruntfile.ts +9 -6
- package/README.md +10 -0
- package/build/browser.ts +2 -2
- package/build/config.ts +1 -1
- package/build/module.ts +2 -2
- package/build/server.ts +2 -2
- package/docker-compose.npm-test.yml +21 -3
- package/out/bin/abstract-sql-compiler.js +5 -5
- package/out/bin/abstract-sql-compiler.js.map +1 -1
- package/out/bin/odata-compiler.js +10 -10
- package/out/bin/odata-compiler.js.map +1 -1
- package/out/bin/sbvr-compiler.js +34 -11
- package/out/bin/sbvr-compiler.js.map +1 -1
- package/out/bin/utils.js +25 -2
- package/out/bin/utils.js.map +1 -1
- package/out/config-loader/config-loader.d.ts +4 -2
- package/out/config-loader/config-loader.js +54 -13
- package/out/config-loader/config-loader.js.map +1 -1
- package/out/config-loader/env.d.ts +2 -1
- package/out/config-loader/env.js +5 -2
- package/out/config-loader/env.js.map +1 -1
- package/out/data-server/sbvr-server.d.ts +1 -1
- package/out/data-server/sbvr-server.js +3 -1
- package/out/data-server/sbvr-server.js.map +1 -1
- package/out/database-layer/db.js +40 -14
- package/out/database-layer/db.js.map +1 -1
- package/out/express-emulator/express.js +5 -3
- package/out/express-emulator/express.js.map +1 -1
- package/out/http-transactions/transactions.d.ts +1 -1
- package/out/http-transactions/transactions.js +10 -5
- package/out/http-transactions/transactions.js.map +1 -1
- package/out/migrator/async.js +32 -5
- package/out/migrator/async.js.map +1 -1
- package/out/migrator/sync.d.ts +2 -1
- package/out/migrator/sync.js +29 -3
- package/out/migrator/sync.js.map +1 -1
- package/out/migrator/utils.d.ts +6 -3
- package/out/migrator/utils.js +30 -4
- package/out/migrator/utils.js.map +1 -1
- package/out/odata-metadata/odata-metadata-generator.js +4 -1
- package/out/odata-metadata/odata-metadata-generator.js.map +1 -1
- package/out/passport-pinejs/mount-login-router.d.ts +3 -0
- package/out/passport-pinejs/mount-login-router.js +65 -0
- package/out/passport-pinejs/mount-login-router.js.map +1 -0
- package/out/passport-pinejs/passport-pinejs.d.ts +2 -1
- package/out/passport-pinejs/passport-pinejs.js +28 -2
- package/out/passport-pinejs/passport-pinejs.js.map +1 -1
- package/out/pinejs-session-store/pinejs-session-store.js +30 -7
- package/out/pinejs-session-store/pinejs-session-store.js.map +1 -1
- package/out/sbvr-api/abstract-sql.d.ts +2 -2
- package/out/sbvr-api/abstract-sql.js +35 -9
- package/out/sbvr-api/abstract-sql.js.map +1 -1
- package/out/sbvr-api/cached-compile.js +9 -6
- package/out/sbvr-api/cached-compile.js.map +1 -1
- package/out/sbvr-api/common-types.d.ts +1 -1
- package/out/sbvr-api/control-flow.js +5 -2
- package/out/sbvr-api/control-flow.js.map +1 -1
- package/out/sbvr-api/express-extension.d.ts +10 -7
- package/out/sbvr-api/express-extension.js +1 -0
- package/out/sbvr-api/hooks.d.ts +5 -1
- package/out/sbvr-api/hooks.js +12 -10
- package/out/sbvr-api/hooks.js.map +1 -1
- package/out/sbvr-api/odata-response.d.ts +5 -2
- package/out/sbvr-api/odata-response.js +36 -6
- package/out/sbvr-api/odata-response.js.map +1 -1
- package/out/sbvr-api/permissions.d.ts +6 -7
- package/out/sbvr-api/permissions.js +69 -38
- package/out/sbvr-api/permissions.js.map +1 -1
- package/out/sbvr-api/sbvr-utils.d.ts +20 -9
- package/out/sbvr-api/sbvr-utils.js +134 -136
- package/out/sbvr-api/sbvr-utils.js.map +1 -1
- package/out/sbvr-api/translations.d.ts +2 -2
- package/out/sbvr-api/translations.js +17 -10
- package/out/sbvr-api/translations.js.map +1 -1
- package/out/sbvr-api/uri-parser.d.ts +7 -10
- package/out/sbvr-api/uri-parser.js +46 -19
- package/out/sbvr-api/uri-parser.js.map +1 -1
- package/out/server-glue/global-ext.d.ts +2 -1
- package/out/server-glue/module.d.ts +3 -1
- package/out/server-glue/module.js +40 -13
- package/out/server-glue/module.js.map +1 -1
- package/out/server-glue/sbvr-loader.js.map +1 -1
- package/out/server-glue/server.js +31 -39
- package/out/server-glue/server.js.map +1 -1
- package/out/webresource-handler/handlers/NoopHandler.d.ts +7 -0
- package/out/webresource-handler/handlers/NoopHandler.js +20 -0
- package/out/webresource-handler/handlers/NoopHandler.js.map +1 -0
- package/out/webresource-handler/handlers/S3Handler.d.ts +28 -0
- package/out/webresource-handler/handlers/S3Handler.js +97 -0
- package/out/webresource-handler/handlers/S3Handler.js.map +1 -0
- package/out/webresource-handler/handlers/index.d.ts +2 -0
- package/out/webresource-handler/handlers/index.js +19 -0
- package/out/webresource-handler/handlers/index.js.map +1 -0
- package/out/webresource-handler/index.d.ts +34 -0
- package/out/webresource-handler/index.js +307 -0
- package/out/webresource-handler/index.js.map +1 -0
- package/package.json +68 -62
- package/src/bin/abstract-sql-compiler.ts +7 -9
- package/src/bin/odata-compiler.ts +12 -15
- package/src/bin/sbvr-compiler.ts +14 -18
- package/src/bin/utils.ts +1 -1
- package/src/config-loader/config-loader.ts +44 -10
- package/src/config-loader/env.ts +1 -1
- package/src/data-server/sbvr-server.js +3 -1
- package/src/database-layer/db.ts +23 -19
- package/src/express-emulator/express.js +5 -3
- package/src/extended-sbvr-parser/extended-sbvr-parser.ts +1 -1
- package/src/http-transactions/transactions.js +10 -5
- package/src/migrator/async.ts +7 -6
- package/src/migrator/sync.ts +10 -7
- package/src/migrator/utils.ts +11 -5
- package/src/odata-metadata/odata-metadata-generator.ts +2 -2
- package/src/passport-pinejs/mount-login-router.ts +46 -0
- package/src/passport-pinejs/passport-pinejs.ts +7 -3
- package/src/pinejs-session-store/pinejs-session-store.ts +6 -6
- package/src/sbvr-api/abstract-sql.ts +5 -5
- package/src/sbvr-api/cached-compile.ts +1 -2
- package/src/sbvr-api/common-types.ts +1 -1
- package/src/sbvr-api/control-flow.ts +1 -1
- package/src/sbvr-api/express-extension.ts +12 -8
- package/src/sbvr-api/hooks.ts +11 -11
- package/src/sbvr-api/odata-response.ts +56 -9
- package/src/sbvr-api/permissions.ts +44 -35
- package/src/sbvr-api/sbvr-utils.ts +118 -172
- package/src/sbvr-api/translations.ts +9 -6
- package/src/sbvr-api/uri-parser.ts +22 -28
- package/src/server-glue/global-ext.d.ts +2 -1
- package/src/server-glue/module.ts +8 -2
- package/src/server-glue/sbvr-loader.ts +1 -1
- package/src/server-glue/server.ts +11 -49
- package/src/webresource-handler/handlers/NoopHandler.ts +21 -0
- package/src/webresource-handler/handlers/S3Handler.ts +143 -0
- package/src/webresource-handler/handlers/index.ts +2 -0
- package/src/webresource-handler/index.ts +450 -0
- package/tsconfig.dev.json +2 -1
- package/tsconfig.json +1 -1
- package/typings/lf-to-abstract-sql.d.ts +1 -1
- package/typings/memoizee.d.ts +3 -4
@@ -10,7 +10,7 @@ import * as permissions from '../sbvr-api/permissions';
|
|
10
10
|
export let login: (
|
11
11
|
fn: (
|
12
12
|
err: any,
|
13
|
-
user:
|
13
|
+
user: object | null | false | undefined,
|
14
14
|
req: Express.Request,
|
15
15
|
res: Express.Response,
|
16
16
|
next: Express.NextFunction,
|
@@ -35,12 +35,13 @@ export const checkPassword: PassportLocal.VerifyFunction = async (
|
|
35
35
|
|
36
36
|
const setup: ConfigLoader.SetupFunction = async (app: Express.Application) => {
|
37
37
|
if (!process.browser) {
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
38
39
|
const passport: typeof Passport = require('passport');
|
39
40
|
app.use(passport.initialize());
|
40
41
|
app.use(passport.session());
|
41
42
|
|
42
43
|
const {
|
43
|
-
Strategy: LocalStrategy,
|
44
|
+
Strategy: LocalStrategy, // eslint-disable-next-line @typescript-eslint/no-var-requires
|
44
45
|
}: typeof PassportLocal = require('passport-local');
|
45
46
|
|
46
47
|
passport.serializeUser((user, done) => {
|
@@ -66,7 +67,10 @@ const setup: ConfigLoader.SetupFunction = async (app: Express.Application) => {
|
|
66
67
|
|
67
68
|
logout = (req, _res, next) => {
|
68
69
|
req.logout((error) => {
|
69
|
-
|
70
|
+
if (error) {
|
71
|
+
return next(error);
|
72
|
+
}
|
73
|
+
next();
|
70
74
|
});
|
71
75
|
};
|
72
76
|
} else {
|
@@ -50,7 +50,7 @@ const asCallback = async <T>(
|
|
50
50
|
|
51
51
|
export class PinejsSessionStore extends Store {
|
52
52
|
public get = ((sid, callback) => {
|
53
|
-
asCallback(
|
53
|
+
void asCallback(
|
54
54
|
callback,
|
55
55
|
api.session
|
56
56
|
.get({
|
@@ -77,7 +77,7 @@ export class PinejsSessionStore extends Store {
|
|
77
77
|
data,
|
78
78
|
expiry_time: data?.cookie?.expires ?? null,
|
79
79
|
};
|
80
|
-
asCallback(
|
80
|
+
void asCallback(
|
81
81
|
callback,
|
82
82
|
api.session.put({
|
83
83
|
resource: 'session',
|
@@ -91,7 +91,7 @@ export class PinejsSessionStore extends Store {
|
|
91
91
|
}) as Store['set'];
|
92
92
|
|
93
93
|
public destroy = ((sid, callback) => {
|
94
|
-
asCallback(
|
94
|
+
void asCallback(
|
95
95
|
callback,
|
96
96
|
api.session.delete({
|
97
97
|
resource: 'session',
|
@@ -104,7 +104,7 @@ export class PinejsSessionStore extends Store {
|
|
104
104
|
}) as Store['destroy'];
|
105
105
|
|
106
106
|
public all = ((callback) => {
|
107
|
-
asCallback(
|
107
|
+
void asCallback(
|
108
108
|
callback,
|
109
109
|
api.session
|
110
110
|
.get({
|
@@ -124,7 +124,7 @@ export class PinejsSessionStore extends Store {
|
|
124
124
|
}) as Store['all'];
|
125
125
|
|
126
126
|
public clear = ((callback) => {
|
127
|
-
asCallback(
|
127
|
+
void asCallback(
|
128
128
|
callback,
|
129
129
|
// TODO: Use a truncate
|
130
130
|
api.session.delete({
|
@@ -137,7 +137,7 @@ export class PinejsSessionStore extends Store {
|
|
137
137
|
}) as Store['clear'];
|
138
138
|
|
139
139
|
public length = ((callback) => {
|
140
|
-
asCallback(
|
140
|
+
void asCallback(
|
141
141
|
callback,
|
142
142
|
api.session.get({
|
143
143
|
resource: 'session/',
|
@@ -1,18 +1,18 @@
|
|
1
|
-
import
|
1
|
+
import _ from 'lodash';
|
2
2
|
|
3
3
|
import * as AbstractSQLCompiler from '@balena/abstract-sql-compiler';
|
4
4
|
import type { BindKey } from '@balena/odata-parser';
|
5
5
|
import {
|
6
|
-
ODataBinds,
|
6
|
+
type ODataBinds,
|
7
7
|
odataNameToSqlName,
|
8
8
|
isBindReference,
|
9
9
|
} from '@balena/odata-to-abstract-sql';
|
10
10
|
import deepFreeze = require('deep-freeze');
|
11
|
-
import
|
11
|
+
import memoize from 'memoizee';
|
12
12
|
import * as env from '../config-loader/env';
|
13
13
|
import { BadRequestError, SqlCompilationError } from './errors';
|
14
14
|
import * as sbvrUtils from './sbvr-utils';
|
15
|
-
import { ODataRequest } from './uri-parser';
|
15
|
+
import type { ODataRequest } from './uri-parser';
|
16
16
|
|
17
17
|
const getMemoizedCompileRule = memoize(
|
18
18
|
(engine: AbstractSQLCompiler.Engines) =>
|
@@ -116,7 +116,7 @@ export const getAndCheckBindValues = async (
|
|
116
116
|
[dataType, value] = odataBinds[bindValue];
|
117
117
|
field = { dataType };
|
118
118
|
} else if (typeof bindValue === 'string') {
|
119
|
-
if (!
|
119
|
+
if (!Object.prototype.hasOwnProperty.call(odataBinds, bindValue)) {
|
120
120
|
console.error(
|
121
121
|
`Invalid binding '${bindValue}' for binds: `,
|
122
122
|
odataBinds,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import type * as Fs from 'fs';
|
2
2
|
|
3
|
-
import
|
3
|
+
import _ from 'lodash';
|
4
4
|
|
5
5
|
const cacheFile = process.env.PINEJS_CACHE_FILE || '.pinejs-cache.json';
|
6
6
|
let cache: null | {
|
@@ -12,7 +12,6 @@ let cache: null | {
|
|
12
12
|
} = null;
|
13
13
|
let fs: undefined | typeof Fs;
|
14
14
|
try {
|
15
|
-
// tslint:disable-next-line:no-var-requires
|
16
15
|
fs = require('fs');
|
17
16
|
} catch (e) {
|
18
17
|
// Ignore error
|
@@ -1,13 +1,17 @@
|
|
1
1
|
// Augment express.js with pinejs-specific attributes via declaration merging.
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
declare global {
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
5
|
+
namespace Express {
|
6
|
+
type PineUser = import('./sbvr-utils').User;
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
// Augment Express.User to include the props of our PineUser.
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
10
|
+
interface User extends PineUser {}
|
11
|
+
|
12
|
+
interface Request {
|
13
|
+
user?: User;
|
14
|
+
apiKey?: import('./sbvr-utils').ApiKey;
|
15
|
+
}
|
12
16
|
}
|
13
17
|
}
|
package/src/sbvr-api/hooks.ts
CHANGED
@@ -5,17 +5,17 @@ import type { AnyObject } from 'pinejs-client-core';
|
|
5
5
|
import type { TypedError } from 'typed-error';
|
6
6
|
import type { SupportedMethod } from '@balena/odata-to-abstract-sql';
|
7
7
|
|
8
|
-
import
|
8
|
+
import _ from 'lodash';
|
9
9
|
import { settleMapSeries } from './control-flow';
|
10
|
-
import
|
10
|
+
import memoize from 'memoizee';
|
11
11
|
import {
|
12
|
-
PinejsClient,
|
13
|
-
User,
|
14
|
-
ApiKey,
|
12
|
+
type PinejsClient,
|
13
|
+
type User,
|
14
|
+
type ApiKey,
|
15
15
|
resolveSynonym,
|
16
16
|
getAbstractSqlModel,
|
17
17
|
api,
|
18
|
-
Response,
|
18
|
+
type Response,
|
19
19
|
} from './sbvr-utils';
|
20
20
|
|
21
21
|
export interface HookReq {
|
@@ -29,6 +29,7 @@ export interface HookReq {
|
|
29
29
|
custom?: AnyObject;
|
30
30
|
tx?: Tx;
|
31
31
|
hooks?: InstantiatedHooks;
|
32
|
+
is?: (type: string | string[]) => string | false | null;
|
32
33
|
}
|
33
34
|
export interface HookArgs {
|
34
35
|
req: HookReq;
|
@@ -55,7 +56,7 @@ export interface Hooks {
|
|
55
56
|
) => HookResponse;
|
56
57
|
/** These are run in reverse translation order from newest to oldest */
|
57
58
|
'POSTRUN-ERROR'?: (
|
58
|
-
options: HookArgs & { error: TypedError | any },
|
59
|
+
options: HookArgs & { tx: Tx; error: TypedError | any },
|
59
60
|
) => HookResponse;
|
60
61
|
}
|
61
62
|
export type HookBlueprints = {
|
@@ -101,7 +102,7 @@ class SideEffectHook<T extends HookFn> extends Hook<T> {
|
|
101
102
|
|
102
103
|
public registerRollback(fn: RollbackAction): void {
|
103
104
|
if (this.rolledBack) {
|
104
|
-
(async () => {
|
105
|
+
void (async () => {
|
105
106
|
try {
|
106
107
|
await fn();
|
107
108
|
} catch {
|
@@ -140,7 +141,7 @@ export const rollbackRequestHooks = <T extends InstantiatedHooks>(
|
|
140
141
|
if (sideEffectHooks.length === 0) {
|
141
142
|
return;
|
142
143
|
}
|
143
|
-
settleMapSeries(sideEffectHooks, async (hook) => {
|
144
|
+
void settleMapSeries(sideEffectHooks, async (hook) => {
|
144
145
|
await hook.rollback();
|
145
146
|
});
|
146
147
|
};
|
@@ -391,8 +392,7 @@ const getReadOnlyArgs = <T extends keyof Hooks>(
|
|
391
392
|
// If we don't have a tx then read-only/writable is irrelevant
|
392
393
|
return args;
|
393
394
|
}
|
394
|
-
|
395
|
-
readOnlyArgs = { ...args, tx: args.tx.asReadOnly() };
|
395
|
+
const readOnlyArgs: typeof args = { ...args, tx: args.tx.asReadOnly() };
|
396
396
|
if ((args as HookArgs).request != null) {
|
397
397
|
defineApi(modelName, readOnlyArgs as HookArgs);
|
398
398
|
}
|
@@ -1,24 +1,30 @@
|
|
1
|
+
import type {
|
2
|
+
AbstractSqlModel,
|
3
|
+
AbstractSqlTable,
|
4
|
+
} from '@balena/abstract-sql-compiler';
|
5
|
+
|
6
|
+
// Augment express.js with pinejs-specific attributes via declaration merging.
|
1
7
|
declare module '@balena/abstract-sql-compiler' {
|
2
|
-
interface AbstractSqlTable {
|
8
|
+
export interface AbstractSqlTable {
|
3
9
|
fetchProcessingFields?: {
|
4
10
|
[field: string]: NonNullable<SbvrType['fetchProcessing']>;
|
5
11
|
};
|
6
12
|
localFields?: {
|
7
13
|
[odataName: string]: true;
|
8
14
|
};
|
15
|
+
webresourceFields?: {
|
16
|
+
[odataName: string]: true;
|
17
|
+
};
|
9
18
|
}
|
10
19
|
}
|
11
20
|
|
12
|
-
import type {
|
13
|
-
AbstractSqlModel,
|
14
|
-
AbstractSqlTable,
|
15
|
-
} from '@balena/abstract-sql-compiler';
|
16
21
|
import type { Result, Row } from '../database-layer/db';
|
17
22
|
|
18
23
|
import { sqlNameToODataName } from '@balena/odata-to-abstract-sql';
|
19
|
-
import sbvrTypes, { SbvrType } from '@balena/sbvr-types';
|
20
|
-
import
|
24
|
+
import sbvrTypes, { type SbvrType } from '@balena/sbvr-types';
|
25
|
+
import _ from 'lodash';
|
21
26
|
import { resolveNavigationResource, resolveSynonym } from './sbvr-utils';
|
27
|
+
import { getWebresourceHandler } from '../webresource-handler';
|
22
28
|
|
23
29
|
const checkForExpansion = async (
|
24
30
|
vocab: string,
|
@@ -96,6 +102,20 @@ const getLocalFields = (table: AbstractSqlTable) => {
|
|
96
102
|
}
|
97
103
|
return table.localFields;
|
98
104
|
};
|
105
|
+
|
106
|
+
const getWebResourceFields = (table: AbstractSqlTable) => {
|
107
|
+
if (table.webresourceFields == null) {
|
108
|
+
table.webresourceFields = {};
|
109
|
+
for (const { fieldName, dataType } of table.fields) {
|
110
|
+
if (dataType === 'WebResource') {
|
111
|
+
const odataName = sqlNameToODataName(fieldName);
|
112
|
+
table.webresourceFields[odataName] = true;
|
113
|
+
}
|
114
|
+
}
|
115
|
+
}
|
116
|
+
return table.webresourceFields;
|
117
|
+
};
|
118
|
+
|
99
119
|
const getFetchProcessingFields = (table: AbstractSqlTable) => {
|
100
120
|
return (table.fetchProcessingFields ??= _(table.fields)
|
101
121
|
.filter(
|
@@ -138,20 +158,27 @@ export const process = async (
|
|
138
158
|
vocabulary: vocab,
|
139
159
|
resourceName,
|
140
160
|
});
|
161
|
+
const configuredWebResourceHandler = getWebresourceHandler();
|
141
162
|
const table = abstractSqlModel.tables[sqlResourceName];
|
142
163
|
|
143
164
|
const fieldNames = Object.keys(rows[0]);
|
144
165
|
|
145
166
|
const fetchProcessingFields = getFetchProcessingFields(table);
|
146
167
|
const processedFields = fieldNames.filter((fieldName) =>
|
147
|
-
|
168
|
+
Object.prototype.hasOwnProperty.call(fetchProcessingFields, fieldName),
|
148
169
|
);
|
149
170
|
|
150
171
|
const localFields = getLocalFields(table);
|
151
172
|
// We check that it's not a local field, rather than that it is a foreign key because of the case where the foreign key is on the other resource
|
152
173
|
// and hence not known to this resource
|
153
174
|
const expandableFields = fieldNames.filter(
|
154
|
-
(fieldName) =>
|
175
|
+
(fieldName) =>
|
176
|
+
!Object.prototype.hasOwnProperty.call(localFields, fieldName),
|
177
|
+
);
|
178
|
+
|
179
|
+
const webresourceFields = getWebResourceFields(table);
|
180
|
+
const requiredSigningFields = fieldNames.filter((fieldName) =>
|
181
|
+
Object.prototype.hasOwnProperty.call(webresourceFields, fieldName),
|
155
182
|
);
|
156
183
|
|
157
184
|
const odataIdField = sqlNameToODataName(table.idField);
|
@@ -166,6 +193,25 @@ export const process = async (
|
|
166
193
|
}
|
167
194
|
}
|
168
195
|
|
196
|
+
if (
|
197
|
+
requiredSigningFields.length > 0 &&
|
198
|
+
configuredWebResourceHandler != null
|
199
|
+
) {
|
200
|
+
await Promise.all(
|
201
|
+
rows.map(async (row) => {
|
202
|
+
await Promise.all(
|
203
|
+
requiredSigningFields.map(async (fieldName) => {
|
204
|
+
if (row[fieldName] != null) {
|
205
|
+
row[fieldName] = await configuredWebResourceHandler.onPreRespond(
|
206
|
+
row[fieldName],
|
207
|
+
);
|
208
|
+
}
|
209
|
+
}),
|
210
|
+
);
|
211
|
+
}),
|
212
|
+
);
|
213
|
+
}
|
214
|
+
|
169
215
|
if (expandableFields.length > 0) {
|
170
216
|
await Promise.all(
|
171
217
|
rows.map(async (row) => {
|
@@ -192,5 +238,6 @@ export const prepareModel = (abstractSqlModel: AbstractSqlModel) => {
|
|
192
238
|
_.forEach(abstractSqlModel.tables, (table) => {
|
193
239
|
getLocalFields(table);
|
194
240
|
getFetchProcessingFields(table);
|
241
|
+
getWebResourceFields(table);
|
195
242
|
});
|
196
243
|
};
|
@@ -28,17 +28,17 @@ import {
|
|
28
28
|
isBindReference,
|
29
29
|
type OData2AbstractSQL,
|
30
30
|
odataNameToSqlName,
|
31
|
-
ResourceFunction,
|
31
|
+
type ResourceFunction,
|
32
32
|
sqlNameToODataName,
|
33
33
|
} from '@balena/odata-to-abstract-sql';
|
34
34
|
import * as ODataParser from '@balena/odata-parser';
|
35
35
|
|
36
|
-
import
|
37
|
-
import
|
36
|
+
import _ from 'lodash';
|
37
|
+
import memoize from 'memoizee';
|
38
38
|
import * as randomstring from 'randomstring';
|
39
39
|
import * as env from '../config-loader/env';
|
40
40
|
import * as sbvrUtils from '../sbvr-api/sbvr-utils';
|
41
|
-
import { HookReq, addPureHook, addHook } from './hooks';
|
41
|
+
import { type HookReq, addPureHook, addHook } from './hooks';
|
42
42
|
import {
|
43
43
|
BadRequestError,
|
44
44
|
PermissionError,
|
@@ -48,11 +48,11 @@ import {
|
|
48
48
|
memoizedGetOData2AbstractSQL,
|
49
49
|
memoizedParseOdata,
|
50
50
|
metadataEndpoints,
|
51
|
-
ODataRequest,
|
51
|
+
type ODataRequest,
|
52
52
|
} from './uri-parser';
|
53
53
|
import memoizeWeak = require('memoizee/weak');
|
54
54
|
|
55
|
-
//
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
56
56
|
const userModel: string = require('./user.sbvr');
|
57
57
|
|
58
58
|
const DEFAULT_ACTOR_BIND = '@__ACTOR_ID';
|
@@ -87,7 +87,7 @@ interface NestedCheckOr<T> {
|
|
87
87
|
interface NestedCheckAnd<T> {
|
88
88
|
and: NestedCheckArray<T>;
|
89
89
|
}
|
90
|
-
|
90
|
+
type NestedCheckArray<T> = Array<NestedCheck<T>>;
|
91
91
|
type NestedCheck<T> =
|
92
92
|
| NestedCheckOr<T>
|
93
93
|
| NestedCheckAnd<T>
|
@@ -95,20 +95,18 @@ type NestedCheck<T> =
|
|
95
95
|
| T;
|
96
96
|
type PermissionCheck = NestedCheck<string>;
|
97
97
|
|
98
|
-
type MappedType<I, O> =
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
I
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
? NestedCheckArray<MappedType<I, O>>
|
111
|
-
: Exclude<I, string> | O;
|
98
|
+
type MappedType<I, O> =
|
99
|
+
O extends NestedCheck<infer T>
|
100
|
+
? Exclude<Exclude<I, string> | T, boolean>
|
101
|
+
: Exclude<Exclude<I, string> | O, boolean>;
|
102
|
+
type MappedNestedCheck<T extends NestedCheck<I>, I, O> =
|
103
|
+
T extends NestedCheckOr<I>
|
104
|
+
? NestedCheckOr<MappedType<I, O>>
|
105
|
+
: T extends NestedCheckAnd<I>
|
106
|
+
? NestedCheckAnd<MappedType<I, O>>
|
107
|
+
: T extends NestedCheckArray<I>
|
108
|
+
? NestedCheckArray<MappedType<I, O>>
|
109
|
+
: Exclude<I, string> | O;
|
112
110
|
|
113
111
|
const methodPermissions: {
|
114
112
|
[method in Exclude<SupportedMethod, 'OPTIONS'>]: PermissionCheck;
|
@@ -175,22 +173,26 @@ const isAnd = <T>(x: any): x is NestedCheckAnd<T> =>
|
|
175
173
|
typeof x === 'object' && 'and' in x;
|
176
174
|
const isOr = <T>(x: any): x is NestedCheckOr<T> =>
|
177
175
|
typeof x === 'object' && 'or' in x;
|
178
|
-
export function nestedCheck<I extends
|
179
|
-
check:
|
176
|
+
export function nestedCheck<I extends string, O>(
|
177
|
+
check: I,
|
180
178
|
stringCallback: (s: string) => O,
|
181
179
|
): O;
|
182
|
-
export function nestedCheck<I extends
|
183
|
-
check:
|
180
|
+
export function nestedCheck<I extends boolean, O>(
|
181
|
+
check: I,
|
184
182
|
stringCallback: (s: string) => O,
|
185
183
|
): boolean;
|
186
|
-
export function nestedCheck<I extends
|
184
|
+
export function nestedCheck<I extends NonNullable<unknown>, O>(
|
187
185
|
check: NestedCheck<I>,
|
188
186
|
stringCallback: (s: string) => O,
|
189
187
|
): Exclude<I, string> | O | MappedNestedCheck<typeof check, I, O>;
|
190
|
-
export function nestedCheck<I extends
|
191
|
-
check: NestedCheck<I
|
188
|
+
export function nestedCheck<I extends object, O>(
|
189
|
+
check: NestedCheck<I> | string | boolean,
|
192
190
|
stringCallback: (s: string) => O,
|
193
|
-
):
|
191
|
+
):
|
192
|
+
| boolean
|
193
|
+
| Exclude<I, string>
|
194
|
+
| O
|
195
|
+
| MappedNestedCheck<Exclude<typeof check, string | boolean>, I, O> {
|
194
196
|
if (typeof check === 'string') {
|
195
197
|
return stringCallback(check);
|
196
198
|
}
|
@@ -228,10 +230,11 @@ export function nestedCheck<I extends {}, O>(
|
|
228
230
|
}
|
229
231
|
const checkType = checkTypes[0];
|
230
232
|
switch (checkType.toUpperCase()) {
|
231
|
-
case 'AND':
|
233
|
+
case 'AND': {
|
232
234
|
const and = (check as NestedCheckAnd<I>)[checkType as 'and'];
|
233
235
|
return nestedCheck(and, stringCallback);
|
234
|
-
|
236
|
+
}
|
237
|
+
case 'OR': {
|
235
238
|
const or = (check as NestedCheckOr<I>)[checkType as 'or'];
|
236
239
|
let results: any[] = [];
|
237
240
|
for (const subcheck of or) {
|
@@ -255,6 +258,7 @@ export function nestedCheck<I extends {}, O>(
|
|
255
258
|
};
|
256
259
|
}
|
257
260
|
return false;
|
261
|
+
}
|
258
262
|
default:
|
259
263
|
throw new Error('Cannot parse required checking logic: ' + checkType);
|
260
264
|
}
|
@@ -425,7 +429,7 @@ const convertToLambda = (filter: AnyObject, identifier: string) => {
|
|
425
429
|
}
|
426
430
|
}
|
427
431
|
|
428
|
-
if (
|
432
|
+
if (Object.prototype.hasOwnProperty.call(object, 'name')) {
|
429
433
|
object.property = { ...object };
|
430
434
|
object.name = identifier;
|
431
435
|
delete object.lambda;
|
@@ -721,7 +725,7 @@ const deepFreezeExceptDefinition = (obj: AnyObject) => {
|
|
721
725
|
// We skip the definition because we know it's a property we've defined that will throw an error in some cases
|
722
726
|
if (
|
723
727
|
prop !== 'definition' &&
|
724
|
-
|
728
|
+
Object.prototype.hasOwnProperty.call(obj, prop) &&
|
725
729
|
obj[prop] !== null &&
|
726
730
|
!['object', 'function'].includes(typeof obj[prop])
|
727
731
|
) {
|
@@ -1030,9 +1034,14 @@ const getBoundConstrainedMemoizer = memoizeWeak(
|
|
1030
1034
|
if (!permissionsJSON) {
|
1031
1035
|
return;
|
1032
1036
|
}
|
1033
|
-
const permissions = JSON.parse(permissionsJSON);
|
1034
1037
|
|
1035
1038
|
const table = tables[`${resourceName}$bypass`];
|
1039
|
+
if (table == null) {
|
1040
|
+
// If the table we're based upon doesn't exist then this table also shouldn't exist
|
1041
|
+
return;
|
1042
|
+
}
|
1043
|
+
|
1044
|
+
const permissions = JSON.parse(permissionsJSON);
|
1036
1045
|
|
1037
1046
|
const permissionsTable = (tables[permissionResourceName] = {
|
1038
1047
|
...table,
|
@@ -1508,7 +1517,7 @@ export const resolveApiKey = async (
|
|
1508
1517
|
tx?: Tx,
|
1509
1518
|
): Promise<PermissionReq['apiKey']> => {
|
1510
1519
|
const apiKey =
|
1511
|
-
req.params
|
1520
|
+
req.params[paramName] ?? req.body[paramName] ?? req.query[paramName];
|
1512
1521
|
if (apiKey == null) {
|
1513
1522
|
return;
|
1514
1523
|
}
|