30 lines
1.7 KiB
SQL
30 lines
1.7 KiB
SQL
-- user status enum values
|
|
DO $$ BEGIN
|
|
CREATE TYPE user_status AS ENUM ('online', 'idle', 'dnd', 'offline', 'invisible');
|
|
EXCEPTION
|
|
WHEN duplicate_object THEN null;
|
|
END $$;
|
|
|
|
|
|
-- main users table
|
|
CREATE TABLE users (
|
|
id BYTEA PRIMARY KEY NOT NULL CHECK(length(id) = 26),
|
|
username TEXT NOT NULL CHECK (char_length(username) BETWEEN 1 AND 32),
|
|
discriminator TEXT NOT NULL DEFAULT '0000' CHECK (discriminator ~ '^\d{4}$'),
|
|
avatar_hash TEXT CHECK (char_length(avatar_hash) <= 64), -- null if no avatar
|
|
email TEXT UNIQUE NOT NULL CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'),
|
|
email_verified BOOLEAN NOT NULL DEFAULT FALSE,
|
|
password_hash TEXT NOT NULL, -- bcrypt/argon2 hash, never plaintext
|
|
mfa_enabled BOOLEAN NOT NULL DEFAULT FALSE,
|
|
mfa_secret TEXT CHECK (mfa_enabled = FALSE OR char_length(mfa_secret) > 0), -- encrypted if present
|
|
status user_status NOT NULL DEFAULT 'offline',
|
|
public_flags BIGINT NOT NULL DEFAULT 0, -- bitmask for flags
|
|
locale TEXT NOT NULL DEFAULT 'en-US' CHECK (locale ~ '^[a-z]{2}(-[A-Z]{2})?$'), -- BCP 47 pattern
|
|
premium_since TIMESTAMPTZ, -- e.g., Premium subscription start
|
|
premium_end TIMESTAMPTZ,
|
|
bot BOOLEAN NOT NULL DEFAULT FALSE,
|
|
bot_oauth_scopes JSONB NOT NULL DEFAULT '[]'::jsonb, -- e.g., ['bot', 'guilds.join']
|
|
preferences JSONB NOT NULL DEFAULT '{}'::jsonb, -- theme, sound, etc.
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
); |