50e25e3ee8
Rename subdirectories for a cleaner single-repo layout: - website-monitoring-backend/ → backend/ - website-monitoring-frontend/ → frontend/ - website-monitoring-devops/ → devops/ Update all references in package.json scripts, CI workflows, docker-compose, pre-commit hooks, and documentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
210 lines
8.2 KiB
SQL
210 lines
8.2 KiB
SQL
-- Required tables for the website monitoring application
|
|
-- Run these in your Supabase SQL editor to create missing tables
|
|
|
|
-- Team invitations table
|
|
CREATE TABLE IF NOT EXISTS team_invitations (
|
|
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
email text NOT NULL,
|
|
role text CHECK (role IN ('admin', 'member')) NOT NULL DEFAULT 'member',
|
|
organization_id uuid REFERENCES organizations(id) ON DELETE CASCADE,
|
|
invited_by uuid REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
status text CHECK (status IN ('pending', 'accepted', 'expired')) NOT NULL DEFAULT 'pending',
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
expires_at timestamp with time zone DEFAULT (now() + interval '7 days')
|
|
);
|
|
|
|
-- User notification preferences table
|
|
CREATE TABLE IF NOT EXISTS user_notification_preferences (
|
|
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
user_id uuid REFERENCES auth.users(id) ON DELETE CASCADE UNIQUE,
|
|
email_notifications boolean DEFAULT true,
|
|
sms_notifications boolean DEFAULT false,
|
|
browser_notifications boolean DEFAULT true,
|
|
weekly_report boolean DEFAULT true,
|
|
timezone text DEFAULT 'UTC',
|
|
date_format text DEFAULT 'MM/DD/YYYY',
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now()
|
|
);
|
|
|
|
-- Alerts table
|
|
CREATE TABLE IF NOT EXISTS alerts (
|
|
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
website_id uuid REFERENCES websites(id) ON DELETE CASCADE,
|
|
type text CHECK (type IN ('downtime', 'performance', 'error', 'ssl', 'maintenance')) NOT NULL,
|
|
severity text CHECK (severity IN ('low', 'medium', 'high', 'critical')) NOT NULL DEFAULT 'medium',
|
|
title text NOT NULL,
|
|
message text NOT NULL,
|
|
status text CHECK (status IN ('active', 'resolved', 'acknowledged')) NOT NULL DEFAULT 'active',
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
resolved_at timestamp with time zone,
|
|
acknowledged_at timestamp with time zone
|
|
);
|
|
|
|
-- Alert rules table
|
|
CREATE TABLE IF NOT EXISTS alert_rules (
|
|
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
organization_id uuid REFERENCES organizations(id) ON DELETE CASCADE,
|
|
name text NOT NULL,
|
|
type text CHECK (type IN ('downtime', 'performance', 'error_rate')) NOT NULL,
|
|
condition text NOT NULL,
|
|
threshold numeric NOT NULL,
|
|
enabled boolean DEFAULT true,
|
|
notification_methods text[] DEFAULT ARRAY['email'],
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now()
|
|
);
|
|
|
|
-- Uptime checks table
|
|
CREATE TABLE IF NOT EXISTS uptime_checks (
|
|
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
website_id uuid REFERENCES websites(id) ON DELETE CASCADE,
|
|
status text CHECK (status IN ('up', 'down', 'warning')) NOT NULL,
|
|
response_time integer, -- in milliseconds
|
|
status_code integer,
|
|
error_message text,
|
|
checked_at timestamp with time zone DEFAULT now()
|
|
);
|
|
|
|
-- Add missing columns to existing tables if they don't exist
|
|
DO $$
|
|
BEGIN
|
|
-- Add API key to organizations table
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'organizations' AND column_name = 'api_key') THEN
|
|
ALTER TABLE organizations ADD COLUMN api_key text;
|
|
END IF;
|
|
|
|
-- Add max limits to organizations table
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'organizations' AND column_name = 'max_websites') THEN
|
|
ALTER TABLE organizations ADD COLUMN max_websites integer DEFAULT 10;
|
|
END IF;
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'organizations' AND column_name = 'max_scans_per_month') THEN
|
|
ALTER TABLE organizations ADD COLUMN max_scans_per_month integer DEFAULT 1000;
|
|
END IF;
|
|
|
|
-- Add created_at to users table if missing
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'users' AND column_name = 'created_at') THEN
|
|
ALTER TABLE users ADD COLUMN created_at timestamp with time zone DEFAULT now();
|
|
END IF;
|
|
|
|
-- Add last_login_at to users table if missing
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'users' AND column_name = 'last_login_at') THEN
|
|
ALTER TABLE users ADD COLUMN last_login_at timestamp with time zone;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Create indexes for better performance
|
|
CREATE INDEX IF NOT EXISTS idx_team_invitations_organization_id ON team_invitations(organization_id);
|
|
CREATE INDEX IF NOT EXISTS idx_team_invitations_email ON team_invitations(email);
|
|
CREATE INDEX IF NOT EXISTS idx_alerts_website_id ON alerts(website_id);
|
|
CREATE INDEX IF NOT EXISTS idx_alerts_status ON alerts(status);
|
|
CREATE INDEX IF NOT EXISTS idx_alert_rules_organization_id ON alert_rules(organization_id);
|
|
CREATE INDEX IF NOT EXISTS idx_uptime_checks_website_id ON uptime_checks(website_id);
|
|
CREATE INDEX IF NOT EXISTS idx_uptime_checks_checked_at ON uptime_checks(checked_at);
|
|
|
|
-- Enable Row Level Security
|
|
ALTER TABLE team_invitations ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE user_notification_preferences ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE alerts ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE alert_rules ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE uptime_checks ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- Create RLS policies
|
|
-- Team invitations policies
|
|
CREATE POLICY "Users can view invitations for their organization" ON team_invitations
|
|
FOR SELECT USING (
|
|
organization_id IN (
|
|
SELECT organization_id FROM users WHERE id = auth.uid()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Admins and owners can manage invitations" ON team_invitations
|
|
FOR ALL USING (
|
|
organization_id IN (
|
|
SELECT organization_id FROM users
|
|
WHERE id = auth.uid() AND role IN ('admin', 'owner')
|
|
)
|
|
);
|
|
|
|
-- User notification preferences policies
|
|
CREATE POLICY "Users can manage their own preferences" ON user_notification_preferences
|
|
FOR ALL USING (user_id = auth.uid());
|
|
|
|
-- Alerts policies
|
|
CREATE POLICY "Users can view alerts for their organization's websites" ON alerts
|
|
FOR SELECT USING (
|
|
website_id IN (
|
|
SELECT w.id FROM websites w
|
|
JOIN users u ON w.organization_id = u.organization_id
|
|
WHERE u.id = auth.uid()
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can update alerts for their organization's websites" ON alerts
|
|
FOR UPDATE USING (
|
|
website_id IN (
|
|
SELECT w.id FROM websites w
|
|
JOIN users u ON w.organization_id = u.organization_id
|
|
WHERE u.id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- Alert rules policies
|
|
CREATE POLICY "Users can manage alert rules for their organization" ON alert_rules
|
|
FOR ALL USING (
|
|
organization_id IN (
|
|
SELECT organization_id FROM users WHERE id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- Uptime checks policies
|
|
CREATE POLICY "Users can view uptime checks for their organization's websites" ON uptime_checks
|
|
FOR SELECT USING (
|
|
website_id IN (
|
|
SELECT w.id FROM websites w
|
|
JOIN users u ON w.organization_id = u.organization_id
|
|
WHERE u.id = auth.uid()
|
|
)
|
|
);
|
|
|
|
-- Competitor metrics table
|
|
CREATE TABLE IF NOT EXISTS competitor_metrics (
|
|
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
website_id uuid REFERENCES websites(id) ON DELETE CASCADE,
|
|
url text NOT NULL,
|
|
name text,
|
|
performance_score numeric,
|
|
seo_score numeric,
|
|
accessibility_score numeric,
|
|
best_practices_score numeric,
|
|
status_code integer,
|
|
response_time integer,
|
|
last_scanned_at timestamp with time zone DEFAULT now(),
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
UNIQUE(website_id, url)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_competitor_metrics_website_id ON competitor_metrics(website_id);
|
|
|
|
-- Alert configurations table (per-website thresholds)
|
|
CREATE TABLE IF NOT EXISTS alert_configurations (
|
|
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
|
|
website_id uuid REFERENCES websites(id) ON DELETE CASCADE UNIQUE,
|
|
performance_threshold numeric DEFAULT 0.5,
|
|
seo_threshold numeric DEFAULT 0.5,
|
|
accessibility_threshold numeric DEFAULT 0.5,
|
|
uptime_threshold numeric DEFAULT 0.95,
|
|
email_enabled boolean DEFAULT true,
|
|
email_address text,
|
|
slack_enabled boolean DEFAULT false,
|
|
slack_webhook_url text,
|
|
alert_frequency text DEFAULT 'immediate',
|
|
created_at timestamp with time zone DEFAULT now(),
|
|
updated_at timestamp with time zone DEFAULT now()
|
|
);
|
|
|
|
-- Add template_hash to pages table for layout deduplication
|
|
ALTER TABLE pages ADD COLUMN IF NOT EXISTS template_hash VARCHAR;
|
|
CREATE INDEX IF NOT EXISTS idx_pages_template_hash ON pages(template_hash) WHERE template_hash IS NOT NULL;
|
|
); |