2021-08-19 13:51:43 +00:00
//go:build !nomysql
2020-05-23 09:58:05 +00:00
// +build !nomysql
2019-07-20 10:26:52 +00:00
package dataprovider
import (
2020-07-08 16:54:44 +00:00
"context"
2021-02-28 11:10:40 +00:00
"crypto/x509"
2019-07-20 10:26:52 +00:00
"database/sql"
2021-02-22 07:37:50 +00:00
"errors"
2019-07-20 10:26:52 +00:00
"fmt"
2020-02-08 13:44:25 +00:00
"strings"
2019-07-20 10:26:52 +00:00
"time"
2019-09-06 13:19:01 +00:00
2020-05-23 09:58:05 +00:00
// we import go-sql-driver/mysql here to be able to disable MySQL support using a build tag
_ "github.com/go-sql-driver/mysql"
2021-06-26 05:31:41 +00:00
"github.com/drakkan/sftpgo/v2/logger"
"github.com/drakkan/sftpgo/v2/version"
"github.com/drakkan/sftpgo/v2/vfs"
2019-07-20 10:26:52 +00:00
)
2020-02-08 13:44:25 +00:00
const (
2021-11-15 17:40:31 +00:00
mysqlResetSQL = "DROP TABLE IF EXISTS `{{api_keys}}` CASCADE;" +
"DROP TABLE IF EXISTS `{{folders_mapping}}` CASCADE;" +
"DROP TABLE IF EXISTS `{{admins}}` CASCADE;" +
"DROP TABLE IF EXISTS `{{folders}}` CASCADE;" +
"DROP TABLE IF EXISTS `{{shares}}` CASCADE;" +
"DROP TABLE IF EXISTS `{{users}}` CASCADE;" +
2021-12-25 11:08:07 +00:00
"DROP TABLE IF EXISTS `{{defender_events}}` CASCADE;" +
"DROP TABLE IF EXISTS `{{defender_hosts}}` CASCADE;" +
2021-11-15 17:40:31 +00:00
"DROP TABLE IF EXISTS `{{schema_version}}` CASCADE;"
2021-02-22 07:37:50 +00:00
mysqlInitialSQL = "CREATE TABLE `{{schema_version}}` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `version` integer NOT NULL);" +
"CREATE TABLE `{{admins}}` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `username` varchar(255) NOT NULL UNIQUE, " +
2021-06-19 07:03:20 +00:00
"`description` varchar(512) NULL, `password` varchar(255) NOT NULL, `email` varchar(255) NULL, `status` integer NOT NULL, " +
"`permissions` longtext NOT NULL, `filters` longtext NULL, `additional_info` longtext NULL);" +
2021-02-22 07:37:50 +00:00
"CREATE TABLE `{{folders}}` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(255) NOT NULL UNIQUE, " +
2021-06-19 07:03:20 +00:00
"`description` varchar(512) NULL, `path` varchar(512) NULL, `used_quota_size` bigint NOT NULL, " +
"`used_quota_files` integer NOT NULL, `last_quota_update` bigint NOT NULL, `filesystem` longtext NULL);" +
"CREATE TABLE `{{users}}` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `username` varchar(255) NOT NULL UNIQUE, " +
"`status` integer NOT NULL, `expiration_date` bigint NOT NULL, `description` varchar(512) NULL, `password` longtext NULL, " +
2021-02-22 07:37:50 +00:00
"`public_keys` longtext NULL, `home_dir` varchar(512) NOT NULL, `uid` integer NOT NULL, `gid` integer NOT NULL, " +
"`max_sessions` integer NOT NULL, `quota_size` bigint NOT NULL, `quota_files` integer NOT NULL, " +
"`permissions` longtext NOT NULL, `used_quota_size` bigint NOT NULL, `used_quota_files` integer NOT NULL, " +
"`last_quota_update` bigint NOT NULL, `upload_bandwidth` integer NOT NULL, `download_bandwidth` integer NOT NULL, " +
"`last_login` bigint NOT NULL, `filters` longtext NULL, `filesystem` longtext NULL, `additional_info` longtext NULL);" +
2020-06-07 21:30:18 +00:00
"CREATE TABLE `{{folders_mapping}}` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `virtual_path` varchar(512) NOT NULL, " +
"`quota_size` bigint NOT NULL, `quota_files` integer NOT NULL, `folder_id` integer NOT NULL, `user_id` integer NOT NULL);" +
2021-04-12 18:00:49 +00:00
"ALTER TABLE `{{folders_mapping}}` ADD CONSTRAINT `{{prefix}}unique_mapping` UNIQUE (`user_id`, `folder_id`);" +
"ALTER TABLE `{{folders_mapping}}` ADD CONSTRAINT `{{prefix}}folders_mapping_folder_id_fk_folders_id` FOREIGN KEY (`folder_id`) REFERENCES `{{folders}}` (`id`) ON DELETE CASCADE;" +
"ALTER TABLE `{{folders_mapping}}` ADD CONSTRAINT `{{prefix}}folders_mapping_user_id_fk_users_id` FOREIGN KEY (`user_id`) REFERENCES `{{users}}` (`id`) ON DELETE CASCADE;" +
2021-06-19 07:03:20 +00:00
"INSERT INTO {{schema_version}} (version) VALUES (10);"
2021-08-17 16:08:32 +00:00
mysqlV11SQL = "CREATE TABLE `{{api_keys}}` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(255) NOT NULL, `key_id` varchar(50) NOT NULL UNIQUE," +
"`api_key` varchar(255) NOT NULL UNIQUE, `scope` integer NOT NULL, `created_at` bigint NOT NULL, `updated_at` bigint NOT NULL, `last_use_at` bigint NOT NULL, " +
"`expires_at` bigint NOT NULL, `description` longtext NULL, `admin_id` integer NULL, `user_id` integer NULL);" +
"ALTER TABLE `{{api_keys}}` ADD CONSTRAINT `{{prefix}}api_keys_admin_id_fk_admins_id` FOREIGN KEY (`admin_id`) REFERENCES `{{admins}}` (`id`) ON DELETE CASCADE;" +
"ALTER TABLE `{{api_keys}}` ADD CONSTRAINT `{{prefix}}api_keys_user_id_fk_users_id` FOREIGN KEY (`user_id`) REFERENCES `{{users}}` (`id`) ON DELETE CASCADE;"
mysqlV11DownSQL = "DROP TABLE `{{api_keys}}` CASCADE;"
2021-08-19 13:51:43 +00:00
mysqlV12SQL = "ALTER TABLE `{{admins}}` ADD COLUMN `created_at` bigint DEFAULT 0 NOT NULL;" +
"ALTER TABLE `{{admins}}` ALTER COLUMN `created_at` DROP DEFAULT;" +
"ALTER TABLE `{{admins}}` ADD COLUMN `updated_at` bigint DEFAULT 0 NOT NULL;" +
"ALTER TABLE `{{admins}}` ALTER COLUMN `updated_at` DROP DEFAULT;" +
"ALTER TABLE `{{admins}}` ADD COLUMN `last_login` bigint DEFAULT 0 NOT NULL;" +
"ALTER TABLE `{{admins}}` ALTER COLUMN `last_login` DROP DEFAULT;" +
"ALTER TABLE `{{users}}` ADD COLUMN `created_at` bigint DEFAULT 0 NOT NULL;" +
"ALTER TABLE `{{users}}` ALTER COLUMN `created_at` DROP DEFAULT;" +
"ALTER TABLE `{{users}}` ADD COLUMN `updated_at` bigint DEFAULT 0 NOT NULL;" +
"ALTER TABLE `{{users}}` ALTER COLUMN `updated_at` DROP DEFAULT;" +
"CREATE INDEX `{{prefix}}users_updated_at_idx` ON `{{users}}` (`updated_at`);"
mysqlV12DownSQL = "ALTER TABLE `{{admins}}` DROP COLUMN `updated_at`;" +
"ALTER TABLE `{{admins}}` DROP COLUMN `created_at`;" +
"ALTER TABLE `{{admins}}` DROP COLUMN `last_login`;" +
"ALTER TABLE `{{users}}` DROP COLUMN `created_at`;" +
"ALTER TABLE `{{users}}` DROP COLUMN `updated_at`;"
2021-09-25 17:06:13 +00:00
mysqlV13SQL = "ALTER TABLE `{{users}}` ADD COLUMN `email` varchar(255) NULL;"
mysqlV13DownSQL = "ALTER TABLE `{{users}}` DROP COLUMN `email`;"
2021-11-06 13:13:20 +00:00
mysqlV14SQL = "CREATE TABLE `{{shares}}` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, " +
"`share_id` varchar(60) NOT NULL UNIQUE, `name` varchar(255) NOT NULL, `description` varchar(512) NULL, " +
"`scope` integer NOT NULL, `paths` longtext NOT NULL, `created_at` bigint NOT NULL, " +
"`updated_at` bigint NOT NULL, `last_use_at` bigint NOT NULL, `expires_at` bigint NOT NULL, " +
"`password` longtext NULL, `max_tokens` integer NOT NULL, `used_tokens` integer NOT NULL, " +
"`allow_from` longtext NULL, `user_id` integer NOT NULL);" +
"ALTER TABLE `{{shares}}` ADD CONSTRAINT `{{prefix}}shares_user_id_fk_users_id` " +
"FOREIGN KEY (`user_id`) REFERENCES `{{users}}` (`id`) ON DELETE CASCADE;"
mysqlV14DownSQL = "DROP TABLE `{{shares}}` CASCADE;"
2021-12-25 11:08:07 +00:00
mysqlV15SQL = "CREATE TABLE `{{defender_hosts}}` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, " +
"`ip` varchar(50) NOT NULL UNIQUE, `ban_time` bigint NOT NULL, `updated_at` bigint NOT NULL);" +
"CREATE TABLE `{{defender_events}}` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, " +
"`date_time` bigint NOT NULL, `score` integer NOT NULL, `host_id` bigint NOT NULL);" +
"ALTER TABLE `{{defender_events}}` ADD CONSTRAINT `{{prefix}}defender_events_host_id_fk_defender_hosts_id` " +
"FOREIGN KEY (`host_id`) REFERENCES `{{defender_hosts}}` (`id`) ON DELETE CASCADE;" +
"CREATE INDEX `{{prefix}}defender_hosts_updated_at_idx` ON `{{defender_hosts}}` (`updated_at`);" +
"CREATE INDEX `{{prefix}}defender_hosts_ban_time_idx` ON `{{defender_hosts}}` (`ban_time`);" +
"CREATE INDEX `{{prefix}}defender_events_date_time_idx` ON `{{defender_events}}` (`date_time`);"
mysqlV15DownSQL = "DROP TABLE `{{defender_events}}` CASCADE;" +
"DROP TABLE `{{defender_hosts}}` CASCADE;"
2020-02-08 13:44:25 +00:00
)
2019-07-30 18:51:29 +00:00
// MySQLProvider auth provider for MySQL/MariaDB database
2019-07-20 10:26:52 +00:00
type MySQLProvider struct {
2019-08-11 12:53:37 +00:00
dbHandle * sql . DB
2019-07-20 10:26:52 +00:00
}
2020-05-23 09:58:05 +00:00
func init ( ) {
2020-06-19 15:08:51 +00:00
version . AddFeature ( "+mysql" )
2020-05-23 09:58:05 +00:00
}
2019-07-20 10:26:52 +00:00
func initializeMySQLProvider ( ) error {
var err error
2021-03-23 18:14:15 +00:00
2019-09-13 19:57:52 +00:00
dbHandle , err := sql . Open ( "mysql" , getMySQLConnectionString ( false ) )
2019-07-20 10:26:52 +00:00
if err == nil {
2019-09-13 19:57:52 +00:00
providerLog ( logger . LevelDebug , "mysql database handle created, connection string: %#v, pool size: %v" ,
getMySQLConnectionString ( true ) , config . PoolSize )
2019-09-13 06:14:07 +00:00
dbHandle . SetMaxOpenConns ( config . PoolSize )
2020-11-30 20:46:34 +00:00
if config . PoolSize > 0 {
dbHandle . SetMaxIdleConns ( config . PoolSize )
} else {
dbHandle . SetMaxIdleConns ( 2 )
}
dbHandle . SetConnMaxLifetime ( 240 * time . Second )
2021-01-17 21:29:08 +00:00
provider = & MySQLProvider { dbHandle : dbHandle }
2019-07-20 10:26:52 +00:00
} else {
2021-12-16 18:53:00 +00:00
providerLog ( logger . LevelError , "error creating mysql database handler, connection string: %#v, error: %v" ,
2019-09-13 19:57:52 +00:00
getMySQLConnectionString ( true ) , err )
2019-07-20 10:26:52 +00:00
}
return err
}
2019-09-13 19:57:52 +00:00
func getMySQLConnectionString ( redactedPwd bool ) string {
var connectionString string
2021-01-05 08:50:22 +00:00
if config . ConnectionString == "" {
2019-09-13 19:57:52 +00:00
password := config . Password
if redactedPwd {
password = "[redacted]"
}
2021-10-20 17:39:49 +00:00
connectionString = fmt . Sprintf ( "%v:%v@tcp([%v]:%v)/%v?charset=utf8mb4&interpolateParams=true&timeout=10s&parseTime=true&tls=%v&writeTimeout=10s&readTimeout=10s" ,
2019-09-13 19:57:52 +00:00
config . Username , password , config . Host , config . Port , config . Name , getSSLMode ( ) )
} else {
connectionString = config . ConnectionString
}
return connectionString
}
2019-07-20 10:26:52 +00:00
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) checkAvailability ( ) error {
2019-09-13 16:45:36 +00:00
return sqlCommonCheckAvailability ( p . dbHandle )
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) validateUserAndPass ( username , password , ip , protocol string ) ( User , error ) {
2020-08-19 17:36:12 +00:00
return sqlCommonValidateUserAndPass ( username , password , ip , protocol , p . dbHandle )
2019-07-20 10:26:52 +00:00
}
2021-02-28 11:10:40 +00:00
func ( p * MySQLProvider ) validateUserAndTLSCert ( username , protocol string , tlsCert * x509 . Certificate ) ( User , error ) {
return sqlCommonValidateUserAndTLSCertificate ( username , protocol , tlsCert , p . dbHandle )
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) validateUserAndPubKey ( username string , publicKey [ ] byte ) ( User , string , error ) {
2019-08-11 12:53:37 +00:00
return sqlCommonValidateUserAndPubKey ( username , publicKey , p . dbHandle )
2019-07-20 10:26:52 +00:00
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) updateQuota ( username string , filesAdd int , sizeAdd int64 , reset bool ) error {
2019-09-13 06:14:07 +00:00
return sqlCommonUpdateQuota ( username , filesAdd , sizeAdd , reset , p . dbHandle )
2019-07-20 10:26:52 +00:00
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) getUsedQuota ( username string ) ( int , int64 , error ) {
2019-08-11 12:53:37 +00:00
return sqlCommonGetUsedQuota ( username , p . dbHandle )
2019-07-20 10:26:52 +00:00
}
2021-08-19 13:51:43 +00:00
func ( p * MySQLProvider ) setUpdatedAt ( username string ) {
sqlCommonSetUpdatedAt ( username , p . dbHandle )
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) updateLastLogin ( username string ) error {
2020-06-07 21:30:18 +00:00
return sqlCommonUpdateLastLogin ( username , p . dbHandle )
}
2021-08-19 13:51:43 +00:00
func ( p * MySQLProvider ) updateAdminLastLogin ( username string ) error {
return sqlCommonUpdateAdminLastLogin ( username , p . dbHandle )
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) userExists ( username string ) ( User , error ) {
return sqlCommonGetUserByUsername ( username , p . dbHandle )
2019-07-20 10:26:52 +00:00
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) addUser ( user * User ) error {
2019-08-11 12:53:37 +00:00
return sqlCommonAddUser ( user , p . dbHandle )
2019-07-20 10:26:52 +00:00
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) updateUser ( user * User ) error {
2019-08-11 12:53:37 +00:00
return sqlCommonUpdateUser ( user , p . dbHandle )
2019-07-20 10:26:52 +00:00
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) deleteUser ( user * User ) error {
2019-08-11 12:53:37 +00:00
return sqlCommonDeleteUser ( user , p . dbHandle )
2019-07-20 10:26:52 +00:00
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) dumpUsers ( ) ( [ ] User , error ) {
2019-12-27 22:12:44 +00:00
return sqlCommonDumpUsers ( p . dbHandle )
}
2021-08-20 07:35:06 +00:00
func ( p * MySQLProvider ) getRecentlyUpdatedUsers ( after int64 ) ( [ ] User , error ) {
return sqlCommonGetRecentlyUpdatedUsers ( after , p . dbHandle )
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) getUsers ( limit int , offset int , order string ) ( [ ] User , error ) {
return sqlCommonGetUsers ( limit , offset , order , p . dbHandle )
2019-07-20 10:26:52 +00:00
}
2019-09-28 20:48:52 +00:00
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) dumpFolders ( ) ( [ ] vfs . BaseVirtualFolder , error ) {
2020-06-07 21:30:18 +00:00
return sqlCommonDumpFolders ( p . dbHandle )
}
2021-02-01 18:04:15 +00:00
func ( p * MySQLProvider ) getFolders ( limit , offset int , order string ) ( [ ] vfs . BaseVirtualFolder , error ) {
return sqlCommonGetFolders ( limit , offset , order , p . dbHandle )
2020-06-07 21:30:18 +00:00
}
2021-02-01 18:04:15 +00:00
func ( p * MySQLProvider ) getFolderByName ( name string ) ( vfs . BaseVirtualFolder , error ) {
2020-07-08 16:54:44 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , defaultSQLQueryTimeout )
defer cancel ( )
2021-02-01 18:04:15 +00:00
return sqlCommonGetFolderByName ( ctx , name , p . dbHandle )
2020-06-07 21:30:18 +00:00
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) addFolder ( folder * vfs . BaseVirtualFolder ) error {
2020-06-07 21:30:18 +00:00
return sqlCommonAddFolder ( folder , p . dbHandle )
}
2021-02-01 18:04:15 +00:00
func ( p * MySQLProvider ) updateFolder ( folder * vfs . BaseVirtualFolder ) error {
return sqlCommonUpdateFolder ( folder , p . dbHandle )
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) deleteFolder ( folder * vfs . BaseVirtualFolder ) error {
2020-06-07 21:30:18 +00:00
return sqlCommonDeleteFolder ( folder , p . dbHandle )
}
2021-02-01 18:04:15 +00:00
func ( p * MySQLProvider ) updateFolderQuota ( name string , filesAdd int , sizeAdd int64 , reset bool ) error {
return sqlCommonUpdateFolderQuota ( name , filesAdd , sizeAdd , reset , p . dbHandle )
2020-06-07 21:30:18 +00:00
}
2021-02-01 18:04:15 +00:00
func ( p * MySQLProvider ) getUsedFolderQuota ( name string ) ( int , int64 , error ) {
return sqlCommonGetFolderUsedQuota ( name , p . dbHandle )
2020-06-07 21:30:18 +00:00
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) adminExists ( username string ) ( Admin , error ) {
return sqlCommonGetAdminByUsername ( username , p . dbHandle )
}
func ( p * MySQLProvider ) addAdmin ( admin * Admin ) error {
return sqlCommonAddAdmin ( admin , p . dbHandle )
}
func ( p * MySQLProvider ) updateAdmin ( admin * Admin ) error {
return sqlCommonUpdateAdmin ( admin , p . dbHandle )
}
func ( p * MySQLProvider ) deleteAdmin ( admin * Admin ) error {
return sqlCommonDeleteAdmin ( admin , p . dbHandle )
}
func ( p * MySQLProvider ) getAdmins ( limit int , offset int , order string ) ( [ ] Admin , error ) {
return sqlCommonGetAdmins ( limit , offset , order , p . dbHandle )
}
func ( p * MySQLProvider ) dumpAdmins ( ) ( [ ] Admin , error ) {
return sqlCommonDumpAdmins ( p . dbHandle )
}
func ( p * MySQLProvider ) validateAdminAndPass ( username , password , ip string ) ( Admin , error ) {
return sqlCommonValidateAdminAndPass ( username , password , ip , p . dbHandle )
}
2021-08-17 16:08:32 +00:00
func ( p * MySQLProvider ) apiKeyExists ( keyID string ) ( APIKey , error ) {
return sqlCommonGetAPIKeyByID ( keyID , p . dbHandle )
}
func ( p * MySQLProvider ) addAPIKey ( apiKey * APIKey ) error {
return sqlCommonAddAPIKey ( apiKey , p . dbHandle )
}
func ( p * MySQLProvider ) updateAPIKey ( apiKey * APIKey ) error {
return sqlCommonUpdateAPIKey ( apiKey , p . dbHandle )
}
2021-11-06 13:13:20 +00:00
func ( p * MySQLProvider ) deleteAPIKey ( apiKey * APIKey ) error {
2021-08-17 16:08:32 +00:00
return sqlCommonDeleteAPIKey ( apiKey , p . dbHandle )
}
func ( p * MySQLProvider ) getAPIKeys ( limit int , offset int , order string ) ( [ ] APIKey , error ) {
return sqlCommonGetAPIKeys ( limit , offset , order , p . dbHandle )
}
func ( p * MySQLProvider ) dumpAPIKeys ( ) ( [ ] APIKey , error ) {
return sqlCommonDumpAPIKeys ( p . dbHandle )
}
func ( p * MySQLProvider ) updateAPIKeyLastUse ( keyID string ) error {
return sqlCommonUpdateAPIKeyLastUse ( keyID , p . dbHandle )
}
2021-11-06 13:13:20 +00:00
func ( p * MySQLProvider ) shareExists ( shareID , username string ) ( Share , error ) {
return sqlCommonGetShareByID ( shareID , username , p . dbHandle )
}
func ( p * MySQLProvider ) addShare ( share * Share ) error {
return sqlCommonAddShare ( share , p . dbHandle )
}
func ( p * MySQLProvider ) updateShare ( share * Share ) error {
return sqlCommonUpdateShare ( share , p . dbHandle )
}
func ( p * MySQLProvider ) deleteShare ( share * Share ) error {
return sqlCommonDeleteShare ( share , p . dbHandle )
}
func ( p * MySQLProvider ) getShares ( limit int , offset int , order , username string ) ( [ ] Share , error ) {
return sqlCommonGetShares ( limit , offset , order , username , p . dbHandle )
}
func ( p * MySQLProvider ) dumpShares ( ) ( [ ] Share , error ) {
return sqlCommonDumpShares ( p . dbHandle )
}
func ( p * MySQLProvider ) updateShareLastUse ( shareID string , numTokens int ) error {
return sqlCommonUpdateShareLastUse ( shareID , numTokens , p . dbHandle )
}
2021-12-25 11:08:07 +00:00
func ( p * MySQLProvider ) getDefenderHosts ( from int64 , limit int ) ( [ ] * DefenderEntry , error ) {
return sqlCommonGetDefenderHosts ( from , limit , p . dbHandle )
}
func ( p * MySQLProvider ) getDefenderHostByIP ( ip string , from int64 ) ( * DefenderEntry , error ) {
return sqlCommonGetDefenderHostByIP ( ip , from , p . dbHandle )
}
func ( p * MySQLProvider ) isDefenderHostBanned ( ip string ) ( * DefenderEntry , error ) {
return sqlCommonIsDefenderHostBanned ( ip , p . dbHandle )
}
func ( p * MySQLProvider ) updateDefenderBanTime ( ip string , minutes int ) error {
return sqlCommonDefenderIncrementBanTime ( ip , minutes , p . dbHandle )
}
func ( p * MySQLProvider ) deleteDefenderHost ( ip string ) error {
return sqlCommonDeleteDefenderHost ( ip , p . dbHandle )
}
func ( p * MySQLProvider ) addDefenderEvent ( ip string , score int ) error {
return sqlCommonAddDefenderHostAndEvent ( ip , score , p . dbHandle )
}
func ( p * MySQLProvider ) setDefenderBanTime ( ip string , banTime int64 ) error {
return sqlCommonSetDefenderBanTime ( ip , banTime , p . dbHandle )
}
func ( p * MySQLProvider ) cleanupDefender ( from int64 ) error {
return sqlCommonDefenderCleanup ( from , p . dbHandle )
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) close ( ) error {
2019-09-28 20:48:52 +00:00
return p . dbHandle . Close ( )
}
2020-02-02 21:20:39 +00:00
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) reloadConfig ( ) error {
2020-02-02 21:20:39 +00:00
return nil
}
2020-02-08 13:44:25 +00:00
// initializeDatabase creates the initial database structure
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) initializeDatabase ( ) error {
2020-08-30 12:00:45 +00:00
dbVersion , err := sqlCommonGetDatabaseVersion ( p . dbHandle , false )
if err == nil && dbVersion . Version > 0 {
return ErrNoInitRequired
}
2021-11-15 17:40:31 +00:00
if errors . Is ( err , sql . ErrNoRows ) {
return errSchemaVersionEmpty
}
2021-02-22 07:37:50 +00:00
initialSQL := strings . ReplaceAll ( mysqlInitialSQL , "{{schema_version}}" , sqlTableSchemaVersion )
initialSQL = strings . ReplaceAll ( initialSQL , "{{admins}}" , sqlTableAdmins )
initialSQL = strings . ReplaceAll ( initialSQL , "{{folders}}" , sqlTableFolders )
initialSQL = strings . ReplaceAll ( initialSQL , "{{users}}" , sqlTableUsers )
initialSQL = strings . ReplaceAll ( initialSQL , "{{folders_mapping}}" , sqlTableFoldersMapping )
2021-04-12 18:00:49 +00:00
initialSQL = strings . ReplaceAll ( initialSQL , "{{prefix}}" , config . SQLTablesPrefix )
2021-02-16 18:11:36 +00:00
2021-06-19 07:03:20 +00:00
return sqlCommonExecSQLAndUpdateDBVersion ( p . dbHandle , strings . Split ( initialSQL , ";" ) , 10 )
2020-02-08 13:44:25 +00:00
}
2021-11-06 13:13:20 +00:00
//nolint:dupl
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) migrateDatabase ( ) error {
2020-08-30 11:50:43 +00:00
dbVersion , err := sqlCommonGetDatabaseVersion ( p . dbHandle , true )
2020-02-23 10:30:26 +00:00
if err != nil {
return err
}
2021-02-22 07:37:50 +00:00
switch version := dbVersion . Version ; {
case version == sqlDatabaseVersion :
providerLog ( logger . LevelDebug , "sql database is up to date, current version: %v" , version )
2020-10-05 17:42:33 +00:00
return ErrNoInitRequired
2021-06-19 07:03:20 +00:00
case version < 10 :
2021-02-22 07:37:50 +00:00
err = fmt . Errorf ( "database version %v is too old, please see the upgrading docs" , version )
providerLog ( logger . LevelError , "%v" , err )
logger . ErrorToConsole ( "%v" , err )
return err
2021-08-17 16:08:32 +00:00
case version == 10 :
return updateMySQLDatabaseFromV10 ( p . dbHandle )
2021-08-19 13:51:43 +00:00
case version == 11 :
return updateMySQLDatabaseFromV11 ( p . dbHandle )
2021-09-25 17:06:13 +00:00
case version == 12 :
return updateMySQLDatabaseFromV12 ( p . dbHandle )
2021-11-06 13:13:20 +00:00
case version == 13 :
return updateMySQLDatabaseFromV13 ( p . dbHandle )
2021-12-25 11:08:07 +00:00
case version == 14 :
return updateMySQLDatabaseFromV14 ( p . dbHandle )
2020-11-26 21:08:33 +00:00
default :
2021-02-22 07:37:50 +00:00
if version > sqlDatabaseVersion {
2021-12-16 18:53:00 +00:00
providerLog ( logger . LevelError , "database version %v is newer than the supported one: %v" , version ,
2020-11-26 21:08:33 +00:00
sqlDatabaseVersion )
2021-02-22 07:37:50 +00:00
logger . WarnToConsole ( "database version %v is newer than the supported one: %v" , version ,
2020-11-26 21:08:33 +00:00
sqlDatabaseVersion )
return nil
}
2021-03-21 18:15:47 +00:00
return fmt . Errorf ( "database version not handled: %v" , version )
2020-11-26 21:08:33 +00:00
}
}
2021-01-17 21:29:08 +00:00
func ( p * MySQLProvider ) revertDatabase ( targetVersion int ) error {
2020-11-26 21:08:33 +00:00
dbVersion , err := sqlCommonGetDatabaseVersion ( p . dbHandle , true )
if err != nil {
return err
}
if dbVersion . Version == targetVersion {
2021-02-22 07:37:50 +00:00
return errors . New ( "current version match target version, nothing to do" )
2021-02-01 18:04:15 +00:00
}
2021-02-24 18:40:29 +00:00
2021-08-17 16:08:32 +00:00
switch dbVersion . Version {
2021-12-25 11:08:07 +00:00
case 15 :
return downgradeMySQLDatabaseFromV15 ( p . dbHandle )
2021-11-06 13:13:20 +00:00
case 14 :
return downgradeMySQLDatabaseFromV14 ( p . dbHandle )
2021-09-25 17:06:13 +00:00
case 13 :
return downgradeMySQLDatabaseFromV13 ( p . dbHandle )
2021-08-19 13:51:43 +00:00
case 12 :
return downgradeMySQLDatabaseFromV12 ( p . dbHandle )
2021-08-17 16:08:32 +00:00
case 11 :
return downgradeMySQLDatabaseFromV11 ( p . dbHandle )
default :
return fmt . Errorf ( "database version not handled: %v" , dbVersion . Version )
}
}
2021-11-15 17:40:31 +00:00
func ( p * MySQLProvider ) resetDatabase ( ) error {
sql := strings . ReplaceAll ( mysqlResetSQL , "{{schema_version}}" , sqlTableSchemaVersion )
sql = strings . ReplaceAll ( sql , "{{admins}}" , sqlTableAdmins )
sql = strings . ReplaceAll ( sql , "{{folders}}" , sqlTableFolders )
sql = strings . ReplaceAll ( sql , "{{users}}" , sqlTableUsers )
sql = strings . ReplaceAll ( sql , "{{folders_mapping}}" , sqlTableFoldersMapping )
sql = strings . ReplaceAll ( sql , "{{api_keys}}" , sqlTableAPIKeys )
sql = strings . ReplaceAll ( sql , "{{shares}}" , sqlTableShares )
2021-12-25 11:08:07 +00:00
sql = strings . ReplaceAll ( sql , "{{defender_events}}" , sqlTableDefenderEvents )
sql = strings . ReplaceAll ( sql , "{{defender_hosts}}" , sqlTableDefenderHosts )
2021-11-15 17:40:31 +00:00
return sqlCommonExecSQLAndUpdateDBVersion ( p . dbHandle , strings . Split ( sql , ";" ) , 0 )
}
2021-08-17 16:08:32 +00:00
func updateMySQLDatabaseFromV10 ( dbHandle * sql . DB ) error {
2021-08-19 13:51:43 +00:00
if err := updateMySQLDatabaseFrom10To11 ( dbHandle ) ; err != nil {
return err
}
return updateMySQLDatabaseFromV11 ( dbHandle )
}
func updateMySQLDatabaseFromV11 ( dbHandle * sql . DB ) error {
2021-09-25 17:06:13 +00:00
if err := updateMySQLDatabaseFrom11To12 ( dbHandle ) ; err != nil {
return err
}
return updateMySQLDatabaseFromV12 ( dbHandle )
}
func updateMySQLDatabaseFromV12 ( dbHandle * sql . DB ) error {
2021-11-06 13:13:20 +00:00
if err := updateMySQLDatabaseFrom12To13 ( dbHandle ) ; err != nil {
return err
}
return updateMySQLDatabaseFromV13 ( dbHandle )
}
func updateMySQLDatabaseFromV13 ( dbHandle * sql . DB ) error {
2021-12-25 11:08:07 +00:00
if err := updateMySQLDatabaseFrom13To14 ( dbHandle ) ; err != nil {
return err
}
return updateMySQLDatabaseFromV14 ( dbHandle )
}
func updateMySQLDatabaseFromV14 ( dbHandle * sql . DB ) error {
return updateMySQLDatabaseFrom14To15 ( dbHandle )
}
func downgradeMySQLDatabaseFromV15 ( dbHandle * sql . DB ) error {
if err := downgradeMySQLDatabaseFrom15To14 ( dbHandle ) ; err != nil {
return err
}
return downgradeMySQLDatabaseFromV14 ( dbHandle )
2021-11-06 13:13:20 +00:00
}
func downgradeMySQLDatabaseFromV14 ( dbHandle * sql . DB ) error {
if err := downgradeMySQLDatabaseFrom14To13 ( dbHandle ) ; err != nil {
return err
}
return downgradeMySQLDatabaseFromV13 ( dbHandle )
2021-09-25 17:06:13 +00:00
}
func downgradeMySQLDatabaseFromV13 ( dbHandle * sql . DB ) error {
if err := downgradeMySQLDatabaseFrom13To12 ( dbHandle ) ; err != nil {
return err
}
return downgradeMySQLDatabaseFromV12 ( dbHandle )
2021-08-19 13:51:43 +00:00
}
func downgradeMySQLDatabaseFromV12 ( dbHandle * sql . DB ) error {
if err := downgradeMySQLDatabaseFrom12To11 ( dbHandle ) ; err != nil {
return err
}
return downgradeMySQLDatabaseFromV11 ( dbHandle )
2021-08-17 16:08:32 +00:00
}
func downgradeMySQLDatabaseFromV11 ( dbHandle * sql . DB ) error {
return downgradeMySQLDatabaseFrom11To10 ( dbHandle )
}
2021-11-06 13:13:20 +00:00
func updateMySQLDatabaseFrom13To14 ( dbHandle * sql . DB ) error {
logger . InfoToConsole ( "updating database version: 13 -> 14" )
providerLog ( logger . LevelInfo , "updating database version: 13 -> 14" )
sql := strings . ReplaceAll ( mysqlV14SQL , "{{shares}}" , sqlTableShares )
sql = strings . ReplaceAll ( sql , "{{users}}" , sqlTableUsers )
sql = strings . ReplaceAll ( sql , "{{prefix}}" , config . SQLTablesPrefix )
return sqlCommonExecSQLAndUpdateDBVersion ( dbHandle , strings . Split ( sql , ";" ) , 14 )
}
2021-12-25 11:08:07 +00:00
func updateMySQLDatabaseFrom14To15 ( dbHandle * sql . DB ) error {
logger . InfoToConsole ( "updating database version: 14 -> 15" )
providerLog ( logger . LevelInfo , "updating database version: 14 -> 15" )
sql := strings . ReplaceAll ( mysqlV15SQL , "{{defender_events}}" , sqlTableDefenderEvents )
sql = strings . ReplaceAll ( sql , "{{defender_hosts}}" , sqlTableDefenderHosts )
sql = strings . ReplaceAll ( sql , "{{prefix}}" , config . SQLTablesPrefix )
return sqlCommonExecSQLAndUpdateDBVersion ( dbHandle , strings . Split ( sql , ";" ) , 15 )
}
func downgradeMySQLDatabaseFrom15To14 ( dbHandle * sql . DB ) error {
logger . InfoToConsole ( "downgrading database version: 15 -> 14" )
providerLog ( logger . LevelInfo , "downgrading database version: 15 -> 14" )
sql := strings . ReplaceAll ( mysqlV15DownSQL , "{{defender_events}}" , sqlTableDefenderEvents )
sql = strings . ReplaceAll ( sql , "{{defender_hosts}}" , sqlTableDefenderHosts )
return sqlCommonExecSQLAndUpdateDBVersion ( dbHandle , strings . Split ( sql , ";" ) , 14 )
}
2021-11-06 13:13:20 +00:00
func downgradeMySQLDatabaseFrom14To13 ( dbHandle * sql . DB ) error {
logger . InfoToConsole ( "downgrading database version: 14 -> 13" )
providerLog ( logger . LevelInfo , "downgrading database version: 14 -> 13" )
sql := strings . ReplaceAll ( mysqlV14DownSQL , "{{shares}}" , sqlTableShares )
return sqlCommonExecSQLAndUpdateDBVersion ( dbHandle , strings . Split ( sql , ";" ) , 13 )
}
2021-09-25 17:06:13 +00:00
func updateMySQLDatabaseFrom12To13 ( dbHandle * sql . DB ) error {
logger . InfoToConsole ( "updating database version: 12 -> 13" )
providerLog ( logger . LevelInfo , "updating database version: 12 -> 13" )
sql := strings . ReplaceAll ( mysqlV13SQL , "{{users}}" , sqlTableUsers )
return sqlCommonExecSQLAndUpdateDBVersion ( dbHandle , strings . Split ( sql , ";" ) , 13 )
}
func downgradeMySQLDatabaseFrom13To12 ( dbHandle * sql . DB ) error {
logger . InfoToConsole ( "downgrading database version: 13 -> 12" )
providerLog ( logger . LevelInfo , "downgrading database version: 13 -> 12" )
sql := strings . ReplaceAll ( mysqlV13DownSQL , "{{users}}" , sqlTableUsers )
return sqlCommonExecSQLAndUpdateDBVersion ( dbHandle , strings . Split ( sql , ";" ) , 12 )
}
2021-08-19 13:51:43 +00:00
func updateMySQLDatabaseFrom11To12 ( dbHandle * sql . DB ) error {
logger . InfoToConsole ( "updating database version: 11 -> 12" )
providerLog ( logger . LevelInfo , "updating database version: 11 -> 12" )
sql := strings . ReplaceAll ( mysqlV12SQL , "{{users}}" , sqlTableUsers )
sql = strings . ReplaceAll ( sql , "{{admins}}" , sqlTableAdmins )
sql = strings . ReplaceAll ( sql , "{{prefix}}" , config . SQLTablesPrefix )
return sqlCommonExecSQLAndUpdateDBVersion ( dbHandle , strings . Split ( sql , ";" ) , 12 )
}
func downgradeMySQLDatabaseFrom12To11 ( dbHandle * sql . DB ) error {
logger . InfoToConsole ( "downgrading database version: 12 -> 11" )
providerLog ( logger . LevelInfo , "downgrading database version: 12 -> 11" )
sql := strings . ReplaceAll ( mysqlV12DownSQL , "{{users}}" , sqlTableUsers )
sql = strings . ReplaceAll ( sql , "{{admins}}" , sqlTableAdmins )
sql = strings . ReplaceAll ( sql , "{{prefix}}" , config . SQLTablesPrefix )
return sqlCommonExecSQLAndUpdateDBVersion ( dbHandle , strings . Split ( sql , ";" ) , 11 )
}
2021-08-17 16:08:32 +00:00
func updateMySQLDatabaseFrom10To11 ( dbHandle * sql . DB ) error {
logger . InfoToConsole ( "updating database version: 10 -> 11" )
providerLog ( logger . LevelInfo , "updating database version: 10 -> 11" )
sql := strings . ReplaceAll ( mysqlV11SQL , "{{users}}" , sqlTableUsers )
sql = strings . ReplaceAll ( sql , "{{admins}}" , sqlTableAdmins )
sql = strings . ReplaceAll ( sql , "{{api_keys}}" , sqlTableAPIKeys )
sql = strings . ReplaceAll ( sql , "{{prefix}}" , config . SQLTablesPrefix )
return sqlCommonExecSQLAndUpdateDBVersion ( dbHandle , strings . Split ( sql , ";" ) , 11 )
}
func downgradeMySQLDatabaseFrom11To10 ( dbHandle * sql . DB ) error {
logger . InfoToConsole ( "downgrading database version: 11 -> 10" )
providerLog ( logger . LevelInfo , "downgrading database version: 11 -> 10" )
sql := strings . ReplaceAll ( mysqlV11DownSQL , "{{api_keys}}" , sqlTableAPIKeys )
return sqlCommonExecSQLAndUpdateDBVersion ( dbHandle , strings . Split ( sql , ";" ) , 10 )
2021-06-11 20:27:36 +00:00
}