Query API: - GET /api/payloads/store/:id/query - Filter products with flexible params (brand, category, price_min/max, thc_min/max, search, sort, pagination) - GET /api/payloads/store/:id/aggregate - Group by brand/category with metrics (count, avg_price, min_price, max_price, avg_thc, in_stock_count) - Documentation at docs/QUERY_API.md Trusted Origins Admin: - GET/POST/PUT/DELETE /api/admin/trusted-origins - Manage auth bypass list - Trusted IPs, domains, and regex patterns stored in DB - 5-minute cache with invalidation on admin updates - Fallback to hardcoded defaults if DB unavailable - Migration 085 creates table with seed data 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
60 lines
2.2 KiB
SQL
60 lines
2.2 KiB
SQL
-- Migration 085: Trusted Origins Management
|
|
-- Allows admin to manage trusted IPs and domains via UI instead of hardcoded values
|
|
|
|
-- Trusted origins table (IPs and domains that bypass API key auth)
|
|
CREATE TABLE IF NOT EXISTS trusted_origins (
|
|
id SERIAL PRIMARY KEY,
|
|
|
|
-- Origin type: 'ip', 'domain', 'pattern'
|
|
origin_type VARCHAR(20) NOT NULL CHECK (origin_type IN ('ip', 'domain', 'pattern')),
|
|
|
|
-- The actual value
|
|
-- For ip: '127.0.0.1', '::1', '192.168.1.0/24'
|
|
-- For domain: 'cannaiq.co', 'findadispo.com'
|
|
-- For pattern: '^https://.*\.cannabrands\.app$' (regex)
|
|
origin_value VARCHAR(255) NOT NULL,
|
|
|
|
-- Description for admin reference
|
|
description TEXT,
|
|
|
|
-- Active flag
|
|
active BOOLEAN DEFAULT true,
|
|
|
|
-- Audit
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
created_by INTEGER REFERENCES users(id),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
|
|
UNIQUE(origin_type, origin_value)
|
|
);
|
|
|
|
-- Index for quick lookups
|
|
CREATE INDEX IF NOT EXISTS idx_trusted_origins_active ON trusted_origins(active) WHERE active = true;
|
|
CREATE INDEX IF NOT EXISTS idx_trusted_origins_type ON trusted_origins(origin_type, active);
|
|
|
|
-- Seed with current hardcoded values
|
|
INSERT INTO trusted_origins (origin_type, origin_value, description) VALUES
|
|
-- Trusted IPs (localhost)
|
|
('ip', '127.0.0.1', 'Localhost IPv4'),
|
|
('ip', '::1', 'Localhost IPv6'),
|
|
('ip', '::ffff:127.0.0.1', 'Localhost IPv4-mapped IPv6'),
|
|
|
|
-- Trusted domains
|
|
('domain', 'cannaiq.co', 'CannaiQ production'),
|
|
('domain', 'www.cannaiq.co', 'CannaiQ production (www)'),
|
|
('domain', 'findadispo.com', 'FindADispo production'),
|
|
('domain', 'www.findadispo.com', 'FindADispo production (www)'),
|
|
('domain', 'findagram.co', 'Findagram production'),
|
|
('domain', 'www.findagram.co', 'Findagram production (www)'),
|
|
('domain', 'localhost:3010', 'Local backend dev'),
|
|
('domain', 'localhost:8080', 'Local admin dev'),
|
|
('domain', 'localhost:5173', 'Local Vite dev'),
|
|
|
|
-- Pattern-based (regex)
|
|
('pattern', '^https://.*\.cannabrands\.app$', 'All cannabrands.app subdomains'),
|
|
('pattern', '^https://.*\.cannaiq\.co$', 'All cannaiq.co subdomains')
|
|
ON CONFLICT (origin_type, origin_value) DO NOTHING;
|
|
|
|
-- Add comment
|
|
COMMENT ON TABLE trusted_origins IS 'IPs and domains that bypass API key authentication. Managed via /admin.';
|