Echelon system (#18860)

* Murders the old prefixed SQL template

* This no longer needs to exist

* A little refactoring before we do some trollign

* Echelon subsystem

* In hindsight, this shouldn't be here because global variables dont perssist

* Missed a constraint

* Simplifies flag checking logic

* Missed my bloody comma

* Updates outdated comment in config

* Removes the id column and sets ip as the new primary key

* This is embarassing

* Fixes alignment

* Adds round id to ban message

* baby proofs the code

* Oops, can't use it after deleting it

* Changes the ban message so that bans on abusive ISPs make more sense
This commit is contained in:
alexkar598
2023-05-14 17:37:44 -04:00
committed by GitHub
parent 19286096ed
commit 37a65cbc4b
12 changed files with 150 additions and 637 deletions

View File

@@ -133,8 +133,6 @@ jobs:
#tools/travis/install_extools.sh #tools/travis/install_extools.sh
mysql -u root -h 127.0.0.1 -e 'CREATE DATABASE tg_travis;' mysql -u root -h 127.0.0.1 -e 'CREATE DATABASE tg_travis;'
mysql -u root -h 127.0.0.1 tg_travis < SQL/tgstation_schema.sql mysql -u root -h 127.0.0.1 tg_travis < SQL/tgstation_schema.sql
mysql -u root -h 127.0.0.1 -e 'CREATE DATABASE tg_travis_prefixed;'
mysql -u root -h 127.0.0.1 tg_travis_prefixed < SQL/tgstation_schema_prefixed.sql
- name: Compile - name: Compile
run: | run: |
tools/build/build --ci dm -DCIBUILDING tools/build/build --ci dm -DCIBUILDING

View File

@@ -1,13 +1,30 @@
Any time you make a change to the schema files, remember to increment the database schema version. Generally increment the minor number, major should be reserved for significant changes to the schema. Both values go up to 255. Any time you make a change to the schema files, remember to increment the database schema version. Generally increment the minor number, major should be reserved for significant changes to the schema. Both values go up to 255.
The latest database version is 5.12; The query to update the schema revision table is: The latest database version is 5.13; The query to update the schema revision table is:
INSERT INTO `schema_revision` (`major`, `minor`) VALUES (5, 12); INSERT INTO `schema_revision` (`major`, `minor`) VALUES (5, 13);
or or
INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (5, 12); INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (5, 13);
In any query remember to add a prefix to the table names if you use one. In any query remember to add a prefix to the table names if you use one.
version 5.13 2023-05-10
Adds allow_vpn to bound credentials flags
ALTER TABLE `bound_credentials` MODIFY COLUMN flags set('bypass_bans','allow_proxies') DEFAULT NULL NULL;
CREATE TABLE `proxy_cache` (
`ip` int(11) unsigned NOT NULL,
`data` mediumtext NOT NULL,
`last_updated` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`ip`),
CONSTRAINT `data` CHECK (json_valid(`data`))
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE OR REPLACE EVENT proxy_cache_ttl
ON SCHEDULE EVERY 1 HOUR
DO
DELETE FROM proxy_cache WHERE (last_updated + INTERVAL 1 DAY) < current_timestamp();
version 5.12 2023-04-10 version 5.12 2023-04-10
Adds playtime to notes Adds playtime to notes

View File

@@ -3,7 +3,6 @@
/*!50503 SET NAMES utf8mb4 */; /*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
DROP TABLE IF EXISTS `achievements`; DROP TABLE IF EXISTS `achievements`;
CREATE TABLE IF NOT EXISTS `achievements` ( CREATE TABLE IF NOT EXISTS `achievements` (
`name` mediumtext NOT NULL, `name` mediumtext NOT NULL,
@@ -122,7 +121,7 @@ CREATE TABLE `bound_credentials` (
`ckey` varchar(32) NOT NULL, `ckey` varchar(32) NOT NULL,
`computerid` varchar(32) DEFAULT NULL, `computerid` varchar(32) DEFAULT NULL,
`ip` int(10) unsigned DEFAULT NULL, `ip` int(10) unsigned DEFAULT NULL,
`flags` set('bypass_bans') DEFAULT NULL, `flags` set('bypass_bans','allow_proxies') DEFAULT NULL,
`comment` text NULL, `comment` text NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `idx_ckey_lookup` (`ckey`), KEY `idx_ckey_lookup` (`ckey`),
@@ -533,6 +532,19 @@ CREATE TABLE IF NOT EXISTS `stickyban_matched_ip` (
PRIMARY KEY (`stickyban`,`matched_ip`) PRIMARY KEY (`stickyban`,`matched_ip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `proxy_cache`;
CREATE TABLE `proxy_cache` (
`ip` int(11) unsigned NOT NULL,
`data` mediumtext NOT NULL,
`last_updated` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`ip`),
CONSTRAINT `data` CHECK (json_valid(`data`))
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE OR REPLACE EVENT proxy_cache_ttl
ON SCHEDULE EVERY 1 HOUR
DO
DELETE FROM proxy_cache WHERE (last_updated + INTERVAL 1 DAY) < current_timestamp();
-- Dumping structure for trigger yogstation_copy.role_timeTlogdelete -- Dumping structure for trigger yogstation_copy.role_timeTlogdelete
DROP TRIGGER IF EXISTS `role_timeTlogdelete`; DROP TRIGGER IF EXISTS `role_timeTlogdelete`;

View File

@@ -1,571 +0,0 @@
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
DROP TABLE IF EXISTS `SS13_achievements`;
CREATE TABLE IF NOT EXISTS `SS13_achievements` (
`name` mediumtext NOT NULL,
`id` int(10) unsigned NOT NULL,
`descr` varchar(2048) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_admin`;
CREATE TABLE IF NOT EXISTS `SS13_admin` (
`ckey` varchar(32) NOT NULL,
`rank` varchar(32) NOT NULL,
PRIMARY KEY (`ckey`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_admin_log`;
CREATE TABLE IF NOT EXISTS `SS13_admin_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`datetime` datetime NOT NULL,
`round_id` int(10) unsigned NOT NULL,
`adminckey` varchar(32) NOT NULL,
`adminip` int(10) unsigned NOT NULL,
`operation` enum('add admin','remove admin','change admin rank','add rank','remove rank','change rank flags', 'add mentor') NOT NULL,
`target` varchar(32) NOT NULL,
`log` varchar(1000) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=342 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_admin_ranks`;
CREATE TABLE IF NOT EXISTS `SS13_admin_ranks` (
`rank` varchar(32) NOT NULL,
`flags` smallint(5) unsigned NOT NULL,
`exclude_flags` smallint(5) unsigned NOT NULL,
`can_edit_flags` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`rank`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `ss13_admin_tickets`;
CREATE TABLE IF NOT EXISTS `ss13_admin_tickets` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`round_id` int(10) unsigned NOT NULL DEFAULT 0,
`ticket_id` int(10) unsigned NOT NULL DEFAULT 0,
`when` datetime NOT NULL DEFAULT current_timestamp(),
`ckey` varchar(32) NOT NULL,
`a_ckey` varchar(32),
PRIMARY KEY (`id`),
KEY `idx_round` (`round_id`),
KEY `idx_round_ticket` (`round_id`,`ticket_id`)
) ENGINE=InnoDB AUTO_INCREMENT=157319 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `ss13_admin_ticket_interactions`;
CREATE TABLE IF NOT EXISTS `ss13_admin_ticket_content` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ticket_id` int(10) unsigned,
`when` datetime NOT NULL DEFAULT current_timestamp(),
`user` varchar(32) NOT NULL,
`text` text,
PRIMARY KEY (`id`),
FOREIGN KEY (`ticket_id`) REFERENCES `ss13_admin_tickets`(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_antag_tokens`;
CREATE TABLE IF NOT EXISTS `SS13_antag_tokens` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ckey` varchar(32) NOT NULL,
`reason` varchar(2048) NOT NULL,
`denial_reason` varchar(2048) DEFAULT NULL,
`applying_admin` varchar(32) NOT NULL,
`denying_admin` varchar(32) DEFAULT NULL,
`granted_time` datetime NOT NULL,
`redeemed` tinyint(3) unsigned NOT NULL DEFAULT 0,
`round_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=273 DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `SS13_ban`;
CREATE TABLE IF NOT EXISTS `SS13_ban` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`bantime` datetime NOT NULL,
`server_ip` int(10) unsigned NOT NULL,
`server_port` smallint(5) unsigned NOT NULL,
`round_id` int(10) unsigned NOT NULL,
`role` varchar(32) DEFAULT NULL,
`expiration_time` datetime DEFAULT NULL,
`applies_to_admins` tinyint(3) unsigned NOT NULL DEFAULT 0,
`reason` varchar(2048) NOT NULL,
`ckey` varchar(32) DEFAULT NULL,
`ip` int(10) unsigned DEFAULT NULL,
`computerid` varchar(32) DEFAULT NULL,
`a_ckey` varchar(32) NOT NULL,
`a_ip` int(10) unsigned NOT NULL,
`a_computerid` varchar(32) NOT NULL,
`who` varchar(2048) NOT NULL,
`adminwho` varchar(2048) NOT NULL,
`edits` mediumtext DEFAULT NULL,
`unbanned_datetime` datetime DEFAULT NULL,
`unbanned_ckey` varchar(32) DEFAULT NULL,
`unbanned_ip` int(10) unsigned DEFAULT NULL,
`unbanned_computerid` varchar(32) DEFAULT NULL,
`unbanned_round_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_ban_isbanned` (`ckey`,`role`,`unbanned_datetime`,`expiration_time`),
KEY `idx_ban_isbanned_details` (`ckey`,`ip`,`computerid`,`role`,`unbanned_datetime`,`expiration_time`),
KEY `idx_ban_count` (`bantime`,`a_ckey`,`applies_to_admins`,`unbanned_datetime`,`expiration_time`)
) ENGINE=InnoDB AUTO_INCREMENT=39587 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_bound_credentials`;
CREATE TABLE `SS13_bound_credentials` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ckey` varchar(32) NOT NULL,
`computerid` varchar(32) DEFAULT NULL,
`ip` int(10) unsigned DEFAULT NULL,
`flags` set('bypass_bans') DEFAULT NULL,
`comment` text NULL,
PRIMARY KEY (`id`),
KEY `idx_ckey_lookup` (`ckey`),
KEY `idx_cid_lookup` (`computerid`),
KEY `idx_ip_lookup` (`ip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_connection_log`;
CREATE TABLE IF NOT EXISTS `SS13_connection_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`datetime` datetime DEFAULT NULL,
`left` datetime DEFAULT NULL,
`server_ip` int(10) unsigned NOT NULL,
`server_port` smallint(5) unsigned NOT NULL,
`round_id` int(10) unsigned NOT NULL,
`ckey` varchar(45) DEFAULT NULL,
`ip` int(10) unsigned NOT NULL,
`computerid` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_review` (`ckey`, `computerid`, `ip`)
) ENGINE=InnoDB AUTO_INCREMENT=4192042 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_death`;
CREATE TABLE IF NOT EXISTS `SS13_death` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pod` varchar(50) NOT NULL,
`x_coord` smallint(5) unsigned NOT NULL,
`y_coord` smallint(5) unsigned NOT NULL,
`z_coord` smallint(5) unsigned NOT NULL,
`mapname` varchar(32) NOT NULL,
`server_ip` int(10) unsigned NOT NULL,
`server_port` smallint(5) unsigned NOT NULL,
`round_id` int(11) NOT NULL,
`tod` datetime NOT NULL COMMENT 'Time of death',
`job` varchar(32) NOT NULL,
`special` varchar(32) DEFAULT NULL,
`name` varchar(96) NOT NULL,
`byondkey` varchar(32) NOT NULL,
`laname` varchar(96) DEFAULT NULL,
`lakey` varchar(32) DEFAULT NULL,
`bruteloss` smallint(5) unsigned NOT NULL,
`brainloss` smallint(5) unsigned NOT NULL,
`fireloss` smallint(5) unsigned NOT NULL,
`oxyloss` smallint(5) unsigned NOT NULL,
`toxloss` smallint(5) unsigned NOT NULL,
`cloneloss` smallint(5) unsigned NOT NULL,
`staminaloss` smallint(5) unsigned NOT NULL,
`last_words` varchar(255) DEFAULT NULL,
`suicide` tinyint(4) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1422836 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_donors`;
CREATE TABLE IF NOT EXISTS `SS13_donors` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ckey` varchar(32) NOT NULL,
`discord_id` varchar(32) DEFAULT NULL,
`transaction_id` varchar(70) NOT NULL,
`amount` decimal(10,2) NOT NULL,
`datetime` timestamp NOT NULL DEFAULT current_timestamp(),
`expiration_time` datetime DEFAULT NULL,
`revoked` int(11) DEFAULT NULL,
`revoked_ckey` varchar(32) DEFAULT NULL,
`revoked_time` datetime DEFAULT NULL,
`payer_email` varchar(256) DEFAULT NULL,
`status` varchar(32) NOT NULL,
`notes` varchar(1024) DEFAULT NULL,
`valid` tinyint(4) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`),
UNIQUE KEY `transaction_id` (`transaction_id`),
KEY `ckey` (`ckey`),
KEY `forum_username` (`discord_id`)
) ENGINE=InnoDB AUTO_INCREMENT=761 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_earned_achievements`;
CREATE TABLE IF NOT EXISTS `SS13_earned_achievements` (
`ckey` varchar(32) NOT NULL,
`id` int(10) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_feedback`;
CREATE TABLE IF NOT EXISTS `SS13_feedback` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`datetime` datetime NOT NULL,
`round_id` int(10) unsigned NOT NULL,
`key_name` varchar(32) NOT NULL,
`key_type` enum('text','amount','tally','nested tally','associative') NOT NULL,
`version` tinyint(3) unsigned NOT NULL,
`json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`json`)),
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=349150 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_feedback_normalized`;
CREATE TABLE IF NOT EXISTS `SS13_feedback_normalized` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`datetime` datetime NOT NULL,
`round_id` int(10) unsigned NOT NULL,
`category_primary` text NOT NULL DEFAULT '',
`category_secondary` text NOT NULL DEFAULT '',
`category_tertiary` text NOT NULL DEFAULT '',
`version` tinyint(3) unsigned NOT NULL,
`data` longtext NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6204920 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_ipintel`;
CREATE TABLE IF NOT EXISTS `SS13_ipintel` (
`ip` int(10) unsigned NOT NULL,
`date` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`intel` double NOT NULL DEFAULT 0,
PRIMARY KEY (`ip`),
KEY `idx_ipintel` (`ip`,`intel`,`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_legacy_population`;
CREATE TABLE IF NOT EXISTS `SS13_legacy_population` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`playercount` int(11) DEFAULT NULL,
`admincount` int(11) DEFAULT NULL,
`time` datetime NOT NULL,
`server_ip` int(10) unsigned NOT NULL,
`server_port` smallint(5) unsigned NOT NULL,
`round_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=490160 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_library`;
CREATE TABLE IF NOT EXISTS `SS13_library` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`author` varchar(45) NOT NULL,
`title` varchar(45) NOT NULL,
`content` mediumtext NOT NULL,
`category` enum('Any','Fiction','Non-Fiction','Adult','Reference','Religion') NOT NULL,
`ckey` varchar(32) NOT NULL DEFAULT 'LEGACY',
`datetime` datetime NOT NULL,
`deleted` tinyint(3) unsigned DEFAULT NULL,
`round_id_created` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `deleted_idx` (`deleted`),
KEY `idx_lib_id_del` (`id`,`deleted`),
KEY `idx_lib_del_title` (`deleted`,`title`),
KEY `idx_lib_search` (`deleted`,`author`,`title`,`category`)
) ENGINE=InnoDB AUTO_INCREMENT=2017 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_loa`;
CREATE TABLE IF NOT EXISTS `SS13_loa` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ckey` varchar(32) NOT NULL,
`time` date NOT NULL,
`expiry_time` date NOT NULL,
`revoked` bit(1) DEFAULT NULL,
`reason` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=419 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_mentor`;
CREATE TABLE IF NOT EXISTS `SS13_mentor` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ckey` varchar(32) NOT NULL,
`position` varchar(32) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=130 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_mentor_memo`;
CREATE TABLE IF NOT EXISTS `SS13_mentor_memo` (
`ckey` varchar(32) NOT NULL,
`memotext` mediumtext NOT NULL,
`timestamp` datetime NOT NULL,
`last_editor` varchar(32) DEFAULT NULL,
`edits` mediumtext DEFAULT NULL,
PRIMARY KEY (`ckey`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_messages`;
CREATE TABLE IF NOT EXISTS `SS13_messages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(32) NOT NULL,
`targetckey` varchar(32) NOT NULL,
`adminckey` varchar(32) NOT NULL,
`text` mediumtext NOT NULL,
`timestamp` datetime NOT NULL,
`server` varchar(32) DEFAULT NULL,
`server_ip` int(10) unsigned NOT NULL,
`server_port` smallint(5) unsigned NOT NULL,
`round_id` int(10) unsigned NOT NULL,
`secret` tinyint(1) DEFAULT 1,
`expire_timestamp` datetime DEFAULT NULL,
`lasteditor` varchar(32) DEFAULT NULL,
`edits` mediumtext DEFAULT NULL,
`deleted` tinyint(3) unsigned NOT NULL DEFAULT 0,
`playtime` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_msg_ckey_time` (`targetckey`,`timestamp`,`deleted`),
KEY `idx_msg_type_ckeys_time` (`type`,`targetckey`,`adminckey`,`timestamp`,`deleted`),
KEY `idx_msg_type_ckey_time_odr` (`type`,`targetckey`,`timestamp`,`deleted`)
) ENGINE=InnoDB AUTO_INCREMENT=75629 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_mfa_logins`;
CREATE TABLE IF NOT EXISTS `SS13_mfa_logins` (
`ckey` varchar(32) NOT NULL,
`ip` int(10) unsigned NOT NULL,
`cid` varchar(32) NOT NULL,
`datetime` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`ckey`,`ip`,`cid`,`datetime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_misc`;
CREATE TABLE IF NOT EXISTS `SS13_misc` (
`key` varchar(32) NOT NULL,
`value` varchar(2048) NOT NULL,
PRIMARY KEY (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_player`;
CREATE TABLE IF NOT EXISTS `SS13_player` (
`ckey` varchar(32) NOT NULL,
`byond_key` varchar(32) DEFAULT NULL,
`firstseen` datetime NOT NULL,
`firstseen_round_id` int(10) unsigned NOT NULL,
`lastseen` datetime NOT NULL,
`lastseen_round_id` int(10) unsigned NOT NULL,
`ip` int(10) unsigned NOT NULL,
`computerid` varchar(32) NOT NULL,
`lastadminrank` varchar(32) NOT NULL DEFAULT 'Player',
`accountjoindate` date DEFAULT NULL,
`flags` int(11) NOT NULL DEFAULT 0,
`discord_id` bigint(20) DEFAULT NULL,
`antag_tokens` int(10) unsigned NOT NULL DEFAULT 0,
`credits` bigint(20) unsigned NOT NULL DEFAULT 0,
`antag_weight` mediumint(8) unsigned NOT NULL DEFAULT 100,
`job_whitelisted` tinyint(3) unsigned NOT NULL DEFAULT 0,
`totp_seed` varchar(20),
`mfa_backup` varchar(128),
PRIMARY KEY (`ckey`),
KEY `idx_player_cid_ckey` (`computerid`,`ckey`),
KEY `idx_player_ip_ckey` (`ip`,`ckey`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_poll_option`;
CREATE TABLE IF NOT EXISTS `SS13_poll_option` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pollid` int(11) NOT NULL,
`text` varchar(255) NOT NULL,
`minval` int(11) DEFAULT NULL,
`maxval` int(11) DEFAULT NULL,
`descmin` varchar(32) DEFAULT NULL,
`descmid` varchar(32) DEFAULT NULL,
`descmax` varchar(32) DEFAULT NULL,
`default_percentage_calc` tinyint(3) unsigned NOT NULL DEFAULT 1,
PRIMARY KEY (`id`),
KEY `idx_pop_pollid` (`pollid`)
) ENGINE=InnoDB AUTO_INCREMENT=272 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_poll_question`;
CREATE TABLE IF NOT EXISTS `SS13_poll_question` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`polltype` enum('OPTION','TEXT','NUMVAL','MULTICHOICE','IRV') NOT NULL,
`starttime` datetime NOT NULL,
`endtime` datetime NOT NULL,
`question` varchar(255) NOT NULL,
`adminonly` tinyint(3) unsigned NOT NULL,
`multiplechoiceoptions` int(11) DEFAULT NULL,
`createdby_ckey` varchar(32) DEFAULT NULL,
`createdby_ip` int(10) unsigned NOT NULL,
`dontshow` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_pquest_question_time_ckey` (`question`,`starttime`,`endtime`,`createdby_ckey`,`createdby_ip`),
KEY `idx_pquest_time_admin` (`starttime`,`endtime`,`adminonly`),
KEY `idx_pquest_id_time_type_admin` (`id`,`starttime`,`endtime`,`polltype`,`adminonly`)
) ENGINE=InnoDB AUTO_INCREMENT=61 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_poll_textreply`;
CREATE TABLE IF NOT EXISTS `SS13_poll_textreply` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`datetime` datetime NOT NULL,
`pollid` int(11) NOT NULL,
`ckey` varchar(32) NOT NULL,
`ip` int(10) unsigned NOT NULL,
`replytext` varchar(2048) NOT NULL,
`adminrank` varchar(32) NOT NULL DEFAULT 'Player',
PRIMARY KEY (`id`),
KEY `idx_ptext_pollid_ckey` (`pollid`,`ckey`)
) ENGINE=InnoDB AUTO_INCREMENT=365 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_poll_vote`;
CREATE TABLE IF NOT EXISTS `SS13_poll_vote` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`datetime` datetime NOT NULL,
`pollid` int(11) NOT NULL,
`optionid` int(11) NOT NULL,
`ckey` varchar(32) NOT NULL,
`ip` int(10) unsigned NOT NULL,
`adminrank` varchar(32) NOT NULL,
`rating` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_pvote_pollid_ckey` (`pollid`,`ckey`),
KEY `idx_pvote_optionid_ckey` (`optionid`,`ckey`)
) ENGINE=InnoDB AUTO_INCREMENT=12987 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_role_time`;
CREATE TABLE IF NOT EXISTS `SS13_role_time` (
`ckey` varchar(32) NOT NULL,
`job` varchar(128) NOT NULL,
`minutes` int(10) unsigned NOT NULL,
PRIMARY KEY (`ckey`,`job`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_role_time_log`;
CREATE TABLE IF NOT EXISTS `SS13_role_time_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`ckey` varchar(32) NOT NULL,
`job` varchar(128) NOT NULL,
`delta` int(11) NOT NULL,
`datetime` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`id`),
KEY `ckey` (`ckey`),
KEY `job` (`job`),
KEY `datetime` (`datetime`)
) ENGINE=InnoDB AUTO_INCREMENT=7175905 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_round`;
CREATE TABLE IF NOT EXISTS `SS13_round` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`initialize_datetime` datetime NOT NULL,
`start_datetime` datetime DEFAULT NULL,
`shutdown_datetime` datetime DEFAULT NULL,
`end_datetime` datetime DEFAULT NULL,
`server_ip` int(10) unsigned NOT NULL,
`server_port` smallint(5) unsigned NOT NULL,
`commit_hash` char(40) DEFAULT NULL,
`game_mode` varchar(32) DEFAULT NULL,
`game_mode_result` varchar(64) DEFAULT NULL,
`end_state` varchar(64) DEFAULT NULL,
`shuttle_name` varchar(64) DEFAULT NULL,
`map_name` varchar(32) DEFAULT NULL,
`station_name` varchar(80) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32366 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_schema_revision`;
CREATE TABLE IF NOT EXISTS `SS13_schema_revision` (
`major` tinyint(3) unsigned NOT NULL,
`minor` tinyint(3) unsigned NOT NULL,
`date` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`major`,`minor`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_stickyban`;
CREATE TABLE IF NOT EXISTS `SS13_stickyban` (
`ckey` varchar(32) NOT NULL,
`reason` varchar(2048) NOT NULL,
`banning_admin` varchar(32) NOT NULL,
`datetime` datetime NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`ckey`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_stickyban_matched_cid`;
CREATE TABLE IF NOT EXISTS `SS13_stickyban_matched_cid` (
`stickyban` varchar(32) NOT NULL,
`matched_cid` varchar(32) NOT NULL,
`first_matched` datetime NOT NULL DEFAULT current_timestamp(),
`last_matched` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`stickyban`,`matched_cid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_stickyban_matched_ckey`;
CREATE TABLE IF NOT EXISTS `SS13_stickyban_matched_ckey` (
`stickyban` varchar(32) NOT NULL,
`matched_ckey` varchar(32) NOT NULL,
`first_matched` datetime NOT NULL DEFAULT current_timestamp(),
`last_matched` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`exempt` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`stickyban`,`matched_ckey`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_stickyban_matched_ip`;
CREATE TABLE IF NOT EXISTS `SS13_stickyban_matched_ip` (
`stickyban` varchar(32) NOT NULL,
`matched_ip` int(10) unsigned NOT NULL,
`first_matched` datetime NOT NULL DEFAULT current_timestamp(),
`last_matched` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`stickyban`,`matched_ip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Dumping structure for trigger yogstation_copy.role_timeTlogdelete
DROP TRIGGER IF EXISTS `role_timeTlogdelete`;
SET @OLDTMP_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO';
DELIMITER //
CREATE TRIGGER `role_timeTlogdelete` AFTER DELETE ON `SS13_role_time` FOR EACH ROW BEGIN INSERT into SS13_role_time_log (ckey, job, delta) VALUES (OLD.ckey, OLD.job, 0-OLD.minutes);
END//
DELIMITER ;
SET SQL_MODE=@OLDTMP_SQL_MODE;
-- Dumping structure for trigger yogstation_copy.role_timeTloginsert
DROP TRIGGER IF EXISTS `role_timeTloginsert`;
SET @OLDTMP_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO';
DELIMITER //
CREATE TRIGGER `role_timeTloginsert` AFTER INSERT ON `SS13_role_time` FOR EACH ROW BEGIN INSERT into SS13_role_time_log (ckey, job, delta) VALUES (NEW.ckey, NEW.job, NEW.minutes);
END//
DELIMITER ;
SET SQL_MODE=@OLDTMP_SQL_MODE;
-- Dumping structure for trigger yogstation_copy.role_timeTlogupdate
DROP TRIGGER IF EXISTS `role_timeTlogupdate`;
SET @OLDTMP_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO';
DELIMITER //
CREATE TRIGGER `role_timeTlogupdate` AFTER UPDATE ON `SS13_role_time` FOR EACH ROW BEGIN INSERT into SS13_role_time_log (ckey, job, delta) VALUES (NEW.CKEY, NEW.job, NEW.minutes-OLD.minutes);
END//
DELIMITER ;
SET SQL_MODE=@OLDTMP_SQL_MODE;
DROP TRIGGER IF EXISTS messagesTloghours;
CREATE TRIGGER messagesTloghours
BEFORE INSERT ON `SS13_messages` FOR EACH ROW
SET NEW.playtime = (SELECT minutes FROM SS13_role_time rt WHERE rt.ckey = NEW.targetckey AND rt.job = 'Living');
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

View File

@@ -21,7 +21,9 @@
* make sure you add an update to the schema_version stable in the db changelog * make sure you add an update to the schema_version stable in the db changelog
*/ */
#define DB_MINOR_VERSION 12 #define DB_MINOR_VERSION 13
#define DB_BOUND_CREDENTIALS_FLAG_BYPASS_BANS "bypass_bans"
#define DB_BOUND_CREDENTIALS_FLAG_ALLOW_PROXIES "allow_proxies"
//! ## Timing subsystem //! ## Timing subsystem
/** /**
@@ -156,6 +158,7 @@
#define INIT_ORDER_OVERLAY -6 #define INIT_ORDER_OVERLAY -6
#define INIT_ORDER_XKEYSCORE -10 #define INIT_ORDER_XKEYSCORE -10
#define INIT_ORDER_STICKY_BAN -10 #define INIT_ORDER_STICKY_BAN -10
#define INIT_ORDER_ECHELON -10
#define INIT_ORDER_LIGHTING -20 #define INIT_ORDER_LIGHTING -20
#define INIT_ORDER_SHUTTLE -21 #define INIT_ORDER_SHUTTLE -21
#define INIT_ORDER_MINOR_MAPPING -40 #define INIT_ORDER_MINOR_MAPPING -40

View File

@@ -0,0 +1,104 @@
SUBSYSTEM_DEF(echelon)
name = "ECHELON"
init_order = INIT_ORDER_ECHELON
flags = SS_NO_FIRE
var/enabled = TRUE
/datum/controller/subsystem/echelon/Initialize(timeofday, zlevel)
return SS_INIT_SUCCESS
/datum/controller/subsystem/echelon/proc/is_exception(ckey)
PRIVATE_PROC(TRUE)
var/datum/DBQuery/query_get_flags = SSdbcore.NewQuery({"
SELECT
flags
FROM [format_table_name("bound_credentials")]
WHERE
ckey = :ckey AND
FIND_IN_SET('[DB_BOUND_CREDENTIALS_FLAG_ALLOW_PROXIES]', flags)
"}, list("ckey" = ckey))
if(!query_get_flags.Execute())
qdel(query_get_flags)
return FALSE
var/result = query_get_flags.rows.len >= 1
qdel(query_get_flags)
return result
/datum/controller/subsystem/echelon/proc/is_using_proxy(ip)
PRIVATE_PROC(TRUE)
if(IsAdminAdvancedProcCall()) return
var/datum/DBQuery/query_get_cached_matches = SSdbcore.NewQuery({"
SELECT
JSON_VALUE(data, "$.should_block")
FROM [format_table_name("proxy_cache")]
WHERE
(ip = INET_ATON(:ip))
"}, list("ip" = ip))
//This is just the cached value, we can carry on if this fails
if(!query_get_cached_matches.Execute())
var/msg = "An error occured while attempting to fetch a cached proxy result. Check server sql logs."
log_world(msg)
message_admins(msg)
else if(query_get_cached_matches.NextRow())
var/result = query_get_cached_matches.item[1] == "true"
qdel(query_get_cached_matches)
return result
qdel(query_get_cached_matches)
//At this point, we couldnt fetch a cached value
var/datum/http_request/req = new()
var/url = CONFIG_GET(string/vpn_lookup_api)
url = replacetextEx(url, "{key}", CONFIG_GET(string/vpn_lookup_key))
url = replacetextEx(url, "{ip}", ip)
req.prepare(RUSTG_HTTP_METHOD_GET, url)
req.begin_async()
UNTIL(req.is_complete())
var/datum/http_response/res = req.into_response()
var/json = json_decode(res.body)
var/datum/DBQuery/query_update_cache = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("proxy_cache")]
SET ip = INET_ATON(:ip), data = :data
"}, list("ip" = ip, "data" = res.body))
query_update_cache.Execute();
qdel(query_update_cache)
var/status = json["status"]
switch(status)
if("warning")
var/msg = "The proxy checking API has returned a warning. Please inform a server operator."
log_world(msg)
message_admins(msg)
if("denied")
var/msg = "The proxy checking API has refused to answer. Please inform a server operator. The ip [ip] was let through by default."
log_world(msg)
message_admins(msg)
return FALSE
if("error")
var/msg = "Unable to fetch proxy information. Please inform a server operator. The ip [ip] was let through by default."
log_world(msg)
message_admins(msg)
return FALSE
return json["should_block"] == "true"
/datum/controller/subsystem/echelon/proc/is_match(ckey, ip, allow_exceptions=TRUE)
if(!CONFIG_GET(string/vpn_lookup_api) || !CONFIG_GET(string/vpn_lookup_key))
return FALSE
if(!enabled)
return FALSE
if(allow_exceptions && is_exception(ckey)) return FALSE
return is_using_proxy(ip)

View File

@@ -137,6 +137,11 @@ Yogs End*/
qdel(query_get_bound_creds) qdel(query_get_bound_creds)
if(SSechelon.is_match(ckey, address))
log_access("Failed Login: [key] [computer_id] [address] - Blocked due to proxy")
key_cache[key] = FALSE
return list("reason" = "proxy", "desc" = "Round ID [GLOB.round_id]: Your connection has been blocked due to originating from a suspicious IP. If you are using a VPN product, disable it and reconnect. If you are not using a VPN or if you are required to use one to connect to the server, please visit [CONFIG_GET(string/banappeals) || "the forums"].")
var/list/ban_details = is_banned_from_with_details(ckey, address, computer_id, "Server") var/list/ban_details = is_banned_from_with_details(ckey, address, computer_id, "Server")
for(var/i in ban_details) for(var/i in ban_details)
if(admin) if(admin)

View File

@@ -62,8 +62,6 @@
body += "<br><br><b>Show related accounts by:</b> " body += "<br><br><b>Show related accounts by:</b> "
body += "\[ <a href='?_src_=holder;[HrefToken()];showrelatedacc=cid;client=[REF(M.client)]'>CID</a> | " body += "\[ <a href='?_src_=holder;[HrefToken()];showrelatedacc=cid;client=[REF(M.client)]'>CID</a> | "
body += "<a href='?_src_=holder;[HrefToken()];showrelatedacc=ip;client=[REF(M.client)]'>IP</a> \]" body += "<a href='?_src_=holder;[HrefToken()];showrelatedacc=ip;client=[REF(M.client)]'>IP</a> \]"
if(CONFIG_GET(string/vpn_lookup_api) && CONFIG_GET(string/vpn_lookup_key) && M.lastKnownIP)
body += " \[<a href='?_src_=holder;[HrefToken()];vpnlookup=[M.lastKnownIP]'>Check for VPN</a>\]"
var/rep = 0 var/rep = 0
rep += SSpersistence.antag_rep[M.ckey] rep += SSpersistence.antag_rep[M.ckey]
body += "<br><br>Antagonist reputation: [rep]" body += "<br><br>Antagonist reputation: [rep]"

View File

@@ -59,7 +59,7 @@
FROM [format_table_name("bound_credentials")] FROM [format_table_name("bound_credentials")]
WHERE WHERE
ckey = :ckey AND ckey = :ckey AND
FIND_IN_SET('bypass_bans', [format_table_name("bound_credentials")].flags) FIND_IN_SET('[DB_BOUND_CREDENTIALS_FLAG_BYPASS_BANS]', [format_table_name("bound_credentials")].flags)
"}, list("ckey" = player_ckey)); "}, list("ckey" = player_ckey));
if(!query_get_bypass_creds.warn_execute()) if(!query_get_bypass_creds.warn_execute())
qdel(query_get_bypass_creds) qdel(query_get_bypass_creds)

