mirror of
https://github.com/mito-systems/ranger-app.git
synced 2025-12-25 17:54:07 +00:00
233 lines
5.6 KiB
PL/PgSQL
233 lines
5.6 KiB
PL/PgSQL
-- Schema for Supabase to set up user points tracking
|
|
-- This file is the main schema definition for the points system
|
|
|
|
-- Create users table to track user information
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id UUID PRIMARY KEY,
|
|
email TEXT NOT NULL,
|
|
name TEXT,
|
|
first_login TIMESTAMP WITH TIME ZONE DEFAULT now(),
|
|
last_login TIMESTAMP WITH TIME ZONE DEFAULT now()
|
|
);
|
|
|
|
-- Create point_transactions table to track individual point awards
|
|
CREATE TABLE IF NOT EXISTS point_transactions (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
user_id UUID NOT NULL REFERENCES users(id),
|
|
points INTEGER NOT NULL,
|
|
transaction_type TEXT NOT NULL,
|
|
image_hash TEXT,
|
|
image_url TEXT,
|
|
description TEXT,
|
|
animal_type TEXT,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
|
|
);
|
|
|
|
-- Create indexes for faster queries
|
|
CREATE INDEX IF NOT EXISTS idx_point_transactions_user_id ON point_transactions(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_point_transactions_image_hash ON point_transactions(image_hash);
|
|
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
|
|
|
-- Function to ensure a user exists in the database
|
|
CREATE OR REPLACE FUNCTION ensure_user_exists(
|
|
user_id_param TEXT,
|
|
email_param TEXT,
|
|
name_param TEXT DEFAULT NULL
|
|
)
|
|
RETURNS UUID AS $$
|
|
DECLARE
|
|
user_uuid UUID;
|
|
existing_user_id UUID;
|
|
exists_flag BOOLEAN;
|
|
BEGIN
|
|
-- Convert to UUID
|
|
user_uuid := user_id_param::UUID;
|
|
|
|
-- First check if a user with this email already exists
|
|
SELECT id INTO existing_user_id
|
|
FROM users
|
|
WHERE email = email_param;
|
|
|
|
-- If a user with this email exists, use their ID and update
|
|
IF FOUND THEN
|
|
UPDATE users
|
|
SET last_login = now(),
|
|
name = COALESCE(name_param, name)
|
|
WHERE id = existing_user_id;
|
|
|
|
RETURN existing_user_id;
|
|
END IF;
|
|
|
|
-- If we get here, no user with this email exists
|
|
-- Now check if user with this ID exists
|
|
SELECT EXISTS (
|
|
SELECT 1 FROM users WHERE id = user_uuid
|
|
) INTO exists_flag;
|
|
|
|
-- If user doesn't exist, create them
|
|
IF NOT exists_flag THEN
|
|
INSERT INTO users (id, email, name, first_login, last_login)
|
|
VALUES (user_uuid, email_param, name_param, now(), now());
|
|
ELSE
|
|
-- Update last_login and other fields
|
|
UPDATE users
|
|
SET last_login = now(),
|
|
email = email_param,
|
|
name = COALESCE(name_param, name)
|
|
WHERE id = user_uuid;
|
|
END IF;
|
|
|
|
RETURN user_uuid;
|
|
END;
|
|
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
|
|
-- Function to create a point transaction
|
|
CREATE OR REPLACE FUNCTION create_point_transaction(
|
|
user_id_param TEXT,
|
|
points_param INTEGER,
|
|
transaction_type_param TEXT,
|
|
image_hash_param TEXT DEFAULT NULL,
|
|
image_url_param TEXT DEFAULT NULL,
|
|
description_param TEXT DEFAULT NULL,
|
|
animal_type_param TEXT DEFAULT NULL
|
|
)
|
|
RETURNS json AS $$
|
|
DECLARE
|
|
new_transaction point_transactions;
|
|
user_uuid UUID;
|
|
BEGIN
|
|
-- Convert to UUID
|
|
user_uuid := user_id_param::UUID;
|
|
|
|
INSERT INTO point_transactions (
|
|
user_id,
|
|
points,
|
|
transaction_type,
|
|
image_hash,
|
|
image_url,
|
|
description,
|
|
animal_type,
|
|
created_at
|
|
)
|
|
VALUES (
|
|
user_uuid,
|
|
points_param,
|
|
transaction_type_param,
|
|
image_hash_param,
|
|
image_url_param,
|
|
description_param,
|
|
animal_type_param,
|
|
now()
|
|
)
|
|
RETURNING * INTO new_transaction;
|
|
|
|
RETURN row_to_json(new_transaction);
|
|
END;
|
|
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
|
|
-- Function to calculate a user's total points from transactions
|
|
CREATE OR REPLACE FUNCTION get_user_total_points(
|
|
user_id_param TEXT
|
|
)
|
|
RETURNS INTEGER AS $$
|
|
DECLARE
|
|
total INTEGER;
|
|
user_uuid UUID;
|
|
BEGIN
|
|
-- Convert to UUID
|
|
user_uuid := user_id_param::UUID;
|
|
|
|
SELECT COALESCE(SUM(points), 0) INTO total
|
|
FROM point_transactions
|
|
WHERE user_id = user_uuid;
|
|
|
|
RETURN total;
|
|
END;
|
|
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
|
|
-- Function to get user transactions
|
|
CREATE OR REPLACE FUNCTION get_user_transactions(
|
|
user_id_param TEXT
|
|
)
|
|
RETURNS SETOF point_transactions AS $$
|
|
DECLARE
|
|
user_uuid UUID;
|
|
BEGIN
|
|
-- Convert to UUID
|
|
user_uuid := user_id_param::UUID;
|
|
|
|
RETURN QUERY
|
|
SELECT *
|
|
FROM point_transactions
|
|
WHERE user_id = user_uuid
|
|
ORDER BY created_at DESC;
|
|
END;
|
|
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
|
|
-- Function to check if an image has already been processed for a user
|
|
CREATE OR REPLACE FUNCTION check_duplicate_upload(
|
|
user_id_param TEXT,
|
|
image_hash_param TEXT
|
|
)
|
|
RETURNS BOOLEAN AS $$
|
|
DECLARE
|
|
exists_flag BOOLEAN;
|
|
user_uuid UUID;
|
|
BEGIN
|
|
-- Convert to UUID
|
|
user_uuid := user_id_param::UUID;
|
|
|
|
SELECT EXISTS (
|
|
SELECT 1 FROM point_transactions
|
|
WHERE user_id = user_uuid
|
|
AND image_hash = image_hash_param
|
|
) INTO exists_flag;
|
|
|
|
RETURN exists_flag;
|
|
END;
|
|
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
|
|
-- Function to find a user by email
|
|
CREATE OR REPLACE FUNCTION find_user_by_email(
|
|
email_param TEXT
|
|
)
|
|
RETURNS json AS $$
|
|
DECLARE
|
|
user_record users;
|
|
BEGIN
|
|
SELECT * INTO user_record
|
|
FROM users
|
|
WHERE email = email_param;
|
|
|
|
IF FOUND THEN
|
|
RETURN row_to_json(user_record);
|
|
ELSE
|
|
RETURN NULL;
|
|
END IF;
|
|
END;
|
|
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
|
|
-- Enable Row Level Security
|
|
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE point_transactions ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- Create policies section - uncomment if you need to recreate policies
|
|
/*
|
|
-- Users policies
|
|
CREATE POLICY "Users can view their own profile"
|
|
ON users FOR SELECT
|
|
USING (auth.uid() = id);
|
|
|
|
CREATE POLICY "Service role can manage all users"
|
|
ON users FOR ALL
|
|
USING (auth.role() = 'service_role');
|
|
|
|
-- Transaction policies
|
|
CREATE POLICY "Users can view their own transactions"
|
|
ON point_transactions FOR SELECT
|
|
USING (auth.uid() = user_id);
|
|
|
|
CREATE POLICY "Service role can manage all transactions"
|
|
ON point_transactions FOR ALL
|
|
USING (auth.role() = 'service_role');
|
|
*/ |