Skip to content

Commit

Permalink
fix(backend-native): Pass req.securityContext to Python config (#9049)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mcheshkov authored Dec 18, 2024
1 parent 171ea35 commit 95021f2
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
6 changes: 6 additions & 0 deletions packages/cubejs-backend-native/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ export interface PyConfiguration {
repositoryFactory?: (ctx: unknown) => Promise<unknown>,
logger?: (msg: string, params: Record<string, any>) => void,
checkAuth?: (req: unknown, authorization: string) => Promise<{ 'security_context'?: unknown }>
extendContext?: (req: unknown) => Promise<unknown>
queryRewrite?: (query: unknown, ctx: unknown) => Promise<unknown>
contextToApiScopes?: () => Promise<string[]>
contextToRoles?: (ctx: unknown) => Promise<string[]>
Expand All @@ -365,6 +366,11 @@ function simplifyExpressRequest(req: ExpressRequest) {
method: req.method,
headers: req.headers,
ip: req.ip,

// req.securityContext is an extension of request done by api-gateway
// But its typings currently live in api-gateway package, which has native-backend (this package) as it's dependency
// TODO extract typings to separate package and drop as any
...(Object.hasOwn(req, 'securityContext') ? { securityContext: (req as any).securityContext } : {}),
};
}

Expand Down
17 changes: 17 additions & 0 deletions packages/cubejs-backend-native/test/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,23 @@ async def check_auth(req, authorization):
}


@config('extend_context')
def extend_context(req):
print("[python] extend_context req=", req)
if "securityContext" not in req:
return {
"security_context": {
"error": "missing",
}
}

req["securityContext"]["extended_by_config"] = True

return {
"security_context": req["securityContext"],
}


@config
async def repository_factory(ctx):
print("[python] repository_factory ctx=", ctx)
Expand Down
26 changes: 26 additions & 0 deletions packages/cubejs-backend-native/test/python.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ suite('Python Config', () => {
pgSqlPort: 5555,
preAggregationsSchema: expect.any(Function),
checkAuth: expect.any(Function),
extendContext: expect.any(Function),
queryRewrite: expect.any(Function),
repositoryFactory: expect.any(Function),
schemaVersion: expect.any(Function),
Expand Down Expand Up @@ -83,6 +84,31 @@ suite('Python Config', () => {
expect(await config.contextToApiScopes()).toEqual(['meta', 'data', 'jobs']);
});

test('extend_context', async () => {
if (!config.extendContext) {
throw new Error('extendContext was not defined in config.py');
}

// Without security context
expect(await config.extendContext({})).toEqual({
security_context: {
error: 'missing',
},
});

// With security context
expect(await config.extendContext({
securityContext: { sub: '1234567890', iat: 1516239022, user_id: 42 }
})).toEqual({
security_context: {
extended_by_config: true,
sub: '1234567890',
iat: 1516239022,
user_id: 42
},
});
});

test('repository factory', async () => {
if (!config.repositoryFactory) {
throw new Error('repositoryFactory was not defined in config.py');
Expand Down

0 comments on commit 95021f2

Please sign in to comment.