- )
-}
diff --git a/src/contexts/AuthContext.tsx b/src/contexts/AuthContext.tsx
deleted file mode 100644
index 658f1c6..0000000
--- a/src/contexts/AuthContext.tsx
+++ /dev/null
@@ -1,174 +0,0 @@
-import React, { createContext, useContext, useEffect, useState } from 'react'
-import type { User } from '@supabase/supabase-js'
-import { supabase } from '../lib/supabase'
-import type { AuthContextType, AuthUser, UserProfile } from '../types/auth'
-
-const AuthContext = createContext(undefined)
-
-export const useAuth = () => {
- const context = useContext(AuthContext)
- if (context === undefined) {
- throw new Error('useAuth must be used within an AuthProvider')
- }
- return context
-}
-
-interface AuthProviderProps {
- children: React.ReactNode
-}
-
-export const AuthProvider: React.FC = ({ children }) => {
- const [user, setUser] = useState(null)
- const [loading, setLoading] = useState(true)
-
- // Fetch user profile and roles
- const fetchUserData = async (authUser: User): Promise => {
- try {
- // Fetch user profile
- const { data: profile, error: profileError } = await supabase
- .from('user_profiles')
- .select('*')
- .eq('id', authUser.id)
- .single()
-
- if (profileError && profileError.code !== 'PGRST116') {
- console.error('Error fetching user profile:', profileError)
- }
-
- // Fetch user roles using the database function
- const { data: rolesData, error: rolesError } = await supabase
- .rpc('get_user_roles', { user_uuid: authUser.id })
-
- if (rolesError) {
- console.error('Error fetching user roles:', rolesError)
- }
-
- const roles = rolesData?.map(r => r.role_name) || []
-
- return {
- ...authUser,
- profile: profile as UserProfile,
- roles
- }
- } catch (error) {
- console.error('Error fetching user data:', error)
- return {
- ...authUser,
- profile: undefined,
- roles: []
- }
- }
- }
-
- // Refresh user data
- const refreshUserData = async () => {
- const { data: { user: authUser } } = await supabase.auth.getUser()
- if (authUser) {
- const userData = await fetchUserData(authUser)
- setUser(userData)
- }
- }
-
- // Sign in
- const signIn = async (email: string, password: string) => {
- const { error } = await supabase.auth.signInWithPassword({
- email,
- password
- })
- return { error }
- }
-
- // Sign up
- const signUp = async (
- email: string,
- password: string,
- userData?: { first_name?: string; last_name?: string }
- ) => {
- const { data, error } = await supabase.auth.signUp({
- email,
- password,
- options: {
- data: userData
- }
- })
-
- // If signup successful and user data provided, create profile
- if (!error && data.user && userData) {
- const { error: profileError } = await supabase
- .from('user_profiles')
- .insert({
- id: data.user.id,
- first_name: userData.first_name,
- last_name: userData.last_name
- })
-
- if (profileError) {
- console.error('Error creating user profile:', profileError)
- }
-
- // Assign default 'user' role
- const { error: roleError } = await supabase
- .from('user_roles')
- .insert({
- user_id: data.user.id,
- role_id: 6 // 'user' role ID from our database
- })
-
- if (roleError) {
- console.error('Error assigning default role:', roleError)
- }
- }
-
- return { error }
- }
-
- // Sign out
- const signOut = async () => {
- await supabase.auth.signOut()
- setUser(null)
- }
-
- // Check if user has specific role
- const hasRole = (roleName: string): boolean => {
- return user?.roles?.includes(roleName) || false
- }
-
- // Check if user is admin
- const isAdmin = (): boolean => {
- return hasRole('admin')
- }
-
- // Handle auth state changes
- useEffect(() => {
- const { data: { subscription } } = supabase.auth.onAuthStateChange(
- async (event, session) => {
- if (session?.user) {
- const userData = await fetchUserData(session.user)
- setUser(userData)
- } else {
- setUser(null)
- }
- setLoading(false)
- }
- )
-
- return () => subscription.unsubscribe()
- }, [])
-
- const value: AuthContextType = {
- user,
- loading,
- signIn,
- signUp,
- signOut,
- hasRole,
- isAdmin,
- refreshUserData
- }
-
- return (
-
- {children}
-
- )
-}
diff --git a/src/index.css b/src/index.css
index a461c50..08a3ac9 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1 +1,68 @@
-@import "tailwindcss";
\ No newline at end of file
+:root {
+ font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/src/lib/supabase.ts b/src/lib/supabase.ts
deleted file mode 100644
index de3fd35..0000000
--- a/src/lib/supabase.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-import { createClient } from '@supabase/supabase-js'
-
-// Local Supabase instance configuration
-const supabaseUrl = 'http://127.0.0.1:54321'
-const supabaseAnonKey = '[REDACTED]'
-
-export const supabase = createClient(supabaseUrl, supabaseAnonKey)
-
-// Database types for TypeScript
-export interface Database {
- public: {
- Tables: {
- roles: {
- Row: {
- id: number
- name: string
- description: string | null
- created_at: string
- updated_at: string
- }
- Insert: {
- id?: number
- name: string
- description?: string | null
- created_at?: string
- updated_at?: string
- }
- Update: {
- id?: number
- name?: string
- description?: string | null
- created_at?: string
- updated_at?: string
- }
- }
- user_profiles: {
- Row: {
- id: string
- first_name: string | null
- last_name: string | null
- created_at: string
- updated_at: string
- }
- Insert: {
- id: string
- first_name?: string | null
- last_name?: string | null
- created_at?: string
- updated_at?: string
- }
- Update: {
- id?: string
- first_name?: string | null
- last_name?: string | null
- created_at?: string
- updated_at?: string
- }
- }
- user_roles: {
- Row: {
- id: number
- user_id: string | null
- role_id: number | null
- created_at: string
- updated_at: string
- }
- Insert: {
- id?: number
- user_id?: string | null
- role_id?: number | null
- created_at?: string
- updated_at?: string
- }
- Update: {
- id?: number
- user_id?: string | null
- role_id?: number | null
- created_at?: string
- updated_at?: string
- }
- }
- }
- Views: {
- [_ in never]: never
- }
- Functions: {
- get_user_roles: {
- Args: {
- user_uuid: string
- }
- Returns: {
- role_name: string
- }[]
- }
- user_has_role: {
- Args: {
- user_uuid: string
- role_name: string
- }
- Returns: boolean
- }
- }
- Enums: {
- [_ in never]: never
- }
- }
-}
diff --git a/src/types/auth.ts b/src/types/auth.ts
deleted file mode 100644
index 9d06821..0000000
--- a/src/types/auth.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import type { User } from '@supabase/supabase-js'
-
-export interface UserProfile {
- id: string
- first_name: string | null
- last_name: string | null
- created_at: string
- updated_at: string
-}
-
-export interface Role {
- id: number
- name: string
- description: string | null
- created_at: string
- updated_at: string
-}
-
-export interface UserRole {
- id: number
- user_id: string | null
- role_id: number | null
- created_at: string
- updated_at: string
-}
-
-export interface AuthUser extends User {
- profile?: UserProfile
- roles?: string[]
-}
-
-export interface AuthContextType {
- user: AuthUser | null
- loading: boolean
- signIn: (email: string, password: string) => Promise<{ error: any }>
- signUp: (email: string, password: string, userData?: { first_name?: string; last_name?: string }) => Promise<{ error: any }>
- signOut: () => Promise
- hasRole: (roleName: string) => boolean
- isAdmin: () => boolean
- refreshUserData: () => Promise
-}
-
-export type RoleName = 'admin' | 'user' | 'moderator' | 'coordinator' | 'conductor' | 'analyst'
diff --git a/supabase/.gitignore b/supabase/.gitignore
deleted file mode 100644
index ad9264f..0000000
--- a/supabase/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Supabase
-.branches
-.temp
-
-# dotenvx
-.env.keys
-.env.local
-.env.*.local
diff --git a/supabase/config.toml b/supabase/config.toml
deleted file mode 100644
index 04d9c30..0000000
--- a/supabase/config.toml
+++ /dev/null
@@ -1,322 +0,0 @@
-# For detailed configuration reference documentation, visit:
-# https://supabase.com/docs/guides/local-development/cli/config
-# A string used to distinguish different Supabase projects on the same host. Defaults to the
-# working directory name when running `supabase init`.
-project_id = "pecan_experiments"
-
-[api]
-enabled = true
-# Port to use for the API URL.
-port = 54321
-# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API
-# endpoints. `public` and `graphql_public` schemas are included by default.
-schemas = ["public", "graphql_public"]
-# Extra schemas to add to the search_path of every request.
-extra_search_path = ["public", "extensions"]
-# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size
-# for accidental or malicious requests.
-max_rows = 1000
-
-[api.tls]
-# Enable HTTPS endpoints locally using a self-signed certificate.
-enabled = false
-
-[db]
-# Port to use for the local database URL.
-port = 54322
-# Port used by db diff command to initialize the shadow database.
-shadow_port = 54320
-# The database major version to use. This has to be the same as your remote database's. Run `SHOW
-# server_version;` on the remote database to check.
-major_version = 17
-
-[db.pooler]
-enabled = false
-# Port to use for the local connection pooler.
-port = 54329
-# Specifies when a server connection can be reused by other clients.
-# Configure one of the supported pooler modes: `transaction`, `session`.
-pool_mode = "transaction"
-# How many server connections to allow per user/database pair.
-default_pool_size = 20
-# Maximum number of client connections allowed.
-max_client_conn = 100
-
-# [db.vault]
-# secret_key = "env(SECRET_VALUE)"
-
-[db.migrations]
-# If disabled, migrations will be skipped during a db push or reset.
-enabled = true
-# Specifies an ordered list of schema files that describe your database.
-# Supports glob patterns relative to supabase directory: "./schemas/*.sql"
-schema_paths = []
-
-[db.seed]
-# If enabled, seeds the database after migrations during a db reset.
-enabled = true
-# Specifies an ordered list of seed files to load during db reset.
-# Supports glob patterns relative to supabase directory: "./seeds/*.sql"
-sql_paths = ["./seed.sql"]
-
-[realtime]
-enabled = true
-# Bind realtime via either IPv4 or IPv6. (default: IPv4)
-# ip_version = "IPv6"
-# The maximum length in bytes of HTTP request headers. (default: 4096)
-# max_header_length = 4096
-
-[studio]
-enabled = true
-# Port to use for Supabase Studio.
-port = 54323
-# External URL of the API server that frontend connects to.
-api_url = "http://127.0.0.1"
-# OpenAI API Key to use for Supabase AI in the Supabase Studio.
-openai_api_key = "env(OPENAI_API_KEY)"
-
-# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they
-# are monitored, and you can view the emails that would have been sent from the web interface.
-[inbucket]
-enabled = true
-# Port to use for the email testing server web interface.
-port = 54324
-# Uncomment to expose additional ports for testing user applications that send emails.
-# smtp_port = 54325
-# pop3_port = 54326
-# admin_email = "admin@email.com"
-# sender_name = "Admin"
-
-[storage]
-enabled = true
-# The maximum file size allowed (e.g. "5MB", "500KB").
-file_size_limit = "50MiB"
-
-# Image transformation API is available to Supabase Pro plan.
-# [storage.image_transformation]
-# enabled = true
-
-# Uncomment to configure local storage buckets
-# [storage.buckets.images]
-# public = false
-# file_size_limit = "50MiB"
-# allowed_mime_types = ["image/png", "image/jpeg"]
-# objects_path = "./images"
-
-[auth]
-enabled = true
-# The base URL of your website. Used as an allow-list for redirects and for constructing URLs used
-# in emails.
-site_url = "http://127.0.0.1:3000"
-# A list of *exact* URLs that auth providers are permitted to redirect to post authentication.
-additional_redirect_urls = ["https://127.0.0.1:3000"]
-# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 (1 week).
-jwt_expiry = 3600
-# If disabled, the refresh token will never expire.
-enable_refresh_token_rotation = true
-# Allows refresh tokens to be reused after expiry, up to the specified interval in seconds.
-# Requires enable_refresh_token_rotation = true.
-refresh_token_reuse_interval = 10
-# Allow/disallow new user signups to your project.
-enable_signup = true
-# Allow/disallow anonymous sign-ins to your project.
-enable_anonymous_sign_ins = false
-# Allow/disallow testing manual linking of accounts
-enable_manual_linking = false
-# Passwords shorter than this value will be rejected as weak. Minimum 6, recommended 8 or more.
-minimum_password_length = 6
-# Passwords that do not meet the following requirements will be rejected as weak. Supported values
-# are: `letters_digits`, `lower_upper_letters_digits`, `lower_upper_letters_digits_symbols`
-password_requirements = ""
-
-[auth.rate_limit]
-# Number of emails that can be sent per hour. Requires auth.email.smtp to be enabled.
-email_sent = 2
-# Number of SMS messages that can be sent per hour. Requires auth.sms to be enabled.
-sms_sent = 30
-# Number of anonymous sign-ins that can be made per hour per IP address. Requires enable_anonymous_sign_ins = true.
-anonymous_users = 30
-# Number of sessions that can be refreshed in a 5 minute interval per IP address.
-token_refresh = 150
-# Number of sign up and sign-in requests that can be made in a 5 minute interval per IP address (excludes anonymous users).
-sign_in_sign_ups = 30
-# Number of OTP / Magic link verifications that can be made in a 5 minute interval per IP address.
-token_verifications = 30
-# Number of Web3 logins that can be made in a 5 minute interval per IP address.
-web3 = 30
-
-# Configure one of the supported captcha providers: `hcaptcha`, `turnstile`.
-# [auth.captcha]
-# enabled = true
-# provider = "hcaptcha"
-# secret = ""
-
-[auth.email]
-# Allow/disallow new user signups via email to your project.
-enable_signup = true
-# If enabled, a user will be required to confirm any email change on both the old, and new email
-# addresses. If disabled, only the new email is required to confirm.
-double_confirm_changes = true
-# If enabled, users need to confirm their email address before signing in.
-enable_confirmations = false
-# If enabled, users will need to reauthenticate or have logged in recently to change their password.
-secure_password_change = false
-# Controls the minimum amount of time that must pass before sending another signup confirmation or password reset email.
-max_frequency = "1s"
-# Number of characters used in the email OTP.
-otp_length = 6
-# Number of seconds before the email OTP expires (defaults to 1 hour).
-otp_expiry = 3600
-
-# Use a production-ready SMTP server
-# [auth.email.smtp]
-# enabled = true
-# host = "smtp.sendgrid.net"
-# port = 587
-# user = "apikey"
-# pass = "env(SENDGRID_API_KEY)"
-# admin_email = "admin@email.com"
-# sender_name = "Admin"
-
-# Uncomment to customize email template
-# [auth.email.template.invite]
-# subject = "You have been invited"
-# content_path = "./supabase/templates/invite.html"
-
-[auth.sms]
-# Allow/disallow new user signups via SMS to your project.
-enable_signup = false
-# If enabled, users need to confirm their phone number before signing in.
-enable_confirmations = false
-# Template for sending OTP to users
-template = "Your code is {{ .Code }}"
-# Controls the minimum amount of time that must pass before sending another sms otp.
-max_frequency = "5s"
-
-# Use pre-defined map of phone number to OTP for testing.
-# [auth.sms.test_otp]
-# 4152127777 = "123456"
-
-# Configure logged in session timeouts.
-# [auth.sessions]
-# Force log out after the specified duration.
-# timebox = "24h"
-# Force log out if the user has been inactive longer than the specified duration.
-# inactivity_timeout = "8h"
-
-# This hook runs before a new user is created and allows developers to reject the request based on the incoming user object.
-# [auth.hook.before_user_created]
-# enabled = true
-# uri = "pg-functions://postgres/auth/before-user-created-hook"
-
-# This hook runs before a token is issued and allows you to add additional claims based on the authentication method used.
-# [auth.hook.custom_access_token]
-# enabled = true
-# uri = "pg-functions:////"
-
-# Configure one of the supported SMS providers: `twilio`, `twilio_verify`, `messagebird`, `textlocal`, `vonage`.
-[auth.sms.twilio]
-enabled = false
-account_sid = ""
-message_service_sid = ""
-# DO NOT commit your Twilio auth token to git. Use environment variable substitution instead:
-auth_token = "env(SUPABASE_AUTH_SMS_TWILIO_AUTH_TOKEN)"
-
-# Multi-factor-authentication is available to Supabase Pro plan.
-[auth.mfa]
-# Control how many MFA factors can be enrolled at once per user.
-max_enrolled_factors = 10
-
-# Control MFA via App Authenticator (TOTP)
-[auth.mfa.totp]
-enroll_enabled = false
-verify_enabled = false
-
-# Configure MFA via Phone Messaging
-[auth.mfa.phone]
-enroll_enabled = false
-verify_enabled = false
-otp_length = 6
-template = "Your code is {{ .Code }}"
-max_frequency = "5s"
-
-# Configure MFA via WebAuthn
-# [auth.mfa.web_authn]
-# enroll_enabled = true
-# verify_enabled = true
-
-# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`,
-# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin_oidc`, `notion`, `twitch`,
-# `twitter`, `slack`, `spotify`, `workos`, `zoom`.
-[auth.external.apple]
-enabled = false
-client_id = ""
-# DO NOT commit your OAuth provider secret to git. Use environment variable substitution instead:
-secret = "env(SUPABASE_AUTH_EXTERNAL_APPLE_SECRET)"
-# Overrides the default auth redirectUrl.
-redirect_uri = ""
-# Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure,
-# or any other third-party OIDC providers.
-url = ""
-# If enabled, the nonce check will be skipped. Required for local sign in with Google auth.
-skip_nonce_check = false
-
-# Allow Solana wallet holders to sign in to your project via the Sign in with Solana (SIWS, EIP-4361) standard.
-# You can configure "web3" rate limit in the [auth.rate_limit] section and set up [auth.captcha] if self-hosting.
-[auth.web3.solana]
-enabled = false
-
-# Use Firebase Auth as a third-party provider alongside Supabase Auth.
-[auth.third_party.firebase]
-enabled = false
-# project_id = "my-firebase-project"
-
-# Use Auth0 as a third-party provider alongside Supabase Auth.
-[auth.third_party.auth0]
-enabled = false
-# tenant = "my-auth0-tenant"
-# tenant_region = "us"
-
-# Use AWS Cognito (Amplify) as a third-party provider alongside Supabase Auth.
-[auth.third_party.aws_cognito]
-enabled = false
-# user_pool_id = "my-user-pool-id"
-# user_pool_region = "us-east-1"
-
-# Use Clerk as a third-party provider alongside Supabase Auth.
-[auth.third_party.clerk]
-enabled = false
-# Obtain from https://clerk.com/setup/supabase
-# domain = "example.clerk.accounts.dev"
-
-[edge_runtime]
-enabled = true
-# Configure one of the supported request policies: `oneshot`, `per_worker`.
-# Use `oneshot` for hot reload, or `per_worker` for load testing.
-policy = "oneshot"
-# Port to attach the Chrome inspector for debugging edge functions.
-inspector_port = 8083
-# The Deno major version to use.
-deno_version = 1
-
-# [edge_runtime.secrets]
-# secret_key = "env(SECRET_VALUE)"
-
-[analytics]
-enabled = true
-port = 54327
-# Configure one of the supported backends: `postgres`, `bigquery`.
-backend = "postgres"
-
-# Experimental features may be deprecated any time
-[experimental]
-# Configures Postgres storage engine to use OrioleDB (S3)
-orioledb_version = ""
-# Configures S3 bucket URL, eg. .s3-.amazonaws.com
-s3_host = "env(S3_HOST)"
-# Configures S3 bucket region, eg. us-east-1
-s3_region = "env(S3_REGION)"
-# Configures AWS_ACCESS_KEY_ID for S3 bucket
-s3_access_key = "env(S3_ACCESS_KEY)"
-# Configures AWS_SECRET_ACCESS_KEY for S3 bucket
-s3_secret_key = "env(S3_SECRET_KEY)"
diff --git a/supabase/migrations/20250717153538_setup_rbac.sql b/supabase/migrations/20250717153538_setup_rbac.sql
deleted file mode 100644
index 690e4e3..0000000
--- a/supabase/migrations/20250717153538_setup_rbac.sql
+++ /dev/null
@@ -1,102 +0,0 @@
--- Create roles table
-CREATE TABLE IF NOT EXISTS public.roles (
- id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
- name VARCHAR(50) UNIQUE NOT NULL,
- description TEXT,
- created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
- updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
-);
-
--- Create user profiles table
-CREATE TABLE IF NOT EXISTS public.user_profiles (
- id UUID REFERENCES auth.users(id) ON DELETE CASCADE PRIMARY KEY,
- first_name VARCHAR(100),
- last_name VARCHAR(100),
- created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
- updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
-);
-
--- Create user roles junction table
-CREATE TABLE IF NOT EXISTS public.user_roles (
- id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
- user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
- role_id UUID REFERENCES public.roles(id) ON DELETE CASCADE,
- assigned_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
- assigned_by UUID REFERENCES auth.users(id),
- UNIQUE(user_id, role_id)
-);
-
--- Insert default roles
-INSERT INTO public.roles (name, description) VALUES
- ('admin', 'Administrator with full system access'),
- ('user', 'Regular user with basic access'),
- ('moderator', 'Moderator with limited administrative access')
-ON CONFLICT (name) DO NOTHING;
-
--- Enable RLS on all tables
-ALTER TABLE public.roles ENABLE ROW LEVEL SECURITY;
-ALTER TABLE public.user_profiles ENABLE ROW LEVEL SECURITY;
-ALTER TABLE public.user_roles ENABLE ROW LEVEL SECURITY;
-
--- Roles table policies
-CREATE POLICY "Anyone can view roles" ON public.roles FOR SELECT USING (true);
-
-CREATE POLICY "Only admins can manage roles" ON public.roles FOR ALL USING (
- EXISTS (
- SELECT 1 FROM public.user_roles ur
- JOIN public.roles r ON ur.role_id = r.id
- WHERE ur.user_id = auth.uid() AND r.name = 'admin'
- )
-);
-
--- User profiles policies
-CREATE POLICY "Users can view their own profile" ON public.user_profiles FOR SELECT USING (auth.uid() = id);
-
-CREATE POLICY "Users can update their own profile" ON public.user_profiles FOR UPDATE USING (auth.uid() = id);
-
-CREATE POLICY "Users can insert their own profile" ON public.user_profiles FOR INSERT WITH CHECK (auth.uid() = id);
-
-CREATE POLICY "Admins can view all profiles" ON public.user_profiles FOR SELECT USING (
- EXISTS (
- SELECT 1 FROM public.user_roles ur
- JOIN public.roles r ON ur.role_id = r.id
- WHERE ur.user_id = auth.uid() AND r.name = 'admin'
- )
-);
-
--- User roles policies
-CREATE POLICY "Users can view their own roles" ON public.user_roles FOR SELECT USING (auth.uid() = user_id);
-
-CREATE POLICY "Admins can manage all user roles" ON public.user_roles FOR ALL USING (
- EXISTS (
- SELECT 1 FROM public.user_roles ur
- JOIN public.roles r ON ur.role_id = r.id
- WHERE ur.user_id = auth.uid() AND r.name = 'admin'
- )
-);
-
--- Function to get user roles
-CREATE OR REPLACE FUNCTION get_user_roles(user_uuid UUID)
-RETURNS TABLE(role_name VARCHAR(50))
-LANGUAGE sql
-SECURITY DEFINER
-AS $$
- SELECT r.name
- FROM public.user_roles ur
- JOIN public.roles r ON ur.role_id = r.id
- WHERE ur.user_id = user_uuid;
-$$;
-
--- Function to check if user has specific role
-CREATE OR REPLACE FUNCTION user_has_role(user_uuid UUID, role_name VARCHAR(50))
-RETURNS BOOLEAN
-LANGUAGE sql
-SECURITY DEFINER
-AS $$
- SELECT EXISTS (
- SELECT 1
- FROM public.user_roles ur
- JOIN public.roles r ON ur.role_id = r.id
- WHERE ur.user_id = user_uuid AND r.name = role_name
- );
-$$;
\ No newline at end of file