Remodeled database and api to prepare for move
This commit is contained in:
@@ -4,9 +4,11 @@
|
||||
|
||||
-- Custom types
|
||||
create type public.app_permission as enum ('events.see.hidden', 'users.ban');
|
||||
create type public.app_role as enum ('sa', 'gm');
|
||||
create type public.app_role as enum ('sa', 'admin', 'moderator', 'user');
|
||||
create type public.app_colors as enum ('red', 'orange', 'amber', 'yellow', 'lime', 'green', 'emerald', 'teal', 'cyan', 'sky', 'blue', 'indigo', 'violet', 'purple', 'fuchsia', 'pink', 'rose', 'black', 'white');
|
||||
|
||||
-- USERS
|
||||
-- DATA STRUCTURES
|
||||
-- Users
|
||||
create table public.users (
|
||||
id uuid references auth.users not null primary key, -- UUID from auth.users
|
||||
username text
|
||||
@@ -14,16 +16,16 @@ create table public.users (
|
||||
comment on table public.users is 'Profile data for each user.';
|
||||
comment on column public.users.id is 'References the internal Supabase Auth user.';
|
||||
|
||||
-- USER ROLES
|
||||
-- Roles
|
||||
create table public.user_roles (
|
||||
id bigint generated by default as identity primary key,
|
||||
user_id uuid references public.users on delete cascade not null,
|
||||
role app_role not null,
|
||||
user_id uuid references public.users on delete cascade not null,
|
||||
unique (user_id, role)
|
||||
);
|
||||
comment on table public.user_roles is 'Application roles for each user.';
|
||||
|
||||
-- ROLE PERMISSIONS
|
||||
-- Permissions
|
||||
create table public.role_permissions (
|
||||
id bigint generated by default as identity primary key,
|
||||
role app_role not null,
|
||||
@@ -32,6 +34,70 @@ create table public.role_permissions (
|
||||
);
|
||||
comment on table public.role_permissions is 'Application permissions for each role.';
|
||||
|
||||
-- Worlds
|
||||
create table public.worlds (
|
||||
id bigint generated by default as identity primary key,
|
||||
name text not null,
|
||||
description text,
|
||||
color app_colors,
|
||||
gm_id uuid references public.users on delete cascade
|
||||
);
|
||||
comment on table public.worlds is 'Worlds belonging to a single user ; a game master.';
|
||||
|
||||
-- World Calendars
|
||||
create table public.world_calendars (
|
||||
id bigint generated by default as identity primary key,
|
||||
months text array,
|
||||
days_per_year int not null,
|
||||
world_id bigint references public.worlds on delete cascade not null
|
||||
);
|
||||
comment on table public.world_calendars is 'Calendar settings and configuration attached to a single world.';
|
||||
|
||||
-- Event categories
|
||||
create table public.events_category (
|
||||
id bigint generated by default as identity primary key,
|
||||
name text not null,
|
||||
unique (name)
|
||||
);
|
||||
comment on table public.events_category is 'Categories describing events';
|
||||
|
||||
-- Events
|
||||
create table public.events (
|
||||
id bigint generated by default as identity primary key,
|
||||
title text not null,
|
||||
description text,
|
||||
start_date json not null,
|
||||
end_date json,
|
||||
category bigint references public.events_category on delete cascade,
|
||||
hidden boolean,
|
||||
wiki text,
|
||||
calendar_id bigint references public.world_calendars on delete cascade not null
|
||||
);
|
||||
comment on table public.events is 'Events linked to a world';
|
||||
|
||||
-- Character categories
|
||||
create table public.characters_category (
|
||||
id bigint generated by default as identity primary key,
|
||||
name text not null,
|
||||
unique (name)
|
||||
);
|
||||
comment on table public.characters_category is 'Categories describing characters';
|
||||
|
||||
-- Characters
|
||||
create table public.characters (
|
||||
id bigint generated by default as identity primary key,
|
||||
name text not null,
|
||||
description text,
|
||||
birth json not null,
|
||||
death json,
|
||||
category bigint references public.characters_category on delete cascade,
|
||||
hidden_birth boolean,
|
||||
hidden_death boolean,
|
||||
wiki text,
|
||||
world_id bigint references public.worlds on delete cascade not null
|
||||
);
|
||||
comment on table public.characters is 'Characters linked to a world';
|
||||
|
||||
-- authorize with role-based access control (RBAC)
|
||||
create function public.authorize(
|
||||
requested_permission app_permission
|
||||
@@ -54,11 +120,84 @@ $$ language plpgsql security definer set search_path = public;
|
||||
alter table public.users enable row level security;
|
||||
alter table public.user_roles enable row level security;
|
||||
alter table public.role_permissions enable row level security;
|
||||
alter table public.worlds enable row level security;
|
||||
alter table public.world_calendars enable row level security;
|
||||
alter table public.events_category enable row level security;
|
||||
alter table public.characters_category enable row level security;
|
||||
alter table public.characters enable row level security;
|
||||
alter table public.events enable row level security;
|
||||
|
||||
-- User policies
|
||||
create policy "Allow logged-in read access" on public.users for select using ( auth.role() = 'authenticated' );
|
||||
create policy "Allow individual insert access" on public.users for insert with check ( auth.uid() = id );
|
||||
create policy "Allow individual update access" on public.users for update using ( auth.uid() = id );
|
||||
create policy "Allow individual read access" on public.user_roles for select using ( auth.uid() = user_id );
|
||||
|
||||
-- World policies
|
||||
create policy "Allow individual read access for GMs" on public.worlds for select using ( ( auth.uid() = gm_id ) );
|
||||
create policy "Allow individual insert access for GMs" on public.worlds for insert with check ( auth.uid() = gm_id );
|
||||
create policy "Allow individual update access for GMs" on public.worlds for update using ( auth.uid() = gm_id );
|
||||
|
||||
-- Calendar policies
|
||||
create policy "Allow individual read access for GMs" on public.world_calendars for select using (
|
||||
exists (
|
||||
select 1 from worlds
|
||||
where worlds.id = world_calendars.world_id
|
||||
)
|
||||
);
|
||||
create policy "Allow individual insert access for GMs" on public.world_calendars for insert with check (
|
||||
exists (
|
||||
select 1 from worlds
|
||||
where worlds.id = world_calendars.world_id
|
||||
)
|
||||
);
|
||||
create policy "Allow individual update access for GMs" on public.world_calendars for update with check (
|
||||
exists (
|
||||
select 1 from worlds
|
||||
where worlds.id = world_calendars.world_id
|
||||
)
|
||||
);
|
||||
|
||||
-- Event policies
|
||||
create policy "Allow individual read access for GMs" on public.events for select using (
|
||||
exists (
|
||||
select 1 from world_calendars
|
||||
where world_calendars.id = events.calendar_id
|
||||
)
|
||||
);
|
||||
create policy "Allow individual insert access for GMs" on public.events for insert with check (
|
||||
exists (
|
||||
select 1 from world_calendars
|
||||
where world_calendars.id = events.calendar_id
|
||||
)
|
||||
);
|
||||
create policy "Allow individual update access for GMs" on public.events for update with check (
|
||||
exists (
|
||||
select 1 from world_calendars
|
||||
where world_calendars.id = events.calendar_id
|
||||
)
|
||||
);
|
||||
|
||||
-- Character policies
|
||||
create policy "Allow individual read access for GMs" on public.characters for select using (
|
||||
exists (
|
||||
select 1 from worlds
|
||||
where worlds.id = characters.world_id
|
||||
)
|
||||
);
|
||||
create policy "Allow individual insert access for GMs" on public.characters for insert with check (
|
||||
exists (
|
||||
select 1 from worlds
|
||||
where worlds.id = characters.world_id
|
||||
)
|
||||
);
|
||||
create policy "Allow individual update access for GMs" on public.characters for update with check (
|
||||
exists (
|
||||
select 1 from worlds
|
||||
where worlds.id = characters.world_id
|
||||
)
|
||||
);
|
||||
|
||||
-- Send "previous data" on change
|
||||
alter table public.users replica identity full;
|
||||
|
||||
@@ -69,6 +208,8 @@ declare is_admin boolean;
|
||||
begin
|
||||
insert into public.users (id, username)
|
||||
values (new.id, new.email);
|
||||
insert into public.user_roles (role, user_id)
|
||||
values ('user', new.id);
|
||||
|
||||
return new;
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user