sqlite.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. // Copyright (C) 2019-2022 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. //go:build !nosqlite
  15. // +build !nosqlite
  16. package dataprovider
  17. import (
  18. "context"
  19. "crypto/x509"
  20. "database/sql"
  21. "errors"
  22. "fmt"
  23. "path/filepath"
  24. "strings"
  25. "time"
  26. // we import go-sqlite3 here to be able to disable SQLite support using a build tag
  27. _ "github.com/mattn/go-sqlite3"
  28. "github.com/drakkan/sftpgo/v2/logger"
  29. "github.com/drakkan/sftpgo/v2/util"
  30. "github.com/drakkan/sftpgo/v2/version"
  31. "github.com/drakkan/sftpgo/v2/vfs"
  32. )
  33. const (
  34. sqliteResetSQL = `DROP TABLE IF EXISTS "{{api_keys}}";
  35. DROP TABLE IF EXISTS "{{folders_mapping}}";
  36. DROP TABLE IF EXISTS "{{users_folders_mapping}}";
  37. DROP TABLE IF EXISTS "{{users_groups_mapping}}";
  38. DROP TABLE IF EXISTS "{{groups_folders_mapping}}";
  39. DROP TABLE IF EXISTS "{{admins}}";
  40. DROP TABLE IF EXISTS "{{folders}}";
  41. DROP TABLE IF EXISTS "{{shares}}";
  42. DROP TABLE IF EXISTS "{{users}}";
  43. DROP TABLE IF EXISTS "{{groups}}";
  44. DROP TABLE IF EXISTS "{{defender_events}}";
  45. DROP TABLE IF EXISTS "{{defender_hosts}}";
  46. DROP TABLE IF EXISTS "{{active_transfers}}";
  47. DROP TABLE IF EXISTS "{{shared_sessions}}";
  48. DROP TABLE IF EXISTS "{{schema_version}}";
  49. `
  50. sqliteInitialSQL = `CREATE TABLE "{{schema_version}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "version" integer NOT NULL);
  51. CREATE TABLE "{{admins}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "username" varchar(255) NOT NULL UNIQUE,
  52. "description" varchar(512) NULL, "password" varchar(255) NOT NULL, "email" varchar(255) NULL, "status" integer NOT NULL,
  53. "permissions" text NOT NULL, "filters" text NULL, "additional_info" text NULL, "last_login" bigint NOT NULL,
  54. "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL);
  55. CREATE TABLE "{{defender_hosts}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "ip" varchar(50) NOT NULL UNIQUE,
  56. "ban_time" bigint NOT NULL, "updated_at" bigint NOT NULL);
  57. CREATE TABLE "{{defender_events}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "date_time" bigint NOT NULL,
  58. "score" integer NOT NULL, "host_id" integer NOT NULL REFERENCES "{{defender_hosts}}" ("id") ON DELETE CASCADE
  59. DEFERRABLE INITIALLY DEFERRED);
  60. CREATE TABLE "{{folders}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(255) NOT NULL UNIQUE,
  61. "description" varchar(512) NULL, "path" text NULL, "used_quota_size" bigint NOT NULL, "used_quota_files" integer NOT NULL,
  62. "last_quota_update" bigint NOT NULL, "filesystem" text NULL);
  63. CREATE TABLE "{{users}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "username" varchar(255) NOT NULL UNIQUE,
  64. "status" integer NOT NULL, "expiration_date" bigint NOT NULL, "description" varchar(512) NULL, "password" text NULL,
  65. "public_keys" text NULL, "home_dir" text NOT NULL, "uid" bigint NOT NULL, "gid" bigint NOT NULL,
  66. "max_sessions" integer NOT NULL, "quota_size" bigint NOT NULL, "quota_files" integer NOT NULL, "permissions" text NOT NULL,
  67. "used_quota_size" bigint NOT NULL, "used_quota_files" integer NOT NULL, "last_quota_update" bigint NOT NULL,
  68. "upload_bandwidth" integer NOT NULL, "download_bandwidth" integer NOT NULL, "last_login" bigint NOT NULL, "filters" text NULL,
  69. "filesystem" text NULL, "additional_info" text NULL, "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL,
  70. "email" varchar(255) NULL);
  71. CREATE TABLE "{{folders_mapping}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "virtual_path" text NOT NULL,
  72. "quota_size" bigint NOT NULL, "quota_files" integer NOT NULL, "folder_id" integer NOT NULL REFERENCES "{{folders}}" ("id")
  73. ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, "user_id" integer NOT NULL REFERENCES "{{users}}" ("id") ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
  74. CONSTRAINT "{{prefix}}unique_mapping" UNIQUE ("user_id", "folder_id"));
  75. CREATE TABLE "{{shares}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "share_id" varchar(60) NOT NULL UNIQUE,
  76. "name" varchar(255) NOT NULL, "description" varchar(512) NULL, "scope" integer NOT NULL, "paths" text NOT NULL,
  77. "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "last_use_at" bigint NOT NULL, "expires_at" bigint NOT NULL,
  78. "password" text NULL, "max_tokens" integer NOT NULL, "used_tokens" integer NOT NULL, "allow_from" text NULL,
  79. "user_id" integer NOT NULL REFERENCES "{{users}}" ("id") ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED);
  80. CREATE TABLE "{{api_keys}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(255) NOT NULL,
  81. "key_id" varchar(50) NOT NULL UNIQUE, "api_key" varchar(255) NOT NULL UNIQUE, "scope" integer NOT NULL,
  82. "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "last_use_at" bigint NOT NULL, "expires_at" bigint NOT NULL,
  83. "description" text NULL, "admin_id" integer NULL REFERENCES "{{admins}}" ("id") ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
  84. "user_id" integer NULL REFERENCES "{{users}}" ("id") ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED);
  85. CREATE INDEX "{{prefix}}folders_mapping_folder_id_idx" ON "{{folders_mapping}}" ("folder_id");
  86. CREATE INDEX "{{prefix}}folders_mapping_user_id_idx" ON "{{folders_mapping}}" ("user_id");
  87. CREATE INDEX "{{prefix}}api_keys_admin_id_idx" ON "{{api_keys}}" ("admin_id");
  88. CREATE INDEX "{{prefix}}api_keys_user_id_idx" ON "{{api_keys}}" ("user_id");
  89. CREATE INDEX "{{prefix}}users_updated_at_idx" ON "{{users}}" ("updated_at");
  90. CREATE INDEX "{{prefix}}shares_user_id_idx" ON "{{shares}}" ("user_id");
  91. CREATE INDEX "{{prefix}}defender_hosts_updated_at_idx" ON "{{defender_hosts}}" ("updated_at");
  92. CREATE INDEX "{{prefix}}defender_hosts_ban_time_idx" ON "{{defender_hosts}}" ("ban_time");
  93. CREATE INDEX "{{prefix}}defender_events_date_time_idx" ON "{{defender_events}}" ("date_time");
  94. CREATE INDEX "{{prefix}}defender_events_host_id_idx" ON "{{defender_events}}" ("host_id");
  95. INSERT INTO {{schema_version}} (version) VALUES (15);
  96. `
  97. sqliteV16SQL = `ALTER TABLE "{{users}}" ADD COLUMN "download_data_transfer" integer DEFAULT 0 NOT NULL;
  98. ALTER TABLE "{{users}}" ADD COLUMN "total_data_transfer" integer DEFAULT 0 NOT NULL;
  99. ALTER TABLE "{{users}}" ADD COLUMN "upload_data_transfer" integer DEFAULT 0 NOT NULL;
  100. ALTER TABLE "{{users}}" ADD COLUMN "used_download_data_transfer" integer DEFAULT 0 NOT NULL;
  101. ALTER TABLE "{{users}}" ADD COLUMN "used_upload_data_transfer" integer DEFAULT 0 NOT NULL;
  102. CREATE TABLE "{{active_transfers}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "connection_id" varchar(100) NOT NULL,
  103. "transfer_id" bigint NOT NULL, "transfer_type" integer NOT NULL, "username" varchar(255) NOT NULL,
  104. "folder_name" varchar(255) NULL, "ip" varchar(50) NOT NULL, "truncated_size" bigint NOT NULL,
  105. "current_ul_size" bigint NOT NULL, "current_dl_size" bigint NOT NULL, "created_at" bigint NOT NULL,
  106. "updated_at" bigint NOT NULL);
  107. CREATE INDEX "{{prefix}}active_transfers_connection_id_idx" ON "{{active_transfers}}" ("connection_id");
  108. CREATE INDEX "{{prefix}}active_transfers_transfer_id_idx" ON "{{active_transfers}}" ("transfer_id");
  109. CREATE INDEX "{{prefix}}active_transfers_updated_at_idx" ON "{{active_transfers}}" ("updated_at");
  110. `
  111. sqliteV16DownSQL = `ALTER TABLE "{{users}}" DROP COLUMN "used_upload_data_transfer";
  112. ALTER TABLE "{{users}}" DROP COLUMN "used_download_data_transfer";
  113. ALTER TABLE "{{users}}" DROP COLUMN "upload_data_transfer";
  114. ALTER TABLE "{{users}}" DROP COLUMN "total_data_transfer";
  115. ALTER TABLE "{{users}}" DROP COLUMN "download_data_transfer";
  116. DROP TABLE "{{active_transfers}}";
  117. `
  118. sqliteV17SQL = `CREATE TABLE "{{groups}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(255) NOT NULL UNIQUE,
  119. "description" varchar(512) NULL, "created_at" bigint NOT NULL, "updated_at" bigint NOT NULL, "user_settings" text NULL);
  120. CREATE TABLE "{{groups_folders_mapping}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  121. "folder_id" integer NOT NULL REFERENCES "{{folders}}" ("id") ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
  122. "group_id" integer NOT NULL REFERENCES "{{groups}}" ("id") ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
  123. "virtual_path" text NOT NULL, "quota_size" bigint NOT NULL, "quota_files" integer NOT NULL,
  124. CONSTRAINT "{{prefix}}unique_group_folder_mapping" UNIQUE ("group_id", "folder_id"));
  125. CREATE TABLE "{{users_groups_mapping}}" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  126. "user_id" integer NOT NULL REFERENCES "{{users}}" ("id") ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
  127. "group_id" integer NOT NULL REFERENCES "{{groups}}" ("id") ON DELETE NO ACTION,
  128. "group_type" integer NOT NULL, CONSTRAINT "{{prefix}}unique_user_group_mapping" UNIQUE ("user_id", "group_id"));
  129. CREATE TABLE "new__folders_mapping" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  130. "user_id" integer NOT NULL REFERENCES "{{users}}" ("id") ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
  131. "folder_id" integer NOT NULL REFERENCES "{{folders}}" ("id") ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
  132. "virtual_path" text NOT NULL, "quota_size" bigint NOT NULL, "quota_files" integer NOT NULL,
  133. CONSTRAINT "{{prefix}}unique_user_folder_mapping" UNIQUE ("user_id", "folder_id"));
  134. INSERT INTO "new__folders_mapping" ("id", "virtual_path", "quota_size", "quota_files", "folder_id", "user_id") SELECT "id",
  135. "virtual_path", "quota_size", "quota_files", "folder_id", "user_id" FROM "{{folders_mapping}}";
  136. DROP TABLE "{{folders_mapping}}";
  137. ALTER TABLE "new__folders_mapping" RENAME TO "{{users_folders_mapping}}";
  138. CREATE INDEX "{{prefix}}groups_updated_at_idx" ON "{{groups}}" ("updated_at");
  139. CREATE INDEX "{{prefix}}users_folders_mapping_folder_id_idx" ON "{{users_folders_mapping}}" ("folder_id");
  140. CREATE INDEX "{{prefix}}users_folders_mapping_user_id_idx" ON "{{users_folders_mapping}}" ("user_id");
  141. CREATE INDEX "{{prefix}}users_groups_mapping_group_id_idx" ON "{{users_groups_mapping}}" ("group_id");
  142. CREATE INDEX "{{prefix}}users_groups_mapping_user_id_idx" ON "{{users_groups_mapping}}" ("user_id");
  143. CREATE INDEX "{{prefix}}groups_folders_mapping_folder_id_idx" ON "{{groups_folders_mapping}}" ("folder_id");
  144. CREATE INDEX "{{prefix}}groups_folders_mapping_group_id_idx" ON "{{groups_folders_mapping}}" ("group_id");
  145. `
  146. sqliteV17DownSQL = `DROP TABLE "{{users_groups_mapping}}";
  147. DROP TABLE "{{groups_folders_mapping}}";
  148. DROP TABLE "{{groups}}";
  149. CREATE TABLE "new__folders_mapping" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  150. "user_id" integer NOT NULL REFERENCES "{{users}}" ("id") ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
  151. "folder_id" integer NOT NULL REFERENCES "{{folders}}" ("id") ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
  152. "virtual_path" text NOT NULL, "quota_size" bigint NOT NULL, "quota_files" integer NOT NULL,
  153. CONSTRAINT "{{prefix}}unique_folder_mapping" UNIQUE ("user_id", "folder_id"));
  154. INSERT INTO "new__folders_mapping" ("id", "virtual_path", "quota_size", "quota_files", "folder_id", "user_id") SELECT "id",
  155. "virtual_path", "quota_size", "quota_files", "folder_id", "user_id" FROM "{{users_folders_mapping}}";
  156. DROP TABLE "{{users_folders_mapping}}";
  157. ALTER TABLE "new__folders_mapping" RENAME TO "{{folders_mapping}}";
  158. CREATE INDEX "{{prefix}}folders_mapping_folder_id_idx" ON "{{folders_mapping}}" ("folder_id");
  159. CREATE INDEX "{{prefix}}folders_mapping_user_id_idx" ON "{{folders_mapping}}" ("user_id");
  160. `
  161. sqliteV19SQL = `CREATE TABLE "{{shared_sessions}}" ("key" varchar(128) NOT NULL PRIMARY KEY, "data" text NOT NULL,
  162. "type" integer NOT NULL, "timestamp" bigint NOT NULL);
  163. CREATE INDEX "{{prefix}}shared_sessions_type_idx" ON "{{shared_sessions}}" ("type");
  164. CREATE INDEX "{{prefix}}shared_sessions_timestamp_idx" ON "{{shared_sessions}}" ("timestamp");
  165. `
  166. sqliteV19DownSQL = `DROP TABLE "{{shared_sessions}}";`
  167. )
  168. // SQLiteProvider defines the auth provider for SQLite database
  169. type SQLiteProvider struct {
  170. dbHandle *sql.DB
  171. }
  172. func init() {
  173. version.AddFeature("+sqlite")
  174. }
  175. func initializeSQLiteProvider(basePath string) error {
  176. var err error
  177. var connectionString string
  178. if config.ConnectionString == "" {
  179. dbPath := config.Name
  180. if !util.IsFileInputValid(dbPath) {
  181. return fmt.Errorf("invalid database path: %#v", dbPath)
  182. }
  183. if !filepath.IsAbs(dbPath) {
  184. dbPath = filepath.Join(basePath, dbPath)
  185. }
  186. connectionString = fmt.Sprintf("file:%v?cache=shared&_foreign_keys=1", dbPath)
  187. } else {
  188. connectionString = config.ConnectionString
  189. }
  190. dbHandle, err := sql.Open("sqlite3", connectionString)
  191. if err == nil {
  192. providerLog(logger.LevelDebug, "sqlite database handle created, connection string: %#v", connectionString)
  193. dbHandle.SetMaxOpenConns(1)
  194. provider = &SQLiteProvider{dbHandle: dbHandle}
  195. } else {
  196. providerLog(logger.LevelError, "error creating sqlite database handler, connection string: %#v, error: %v",
  197. connectionString, err)
  198. }
  199. return err
  200. }
  201. func (p *SQLiteProvider) checkAvailability() error {
  202. return sqlCommonCheckAvailability(p.dbHandle)
  203. }
  204. func (p *SQLiteProvider) validateUserAndPass(username, password, ip, protocol string) (User, error) {
  205. return sqlCommonValidateUserAndPass(username, password, ip, protocol, p.dbHandle)
  206. }
  207. func (p *SQLiteProvider) validateUserAndTLSCert(username, protocol string, tlsCert *x509.Certificate) (User, error) {
  208. return sqlCommonValidateUserAndTLSCertificate(username, protocol, tlsCert, p.dbHandle)
  209. }
  210. func (p *SQLiteProvider) validateUserAndPubKey(username string, publicKey []byte, isSSHCert bool) (User, string, error) {
  211. return sqlCommonValidateUserAndPubKey(username, publicKey, isSSHCert, p.dbHandle)
  212. }
  213. func (p *SQLiteProvider) updateTransferQuota(username string, uploadSize, downloadSize int64, reset bool) error {
  214. return sqlCommonUpdateTransferQuota(username, uploadSize, downloadSize, reset, p.dbHandle)
  215. }
  216. func (p *SQLiteProvider) updateQuota(username string, filesAdd int, sizeAdd int64, reset bool) error {
  217. return sqlCommonUpdateQuota(username, filesAdd, sizeAdd, reset, p.dbHandle)
  218. }
  219. func (p *SQLiteProvider) getUsedQuota(username string) (int, int64, int64, int64, error) {
  220. return sqlCommonGetUsedQuota(username, p.dbHandle)
  221. }
  222. func (p *SQLiteProvider) setUpdatedAt(username string) {
  223. sqlCommonSetUpdatedAt(username, p.dbHandle)
  224. }
  225. func (p *SQLiteProvider) updateLastLogin(username string) error {
  226. return sqlCommonUpdateLastLogin(username, p.dbHandle)
  227. }
  228. func (p *SQLiteProvider) updateAdminLastLogin(username string) error {
  229. return sqlCommonUpdateAdminLastLogin(username, p.dbHandle)
  230. }
  231. func (p *SQLiteProvider) userExists(username string) (User, error) {
  232. return sqlCommonGetUserByUsername(username, p.dbHandle)
  233. }
  234. func (p *SQLiteProvider) addUser(user *User) error {
  235. return sqlCommonAddUser(user, p.dbHandle)
  236. }
  237. func (p *SQLiteProvider) updateUser(user *User) error {
  238. return sqlCommonUpdateUser(user, p.dbHandle)
  239. }
  240. func (p *SQLiteProvider) deleteUser(user User) error {
  241. return sqlCommonDeleteUser(user, p.dbHandle)
  242. }
  243. func (p *SQLiteProvider) updateUserPassword(username, password string) error {
  244. return sqlCommonUpdateUserPassword(username, password, p.dbHandle)
  245. }
  246. func (p *SQLiteProvider) dumpUsers() ([]User, error) {
  247. return sqlCommonDumpUsers(p.dbHandle)
  248. }
  249. func (p *SQLiteProvider) getRecentlyUpdatedUsers(after int64) ([]User, error) {
  250. return sqlCommonGetRecentlyUpdatedUsers(after, p.dbHandle)
  251. }
  252. func (p *SQLiteProvider) getUsers(limit int, offset int, order string) ([]User, error) {
  253. return sqlCommonGetUsers(limit, offset, order, p.dbHandle)
  254. }
  255. func (p *SQLiteProvider) getUsersForQuotaCheck(toFetch map[string]bool) ([]User, error) {
  256. return sqlCommonGetUsersForQuotaCheck(toFetch, p.dbHandle)
  257. }
  258. func (p *SQLiteProvider) dumpFolders() ([]vfs.BaseVirtualFolder, error) {
  259. return sqlCommonDumpFolders(p.dbHandle)
  260. }
  261. func (p *SQLiteProvider) getFolders(limit, offset int, order string, minimal bool) ([]vfs.BaseVirtualFolder, error) {
  262. return sqlCommonGetFolders(limit, offset, order, minimal, p.dbHandle)
  263. }
  264. func (p *SQLiteProvider) getFolderByName(name string) (vfs.BaseVirtualFolder, error) {
  265. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  266. defer cancel()
  267. return sqlCommonGetFolderByName(ctx, name, p.dbHandle)
  268. }
  269. func (p *SQLiteProvider) addFolder(folder *vfs.BaseVirtualFolder) error {
  270. return sqlCommonAddFolder(folder, p.dbHandle)
  271. }
  272. func (p *SQLiteProvider) updateFolder(folder *vfs.BaseVirtualFolder) error {
  273. return sqlCommonUpdateFolder(folder, p.dbHandle)
  274. }
  275. func (p *SQLiteProvider) deleteFolder(folder vfs.BaseVirtualFolder) error {
  276. return sqlCommonDeleteFolder(folder, p.dbHandle)
  277. }
  278. func (p *SQLiteProvider) updateFolderQuota(name string, filesAdd int, sizeAdd int64, reset bool) error {
  279. return sqlCommonUpdateFolderQuota(name, filesAdd, sizeAdd, reset, p.dbHandle)
  280. }
  281. func (p *SQLiteProvider) getUsedFolderQuota(name string) (int, int64, error) {
  282. return sqlCommonGetFolderUsedQuota(name, p.dbHandle)
  283. }
  284. func (p *SQLiteProvider) getGroups(limit, offset int, order string, minimal bool) ([]Group, error) {
  285. return sqlCommonGetGroups(limit, offset, order, minimal, p.dbHandle)
  286. }
  287. func (p *SQLiteProvider) getGroupsWithNames(names []string) ([]Group, error) {
  288. return sqlCommonGetGroupsWithNames(names, p.dbHandle)
  289. }
  290. func (p *SQLiteProvider) getUsersInGroups(names []string) ([]string, error) {
  291. return sqlCommonGetUsersInGroups(names, p.dbHandle)
  292. }
  293. func (p *SQLiteProvider) groupExists(name string) (Group, error) {
  294. return sqlCommonGetGroupByName(name, p.dbHandle)
  295. }
  296. func (p *SQLiteProvider) addGroup(group *Group) error {
  297. return sqlCommonAddGroup(group, p.dbHandle)
  298. }
  299. func (p *SQLiteProvider) updateGroup(group *Group) error {
  300. return sqlCommonUpdateGroup(group, p.dbHandle)
  301. }
  302. func (p *SQLiteProvider) deleteGroup(group Group) error {
  303. return sqlCommonDeleteGroup(group, p.dbHandle)
  304. }
  305. func (p *SQLiteProvider) dumpGroups() ([]Group, error) {
  306. return sqlCommonDumpGroups(p.dbHandle)
  307. }
  308. func (p *SQLiteProvider) adminExists(username string) (Admin, error) {
  309. return sqlCommonGetAdminByUsername(username, p.dbHandle)
  310. }
  311. func (p *SQLiteProvider) addAdmin(admin *Admin) error {
  312. return sqlCommonAddAdmin(admin, p.dbHandle)
  313. }
  314. func (p *SQLiteProvider) updateAdmin(admin *Admin) error {
  315. return sqlCommonUpdateAdmin(admin, p.dbHandle)
  316. }
  317. func (p *SQLiteProvider) deleteAdmin(admin Admin) error {
  318. return sqlCommonDeleteAdmin(admin, p.dbHandle)
  319. }
  320. func (p *SQLiteProvider) getAdmins(limit int, offset int, order string) ([]Admin, error) {
  321. return sqlCommonGetAdmins(limit, offset, order, p.dbHandle)
  322. }
  323. func (p *SQLiteProvider) dumpAdmins() ([]Admin, error) {
  324. return sqlCommonDumpAdmins(p.dbHandle)
  325. }
  326. func (p *SQLiteProvider) validateAdminAndPass(username, password, ip string) (Admin, error) {
  327. return sqlCommonValidateAdminAndPass(username, password, ip, p.dbHandle)
  328. }
  329. func (p *SQLiteProvider) apiKeyExists(keyID string) (APIKey, error) {
  330. return sqlCommonGetAPIKeyByID(keyID, p.dbHandle)
  331. }
  332. func (p *SQLiteProvider) addAPIKey(apiKey *APIKey) error {
  333. return sqlCommonAddAPIKey(apiKey, p.dbHandle)
  334. }
  335. func (p *SQLiteProvider) updateAPIKey(apiKey *APIKey) error {
  336. return sqlCommonUpdateAPIKey(apiKey, p.dbHandle)
  337. }
  338. func (p *SQLiteProvider) deleteAPIKey(apiKey APIKey) error {
  339. return sqlCommonDeleteAPIKey(apiKey, p.dbHandle)
  340. }
  341. func (p *SQLiteProvider) getAPIKeys(limit int, offset int, order string) ([]APIKey, error) {
  342. return sqlCommonGetAPIKeys(limit, offset, order, p.dbHandle)
  343. }
  344. func (p *SQLiteProvider) dumpAPIKeys() ([]APIKey, error) {
  345. return sqlCommonDumpAPIKeys(p.dbHandle)
  346. }
  347. func (p *SQLiteProvider) updateAPIKeyLastUse(keyID string) error {
  348. return sqlCommonUpdateAPIKeyLastUse(keyID, p.dbHandle)
  349. }
  350. func (p *SQLiteProvider) shareExists(shareID, username string) (Share, error) {
  351. return sqlCommonGetShareByID(shareID, username, p.dbHandle)
  352. }
  353. func (p *SQLiteProvider) addShare(share *Share) error {
  354. return sqlCommonAddShare(share, p.dbHandle)
  355. }
  356. func (p *SQLiteProvider) updateShare(share *Share) error {
  357. return sqlCommonUpdateShare(share, p.dbHandle)
  358. }
  359. func (p *SQLiteProvider) deleteShare(share Share) error {
  360. return sqlCommonDeleteShare(share, p.dbHandle)
  361. }
  362. func (p *SQLiteProvider) getShares(limit int, offset int, order, username string) ([]Share, error) {
  363. return sqlCommonGetShares(limit, offset, order, username, p.dbHandle)
  364. }
  365. func (p *SQLiteProvider) dumpShares() ([]Share, error) {
  366. return sqlCommonDumpShares(p.dbHandle)
  367. }
  368. func (p *SQLiteProvider) updateShareLastUse(shareID string, numTokens int) error {
  369. return sqlCommonUpdateShareLastUse(shareID, numTokens, p.dbHandle)
  370. }
  371. func (p *SQLiteProvider) getDefenderHosts(from int64, limit int) ([]DefenderEntry, error) {
  372. return sqlCommonGetDefenderHosts(from, limit, p.dbHandle)
  373. }
  374. func (p *SQLiteProvider) getDefenderHostByIP(ip string, from int64) (DefenderEntry, error) {
  375. return sqlCommonGetDefenderHostByIP(ip, from, p.dbHandle)
  376. }
  377. func (p *SQLiteProvider) isDefenderHostBanned(ip string) (DefenderEntry, error) {
  378. return sqlCommonIsDefenderHostBanned(ip, p.dbHandle)
  379. }
  380. func (p *SQLiteProvider) updateDefenderBanTime(ip string, minutes int) error {
  381. return sqlCommonDefenderIncrementBanTime(ip, minutes, p.dbHandle)
  382. }
  383. func (p *SQLiteProvider) deleteDefenderHost(ip string) error {
  384. return sqlCommonDeleteDefenderHost(ip, p.dbHandle)
  385. }
  386. func (p *SQLiteProvider) addDefenderEvent(ip string, score int) error {
  387. return sqlCommonAddDefenderHostAndEvent(ip, score, p.dbHandle)
  388. }
  389. func (p *SQLiteProvider) setDefenderBanTime(ip string, banTime int64) error {
  390. return sqlCommonSetDefenderBanTime(ip, banTime, p.dbHandle)
  391. }
  392. func (p *SQLiteProvider) cleanupDefender(from int64) error {
  393. return sqlCommonDefenderCleanup(from, p.dbHandle)
  394. }
  395. func (p *SQLiteProvider) addActiveTransfer(transfer ActiveTransfer) error {
  396. return sqlCommonAddActiveTransfer(transfer, p.dbHandle)
  397. }
  398. func (p *SQLiteProvider) updateActiveTransferSizes(ulSize, dlSize, transferID int64, connectionID string) error {
  399. return sqlCommonUpdateActiveTransferSizes(ulSize, dlSize, transferID, connectionID, p.dbHandle)
  400. }
  401. func (p *SQLiteProvider) removeActiveTransfer(transferID int64, connectionID string) error {
  402. return sqlCommonRemoveActiveTransfer(transferID, connectionID, p.dbHandle)
  403. }
  404. func (p *SQLiteProvider) cleanupActiveTransfers(before time.Time) error {
  405. return sqlCommonCleanupActiveTransfers(before, p.dbHandle)
  406. }
  407. func (p *SQLiteProvider) getActiveTransfers(from time.Time) ([]ActiveTransfer, error) {
  408. return sqlCommonGetActiveTransfers(from, p.dbHandle)
  409. }
  410. func (p *SQLiteProvider) addSharedSession(session Session) error {
  411. return sqlCommonAddSession(session, p.dbHandle)
  412. }
  413. func (p *SQLiteProvider) deleteSharedSession(key string) error {
  414. return sqlCommonDeleteSession(key, p.dbHandle)
  415. }
  416. func (p *SQLiteProvider) getSharedSession(key string) (Session, error) {
  417. return sqlCommonGetSession(key, p.dbHandle)
  418. }
  419. func (p *SQLiteProvider) cleanupSharedSessions(sessionType SessionType, before int64) error {
  420. return sqlCommonCleanupSessions(sessionType, before, p.dbHandle)
  421. }
  422. func (p *SQLiteProvider) close() error {
  423. return p.dbHandle.Close()
  424. }
  425. func (p *SQLiteProvider) reloadConfig() error {
  426. return nil
  427. }
  428. // initializeDatabase creates the initial database structure
  429. func (p *SQLiteProvider) initializeDatabase() error {
  430. dbVersion, err := sqlCommonGetDatabaseVersion(p.dbHandle, false)
  431. if err == nil && dbVersion.Version > 0 {
  432. return ErrNoInitRequired
  433. }
  434. if errors.Is(err, sql.ErrNoRows) {
  435. return errSchemaVersionEmpty
  436. }
  437. logger.InfoToConsole("creating initial database schema, version 15")
  438. providerLog(logger.LevelInfo, "creating initial database schema, version 15")
  439. initialSQL := strings.ReplaceAll(sqliteInitialSQL, "{{schema_version}}", sqlTableSchemaVersion)
  440. initialSQL = strings.ReplaceAll(initialSQL, "{{admins}}", sqlTableAdmins)
  441. initialSQL = strings.ReplaceAll(initialSQL, "{{folders}}", sqlTableFolders)
  442. initialSQL = strings.ReplaceAll(initialSQL, "{{users}}", sqlTableUsers)
  443. initialSQL = strings.ReplaceAll(initialSQL, "{{folders_mapping}}", sqlTableFoldersMapping)
  444. initialSQL = strings.ReplaceAll(initialSQL, "{{api_keys}}", sqlTableAPIKeys)
  445. initialSQL = strings.ReplaceAll(initialSQL, "{{shares}}", sqlTableShares)
  446. initialSQL = strings.ReplaceAll(initialSQL, "{{defender_events}}", sqlTableDefenderEvents)
  447. initialSQL = strings.ReplaceAll(initialSQL, "{{defender_hosts}}", sqlTableDefenderHosts)
  448. initialSQL = strings.ReplaceAll(initialSQL, "{{prefix}}", config.SQLTablesPrefix)
  449. return sqlCommonExecSQLAndUpdateDBVersion(p.dbHandle, []string{initialSQL}, 15, true)
  450. }
  451. func (p *SQLiteProvider) migrateDatabase() error { //nolint:dupl
  452. dbVersion, err := sqlCommonGetDatabaseVersion(p.dbHandle, true)
  453. if err != nil {
  454. return err
  455. }
  456. switch version := dbVersion.Version; {
  457. case version == sqlDatabaseVersion:
  458. providerLog(logger.LevelDebug, "sql database is up to date, current version: %v", version)
  459. return ErrNoInitRequired
  460. case version < 15:
  461. err = fmt.Errorf("database version %v is too old, please see the upgrading docs", version)
  462. providerLog(logger.LevelError, "%v", err)
  463. logger.ErrorToConsole("%v", err)
  464. return err
  465. case version == 15:
  466. return updateSQLiteDatabaseFromV15(p.dbHandle)
  467. case version == 16:
  468. return updateSQLiteDatabaseFromV16(p.dbHandle)
  469. case version == 17:
  470. return updateSQLiteDatabaseFromV17(p.dbHandle)
  471. case version == 18:
  472. return updateSQLiteDatabaseFromV18(p.dbHandle)
  473. default:
  474. if version > sqlDatabaseVersion {
  475. providerLog(logger.LevelError, "database version %v is newer than the supported one: %v", version,
  476. sqlDatabaseVersion)
  477. logger.WarnToConsole("database version %v is newer than the supported one: %v", version,
  478. sqlDatabaseVersion)
  479. return nil
  480. }
  481. return fmt.Errorf("database version not handled: %v", version)
  482. }
  483. }
  484. func (p *SQLiteProvider) revertDatabase(targetVersion int) error {
  485. dbVersion, err := sqlCommonGetDatabaseVersion(p.dbHandle, true)
  486. if err != nil {
  487. return err
  488. }
  489. if dbVersion.Version == targetVersion {
  490. return errors.New("current version match target version, nothing to do")
  491. }
  492. switch dbVersion.Version {
  493. case 16:
  494. return downgradeSQLiteDatabaseFromV16(p.dbHandle)
  495. case 17:
  496. return downgradeSQLiteDatabaseFromV17(p.dbHandle)
  497. case 18:
  498. return downgradeSQLiteDatabaseFromV18(p.dbHandle)
  499. case 19:
  500. return downgradeSQLiteDatabaseFromV19(p.dbHandle)
  501. default:
  502. return fmt.Errorf("database version not handled: %v", dbVersion.Version)
  503. }
  504. }
  505. func (p *SQLiteProvider) resetDatabase() error {
  506. sql := sqlReplaceAll(sqliteResetSQL)
  507. return sqlCommonExecSQLAndUpdateDBVersion(p.dbHandle, []string{sql}, 0, false)
  508. }
  509. func updateSQLiteDatabaseFromV15(dbHandle *sql.DB) error {
  510. if err := updateSQLiteDatabaseFrom15To16(dbHandle); err != nil {
  511. return err
  512. }
  513. return updateSQLiteDatabaseFromV16(dbHandle)
  514. }
  515. func updateSQLiteDatabaseFromV16(dbHandle *sql.DB) error {
  516. if err := updateSQLiteDatabaseFrom16To17(dbHandle); err != nil {
  517. return err
  518. }
  519. return updateSQLiteDatabaseFromV17(dbHandle)
  520. }
  521. func updateSQLiteDatabaseFromV17(dbHandle *sql.DB) error {
  522. if err := updateSQLiteDatabaseFrom17To18(dbHandle); err != nil {
  523. return err
  524. }
  525. return updateSQLiteDatabaseFromV18(dbHandle)
  526. }
  527. func updateSQLiteDatabaseFromV18(dbHandle *sql.DB) error {
  528. return updateSQLiteDatabaseFrom18To19(dbHandle)
  529. }
  530. func downgradeSQLiteDatabaseFromV16(dbHandle *sql.DB) error {
  531. return downgradeSQLiteDatabaseFrom16To15(dbHandle)
  532. }
  533. func downgradeSQLiteDatabaseFromV17(dbHandle *sql.DB) error {
  534. if err := downgradeSQLiteDatabaseFrom17To16(dbHandle); err != nil {
  535. return err
  536. }
  537. return downgradeSQLiteDatabaseFromV16(dbHandle)
  538. }
  539. func downgradeSQLiteDatabaseFromV18(dbHandle *sql.DB) error {
  540. if err := downgradeSQLiteDatabaseFrom18To17(dbHandle); err != nil {
  541. return err
  542. }
  543. return downgradeSQLiteDatabaseFromV17(dbHandle)
  544. }
  545. func downgradeSQLiteDatabaseFromV19(dbHandle *sql.DB) error {
  546. if err := downgradeSQLiteDatabaseFrom19To18(dbHandle); err != nil {
  547. return err
  548. }
  549. return downgradeSQLiteDatabaseFromV18(dbHandle)
  550. }
  551. func updateSQLiteDatabaseFrom15To16(dbHandle *sql.DB) error {
  552. logger.InfoToConsole("updating database version: 15 -> 16")
  553. providerLog(logger.LevelInfo, "updating database version: 15 -> 16")
  554. sql := strings.ReplaceAll(sqliteV16SQL, "{{users}}", sqlTableUsers)
  555. sql = strings.ReplaceAll(sql, "{{active_transfers}}", sqlTableActiveTransfers)
  556. sql = strings.ReplaceAll(sql, "{{prefix}}", config.SQLTablesPrefix)
  557. return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 16, true)
  558. }
  559. func updateSQLiteDatabaseFrom16To17(dbHandle *sql.DB) error {
  560. logger.InfoToConsole("updating database version: 16 -> 17")
  561. providerLog(logger.LevelInfo, "updating database version: 16 -> 17")
  562. if err := setPragmaFK(dbHandle, "OFF"); err != nil {
  563. return err
  564. }
  565. sql := strings.ReplaceAll(sqliteV17SQL, "{{users}}", sqlTableUsers)
  566. sql = strings.ReplaceAll(sql, "{{groups}}", sqlTableGroups)
  567. sql = strings.ReplaceAll(sql, "{{users}}", sqlTableUsers)
  568. sql = strings.ReplaceAll(sql, "{{folders}}", sqlTableFolders)
  569. sql = strings.ReplaceAll(sql, "{{folders_mapping}}", sqlTableFoldersMapping)
  570. sql = strings.ReplaceAll(sql, "{{users_folders_mapping}}", sqlTableUsersFoldersMapping)
  571. sql = strings.ReplaceAll(sql, "{{users_groups_mapping}}", sqlTableUsersGroupsMapping)
  572. sql = strings.ReplaceAll(sql, "{{groups_folders_mapping}}", sqlTableGroupsFoldersMapping)
  573. sql = strings.ReplaceAll(sql, "{{prefix}}", config.SQLTablesPrefix)
  574. if err := sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 17, true); err != nil {
  575. return err
  576. }
  577. return setPragmaFK(dbHandle, "ON")
  578. }
  579. func updateSQLiteDatabaseFrom17To18(dbHandle *sql.DB) error {
  580. logger.InfoToConsole("updating database version: 17 -> 18")
  581. providerLog(logger.LevelInfo, "updating database version: 17 -> 18")
  582. if err := importGCSCredentials(); err != nil {
  583. return err
  584. }
  585. return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, nil, 18, true)
  586. }
  587. func updateSQLiteDatabaseFrom18To19(dbHandle *sql.DB) error {
  588. logger.InfoToConsole("updating database version: 18 -> 19")
  589. providerLog(logger.LevelInfo, "updating database version: 18 -> 19")
  590. sql := strings.ReplaceAll(sqliteV19SQL, "{{shared_sessions}}", sqlTableSharedSessions)
  591. sql = strings.ReplaceAll(sql, "{{prefix}}", config.SQLTablesPrefix)
  592. return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 19, true)
  593. }
  594. func downgradeSQLiteDatabaseFrom16To15(dbHandle *sql.DB) error {
  595. logger.InfoToConsole("downgrading database version: 16 -> 15")
  596. providerLog(logger.LevelInfo, "downgrading database version: 16 -> 15")
  597. sql := strings.ReplaceAll(sqliteV16DownSQL, "{{users}}", sqlTableUsers)
  598. sql = strings.ReplaceAll(sql, "{{active_transfers}}", sqlTableActiveTransfers)
  599. return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 15, false)
  600. }
  601. func downgradeSQLiteDatabaseFrom17To16(dbHandle *sql.DB) error {
  602. logger.InfoToConsole("downgrading database version: 17 -> 16")
  603. providerLog(logger.LevelInfo, "downgrading database version: 17 -> 16")
  604. if err := setPragmaFK(dbHandle, "OFF"); err != nil {
  605. return err
  606. }
  607. sql := strings.ReplaceAll(sqliteV17DownSQL, "{{groups}}", sqlTableGroups)
  608. sql = strings.ReplaceAll(sql, "{{users}}", sqlTableUsers)
  609. sql = strings.ReplaceAll(sql, "{{folders}}", sqlTableFolders)
  610. sql = strings.ReplaceAll(sql, "{{folders_mapping}}", sqlTableFoldersMapping)
  611. sql = strings.ReplaceAll(sql, "{{users_folders_mapping}}", sqlTableUsersFoldersMapping)
  612. sql = strings.ReplaceAll(sql, "{{users_groups_mapping}}", sqlTableUsersGroupsMapping)
  613. sql = strings.ReplaceAll(sql, "{{groups_folders_mapping}}", sqlTableGroupsFoldersMapping)
  614. sql = strings.ReplaceAll(sql, "{{prefix}}", config.SQLTablesPrefix)
  615. if err := sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 16, false); err != nil {
  616. return err
  617. }
  618. return setPragmaFK(dbHandle, "ON")
  619. }
  620. func downgradeSQLiteDatabaseFrom18To17(dbHandle *sql.DB) error {
  621. logger.InfoToConsole("downgrading database version: 18 -> 17")
  622. providerLog(logger.LevelInfo, "downgrading database version: 18 -> 17")
  623. return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, nil, 17, false)
  624. }
  625. func downgradeSQLiteDatabaseFrom19To18(dbHandle *sql.DB) error {
  626. logger.InfoToConsole("downgrading database version: 19 -> 18")
  627. providerLog(logger.LevelInfo, "downgrading database version: 19 -> 18")
  628. sql := strings.ReplaceAll(sqliteV19DownSQL, "{{shared_sessions}}", sqlTableSharedSessions)
  629. return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 18, false)
  630. }
  631. func setPragmaFK(dbHandle *sql.DB, value string) error {
  632. ctx, cancel := context.WithTimeout(context.Background(), longSQLQueryTimeout)
  633. defer cancel()
  634. sql := fmt.Sprintf("PRAGMA foreign_keys=%v;", value)
  635. _, err := dbHandle.ExecContext(ctx, sql)
  636. return err
  637. }