mirror of
https://github.com/supabase/supabase.git
synced 2026-05-31 18:03:33 +08:00
fix: simplify rooms_users policies (#27629)
This commit is contained in:
@@ -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.
|
||||
|
||||

|
||||

|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user