| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402 | 
							- //go:build !nobolt
 
- // +build !nobolt
 
- package dataprovider
 
- import (
 
- 	"crypto/x509"
 
- 	"encoding/json"
 
- 	"errors"
 
- 	"fmt"
 
- 	"path/filepath"
 
- 	"time"
 
- 	bolt "go.etcd.io/bbolt"
 
- 	"github.com/drakkan/sftpgo/v2/logger"
 
- 	"github.com/drakkan/sftpgo/v2/util"
 
- 	"github.com/drakkan/sftpgo/v2/version"
 
- 	"github.com/drakkan/sftpgo/v2/vfs"
 
- )
 
- const (
 
- 	boltDatabaseVersion = 12
 
- )
 
- var (
 
- 	usersBucket     = []byte("users")
 
- 	foldersBucket   = []byte("folders")
 
- 	adminsBucket    = []byte("admins")
 
- 	apiKeysBucket   = []byte("api_keys")
 
- 	dbVersionBucket = []byte("db_version")
 
- 	dbVersionKey    = []byte("version")
 
- )
 
- // BoltProvider auth provider for bolt key/value store
 
- type BoltProvider struct {
 
- 	dbHandle *bolt.DB
 
- }
 
- func init() {
 
- 	version.AddFeature("+bolt")
 
- }
 
- func initializeBoltProvider(basePath string) error {
 
- 	var err error
 
- 	dbPath := config.Name
 
- 	if !util.IsFileInputValid(dbPath) {
 
- 		return fmt.Errorf("invalid database path: %#v", dbPath)
 
- 	}
 
- 	if !filepath.IsAbs(dbPath) {
 
- 		dbPath = filepath.Join(basePath, dbPath)
 
- 	}
 
- 	dbHandle, err := bolt.Open(dbPath, 0600, &bolt.Options{
 
- 		NoGrowSync:   false,
 
- 		FreelistType: bolt.FreelistArrayType,
 
- 		Timeout:      5 * time.Second})
 
- 	if err == nil {
 
- 		providerLog(logger.LevelDebug, "bolt key store handle created")
 
- 		err = dbHandle.Update(func(tx *bolt.Tx) error {
 
- 			_, e := tx.CreateBucketIfNotExists(usersBucket)
 
- 			return e
 
- 		})
 
- 		if err != nil {
 
- 			providerLog(logger.LevelWarn, "error creating users bucket: %v", err)
 
- 			return err
 
- 		}
 
- 		if err != nil {
 
- 			providerLog(logger.LevelWarn, "error creating username idx bucket: %v", err)
 
- 			return err
 
- 		}
 
- 		err = dbHandle.Update(func(tx *bolt.Tx) error {
 
- 			_, e := tx.CreateBucketIfNotExists(foldersBucket)
 
- 			return e
 
- 		})
 
- 		if err != nil {
 
- 			providerLog(logger.LevelWarn, "error creating folders bucket: %v", err)
 
- 			return err
 
- 		}
 
- 		err = dbHandle.Update(func(tx *bolt.Tx) error {
 
- 			_, e := tx.CreateBucketIfNotExists(adminsBucket)
 
- 			return e
 
- 		})
 
- 		if err != nil {
 
- 			providerLog(logger.LevelWarn, "error creating admins bucket: %v", err)
 
- 			return err
 
- 		}
 
- 		err = dbHandle.Update(func(tx *bolt.Tx) error {
 
- 			_, e := tx.CreateBucketIfNotExists(apiKeysBucket)
 
- 			return e
 
- 		})
 
- 		if err != nil {
 
- 			providerLog(logger.LevelWarn, "error creating api keys bucket: %v", err)
 
- 			return err
 
- 		}
 
- 		err = dbHandle.Update(func(tx *bolt.Tx) error {
 
- 			_, e := tx.CreateBucketIfNotExists(dbVersionBucket)
 
- 			return e
 
- 		})
 
- 		if err != nil {
 
- 			providerLog(logger.LevelWarn, "error creating database version bucket: %v", err)
 
- 			return err
 
- 		}
 
- 		provider = &BoltProvider{dbHandle: dbHandle}
 
- 	} else {
 
- 		providerLog(logger.LevelWarn, "error creating bolt key/value store handler: %v", err)
 
- 	}
 
- 	return err
 
- }
 
- func (p *BoltProvider) checkAvailability() error {
 
- 	_, err := getBoltDatabaseVersion(p.dbHandle)
 
- 	return err
 
- }
 
- func (p *BoltProvider) validateUserAndTLSCert(username, protocol string, tlsCert *x509.Certificate) (User, error) {
 
- 	var user User
 
- 	if tlsCert == nil {
 
- 		return user, errors.New("TLS certificate cannot be null or empty")
 
- 	}
 
- 	user, err := p.userExists(username)
 
- 	if err != nil {
 
- 		providerLog(logger.LevelWarn, "error authenticating user %#v: %v", username, err)
 
- 		return user, err
 
- 	}
 
- 	return checkUserAndTLSCertificate(&user, protocol, tlsCert)
 
- }
 
