109 lines
3.6 KiB
SQL
109 lines
3.6 KiB
SQL
-- Better Auth Core Schema
|
|
-- See: https://better-auth.com/docs/concepts/database
|
|
-- Note: Using quoted "user" to avoid SQL keyword issues while keeping Better Auth's expected table name
|
|
|
|
-- User table (better-auth core)
|
|
CREATE TABLE IF NOT EXISTS "user" (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
email TEXT UNIQUE NOT NULL,
|
|
"emailVerified" BOOLEAN NOT NULL DEFAULT FALSE,
|
|
image TEXT,
|
|
"createdAt" TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_user_email ON "user"(email);
|
|
|
|
-- Session table (better-auth core)
|
|
CREATE TABLE IF NOT EXISTS session (
|
|
id TEXT PRIMARY KEY,
|
|
"expiresAt" TIMESTAMP NOT NULL,
|
|
token TEXT UNIQUE NOT NULL,
|
|
"createdAt" TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
"ipAddress" TEXT,
|
|
"userAgent" TEXT,
|
|
"userId" TEXT NOT NULL REFERENCES "user"(id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE INDEX idx_session_userId ON session("userId");
|
|
CREATE INDEX idx_session_token ON session(token);
|
|
|
|
-- Account table (better-auth core, for OAuth providers)
|
|
CREATE TABLE IF NOT EXISTS account (
|
|
id TEXT PRIMARY KEY,
|
|
"accountId" TEXT NOT NULL,
|
|
"providerId" TEXT NOT NULL,
|
|
"userId" TEXT NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
|
|
"accessToken" TEXT,
|
|
"refreshToken" TEXT,
|
|
"idToken" TEXT,
|
|
"accessTokenExpiresAt" TIMESTAMP,
|
|
"refreshTokenExpiresAt" TIMESTAMP,
|
|
scope TEXT,
|
|
password TEXT,
|
|
"createdAt" TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
"updatedAt" TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_account_userId ON account("userId");
|
|
|
|
-- Verification table (better-auth core)
|
|
CREATE TABLE IF NOT EXISTS verification (
|
|
id TEXT PRIMARY KEY,
|
|
identifier TEXT NOT NULL,
|
|
value TEXT NOT NULL,
|
|
"expiresAt" TIMESTAMP NOT NULL,
|
|
"createdAt" TIMESTAMP,
|
|
"updatedAt" TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX idx_verification_identifier ON verification(identifier);
|
|
|
|
-- User license and authorization schema (custom tables)
|
|
|
|
CREATE TABLE IF NOT EXISTS user_licenses (
|
|
user_id TEXT PRIMARY KEY REFERENCES "user"(id) ON DELETE CASCADE,
|
|
email TEXT,
|
|
license_type TEXT NOT NULL CHECK (license_type IN ('free', 'pro', 'enterprise')),
|
|
features JSONB NOT NULL DEFAULT '{
|
|
"maxIndicators": 5,
|
|
"maxStrategies": 3,
|
|
"maxBacktestDays": 30,
|
|
"realtimeData": false,
|
|
"customExecutors": false,
|
|
"apiAccess": false
|
|
}',
|
|
resource_limits JSONB NOT NULL DEFAULT '{
|
|
"maxConcurrentSessions": 1,
|
|
"maxMessagesPerDay": 100,
|
|
"maxTokensPerMessage": 4096,
|
|
"rateLimitPerMinute": 10
|
|
}',
|
|
mcp_server_url TEXT NOT NULL,
|
|
preferred_model JSONB DEFAULT NULL,
|
|
expires_at TIMESTAMP WITH TIME ZONE,
|
|
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
COMMENT ON COLUMN user_licenses.preferred_model IS 'Optional model preference: {"provider": "anthropic", "model": "claude-3-5-sonnet-20241022", "temperature": 0.7}';
|
|
|
|
CREATE INDEX idx_user_licenses_expires_at ON user_licenses(expires_at)
|
|
WHERE expires_at IS NOT NULL;
|
|
|
|
-- Channel linking for multi-channel support
|
|
CREATE TABLE IF NOT EXISTS user_channel_links (
|
|
id SERIAL PRIMARY KEY,
|
|
user_id TEXT NOT NULL REFERENCES user_licenses(user_id) ON DELETE CASCADE,
|
|
channel_type TEXT NOT NULL CHECK (channel_type IN ('telegram', 'slack', 'discord', 'websocket')),
|
|
channel_user_id TEXT NOT NULL,
|
|
metadata JSONB,
|
|
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
|
UNIQUE(channel_type, channel_user_id)
|
|
);
|
|
|
|
CREATE INDEX idx_user_channel_links_user_id ON user_channel_links(user_id);
|
|
CREATE INDEX idx_user_channel_links_channel ON user_channel_links(channel_type, channel_user_id);
|