View File

@@ -2103,60 +2103,6 @@
popup.set_content(dat.Join()) popup.set_content(dat.Join())
popup.open(FALSE) popup.open(FALSE)
else if(href_list["vpnlookup"])
if(!check_rights(R_ADMIN))
return
var/ip = href_list["vpnlookup"]
if(!ip)
return
if(!CONFIG_GET(string/vpn_lookup_api) || !CONFIG_GET(string/vpn_lookup_key))
to_chat(usr, span_warning("VPN Lookup is disabled!"))
return
var/datum/http_request/req = new()
req.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/vpn_lookup_api)]/[ip]?vpn=1&risk=1&asn=1&key=[CONFIG_GET(string/vpn_lookup_key)]")
req.begin_async()
UNTIL(req.is_complete())
var/datum/http_response/response = req.into_response()
var/list/body = json_decode(response.body)
var/list/dat = list()
dat += "<div align='center'>STATUS: [uppertext(body["status"])]</div>"
dat += "<br>"
if(body["status"] != "ok" && body["message"])
dat += "<div align='center'>[uppertext(body["message"])]</div>"
dat += "<br>"
if(body[ip] && islist(body[ip]))
if(body[ip]["proxy"])
dat += "<div align='center'><b>Proxy?: [body[ip]["proxy"]]</b></div>"
dat += "<br>"
if(body[ip]["type"])
dat += "<div align='center'><b>Type: [body[ip]["type"]]</b></div>"
dat += "<br>"
if(body[ip]["risk"])
dat += "<div align='center'><b>Risk Rating: [body[ip]["risk"]]/100</b></div>"
dat += "<br>"
if(body[ip]["operator"] && islist(body[ip]["operator"]) && body[ip]["operator"]["name"])
dat += "<div align='center'><b>"
dat += "Operator: [body[ip]["operator"]["name"]]"
if(body[ip]["operator"]["url"])
dat += " @ [body[ip]["operator"]["url"]]"
dat += "</b></div><br>"
dat += "Additional Info:"
dat += "<br>"
dat += "[ip]"
dat += "<br>"
for(var/P in body[ip])
if(P != "proxy" && P != "type" && P != "risk" && P != "operator")
dat += "[P]: [body[ip][P]]"
dat += "<br>"
var/datum/browser/popup = new(usr, "vpnlookup-[ip]", "<div align='center'>VPN Lookup</div>", 700, 600)
popup.set_content(dat.Join())
popup.open(FALSE)
else if(href_list["modantagrep"]) else if(href_list["modantagrep"])
if(!check_rights(R_ADMIN)) if(!check_rights(R_ADMIN))
return return

