Update environment configuration and enhance user management features

- Changed VITE_SUPABASE_URL in .env.example for deployment consistency.
- Added new user management functionality to reset user passwords in UserManagement component.
- Updated supabase.ts to include first and last name fields in user profiles and added password reset functionality.
- Enhanced DashboardLayout to include a user profile view and improved user display in TopNavbar.
- Updated seed.sql to create additional users with roles for testing purposes.
This commit is contained in:
salirezav
2025-09-22 11:20:15 -04:00
parent 0ba385eebc
commit 44c8c3f6dd
23 changed files with 1398 additions and 31 deletions

View File

@@ -1 +1 @@
v2.34.3
v2.40.7

View File

@@ -81,7 +81,7 @@ 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"
api_url = "http://exp-dash"
# OpenAI API Key to use for Supabase AI in the Supabase Studio.
openai_api_key = "env(OPENAI_API_KEY)"
@@ -117,9 +117,9 @@ file_size_limit = "50MiB"
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"
site_url = "http://exp-dash: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"]
additional_redirect_urls = ["https://exp-dash: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.

View File

@@ -0,0 +1,341 @@
-- Add Conductor Availability and Experiment Phase Assignment Tables
-- This migration adds tables for conductor availability management and future experiment scheduling
-- =============================================
-- 1. CONDUCTOR AVAILABILITY TABLE
-- =============================================
-- Create conductor_availability table
CREATE TABLE IF NOT EXISTS public.conductor_availability (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES public.user_profiles(id) ON DELETE CASCADE,
available_from TIMESTAMP WITH TIME ZONE NOT NULL,
available_to TIMESTAMP WITH TIME ZONE NOT NULL,
notes TEXT, -- Optional notes about the availability
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'cancelled')),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
created_by UUID NOT NULL REFERENCES public.user_profiles(id),
-- Ensure available_to is after available_from
CONSTRAINT valid_time_range CHECK (available_to > available_from),
-- Ensure availability is in the future (can be modified if needed for past records)
CONSTRAINT future_availability CHECK (available_from >= NOW() - INTERVAL '1 day')
);
-- =============================================
-- 2. EXPERIMENT PHASE ASSIGNMENTS TABLE (Future Scheduling)
-- =============================================
-- Create experiment_phase_assignments table for scheduling conductors to experiment phases
CREATE TABLE IF NOT EXISTS public.experiment_phase_assignments (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
experiment_id UUID NOT NULL REFERENCES public.experiments(id) ON DELETE CASCADE,
repetition_id UUID NOT NULL REFERENCES public.experiment_repetitions(id) ON DELETE CASCADE,
conductor_id UUID NOT NULL REFERENCES public.user_profiles(id) ON DELETE CASCADE,
phase_name TEXT NOT NULL CHECK (phase_name IN ('pre-soaking', 'air-drying', 'cracking', 'shelling')),
scheduled_start_time TIMESTAMP WITH TIME ZONE NOT NULL,
scheduled_end_time TIMESTAMP WITH TIME ZONE NOT NULL,
status TEXT NOT NULL DEFAULT 'scheduled' CHECK (status IN ('scheduled', 'in-progress', 'completed', 'cancelled')),
notes TEXT, -- Optional notes about the assignment
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
created_by UUID NOT NULL REFERENCES public.user_profiles(id),
-- Ensure scheduled_end_time is after scheduled_start_time
CONSTRAINT valid_scheduled_time_range CHECK (scheduled_end_time > scheduled_start_time),
-- Ensure unique assignment per conductor per phase per repetition
CONSTRAINT unique_conductor_phase_assignment UNIQUE (repetition_id, conductor_id, phase_name)
);
-- =============================================
-- 3. INDEXES FOR PERFORMANCE
-- =============================================
-- Conductor availability indexes
CREATE INDEX IF NOT EXISTS idx_conductor_availability_user_id ON public.conductor_availability(user_id);
CREATE INDEX IF NOT EXISTS idx_conductor_availability_available_from ON public.conductor_availability(available_from);
CREATE INDEX IF NOT EXISTS idx_conductor_availability_available_to ON public.conductor_availability(available_to);
CREATE INDEX IF NOT EXISTS idx_conductor_availability_status ON public.conductor_availability(status);
CREATE INDEX IF NOT EXISTS idx_conductor_availability_created_by ON public.conductor_availability(created_by);
CREATE INDEX IF NOT EXISTS idx_conductor_availability_time_range ON public.conductor_availability(available_from, available_to);
-- Experiment phase assignments indexes
CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_experiment_id ON public.experiment_phase_assignments(experiment_id);
CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_repetition_id ON public.experiment_phase_assignments(repetition_id);
CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_conductor_id ON public.experiment_phase_assignments(conductor_id);
CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_phase_name ON public.experiment_phase_assignments(phase_name);
CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_status ON public.experiment_phase_assignments(status);
CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_scheduled_start ON public.experiment_phase_assignments(scheduled_start_time);
CREATE INDEX IF NOT EXISTS idx_experiment_phase_assignments_created_by ON public.experiment_phase_assignments(created_by);
-- =============================================
-- 4. FUNCTIONS FOR OVERLAP PREVENTION
-- =============================================
-- Function to check for overlapping availabilities
CREATE OR REPLACE FUNCTION public.check_availability_overlap()
RETURNS TRIGGER AS $$
DECLARE
overlap_count INTEGER;
BEGIN
-- Check for overlapping availabilities for the same user
SELECT COUNT(*) INTO overlap_count
FROM public.conductor_availability
WHERE user_id = NEW.user_id
AND id != COALESCE(NEW.id, '00000000-0000-0000-0000-000000000000'::UUID)
AND status = 'active'
AND (
-- New availability starts during an existing one
(NEW.available_from >= available_from AND NEW.available_from < available_to) OR
-- New availability ends during an existing one
(NEW.available_to > available_from AND NEW.available_to <= available_to) OR
-- New availability completely contains an existing one
(NEW.available_from <= available_from AND NEW.available_to >= available_to) OR
-- Existing availability completely contains the new one
(available_from <= NEW.available_from AND available_to >= NEW.available_to)
);
IF overlap_count > 0 THEN
RAISE EXCEPTION 'Availability overlaps with existing availability for user %. Please adjust the time range or cancel the conflicting availability.', NEW.user_id;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Function to automatically adjust overlapping availabilities (alternative approach)
CREATE OR REPLACE FUNCTION public.adjust_overlapping_availability()
RETURNS TRIGGER AS $$
DECLARE
overlapping_record RECORD;
BEGIN
-- Find overlapping availabilities and adjust them
FOR overlapping_record IN
SELECT id, available_from, available_to
FROM public.conductor_availability
WHERE user_id = NEW.user_id
AND id != COALESCE(NEW.id, '00000000-0000-0000-0000-000000000000'::UUID)
AND status = 'active'
AND (
(NEW.available_from >= available_from AND NEW.available_from < available_to) OR
(NEW.available_to > available_from AND NEW.available_to <= available_to) OR
(NEW.available_from <= available_from AND NEW.available_to >= available_to) OR
(available_from <= NEW.available_from AND available_to >= NEW.available_to)
)
LOOP
-- Adjust the overlapping record to end where the new one starts
IF overlapping_record.available_from < NEW.available_from AND overlapping_record.available_to > NEW.available_from THEN
UPDATE public.conductor_availability
SET available_to = NEW.available_from,
updated_at = NOW()
WHERE id = overlapping_record.id;
END IF;
-- If the overlapping record starts after the new one, adjust it to start where the new one ends
IF overlapping_record.available_from < NEW.available_to AND overlapping_record.available_to > NEW.available_to THEN
UPDATE public.conductor_availability
SET available_from = NEW.available_to,
updated_at = NOW()
WHERE id = overlapping_record.id;
END IF;
-- If the overlapping record is completely contained within the new one, cancel it
IF overlapping_record.available_from >= NEW.available_from AND overlapping_record.available_to <= NEW.available_to THEN
UPDATE public.conductor_availability
SET status = 'cancelled',
updated_at = NOW()
WHERE id = overlapping_record.id;
END IF;
END LOOP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- =============================================
-- 5. TRIGGERS
-- =============================================
-- Create trigger for updated_at on conductor_availability
CREATE TRIGGER set_updated_at_conductor_availability
BEFORE UPDATE ON public.conductor_availability
FOR EACH ROW
EXECUTE FUNCTION public.handle_updated_at();
-- Create trigger for updated_at on experiment_phase_assignments
CREATE TRIGGER set_updated_at_experiment_phase_assignments
BEFORE UPDATE ON public.experiment_phase_assignments
FOR EACH ROW
EXECUTE FUNCTION public.handle_updated_at();
-- Create trigger to prevent overlapping availabilities (strict approach)
CREATE TRIGGER trigger_check_availability_overlap
BEFORE INSERT OR UPDATE ON public.conductor_availability
FOR EACH ROW
EXECUTE FUNCTION public.check_availability_overlap();
-- Alternative trigger to automatically adjust overlapping availabilities (uncomment if preferred)
-- CREATE TRIGGER trigger_adjust_overlapping_availability
-- BEFORE INSERT OR UPDATE ON public.conductor_availability
-- FOR EACH ROW
-- EXECUTE FUNCTION public.adjust_overlapping_availability();
-- =============================================
-- 6. HELPER FUNCTIONS
-- =============================================
-- Function to get available conductors for a specific time range
CREATE OR REPLACE FUNCTION public.get_available_conductors(
start_time TIMESTAMP WITH TIME ZONE,
end_time TIMESTAMP WITH TIME ZONE
)
RETURNS TABLE (
user_id UUID,
email TEXT,
available_from TIMESTAMP WITH TIME ZONE,
available_to TIMESTAMP WITH TIME ZONE
) AS $$
BEGIN
RETURN QUERY
SELECT
ca.user_id,
up.email,
ca.available_from,
ca.available_to
FROM public.conductor_availability ca
JOIN public.user_profiles up ON ca.user_id = up.id
JOIN public.user_roles ur ON up.id = ur.user_id
JOIN public.roles r ON ur.role_id = r.id
WHERE ca.status = 'active'
AND r.name = 'conductor'
AND ca.available_from <= start_time
AND ca.available_to >= end_time
ORDER BY up.email;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Function to check if a conductor is available for a specific time range
CREATE OR REPLACE FUNCTION public.is_conductor_available(
conductor_user_id UUID,
start_time TIMESTAMP WITH TIME ZONE,
end_time TIMESTAMP WITH TIME ZONE
)
RETURNS BOOLEAN AS $$
DECLARE
availability_count INTEGER;
BEGIN
SELECT COUNT(*) INTO availability_count
FROM public.conductor_availability
WHERE user_id = conductor_user_id
AND status = 'active'
AND available_from <= start_time
AND available_to >= end_time;
RETURN availability_count > 0;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- =============================================
-- 7. ROW LEVEL SECURITY (RLS)
-- =============================================
-- Enable RLS on new tables
ALTER TABLE public.conductor_availability ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.experiment_phase_assignments ENABLE ROW LEVEL SECURITY;
-- Conductor availability policies
CREATE POLICY "conductor_availability_select_policy" ON public.conductor_availability
FOR SELECT
TO authenticated
USING (
-- Users can view their own availability, admins can view all
user_id = auth.uid() OR public.is_admin()
);
CREATE POLICY "conductor_availability_insert_policy" ON public.conductor_availability
FOR INSERT
TO authenticated
WITH CHECK (
-- Users can create their own availability, admins can create for anyone
(user_id = auth.uid() AND created_by = auth.uid()) OR public.is_admin()
);
CREATE POLICY "conductor_availability_update_policy" ON public.conductor_availability
FOR UPDATE
TO authenticated
USING (
-- Users can update their own availability, admins can update any
user_id = auth.uid() OR public.is_admin()
)
WITH CHECK (
-- Users can update their own availability, admins can update any
user_id = auth.uid() OR public.is_admin()
);
CREATE POLICY "conductor_availability_delete_policy" ON public.conductor_availability
FOR DELETE
TO authenticated
USING (
-- Users can delete their own availability, admins can delete any
user_id = auth.uid() OR public.is_admin()
);
-- Experiment phase assignments policies
CREATE POLICY "experiment_phase_assignments_select_policy" ON public.experiment_phase_assignments
FOR SELECT
TO authenticated
USING (
-- Conductors can view their own assignments, admins can view all
conductor_id = auth.uid() OR public.is_admin()
);
CREATE POLICY "experiment_phase_assignments_insert_policy" ON public.experiment_phase_assignments
FOR INSERT
TO authenticated
WITH CHECK (
-- Only admins and conductors can create assignments
public.can_manage_experiments()
);
CREATE POLICY "experiment_phase_assignments_update_policy" ON public.experiment_phase_assignments
FOR UPDATE
TO authenticated
USING (
-- Conductors can update their own assignments, admins can update any
conductor_id = auth.uid() OR public.is_admin()
)
WITH CHECK (
-- Conductors can update their own assignments, admins can update any
conductor_id = auth.uid() OR public.is_admin()
);
CREATE POLICY "experiment_phase_assignments_delete_policy" ON public.experiment_phase_assignments
FOR DELETE
TO authenticated
USING (
-- Only admins can delete assignments
public.is_admin()
);
-- =============================================
-- 8. COMMENTS FOR DOCUMENTATION
-- =============================================
COMMENT ON TABLE public.conductor_availability IS 'Stores conductor availability windows for experiment scheduling';
COMMENT ON TABLE public.experiment_phase_assignments IS 'Assigns conductors to specific experiment repetition phases with scheduled times';
COMMENT ON COLUMN public.conductor_availability.available_from IS 'Start time of availability window';
COMMENT ON COLUMN public.conductor_availability.available_to IS 'End time of availability window';
COMMENT ON COLUMN public.conductor_availability.notes IS 'Optional notes about the availability period';
COMMENT ON COLUMN public.conductor_availability.status IS 'Status of the availability (active or cancelled)';
COMMENT ON COLUMN public.experiment_phase_assignments.phase_name IS 'Experiment phase being assigned (pre-soaking, air-drying, cracking, shelling)';
COMMENT ON COLUMN public.experiment_phase_assignments.scheduled_start_time IS 'Planned start time for the phase';
COMMENT ON COLUMN public.experiment_phase_assignments.scheduled_end_time IS 'Planned end time for the phase';
COMMENT ON COLUMN public.experiment_phase_assignments.status IS 'Current status of the assignment';
COMMENT ON COLUMN public.experiment_phase_assignments.notes IS 'Optional notes about the assignment';