- func (p *BoltProvider) validateUserAndPass(username, password, ip, protocol string) (User, error) {
 
- 	var user User
 
- 	if password == "" {
 
- 		return user, errors.New("credentials cannot be null or empty")
 
- 	}
 
- 	user, err := p.userExists(username)
 
- 	if err != nil {
 
- 		providerLog(logger.LevelWarn, "error authenticating user %#v: %v", username, err)
 
- 		return user, err
 
- 	}
 
- 	return checkUserAndPass(&user, password, ip, protocol)
 
- }
 
- func (p *BoltProvider) validateAdminAndPass(username, password, ip string) (Admin, error) {
 
- 	admin, err := p.adminExists(username)
 
- 	if err != nil {
 
- 		providerLog(logger.LevelWarn, "error authenticating admin %#v: %v", username, err)
 
- 		return admin, ErrInvalidCredentials
 
- 	}
 
- 	err = admin.checkUserAndPass(password, ip)
 
- 	return admin, err
 
- }
 
- func (p *BoltProvider) validateUserAndPubKey(username string, pubKey []byte) (User, string, error) {
 
- 	var user User
 
- 	if len(pubKey) == 0 {
 
- 		return user, "", errors.New("credentials cannot be null or empty")
 
- 	}
 
- 	user, err := p.userExists(username)
 
- 	if err != nil {
 
- 		providerLog(logger.LevelWarn, "error authenticating user %#v: %v", username, err)
 
- 		return user, "", err
 
- 	}
 
- 	return checkUserAndPubKey(&user, pubKey)
 
- }
 
- func (p *BoltProvider) updateAPIKeyLastUse(keyID string) error {
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAPIKeysBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		var u []byte
 
- 		if u = bucket.Get([]byte(keyID)); u == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("key %#v does not exist, unable to update last use", keyID))
 
- 		}
 
- 		var apiKey APIKey
 
- 		err = json.Unmarshal(u, &apiKey)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		apiKey.LastUseAt = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		buf, err := json.Marshal(apiKey)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		err = bucket.Put([]byte(keyID), buf)
 
- 		if err != nil {
 
- 			providerLog(logger.LevelWarn, "error updating last use for key %#v: %v", keyID, err)
 
- 			return err
 
- 		}
 
- 		providerLog(logger.LevelDebug, "last use updated for key %#v", keyID)
 
- 		return nil
 
- 	})
 
- }
 
- func (p *BoltProvider) setUpdatedAt(username string) {
 
- 	p.dbHandle.Update(func(tx *bolt.Tx) error { //nolint:errcheck
 
- 		bucket, err := getUsersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		var u []byte
 
- 		if u = bucket.Get([]byte(username)); u == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("username %#v does not exist, unable to update updated at", username))
 
- 		}
 
- 		var user User
 
- 		err = json.Unmarshal(u, &user)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		user.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		buf, err := json.Marshal(user)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		err = bucket.Put([]byte(username), buf)
 
- 		if err == nil {
 
- 			providerLog(logger.LevelDebug, "updated at set for user %#v", username)
 
- 		} else {
 
- 			providerLog(logger.LevelWarn, "error setting updated_at for user %#v: %v", username, err)
 
- 		}
 
- 		return err
 
- 	})
 
- }
 
- func (p *BoltProvider) updateLastLogin(username string) error {
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getUsersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		var u []byte
 
- 		if u = bucket.Get([]byte(username)); u == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("username %#v does not exist, unable to update last login", username))
 
- 		}
 
- 		var user User
 
- 		err = json.Unmarshal(u, &user)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		user.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		buf, err := json.Marshal(user)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		err = bucket.Put([]byte(username), buf)
 
- 		if err == nil {
 
- 			providerLog(logger.LevelDebug, "last login updated for user %#v", username)
 
- 		} else {
 
- 			providerLog(logger.LevelWarn, "error updating last login for user %#v: %v", username, err)
 
- 		}
 
- 		return err
 
- 	})
 
- }
 
- func (p *BoltProvider) updateAdminLastLogin(username string) error {
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAdminsBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		var a []byte
 
- 		if a = bucket.Get([]byte(username)); a == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("admin %#v does not exist, unable to update last login", username))
 
- 		}
 
- 		var admin Admin
 
- 		err = json.Unmarshal(a, &admin)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		admin.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		buf, err := json.Marshal(admin)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		err = bucket.Put([]byte(username), buf)
 
- 		if err == nil {
 
- 			providerLog(logger.LevelDebug, "last login updated for admin %#v", username)
 
- 			return err
 
- 		}
 
- 		providerLog(logger.LevelWarn, "error updating last login for admin %#v: %v", username, err)
 
- 		return err
 
- 	})
 
- }
 
- func (p *BoltProvider) updateQuota(username string, filesAdd int, sizeAdd int64, reset bool) error {
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getUsersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		var u []byte
 
- 		if u = bucket.Get([]byte(username)); u == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("username %#v does not exist, unable to update quota", username))
 
- 		}
 
- 		var user User
 
- 		err = json.Unmarshal(u, &user)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		if reset {
 
- 			user.UsedQuotaSize = sizeAdd
 
- 			user.UsedQuotaFiles = filesAdd
 
- 		} else {
 
- 			user.UsedQuotaSize += sizeAdd
 
- 			user.UsedQuotaFiles += filesAdd
 
- 		}
 
- 		user.LastQuotaUpdate = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		buf, err := json.Marshal(user)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		err = bucket.Put([]byte(username), buf)
 
