sqlcommon.go 39 KB

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