-- NB: This is a manually squashed view of all the CREATE and ALTER statements, -- with comments attached to the fields for centralized documentation. -- noinspection SqlDialectInspectionForFile -- noinspection SqlNoDataSourceInspectionForFile -- noinspection SqlResolveForFile CREATE TABLE users ( -- Not used for anything except replication. id BIGINT(20) NOT NULL AUTO_INCREMENT, -- Visible "primary key" token VARCHAR(32) NOT NULL, -- Username is a lookup key; display_name allows the user to add custom case. username VARCHAR(20) NOT NULL, display_name VARCHAR(20) NOT NULL, email_address VARCHAR(255) NOT NULL, email_confirmed BOOLEAN NOT NULL DEFAULT false, -- The role assigned to the user confers permissions. user_role_slug VARCHAR(16) NOT NULL, -- ========== PREMIUM FEATURES ========== -- If the user has a Stripe subscription (or has had one), we link it to the user here. -- Will never exceed 255 characters: https://groups.google.com/a/lists.stripe.com/g/api-discuss/c/1F5Wb4HRnNQ maybe_stripe_customer_id VARCHAR(255) DEFAULT NULL, -- If a user is a known-good contributor, we can assign them premium service for free. -- Internally, our system statically maps keys to zero or more premium products. -- The business logic can live in the plans code. maybe_loyalty_program_key VARCHAR(32) DEFAULT NULL, -- ========== CREDENTIALS ========== -- Bcrypt password hash. Granted, there are newer methods: -- https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html -- Passwords may be a max of 64 characters per BCrypt. password_hash BINARY(60) NOT NULL, -- Incremented with every update to the password. password_version INT NOT NULL DEFAULT 0, -- ========== ABUSE TRACKING ========== -- For abuse tracking. -- Wide enough for IPv4/6 ip_address_creation VARCHAR(40) NOT NULL, ip_address_last_login VARCHAR(40) NOT NULL, ip_address_last_update VARCHAR(40) NOT NULL, -- ========== DISPLAY / PROFILE ========== -- Gravatar image hashes are precomputed. email_gravatar_hash CHAR(32) NOT NULL, -- The profile of the user in markdown (user editable). profile_markdown TEXT NOT NULL, -- Generated HTML (not user-editable). profile_rendered_html TEXT NOT NULL, -- An uploaded avatar. Public hash in our bucket. -- avatar_public_bucket_hash CHAR(32) DEFAULT NULL, -- ========== SOCIAL MEDIA ========== -- Social media usernames -- These are not confirmed. We'll need to build an OAuth system to handle that. discord_username VARCHAR(36) DEFAULT NULL, twitter_username VARCHAR(36) DEFAULT NULL, twitch_username VARCHAR(36) DEFAULT NULL, patreon_username VARCHAR(36) DEFAULT NULL, github_username VARCHAR(36) DEFAULT NULL, cashapp_username VARCHAR(36) DEFAULT NULL, website_url VARCHAR(255) DEFAULT NULL, -- ========== USER PREFERENCES ========== -- If the user doesn't want to use gravatar and doesn't have an uploaded avatar. disable_gravatar BOOLEAN NOT NULL DEFAULT false, -- (THIS MIGHT NOT BE USED) -- NB: DO NOT SORT! -- THIS MUST MATCH THE RESPECTIVE JOBS TABLE. -- Visibility preference used at TTS inference time (which can be changed on the result itself). -- Moderators will still see them. preferred_tts_result_visibility ENUM( 'public', 'hidden', 'private' ) NOT NULL DEFAULT 'public', -- (THIS MIGHT NOT BE USED) -- NB: DO NOT SORT! -- THIS MUST MATCH THE RESPECTIVE JOBS TABLE. -- Visibility preference used at TTS inference time (which can be changed on the result itself). -- Moderators will still see them. preferred_w2l_result_visibility ENUM( 'public', 'hidden', 'private' ) NOT NULL DEFAULT 'public', -- Auto play preferences -- Tri-state because we want to potentially change the default behavior. auto_play_audio_preference BOOLEAN DEFAULT NULL, auto_play_video_preference BOOLEAN DEFAULT NULL, -- Favorite TTS voice to use by default -- maybe_preferred_tts_model_token VARCHAR(32) DEFAULT NULL, -- Favorite W2L model to use by default -- maybe_preferred_w2l_template_token VARCHAR(32) DEFAULT NULL, -- Settings -- DO NOT REORDER. -- dark_mode_preference ENUM( -- 'light-mode', -- 'dark-mode', -- 'use-clock' -- ) NOT NULL DEFAULT 'light-mode', -- ========== STATS ========== -- For tracking stats. -- The "cached" values are updated by a background job. -- cached_tts_rendered_counter INT(10) NOT NULL DEFAULT 0, -- cached_w2l_rendered_counter INT(10) NOT NULL DEFAULT 0, -- ========== MODERATION DETAILS ========== -- Different than deleted. -- Users still show up, but can't do anything. is_banned BOOLEAN NOT NULL DEFAULT false, -- If a moderator has comments. maybe_mod_comments VARCHAR(255) DEFAULT NULL, -- The last moderator that made changes. maybe_mod_user_token VARCHAR(32) DEFAULT NULL, -- ========== VECTOR CLOCK ========== -- Incremented with every update. version INT NOT NULL DEFAULT 0, -- ========== TIMESTAMPS ========== created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- If the user is deleted, we set this. -- This is different than banned. These users won't show up at all. user_deleted_at TIMESTAMP NULL, mod_deleted_at TIMESTAMP NULL, -- INDICES -- PRIMARY KEY (id), UNIQUE KEY (token), UNIQUE KEY (username), UNIQUE KEY (email_address), KEY fk_user_role_slug (user_role_slug) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;