- 		providerLog(logger.LevelDebug, "quota updated for user %#v, files increment: %v size increment: %v is reset? %v",
 
- 			username, filesAdd, sizeAdd, reset)
 
- 		return err
 
- 	})
 
- }
 
- func (p *BoltProvider) getUsedQuota(username string) (int, int64, error) {
 
- 	user, err := p.userExists(username)
 
- 	if err != nil {
 
- 		providerLog(logger.LevelWarn, "unable to get quota for user %v error: %v", username, err)
 
- 		return 0, 0, err
 
- 	}
 
- 	return user.UsedQuotaFiles, user.UsedQuotaSize, err
 
- }
 
- func (p *BoltProvider) adminExists(username string) (Admin, error) {
 
- 	var admin Admin
 
- 	err := p.dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAdminsBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		a := bucket.Get([]byte(username))
 
- 		if a == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("admin %v does not exist", username))
 
- 		}
 
- 		return json.Unmarshal(a, &admin)
 
- 	})
 
- 	return admin, err
 
- }
 
- func (p *BoltProvider) addAdmin(admin *Admin) error {
 
- 	err := admin.validate()
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAdminsBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		if a := bucket.Get([]byte(admin.Username)); a != nil {
 
- 			return fmt.Errorf("admin %v already exists", admin.Username)
 
- 		}
 
- 		id, err := bucket.NextSequence()
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		admin.ID = int64(id)
 
- 		admin.LastLogin = 0
 
- 		admin.CreatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		admin.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		buf, err := json.Marshal(admin)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		return bucket.Put([]byte(admin.Username), buf)
 
- 	})
 
- }
 
- func (p *BoltProvider) updateAdmin(admin *Admin) error {
 
- 	err := admin.validate()
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAdminsBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		var a []byte
 
- 		if a = bucket.Get([]byte(admin.Username)); a == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("admin %v does not exist", admin.Username))
 
- 		}
 
- 		var oldAdmin Admin
 
- 		err = json.Unmarshal(a, &oldAdmin)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		admin.ID = oldAdmin.ID
 
- 		admin.CreatedAt = oldAdmin.CreatedAt
 
- 		admin.LastLogin = oldAdmin.LastLogin
 
- 		admin.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		buf, err := json.Marshal(admin)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		return bucket.Put([]byte(admin.Username), buf)
 
- 	})
 
- }
 
- func (p *BoltProvider) deleteAdmin(admin *Admin) error {
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAdminsBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		if bucket.Get([]byte(admin.Username)) == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("admin %v does not exist", admin.Username))
 
- 		}
 
- 		if err := deleteRelatedAPIKey(tx, admin.Username, APIKeyScopeAdmin); err != nil {
 
- 			return err
 
- 		}
 
- 		return bucket.Delete([]byte(admin.Username))
 
- 	})
 
- }
 
- func (p *BoltProvider) getAdmins(limit int, offset int, order string) ([]Admin, error) {
 
- 	admins := make([]Admin, 0, limit)
 
- 	err := p.dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAdminsBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		cursor := bucket.Cursor()
 
- 		itNum := 0
 
- 		if order == OrderASC {
 
- 			for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
 
- 				itNum++
 
- 				if itNum <= offset {
 
- 					continue
 
- 				}
 
- 				var admin Admin
 
- 				err = json.Unmarshal(v, &admin)
 
- 				if err != nil {
 
- 					return err
 
- 				}
 
- 				admin.HideConfidentialData()
 
- 				admins = append(admins, admin)
 
- 				if len(admins) >= limit {
 
- 					break
 
- 				}
 
- 			}
 
- 		} else {
 
- 			for k, v := cursor.Last(); k != nil; k, v = cursor.Prev() {
 
- 				itNum++
 
- 				if itNum <= offset {
 
- 					continue
 
- 				}
 
- 				var admin Admin
 
- 				err = json.Unmarshal(v, &admin)
 
- 				if err != nil {
 
- 					return err
 
- 				}
 
- 				admin.HideConfidentialData()
 
- 				admins = append(admins, admin)
 
- 				if len(admins) >= limit {
 
- 					break
 
- 				}
 
- 			}
 
- 		}
 
- 		return err
 
- 	})
 
- 	return admins, err
 
- }
 
- func (p *BoltProvider) dumpAdmins() ([]Admin, error) {
 
- 	admins := make([]Admin, 0, 30)
 
- 	err := p.dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAdminsBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		cursor := bucket.Cursor()
 
- 		for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
 
- 			var admin Admin
 
- 			err = json.Unmarshal(v, &admin)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 			admins = append(admins, admin)
 
- 		}
 
- 		return err
 
- 	})
 
- 	return admins, err
 
- }
 
- func (p *BoltProvider) userExists(username string) (User, error) {
 
- 	var user User
 
- 	err := p.dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket, err := getUsersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		u := bucket.Get([]byte(username))
 
- 		if u == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("username %#v does not exist", username))
 
- 		}
 
- 		folderBucket, err := getFoldersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		user, err = joinUserAndFolders(u, folderBucket)
 
- 		return err
 
- 	})
 
- 	return user, err
 
- }
 
