mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-05 09:33:25 -08:00
Some checks are pending
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 cover (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 26 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Desktop / Prune caches (push) Waiting to run
Build Docker / Servatrice (arm) (push) Waiting to run
Build Docker / Servatrice (x86) (push) Waiting to run
Build Docker / Publish multi-platform Servatrice image (push) Blocked by required conditions
* [Security] Add challenge-response auth with scrypt verifiers and stop storing plaintext passwords Challenge-response authentication: the client derives a scrypt verifier (RFC 7914, EVP_PBE_scrypt, N=32768, r=8, p=1) and authenticates with HMAC-SHA256(key, nonce), so neither the password nor its hash is transmitted. The stored format becomes "$scrypt$<n>$<r>$<p>$<salt>$<verifier>" and Response_PasswordSalt now carries the cost parameters. Strict servers only accept scrypt verifiers; legacy accounts are migrated after a successful login. Fix #344 for challenge-response servers: a saved profile stores the derived verifier under the password key instead of the plaintext password. The connect dialog loads it without revealing it, autoconnect passes it through, the change-password dialog no longer prefills the old password field with it, and the client only persists the verifier when "Save password" is checked. Took 3 minutes Took 1 minute Took 10 seconds Took 7 minutes * [Security] Harden credential format acceptance and challenge nonce validation * [Security] Refuse KDF downgrade; trim profile name and warn on silent credential drop * [Security] Add SupportsAll ServerOptions enumerator to fix enum validation assert The server advertised both SupportsPasswordHash (1) and SupportsChallengeResponseAuth (2) via a bitwise-OR that produced the value 3, which no enumerator declared. Protobuf's proto2 enum validation rejects the value in _internal_set_server_options, crashing servatrice on the debug assertion. Add a SupportsAll = 3 enumerator with an identical wire value so the bitmask reads unchanged while the value is now a documented, valid member of the enum. * [Security] Normalize username when issuing challenge nonce cmdRequestPasswordSalt bound the challenge nonce to the raw, un-simplified username while cmdLogin verifies it against the simplified name. A user who typed leading or trailing whitespace in the username box would be silently rejected during challenge-response login even with the correct password. Simplify at the nonce-issuing site so both commands agree on the normalized name. Also drive-by formatting: collapse the now single-expression serverOptions initializer onto one line. * [Security] Keep an encrypted legacy password backup for old-client logins Migrating an account to scrypt stranded pre-challenge clients, which can only present the legacy salt+hash: after migration the server served them a scrypt salt they cannot use, so the only recovery was a password reset. When security/legacy_backup_key is configured (64 hex chars, openssl rand -hex 32), submitPasswordVerifier now seals the legacy credential with AES-256-GCM under that key before overwriting the row, storing it in password_legacy_backup with the time it was last used. Old clients keep working: cmdRequestPasswordSalt serves the backup's 16-char salt in password_salt so they can derive the legacy hash they were always able to compute, while new clients derive the verifier from the new scrypt_salt field, which always carries the verifier salt. The non-challenge login path accepts the plaintext or legacy hash against the decrypted backup and refreshes its window; a migrated row with no usable backup fails closed. Backups age out so a database dump taken after the window closes never carries a crackable legacy hash: getUsableLegacyBackup purges on first use past security/legacy_backup_ttl_days (default 90, clamped 1..3650), and a six-hourly sweep drops backups idle accounts never touch. changeUserPassword clears the backup since a new credential invalidates it. Without a configured key nothing is sealed or purged, so a temporarily missing key cannot destroy existing backups. The AAD is the simplified user name on both sides, sealing the blob to its row so it cannot be moved between accounts. Sealing failures degrade to the previous lockout behaviour rather than blocking migration. The columns extend the unmerged 0036->0037 migration, so the schema version stays 37. * [Security] Address review: proto compat, plaintext verify, AAD case, strict scope Fix the two blockers and follow-ups from the 2026-10-16 review: - Advertise challenge-response in a new supports_challenge_response field instead of the ServerOptions enum and drop SupportsAll: proto2 enums are closed, so already-released clients parsed server_options = 3 as NoOptions and fell back to plaintext passwords. server_options stays exactly SupportsPasswordHash on the wire; old clients ignore the new field. - Verify a plaintext password directly against a migrated scrypt row with verifyPassword() so email changes (cmdAccountEdit) and old clients sending password keep working without a legacy backup key. Pre-hashed values are still checked against the backup, and its TTL window is refreshed only when the backup is what actually matched. - Use the stored row name as the AES-GCM AAD on both seal and open so a login whose case differs from the stored name (utf8mb4_unicode_ci) still opens its backup. - Require challenge-response in strict mode only for registered SQL accounts (userExists gate), leaving guest/unregistered logins and none/password auth methods unaffected. - Document in servatrice.ini.example that a captured legacy hash can take over a not-yet-migrated account and that strict only constrains registered SQL accounts. Schema version is 38. * [Security] Raise legacy backup TTL default to 180 days Gives operators and slow-to-upgrade users a longer downgrade window for pre-challenge clients before unused encrypted legacy password backups age out. * [Security] Fix servatrice.cpp formatting per clang-format-18 * [Security] Add missing forward declaration for Command_SubmitPasswordVerifier The cmdSubmitPasswordVerifier declaration references the proto-generated type, which otherwise does not name a type in this header and breaks every C++ build. --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de> Co-authored-by: BruebachL <bruebachl@cockatrice.example>
424 lines
18 KiB
SQL
424 lines
18 KiB
SQL
-- Schema file for servatrice database.
|
|
|
|
-- This schema file is using the default table prefix "cockatrice",
|
|
-- to match the "prefix=cockatrice" default setting in servatrice.ini
|
|
|
|
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
|
|
|
|
|
|
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
|
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
|
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
|
/*!40101 SET NAMES utf8 */;
|
|
|
|
-- Every time the database schema changes, the schema version number
|
|
-- must be incremented. Also remember to update the corresponding
|
|
-- number in servatrice/src/servatrice_database_interface.h
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_schema_version` (
|
|
`version` int(7) unsigned NOT NULL,
|
|
PRIMARY KEY (`version`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
INSERT INTO cockatrice_schema_version VALUES(40);
|
|
|
|
-- users and user data tables
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_users` (
|
|
`id` int(7) unsigned zerofill NOT NULL auto_increment,
|
|
-- Bitfield of staff levels: 1 = admin (implies moderator), 2 = moderator,
|
|
-- 4 = judge, 8 = developer. Operators set these by hand with
|
|
-- "UPDATE cockatrice_users SET admin = ...".
|
|
`admin` tinyint(1) NOT NULL,
|
|
`name` varchar(35) NOT NULL,
|
|
`realname` varchar(255) NOT NULL,
|
|
`password_sha512` varchar(255) NOT NULL,
|
|
`password_legacy_backup` varchar(255) NOT NULL DEFAULT '',
|
|
`password_legacy_backup_used_at` datetime DEFAULT NULL,
|
|
`email` varchar(255) NOT NULL,
|
|
`country` char(2) NOT NULL,
|
|
`avatar_bmp` mediumblob NOT NULL,
|
|
`registrationDate` datetime NOT NULL,
|
|
`active` tinyint(1) NOT NULL,
|
|
`token` binary(16),
|
|
`clientid` varchar(15) NOT NULL,
|
|
`adminnotes` mediumtext NOT NULL,
|
|
`privlevel` enum("NONE","VIP","DONATOR") NOT NULL,
|
|
`privlevelStartDate` datetime NOT NULL,
|
|
`privlevelEndDate` datetime NOT NULL,
|
|
`passwordLastChangedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
`force_password_change` tinyint(1) NOT NULL DEFAULT 0,
|
|
`leftPawnColorOverride` varchar(255),
|
|
`rightPawnColorOverride` varchar(255),
|
|
`card_art_params` TEXT DEFAULT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `name` (`name`),
|
|
KEY `token` (`token`),
|
|
KEY `email` (`email`),
|
|
INDEX `idx_admin` (`admin`),
|
|
INDEX `idx_active` (`active`),
|
|
INDEX `idx_privlevel` (`privlevel`),
|
|
INDEX `idx_clientid` (`clientid`),
|
|
INDEX `idx_pawnColorOverrides` (`leftPawnColorOverride`, `rightPawnColorOverride`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_decklist_files` (
|
|
`id` int(7) unsigned zerofill NOT NULL auto_increment,
|
|
`id_folder` int(7) unsigned zerofill NOT NULL,
|
|
`id_user` int(7) unsigned NULL,
|
|
`name` varchar(50) NOT NULL,
|
|
`upload_time` datetime NOT NULL,
|
|
`content` text NOT NULL,
|
|
`is_public` tinyint(1) NOT NULL DEFAULT 0,
|
|
`banner_card_name` varchar(255) NULL,
|
|
`banner_card_provider` varchar(32) NULL,
|
|
`color_identity` varchar(5) NULL,
|
|
`tags` text NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `FolderPlusUser` (`id_folder`,`id_user`),
|
|
FOREIGN KEY(`id_user`) REFERENCES `cockatrice_users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
-- Temporary deck shares: a named bundle of decks that can be fetched by
|
|
-- anyone who knows the (unguessable) token, until the share expires.
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_deck_share` (
|
|
`id` int(7) unsigned zerofill NOT NULL auto_increment,
|
|
`token` varchar(64) COLLATE utf8mb4_bin NOT NULL,
|
|
`name` varchar(64) NOT NULL,
|
|
`created_by` int(7) unsigned NULL,
|
|
`created_at` datetime NOT NULL,
|
|
`expires_at` datetime NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `token` (`token`),
|
|
KEY `expires_at` (`expires_at`),
|
|
FOREIGN KEY(`created_by`) REFERENCES `cockatrice_users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
-- Individual decks inside a share bundle. Content is materialized at share
|
|
-- time so expiring/deleting a share can cascade cleanly. The metadata columns
|
|
-- are nullable because Qt's MySQL driver binds empty QStrings as NULL when
|
|
-- using prepared statements.
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_deck_share_item` (
|
|
`id` int(7) unsigned zerofill NOT NULL auto_increment,
|
|
`share_id` int(7) unsigned zerofill NOT NULL,
|
|
`name` varchar(50) NOT NULL,
|
|
`tags` text NULL,
|
|
`banner_card` varchar(255) NULL,
|
|
`game_format` varchar(50) NULL,
|
|
`color_identity` varchar(5) NULL,
|
|
`content` text NOT NULL,
|
|
`position` int(7) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `share_id` (`share_id`),
|
|
FOREIGN KEY(`share_id`) REFERENCES `cockatrice_deck_share`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_decklist_folders` (
|
|
`id` int(7) unsigned zerofill NOT NULL auto_increment,
|
|
`id_parent` int(7) unsigned zerofill NOT NULL,
|
|
`id_user` int(7) unsigned NULL,
|
|
`name` varchar(30) NOT NULL,
|
|
`is_public` tinyint(1) NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (`id`),
|
|
KEY `ParentPlusUser` (`id_parent`,`id_user`),
|
|
FOREIGN KEY(`id_user`) REFERENCES `cockatrice_users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_ignorelist` (
|
|
`id_user1` int(7) unsigned NOT NULL,
|
|
`id_user2` int(7) unsigned NOT NULL,
|
|
UNIQUE KEY `key` (`id_user1`, `id_user2`),
|
|
FOREIGN KEY(`id_user1`) REFERENCES `cockatrice_users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
FOREIGN KEY(`id_user2`) REFERENCES `cockatrice_users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_buddylist` (
|
|
`id_user1` int(7) unsigned NOT NULL,
|
|
`id_user2` int(7) unsigned NOT NULL,
|
|
UNIQUE KEY `key` (`id_user1`, `id_user2`),
|
|
FOREIGN KEY(`id_user1`) REFERENCES `cockatrice_users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
FOREIGN KEY(`id_user2`) REFERENCES `cockatrice_users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
-- rooms
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_rooms` (
|
|
`id` int(7) unsigned NOT NULL auto_increment,
|
|
`name` varchar(50) NOT NULL,
|
|
`descr` varchar(255) NOT NULL,
|
|
`permissionlevel` enum('NONE','REGISTERED','MODERATOR','ADMINISTRATOR') NOT NULL,
|
|
`privlevel` enum('NONE','PRIVILEGED','VIP','DONATOR') NOT NULL,
|
|
`auto_join` tinyint(1) default 0,
|
|
`join_message` varchar(255) NOT NULL,
|
|
`chat_history_size` int(4) NOT NULL,
|
|
`id_server` tinyint(3) NOT NULL DEFAULT 1,
|
|
PRIMARY KEY (`id`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_rooms_gametypes` (
|
|
`id_room` int(7) unsigned NOT NULL,
|
|
`name` varchar(50) NOT NULL,
|
|
`id_server` tinyint(3) NOT NULL DEFAULT 1,
|
|
FOREIGN KEY(`id_room`) REFERENCES `cockatrice_rooms`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_rooms_channels` (
|
|
`id_room` int(7) unsigned NOT NULL,
|
|
`id_server` tinyint(3) NOT NULL DEFAULT 1,
|
|
`channel_id` varchar(50) NOT NULL,
|
|
`display_name` varchar(50) NOT NULL,
|
|
`access_level` ENUM('public','registered','judge','moderator','admin','developer') NOT NULL DEFAULT 'public',
|
|
`write_access_level` ENUM('public','registered','judge','moderator','admin','developer') NULL DEFAULT NULL,
|
|
`banner_message` varchar(255) NOT NULL DEFAULT '',
|
|
PRIMARY KEY (`id_room`, `id_server`, `channel_id`),
|
|
FOREIGN KEY(`id_room`) REFERENCES `cockatrice_rooms`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
-- games
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_games` (
|
|
`room_name` varchar(255) NOT NULL,
|
|
`id` int(7) unsigned NOT NULL auto_increment,
|
|
`descr` varchar(50) default NULL,
|
|
`creator_name` varchar(35) NOT NULL,
|
|
`password` tinyint(1) NOT NULL,
|
|
`game_types` varchar(255) NOT NULL,
|
|
`player_count` tinyint(3) NOT NULL,
|
|
`time_started` datetime default NULL,
|
|
`time_finished` datetime default NULL,
|
|
PRIMARY KEY (`id`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_games_players` (
|
|
`id_game` int(7) unsigned zerofill NOT NULL,
|
|
`player_name` varchar(35) NOT NULL,
|
|
FOREIGN KEY(`id_game`) REFERENCES `cockatrice_games`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
-- Note: an empty row with id_game = NULL is created when the game is created,
|
|
-- and then updated when the game ends with the full replay data.
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_replays` (
|
|
`id` int(7) NOT NULL AUTO_INCREMENT,
|
|
`id_game` int(7) unsigned NULL,
|
|
`duration` int(7) NOT NULL,
|
|
`replay` mediumblob NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
FOREIGN KEY(`id_game`) REFERENCES `cockatrice_games`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_replays_access` (
|
|
`id_game` int(7) unsigned NOT NULL,
|
|
`id_player` int(7) unsigned NOT NULL,
|
|
`replay_name` varchar(255) NOT NULL,
|
|
`do_not_hide` tinyint(1) NOT NULL,
|
|
KEY `id_player` (`id_player`),
|
|
FOREIGN KEY(`id_game`) REFERENCES `cockatrice_games`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
FOREIGN KEY(`id_player`) REFERENCES `cockatrice_users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
-- server administration
|
|
|
|
-- Note: unused table
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_servers` (
|
|
`id` mediumint(8) unsigned NOT NULL,
|
|
`ssl_cert` text NOT NULL,
|
|
`hostname` varchar(255) NOT NULL,
|
|
`address` varchar(255) NOT NULL,
|
|
`game_port` mediumint(8) unsigned NOT NULL,
|
|
`control_port` mediumint(9) NOT NULL,
|
|
PRIMARY KEY (`id`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_uptime` (
|
|
`id_server` tinyint(3) NOT NULL,
|
|
`timest` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
`uptime` int(11) NOT NULL,
|
|
`users_count` int(11) NOT NULL,
|
|
`mods_count` int(11) NOT NULL DEFAULT 0,
|
|
`mods_list` TEXT,
|
|
`games_count` int(11) NOT NULL,
|
|
`rx_bytes` int(11) NOT NULL,
|
|
`tx_bytes` int(11) NOT NULL,
|
|
PRIMARY KEY (`timest`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_servermessages` (
|
|
`id_server` tinyint(3) not null default 1,
|
|
`timest` datetime NOT NULL default '0000-00-00 00:00:00',
|
|
`message` text,
|
|
PRIMARY KEY (`timest`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_sessions` (
|
|
`id` int(9) NOT NULL AUTO_INCREMENT,
|
|
`user_name` varchar(35) NOT NULL,
|
|
`id_server` tinyint(3) NOT NULL,
|
|
`ip_address` varchar(45) NOT NULL,
|
|
`start_time` datetime NOT NULL,
|
|
`end_time` datetime DEFAULT NULL,
|
|
`clientid` varchar(15) NOT NULL,
|
|
`connection_type` ENUM('tcp', 'websocket'),
|
|
PRIMARY KEY (`id`),
|
|
KEY `username` (`user_name`),
|
|
INDEX `idx_start_time` (`start_time`),
|
|
INDEX `idx_clientid` (`clientid`),
|
|
INDEX `idx_ip_address` (`ip_address`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
-- server moderation
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_bans` (
|
|
`user_name` varchar(35) NOT NULL,
|
|
`ip_address` varchar(45) NOT NULL,
|
|
`id_admin` int(7) unsigned zerofill NOT NULL,
|
|
`time_from` datetime NOT NULL,
|
|
`minutes` int(6) NOT NULL,
|
|
`reason` text NOT NULL,
|
|
`visible_reason` text NOT NULL,
|
|
`clientid` varchar(15) NOT NULL,
|
|
PRIMARY KEY (`user_name`,`time_from`),
|
|
KEY `time_from` (`time_from`,`ip_address`),
|
|
KEY `ip_address` (`ip_address`),
|
|
INDEX `idx_user_name` (`user_name`),
|
|
FOREIGN KEY(`id_admin`) REFERENCES `cockatrice_users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_warnings` (
|
|
`user_id` int(7) unsigned NOT NULL,
|
|
`user_name` varchar(35) NOT NULL,
|
|
`mod_name` varchar(35) NOT NULL,
|
|
`reason` text NOT NULL,
|
|
`time_of` datetime NOT NULL,
|
|
`clientid` varchar(15) NOT NULL,
|
|
PRIMARY KEY (`user_id`,`time_of`),
|
|
INDEX `idx_time_of` (`time_of`),
|
|
INDEX `idx_user_name` (`user_name`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_reports` (
|
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
|
`reporter_id` int(7) unsigned NULL,
|
|
`reporter_name` varchar(35) NOT NULL,
|
|
`reported_user_id` int(7) unsigned NULL,
|
|
`reported_user_name` varchar(35) NOT NULL,
|
|
`game_id` int(7) unsigned NULL,
|
|
`room_id` int(7) unsigned NULL,
|
|
`category` varchar(255) NOT NULL,
|
|
`description` text NOT NULL,
|
|
`chat_log` mediumtext NULL,
|
|
`created_at` datetime NOT NULL,
|
|
`resolution_time` datetime NULL,
|
|
`status` enum('open','assigned','resolved','dismissed') NOT NULL DEFAULT 'open',
|
|
`assigned_to` int(7) unsigned NULL,
|
|
`resolved_by` int(7) unsigned NULL,
|
|
`resolution_note` text,
|
|
`notified` tinyint(1) NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (`id`),
|
|
INDEX `idx_status` (`status`),
|
|
INDEX `idx_created` (`created_at`),
|
|
INDEX `idx_reporter_id_created` (`reporter_id`, `created_at`),
|
|
INDEX `idx_reported_user_name` (`reported_user_name`),
|
|
INDEX `idx_status_created` (`status`, `created_at`),
|
|
FOREIGN KEY (`reporter_id`) REFERENCES `cockatrice_users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE,
|
|
FOREIGN KEY (`reported_user_id`) REFERENCES `cockatrice_users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE,
|
|
FOREIGN KEY (`assigned_to`) REFERENCES `cockatrice_users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE,
|
|
FOREIGN KEY (`resolved_by`) REFERENCES `cockatrice_users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_report_comments` (
|
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
|
`report_id` int(11) unsigned NOT NULL,
|
|
`author_name` varchar(35) NOT NULL,
|
|
`author_id` int(7) unsigned NULL,
|
|
`comment_text` text NOT NULL,
|
|
`created_at` datetime NOT NULL,
|
|
`is_moderator` tinyint(1) NOT NULL DEFAULT 0,
|
|
`notified` tinyint(1) NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (`id`),
|
|
INDEX `idx_report_id` (`report_id`),
|
|
INDEX `idx_notified` (`notified`),
|
|
FOREIGN KEY (`report_id`) REFERENCES `cockatrice_reports`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
FOREIGN KEY (`author_id`) REFERENCES `cockatrice_users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_log` (
|
|
`log_time` datetime NOT NULL,
|
|
`sender_id` int(7) unsigned NULL,
|
|
`sender_name` varchar(35) NOT NULL,
|
|
`sender_ip` varchar(45) NOT NULL,
|
|
`log_message` text NOT NULL,
|
|
`target_type` ENUM('room', 'game', 'chat', 'room_channel'),
|
|
`target_id` int(7) NULL,
|
|
`target_name` varchar(50) NOT NULL,
|
|
`channel` varchar(50) NULL,
|
|
KEY `sender_name` (`sender_name`),
|
|
KEY `sender_ip` (`sender_ip`),
|
|
KEY `target_id` (`target_id`),
|
|
KEY `target_name` (`target_name`),
|
|
INDEX `idx_log_time` (`log_time`),
|
|
FOREIGN KEY(`sender_id`) REFERENCES `cockatrice_users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
-- No FK on target_id, it can be zero
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_activation_emails` (
|
|
`name` varchar(35) NOT NULL,
|
|
FOREIGN KEY(`name`) REFERENCES `cockatrice_users`(`name`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_user_analytics` (
|
|
`id` int(7) unsigned zerofill NOT NULL,
|
|
`client_ver` varchar(35) NOT NULL,
|
|
`last_login` datetime NOT NULL,
|
|
`notes` varchar(255) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
INDEX `idx_last_login` (`last_login`),
|
|
FOREIGN KEY(`id`) REFERENCES `cockatrice_users`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_donations` (
|
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
|
`username` varchar(35) DEFAULT NULL,
|
|
`email` varchar(255) DEFAULT NULL,
|
|
`payment_pre_fee` double DEFAULT NULL,
|
|
`payment_post_fee` double DEFAULT NULL,
|
|
`term_length` int(11) DEFAULT NULL,
|
|
`date` varchar(255) DEFAULT NULL,
|
|
`pp_type` varchar(255) DEFAULT NULL,
|
|
PRIMARY KEY (`id`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_forgot_password` (
|
|
`id` int(7) unsigned zerofill NOT NULL auto_increment,
|
|
`name` varchar(35) NOT NULL,
|
|
`requestDate` datetime NOT NULL default '0000-00-00 00:00:00',
|
|
`emailed` tinyint(1) NOT NULL default 0,
|
|
PRIMARY KEY (`id`),
|
|
KEY `user_name` (`name`),
|
|
INDEX `idx_emailed` (`emailed`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_audit` (
|
|
`id` int(7) unsigned zerofill NOT NULL auto_increment,
|
|
`id_server` tinyint(3) NOT NULL,
|
|
`name` varchar(35) NOT NULL,
|
|
`ip_address` varchar(45) NOT NULL,
|
|
`clientid` varchar(15) NOT NULL,
|
|
`incidentDate` datetime NOT NULL default '0000-00-00 00:00:00',
|
|
`action` varchar(35) NOT NULL,
|
|
`results` ENUM('fail', 'success') NOT NULL DEFAULT 'fail',
|
|
`details` varchar(255) NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `user_name` (`name`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `cockatrice_card_art_name_rules` (
|
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
|
`card_name` varchar(255) NOT NULL,
|
|
`card_provider_id` varchar(255) NOT NULL,
|
|
`mode` enum('ALLOW','DENY') NOT NULL,
|
|
`reason` varchar(255) DEFAULT NULL,
|
|
`created_by` int(7) unsigned DEFAULT NULL,
|
|
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `uniq_provider_card_name` (`card_provider_id`, `card_name`),
|
|
KEY `idx_mode` (`mode`),
|
|
FOREIGN KEY (`created_by`) REFERENCES `cockatrice_users`(`id`)
|
|
ON DELETE SET NULL
|
|
ON UPDATE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;
|