159 lines
No EOL
5.3 KiB
PL/PgSQL
159 lines
No EOL
5.3 KiB
PL/PgSQL
-- Initial database schema for Keys for All
|
|
|
|
-- Enable UUID extension
|
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
|
|
-- Apps table
|
|
CREATE TABLE IF NOT EXISTS apps (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
app_id VARCHAR(255) UNIQUE NOT NULL,
|
|
name VARCHAR(255) NOT NULL,
|
|
api_key VARCHAR(255) UNIQUE NOT NULL,
|
|
webhook_url VARCHAR(500),
|
|
settings JSONB DEFAULT '{}',
|
|
role VARCHAR(50) DEFAULT 'app',
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX idx_apps_api_key ON apps(api_key);
|
|
|
|
-- Keys table
|
|
CREATE TABLE IF NOT EXISTS keys (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
key VARCHAR(19) UNIQUE NOT NULL,
|
|
app_id UUID REFERENCES apps(id),
|
|
level INTEGER NOT NULL DEFAULT 1,
|
|
type VARCHAR(50) NOT NULL DEFAULT 'purchase',
|
|
status VARCHAR(50) NOT NULL DEFAULT 'unused',
|
|
metadata JSONB DEFAULT '{}',
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
expires_at TIMESTAMP WITH TIME ZONE,
|
|
first_activated_at TIMESTAMP WITH TIME ZONE,
|
|
last_used_at TIMESTAMP WITH TIME ZONE
|
|
);
|
|
|
|
CREATE INDEX idx_keys_key ON keys(key);
|
|
CREATE INDEX idx_keys_status ON keys(status);
|
|
CREATE INDEX idx_keys_app_id ON keys(app_id);
|
|
|
|
-- Activations table
|
|
CREATE TABLE IF NOT EXISTS activations (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
key_id UUID REFERENCES keys(id),
|
|
app_id UUID REFERENCES apps(id),
|
|
device_id VARCHAR(255),
|
|
device_info JSONB DEFAULT '{}',
|
|
ip_address INET,
|
|
activated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
last_seen_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX idx_activations_key_id ON activations(key_id);
|
|
CREATE INDEX idx_activations_device_id ON activations(device_id);
|
|
|
|
-- Purchases table
|
|
CREATE TABLE IF NOT EXISTS purchases (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
app_id UUID REFERENCES apps(id),
|
|
transaction_id VARCHAR(255) UNIQUE NOT NULL,
|
|
product_id VARCHAR(255) NOT NULL,
|
|
keys_granted INTEGER NOT NULL,
|
|
price DECIMAL(10, 2),
|
|
currency VARCHAR(3) DEFAULT 'USD',
|
|
receipt_data TEXT,
|
|
verified_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
metadata JSONB DEFAULT '{}'
|
|
);
|
|
|
|
CREATE INDEX idx_purchases_transaction_id ON purchases(transaction_id);
|
|
CREATE INDEX idx_purchases_app_id ON purchases(app_id);
|
|
|
|
-- Purchase keys link table
|
|
CREATE TABLE IF NOT EXISTS purchase_keys (
|
|
purchase_id UUID REFERENCES purchases(id),
|
|
key_id UUID REFERENCES keys(id),
|
|
PRIMARY KEY (purchase_id, key_id)
|
|
);
|
|
|
|
-- Shares table
|
|
CREATE TABLE IF NOT EXISTS shares (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
share_code VARCHAR(50) UNIQUE NOT NULL,
|
|
from_key_id UUID REFERENCES keys(id),
|
|
to_key_id UUID REFERENCES keys(id),
|
|
keys_shared INTEGER NOT NULL DEFAULT 1,
|
|
message TEXT,
|
|
status VARCHAR(50) DEFAULT 'pending',
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
expires_at TIMESTAMP WITH TIME ZONE,
|
|
claimed_at TIMESTAMP WITH TIME ZONE
|
|
);
|
|
|
|
CREATE INDEX idx_shares_code ON shares(share_code);
|
|
CREATE INDEX idx_shares_status ON shares(status);
|
|
|
|
-- Community pool table
|
|
CREATE TABLE IF NOT EXISTS community_pool (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
key_id UUID REFERENCES keys(id) UNIQUE,
|
|
donor_message TEXT,
|
|
anonymous BOOLEAN DEFAULT true,
|
|
donated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
claimed_at TIMESTAMP WITH TIME ZONE,
|
|
claimed_by_request_id UUID
|
|
);
|
|
|
|
CREATE INDEX idx_pool_claimed ON community_pool(claimed_at) WHERE claimed_at IS NULL;
|
|
|
|
-- Community requests table
|
|
CREATE TABLE IF NOT EXISTS community_requests (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
app_id UUID REFERENCES apps(id),
|
|
email VARCHAR(255) NOT NULL,
|
|
reason TEXT,
|
|
status VARCHAR(50) DEFAULT 'pending',
|
|
ip_address INET,
|
|
requested_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
fulfilled_at TIMESTAMP WITH TIME ZONE,
|
|
key_id UUID REFERENCES keys(id)
|
|
);
|
|
|
|
CREATE INDEX idx_requests_status ON community_requests(status);
|
|
CREATE INDEX idx_requests_email ON community_requests(email);
|
|
|
|
-- Analytics events table
|
|
CREATE TABLE IF NOT EXISTS analytics_events (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
app_id UUID REFERENCES apps(id),
|
|
event_type VARCHAR(50) NOT NULL,
|
|
key_id UUID REFERENCES keys(id),
|
|
metadata JSONB DEFAULT '{}',
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX idx_analytics_app_id ON analytics_events(app_id);
|
|
CREATE INDEX idx_analytics_event_type ON analytics_events(event_type);
|
|
CREATE INDEX idx_analytics_created_at ON analytics_events(created_at);
|
|
|
|
-- Rate limits table
|
|
CREATE TABLE IF NOT EXISTS rate_limits (
|
|
id VARCHAR(255) PRIMARY KEY,
|
|
count INTEGER NOT NULL DEFAULT 0,
|
|
window_start TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX idx_rate_limits_window ON rate_limits(window_start);
|
|
|
|
-- Updated timestamp trigger
|
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = CURRENT_TIMESTAMP;
|
|
RETURN NEW;
|
|
END;
|
|
$$ language 'plpgsql';
|
|
|
|
CREATE TRIGGER update_apps_updated_at BEFORE UPDATE ON apps
|
|
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); |