- func (p *BoltProvider) addUser(user *User) error {
 
- 	err := ValidateUser(user)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getUsersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		folderBucket, err := getFoldersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		if u := bucket.Get([]byte(user.Username)); u != nil {
 
- 			return fmt.Errorf("username %v already exists", user.Username)
 
- 		}
 
- 		id, err := bucket.NextSequence()
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		user.ID = int64(id)
 
- 		user.LastQuotaUpdate = 0
 
- 		user.UsedQuotaSize = 0
 
- 		user.UsedQuotaFiles = 0
 
- 		user.LastLogin = 0
 
- 		user.CreatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		user.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		for idx := range user.VirtualFolders {
 
- 			err = addUserToFolderMapping(&user.VirtualFolders[idx].BaseVirtualFolder, user, folderBucket)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 		}
 
- 		buf, err := json.Marshal(user)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		return bucket.Put([]byte(user.Username), buf)
 
- 	})
 
- }
 
- func (p *BoltProvider) updateUser(user *User) error {
 
- 	err := ValidateUser(user)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getUsersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		folderBucket, err := getFoldersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		var u []byte
 
- 		if u = bucket.Get([]byte(user.Username)); u == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("username %#v does not exist", user.Username))
 
- 		}
 
- 		var oldUser User
 
- 		err = json.Unmarshal(u, &oldUser)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		for idx := range oldUser.VirtualFolders {
 
- 			err = removeUserFromFolderMapping(&oldUser.VirtualFolders[idx], &oldUser, folderBucket)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 		}
 
- 		for idx := range user.VirtualFolders {
 
- 			err = addUserToFolderMapping(&user.VirtualFolders[idx].BaseVirtualFolder, user, folderBucket)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 		}
 
- 		user.ID = oldUser.ID
 
- 		user.LastQuotaUpdate = oldUser.LastQuotaUpdate
 
- 		user.UsedQuotaSize = oldUser.UsedQuotaSize
 
- 		user.UsedQuotaFiles = oldUser.UsedQuotaFiles
 
- 		user.LastLogin = oldUser.LastLogin
 
- 		user.CreatedAt = oldUser.CreatedAt
 
- 		user.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		buf, err := json.Marshal(user)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		return bucket.Put([]byte(user.Username), buf)
 
- 	})
 
- }
 
- func (p *BoltProvider) deleteUser(user *User) error {
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getUsersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		exists := bucket.Get([]byte(user.Username))
 
- 		if exists == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("user %#v does not exist", user.Username))
 
- 		}
 
- 		if len(user.VirtualFolders) > 0 {
 
- 			folderBucket, err := getFoldersBucket(tx)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 			for idx := range user.VirtualFolders {
 
- 				err = removeUserFromFolderMapping(&user.VirtualFolders[idx], user, folderBucket)
 
- 				if err != nil {
 
- 					return err
 
- 				}
 
- 			}
 
- 		}
 
- 		if err := deleteRelatedAPIKey(tx, user.Username, APIKeyScopeUser); err != nil {
 
- 			return err
 
- 		}
 
- 		return bucket.Delete([]byte(user.Username))
 
- 	})
 
- }
 
- func (p *BoltProvider) dumpUsers() ([]User, error) {
 
- 	users := make([]User, 0, 100)
 
- 	err := p.dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket, err := getUsersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		folderBucket, err := getFoldersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		cursor := bucket.Cursor()
 
- 		for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
 
- 			user, err := joinUserAndFolders(v, folderBucket)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 			err = addCredentialsToUser(&user)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 			users = append(users, user)
 
- 		}
 
- 		return err
 
- 	})
 
- 	return users, err
 
- }
 
- // bolt provider cannot be shared, so we always return no recently updated users
 
- func (p *BoltProvider) getRecentlyUpdatedUsers(after int64) ([]User, error) {
 
- 	return nil, nil
 
- }
 
- func (p *BoltProvider) getUsers(limit int, offset int, order string) ([]User, error) {
 
- 	users := make([]User, 0, limit)
 
- 	var err error
 
- 	if limit <= 0 {
 
- 		return users, err
 
- 	}
 
- 	err = p.dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket, err := getUsersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		folderBucket, err := getFoldersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		cursor := bucket.Cursor()
 
- 		itNum := 0
 
- 		if order == OrderASC {
 
- 			for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
 
- 				itNum++
 
- 				if itNum <= offset {
 
- 					continue
 
- 				}
 
- 				user, err := joinUserAndFolders(v, folderBucket)
 
- 				if err == nil {
 
- 					user.PrepareForRendering()
 
- 					users = append(users, user)
 
- 				}
 
- 				if len(users) >= limit {
 
- 					break
 
- 				}
 
- 			}
 
- 		} else {
 
- 			for k, v := cursor.Last(); k != nil; k, v = cursor.Prev() {
 
- 				itNum++
 
- 				if itNum <= offset {
 
- 					continue
 
- 				}
 
- 				user, err := joinUserAndFolders(v, folderBucket)
 
- 				if err == nil {
 
- 					user.PrepareForRendering()
 
- 					users = append(users, user)
 
- 				}
 
- 				if len(users) >= limit {
 
- 					break
 
- 				}
 
- 			}
 
- 		}
 
- 		return err
 
- 	})
 
- 	return users, err
 
- }
 