View File

@@ -0,0 +1,49 @@
-- Add password reset function for admin use
-- This migration adds a function to reset user passwords back to the default "password123"
-- Function to reset user password (admin only)
CREATE OR REPLACE FUNCTION public.reset_user_password(
target_user_id UUID
)
RETURNS JSON AS $$
DECLARE
user_email TEXT;
result JSON;
BEGIN
-- Only admins can reset passwords
IF NOT public.is_admin() THEN
RAISE EXCEPTION 'Only administrators can reset user passwords';
END IF;
-- Check if target user exists
SELECT email INTO user_email
FROM public.user_profiles
WHERE id = target_user_id;
IF user_email IS NULL THEN
RAISE EXCEPTION 'User not found';
END IF;
-- Update the password in auth.users table
UPDATE auth.users
SET
encrypted_password = crypt('password123', gen_salt('bf')),
updated_at = NOW()
WHERE id = target_user_id;
-- Return result
result := json_build_object(
'user_id', target_user_id,
'email', user_email,
'new_password', 'password123',
'reset_at', NOW()
);
RETURN result;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

View File

@@ -0,0 +1,12 @@
-- Add first_name and last_name fields to user_profiles table
-- This migration adds name fields to store user's first and last names
-- Add first_name and last_name columns to user_profiles table
ALTER TABLE public.user_profiles
ADD COLUMN first_name TEXT,
ADD COLUMN last_name TEXT;
-- Add comments for documentation
COMMENT ON COLUMN public.user_profiles.first_name IS 'User first name';
COMMENT ON COLUMN public.user_profiles.last_name IS 'User last name';

