mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
Update
This commit is contained in:
1 parent
358c2be0ee
commit
b10eae1bf3
26 files changed
+2509
-53
No files matched your search
@@ -0,0 +1,69 @@
|
||||
-- Admin Role-Based Access Control
|
||||
-- Creates admin_users table and helper functions for role management
|
||||
|
||||
-- Create admin role enum
|
||||
CREATE TYPE public.admin_role AS ENUM ('pack_creator', 'super_admin');
|
||||
|
||||
-- Admin users table (tracks which auth.users are admins and their role)
|
||||
CREATE TABLE public.admin_users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL UNIQUE REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
role public.admin_role NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
created_by UUID REFERENCES auth.users(id),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Index for quick lookups
|
||||
CREATE INDEX idx_admin_users_user_id ON public.admin_users(user_id);
|
||||
CREATE INDEX idx_admin_users_role ON public.admin_users(role);
|
||||
|
||||
-- Updated_at trigger
|
||||
CREATE TRIGGER update_admin_users_updated_at
|
||||
BEFORE UPDATE ON public.admin_users
|
||||
FOR EACH ROW EXECUTE FUNCTION public.update_updated_at();
|
||||
|
||||
-- Enable RLS
|
||||
ALTER TABLE public.admin_users ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Policy: Allow admins to read their own record
|
||||
CREATE POLICY "Admin users can read own record"
|
||||
ON public.admin_users FOR SELECT
|
||||
USING (auth.uid() = user_id);
|
||||
|
||||
-- Helper function to check if user is admin
|
||||
CREATE OR REPLACE FUNCTION public.is_admin(check_user_id UUID DEFAULT auth.uid())
|
||||
RETURNS BOOLEAN AS $$
|
||||
BEGIN
|
||||
RETURN EXISTS (
|
||||
SELECT 1 FROM public.admin_users WHERE user_id = check_user_id
|
||||
);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql SECURITY DEFINER STABLE;
|
||||
|
||||
-- Helper function to get admin role
|
||||
CREATE OR REPLACE FUNCTION public.get_admin_role(check_user_id UUID DEFAULT auth.uid())
|
||||
RETURNS public.admin_role AS $$
|
||||
DECLARE
|
||||
user_role public.admin_role;
|
||||
BEGIN
|
||||
SELECT role INTO user_role FROM public.admin_users WHERE user_id = check_user_id;
|
||||
RETURN user_role;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql SECURITY DEFINER STABLE;
|
||||
|
||||
-- Helper function to check if user is super admin
|
||||
CREATE OR REPLACE FUNCTION public.is_super_admin(check_user_id UUID DEFAULT auth.uid())
|
||||
RETURNS BOOLEAN AS $$
|
||||
BEGIN
|
||||
RETURN EXISTS (
|
||||
SELECT 1 FROM public.admin_users
|
||||
WHERE user_id = check_user_id AND role = 'super_admin'
|
||||
);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql SECURITY DEFINER STABLE;
|
||||
|
||||
-- Grant execute permissions on helper functions
|
||||
GRANT EXECUTE ON FUNCTION public.is_admin TO authenticated;
|
||||
GRANT EXECUTE ON FUNCTION public.get_admin_role TO authenticated;
|
||||
GRANT EXECUTE ON FUNCTION public.is_super_admin TO authenticated;
|
||||
@@ -0,0 +1,81 @@
|
||||
-- Audit Logging System
|
||||
-- Creates audit_logs table and RPC function for logging admin actions
|
||||
|
||||
-- Create action type enum for audit logging
|
||||
CREATE TYPE public.audit_action AS ENUM ('INSERT', 'UPDATE', 'DELETE');
|
||||
|
||||
-- Audit log table
|
||||
CREATE TABLE public.audit_logs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
table_name TEXT NOT NULL,
|
||||
record_id UUID NOT NULL,
|
||||
action public.audit_action NOT NULL,
|
||||
old_values JSONB,
|
||||
new_values JSONB,
|
||||
changed_fields TEXT[],
|
||||
admin_user_id UUID NOT NULL REFERENCES auth.users(id),
|
||||
admin_role public.admin_role NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Indexes for querying audit logs
|
||||
CREATE INDEX idx_audit_logs_table_name ON public.audit_logs(table_name);
|
||||
CREATE INDEX idx_audit_logs_record_id ON public.audit_logs(record_id);
|
||||
CREATE INDEX idx_audit_logs_admin_user_id ON public.audit_logs(admin_user_id);
|
||||
CREATE INDEX idx_audit_logs_created_at ON public.audit_logs(created_at DESC);
|
||||
CREATE INDEX idx_audit_logs_action ON public.audit_logs(action);
|
||||
|
||||
-- Enable RLS (super_admins only can view logs)
|
||||
ALTER TABLE public.audit_logs ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Policy: Only super admins can view audit logs
|
||||
CREATE POLICY "Super admins can view audit logs"
|
||||
ON public.audit_logs FOR SELECT
|
||||
USING (public.is_super_admin());
|
||||
|
||||
-- Function to log admin actions (called from frontend via RPC)
|
||||
CREATE OR REPLACE FUNCTION public.log_admin_action(
|
||||
p_table_name TEXT,
|
||||
p_record_id UUID,
|
||||
p_action public.audit_action,
|
||||
p_old_values JSONB DEFAULT NULL,
|
||||
p_new_values JSONB DEFAULT NULL
|
||||
)
|
||||
RETURNS UUID AS $$
|
||||
DECLARE
|
||||
log_id UUID;
|
||||
admin_role_val public.admin_role;
|
||||
changed_fields_arr TEXT[];
|
||||
BEGIN
|
||||
-- Get admin role
|
||||
SELECT role INTO admin_role_val FROM public.admin_users WHERE user_id = auth.uid();
|
||||
|
||||
IF admin_role_val IS NULL THEN
|
||||
RAISE EXCEPTION 'User is not an admin';
|
||||
END IF;
|
||||
|
||||
-- Calculate changed fields for updates
|
||||
IF p_action = 'UPDATE' AND p_old_values IS NOT NULL AND p_new_values IS NOT NULL THEN
|
||||
SELECT ARRAY(
|
||||
SELECT key FROM jsonb_each(p_new_values)
|
||||
WHERE p_old_values->key IS DISTINCT FROM p_new_values->key
|
||||
) INTO changed_fields_arr;
|
||||
END IF;
|
||||
|
||||
-- Insert audit log
|
||||
INSERT INTO public.audit_logs (
|
||||
table_name, record_id, action, old_values, new_values,
|
||||
changed_fields, admin_user_id, admin_role
|
||||
)
|
||||
VALUES (
|
||||
p_table_name, p_record_id, p_action, p_old_values, p_new_values,
|
||||
changed_fields_arr, auth.uid(), admin_role_val
|
||||
)
|
||||
RETURNING id INTO log_id;
|
||||
|
||||
RETURN log_id;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
||||
|
||||
-- Grant execute permission on logging function
|
||||
GRANT EXECUTE ON FUNCTION public.log_admin_action TO authenticated;
|
||||
@@ -0,0 +1,79 @@
|
||||
-- Admin RLS Policies
|
||||
-- Adds policies for admin access to tables
|
||||
|
||||
-- Question Packs: All admins can manage (CRUD)
|
||||
CREATE POLICY "Admins can view all question packs"
|
||||
ON public.question_packs FOR SELECT
|
||||
USING (public.is_admin());
|
||||
|
||||
CREATE POLICY "Admins can insert question packs"
|
||||
ON public.question_packs FOR INSERT
|
||||
WITH CHECK (public.is_admin());
|
||||
|
||||
CREATE POLICY "Admins can update question packs"
|
||||
ON public.question_packs FOR UPDATE
|
||||
USING (public.is_admin());
|
||||
|
||||
CREATE POLICY "Admins can delete question packs"
|
||||
ON public.question_packs FOR DELETE
|
||||
USING (public.is_admin());
|
||||
|
||||
-- Questions: All admins can manage (CRUD)
|
||||
CREATE POLICY "Admins can view all questions"
|
||||
ON public.questions FOR SELECT
|
||||
USING (public.is_admin());
|
||||
|
||||
CREATE POLICY "Admins can insert questions"
|
||||
ON public.questions FOR INSERT
|
||||
WITH CHECK (public.is_admin());
|
||||
|
||||
CREATE POLICY "Admins can update questions"
|
||||
ON public.questions FOR UPDATE
|
||||
USING (public.is_admin());
|
||||
|
||||
CREATE POLICY "Admins can delete questions"
|
||||
ON public.questions FOR DELETE
|
||||
USING (public.is_admin());
|
||||
|
||||
-- Profiles: Super admins can view and update all
|
||||
CREATE POLICY "Super admins can view all profiles"
|
||||
ON public.profiles FOR SELECT
|
||||
USING (public.is_super_admin());
|
||||
|
||||
CREATE POLICY "Super admins can update all profiles"
|
||||
ON public.profiles FOR UPDATE
|
||||
USING (public.is_super_admin());
|
||||
|
||||
-- Couples: Super admins can view all
|
||||
CREATE POLICY "Super admins can view all couples"
|
||||
ON public.couples FOR SELECT
|
||||
USING (public.is_super_admin());
|
||||
|
||||
-- Responses: Super admins can view all
|
||||
CREATE POLICY "Super admins can view all responses"
|
||||
ON public.responses FOR SELECT
|
||||
USING (public.is_super_admin());
|
||||
|
||||
-- Matches: Super admins can view all
|
||||
CREATE POLICY "Super admins can view all matches"
|
||||
ON public.matches FOR SELECT
|
||||
USING (public.is_super_admin());
|
||||
|
||||
-- Messages: Super admins can view all
|
||||
CREATE POLICY "Super admins can view all messages"
|
||||
ON public.messages FOR SELECT
|
||||
USING (public.is_super_admin());
|
||||
|
||||
-- Subscriptions: Super admins can view all
|
||||
CREATE POLICY "Super admins can view all subscriptions"
|
||||
ON public.subscriptions FOR SELECT
|
||||
USING (public.is_super_admin());
|
||||
|
||||
-- Feedback: Super admins can view and manage all
|
||||
CREATE POLICY "Super admins can view all feedback"
|
||||
ON public.feedback FOR SELECT
|
||||
USING (public.is_super_admin());
|
||||
|
||||
CREATE POLICY "Super admins can update all feedback"
|
||||
ON public.feedback FOR UPDATE
|
||||
USING (public.is_super_admin());
|
||||
Reference in new issue
Block a user