- func (p *BoltProvider) dumpFolders() ([]vfs.BaseVirtualFolder, error) {
 
- 	folders := make([]vfs.BaseVirtualFolder, 0, 50)
 
- 	err := p.dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket, err := getFoldersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		cursor := bucket.Cursor()
 
- 		for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
 
- 			var folder vfs.BaseVirtualFolder
 
- 			err = json.Unmarshal(v, &folder)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 			folders = append(folders, folder)
 
- 		}
 
- 		return err
 
- 	})
 
- 	return folders, err
 
- }
 
- func (p *BoltProvider) getFolders(limit, offset int, order string) ([]vfs.BaseVirtualFolder, error) {
 
- 	folders := make([]vfs.BaseVirtualFolder, 0, limit)
 
- 	var err error
 
- 	if limit <= 0 {
 
- 		return folders, err
 
- 	}
 
- 	err = p.dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket, err := getFoldersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		cursor := bucket.Cursor()
 
- 		itNum := 0
 
- 		if order == OrderASC {
 
- 			for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
 
- 				itNum++
 
- 				if itNum <= offset {
 
- 					continue
 
- 				}
 
- 				var folder vfs.BaseVirtualFolder
 
- 				err = json.Unmarshal(v, &folder)
 
- 				if err != nil {
 
- 					return err
 
- 				}
 
- 				folder.PrepareForRendering()
 
- 				folders = append(folders, folder)
 
- 				if len(folders) >= limit {
 
- 					break
 
- 				}
 
- 			}
 
- 		} else {
 
- 			for k, v := cursor.Last(); k != nil; k, v = cursor.Prev() {
 
- 				itNum++
 
- 				if itNum <= offset {
 
- 					continue
 
- 				}
 
- 				var folder vfs.BaseVirtualFolder
 
- 				err = json.Unmarshal(v, &folder)
 
- 				if err != nil {
 
- 					return err
 
- 				}
 
- 				folder.PrepareForRendering()
 
- 				folders = append(folders, folder)
 
- 				if len(folders) >= limit {
 
- 					break
 
- 				}
 
- 			}
 
- 		}
 
- 		return err
 
- 	})
 
- 	return folders, err
 
- }
 
- func (p *BoltProvider) getFolderByName(name string) (vfs.BaseVirtualFolder, error) {
 
- 	var folder vfs.BaseVirtualFolder
 
- 	err := p.dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket, err := getFoldersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		folder, err = folderExistsInternal(name, bucket)
 
- 		return err
 
- 	})
 
- 	return folder, err
 
- }
 
- func (p *BoltProvider) addFolder(folder *vfs.BaseVirtualFolder) error {
 
- 	err := ValidateFolder(folder)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getFoldersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		if f := bucket.Get([]byte(folder.Name)); f != nil {
 
- 			return fmt.Errorf("folder %v already exists", folder.Name)
 
- 		}
 
- 		folder.Users = nil
 
- 		return addFolderInternal(*folder, bucket)
 
- 	})
 
- }
 
- func (p *BoltProvider) updateFolder(folder *vfs.BaseVirtualFolder) error {
 
- 	err := ValidateFolder(folder)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getFoldersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		var f []byte
 
- 		if f = bucket.Get([]byte(folder.Name)); f == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("folder %v does not exist", folder.Name))
 
- 		}
 
- 		var oldFolder vfs.BaseVirtualFolder
 
- 		err = json.Unmarshal(f, &oldFolder)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		folder.ID = oldFolder.ID
 
- 		folder.LastQuotaUpdate = oldFolder.LastQuotaUpdate
 
- 		folder.UsedQuotaFiles = oldFolder.UsedQuotaFiles
 
- 		folder.UsedQuotaSize = oldFolder.UsedQuotaSize
 
- 		folder.Users = oldFolder.Users
 
- 		buf, err := json.Marshal(folder)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		return bucket.Put([]byte(folder.Name), buf)
 
- 	})
 
- }
 
- func (p *BoltProvider) deleteFolder(folder *vfs.BaseVirtualFolder) error {
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getFoldersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		usersBucket, err := getUsersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		var f []byte
 
- 		if f = bucket.Get([]byte(folder.Name)); f == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("folder %v does not exist", folder.Name))
 
- 		}
 
- 		var folder vfs.BaseVirtualFolder
 
- 		err = json.Unmarshal(f, &folder)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		for _, username := range folder.Users {
 
- 			var u []byte
 
- 			if u = usersBucket.Get([]byte(username)); u == nil {
 
- 				continue
 
- 			}
 
- 			var user User
 
- 			err = json.Unmarshal(u, &user)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 			var folders []vfs.VirtualFolder
 
- 			for _, userFolder := range user.VirtualFolders {
 
- 				if folder.Name != userFolder.Name {
 
- 					folders = append(folders, userFolder)
 
- 				}
 
- 			}
 
- 			user.VirtualFolders = folders
 
- 			buf, err := json.Marshal(user)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 			err = usersBucket.Put([]byte(user.Username), buf)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 		}
 
- 		return bucket.Delete([]byte(folder.Name))
 
- 	})
 
- }
 
- func (p *BoltProvider) updateFolderQuota(name string, filesAdd int, sizeAdd int64, reset bool) error {
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getFoldersBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		var f []byte
 
- 		if f = bucket.Get([]byte(name)); f == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("folder %#v does not exist, unable to update quota", name))
 
- 		}
 
- 		var folder vfs.BaseVirtualFolder
 
