-- ===================================================================== -- GameDev Tracker — Schéma de base de données (Supabase / PostgreSQL) -- À exécuter UNE SEULE FOIS dans : Supabase > SQL Editor > New query -- ===================================================================== -- ---------- Types énumérés ------------------------------------------- do $$ begin create type member_role as enum ('lead','programmer','artist','game_designer','sound','writer','qa','other'); exception when duplicate_object then null; end $$; do $$ begin create type task_status as enum ('todo','in_progress','review','done'); exception when duplicate_object then null; end $$; do $$ begin create type priority_level as enum ('low','medium','high','urgent'); exception when duplicate_object then null; end $$; do $$ begin create type milestone_status as enum ('planned','in_progress','done'); exception when duplicate_object then null; end $$; do $$ begin create type bug_severity as enum ('low','medium','high','critical'); exception when duplicate_object then null; end $$; do $$ begin create type bug_status as enum ('open','in_progress','resolved','closed'); exception when duplicate_object then null; end $$; -- ---------- Profils (étend auth.users) ------------------------------- create table if not exists public.profiles ( id uuid primary key references auth.users(id) on delete cascade, full_name text not null default 'Membre', role member_role not null default 'other', avatar_color text not null default '#7c5cff', created_at timestamptz not null default now() ); -- ---------- Projets -------------------------------------------------- create table if not exists public.projects ( id uuid primary key default gen_random_uuid(), name text not null, description text, created_by uuid references public.profiles(id) on delete set null, created_at timestamptz not null default now() ); -- ---------- Jalons (milestones) -------------------------------------- create table if not exists public.milestones ( id uuid primary key default gen_random_uuid(), project_id uuid not null references public.projects(id) on delete cascade, title text not null, description text, due_date date, status milestone_status not null default 'planned', created_at timestamptz not null default now() ); -- ---------- Tâches --------------------------------------------------- create table if not exists public.tasks ( id uuid primary key default gen_random_uuid(), project_id uuid not null references public.projects(id) on delete cascade, title text not null, description text, status task_status not null default 'todo', priority priority_level not null default 'medium', assignee_id uuid references public.profiles(id) on delete set null, milestone_id uuid references public.milestones(id) on delete set null, due_date date, position double precision not null default 0, created_by uuid references public.profiles(id) on delete set null, created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); -- ---------- Bugs ----------------------------------------------------- create table if not exists public.bugs ( id uuid primary key default gen_random_uuid(), project_id uuid not null references public.projects(id) on delete cascade, title text not null, description text, severity bug_severity not null default 'medium', status bug_status not null default 'open', priority priority_level not null default 'medium', assignee_id uuid references public.profiles(id) on delete set null, reporter_id uuid references public.profiles(id) on delete set null, created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); create index if not exists idx_tasks_project on public.tasks(project_id); create index if not exists idx_bugs_project on public.bugs(project_id); create index if not exists idx_milestones_project on public.milestones(project_id); -- ---------- Maj automatique de updated_at ---------------------------- create or replace function public.touch_updated_at() returns trigger language plpgsql as $$ begin new.updated_at = now(); return new; end $$; drop trigger if exists trg_tasks_touch on public.tasks; create trigger trg_tasks_touch before update on public.tasks for each row execute function public.touch_updated_at(); drop trigger if exists trg_bugs_touch on public.bugs; create trigger trg_bugs_touch before update on public.bugs for each row execute function public.touch_updated_at(); -- ---------- Création auto du profil à l'inscription ------------------ create or replace function public.handle_new_user() returns trigger language plpgsql security definer set search_path = public as $$ begin insert into public.profiles (id, full_name, role) values ( new.id, coalesce(new.raw_user_meta_data->>'full_name', split_part(new.email,'@',1)), coalesce((new.raw_user_meta_data->>'role')::member_role, 'other') ) on conflict (id) do nothing; return new; end $$; drop trigger if exists on_auth_user_created on auth.users; create trigger on_auth_user_created after insert on auth.users for each row execute function public.handle_new_user(); -- ---------- Sécurité (RLS) ------------------------------------------- -- Équipe privée et de confiance : tout membre connecté a accès complet. alter table public.profiles enable row level security; alter table public.projects enable row level security; alter table public.milestones enable row level security; alter table public.tasks enable row level security; alter table public.bugs enable row level security; do $$ declare t text; begin foreach t in array array['profiles','projects','milestones','tasks','bugs'] loop execute format('drop policy if exists %I_all on public.%I', t, t); execute format( 'create policy %I_all on public.%I for all to authenticated using (true) with check (true)', t, t); end loop; end $$; -- ---------- Realtime (synchro live entre membres) -------------------- do $$ begin alter publication supabase_realtime add table public.tasks; exception when duplicate_object then null; end $$; do $$ begin alter publication supabase_realtime add table public.bugs; exception when duplicate_object then null; end $$; do $$ begin alter publication supabase_realtime add table public.milestones; exception when duplicate_object then null; end $$;