fix: simplify rooms_users policies (#27629)

This commit is contained in:
Wen Bo Xie
2024-06-28 18:04:02 -04:00
committed by GitHub
parent 3957343713
commit 83ecfa5e76
3 changed files with 34 additions and 37 deletions

View File

@@ -41,25 +41,23 @@ We'll be using:
```sql
CREATE TABLE public.rooms (
id bigint GENERATED BY default AS IDENTITY PRIMARY KEY,
topic text NOT NULL
topic text NOT NULL UNIQUE
);
CREATE UNIQUE INDEX "unique_topic" on public.rooms (topic);
ALTER TABLE public.rooms ENABLE ROW LEVEL SECURITY;
CREATE TABLE public.profiles (
id bigint GENERATED BY default AS IDENTITY PRIMARY KEY,
id uuid NOT NULL REFERENCES auth.users ON DELETE CASCADE,
email text NOT NULL,
user_id uuid REFERENCES auth.users (id)
PRIMARY KEY (id)
);
ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
CREATE TABLE public.rooms_users (
user_id uuid REFERENCES auth.users (id),
room_id bigint REFERENCES public.rooms (id),
room_topic text REFERENCES public.rooms (topic),
created_at timestamptz DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE public.rooms ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.rooms_users ENABLE ROW LEVEL SECURITY;
```
@@ -82,7 +80,6 @@ AS PERMISSIVE FOR INSERT
TO supabase_auth_admin
WITH CHECK (true);
CREATE POLICY "authenticated users can read rooms"
ON "public"."rooms"
AS PERMISSIVE FOR SELECT
@@ -95,7 +92,6 @@ AS PERMISSIVE FOR INSERT
TO authenticated
WITH CHECK (TRUE);
CREATE POLICY "authenticated users can read rooms_users"
ON "public"."rooms_users"
AS PERMISSIVE FOR SELECT
@@ -108,30 +104,30 @@ AS PERMISSIVE FOR INSERT
TO authenticated
WITH CHECK (TRUE);
CREATE POLICY "authenticated user can enter room"
CREATE POLICY "authenticated user can read broadcast messages and presence state"
ON "realtime"."messages"
AS PERMISSIVE FOR SELECT
TO authenticated
USING (
EXISTS (
SELECT ru.user_id
FROM public.rooms_users ru
JOIN public.rooms r ON r.id = ru.room_id AND r.topic = realtime.topic()
WHERE ru.user_id = auth.uid()
SELECT 1
FROM public.rooms_users
WHERE user_id = auth.uid()
AND room_topic = realtime.topic()
AND realtime.messages.extension in ('broadcast', 'presence')
)
);
CREATE POLICY "authenticated user can broadcast in room"
CREATE POLICY "authenticated user can send broadcast messages and track presence"
ON "realtime"."messages"
AS PERMISSIVE FOR INSERT
TO authenticated
WITH CHECK (
EXISTS (
SELECT ru.user_id
FROM public.rooms_users ru
JOIN public.rooms r ON r.id = ru.room_id AND r.topic = realtime.topic()
WHERE ru.user_id = auth.uid()
SELECT 1
FROM public.rooms_users
WHERE user_id = auth.uid()
AND room_topic = realtime.topic()
AND realtime.messages.extension in ('broadcast', 'presence')
)
);
@@ -145,7 +141,7 @@ We need to create a database function and trigger to add an entry to `public.pro
CREATE OR REPLACE FUNCTION insert_user() RETURNS TRIGGER AS
$$
BEGIN
INSERT INTO public.profiles (user_id, email) VALUES (NEW.id, NEW.email); RETURN NEW;
INSERT INTO public.profiles (id, email) VALUES (NEW.id, NEW.email); RETURN NEW;
END;
$$ LANGUAGE plpgsql;
@@ -159,18 +155,19 @@ GRANT INSERT ON TABLE public.profiles TO supabase_auth_admin;
## Coding Concerns
* Check we're using the `2.10.0` version of `@supabase/realtime-js`
* Check that you're using `@supabase/realtime-js` v2.44.0 or later.
* You need to define that the channel is private using the new configuration field during channel creation:
```typescript
let channel = supabase.realtime.channel(selectedRoom, {
config: { broadcast: { self: true }, private: true },
})
```
You can check `app/protected/page.tsx` for more information regarding this
```typescript
const channel = supabase.channel('room-1', {
config: { private: true },
})
```
You can check `app/protected/page.tsx` to see how we've set it up in the demo.
## Adding user to channel
Type `/invite <email>` of an existing user and they will be added to the channel.
![](invite.png)
![invite user slash command](invite.png)

View File

@@ -23,15 +23,15 @@ export default function Chat() {
}
const addUserToChannel = async (email: string) => {
const user = await supabase.from('profiles').select('user_id').eq('email', email)
const user = await supabase.from('profiles').select('id').eq('email', email)
if (!user.data?.length) {
addMessage(true, true, `User ${email} not found`)
} else {
const room = await supabase.from('rooms').select('id').eq('topic', selectedRoom)
const room = await supabase.from('rooms').select('topic').eq('topic', selectedRoom)
await supabase
.from('rooms_users')
.upsert({ user_id: user.data?.[0].user_id, room_id: room.data?.[0].id })
.upsert({ user_id: user.data?.[0].id, room_topic: room.data?.[0].topic })
addMessage(true, true, `Added ${email} to channel ${selectedRoom}`)
}
}
@@ -65,7 +65,7 @@ export default function Chat() {
await supabase.auth.getUser()
const token = (await supabase.auth.getSession()).data.session?.access_token!
supabase.realtime.setAuth(token)
let main = supabase.realtime
let main = supabase
.channel('supaslack')
.on('broadcast', { event: 'new_room' }, () => getChannels())
.subscribe()
@@ -86,7 +86,7 @@ export default function Chat() {
channel?.unsubscribe()
setUsers(new Set())
let newChannel = supabase.realtime.channel(selectedRoom, {
let newChannel = supabase.channel(selectedRoom, {
config: {
broadcast: { self: true },
private: true, // This line will tell the server that you want to use a private channel for this connection

View File

@@ -14,12 +14,12 @@ export default function CreateRoomModal({ channel }: { channel: RealtimeChannel
supabase.realtime.setAuth(token)
const rooms_response = await supabase.from('rooms').insert({ topic }).select('id')
const rooms_response = await supabase.from('rooms').insert({ topic }).select('topic')
if (rooms_response.data) {
await supabase
.from('rooms_users')
.insert({ user_id: user.data.user!.id, room_id: rooms_response.data![0].id })
.insert({ user_id: user.data.user!.id, room_topic: rooms_response.data![0].topic })
await channel?.send({
type: 'broadcast',