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, " +
2022-01-09 11:25:53 +00:00
"`permissions` longtext NOT NULL, `filters` longtext NULL, `additional_info` longtext NULL, `last_login` bigint NOT NULL, " +
"`created_at` bigint NOT NULL, `updated_at` bigint NOT NULL);" +
"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;" +
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, " +
2022-01-09 11:25:53 +00:00
"`description` varchar(512) NULL, `path` longtext NULL, `used_quota_size` bigint NOT NULL, " +
2021-06-19 07:03:20 +00:00
"`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, " +
2022-01-09 11:25:53 +00:00
"`public_keys` longtext NULL, `home_dir` longtext NOT NULL, `uid` integer NOT NULL, `gid` integer NOT NULL, " +
2021-02-22 07:37:50 +00:00
"`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, " +
2022-01-09 11:25:53 +00:00
"`last_login` bigint NOT NULL, `filters` longtext NULL, `filesystem` longtext NULL, `additional_info` longtext NULL, " +
"`created_at` bigint NOT NULL, `updated_at` bigint NOT NULL, `email` varchar(255) NULL);" +
"CREATE TABLE `{{folders_mapping}}` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `virtual_path` longtext NOT NULL, " +
2020-06-07 21:30:18 +00:00
"`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;" +
2022-01-09 11:25:53 +00:00
"CREATE TABLE `{{shares}}` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, " +
2021-11-06 13:13:20 +00:00
"`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` " +
2022-01-09 11:25:53 +00:00
"FOREIGN KEY (`user_id`) REFERENCES `{{users}}` (`id`) ON DELETE CASCADE;" +
"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;" +
"CREATE INDEX `{{prefix}}users_updated_at_idx` ON `{{users}}` (`updated_at`);" +
2021-12-25 11:08:07 +00:00
"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`);" +
2022-01-09 11:25:53 +00:00
"CREATE INDEX `{{prefix}}defender_events_date_time_idx` ON `{{defender_events}}` (`date_time`);" +
"INSERT INTO {{schema_version}} (version) VALUES (15);"
2020-02-08 13:44:25 +00:00
)
2022-01-09 11:25:53 +00:00
// MySQLProvider defines the 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
}
2022-01-09 11:25:53 +00:00
logger . InfoToConsole ( "creating initial database schema, version 15" )
providerLog ( logger . LevelInfo , "creating initial database schema, version 15" )
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 )
2022-01-09 11:25:53 +00:00
initialSQL = strings . ReplaceAll ( initialSQL , "{{api_keys}}" , sqlTableAPIKeys )
initialSQL = strings . ReplaceAll ( initialSQL , "{{shares}}" , sqlTableShares )
initialSQL = strings . ReplaceAll ( initialSQL , "{{defender_events}}" , sqlTableDefenderEvents )
initialSQL = strings . ReplaceAll ( initialSQL , "{{defender_hosts}}" , sqlTableDefenderHosts )
2021-04-12 18:00:49 +00:00
initialSQL = strings . ReplaceAll ( initialSQL , "{{prefix}}" , config . SQLTablesPrefix )
2021-02-16 18:11:36 +00:00
2022-01-09 11:25:53 +00:00
return sqlCommonExecSQLAndUpdateDBVersion ( p . dbHandle , strings . Split ( initialSQL , ";" ) , 15 )
2020-02-08 13:44:25 +00:00
}
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
2022-01-09 11:25:53 +00:00
case version < 15 :
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
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 {
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 )
}