- Move supabase/ from packages/db/ to repo root for simpler CLI usage - Use custom ports (553xx) to avoid conflicts with other local Supabase instances - Add --env-mode=loose to turbo dev so root .env vars reach Next.js - Remove hardcoded --port 3000 from next dev (reads PORT env var instead) - Add .env.example with Supabase env var placeholders - Add supabase local state dirs to .gitignore Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
166 lines
5.2 KiB
PL/PgSQL
166 lines
5.2 KiB
PL/PgSQL
-- Properties tables
|
|
-- Simple property management without organizations
|
|
|
|
-- Properties addresses table (must be created first due to foreign key)
|
|
CREATE TABLE IF NOT EXISTS properties_addresses (
|
|
id TEXT PRIMARY KEY,
|
|
street_number TEXT,
|
|
route TEXT,
|
|
route_short TEXT,
|
|
neighborhood TEXT,
|
|
city TEXT,
|
|
county TEXT,
|
|
state TEXT,
|
|
state_long TEXT,
|
|
postal_code TEXT,
|
|
postal_code_suffix TEXT,
|
|
country TEXT,
|
|
country_long TEXT,
|
|
latitude NUMERIC,
|
|
longitude NUMERIC,
|
|
raw_json JSONB,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
UNIQUE(street_number, route, city, state, postal_code)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_properties_addresses_city_state ON properties_addresses(city, state);
|
|
|
|
-- Properties table
|
|
CREATE TABLE IF NOT EXISTS properties (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT,
|
|
address_id TEXT UNIQUE REFERENCES properties_addresses(id) ON DELETE SET NULL,
|
|
owner_id TEXT REFERENCES auth_users(id) ON DELETE SET NULL,
|
|
details_json JSONB,
|
|
metadata JSONB,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_properties_owner_id ON properties(owner_id);
|
|
CREATE INDEX IF NOT EXISTS idx_properties_address_id ON properties(address_id);
|
|
|
|
-- Properties models table (scene graphs)
|
|
CREATE TABLE IF NOT EXISTS properties_models (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT,
|
|
version INTEGER DEFAULT 1,
|
|
description TEXT,
|
|
draft BOOLEAN DEFAULT true,
|
|
property_id TEXT REFERENCES properties(id) ON DELETE SET NULL,
|
|
scene_graph JSONB,
|
|
metadata JSONB,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_properties_models_property_id ON properties_models(property_id);
|
|
CREATE INDEX IF NOT EXISTS idx_properties_models_version ON properties_models(property_id, version DESC);
|
|
|
|
-- Enable Row Level Security (RLS)
|
|
ALTER TABLE properties ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE properties_addresses ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE properties_models ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- RLS Policies for properties table
|
|
CREATE POLICY "Users can view their own properties"
|
|
ON properties FOR SELECT
|
|
USING (owner_id = current_setting('app.user_id', true)::TEXT OR owner_id IS NULL);
|
|
|
|
CREATE POLICY "Users can insert their own properties"
|
|
ON properties FOR INSERT
|
|
WITH CHECK (owner_id = current_setting('app.user_id', true)::TEXT OR owner_id IS NULL);
|
|
|
|
CREATE POLICY "Users can update their own properties"
|
|
ON properties FOR UPDATE
|
|
USING (owner_id = current_setting('app.user_id', true)::TEXT OR owner_id IS NULL);
|
|
|
|
CREATE POLICY "Users can delete their own properties"
|
|
ON properties FOR DELETE
|
|
USING (owner_id = current_setting('app.user_id', true)::TEXT OR owner_id IS NULL);
|
|
|
|
-- RLS Policies for properties_addresses table
|
|
-- Addresses table doesn't have property_id, so we'll allow all authenticated users
|
|
CREATE POLICY "Authenticated users can view all addresses"
|
|
ON properties_addresses FOR SELECT
|
|
USING (true);
|
|
|
|
CREATE POLICY "Authenticated users can insert addresses"
|
|
ON properties_addresses FOR INSERT
|
|
WITH CHECK (true);
|
|
|
|
CREATE POLICY "Authenticated users can update addresses"
|
|
ON properties_addresses FOR UPDATE
|
|
USING (true);
|
|
|
|
CREATE POLICY "Authenticated users can delete addresses"
|
|
ON properties_addresses FOR DELETE
|
|
USING (true);
|
|
|
|
-- RLS Policies for properties_models table
|
|
CREATE POLICY "Users can view models of their own properties"
|
|
ON properties_models FOR SELECT
|
|
USING (
|
|
EXISTS (
|
|
SELECT 1 FROM properties
|
|
WHERE properties.id = properties_models.property_id
|
|
AND properties.owner_id = current_setting('app.user_id', true)::TEXT
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can insert models for their own properties"
|
|
ON properties_models FOR INSERT
|
|
WITH CHECK (
|
|
EXISTS (
|
|
SELECT 1 FROM properties
|
|
WHERE properties.id = properties_models.property_id
|
|
AND properties.owner_id = current_setting('app.user_id', true)::TEXT
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can update models of their own properties"
|
|
ON properties_models FOR UPDATE
|
|
USING (
|
|
EXISTS (
|
|
SELECT 1 FROM properties
|
|
WHERE properties.id = properties_models.property_id
|
|
AND properties.owner_id = current_setting('app.user_id', true)::TEXT
|
|
)
|
|
);
|
|
|
|
CREATE POLICY "Users can delete models of their own properties"
|
|
ON properties_models FOR DELETE
|
|
USING (
|
|
EXISTS (
|
|
SELECT 1 FROM properties
|
|
WHERE properties.id = properties_models.property_id
|
|
AND properties.owner_id = current_setting('app.user_id', true)::TEXT
|
|
)
|
|
);
|
|
|
|
-- Trigger to update updated_at timestamp
|
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER update_properties_updated_at
|
|
BEFORE UPDATE ON properties
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
CREATE TRIGGER update_properties_addresses_updated_at
|
|
BEFORE UPDATE ON properties_addresses
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
CREATE TRIGGER update_properties_models_updated_at
|
|
BEFORE UPDATE ON properties_models
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_updated_at_column();
|