Skip to content

Commit 95021f2

Browse files
authored
fix(backend-native): Pass req.securityContext to Python config (#9049)
This is necessary for `extend_context`. By the time `extendContext` is called, `req` in JS-land is already extended with `securityContext` after `checkAuth`, and JS config receives it with extensions.
1 parent 171ea35 commit 95021f2

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

packages/cubejs-backend-native/js/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ export interface PyConfiguration {
352352
repositoryFactory?: (ctx: unknown) => Promise<unknown>,
353353
logger?: (msg: string, params: Record<string, any>) => void,
354354
checkAuth?: (req: unknown, authorization: string) => Promise<{ 'security_context'?: unknown }>
355+
extendContext?: (req: unknown) => Promise<unknown>
355356
queryRewrite?: (query: unknown, ctx: unknown) => Promise<unknown>
356357
contextToApiScopes?: () => Promise<string[]>
357358
contextToRoles?: (ctx: unknown) => Promise<string[]>
@@ -365,6 +366,11 @@ function simplifyExpressRequest(req: ExpressRequest) {
365366
method: req.method,
366367
headers: req.headers,
367368
ip: req.ip,
369+
370+
// req.securityContext is an extension of request done by api-gateway
371+
// But its typings currently live in api-gateway package, which has native-backend (this package) as it's dependency
372+
// TODO extract typings to separate package and drop as any
373+
...(Object.hasOwn(req, 'securityContext') ? { securityContext: (req as any).securityContext } : {}),
368374
};
369375
}
370376

packages/cubejs-backend-native/test/config.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,23 @@ async def check_auth(req, authorization):
2020
}
2121

2222

23+
@config('extend_context')
24+
def extend_context(req):
25+
print("[python] extend_context req=", req)
26+
if "securityContext" not in req:
27+
return {
28+
"security_context": {
29+
"error": "missing",
30+
}
31+
}
32+
33+
req["securityContext"]["extended_by_config"] = True
34+
35+
return {
36+
"security_context": req["securityContext"],
37+
}
38+
39+
2340
@config
2441
async def repository_factory(ctx):
2542
print("[python] repository_factory ctx=", ctx)

packages/cubejs-backend-native/test/python.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ suite('Python Config', () => {
4343
pgSqlPort: 5555,
4444
preAggregationsSchema: expect.any(Function),
4545
checkAuth: expect.any(Function),
46+
extendContext: expect.any(Function),
4647
queryRewrite: expect.any(Function),
4748
repositoryFactory: expect.any(Function),
4849
schemaVersion: expect.any(Function),
@@ -83,6 +84,31 @@ suite('Python Config', () => {
8384
expect(await config.contextToApiScopes()).toEqual(['meta', 'data', 'jobs']);
8485
});
8586

87+
test('extend_context', async () => {
88+
if (!config.extendContext) {
89+
throw new Error('extendContext was not defined in config.py');
90+
}
91+
92+
// Without security context
93+
expect(await config.extendContext({})).toEqual({
94+
security_context: {
95+
error: 'missing',
96+
},
97+
});
98+
99+
// With security context
100+
expect(await config.extendContext({
101+
securityContext: { sub: '1234567890', iat: 1516239022, user_id: 42 }
102+
})).toEqual({
103+
security_context: {
104+
extended_by_config: true,
105+
sub: '1234567890',
106+
iat: 1516239022,
107+
user_id: 42
108+
},
109+
});
110+
});
111+
86112
test('repository factory', async () => {
87113
if (!config.repositoryFactory) {
88114
throw new Error('repositoryFactory was not defined in config.py');

0 commit comments

Comments
 (0)