View File

@@ -27,7 +27,7 @@ $include private_default.txt
# IPINTEL_EMAIL ch@nge.me # IPINTEL_EMAIL ch@nge.me
## VPN Lookup ## VPN Lookup
## URL, see code/modules/admin/topic.dm to change args ## URL, {ip} gets replaced with the ip to check and {key} gets replaced with the creds
# VPN_LOOKUP_API https://website.com/v1 # VPN_LOOKUP_API https://website.com/v1
## API Key ## API Key
# VPN_LOOKUP_KEY insertkey # VPN_LOOKUP_KEY insertkey

View File

@@ -327,6 +327,7 @@
#include "code\controllers\subsystem\discord.dm" #include "code\controllers\subsystem\discord.dm"
#include "code\controllers\subsystem\disease.dm" #include "code\controllers\subsystem\disease.dm"
#include "code\controllers\subsystem\early_assets.dm" #include "code\controllers\subsystem\early_assets.dm"
#include "code\controllers\subsystem\echelon.dm"
#include "code\controllers\subsystem\economy.dm" #include "code\controllers\subsystem\economy.dm"
#include "code\controllers\subsystem\events.dm" #include "code\controllers\subsystem\events.dm"
#include "code\controllers\subsystem\explosions.dm" #include "code\controllers\subsystem\explosions.dm"