- 		err = json.Unmarshal(f, &folder)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		if reset {
 
- 			folder.UsedQuotaSize = sizeAdd
 
- 			folder.UsedQuotaFiles = filesAdd
 
- 		} else {
 
- 			folder.UsedQuotaSize += sizeAdd
 
- 			folder.UsedQuotaFiles += filesAdd
 
- 		}
 
- 		folder.LastQuotaUpdate = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		buf, err := json.Marshal(folder)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		return bucket.Put([]byte(folder.Name), buf)
 
- 	})
 
- }
 
- func (p *BoltProvider) getUsedFolderQuota(name string) (int, int64, error) {
 
- 	folder, err := p.getFolderByName(name)
 
- 	if err != nil {
 
- 		providerLog(logger.LevelWarn, "unable to get quota for folder %#v error: %v", name, err)
 
- 		return 0, 0, err
 
- 	}
 
- 	return folder.UsedQuotaFiles, folder.UsedQuotaSize, err
 
- }
 
- func (p *BoltProvider) apiKeyExists(keyID string) (APIKey, error) {
 
- 	var apiKey APIKey
 
- 	err := p.dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAPIKeysBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		k := bucket.Get([]byte(keyID))
 
- 		if k == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("API key %v does not exist", keyID))
 
- 		}
 
- 		return json.Unmarshal(k, &apiKey)
 
- 	})
 
- 	return apiKey, err
 
- }
 
- func (p *BoltProvider) addAPIKey(apiKey *APIKey) error {
 
- 	err := apiKey.validate()
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAPIKeysBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		if a := bucket.Get([]byte(apiKey.KeyID)); a != nil {
 
- 			return fmt.Errorf("API key %v already exists", apiKey.KeyID)
 
- 		}
 
- 		id, err := bucket.NextSequence()
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		apiKey.ID = int64(id)
 
- 		apiKey.CreatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		apiKey.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		apiKey.LastUseAt = 0
 
- 		buf, err := json.Marshal(apiKey)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		return bucket.Put([]byte(apiKey.KeyID), buf)
 
- 	})
 
- }
 
- func (p *BoltProvider) updateAPIKey(apiKey *APIKey) error {
 
- 	err := apiKey.validate()
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAPIKeysBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		var a []byte
 
- 		if a = bucket.Get([]byte(apiKey.KeyID)); a == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("API key %v does not exist", apiKey.KeyID))
 
- 		}
 
- 		var oldAPIKey APIKey
 
- 		err = json.Unmarshal(a, &oldAPIKey)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		apiKey.ID = oldAPIKey.ID
 
- 		apiKey.KeyID = oldAPIKey.KeyID
 
- 		apiKey.Key = oldAPIKey.Key
 
- 		apiKey.CreatedAt = oldAPIKey.CreatedAt
 
- 		apiKey.LastUseAt = oldAPIKey.LastUseAt
 
- 		apiKey.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
 
- 		buf, err := json.Marshal(apiKey)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		return bucket.Put([]byte(apiKey.KeyID), buf)
 
- 	})
 
- }
 
- func (p *BoltProvider) deleteAPIKeys(apiKey *APIKey) error {
 
- 	return p.dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAPIKeysBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		if bucket.Get([]byte(apiKey.KeyID)) == nil {
 
- 			return util.NewRecordNotFoundError(fmt.Sprintf("API key %v does not exist", apiKey.KeyID))
 
- 		}
 
- 		return bucket.Delete([]byte(apiKey.KeyID))
 
- 	})
 
- }
 
- func (p *BoltProvider) getAPIKeys(limit int, offset int, order string) ([]APIKey, error) {
 
- 	apiKeys := make([]APIKey, 0, limit)
 
- 	err := p.dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAPIKeysBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		cursor := bucket.Cursor()
 
- 		itNum := 0
 
- 		if order == OrderASC {
 
- 			for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
 
- 				itNum++
 
- 				if itNum <= offset {
 
- 					continue
 
- 				}
 
- 				var apiKey APIKey
 
- 				err = json.Unmarshal(v, &apiKey)
 
- 				if err != nil {
 
- 					return err
 
- 				}
 
- 				apiKey.HideConfidentialData()
 
- 				apiKeys = append(apiKeys, apiKey)
 
- 				if len(apiKeys) >= limit {
 
- 					break
 
- 				}
 
- 			}
 
- 			return nil
 
- 		}
 
- 		for k, v := cursor.Last(); k != nil; k, v = cursor.Prev() {
 
- 			itNum++
 
- 			if itNum <= offset {
 
- 				continue
 
- 			}
 
- 			var apiKey APIKey
 
- 			err = json.Unmarshal(v, &apiKey)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 			apiKey.HideConfidentialData()
 
- 			apiKeys = append(apiKeys, apiKey)
 
- 			if len(apiKeys) >= limit {
 
- 				break
 
- 			}
 
- 		}
 
- 		return nil
 
- 	})
 
- 	return apiKeys, err
 
- }
 
- func (p *BoltProvider) dumpAPIKeys() ([]APIKey, error) {
 
- 	apiKeys := make([]APIKey, 0, 30)
 
- 	err := p.dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket, err := getAPIKeysBucket(tx)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		cursor := bucket.Cursor()
 
- 		for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
 
- 			var apiKey APIKey
 
- 			err = json.Unmarshal(v, &apiKey)
 
- 			if err != nil {
 
- 				return err
 
- 			}
 
- 			apiKeys = append(apiKeys, apiKey)
 
- 		}
 
