-- Migration: 110_trusted_origins.sql
-- Description: Trusted origins for API access without token
-- Created: 2024-12-14
--
-- Manages which domains, IPs, and patterns can access the API without a Bearer token.
-- Used by auth middleware to grant 'internal' role to trusted requests.

-- ============================================================
-- TRUSTED ORIGINS TABLE
-- ============================================================
CREATE TABLE IF NOT EXISTS trusted_origins (
  id SERIAL PRIMARY KEY,

  -- Origin identification
  name VARCHAR(100) NOT NULL,              -- Friendly name (e.g., "CannaIQ Production")
  origin_type VARCHAR(20) NOT NULL,        -- 'domain', 'ip', or 'pattern'
  origin_value VARCHAR(255) NOT NULL,      -- The actual value to match

  -- Metadata
  description TEXT,                         -- Optional notes
  active BOOLEAN DEFAULT TRUE,

  -- Tracking
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW(),
  created_by INTEGER REFERENCES users(id),

  -- Constraints
  CONSTRAINT valid_origin_type CHECK (origin_type IN ('domain', 'ip', 'pattern')),
  UNIQUE(origin_type, origin_value)
);

-- Index for active lookups (used by auth middleware)
CREATE INDEX IF NOT EXISTS idx_trusted_origins_active
  ON trusted_origins(active) WHERE active = TRUE;

-- Updated at trigger
CREATE OR REPLACE FUNCTION update_trusted_origins_updated_at()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trusted_origins_updated_at ON trusted_origins;
CREATE TRIGGER trusted_origins_updated_at
  BEFORE UPDATE ON trusted_origins
  FOR EACH ROW
  EXECUTE FUNCTION update_trusted_origins_updated_at();

-- ============================================================
-- SEED DEFAULT TRUSTED ORIGINS
-- These match the hardcoded fallbacks in middleware.ts
-- ============================================================

-- Production domains
INSERT INTO trusted_origins (name, origin_type, origin_value, description) VALUES
  ('CannaIQ Production', 'domain', 'https://cannaiq.co', 'Main CannaIQ dashboard'),
  ('CannaIQ Production (www)', 'domain', 'https://www.cannaiq.co', 'Main CannaIQ dashboard with www'),
  ('FindADispo Production', 'domain', 'https://findadispo.com', 'Consumer dispensary finder'),
  ('FindADispo Production (www)', 'domain', 'https://www.findadispo.com', 'Consumer dispensary finder with www'),
  ('Findagram Production', 'domain', 'https://findagram.co', 'Instagram-style cannabis discovery'),
  ('Findagram Production (www)', 'domain', 'https://www.findagram.co', 'Instagram-style cannabis discovery with www')
ON CONFLICT (origin_type, origin_value) DO NOTHING;

-- Wildcard patterns
INSERT INTO trusted_origins (name, origin_type, origin_value, description) VALUES
  ('CannaBrands Subdomains', 'pattern', '^https://.*\\.cannabrands\\.app$', 'All *.cannabrands.app subdomains'),
  ('CannaIQ Subdomains', 'pattern', '^https://.*\\.cannaiq\\.co$', 'All *.cannaiq.co subdomains')
ON CONFLICT (origin_type, origin_value) DO NOTHING;

-- Local development
INSERT INTO trusted_origins (name, origin_type, origin_value, description) VALUES
  ('Local API', 'domain', 'http://localhost:3010', 'Local backend API'),
  ('Local Admin', 'domain', 'http://localhost:8080', 'Local admin dashboard'),
  ('Local Vite Dev', 'domain', 'http://localhost:5173', 'Vite dev server')
ON CONFLICT (origin_type, origin_value) DO NOTHING;

-- Trusted IPs (localhost)
INSERT INTO trusted_origins (name, origin_type, origin_value, description) VALUES
  ('Localhost IPv4', 'ip', '127.0.0.1', 'Local machine'),
  ('Localhost IPv6', 'ip', '::1', 'Local machine IPv6'),
  ('Localhost IPv6 Mapped', 'ip', '::ffff:127.0.0.1', 'IPv6-mapped IPv4 localhost')
ON CONFLICT (origin_type, origin_value) DO NOTHING;

-- ============================================================
-- COMMENTS
-- ============================================================
COMMENT ON TABLE trusted_origins IS 'Domains, IPs, and patterns that can access API without token';
COMMENT ON COLUMN trusted_origins.origin_type IS 'domain = exact URL match, ip = IP address, pattern = regex pattern';
COMMENT ON COLUMN trusted_origins.origin_value IS 'For domain: full URL. For ip: IP address. For pattern: regex string';
