veza/veza-backend-api/migrations/021_rbac_and_profiles.sql
senke ae586f6134 Phase 2 stabilisation: code mort, Modal→Dialog, feature flags, tests, router split, Rust legacy
Bloc A - Code mort:
- Suppression Studio (components, views, features)
- Suppression gamification + services mock (projectService, storageService, gamificationService)
- Mise à jour Sidebar, Navbar, locales

Bloc B - Frontend:
- Suppression modal.tsx deprecated, Modal.stories (doublon Dialog)
- Feature flags: PLAYLIST_SEARCH, PLAYLIST_RECOMMENDATIONS, ROLE_MANAGEMENT = true
- Suppression 19 tests orphelins, retrait exclusions vitest.config

Bloc C - Backend:
- Extraction routes_auth.go depuis router.go

Bloc D - Rust:
- Suppression security_legacy.rs (code mort, patterns déjà dans security/)
2026-02-14 17:23:32 +01:00

162 lines
No EOL
5.2 KiB
SQL

-- 020_rbac_and_profiles.sql
-- Role Based Access Control and User Profiles (Aligned with ORIGIN)
-- === ROLES ===
CREATE TABLE public.roles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(50) NOT NULL,
display_name VARCHAR(100) NOT NULL,
description TEXT,
is_system BOOLEAN DEFAULT false,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uni_roles_name UNIQUE (name)
);
-- === PERMISSIONS ===
CREATE TABLE public.permissions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(100) NOT NULL,
resource VARCHAR(50) NOT NULL,
action VARCHAR(50) NOT NULL,
description TEXT,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uni_permissions_name UNIQUE (name)
);
-- === USER ROLES (Assignments) ===
CREATE TABLE public.user_roles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
role_id UUID REFERENCES public.roles(id) ON DELETE SET NULL,
assigned_by UUID REFERENCES public.users(id) ON DELETE SET NULL,
-- Origin Alignment (adding missing fields)
role VARCHAR(50) NOT NULL, -- kept for redundancy/legacy or simple checks
verified BOOLEAN NOT NULL DEFAULT false,
verified_at TIMESTAMPTZ,
verified_by UUID REFERENCES public.users(id),
-- Legacy
assigned_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMPTZ,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_user_roles_user_role UNIQUE (user_id, role)
);
CREATE INDEX idx_user_roles_user_id ON public.user_roles(user_id);
CREATE INDEX idx_user_roles_role_id ON public.user_roles(role_id);
CREATE INDEX idx_user_roles_role ON public.user_roles(role);
-- === ROLE PERMISSIONS (Mapping) ===
CREATE TABLE public.role_permissions (
role_id UUID NOT NULL REFERENCES public.roles(id) ON DELETE CASCADE,
permission_id UUID NOT NULL REFERENCES public.permissions(id) ON DELETE CASCADE,
CONSTRAINT pk_role_permissions PRIMARY KEY (role_id, permission_id)
);
CREATE INDEX idx_role_permissions_role_id ON public.role_permissions(role_id);
CREATE INDEX idx_role_permissions_permission_id ON public.role_permissions(permission_id);
-- === USER PROFILES (Origin Standard) ===
CREATE TABLE public.user_profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
-- Profile Info
bio TEXT,
tagline VARCHAR(255),
location VARCHAR(255),
website_url VARCHAR(500),
-- Personal Info
birthdate DATE,
gender VARCHAR(50),
-- Media
avatar_url TEXT,
banner_url TEXT,
-- Preferences
language VARCHAR(5) DEFAULT 'en',
timezone VARCHAR(50) DEFAULT 'UTC',
theme VARCHAR(20) DEFAULT 'auto',
-- Privacy
profile_visibility public.visibility NOT NULL DEFAULT 'public',
show_email BOOLEAN NOT NULL DEFAULT false,
show_location BOOLEAN NOT NULL DEFAULT true,
-- Counts
follower_count INTEGER NOT NULL DEFAULT 0,
following_count INTEGER NOT NULL DEFAULT 0,
track_count INTEGER NOT NULL DEFAULT 0,
playlist_count INTEGER NOT NULL DEFAULT 0,
-- Timestamps
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_user_profiles_user_id UNIQUE (user_id)
);
CREATE INDEX idx_user_profiles_location ON public.user_profiles(location) WHERE location IS NOT NULL;
-- === USER SETTINGS (Origin Standard) ===
CREATE TABLE public.user_settings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
-- Notification Preferences
email_notifications BOOLEAN NOT NULL DEFAULT true,
push_notifications BOOLEAN NOT NULL DEFAULT true,
browser_notifications BOOLEAN NOT NULL DEFAULT true,
-- Email Notification Types
email_on_follow BOOLEAN NOT NULL DEFAULT true,
email_on_like BOOLEAN NOT NULL DEFAULT true,
email_on_comment BOOLEAN NOT NULL DEFAULT true,
email_on_message BOOLEAN NOT NULL DEFAULT true,
email_on_mention BOOLEAN NOT NULL DEFAULT true,
email_marketing BOOLEAN NOT NULL DEFAULT false,
-- Privacy
allow_search_indexing BOOLEAN NOT NULL DEFAULT true,
show_activity BOOLEAN NOT NULL DEFAULT true,
-- Content
explicit_content BOOLEAN NOT NULL DEFAULT false,
autoplay BOOLEAN NOT NULL DEFAULT true,
-- Timestamps
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uq_user_settings_user_id UNIQUE (user_id)
);
-- === ADMIN SETTINGS (Legacy) ===
CREATE TABLE public.admin_settings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
key VARCHAR(255) NOT NULL,
value TEXT,
type VARCHAR(50),
description TEXT,
category VARCHAR(50),
is_public BOOLEAN DEFAULT false,
updated_by UUID REFERENCES public.users(id) ON DELETE SET NULL,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_admin_settings_key UNIQUE (key)
);