Skip to content

Commit 350f0c5

Browse files
authored
Merge pull request #17 from launchql/fix/use-supabase-users
Fix/use supabase users
2 parents 99529c3 + 1b39912 commit 350f0c5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2356
-5320
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
fail-fast: false
1414
matrix:
1515
package:
16-
- rls-demo
16+
- hello-world
1717
- supabase
1818

1919
env:

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ npx supabase start
3535
pnpm install
3636

3737
# Run tests in watch mode
38-
cd packages/rls-demo
38+
cd packages/hello-world
3939
pnpm test:watch
4040
```
4141

@@ -44,7 +44,7 @@ pnpm test:watch
4444
This is a LaunchQL workspace combining `pnpm` and `lql` for modular Postgres packages:
4545

4646
- **`packages/supabase`** - Supabase-focused SQL, tests, and helpers
47-
- **`packages/rls-demo`** - Demo extension showcasing RLS with users/products
47+
- **`packages/hello-world`** - Demo extension showcasing RLS with users/products
4848

4949
## Testing
5050

@@ -55,7 +55,7 @@ Run tests in different modes:
5555
pnpm test
5656

5757
# Watch mode for specific package
58-
cd packages/rls-demo
58+
cd packages/hello-world
5959
pnpm test:watch
6060

6161
# Run Supabase package tests

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"lerna": "^8.2.3",
4141
"prettier": "^3.0.2",
4242
"rimraf": "4.4.1",
43-
"supabase-test": "^0.0.9",
43+
"supabase-test": "^0.0.10",
4444
"ts-jest": "^29.4.5",
4545
"ts-node": "^10.9.2",
4646
"typescript": "^5.9.3"
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
EXTENSION = launchql-rls-demo
2-
DATA = sql/launchql-rls-demo--0.0.1.sql
1+
EXTENSION = hello-world
2+
DATA = sql/hello-world--0.0.1.sql
33

44
PG_CONFIG = pg_config
55
PGXS := $(shell $(PG_CONFIG) --pgxs)
File renamed without changes.
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import { getConnections, PgTestClient } from 'supabase-test';
2+
import { insertUser } from '../test-utils';
3+
4+
let db: PgTestClient;
5+
let pg: PgTestClient;
6+
let teardown: () => Promise<void>;
7+
8+
let user1: any;
9+
let user2: any;
10+
let user3: any;
11+
12+
const users = [
13+
{
14+
id: '550e8400-e29b-41d4-a716-446655440001',
15+
16+
name: 'Tutorial User 1'
17+
},
18+
{
19+
id: '550e8400-e29b-41d4-a716-446655440002',
20+
21+
name: 'Tutorial User 2'
22+
},
23+
{
24+
id: '550e8400-e29b-41d4-a716-446655440003',
25+
26+
name: 'Tutorial User 3'
27+
}
28+
];
29+
30+
beforeAll(async () => {
31+
({ pg, db, teardown } = await getConnections());
32+
user1 = await insertUser(pg, users[0].email, users[0].id);
33+
user2 = await insertUser(pg, users[1].email, users[1].id);
34+
user3 = await insertUser(pg, users[2].email, users[2].id);
35+
});
36+
37+
afterAll(async () => {
38+
await teardown();
39+
});
40+
41+
beforeEach(async () => {
42+
await db.beforeEach();
43+
});
44+
45+
afterEach(async () => {
46+
await db.afterEach();
47+
});
48+
49+
describe('tutorial: basic rls crud operations', () => {
50+
it('should allow user to create their own user record', async () => {
51+
// set context to simulate authenticated user
52+
db.setContext({
53+
role: 'authenticated',
54+
'request.jwt.claim.sub': user1.id
55+
});
56+
57+
// user can create their own pet
58+
const pet = await db.one(
59+
`INSERT INTO rls_test.pets (name, breed, user_id)
60+
VALUES ($1, $2, $3)
61+
RETURNING id, name, breed, user_id`,
62+
['Fido', 'Labrador', user1.id]
63+
);
64+
65+
expect(pet.name).toBe('Fido');
66+
expect(pet.breed).toBe('Labrador');
67+
expect(pet.user_id).toBe(user1.id);
68+
});
69+
70+
it('should prevent user1 from updating user2\'s record', async () => {
71+
// user2 creates a pet
72+
db.setContext({
73+
role: 'authenticated',
74+
'request.jwt.claim.sub': user2.id
75+
});
76+
77+
const pet = await db.one(
78+
`INSERT INTO rls_test.pets (name, breed, user_id)
79+
VALUES ($1, $2, $3)
80+
RETURNING id, name, breed, user_id`,
81+
['Buddy', 'Golden Retriever', user2.id]
82+
);
83+
84+
expect(pet.user_id).toBe(user2.id);
85+
86+
// user1 tries to update user2's pet - should throw
87+
db.setContext({
88+
role: 'authenticated',
89+
'request.jwt.claim.sub': user1.id
90+
});
91+
92+
await expect(
93+
db.one(
94+
`UPDATE rls_test.pets
95+
SET name = $1
96+
WHERE id = $2
97+
RETURNING id, name, breed, user_id`,
98+
['Hacked Name', pet.id]
99+
)
100+
).rejects.toThrow();
101+
});
102+
103+
it('should allow users to see only their own data in list queries', async () => {
104+
// set context to user1
105+
db.setContext({
106+
role: 'authenticated',
107+
'request.jwt.claim.sub': user1.id
108+
});
109+
110+
// create multiple users as admin
111+
await db.one(
112+
`INSERT INTO rls_test.pets (name, breed, user_id)
113+
VALUES ($1, $2, $3)
114+
RETURNING id`,
115+
['Fido', 'Labrador', user1.id]
116+
);
117+
118+
// set context to user1
119+
db.setContext({
120+
role: 'authenticated',
121+
'request.jwt.claim.sub': user2.id
122+
});
123+
124+
await db.one(
125+
`INSERT INTO rls_test.pets (name, breed, user_id)
126+
VALUES ($1, $2, $3)
127+
RETURNING id`,
128+
['Buddy', 'Golden Retriever', user2.id]
129+
);
130+
131+
// set context to user1
132+
db.setContext({
133+
role: 'authenticated',
134+
'request.jwt.claim.sub': user3.id
135+
});
136+
137+
await db.one(
138+
`INSERT INTO rls_test.pets (name, breed, user_id)
139+
VALUES ($1, $2, $3)
140+
RETURNING id`,
141+
['Rex', 'German Shepherd', user3.id]
142+
);
143+
144+
// set context to user1
145+
db.setContext({
146+
role: 'authenticated',
147+
'request.jwt.claim.sub': user1.id
148+
});
149+
150+
// user1 should only see their own record in a list query
151+
const allUsers = await db.many(
152+
`SELECT id, name, breed, user_id FROM rls_test.pets ORDER BY name`
153+
);
154+
155+
expect(allUsers.length).toBe(1);
156+
expect(allUsers[0].user_id).toBe(user1.id);
157+
expect(allUsers[0].name).toBe('Fido');
158+
expect(allUsers[0].breed).toBe('Labrador');
159+
});
160+
161+
});
162+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
id,name,breed,user_id
2+
660e8400-e29b-41d4-a716-446655440001,Fido,Labrador,550e8400-e29b-41d4-a716-446655440001
3+
660e8400-e29b-41d4-a716-446655440002,Buddy,Golden Retriever,550e8400-e29b-41d4-a716-446655440002
4+
660e8400-e29b-41d4-a716-446655440003,Rex,German Shepherd,550e8400-e29b-41d4-a716-446655440003
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-- Seed data for rls_test schema
2+
-- This file can be used to populate the database with test data
3+
4+
-- Insert test users
5+
INSERT INTO auth.users (id, email) VALUES
6+
('550e8400-e29b-41d4-a716-446655440001', '[email protected]'),
7+
('550e8400-e29b-41d4-a716-446655440002', '[email protected]'),
8+
('550e8400-e29b-41d4-a716-446655440003', '[email protected]'),
9+
('550e8400-e29b-41d4-a716-446655440004', '[email protected]');
10+
11+
-- Insert test pets
12+
INSERT INTO rls_test.pets (id, name, breed, user_id) VALUES
13+
('660e8400-e29b-41d4-a716-446655440001', 'Fido', 'Labrador', '550e8400-e29b-41d4-a716-446655440001'),
14+
('660e8400-e29b-41d4-a716-446655440002', 'Buddy', 'Golden Retriever', '550e8400-e29b-41d4-a716-446655440002'),
15+
('660e8400-e29b-41d4-a716-446655440003', 'Rex', 'German Shepherd', '550e8400-e29b-41d4-a716-446655440003');
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
export const users = [
2+
{
3+
id: '550e8400-e29b-41d4-a716-446655440001',
4+
5+
},
6+
{
7+
id: '550e8400-e29b-41d4-a716-446655440002',
8+
9+
},
10+
{
11+
id: '550e8400-e29b-41d4-a716-446655440003',
12+
13+
}
14+
];
15+
16+
export const pets = [
17+
{
18+
id: '660e8400-e29b-41d4-a716-446655440001',
19+
name: 'Fido',
20+
breed: 'Labrador',
21+
user_id: '550e8400-e29b-41d4-a716-446655440001'
22+
},
23+
{
24+
id: '660e8400-e29b-41d4-a716-446655440002',
25+
name: 'Buddy',
26+
breed: 'Golden Retriever',
27+
user_id: '550e8400-e29b-41d4-a716-446655440002'
28+
},
29+
{
30+
id: '660e8400-e29b-41d4-a716-446655440003',
31+
name: 'Rex',
32+
breed: 'German Shepherd',
33+
user_id: '550e8400-e29b-41d4-a716-446655440003'
34+
}
35+
];
36+

0 commit comments

Comments
 (0)