View File

@@ -0,0 +1,62 @@
-- Add change password function for users
-- This migration adds a function to allow users to change their own password
-- Function to change user password (user can only change their own password)
CREATE OR REPLACE FUNCTION public.change_user_password(
current_password TEXT,
new_password TEXT
)
RETURNS JSON AS $$
DECLARE
user_id UUID;
user_email TEXT;
result JSON;
BEGIN
-- Get current user ID
user_id := auth.uid();
IF user_id IS NULL THEN
RAISE EXCEPTION 'User not authenticated';
END IF;
-- Get user email
SELECT email INTO user_email
FROM public.user_profiles
WHERE id = user_id;
IF user_email IS NULL THEN
RAISE EXCEPTION 'User profile not found';
END IF;
-- Verify current password
IF NOT EXISTS (
SELECT 1
FROM auth.users
WHERE id = user_id
AND encrypted_password = crypt(current_password, encrypted_password)
) THEN
RAISE EXCEPTION 'Current password is incorrect';
END IF;
-- Update the password in auth.users table
UPDATE auth.users
SET
encrypted_password = crypt(new_password, gen_salt('bf')),
updated_at = NOW()
WHERE id = user_id;
-- Return result
result := json_build_object(
'user_id', user_id,
'email', user_email,
'password_changed_at', NOW()
);
RETURN result;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

