Skip to content

Commit

Permalink
fix(api-gateway): make sure DAP works sql pushdown
Browse files Browse the repository at this point in the history
fixes an issue when processing queries with member expressions
  • Loading branch information
bsod90 committed Dec 6, 2024
1 parent 2b4bc9e commit 75f8708
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 3 deletions.
11 changes: 8 additions & 3 deletions packages/cubejs-api-gateway/src/gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1195,7 +1195,12 @@ class ApiGateway {
currentQuery = this.parseMemberExpressionsInQuery(currentQuery);
}

const normalizedQuery = normalizeQuery(currentQuery, persistent);
let normalizedQuery = normalizeQuery(currentQuery, persistent);

if (hasExpressionsInQuery) {
normalizedQuery = this.evalMemberExpressionsInQuery(normalizedQuery);
}

// First apply cube/view level security policies
const queryWithRlsFilters = await compilerApi.applyRowLevelSecurity(
normalizedQuery,
Expand All @@ -1207,8 +1212,8 @@ class ApiGateway {
context,
);

if (hasExpressionsInQuery) {
rewrittenQuery = this.evalMemberExpressionsInQuery(rewrittenQuery);
if (this.hasExpressionsInQuery(rewrittenQuery)) {
rewrittenQuery = this.parseMemberExpressionsInQuery(rewrittenQuery);
}

return normalizeQuery(
Expand Down
21 changes: 21 additions & 0 deletions packages/cubejs-testing/birdbox-fixtures/rbac/cube.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,27 @@ module.exports = {
},
};
}
if (user === 'default') {
if (password && password !== 'default_password') {
throw new Error(`Password doesn't match for ${user}`);
}
return {
password,
superuser: false,
securityContext: {
auth: {
username: 'default',
userAttributes: {
region: 'CA',
city: 'San Francisco',
canHaveAdmin: false,
minDefaultId: 20000,
},
roles: [],
},
},
};
}
throw new Error(`User "${user}" doesn't exist`);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ cubes:

access_policy:
- role: "*"
row_level:
filters:
- member: "{CUBE}.city"
operator: equals
values: ["{ security_context.auth.userAttributes.city }"]
- role: admin
conditions:
# This thing will fail if there's no auth info in the context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -587,4 +587,12 @@ Array [
]
`;

exports[`Cube RBAC Engine RBAC via SQL API default policy SELECT with member expressions: users_member_expression 1`] = `
Array [
Object {
"count": "149",
},
]
`;

exports[`Cube RBAC Engine RBAC via SQL API manager SELECT * from line_items: line_items_manager 1`] = `Array []`;
18 changes: 18 additions & 0 deletions packages/cubejs-testing/test/smoke-rbac.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,24 @@ describe('Cube RBAC Engine', () => {
});
});

describe('RBAC via SQL API default policy', () => {
let connection: PgClient;

beforeAll(async () => {
connection = await createPostgresClient('default', 'default_password');

Check failure

Code scanning / CodeQL

Hard-coded credentials Critical test

The hard-coded value "default" is used as
user name
.
});

afterAll(async () => {
await connection.end();
}, JEST_AFTER_ALL_DEFAULT_TIMEOUT);

test('SELECT with member expressions', async () => {
const res = await connection.query('SELECT COUNT(city) as count from "users" HAVING (COUNT(1) > 0)');
// Pushed SQL queries should not fail
expect(res.rows).toMatchSnapshot('users_member_expression');
});
});

describe('RBAC via REST API', () => {
let client: CubeApi;
let defaultClient: CubeApi;
Expand Down

0 comments on commit 75f8708

Please sign in to comment.