sqlcommon.go 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  1. package dataprovider
  2. import (
  3. "context"
  4. "database/sql"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "strings"
  9. "time"
  10. "github.com/drakkan/sftpgo/logger"
  11. "github.com/drakkan/sftpgo/utils"
  12. "github.com/drakkan/sftpgo/vfs"
  13. )
  14. const (
  15. sqlDatabaseVersion = 8
  16. initialDBVersionSQL = "INSERT INTO {{schema_version}} (version) VALUES (1);"
  17. defaultSQLQueryTimeout = 10 * time.Second
  18. longSQLQueryTimeout = 60 * time.Second
  19. )
  20. var errSQLFoldersAssosaction = errors.New("unable to associate virtual folders to user")
  21. type sqlQuerier interface {
  22. PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
  23. }
  24. type sqlScanner interface {
  25. Scan(dest ...interface{}) error
  26. }
  27. func sqlCommonGetAdminByUsername(username string, dbHandle sqlQuerier) (Admin, error) {
  28. var admin Admin
  29. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  30. defer cancel()
  31. q := getAdminByUsernameQuery()
  32. stmt, err := dbHandle.PrepareContext(ctx, q)
  33. if err != nil {
  34. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  35. return admin, err
  36. }
  37. defer stmt.Close()
  38. row := stmt.QueryRowContext(ctx, username)
  39. return getAdminFromDbRow(row)
  40. }
  41. func sqlCommonValidateAdminAndPass(username, password, ip string, dbHandle *sql.DB) (Admin, error) {
  42. admin, err := sqlCommonGetAdminByUsername(username, dbHandle)
  43. if err != nil {
  44. providerLog(logger.LevelWarn, "error authenticating admin %#v: %v", username, err)
  45. return admin, err
  46. }
  47. err = admin.checkUserAndPass(password, ip)
  48. return admin, err
  49. }
  50. func sqlCommonAddAdmin(admin *Admin, dbHandle *sql.DB) error {
  51. err := admin.validate()
  52. if err != nil {
  53. return err
  54. }
  55. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  56. defer cancel()
  57. q := getAddAdminQuery()
  58. stmt, err := dbHandle.PrepareContext(ctx, q)
  59. if err != nil {
  60. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  61. return err
  62. }
  63. defer stmt.Close()
  64. perms, err := json.Marshal(admin.Permissions)
  65. if err != nil {
  66. return err
  67. }
  68. filters, err := json.Marshal(admin.Filters)
  69. if err != nil {
  70. return err
  71. }
  72. _, err = stmt.ExecContext(ctx, admin.Username, admin.Password, admin.Status, admin.Email, string(perms),
  73. string(filters), admin.AdditionalInfo)
  74. return err
  75. }
  76. func sqlCommonUpdateAdmin(admin *Admin, dbHandle *sql.DB) error {
  77. err := admin.validate()
  78. if err != nil {
  79. return err
  80. }
  81. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  82. defer cancel()
  83. q := getUpdateAdminQuery()
  84. stmt, err := dbHandle.PrepareContext(ctx, q)
  85. if err != nil {
  86. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  87. return err
  88. }
  89. defer stmt.Close()
  90. perms, err := json.Marshal(admin.Permissions)
  91. if err != nil {
  92. return err
  93. }
  94. filters, err := json.Marshal(admin.Filters)
  95. if err != nil {
  96. return err
  97. }
  98. _, err = stmt.ExecContext(ctx, admin.Password, admin.Status, admin.Email, string(perms), string(filters),
  99. admin.AdditionalInfo, admin.Username)
  100. return err
  101. }
  102. func sqlCommonDeleteAdmin(admin *Admin, dbHandle *sql.DB) error {
  103. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  104. defer cancel()
  105. q := getDeleteAdminQuery()
  106. stmt, err := dbHandle.PrepareContext(ctx, q)
  107. if err != nil {
  108. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  109. return err
  110. }
  111. defer stmt.Close()
  112. _, err = stmt.ExecContext(ctx, admin.Username)
  113. return err
  114. }
  115. func sqlCommonGetAdmins(limit, offset int, order string, dbHandle sqlQuerier) ([]Admin, error) {
  116. admins := make([]Admin, 0, limit)
  117. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  118. defer cancel()
  119. q := getAdminsQuery(order)
  120. stmt, err := dbHandle.PrepareContext(ctx, q)
  121. if err != nil {
  122. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  123. return nil, err
  124. }
  125. defer stmt.Close()
  126. rows, err := stmt.QueryContext(ctx, limit, offset)
  127. if err != nil {
  128. return admins, err
  129. }
  130. defer rows.Close()
  131. for rows.Next() {
  132. a, err := getAdminFromDbRow(rows)
  133. if err != nil {
  134. return admins, err
  135. }
  136. a.HideConfidentialData()
  137. admins = append(admins, a)
  138. }
  139. return admins, rows.Err()
  140. }
  141. func sqlCommonDumpAdmins(dbHandle sqlQuerier) ([]Admin, error) {
  142. admins := make([]Admin, 0, 30)
  143. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  144. defer cancel()
  145. q := getDumpAdminsQuery()
  146. stmt, err := dbHandle.PrepareContext(ctx, q)
  147. if err != nil {
  148. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  149. return nil, err
  150. }
  151. defer stmt.Close()
  152. rows, err := stmt.QueryContext(ctx)
  153. if err != nil {
  154. return admins, err
  155. }
  156. defer rows.Close()
  157. for rows.Next() {
  158. a, err := getAdminFromDbRow(rows)
  159. if err != nil {
  160. return admins, err
  161. }
  162. admins = append(admins, a)
  163. }
  164. return admins, rows.Err()
  165. }
  166. func sqlCommonGetUserByUsername(username string, dbHandle sqlQuerier) (User, error) {
  167. var user User
  168. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  169. defer cancel()
  170. q := getUserByUsernameQuery()
  171. stmt, err := dbHandle.PrepareContext(ctx, q)
  172. if err != nil {
  173. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  174. return user, err
  175. }
  176. defer stmt.Close()
  177. row := stmt.QueryRowContext(ctx, username)
  178. user, err = getUserFromDbRow(row)
  179. if err != nil {
  180. return user, err
  181. }
  182. return getUserWithVirtualFolders(user, dbHandle)
  183. }
  184. func sqlCommonValidateUserAndPass(username, password, ip, protocol string, dbHandle *sql.DB) (User, error) {
  185. var user User
  186. if password == "" {
  187. return user, errors.New("Credentials cannot be null or empty")
  188. }
  189. user, err := sqlCommonGetUserByUsername(username, dbHandle)
  190. if err != nil {
  191. providerLog(logger.LevelWarn, "error authenticating user %#v: %v", username, err)
  192. return user, err
  193. }
  194. return checkUserAndPass(user, password, ip, protocol)
  195. }
  196. func sqlCommonValidateUserAndPubKey(username string, pubKey []byte, dbHandle *sql.DB) (User, string, error) {
  197. var user User
  198. if len(pubKey) == 0 {
  199. return user, "", errors.New("Credentials cannot be null or empty")
  200. }
  201. user, err := sqlCommonGetUserByUsername(username, dbHandle)
  202. if err != nil {
  203. providerLog(logger.LevelWarn, "error authenticating user %#v: %v", username, err)
  204. return user, "", err
  205. }
  206. return checkUserAndPubKey(user, pubKey)
  207. }
  208. func sqlCommonCheckAvailability(dbHandle *sql.DB) error {
  209. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  210. defer cancel()
  211. return dbHandle.PingContext(ctx)
  212. }
  213. func sqlCommonUpdateQuota(username string, filesAdd int, sizeAdd int64, reset bool, dbHandle *sql.DB) error {
  214. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  215. defer cancel()
  216. q := getUpdateQuotaQuery(reset)
  217. stmt, err := dbHandle.PrepareContext(ctx, q)
  218. if err != nil {
  219. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  220. return err
  221. }
  222. defer stmt.Close()
  223. _, err = stmt.ExecContext(ctx, sizeAdd, filesAdd, utils.GetTimeAsMsSinceEpoch(time.Now()), username)
  224. if err == nil {
  225. providerLog(logger.LevelDebug, "quota updated for user %#v, files increment: %v size increment: %v is reset? %v",
  226. username, filesAdd, sizeAdd, reset)
  227. } else {
  228. providerLog(logger.LevelWarn, "error updating quota for user %#v: %v", username, err)
  229. }
  230. return err
  231. }
  232. func sqlCommonGetUsedQuota(username string, dbHandle *sql.DB) (int, int64, error) {
  233. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  234. defer cancel()
  235. q := getQuotaQuery()
  236. stmt, err := dbHandle.PrepareContext(ctx, q)
  237. if err != nil {
  238. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  239. return 0, 0, err
  240. }
  241. defer stmt.Close()
  242. var usedFiles int
  243. var usedSize int64
  244. err = stmt.QueryRowContext(ctx, username).Scan(&usedSize, &usedFiles)
  245. if err != nil {
  246. providerLog(logger.LevelWarn, "error getting quota for user: %v, error: %v", username, err)
  247. return 0, 0, err
  248. }
  249. return usedFiles, usedSize, err
  250. }
  251. func sqlCommonUpdateLastLogin(username string, dbHandle *sql.DB) error {
  252. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  253. defer cancel()
  254. q := getUpdateLastLoginQuery()
  255. stmt, err := dbHandle.PrepareContext(ctx, q)
  256. if err != nil {
  257. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  258. return err
  259. }
  260. defer stmt.Close()
  261. _, err = stmt.ExecContext(ctx, utils.GetTimeAsMsSinceEpoch(time.Now()), username)
  262. if err == nil {
  263. providerLog(logger.LevelDebug, "last login updated for user %#v", username)
  264. } else {
  265. providerLog(logger.LevelWarn, "error updating last login for user %#v: %v", username, err)
  266. }
  267. return err
  268. }
  269. func sqlCommonAddUser(user *User, dbHandle *sql.DB) error {
  270. err := ValidateUser(user)
  271. if err != nil {
  272. return err
  273. }
  274. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  275. defer cancel()
  276. tx, err := dbHandle.BeginTx(ctx, nil)
  277. if err != nil {
  278. return err
  279. }
  280. q := getAddUserQuery()
  281. stmt, err := tx.PrepareContext(ctx, q)
  282. if err != nil {
  283. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  284. sqlCommonRollbackTransaction(tx)
  285. return err
  286. }
  287. defer stmt.Close()
  288. permissions, err := user.GetPermissionsAsJSON()
  289. if err != nil {
  290. sqlCommonRollbackTransaction(tx)
  291. return err
  292. }
  293. publicKeys, err := user.GetPublicKeysAsJSON()
  294. if err != nil {
  295. sqlCommonRollbackTransaction(tx)
  296. return err
  297. }
  298. filters, err := user.GetFiltersAsJSON()
  299. if err != nil {
  300. sqlCommonRollbackTransaction(tx)
  301. return err
  302. }
  303. fsConfig, err := user.GetFsConfigAsJSON()
  304. if err != nil {
  305. sqlCommonRollbackTransaction(tx)
  306. return err
  307. }
  308. _, err = stmt.ExecContext(ctx, user.Username, user.Password, string(publicKeys), user.HomeDir, user.UID, user.GID, user.MaxSessions, user.QuotaSize,
  309. user.QuotaFiles, string(permissions), user.UploadBandwidth, user.DownloadBandwidth, user.Status, user.ExpirationDate, string(filters),
  310. string(fsConfig), user.AdditionalInfo)
  311. if err != nil {
  312. sqlCommonRollbackTransaction(tx)
  313. return err
  314. }
  315. err = generateVirtualFoldersMapping(ctx, user, tx)
  316. if err != nil {
  317. sqlCommonRollbackTransaction(tx)
  318. return err
  319. }
  320. return tx.Commit()
  321. }
  322. func sqlCommonUpdateUser(user *User, dbHandle *sql.DB) error {
  323. err := ValidateUser(user)
  324. if err != nil {
  325. return err
  326. }
  327. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  328. defer cancel()
  329. tx, err := dbHandle.BeginTx(ctx, nil)
  330. if err != nil {
  331. return err
  332. }
  333. q := getUpdateUserQuery()
  334. stmt, err := tx.PrepareContext(ctx, q)
  335. if err != nil {
  336. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  337. sqlCommonRollbackTransaction(tx)
  338. return err
  339. }
  340. defer stmt.Close()
  341. permissions, err := user.GetPermissionsAsJSON()
  342. if err != nil {
  343. sqlCommonRollbackTransaction(tx)
  344. return err
  345. }
  346. publicKeys, err := user.GetPublicKeysAsJSON()
  347. if err != nil {
  348. sqlCommonRollbackTransaction(tx)
  349. return err
  350. }
  351. filters, err := user.GetFiltersAsJSON()
  352. if err != nil {
  353. sqlCommonRollbackTransaction(tx)
  354. return err
  355. }
  356. fsConfig, err := user.GetFsConfigAsJSON()
  357. if err != nil {
  358. sqlCommonRollbackTransaction(tx)
  359. return err
  360. }
  361. _, err = stmt.ExecContext(ctx, user.Password, string(publicKeys), user.HomeDir, user.UID, user.GID, user.MaxSessions, user.QuotaSize,
  362. user.QuotaFiles, string(permissions), user.UploadBandwidth, user.DownloadBandwidth, user.Status, user.ExpirationDate,
  363. string(filters), string(fsConfig), user.AdditionalInfo, user.ID)
  364. if err != nil {
  365. sqlCommonRollbackTransaction(tx)
  366. return err
  367. }
  368. err = generateVirtualFoldersMapping(ctx, user, tx)
  369. if err != nil {
  370. sqlCommonRollbackTransaction(tx)
  371. return err
  372. }
  373. return tx.Commit()
  374. }
  375. func sqlCommonDeleteUser(user *User, dbHandle *sql.DB) error {
  376. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  377. defer cancel()
  378. q := getDeleteUserQuery()
  379. stmt, err := dbHandle.PrepareContext(ctx, q)
  380. if err != nil {
  381. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  382. return err
  383. }
  384. defer stmt.Close()
  385. _, err = stmt.ExecContext(ctx, user.ID)
  386. return err
  387. }
  388. func sqlCommonDumpUsers(dbHandle sqlQuerier) ([]User, error) {
  389. users := make([]User, 0, 100)
  390. ctx, cancel := context.WithTimeout(context.Background(), longSQLQueryTimeout)
  391. defer cancel()
  392. q := getDumpUsersQuery()
  393. stmt, err := dbHandle.PrepareContext(ctx, q)
  394. if err != nil {
  395. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  396. return nil, err
  397. }
  398. defer stmt.Close()
  399. rows, err := stmt.QueryContext(ctx)
  400. if err != nil {
  401. return users, err
  402. }
  403. defer rows.Close()
  404. for rows.Next() {
  405. u, err := getUserFromDbRow(rows)
  406. if err != nil {
  407. return users, err
  408. }
  409. err = addCredentialsToUser(&u)
  410. if err != nil {
  411. return users, err
  412. }
  413. users = append(users, u)
  414. }
  415. err = rows.Err()
  416. if err != nil {
  417. return users, err
  418. }
  419. return getUsersWithVirtualFolders(users, dbHandle)
  420. }
  421. func sqlCommonGetUsers(limit int, offset int, order string, dbHandle sqlQuerier) ([]User, error) {
  422. users := make([]User, 0, limit)
  423. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  424. defer cancel()
  425. q := getUsersQuery(order)
  426. stmt, err := dbHandle.PrepareContext(ctx, q)
  427. if err != nil {
  428. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  429. return nil, err
  430. }
  431. defer stmt.Close()
  432. rows, err := stmt.QueryContext(ctx, limit, offset)
  433. if err == nil {
  434. defer rows.Close()
  435. for rows.Next() {
  436. u, err := getUserFromDbRow(rows)
  437. if err != nil {
  438. return users, err
  439. }
  440. u.HideConfidentialData()
  441. users = append(users, u)
  442. }
  443. }
  444. err = rows.Err()
  445. if err != nil {
  446. return users, err
  447. }
  448. return getUsersWithVirtualFolders(users, dbHandle)
  449. }
  450. func updateUserPermissionsFromDb(user *User, permissions string) error {
  451. var err error
  452. perms := make(map[string][]string)
  453. err = json.Unmarshal([]byte(permissions), &perms)
  454. if err == nil {
  455. user.Permissions = perms
  456. } else {
  457. // compatibility layer: until version 0.9.4 permissions were a string list
  458. var list []string
  459. err = json.Unmarshal([]byte(permissions), &list)
  460. if err != nil {
  461. return err
  462. }
  463. perms["/"] = list
  464. user.Permissions = perms
  465. }
  466. return err
  467. }
  468. func getAdminFromDbRow(row sqlScanner) (Admin, error) {
  469. var admin Admin
  470. var email, filters, additionalInfo, permissions sql.NullString
  471. err := row.Scan(&admin.ID, &admin.Username, &admin.Password, &admin.Status, &email, &permissions,
  472. &filters, &additionalInfo)
  473. if err != nil {
  474. if err == sql.ErrNoRows {
  475. return admin, &RecordNotFoundError{err: err.Error()}
  476. }
  477. return admin, err
  478. }
  479. if permissions.Valid {
  480. var perms []string
  481. err = json.Unmarshal([]byte(permissions.String), &perms)
  482. if err != nil {
  483. return admin, err
  484. }
  485. admin.Permissions = perms
  486. }
  487. if email.Valid {
  488. admin.Email = email.String
  489. }
  490. if filters.Valid {
  491. var adminFilters AdminFilters
  492. err = json.Unmarshal([]byte(filters.String), &adminFilters)
  493. if err == nil {
  494. admin.Filters = adminFilters
  495. }
  496. }
  497. if additionalInfo.Valid {
  498. admin.AdditionalInfo = additionalInfo.String
  499. }
  500. return admin, err
  501. }
  502. func getUserFromDbRow(row sqlScanner) (User, error) {
  503. var user User
  504. var permissions sql.NullString
  505. var password sql.NullString
  506. var publicKey sql.NullString
  507. var filters sql.NullString
  508. var fsConfig sql.NullString
  509. var additionalInfo sql.NullString
  510. err := row.Scan(&user.ID, &user.Username, &password, &publicKey, &user.HomeDir, &user.UID, &user.GID, &user.MaxSessions,
  511. &user.QuotaSize, &user.QuotaFiles, &permissions, &user.UsedQuotaSize, &user.UsedQuotaFiles, &user.LastQuotaUpdate,
  512. &user.UploadBandwidth, &user.DownloadBandwidth, &user.ExpirationDate, &user.LastLogin, &user.Status, &filters, &fsConfig,
  513. &additionalInfo)
  514. if err != nil {
  515. if err == sql.ErrNoRows {
  516. return user, &RecordNotFoundError{err: err.Error()}
  517. }
  518. return user, err
  519. }
  520. if password.Valid {
  521. user.Password = password.String
  522. }
  523. // we can have a empty string or an invalid json in null string
  524. // so we do a relaxed test if the field is optional, for example we
  525. // populate public keys only if unmarshal does not return an error
  526. if publicKey.Valid {
  527. var list []string
  528. err = json.Unmarshal([]byte(publicKey.String), &list)
  529. if err == nil {
  530. user.PublicKeys = list
  531. }
  532. }
  533. if permissions.Valid {
  534. err = updateUserPermissionsFromDb(&user, permissions.String)
  535. if err != nil {
  536. return user, err
  537. }
  538. }
  539. if filters.Valid {
  540. var userFilters UserFilters
  541. err = json.Unmarshal([]byte(filters.String), &userFilters)
  542. if err == nil {
  543. user.Filters = userFilters
  544. }
  545. }
  546. if fsConfig.Valid {
  547. var fs Filesystem
  548. err = json.Unmarshal([]byte(fsConfig.String), &fs)
  549. if err == nil {
  550. user.FsConfig = fs
  551. }
  552. }
  553. if additionalInfo.Valid {
  554. user.AdditionalInfo = additionalInfo.String
  555. }
  556. user.SetEmptySecretsIfNil()
  557. return user, err
  558. }
  559. func sqlCommonCheckFolderExists(ctx context.Context, name string, dbHandle sqlQuerier) (vfs.BaseVirtualFolder, error) {
  560. var folder vfs.BaseVirtualFolder
  561. q := getFolderByNameQuery()
  562. stmt, err := dbHandle.PrepareContext(ctx, q)
  563. if err != nil {
  564. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  565. return folder, err
  566. }
  567. defer stmt.Close()
  568. row := stmt.QueryRowContext(ctx, name)
  569. var mappedPath sql.NullString
  570. err = row.Scan(&folder.ID, &mappedPath, &folder.UsedQuotaSize, &folder.UsedQuotaFiles, &folder.LastQuotaUpdate,
  571. &folder.Name)
  572. if err == sql.ErrNoRows {
  573. return folder, &RecordNotFoundError{err: err.Error()}
  574. }
  575. if mappedPath.Valid {
  576. folder.MappedPath = mappedPath.String
  577. }
  578. return folder, err
  579. }
  580. func sqlCommonGetFolderByName(ctx context.Context, name string, dbHandle sqlQuerier) (vfs.BaseVirtualFolder, error) {
  581. folder, err := sqlCommonCheckFolderExists(ctx, name, dbHandle)
  582. if err != nil {
  583. return folder, err
  584. }
  585. folders, err := getVirtualFoldersWithUsers([]vfs.BaseVirtualFolder{folder}, dbHandle)
  586. if err != nil {
  587. return folder, err
  588. }
  589. if len(folders) != 1 {
  590. return folder, fmt.Errorf("unable to associate users with folder %#v", name)
  591. }
  592. return folders[0], nil
  593. }
  594. func sqlCommonAddOrGetFolder(ctx context.Context, baseFolder vfs.BaseVirtualFolder, usedQuotaSize int64, usedQuotaFiles int, lastQuotaUpdate int64, dbHandle sqlQuerier) (vfs.BaseVirtualFolder, error) {
  595. folder, err := sqlCommonCheckFolderExists(ctx, baseFolder.Name, dbHandle)
  596. if _, ok := err.(*RecordNotFoundError); ok {
  597. f := &vfs.BaseVirtualFolder{
  598. Name: baseFolder.Name,
  599. MappedPath: baseFolder.MappedPath,
  600. UsedQuotaSize: usedQuotaSize,
  601. UsedQuotaFiles: usedQuotaFiles,
  602. LastQuotaUpdate: lastQuotaUpdate,
  603. }
  604. err = sqlCommonAddFolder(f, dbHandle)
  605. if err != nil {
  606. return folder, err
  607. }
  608. return sqlCommonCheckFolderExists(ctx, baseFolder.Name, dbHandle)
  609. }
  610. return folder, err
  611. }
  612. func sqlCommonAddFolder(folder *vfs.BaseVirtualFolder, dbHandle sqlQuerier) error {
  613. err := validateFolder(folder)
  614. if err != nil {
  615. return err
  616. }
  617. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  618. defer cancel()
  619. q := getAddFolderQuery()
  620. stmt, err := dbHandle.PrepareContext(ctx, q)
  621. if err != nil {
  622. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  623. return err
  624. }
  625. defer stmt.Close()
  626. _, err = stmt.ExecContext(ctx, folder.MappedPath, folder.UsedQuotaSize, folder.UsedQuotaFiles,
  627. folder.LastQuotaUpdate, folder.Name)
  628. return err
  629. }
  630. func sqlCommonUpdateFolder(folder *vfs.BaseVirtualFolder, dbHandle *sql.DB) error {
  631. err := validateFolder(folder)
  632. if err != nil {
  633. return err
  634. }
  635. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  636. defer cancel()
  637. q := getUpdateFolderQuery()
  638. stmt, err := dbHandle.PrepareContext(ctx, q)
  639. if err != nil {
  640. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  641. return err
  642. }
  643. defer stmt.Close()
  644. _, err = stmt.ExecContext(ctx, folder.MappedPath, folder.Name)
  645. return err
  646. }
  647. func sqlCommonDeleteFolder(folder *vfs.BaseVirtualFolder, dbHandle sqlQuerier) error {
  648. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  649. defer cancel()
  650. q := getDeleteFolderQuery()
  651. stmt, err := dbHandle.PrepareContext(ctx, q)
  652. if err != nil {
  653. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  654. return err
  655. }
  656. defer stmt.Close()
  657. _, err = stmt.ExecContext(ctx, folder.ID)
  658. return err
  659. }
  660. func sqlCommonDumpFolders(dbHandle sqlQuerier) ([]vfs.BaseVirtualFolder, error) {
  661. folders := make([]vfs.BaseVirtualFolder, 0, 50)
  662. ctx, cancel := context.WithTimeout(context.Background(), longSQLQueryTimeout)
  663. defer cancel()
  664. q := getDumpFoldersQuery()
  665. stmt, err := dbHandle.PrepareContext(ctx, q)
  666. if err != nil {
  667. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  668. return nil, err
  669. }
  670. defer stmt.Close()
  671. rows, err := stmt.QueryContext(ctx)
  672. if err != nil {
  673. return folders, err
  674. }
  675. defer rows.Close()
  676. for rows.Next() {
  677. var folder vfs.BaseVirtualFolder
  678. var mappedPath sql.NullString
  679. err = rows.Scan(&folder.ID, &mappedPath, &folder.UsedQuotaSize, &folder.UsedQuotaFiles,
  680. &folder.LastQuotaUpdate, &folder.Name)
  681. if err != nil {
  682. return folders, err
  683. }
  684. if mappedPath.Valid {
  685. folder.MappedPath = mappedPath.String
  686. }
  687. folders = append(folders, folder)
  688. }
  689. err = rows.Err()
  690. if err != nil {
  691. return folders, err
  692. }
  693. return getVirtualFoldersWithUsers(folders, dbHandle)
  694. }
  695. func sqlCommonGetFolders(limit, offset int, order string, dbHandle sqlQuerier) ([]vfs.BaseVirtualFolder, error) {
  696. folders := make([]vfs.BaseVirtualFolder, 0, limit)
  697. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  698. defer cancel()
  699. q := getFoldersQuery(order)
  700. stmt, err := dbHandle.PrepareContext(ctx, q)
  701. if err != nil {
  702. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  703. return nil, err
  704. }
  705. defer stmt.Close()
  706. rows, err := stmt.QueryContext(ctx, limit, offset)
  707. if err != nil {
  708. return folders, err
  709. }
  710. defer rows.Close()
  711. for rows.Next() {
  712. var folder vfs.BaseVirtualFolder
  713. var mappedPath sql.NullString
  714. err = rows.Scan(&folder.ID, &mappedPath, &folder.UsedQuotaSize, &folder.UsedQuotaFiles,
  715. &folder.LastQuotaUpdate, &folder.Name)
  716. if err != nil {
  717. return folders, err
  718. }
  719. if mappedPath.Valid {
  720. folder.MappedPath = mappedPath.String
  721. }
  722. folders = append(folders, folder)
  723. }
  724. err = rows.Err()
  725. if err != nil {
  726. return folders, err
  727. }
  728. return getVirtualFoldersWithUsers(folders, dbHandle)
  729. }
  730. func sqlCommonClearFolderMapping(ctx context.Context, user *User, dbHandle sqlQuerier) error {
  731. q := getClearFolderMappingQuery()
  732. stmt, err := dbHandle.PrepareContext(ctx, q)
  733. if err != nil {
  734. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  735. return err
  736. }
  737. defer stmt.Close()
  738. _, err = stmt.ExecContext(ctx, user.Username)
  739. return err
  740. }
  741. func sqlCommonAddFolderMapping(ctx context.Context, user *User, folder vfs.VirtualFolder, dbHandle sqlQuerier) error {
  742. q := getAddFolderMappingQuery()
  743. stmt, err := dbHandle.PrepareContext(ctx, q)
  744. if err != nil {
  745. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  746. return err
  747. }
  748. defer stmt.Close()
  749. _, err = stmt.ExecContext(ctx, folder.VirtualPath, folder.QuotaSize, folder.QuotaFiles, folder.ID, user.Username)
  750. return err
  751. }
  752. func generateVirtualFoldersMapping(ctx context.Context, user *User, dbHandle sqlQuerier) error {
  753. err := sqlCommonClearFolderMapping(ctx, user, dbHandle)
  754. if err != nil {
  755. return err
  756. }
  757. for _, vfolder := range user.VirtualFolders {
  758. f, err := sqlCommonAddOrGetFolder(ctx, vfolder.BaseVirtualFolder, 0, 0, 0, dbHandle)
  759. if err != nil {
  760. return err
  761. }
  762. vfolder.BaseVirtualFolder = f
  763. err = sqlCommonAddFolderMapping(ctx, user, vfolder, dbHandle)
  764. if err != nil {
  765. return err
  766. }
  767. }
  768. return err
  769. }
  770. func getUserWithVirtualFolders(user User, dbHandle sqlQuerier) (User, error) {
  771. users, err := getUsersWithVirtualFolders([]User{user}, dbHandle)
  772. if err != nil {
  773. return user, err
  774. }
  775. if len(users) == 0 {
  776. return user, errSQLFoldersAssosaction
  777. }
  778. return users[0], err
  779. }
  780. func getUsersWithVirtualFolders(users []User, dbHandle sqlQuerier) ([]User, error) {
  781. var err error
  782. usersVirtualFolders := make(map[int64][]vfs.VirtualFolder)
  783. if len(users) == 0 {
  784. return users, err
  785. }
  786. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  787. defer cancel()
  788. q := getRelatedFoldersForUsersQuery(users)
  789. stmt, err := dbHandle.PrepareContext(ctx, q)
  790. if err != nil {
  791. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  792. return nil, err
  793. }
  794. defer stmt.Close()
  795. rows, err := stmt.QueryContext(ctx)
  796. if err != nil {
  797. return nil, err
  798. }
  799. defer rows.Close()
  800. for rows.Next() {
  801. var folder vfs.VirtualFolder
  802. var userID int64
  803. var mappedPath sql.NullString
  804. err = rows.Scan(&folder.ID, &folder.Name, &mappedPath, &folder.UsedQuotaSize, &folder.UsedQuotaFiles,
  805. &folder.LastQuotaUpdate, &folder.VirtualPath, &folder.QuotaSize, &folder.QuotaFiles, &userID)
  806. if err != nil {
  807. return users, err
  808. }
  809. if mappedPath.Valid {
  810. folder.MappedPath = mappedPath.String
  811. }
  812. usersVirtualFolders[userID] = append(usersVirtualFolders[userID], folder)
  813. }
  814. err = rows.Err()
  815. if err != nil {
  816. return users, err
  817. }
  818. if len(usersVirtualFolders) == 0 {
  819. return users, err
  820. }
  821. for idx := range users {
  822. ref := &users[idx]
  823. ref.VirtualFolders = usersVirtualFolders[ref.ID]
  824. }
  825. return users, err
  826. }
  827. func getVirtualFoldersWithUsers(folders []vfs.BaseVirtualFolder, dbHandle sqlQuerier) ([]vfs.BaseVirtualFolder, error) {
  828. var err error
  829. vFoldersUsers := make(map[int64][]string)
  830. if len(folders) == 0 {
  831. return folders, err
  832. }
  833. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  834. defer cancel()
  835. q := getRelatedUsersForFoldersQuery(folders)
  836. stmt, err := dbHandle.PrepareContext(ctx, q)
  837. if err != nil {
  838. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  839. return nil, err
  840. }
  841. defer stmt.Close()
  842. rows, err := stmt.QueryContext(ctx)
  843. if err != nil {
  844. return nil, err
  845. }
  846. defer rows.Close()
  847. for rows.Next() {
  848. var username string
  849. var folderID int64
  850. err = rows.Scan(&folderID, &username)
  851. if err != nil {
  852. return folders, err
  853. }
  854. vFoldersUsers[folderID] = append(vFoldersUsers[folderID], username)
  855. }
  856. err = rows.Err()
  857. if err != nil {
  858. return folders, err
  859. }
  860. if len(vFoldersUsers) == 0 {
  861. return folders, err
  862. }
  863. for idx := range folders {
  864. ref := &folders[idx]
  865. ref.Users = vFoldersUsers[ref.ID]
  866. }
  867. return folders, err
  868. }
  869. func sqlCommonUpdateFolderQuota(name string, filesAdd int, sizeAdd int64, reset bool, dbHandle *sql.DB) error {
  870. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  871. defer cancel()
  872. q := getUpdateFolderQuotaQuery(reset)
  873. stmt, err := dbHandle.PrepareContext(ctx, q)
  874. if err != nil {
  875. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  876. return err
  877. }
  878. defer stmt.Close()
  879. _, err = stmt.ExecContext(ctx, sizeAdd, filesAdd, utils.GetTimeAsMsSinceEpoch(time.Now()), name)
  880. if err == nil {
  881. providerLog(logger.LevelDebug, "quota updated for folder %#v, files increment: %v size increment: %v is reset? %v",
  882. name, filesAdd, sizeAdd, reset)
  883. } else {
  884. providerLog(logger.LevelWarn, "error updating quota for folder %#v: %v", name, err)
  885. }
  886. return err
  887. }
  888. func sqlCommonGetFolderUsedQuota(mappedPath string, dbHandle *sql.DB) (int, int64, error) {
  889. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  890. defer cancel()
  891. q := getQuotaFolderQuery()
  892. stmt, err := dbHandle.PrepareContext(ctx, q)
  893. if err != nil {
  894. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  895. return 0, 0, err
  896. }
  897. defer stmt.Close()
  898. var usedFiles int
  899. var usedSize int64
  900. err = stmt.QueryRowContext(ctx, mappedPath).Scan(&usedSize, &usedFiles)
  901. if err != nil {
  902. providerLog(logger.LevelWarn, "error getting quota for folder: %v, error: %v", mappedPath, err)
  903. return 0, 0, err
  904. }
  905. return usedFiles, usedSize, err
  906. }
  907. func sqlCommonRollbackTransaction(tx *sql.Tx) {
  908. err := tx.Rollback()
  909. if err != nil {
  910. providerLog(logger.LevelWarn, "error rolling back transaction: %v", err)
  911. }
  912. }
  913. func sqlCommonGetDatabaseVersion(dbHandle *sql.DB, showInitWarn bool) (schemaVersion, error) {
  914. var result schemaVersion
  915. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  916. defer cancel()
  917. q := getDatabaseVersionQuery()
  918. stmt, err := dbHandle.PrepareContext(ctx, q)
  919. if err != nil {
  920. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  921. if showInitWarn && strings.Contains(err.Error(), sqlTableSchemaVersion) {
  922. logger.WarnToConsole("database query error, did you forgot to run the \"initprovider\" command?")
  923. }
  924. return result, err
  925. }
  926. defer stmt.Close()
  927. row := stmt.QueryRowContext(ctx)
  928. err = row.Scan(&result.Version)
  929. return result, err
  930. }
  931. func sqlCommonUpdateDatabaseVersion(ctx context.Context, dbHandle sqlQuerier, version int) error {
  932. q := getUpdateDBVersionQuery()
  933. stmt, err := dbHandle.PrepareContext(ctx, q)
  934. if err != nil {
  935. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  936. return err
  937. }
  938. defer stmt.Close()
  939. _, err = stmt.ExecContext(ctx, version)
  940. return err
  941. }
  942. func sqlCommonExecSQLAndUpdateDBVersion(dbHandle *sql.DB, sql []string, newVersion int) error {
  943. ctx, cancel := context.WithTimeout(context.Background(), longSQLQueryTimeout)
  944. defer cancel()
  945. tx, err := dbHandle.BeginTx(ctx, nil)
  946. if err != nil {
  947. return err
  948. }
  949. for _, q := range sql {
  950. if strings.TrimSpace(q) == "" {
  951. continue
  952. }
  953. _, err = tx.ExecContext(ctx, q)
  954. if err != nil {
  955. sqlCommonRollbackTransaction(tx)
  956. return err
  957. }
  958. }
  959. err = sqlCommonUpdateDatabaseVersion(ctx, tx, newVersion)
  960. if err != nil {
  961. sqlCommonRollbackTransaction(tx)
  962. return err
  963. }
  964. return tx.Commit()
  965. }
  966. /*func sqlCommonGetCompatVirtualFolders(dbHandle *sql.DB) ([]userCompactVFolders, error) {
  967. users := []userCompactVFolders{}
  968. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  969. defer cancel()
  970. q := getCompatVirtualFoldersQuery()
  971. stmt, err := dbHandle.PrepareContext(ctx, q)
  972. if err != nil {
  973. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  974. return nil, err
  975. }
  976. defer stmt.Close()
  977. rows, err := stmt.QueryContext(ctx)
  978. if err != nil {
  979. return nil, err
  980. }
  981. defer rows.Close()
  982. for rows.Next() {
  983. var user userCompactVFolders
  984. var virtualFolders sql.NullString
  985. err = rows.Scan(&user.ID, &user.Username, &virtualFolders)
  986. if err != nil {
  987. return nil, err
  988. }
  989. if virtualFolders.Valid {
  990. var list []virtualFoldersCompact
  991. err = json.Unmarshal([]byte(virtualFolders.String), &list)
  992. if err == nil && len(list) > 0 {
  993. user.VirtualFolders = list
  994. users = append(users, user)
  995. }
  996. }
  997. }
  998. return users, rows.Err()
  999. }*/
  1000. /*func sqlCommonRestoreCompatVirtualFolders(ctx context.Context, users []userCompactVFolders, dbHandle sqlQuerier) ([]string, error) {
  1001. foldersToScan := []string{}
  1002. for _, user := range users {
  1003. for _, vfolder := range user.VirtualFolders {
  1004. providerLog(logger.LevelInfo, "restoring virtual folder: %+v for user %#v", vfolder, user.Username)
  1005. // -1 means included in user quota, 0 means unlimited
  1006. quotaSize := int64(-1)
  1007. quotaFiles := -1
  1008. if vfolder.ExcludeFromQuota {
  1009. quotaFiles = 0
  1010. quotaSize = 0
  1011. }
  1012. b, err := sqlCommonAddOrGetFolder(ctx, vfolder.MappedPath, 0, 0, 0, dbHandle)
  1013. if err != nil {
  1014. providerLog(logger.LevelWarn, "error restoring virtual folder for user %#v: %v", user.Username, err)
  1015. return foldersToScan, err
  1016. }
  1017. u := User{
  1018. ID: user.ID,
  1019. Username: user.Username,
  1020. }
  1021. f := vfs.VirtualFolder{
  1022. BaseVirtualFolder: b,
  1023. VirtualPath: vfolder.VirtualPath,
  1024. QuotaSize: quotaSize,
  1025. QuotaFiles: quotaFiles,
  1026. }
  1027. err = sqlCommonAddFolderMapping(ctx, &u, f, dbHandle)
  1028. if err != nil {
  1029. providerLog(logger.LevelWarn, "error adding virtual folder mapping for user %#v: %v", user.Username, err)
  1030. return foldersToScan, err
  1031. }
  1032. if !utils.IsStringInSlice(vfolder.MappedPath, foldersToScan) {
  1033. foldersToScan = append(foldersToScan, vfolder.MappedPath)
  1034. }
  1035. providerLog(logger.LevelInfo, "virtual folder: %+v for user %#v successfully restored", vfolder, user.Username)
  1036. }
  1037. }
  1038. return foldersToScan, nil
  1039. }*/
  1040. func sqlCommonUpdateDatabaseFrom3To4(sqlV4 string, dbHandle *sql.DB) error {
  1041. logger.InfoToConsole("updating database version: 3 -> 4")
  1042. providerLog(logger.LevelInfo, "updating database version: 3 -> 4")
  1043. /*users, err := sqlCommonGetCompatVirtualFolders(dbHandle)
  1044. if err != nil {
  1045. return err
  1046. }*/
  1047. sql := strings.ReplaceAll(sqlV4, "{{users}}", sqlTableUsers)
  1048. sql = strings.ReplaceAll(sql, "{{folders}}", sqlTableFolders)
  1049. sql = strings.ReplaceAll(sql, "{{folders_mapping}}", sqlTableFoldersMapping)
  1050. ctx, cancel := context.WithTimeout(context.Background(), longSQLQueryTimeout)
  1051. defer cancel()
  1052. tx, err := dbHandle.BeginTx(ctx, nil)
  1053. if err != nil {
  1054. return err
  1055. }
  1056. for _, q := range strings.Split(sql, ";") {
  1057. if strings.TrimSpace(q) == "" {
  1058. continue
  1059. }
  1060. _, err = tx.ExecContext(ctx, q)
  1061. if err != nil {
  1062. sqlCommonRollbackTransaction(tx)
  1063. return err
  1064. }
  1065. }
  1066. /*_, err = sqlCommonRestoreCompatVirtualFolders(ctx, users, tx)
  1067. if err != nil {
  1068. sqlCommonRollbackTransaction(tx)
  1069. return err
  1070. }*/
  1071. err = sqlCommonUpdateDatabaseVersion(ctx, tx, 4)
  1072. if err != nil {
  1073. sqlCommonRollbackTransaction(tx)
  1074. return err
  1075. }
  1076. return tx.Commit()
  1077. /*if err == nil {
  1078. go updateVFoldersQuotaAfterRestore(foldersToScan)
  1079. }
  1080. return err*/
  1081. }
  1082. //nolint:dupl
  1083. func sqlCommonUpdateDatabaseFrom4To5(dbHandle *sql.DB) error {
  1084. logger.InfoToConsole("updating database version: 4 -> 5")
  1085. providerLog(logger.LevelInfo, "updating database version: 4 -> 5")
  1086. ctx, cancel := context.WithTimeout(context.Background(), longSQLQueryTimeout)
  1087. defer cancel()
  1088. q := getCompatV4FsConfigQuery()
  1089. stmt, err := dbHandle.PrepareContext(ctx, q)
  1090. if err != nil {
  1091. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  1092. return err
  1093. }
  1094. defer stmt.Close()
  1095. rows, err := stmt.QueryContext(ctx)
  1096. if err != nil {
  1097. return err
  1098. }
  1099. defer rows.Close()
  1100. users := []User{}
  1101. for rows.Next() {
  1102. var compatUser compatUserV4
  1103. var fsConfigString sql.NullString
  1104. err = rows.Scan(&compatUser.ID, &compatUser.Username, &fsConfigString)
  1105. if err != nil {
  1106. return err
  1107. }
  1108. if fsConfigString.Valid {
  1109. err = json.Unmarshal([]byte(fsConfigString.String), &compatUser.FsConfig)
  1110. if err != nil {
  1111. logger.WarnToConsole("failed to unmarshal v4 user %#v, is it already migrated?", compatUser.Username)
  1112. continue
  1113. }
  1114. fsConfig, err := convertFsConfigFromV4(compatUser.FsConfig, compatUser.Username)
  1115. if err != nil {
  1116. return err
  1117. }
  1118. users = append(users, createUserFromV4(compatUser, fsConfig))
  1119. }
  1120. }
  1121. if err := rows.Err(); err != nil {
  1122. return err
  1123. }
  1124. for _, user := range users {
  1125. err = sqlCommonUpdateV4User(dbHandle, user)
  1126. if err != nil {
  1127. return err
  1128. }
  1129. providerLog(logger.LevelInfo, "filesystem config updated for user %#v", user.Username)
  1130. }
  1131. ctxVersion, cancelVersion := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  1132. defer cancelVersion()
  1133. return sqlCommonUpdateDatabaseVersion(ctxVersion, dbHandle, 5)
  1134. }
  1135. func sqlCommonUpdateV4CompatUser(dbHandle *sql.DB, user compatUserV4) error {
  1136. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  1137. defer cancel()
  1138. q := updateCompatV4FsConfigQuery()
  1139. stmt, err := dbHandle.PrepareContext(ctx, q)
  1140. if err != nil {
  1141. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  1142. return err
  1143. }
  1144. defer stmt.Close()
  1145. fsConfig, err := json.Marshal(user.FsConfig)
  1146. if err != nil {
  1147. return err
  1148. }
  1149. _, err = stmt.ExecContext(ctx, string(fsConfig), user.ID)
  1150. return err
  1151. }
  1152. func sqlCommonUpdateV4User(dbHandle *sql.DB, user User) error {
  1153. err := validateFilesystemConfig(&user)
  1154. if err != nil {
  1155. return err
  1156. }
  1157. err = saveGCSCredentials(&user)
  1158. if err != nil {
  1159. return err
  1160. }
  1161. ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  1162. defer cancel()
  1163. q := updateCompatV4FsConfigQuery()
  1164. stmt, err := dbHandle.PrepareContext(ctx, q)
  1165. if err != nil {
  1166. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  1167. return err
  1168. }
  1169. defer stmt.Close()
  1170. fsConfig, err := user.GetFsConfigAsJSON()
  1171. if err != nil {
  1172. return err
  1173. }
  1174. _, err = stmt.ExecContext(ctx, string(fsConfig), user.ID)
  1175. return err
  1176. }
  1177. //nolint:dupl
  1178. func sqlCommonDowngradeDatabaseFrom5To4(dbHandle *sql.DB) error {
  1179. logger.InfoToConsole("downgrading database version: 5 -> 4")
  1180. providerLog(logger.LevelInfo, "downgrading database version: 5 -> 4")
  1181. ctx, cancel := context.WithTimeout(context.Background(), longSQLQueryTimeout)
  1182. defer cancel()
  1183. q := getCompatV4FsConfigQuery()
  1184. stmt, err := dbHandle.PrepareContext(ctx, q)
  1185. if err != nil {
  1186. providerLog(logger.LevelWarn, "error preparing database query %#v: %v", q, err)
  1187. return err
  1188. }
  1189. defer stmt.Close()
  1190. rows, err := stmt.QueryContext(ctx)
  1191. if err != nil {
  1192. return err
  1193. }
  1194. defer rows.Close()
  1195. users := []compatUserV4{}
  1196. for rows.Next() {
  1197. var user User
  1198. var fsConfigString sql.NullString
  1199. err = rows.Scan(&user.ID, &user.Username, &fsConfigString)
  1200. if err != nil {
  1201. return err
  1202. }
  1203. if fsConfigString.Valid {
  1204. err = json.Unmarshal([]byte(fsConfigString.String), &user.FsConfig)
  1205. if err != nil {
  1206. logger.WarnToConsole("failed to unmarshal user %#v to v4, is it already migrated?", user.Username)
  1207. continue
  1208. }
  1209. fsConfig, err := convertFsConfigToV4(user.FsConfig, user.Username)
  1210. if err != nil {
  1211. return err
  1212. }
  1213. users = append(users, convertUserToV4(user, fsConfig))
  1214. }
  1215. }
  1216. if err := rows.Err(); err != nil {
  1217. return err
  1218. }
  1219. for _, user := range users {
  1220. err = sqlCommonUpdateV4CompatUser(dbHandle, user)
  1221. if err != nil {
  1222. return err
  1223. }
  1224. providerLog(logger.LevelInfo, "filesystem config downgraded for user %#v", user.Username)
  1225. }
  1226. ctxVersion, cancelVersion := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
  1227. defer cancelVersion()
  1228. return sqlCommonUpdateDatabaseVersion(ctxVersion, dbHandle, 4)
  1229. }