View File

@@ -47,8 +47,8 @@ INSERT INTO auth.users (
);
-- Create user profile
INSERT INTO public.user_profiles (id, email, status)
SELECT id, email, 'active'
INSERT INTO public.user_profiles (id, email, first_name, last_name, status)
SELECT id, email, 'Alireza', 'Vaezi', 'active'
FROM auth.users
WHERE email = 's.alireza.v@gmail.com'
;
@@ -66,7 +66,443 @@ AND r.name = 'admin'
;
-- =============================================
-- 3. CREATE EXPERIMENT PHASES
-- 3. CREATE ADDITIONAL USERS
-- =============================================
-- Create Claire Floyd (Conductor & Data Recorder)
INSERT INTO auth.users (
instance_id,
id,
aud,
role,
email,
encrypted_password,
email_confirmed_at,
created_at,
updated_at,
confirmation_token,
email_change,
email_change_token_new,
recovery_token
) VALUES (
'00000000-0000-0000-0000-000000000000',
uuid_generate_v4(),
'authenticated',
'authenticated',
'Ashlyn.Floyd@uga.edu',
crypt('password123', gen_salt('bf')),
NOW(),
NOW(),
NOW(),
'',
'',
'',
''
);
INSERT INTO public.user_profiles (id, email, first_name, last_name, status)
SELECT id, email, 'Claire', 'Floyd', 'active'
FROM auth.users
WHERE email = 'Ashlyn.Floyd@uga.edu'
;
INSERT INTO public.user_roles (user_id, role_id, assigned_by)
SELECT
up.id,
r.id,
(SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')
FROM public.user_profiles up
CROSS JOIN public.roles r
WHERE up.email = 'Ashlyn.Floyd@uga.edu'
AND r.name IN ('conductor', 'data recorder')
;
-- Create Bruna Dos-Santos (Conductor & Data Recorder)
INSERT INTO auth.users (
instance_id,
id,
aud,
role,
email,
encrypted_password,
email_confirmed_at,
created_at,
updated_at,
confirmation_token,
email_change,
email_change_token_new,
recovery_token
) VALUES (
'00000000-0000-0000-0000-000000000000',
uuid_generate_v4(),
'authenticated',
'authenticated',
'bkvsantos@uga.edu',
crypt('password123', gen_salt('bf')),
NOW(),
NOW(),
NOW(),
'',
'',
'',
''
);
INSERT INTO public.user_profiles (id, email, first_name, last_name, status)
SELECT id, email, 'Bruna', 'Dos-Santos', 'active'
FROM auth.users
WHERE email = 'bkvsantos@uga.edu'
;
INSERT INTO public.user_roles (user_id, role_id, assigned_by)
SELECT
up.id,
r.id,
(SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')
FROM public.user_profiles up
CROSS JOIN public.roles r
WHERE up.email = 'bkvsantos@uga.edu'
AND r.name IN ('conductor', 'data recorder')
;
-- Create Beni Rodriguez (Conductor & Data Recorder)
INSERT INTO auth.users (
instance_id,
id,
aud,
role,
email,
encrypted_password,
email_confirmed_at,
created_at,
updated_at,
confirmation_token,
email_change,
email_change_token_new,
recovery_token
) VALUES (
'00000000-0000-0000-0000-000000000000',
uuid_generate_v4(),
'authenticated',
'authenticated',
'Beni.Rodriguez@uga.edu',
crypt('password123', gen_salt('bf')),
NOW(),
NOW(),
NOW(),
'',
'',
'',
''
);
INSERT INTO public.user_profiles (id, email, first_name, last_name, status)
SELECT id, email, 'Beni', 'Rodriguez', 'active'
FROM auth.users
WHERE email = 'Beni.Rodriguez@uga.edu'
;
INSERT INTO public.user_roles (user_id, role_id, assigned_by)
SELECT
up.id,
r.id,
(SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')
FROM public.user_profiles up
CROSS JOIN public.roles r
WHERE up.email = 'Beni.Rodriguez@uga.edu'
AND r.name IN ('conductor', 'data recorder')
;
-- Create Brendan Surio (Data Recorder)
INSERT INTO auth.users (
instance_id,
id,
aud,
role,
email,
encrypted_password,
email_confirmed_at,
created_at,
updated_at,
confirmation_token,
email_change,
email_change_token_new,
recovery_token
) VALUES (
'00000000-0000-0000-0000-000000000000',
uuid_generate_v4(),
'authenticated',
'authenticated',
'Brendan.Surio@uga.edu',
crypt('password123', gen_salt('bf')),
NOW(),
NOW(),
NOW(),
'',
'',
'',
''
);
INSERT INTO public.user_profiles (id, email, first_name, last_name, status)
SELECT id, email, 'Brendan', 'Surio', 'active'
FROM auth.users
WHERE email = 'Brendan.Surio@uga.edu'
;
INSERT INTO public.user_roles (user_id, role_id, assigned_by)
SELECT
up.id,
r.id,
(SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')
FROM public.user_profiles up
CROSS JOIN public.roles r
WHERE up.email = 'Brendan.Surio@uga.edu'
AND r.name = 'data recorder'
;
-- Create William Mcconnell (Data Recorder)
INSERT INTO auth.users (
instance_id,
id,
aud,
role,
email,
encrypted_password,
email_confirmed_at,
created_at,
updated_at,
confirmation_token,
email_change,
email_change_token_new,
recovery_token
) VALUES (
'00000000-0000-0000-0000-000000000000',
uuid_generate_v4(),
'authenticated',
'authenticated',
'William.McConnell@uga.edu',
crypt('password123', gen_salt('bf')),
NOW(),
NOW(),
NOW(),
'',
'',
'',
''
);
INSERT INTO public.user_profiles (id, email, first_name, last_name, status)
SELECT id, email, 'William', 'Mcconnell', 'active'
FROM auth.users
WHERE email = 'William.McConnell@uga.edu'
;
INSERT INTO public.user_roles (user_id, role_id, assigned_by)
SELECT
up.id,
r.id,
(SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')
FROM public.user_profiles up
CROSS JOIN public.roles r
WHERE up.email = 'William.McConnell@uga.edu'
AND r.name = 'data recorder'
;
-- Create Camille Deguzman (Data Recorder)
INSERT INTO auth.users (
instance_id,
id,
aud,
role,
email,
encrypted_password,
email_confirmed_at,
created_at,
updated_at,
confirmation_token,
email_change,
email_change_token_new,
recovery_token
) VALUES (
'00000000-0000-0000-0000-000000000000',
uuid_generate_v4(),
'authenticated',
'authenticated',
'cpd08598@uga.edu',
crypt('password123', gen_salt('bf')),
NOW(),
NOW(),
NOW(),
'',
'',
'',
''
);
INSERT INTO public.user_profiles (id, email, first_name, last_name, status)
SELECT id, email, 'Camille', 'Deguzman', 'active'
FROM auth.users
WHERE email = 'cpd08598@uga.edu'
;
INSERT INTO public.user_roles (user_id, role_id, assigned_by)
SELECT
up.id,
r.id,
(SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')
FROM public.user_profiles up
CROSS JOIN public.roles r
WHERE up.email = 'cpd08598@uga.edu'
AND r.name = 'data recorder'
;
-- Create Justin Hetzler (Data Recorder)
INSERT INTO auth.users (
instance_id,
id,
aud,
role,
email,
encrypted_password,
email_confirmed_at,
created_at,
updated_at,
confirmation_token,
email_change,
email_change_token_new,
recovery_token
) VALUES (
'00000000-0000-0000-0000-000000000000',
uuid_generate_v4(),
'authenticated',
'authenticated',
'Justin.Hetzler@uga.edu',
crypt('password123', gen_salt('bf')),
NOW(),
NOW(),
NOW(),
'',
'',
'',
''
);
INSERT INTO public.user_profiles (id, email, first_name, last_name, status)
SELECT id, email, 'Justin', 'Hetzler', 'active'
FROM auth.users
WHERE email = 'Justin.Hetzler@uga.edu'
;
INSERT INTO public.user_roles (user_id, role_id, assigned_by)
SELECT
up.id,
r.id,
(SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')
FROM public.user_profiles up
CROSS JOIN public.roles r
WHERE up.email = 'Justin.Hetzler@uga.edu'
AND r.name = 'data recorder'
;
-- Create Joshua Wilson (Data Recorder)
INSERT INTO auth.users (
instance_id,
id,
aud,
role,
email,
encrypted_password,
email_confirmed_at,
created_at,
updated_at,
confirmation_token,
email_change,
email_change_token_new,
recovery_token
) VALUES (
'00000000-0000-0000-0000-000000000000',
uuid_generate_v4(),
'authenticated',
'authenticated',
'jdw58940@uga.edu',
crypt('password123', gen_salt('bf')),
NOW(),
NOW(),
NOW(),
'',
'',
'',
''
);
INSERT INTO public.user_profiles (id, email, first_name, last_name, status)
SELECT id, email, 'Joshua', 'Wilson', 'active'
FROM auth.users
WHERE email = 'jdw58940@uga.edu'
;
INSERT INTO public.user_roles (user_id, role_id, assigned_by)
SELECT
up.id,
r.id,
(SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')
FROM public.user_profiles up
CROSS JOIN public.roles r
WHERE up.email = 'jdw58940@uga.edu'
AND r.name = 'data recorder'
;
-- Create Sydney Orlofsky (Data Recorder)
INSERT INTO auth.users (
instance_id,
id,
aud,
role,
email,
encrypted_password,
email_confirmed_at,
created_at,
updated_at,
confirmation_token,
email_change,
email_change_token_new,
recovery_token
) VALUES (
'00000000-0000-0000-0000-000000000000',
uuid_generate_v4(),
'authenticated',
'authenticated',
'Sydney.Orlofsky@uga.edu',
crypt('password123', gen_salt('bf')),
NOW(),
NOW(),
NOW(),
'',
'',
'',
''
);
INSERT INTO public.user_profiles (id, email, first_name, last_name, status)
SELECT id, email, 'Sydney', 'Orlofsky', 'active'
FROM auth.users
WHERE email = 'Sydney.Orlofsky@uga.edu'
;
INSERT INTO public.user_roles (user_id, role_id, assigned_by)
SELECT
up.id,
r.id,
(SELECT id FROM public.user_profiles WHERE email = 's.alireza.v@gmail.com')
FROM public.user_profiles up
CROSS JOIN public.roles r
WHERE up.email = 'Sydney.Orlofsky@uga.edu'
AND r.name = 'data recorder'
;
-- =============================================
-- 4. CREATE EXPERIMENT PHASES
-- =============================================
-- Create "Phase 2 of JC Experiments" phase
@@ -80,7 +516,7 @@ WHERE up.email = 's.alireza.v@gmail.com'
;
-- =============================================
-- 4. INSERT EXPERIMENTS (First 10 as example)
-- 5. INSERT EXPERIMENTS (First 10 as example)
-- =============================================
INSERT INTO public.experiments (
@@ -130,7 +566,7 @@ INSERT INTO public.experiments (
;
-- =============================================
-- 5. CREATE SAMPLE EXPERIMENT REPETITIONS
-- 6. CREATE SAMPLE EXPERIMENT REPETITIONS
-- =============================================
-- Create repetitions for first 5 experiments as examples