- 		return err
 
- 	})
 
- 	return apiKeys, err
 
- }
 
- func (p *BoltProvider) close() error {
 
- 	return p.dbHandle.Close()
 
- }
 
- func (p *BoltProvider) reloadConfig() error {
 
- 	return nil
 
- }
 
- // initializeDatabase does nothing, no initilization is needed for bolt provider
 
- func (p *BoltProvider) initializeDatabase() error {
 
- 	return ErrNoInitRequired
 
- }
 
- func (p *BoltProvider) migrateDatabase() error {
 
- 	dbVersion, err := getBoltDatabaseVersion(p.dbHandle)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	switch version := dbVersion.Version; {
 
- 	case version == boltDatabaseVersion:
 
- 		providerLog(logger.LevelDebug, "bolt database is up to date, current version: %v", version)
 
- 		return ErrNoInitRequired
 
- 	case version < 10:
 
- 		err = fmt.Errorf("database version %v is too old, please see the upgrading docs", version)
 
- 		providerLog(logger.LevelError, "%v", err)
 
- 		logger.ErrorToConsole("%v", err)
 
- 		return err
 
- 	case version == 10:
 
- 		return updateBoltDatabaseVersion(p.dbHandle, 12)
 
- 	case version == 11:
 
- 		return updateBoltDatabaseVersion(p.dbHandle, 12)
 
- 	default:
 
- 		if version > boltDatabaseVersion {
 
- 			providerLog(logger.LevelWarn, "database version %v is newer than the supported one: %v", version,
 
- 				boltDatabaseVersion)
 
- 			logger.WarnToConsole("database version %v is newer than the supported one: %v", version,
 
- 				boltDatabaseVersion)
 
- 			return nil
 
- 		}
 
- 		return fmt.Errorf("database version not handled: %v", version)
 
- 	}
 
- }
 
- func (p *BoltProvider) revertDatabase(targetVersion int) error {
 
- 	dbVersion, err := getBoltDatabaseVersion(p.dbHandle)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	if dbVersion.Version == targetVersion {
 
- 		return errors.New("current version match target version, nothing to do")
 
- 	}
 
- 	switch dbVersion.Version {
 
- 	case 12:
 
- 		return updateBoltDatabaseVersion(p.dbHandle, 10)
 
- 	case 11:
 
- 		return updateBoltDatabaseVersion(p.dbHandle, 10)
 
- 	default:
 
- 		return fmt.Errorf("database version not handled: %v", dbVersion.Version)
 
- 	}
 
- }
 
- func joinUserAndFolders(u []byte, foldersBucket *bolt.Bucket) (User, error) {
 
- 	var user User
 
- 	err := json.Unmarshal(u, &user)
 
- 	if err != nil {
 
- 		return user, err
 
- 	}
 
- 	if len(user.VirtualFolders) > 0 {
 
- 		var folders []vfs.VirtualFolder
 
- 		for idx := range user.VirtualFolders {
 
- 			folder := &user.VirtualFolders[idx]
 
- 			baseFolder, err := folderExistsInternal(folder.Name, foldersBucket)
 
- 			if err != nil {
 
- 				continue
 
- 			}
 
- 			folder.BaseVirtualFolder = baseFolder
 
- 			folders = append(folders, *folder)
 
- 		}
 
- 		user.VirtualFolders = folders
 
- 	}
 
- 	user.SetEmptySecretsIfNil()
 
- 	return user, err
 
- }
 
- func folderExistsInternal(name string, bucket *bolt.Bucket) (vfs.BaseVirtualFolder, error) {
 
- 	var folder vfs.BaseVirtualFolder
 
- 	f := bucket.Get([]byte(name))
 
- 	if f == nil {
 
- 		err := util.NewRecordNotFoundError(fmt.Sprintf("folder %v does not exist", name))
 
- 		return folder, err
 
- 	}
 
- 	err := json.Unmarshal(f, &folder)
 
- 	return folder, err
 
- }
 
- func addFolderInternal(folder vfs.BaseVirtualFolder, bucket *bolt.Bucket) error {
 
- 	id, err := bucket.NextSequence()
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	folder.ID = int64(id)
 
- 	buf, err := json.Marshal(folder)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	return bucket.Put([]byte(folder.Name), buf)
 
- }
 
- func addUserToFolderMapping(baseFolder *vfs.BaseVirtualFolder, user *User, bucket *bolt.Bucket) error {
 
- 	f := bucket.Get([]byte(baseFolder.Name))
 
- 	if f == nil {
 
- 		// folder does not exists, try to create
 
- 		baseFolder.LastQuotaUpdate = 0
 
- 		baseFolder.UsedQuotaFiles = 0
 
- 		baseFolder.UsedQuotaSize = 0
 
- 		baseFolder.Users = []string{user.Username}
 
- 		return addFolderInternal(*baseFolder, bucket)
 
- 	}
 
- 	var oldFolder vfs.BaseVirtualFolder
 
- 	err := json.Unmarshal(f, &oldFolder)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	baseFolder.ID = oldFolder.ID
 
- 	baseFolder.LastQuotaUpdate = oldFolder.LastQuotaUpdate
 
- 	baseFolder.UsedQuotaFiles = oldFolder.UsedQuotaFiles
 
- 	baseFolder.UsedQuotaSize = oldFolder.UsedQuotaSize
 
- 	baseFolder.Users = oldFolder.Users
 
- 	if !util.IsStringInSlice(user.Username, baseFolder.Users) {
 
- 		baseFolder.Users = append(baseFolder.Users, user.Username)
 
- 	}
 
- 	buf, err := json.Marshal(baseFolder)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	return bucket.Put([]byte(baseFolder.Name), buf)
 
- }
 
