Skip to content

Commit befeb46

Browse files
fix(rls): apply RLS filter post-QueryEngine, fix getSingleDoc $and, update dashboard label
Agent-Logs-Url: https://github.com/yash-pouranik/urBackend/sessions/91669e19-a2de-410f-a997-63b1a2f4f61d Co-authored-by: yash-pouranik <172860064+yash-pouranik@users.noreply.github.com>
1 parent efcab14 commit befeb46

3 files changed

Lines changed: 35 additions & 14 deletions

File tree

apps/public-api/src/__tests__/data.controller.read.test.js

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
'use strict';
22

33
const mockFind = jest.fn();
4+
const mockAnd = jest.fn();
45
const mockFindOne = jest.fn();
6+
const mockQueryLean = jest.fn().mockResolvedValue([]);
57

6-
const mockQueryEngine = jest.fn((query) => ({
7-
filter: () => ({
8-
sort: () => ({
9-
paginate: () => ({ query }),
10-
}),
11-
}),
12-
}));
8+
// mockAnd returns an object with .lean() so features.query.lean() works after .and()
9+
mockAnd.mockReturnValue({ lean: mockQueryLean });
10+
11+
const mockQueryEngine = jest.fn((query) => {
12+
const engine = {
13+
query,
14+
filter() { return engine; },
15+
sort() { return engine; },
16+
paginate() { return engine; },
17+
};
18+
return engine;
19+
});
1320

1421
jest.mock('@urbackend/common', () => ({
1522
sanitize: (v) => v,
@@ -18,7 +25,7 @@ jest.mock('@urbackend/common', () => ({
1825
getCompiledModel: jest.fn(() => ({
1926
find: (...args) => {
2027
mockFind(...args);
21-
return { lean: jest.fn().mockResolvedValue([]) };
28+
return { and: mockAnd, lean: mockQueryLean };
2229
},
2330
findOne: (...args) => {
2431
mockFindOne(...args);
@@ -75,7 +82,8 @@ describe('data.controller read RLS filters', () => {
7582

7683
await getAllData(req, res);
7784

78-
expect(mockFind).toHaveBeenCalledWith({ userId: 'user_1' });
85+
expect(mockFind).toHaveBeenCalledWith();
86+
expect(mockAnd).toHaveBeenCalledWith([{ userId: 'user_1' }]);
7987
expect(res.json).toHaveBeenCalled();
8088
});
8189

@@ -86,8 +94,10 @@ describe('data.controller read RLS filters', () => {
8694
await getSingleDoc(req, res);
8795

8896
expect(mockFindOne).toHaveBeenCalledWith({
89-
_id: '507f1f77bcf86cd799439011',
90-
userId: 'user_1',
97+
$and: [
98+
{ _id: '507f1f77bcf86cd799439011' },
99+
{ userId: 'user_1' },
100+
],
91101
});
92102
expect(res.json).toHaveBeenCalled();
93103
});

apps/public-api/src/controllers/data.controller.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,14 @@ module.exports.getAllData = async (req, res) => {
103103
);
104104

105105
const baseFilter = req.rlsFilter && typeof req.rlsFilter === 'object' ? req.rlsFilter : {};
106-
const features = new QueryEngine(Model.find(baseFilter), req.query)
107-
.filter()
106+
const features = new QueryEngine(Model.find(), req.query)
107+
.filter();
108+
109+
if (Object.keys(baseFilter).length > 0) {
110+
features.query = features.query.and([baseFilter]);
111+
}
112+
113+
features
108114
.sort()
109115
.paginate();
110116

apps/web-dashboard/src/pages/Database.jsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,8 +782,13 @@ export default function Database() {
782782
onChange={(e) => setRlsEnabled(e.target.checked)}
783783
style={{ accentColor: "var(--color-primary)" }}
784784
/>
785-
<span>Enable RLS for publishable-key writes</span>
785+
<span>Enable RLS access rules for publishable-key requests</span>
786786
</label>
787+
<p className="rls-help-text">
788+
{rlsMode === "private"
789+
? "When enabled, publishable-key access is restricted to the owner for both reads and writes."
790+
: "When enabled, publishable-key writes are restricted to the owner. Reads remain available according to the selected access mode."}
791+
</p>
787792

788793
<div className="rls-owner-field-group">
789794
<label htmlFor="rls-mode">Access Mode</label>

0 commit comments

Comments
 (0)