@flowerforce/flowerbase 1.9.1-beta.0 → 1.10.1-beta.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/CHANGELOG.md +7 -0
- package/dist/utils/context/helpers.d.ts +10 -2
- package/dist/utils/context/helpers.d.ts.map +1 -1
- package/dist/utils/context/helpers.js +12 -2
- package/dist/utils/context/index.d.ts.map +1 -1
- package/dist/utils/context/index.js +4 -2
- package/package.json +1 -1
- package/src/utils/__tests__/contextExecuteCompatibility.test.ts +0 -21
- package/src/utils/__tests__/generateContextData.test.ts +47 -4
- package/src/utils/context/helpers.ts +16 -2
- package/src/utils/context/index.ts +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { mongodb } from '@fastify/mongodb';
|
|
2
|
-
import { Arguments } from '../../auth/dtos';
|
|
2
|
+
import { Arguments, User } from '../../auth/dtos';
|
|
3
3
|
import { GenerateContextDataParams } from './interface';
|
|
4
|
+
/** Realm-compatible system user for run_as_system execution with no authenticated caller. */
|
|
5
|
+
export declare const REALM_SYSTEM_USER: {
|
|
6
|
+
readonly type: "system";
|
|
7
|
+
readonly data: {};
|
|
8
|
+
readonly custom_data: {};
|
|
9
|
+
readonly identities: readonly [];
|
|
10
|
+
};
|
|
11
|
+
export declare const contextUserForRun: (user: User, runAsSystem: boolean) => User;
|
|
4
12
|
type JwtUtils = {
|
|
5
13
|
encode: (signingMethod: string, payload: unknown, secret: string | Buffer, customHeaderFields?: Record<string, unknown>) => string;
|
|
6
14
|
decode: (jwtString: string, key: string | Buffer, returnHeader?: boolean, acceptedSigningMethods?: string[]) => unknown;
|
|
@@ -24,7 +32,6 @@ export declare const generateContextData: ({ user, services, app, rules, current
|
|
|
24
32
|
deserialize: (ejson: mongodb.BSON.Document, options?: mongodb.BSON.EJSONOptions) => any;
|
|
25
33
|
};
|
|
26
34
|
Buffer: BufferConstructor;
|
|
27
|
-
fetch: typeof fetch;
|
|
28
35
|
utils: {
|
|
29
36
|
jwt: JwtUtils;
|
|
30
37
|
};
|
|
@@ -47,6 +54,7 @@ export declare const generateContextData: ({ user, services, app, rules, current
|
|
|
47
54
|
action: string;
|
|
48
55
|
};
|
|
49
56
|
user: unknown;
|
|
57
|
+
runningAsSystem: () => boolean;
|
|
50
58
|
environment: {
|
|
51
59
|
tag: string | undefined;
|
|
52
60
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/context/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAG1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/utils/context/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAG1C,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAEvD,6FAA6F;AAC7F,eAAO,MAAM,iBAAiB;;;;;CAKpB,CAAA;AAKV,eAAO,MAAM,iBAAiB,GAAI,MAAM,IAAI,EAAE,aAAa,OAAO,KAAG,IACR,CAAA;AAE7D,KAAK,QAAQ,GAAG;IACd,MAAM,EAAE,CACN,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KACzC,MAAM,CAAA;IACX,MAAM,EAAE,CACN,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,YAAY,CAAC,EAAE,OAAO,EACtB,sBAAsB,CAAC,EAAE,MAAM,EAAE,KAC9B,OAAO,CAAA;CACb,CAAA;AAgFD;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAAI,4GAUjC,yBAAyB;;;;;;;;;;;;;uBA4DP,SAAS;yBAGP,SAAS;;;;;;;;;;;0BAoBmB,MAAM,GAAG,SAAS;2BACV,MAAM,GAAG,SAAS;;;;;;;;;;uBAU1D,MAAM;;;;;;+BA7DU,MAAM,OAAO,QAAQ;;;;sCAjJtD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BAkHM,CAAC;iCAAa,CAAC;;;;;;;;;;;;;;;;;;;kCAlHtB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAkHM,CAAC;6BAAa,CAAC;;;;;;;;;;;;;;;;;;kCAlHtB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAkHM,CAAC;6BAAa,CAAC;;;;;;;;;;;;;;;4BAqGA,MAAM,OAAO,aAAa,WAAW,SAAS;;;CAkBrE,CAAA"}
|
|
@@ -33,10 +33,20 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.generateContextData = void 0;
|
|
36
|
+
exports.generateContextData = exports.contextUserForRun = exports.REALM_SYSTEM_USER = void 0;
|
|
37
37
|
const mongodb_1 = require("@fastify/mongodb");
|
|
38
38
|
const bson_1 = require("bson");
|
|
39
39
|
const jwt = __importStar(require("jsonwebtoken"));
|
|
40
|
+
/** Realm-compatible system user for run_as_system execution with no authenticated caller. */
|
|
41
|
+
exports.REALM_SYSTEM_USER = {
|
|
42
|
+
type: 'system',
|
|
43
|
+
data: {},
|
|
44
|
+
custom_data: {},
|
|
45
|
+
identities: []
|
|
46
|
+
};
|
|
47
|
+
const isEmptyUser = (user) => user != null && typeof user === 'object' && !Array.isArray(user) && Object.keys(user).length === 0;
|
|
48
|
+
const contextUserForRun = (user, runAsSystem) => runAsSystem && isEmptyUser(user) ? exports.REALM_SYSTEM_USER : user;
|
|
49
|
+
exports.contextUserForRun = contextUserForRun;
|
|
40
50
|
const normalizePayload = (payload) => {
|
|
41
51
|
if (typeof payload !== 'string')
|
|
42
52
|
return payload;
|
|
@@ -150,7 +160,6 @@ const generateContextData = ({ user, services, app, rules, currentFunction, func
|
|
|
150
160
|
BSON,
|
|
151
161
|
EJSON: bson_1.EJSON,
|
|
152
162
|
Buffer,
|
|
153
|
-
fetch,
|
|
154
163
|
utils,
|
|
155
164
|
console: {
|
|
156
165
|
log: (...args) => {
|
|
@@ -180,6 +189,7 @@ const generateContextData = ({ user, services, app, rules, currentFunction, func
|
|
|
180
189
|
action: ''
|
|
181
190
|
},
|
|
182
191
|
user,
|
|
192
|
+
runningAsSystem: () => Boolean(currentFunction.run_as_system),
|
|
183
193
|
environment: {
|
|
184
194
|
tag: process.env.NODE_ENV
|
|
185
195
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/context/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AA8RnD;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,EACpC,IAAI,EACJ,GAAG,EACH,KAAK,EACL,IAAI,EACJ,eAAe,EACf,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,eAAsB,EACtB,OAAO,EACP,OAAO,EACR,EAAE,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/context/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AA8RnD;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,EACpC,IAAI,EACJ,GAAG,EACH,KAAK,EACL,IAAI,EACJ,eAAe,EACf,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,eAAsB,EACtB,OAAO,EACP,OAAO,EACR,EAAE,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,CA4G1C;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,GAAG,EACH,KAAK,EACL,IAAI,EACJ,eAAe,EACf,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,eAAsB,EACtB,OAAO,EACR,EAAE,qBAAqB,GAAG,OAAO,CA2BjC"}
|
|
@@ -238,10 +238,11 @@ function GenerateContext(_a) {
|
|
|
238
238
|
const functionsQueue = state_1.StateManager.select("functionsQueue");
|
|
239
239
|
const effectiveRunAsSystem = Boolean(runAsSystem || currentFunction.run_as_system);
|
|
240
240
|
const functionToRun = Object.assign(Object.assign({}, currentFunction), { run_as_system: effectiveRunAsSystem });
|
|
241
|
+
const contextUser = (0, helpers_1.contextUserForRun)(user, effectiveRunAsSystem);
|
|
241
242
|
const run = () => __awaiter(this, void 0, void 0, function* () {
|
|
242
243
|
var _a;
|
|
243
244
|
const contextData = (0, helpers_1.generateContextData)({
|
|
244
|
-
user,
|
|
245
|
+
user: contextUser,
|
|
245
246
|
services,
|
|
246
247
|
app,
|
|
247
248
|
rules,
|
|
@@ -315,8 +316,9 @@ function GenerateContextSync({ args, app, rules, user, currentFunction, function
|
|
|
315
316
|
return;
|
|
316
317
|
const effectiveRunAsSystem = Boolean(runAsSystem || currentFunction.run_as_system);
|
|
317
318
|
const functionToRun = Object.assign(Object.assign({}, currentFunction), { run_as_system: effectiveRunAsSystem });
|
|
319
|
+
const contextUser = (0, helpers_1.contextUserForRun)(user, effectiveRunAsSystem);
|
|
318
320
|
const contextData = (0, helpers_1.generateContextData)({
|
|
319
|
-
user,
|
|
321
|
+
user: contextUser,
|
|
320
322
|
services,
|
|
321
323
|
app,
|
|
322
324
|
rules,
|
package/package.json
CHANGED
|
@@ -157,25 +157,4 @@ describe('context.functions.execute compatibility', () => {
|
|
|
157
157
|
expect(result).toEqual({ address: 'rome', total: 10 })
|
|
158
158
|
fs.rmSync(tempDir, { recursive: true, force: true })
|
|
159
159
|
})
|
|
160
|
-
|
|
161
|
-
it('exposes native fetch in the sandbox global scope', () => {
|
|
162
|
-
const functionsList = {
|
|
163
|
-
caller: {
|
|
164
|
-
code: 'module.exports = function() { return fetch === globalThis.fetch && typeof fetch === "function" }'
|
|
165
|
-
}
|
|
166
|
-
} as Functions
|
|
167
|
-
|
|
168
|
-
const result = GenerateContextSync({
|
|
169
|
-
args: [],
|
|
170
|
-
app: {} as any,
|
|
171
|
-
rules: {} as any,
|
|
172
|
-
user: {} as any,
|
|
173
|
-
currentFunction: functionsList.caller,
|
|
174
|
-
functionsList,
|
|
175
|
-
services: mockServices,
|
|
176
|
-
functionName: 'caller'
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
expect(result).toBe(true)
|
|
180
|
-
})
|
|
181
160
|
})
|
|
@@ -4,7 +4,7 @@ import { User } from '../../auth/dtos'
|
|
|
4
4
|
import { Functions } from '../../features/functions/interface'
|
|
5
5
|
import { Rules } from '../../features/rules/interface'
|
|
6
6
|
import { services } from '../../services'
|
|
7
|
-
import { generateContextData } from '../context/helpers'
|
|
7
|
+
import { contextUserForRun, generateContextData, REALM_SYSTEM_USER } from '../context/helpers'
|
|
8
8
|
|
|
9
9
|
const originalEnv = process.env
|
|
10
10
|
|
|
@@ -47,7 +47,7 @@ describe('generateContextData', () => {
|
|
|
47
47
|
|
|
48
48
|
it('should return an object with context configuration', async () => {
|
|
49
49
|
const mockApp = Fastify()
|
|
50
|
-
const { context, console: contextConsole, BSON
|
|
50
|
+
const { context, console: contextConsole, BSON } = generateContextData({
|
|
51
51
|
services,
|
|
52
52
|
app: mockApp,
|
|
53
53
|
functionsList: mockFunctions,
|
|
@@ -66,8 +66,6 @@ describe('generateContextData', () => {
|
|
|
66
66
|
|
|
67
67
|
expect(context.user).toEqual(mockUser)
|
|
68
68
|
|
|
69
|
-
expect(fetch).toBe(global.fetch)
|
|
70
|
-
|
|
71
69
|
const mockedLog = jest.spyOn(console, 'log').mockImplementation(() => { })
|
|
72
70
|
contextConsole.log('Test', 'generateContextData')
|
|
73
71
|
expect(mockedLog).toHaveBeenCalledWith('Test', 'generateContextData')
|
|
@@ -115,4 +113,49 @@ describe('generateContextData', () => {
|
|
|
115
113
|
const binaryObject = Binary.fromBase64Binary(base64, 0)
|
|
116
114
|
expect(binaryObject).toBeInstanceOf(BSON.Binary)
|
|
117
115
|
})
|
|
116
|
+
|
|
117
|
+
it('exposes Realm system user and runningAsSystem when run_as_system is enabled', () => {
|
|
118
|
+
const mockApp = Fastify()
|
|
119
|
+
const systemFunction = { ...currentFunction, run_as_system: true }
|
|
120
|
+
const { context } = generateContextData({
|
|
121
|
+
services,
|
|
122
|
+
app: mockApp,
|
|
123
|
+
functionsList: mockFunctions,
|
|
124
|
+
currentFunction: systemFunction,
|
|
125
|
+
GenerateContext: GenerateContextMock,
|
|
126
|
+
GenerateContextSync: GenerateContextSyncMock,
|
|
127
|
+
user: REALM_SYSTEM_USER,
|
|
128
|
+
rules: mockRules
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
expect(context.user).toEqual(REALM_SYSTEM_USER)
|
|
132
|
+
expect(context.runningAsSystem()).toBe(true)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('runningAsSystem is false for regular function execution', () => {
|
|
136
|
+
const mockApp = Fastify()
|
|
137
|
+
const { context } = generateContextData({
|
|
138
|
+
services,
|
|
139
|
+
app: mockApp,
|
|
140
|
+
functionsList: mockFunctions,
|
|
141
|
+
currentFunction,
|
|
142
|
+
GenerateContext: GenerateContextMock,
|
|
143
|
+
GenerateContextSync: GenerateContextSyncMock,
|
|
144
|
+
user: { id: 'user-1', type: 'normal', data: {}, custom_data: {}, identities: [] },
|
|
145
|
+
rules: mockRules
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
expect(context.runningAsSystem()).toBe(false)
|
|
149
|
+
})
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
describe('contextUserForRun', () => {
|
|
153
|
+
it('returns Realm system user for empty user with run_as_system', () => {
|
|
154
|
+
expect(contextUserForRun({}, true)).toEqual(REALM_SYSTEM_USER)
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('returns the user unchanged when not running as system', () => {
|
|
158
|
+
const user = { id: 'user-1' }
|
|
159
|
+
expect(contextUserForRun(user, false)).toBe(user)
|
|
160
|
+
})
|
|
118
161
|
})
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import { mongodb } from '@fastify/mongodb'
|
|
2
2
|
import { EJSON } from 'bson'
|
|
3
3
|
import * as jwt from 'jsonwebtoken'
|
|
4
|
-
import { Arguments } from '../../auth/dtos'
|
|
4
|
+
import { Arguments, User } from '../../auth/dtos'
|
|
5
5
|
import { Function } from '../../features/functions/interface'
|
|
6
6
|
import { GenerateContextDataParams } from './interface'
|
|
7
7
|
|
|
8
|
+
/** Realm-compatible system user for run_as_system execution with no authenticated caller. */
|
|
9
|
+
export const REALM_SYSTEM_USER = {
|
|
10
|
+
type: 'system',
|
|
11
|
+
data: {},
|
|
12
|
+
custom_data: {},
|
|
13
|
+
identities: []
|
|
14
|
+
} as const
|
|
15
|
+
|
|
16
|
+
const isEmptyUser = (user: User) =>
|
|
17
|
+
user != null && typeof user === 'object' && !Array.isArray(user) && Object.keys(user).length === 0
|
|
18
|
+
|
|
19
|
+
export const contextUserForRun = (user: User, runAsSystem: boolean): User =>
|
|
20
|
+
runAsSystem && isEmptyUser(user) ? REALM_SYSTEM_USER : user
|
|
21
|
+
|
|
8
22
|
type JwtUtils = {
|
|
9
23
|
encode: (
|
|
10
24
|
signingMethod: string,
|
|
@@ -176,7 +190,6 @@ export const generateContextData = ({
|
|
|
176
190
|
BSON,
|
|
177
191
|
EJSON,
|
|
178
192
|
Buffer,
|
|
179
|
-
fetch,
|
|
180
193
|
utils,
|
|
181
194
|
console: {
|
|
182
195
|
log: (...args: Arguments) => {
|
|
@@ -208,6 +221,7 @@ export const generateContextData = ({
|
|
|
208
221
|
action: ''
|
|
209
222
|
},
|
|
210
223
|
user,
|
|
224
|
+
runningAsSystem: () => Boolean(currentFunction.run_as_system),
|
|
211
225
|
environment: {
|
|
212
226
|
tag: process.env.NODE_ENV
|
|
213
227
|
},
|
|
@@ -6,7 +6,7 @@ import vm from 'vm'
|
|
|
6
6
|
import { EJSON } from 'bson'
|
|
7
7
|
import { StateManager } from '../../state'
|
|
8
8
|
import { Function as AppFunction } from '../../features/functions/interface'
|
|
9
|
-
import { generateContextData } from './helpers'
|
|
9
|
+
import { contextUserForRun, generateContextData } from './helpers'
|
|
10
10
|
import { GenerateContextParams } from './interface'
|
|
11
11
|
|
|
12
12
|
const dynamicImport = new Function('specifier', 'return import(specifier)') as (
|
|
@@ -323,11 +323,12 @@ export async function GenerateContext({
|
|
|
323
323
|
const functionsQueue = StateManager.select("functionsQueue")
|
|
324
324
|
const effectiveRunAsSystem = Boolean(runAsSystem || currentFunction.run_as_system)
|
|
325
325
|
const functionToRun = { ...currentFunction, run_as_system: effectiveRunAsSystem }
|
|
326
|
+
const contextUser = contextUserForRun(user, effectiveRunAsSystem)
|
|
326
327
|
|
|
327
328
|
const run = async () => {
|
|
328
329
|
|
|
329
330
|
const contextData = generateContextData({
|
|
330
|
-
user,
|
|
331
|
+
user: contextUser,
|
|
331
332
|
services,
|
|
332
333
|
app,
|
|
333
334
|
rules,
|
|
@@ -443,8 +444,9 @@ export function GenerateContextSync({
|
|
|
443
444
|
|
|
444
445
|
const effectiveRunAsSystem = Boolean(runAsSystem || currentFunction.run_as_system)
|
|
445
446
|
const functionToRun = { ...currentFunction, run_as_system: effectiveRunAsSystem }
|
|
447
|
+
const contextUser = contextUserForRun(user, effectiveRunAsSystem)
|
|
446
448
|
const contextData = generateContextData({
|
|
447
|
-
user,
|
|
449
|
+
user: contextUser,
|
|
448
450
|
services,
|
|
449
451
|
app,
|
|
450
452
|
rules,
|