- func removeUserFromFolderMapping(folder *vfs.VirtualFolder, user *User, bucket *bolt.Bucket) error {
 
- 	var f []byte
 
- 	if f = bucket.Get([]byte(folder.Name)); f == nil {
 
- 		// the folder does not exists so there is no associated user
 
- 		return nil
 
- 	}
 
- 	var baseFolder vfs.BaseVirtualFolder
 
- 	err := json.Unmarshal(f, &baseFolder)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	if util.IsStringInSlice(user.Username, baseFolder.Users) {
 
- 		var newUserMapping []string
 
- 		for _, u := range baseFolder.Users {
 
- 			if u != user.Username {
 
- 				newUserMapping = append(newUserMapping, u)
 
- 			}
 
- 		}
 
- 		baseFolder.Users = newUserMapping
 
- 		buf, err := json.Marshal(baseFolder)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		return bucket.Put([]byte(folder.Name), buf)
 
- 	}
 
- 	return err
 
- }
 
- func deleteRelatedAPIKey(tx *bolt.Tx, username string, scope APIKeyScope) error {
 
- 	bucket, err := getAPIKeysBucket(tx)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	var toRemove []string
 
- 	cursor := bucket.Cursor()
 
- 	for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
 
- 		var apiKey APIKey
 
- 		err = json.Unmarshal(v, &apiKey)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		if scope == APIKeyScopeUser {
 
- 			if apiKey.User == username {
 
- 				toRemove = append(toRemove, apiKey.KeyID)
 
- 			}
 
- 		} else {
 
- 			if apiKey.Admin == username {
 
- 				toRemove = append(toRemove, apiKey.KeyID)
 
- 			}
 
- 		}
 
- 	}
 
- 	for _, k := range toRemove {
 
- 		if err := bucket.Delete([]byte(k)); err != nil {
 
- 			return err
 
- 		}
 
- 	}
 
- 	return nil
 
- }
 
- func getAPIKeysBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
 
- 	var err error
 
- 	bucket := tx.Bucket(apiKeysBucket)
 
- 	if bucket == nil {
 
- 		err = errors.New("unable to find api keys bucket, bolt database structure not correcly defined")
 
- 	}
 
- 	return bucket, err
 
- }
 
- func getAdminsBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
 
- 	var err error
 
- 	bucket := tx.Bucket(adminsBucket)
 
- 	if bucket == nil {
 
- 		err = errors.New("unable to find admins bucket, bolt database structure not correcly defined")
 
- 	}
 
- 	return bucket, err
 
- }
 
- func getUsersBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
 
- 	var err error
 
- 	bucket := tx.Bucket(usersBucket)
 
- 	if bucket == nil {
 
- 		err = errors.New("unable to find users bucket, bolt database structure not correcly defined")
 
- 	}
 
- 	return bucket, err
 
- }
 
- func getFoldersBucket(tx *bolt.Tx) (*bolt.Bucket, error) {
 
- 	var err error
 
- 	bucket := tx.Bucket(foldersBucket)
 
- 	if bucket == nil {
 
- 		err = fmt.Errorf("unable to find folders buckets, bolt database structure not correcly defined")
 
- 	}
 
- 	return bucket, err
 
- }
 
- func getBoltDatabaseVersion(dbHandle *bolt.DB) (schemaVersion, error) {
 
- 	var dbVersion schemaVersion
 
- 	err := dbHandle.View(func(tx *bolt.Tx) error {
 
- 		bucket := tx.Bucket(dbVersionBucket)
 
- 		if bucket == nil {
 
- 			return fmt.Errorf("unable to find database version bucket")
 
- 		}
 
- 		v := bucket.Get(dbVersionKey)
 
- 		if v == nil {
 
- 			dbVersion = schemaVersion{
 
- 				Version: 10,
 
- 			}
 
- 			return nil
 
- 		}
 
- 		return json.Unmarshal(v, &dbVersion)
 
- 	})
 
- 	return dbVersion, err
 
- }
 
- func updateBoltDatabaseVersion(dbHandle *bolt.DB, version int) error {
 
- 	err := dbHandle.Update(func(tx *bolt.Tx) error {
 
- 		bucket := tx.Bucket(dbVersionBucket)
 
- 		if bucket == nil {
 
- 			return fmt.Errorf("unable to find database version bucket")
 
- 		}
 
- 		newDbVersion := schemaVersion{
 
- 			Version: version,
 
- 		}
 
- 		buf, err := json.Marshal(newDbVersion)
 
- 		if err != nil {
 
- 			return err
 
- 		}
 
- 		return bucket.Put(dbVersionKey, buf)
 
- 	})
 
- 	return err
 
- }
 
 
  |