Migrations
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
-- Leave of Absence table
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'leave_type') THEN
|
||||
CREATE TYPE leave_type AS ENUM (
|
||||
'emergency_leave',
|
||||
'parental_leave',
|
||||
'sick_leave',
|
||||
'vacation_leave'
|
||||
);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'leave_status') THEN
|
||||
CREATE TYPE leave_status AS ENUM (
|
||||
'pending',
|
||||
'approved',
|
||||
'rejected',
|
||||
'cancelled'
|
||||
);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS leave_of_absence (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
leave_type leave_type NOT NULL,
|
||||
justification TEXT NOT NULL,
|
||||
start_time TIMESTAMPTZ NOT NULL,
|
||||
end_time TIMESTAMPTZ NOT NULL,
|
||||
status leave_status NOT NULL DEFAULT 'pending',
|
||||
filed_by UUID NOT NULL REFERENCES auth.users(id),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
|
||||
CONSTRAINT valid_time_range CHECK (end_time > start_time)
|
||||
);
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_leave_user_id ON leave_of_absence(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_leave_start_time ON leave_of_absence(start_time);
|
||||
CREATE INDEX IF NOT EXISTS idx_leave_status ON leave_of_absence(status);
|
||||
|
||||
-- RLS
|
||||
ALTER TABLE leave_of_absence ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
DROP POLICY IF EXISTS "Privileged users can view all leaves" ON leave_of_absence;
|
||||
DROP POLICY IF EXISTS "Users can view own leaves" ON leave_of_absence;
|
||||
DROP POLICY IF EXISTS "Privileged users can file own leaves" ON leave_of_absence;
|
||||
DROP POLICY IF EXISTS "Users can file own leaves" ON leave_of_absence;
|
||||
DROP POLICY IF EXISTS "Admins can approve or reject leaves" ON leave_of_absence;
|
||||
DROP POLICY IF EXISTS "Users can cancel own future approved leaves" ON leave_of_absence;
|
||||
DROP POLICY IF EXISTS "Admins can cancel future approved leaves" ON leave_of_absence;
|
||||
DROP POLICY IF EXISTS "Privileged users can update leaves" ON leave_of_absence;
|
||||
DROP POLICY IF EXISTS "Users can cancel own pending leaves" ON leave_of_absence;
|
||||
|
||||
-- Admin/dispatcher/it_staff can see all leaves
|
||||
CREATE POLICY "Privileged users can view all leaves"
|
||||
ON leave_of_absence FOR SELECT
|
||||
USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM profiles
|
||||
WHERE profiles.id = auth.uid()
|
||||
AND profiles.role IN ('admin', 'dispatcher', 'it_staff')
|
||||
)
|
||||
);
|
||||
|
||||
-- All users can see their own leaves
|
||||
CREATE POLICY "Users can view own leaves"
|
||||
ON leave_of_absence FOR SELECT
|
||||
USING (user_id = auth.uid());
|
||||
|
||||
-- Only admin/dispatcher/it_staff can file leaves (for themselves)
|
||||
CREATE POLICY "Privileged users can file own leaves"
|
||||
ON leave_of_absence FOR INSERT
|
||||
WITH CHECK (
|
||||
user_id = auth.uid()
|
||||
AND filed_by = auth.uid()
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM profiles
|
||||
WHERE profiles.id = auth.uid()
|
||||
AND profiles.role IN ('admin', 'dispatcher', 'it_staff')
|
||||
)
|
||||
);
|
||||
|
||||
-- Only admins can approve/reject pending leaves
|
||||
CREATE POLICY "Admins can approve or reject leaves"
|
||||
ON leave_of_absence FOR UPDATE
|
||||
USING (
|
||||
status = 'pending'
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM profiles
|
||||
WHERE profiles.id = auth.uid()
|
||||
AND profiles.role = 'admin'
|
||||
)
|
||||
)
|
||||
WITH CHECK (
|
||||
status IN ('approved', 'rejected')
|
||||
);
|
||||
|
||||
-- Users can cancel their own future approved leaves
|
||||
CREATE POLICY "Users can cancel own future approved leaves"
|
||||
ON leave_of_absence FOR UPDATE
|
||||
USING (
|
||||
user_id = auth.uid()
|
||||
AND status = 'approved'
|
||||
AND start_time > now()
|
||||
)
|
||||
WITH CHECK (
|
||||
status = 'cancelled'
|
||||
);
|
||||
|
||||
-- Admins can cancel future approved leaves
|
||||
CREATE POLICY "Admins can cancel future approved leaves"
|
||||
ON leave_of_absence FOR UPDATE
|
||||
USING (
|
||||
status = 'approved'
|
||||
AND start_time > now()
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM profiles
|
||||
WHERE profiles.id = auth.uid()
|
||||
AND profiles.role = 'admin'
|
||||
)
|
||||
)
|
||||
WITH CHECK (
|
||||
status = 'cancelled'
|
||||
);
|
||||
|
||||
-- Drop legacy reason column if it exists from an earlier migration
|
||||
ALTER TABLE leave_of_absence DROP COLUMN IF EXISTS reason;
|
||||
|
||||
-- Updated_at trigger
|
||||
CREATE OR REPLACE FUNCTION update_leave_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = now();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
DROP TRIGGER IF EXISTS trigger_leave_updated_at ON leave_of_absence;
|
||||
CREATE TRIGGER trigger_leave_updated_at
|
||||
BEFORE UPDATE ON leave_of_absence
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_leave_updated_at();
|
||||
Reference in New Issue
Block a user