1package dataprovider
2
3import (
4	"crypto/x509"
5	"errors"
6	"fmt"
7	"os"
8	"path/filepath"
9	"sort"
10	"sync"
11	"time"
12
13	"github.com/drakkan/sftpgo/v2/logger"
14	"github.com/drakkan/sftpgo/v2/util"
15	"github.com/drakkan/sftpgo/v2/vfs"
16)
17
18var (
19	errMemoryProviderClosed = errors.New("memory provider is closed")
20)
21
22type memoryProviderHandle struct {
23	// configuration file to use for loading users
24	configFile string
25	sync.Mutex
26	isClosed bool
27	// slice with ordered usernames
28	usernames []string
29	// map for users, username is the key
30	users map[string]User
31	// map for virtual folders, folder name is the key
32	vfolders map[string]vfs.BaseVirtualFolder
33	// slice with ordered folder names
34	vfoldersNames []string
35	// map for admins, username is the key
36	admins map[string]Admin
37	// slice with ordered admins
38	adminsUsernames []string
39	// map for API keys, keyID is the key
40	apiKeys map[string]APIKey
41	// slice with ordered API keys KeyID
42	apiKeysIDs []string
43	// map for shares, shareID is the key
44	shares map[string]Share
45	// slice with ordered shares shareID
46	sharesIDs []string
47}
48
49// MemoryProvider auth provider for a memory store
50type MemoryProvider struct {
51	dbHandle *memoryProviderHandle
52}
53
54func initializeMemoryProvider(basePath string) {
55	configFile := ""
56	if util.IsFileInputValid(config.Name) {
57		configFile = config.Name
58		if !filepath.IsAbs(configFile) {
59			configFile = filepath.Join(basePath, configFile)
60		}
61	}
62	provider = &MemoryProvider{
63		dbHandle: &memoryProviderHandle{
64			isClosed:        false,
65			usernames:       []string{},
66			users:           make(map[string]User),
67			vfolders:        make(map[string]vfs.BaseVirtualFolder),
68			vfoldersNames:   []string{},
69			admins:          make(map[string]Admin),
70			adminsUsernames: []string{},
71			apiKeys:         make(map[string]APIKey),
72			apiKeysIDs:      []string{},
73			shares:          make(map[string]Share),
74			sharesIDs:       []string{},
75			configFile:      configFile,
76		},
77	}
78	if err := provider.reloadConfig(); err != nil {
79		logger.Error(logSender, "", "unable to load initial data: %v", err)
80		logger.ErrorToConsole("unable to load initial data: %v", err)
81	}
82}
83
84func (p *MemoryProvider) checkAvailability() error {
85	p.dbHandle.Lock()
86	defer p.dbHandle.Unlock()
87	if p.dbHandle.isClosed {
88		return errMemoryProviderClosed
89	}
90	return nil
91}
92
93func (p *MemoryProvider) close() error {
94	p.dbHandle.Lock()
95	defer p.dbHandle.Unlock()
96	if p.dbHandle.isClosed {
97		return errMemoryProviderClosed
98	}
99	p.dbHandle.isClosed = true
100	return nil
101}
102
103func (p *MemoryProvider) validateUserAndTLSCert(username, protocol string, tlsCert *x509.Certificate) (User, error) {
104	var user User
105	if tlsCert == nil {
106		return user, errors.New("TLS certificate cannot be null or empty")
107	}
108	user, err := p.userExists(username)
109	if err != nil {
110		providerLog(logger.LevelWarn, "error authenticating user %#v: %v", username, err)
111		return user, err
112	}
113	return checkUserAndTLSCertificate(&user, protocol, tlsCert)
114}
115
116func (p *MemoryProvider) validateUserAndPass(username, password, ip, protocol string) (User, error) {
117	var user User
118	if password == "" {
119		return user, errors.New("credentials cannot be null or empty")
120	}
121	user, err := p.userExists(username)
122	if err != nil {
123		providerLog(logger.LevelWarn, "error authenticating user %#v: %v", username, err)
124		return user, err
125	}
126	return checkUserAndPass(&user, password, ip, protocol)
127}
128
129func (p *MemoryProvider) validateUserAndPubKey(username string, pubKey []byte) (User, string, error) {
130	var user User
131	if len(pubKey) == 0 {
132		return user, "", errors.New("credentials cannot be null or empty")
133	}
134	user, err := p.userExists(username)
135	if err != nil {
136		providerLog(logger.LevelWarn, "error authenticating user %#v: %v", username, err)
137		return user, "", err
138	}
139	return checkUserAndPubKey(&user, pubKey)
140}
141
142func (p *MemoryProvider) validateAdminAndPass(username, password, ip string) (Admin, error) {
143	admin, err := p.adminExists(username)
144	if err != nil {
145		providerLog(logger.LevelWarn, "error authenticating admin %#v: %v", username, err)
146		return admin, ErrInvalidCredentials
147	}
148	err = admin.checkUserAndPass(password, ip)
149	return admin, err
150}
151
152func (p *MemoryProvider) updateAPIKeyLastUse(keyID string) error {
153	p.dbHandle.Lock()
154	defer p.dbHandle.Unlock()
155	if p.dbHandle.isClosed {
156		return errMemoryProviderClosed
157	}
158	apiKey, err := p.apiKeyExistsInternal(keyID)
159	if err != nil {
160		return err
161	}
162	apiKey.LastUseAt = util.GetTimeAsMsSinceEpoch(time.Now())
163	p.dbHandle.apiKeys[apiKey.KeyID] = apiKey
164	return nil
165}
166
167func (p *MemoryProvider) setUpdatedAt(username string) {
168	p.dbHandle.Lock()
169	defer p.dbHandle.Unlock()
170	if p.dbHandle.isClosed {
171		return
172	}
173	user, err := p.userExistsInternal(username)
174	if err != nil {
175		return
176	}
177	user.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
178	p.dbHandle.users[user.Username] = user
179}
180
181func (p *MemoryProvider) updateLastLogin(username string) error {
182	p.dbHandle.Lock()
183	defer p.dbHandle.Unlock()
184	if p.dbHandle.isClosed {
185		return errMemoryProviderClosed
186	}
187	user, err := p.userExistsInternal(username)
188	if err != nil {
189		return err
190	}
191	user.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now())
192	p.dbHandle.users[user.Username] = user
193	return nil
194}
195
196func (p *MemoryProvider) updateAdminLastLogin(username string) error {
197	p.dbHandle.Lock()
198	defer p.dbHandle.Unlock()
199	if p.dbHandle.isClosed {
200		return errMemoryProviderClosed
201	}
202	admin, err := p.adminExistsInternal(username)
203	if err != nil {
204		return err
205	}
206	admin.LastLogin = util.GetTimeAsMsSinceEpoch(time.Now())
207	p.dbHandle.admins[admin.Username] = admin
208	return nil
209}
210
211func (p *MemoryProvider) updateQuota(username string, filesAdd int, sizeAdd int64, reset bool) error {
212	p.dbHandle.Lock()
213	defer p.dbHandle.Unlock()
214	if p.dbHandle.isClosed {
215		return errMemoryProviderClosed
216	}
217	user, err := p.userExistsInternal(username)
218	if err != nil {
219		providerLog(logger.LevelWarn, "unable to update quota for user %#v error: %v", username, err)
220		return err
221	}
222	if reset {
223		user.UsedQuotaSize = sizeAdd
224		user.UsedQuotaFiles = filesAdd
225	} else {
226		user.UsedQuotaSize += sizeAdd
227		user.UsedQuotaFiles += filesAdd
228	}
229	user.LastQuotaUpdate = util.GetTimeAsMsSinceEpoch(time.Now())
230	providerLog(logger.LevelDebug, "quota updated for user %#v, files increment: %v size increment: %v is reset? %v",
231		username, filesAdd, sizeAdd, reset)
232	p.dbHandle.users[user.Username] = user
233	return nil
234}
235
236func (p *MemoryProvider) getUsedQuota(username string) (int, int64, error) {
237	p.dbHandle.Lock()
238	defer p.dbHandle.Unlock()
239	if p.dbHandle.isClosed {
240		return 0, 0, errMemoryProviderClosed
241	}
242	user, err := p.userExistsInternal(username)
243	if err != nil {
244		providerLog(logger.LevelWarn, "unable to get quota for user %#v error: %v", username, err)
245		return 0, 0, err
246	}
247	return user.UsedQuotaFiles, user.UsedQuotaSize, err
248}
249
250func (p *MemoryProvider) addUser(user *User) error {
251	// we can query virtual folder while validating a user
252	// so we have to check without holding the lock
253	err := ValidateUser(user)
254	if err != nil {
255		return err
256	}
257
258	p.dbHandle.Lock()
259	defer p.dbHandle.Unlock()
260	if p.dbHandle.isClosed {
261		return errMemoryProviderClosed
262	}
263
264	_, err = p.userExistsInternal(user.Username)
265	if err == nil {
266		return fmt.Errorf("username %#v already exists", user.Username)
267	}
268	user.ID = p.getNextID()
269	user.LastQuotaUpdate = 0
270	user.UsedQuotaSize = 0
271	user.UsedQuotaFiles = 0
272	user.LastLogin = 0
273	user.CreatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
274	user.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
275	user.VirtualFolders = p.joinVirtualFoldersFields(user)
276	p.dbHandle.users[user.Username] = user.getACopy()
277	p.dbHandle.usernames = append(p.dbHandle.usernames, user.Username)
278	sort.Strings(p.dbHandle.usernames)
279	return nil
280}
281
282func (p *MemoryProvider) updateUser(user *User) error {
283	// we can query virtual folder while validating a user
284	// so we have to check without holding the lock
285	err := ValidateUser(user)
286	if err != nil {
287		return err
288	}
289
290	p.dbHandle.Lock()
291	defer p.dbHandle.Unlock()
292	if p.dbHandle.isClosed {
293		return errMemoryProviderClosed
294	}
295
296	u, err := p.userExistsInternal(user.Username)
297	if err != nil {
298		return err
299	}
300	for _, oldFolder := range u.VirtualFolders {
301		p.removeUserFromFolderMapping(oldFolder.Name, u.Username)
302	}
303	user.VirtualFolders = p.joinVirtualFoldersFields(user)
304	user.LastQuotaUpdate = u.LastQuotaUpdate
305	user.UsedQuotaSize = u.UsedQuotaSize
306	user.UsedQuotaFiles = u.UsedQuotaFiles
307	user.LastLogin = u.LastLogin
308	user.CreatedAt = u.CreatedAt
309	user.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
310	user.ID = u.ID
311	// pre-login and external auth hook will use the passed *user so save a copy
312	p.dbHandle.users[user.Username] = user.getACopy()
313	return nil
314}
315
316func (p *MemoryProvider) deleteUser(user *User) error {
317	p.dbHandle.Lock()
318	defer p.dbHandle.Unlock()
319	if p.dbHandle.isClosed {
320		return errMemoryProviderClosed
321	}
322	u, err := p.userExistsInternal(user.Username)
323	if err != nil {
324		return err
325	}
326	for _, oldFolder := range u.VirtualFolders {
327		p.removeUserFromFolderMapping(oldFolder.Name, u.Username)
328	}
329	delete(p.dbHandle.users, user.Username)
330	// this could be more efficient
331	p.dbHandle.usernames = make([]string, 0, len(p.dbHandle.users))
332	for username := range p.dbHandle.users {
333		p.dbHandle.usernames = append(p.dbHandle.usernames, username)
334	}
335	sort.Strings(p.dbHandle.usernames)
336	p.deleteAPIKeysWithUser(user.Username)
337	p.deleteSharesWithUser(user.Username)
338	return nil
339}
340
341func (p *MemoryProvider) dumpUsers() ([]User, error) {
342	p.dbHandle.Lock()
343	defer p.dbHandle.Unlock()
344	users := make([]User, 0, len(p.dbHandle.usernames))
345	var err error
346	if p.dbHandle.isClosed {
347		return users, errMemoryProviderClosed
348	}
349	for _, username := range p.dbHandle.usernames {
350		u := p.dbHandle.users[username]
351		user := u.getACopy()
352		err = addCredentialsToUser(&user)
353		if err != nil {
354			return users, err
355		}
356		users = append(users, user)
357	}
358	return users, err
359}
360
361func (p *MemoryProvider) dumpFolders() ([]vfs.BaseVirtualFolder, error) {
362	p.dbHandle.Lock()
363	defer p.dbHandle.Unlock()
364	folders := make([]vfs.BaseVirtualFolder, 0, len(p.dbHandle.vfoldersNames))
365	if p.dbHandle.isClosed {
366		return folders, errMemoryProviderClosed
367	}
368	for _, f := range p.dbHandle.vfolders {
369		folders = append(folders, f)
370	}
371	return folders, nil
372}
373
374// memory provider cannot be shared, so we always return no recently updated users
375func (p *MemoryProvider) getRecentlyUpdatedUsers(after int64) ([]User, error) {
376	return nil, nil
377}
378
379func (p *MemoryProvider) getUsers(limit int, offset int, order string) ([]User, error) {
380	users := make([]User, 0, limit)
381	var err error
382	p.dbHandle.Lock()
383	defer p.dbHandle.Unlock()
384	if p.dbHandle.isClosed {
385		return users, errMemoryProviderClosed
386	}
387	if limit <= 0 {
388		return users, err
389	}
390	itNum := 0
391	if order == OrderASC {
392		for _, username := range p.dbHandle.usernames {
393			itNum++
394			if itNum <= offset {
395				continue
396			}
397			u := p.dbHandle.users[username]
398			user := u.getACopy()
399			user.PrepareForRendering()
400			users = append(users, user)
401			if len(users) >= limit {
402				break
403			}
404		}
405	} else {
406		for i := len(p.dbHandle.usernames) - 1; i >= 0; i-- {
407			itNum++
408			if itNum <= offset {
409				continue
410			}
411			username := p.dbHandle.usernames[i]
412			u := p.dbHandle.users[username]
413			user := u.getACopy()
414			user.PrepareForRendering()
415			users = append(users, user)
416			if len(users) >= limit {
417				break
418			}
419		}
420	}
421	return users, err
422}
423
424func (p *MemoryProvider) userExists(username string) (User, error) {
425	p.dbHandle.Lock()
426	defer p.dbHandle.Unlock()
427	if p.dbHandle.isClosed {
428		return User{}, errMemoryProviderClosed
429	}
430	return p.userExistsInternal(username)
431}
432
433func (p *MemoryProvider) userExistsInternal(username string) (User, error) {
434	if val, ok := p.dbHandle.users[username]; ok {
435		return val.getACopy(), nil
436	}
437	return User{}, util.NewRecordNotFoundError(fmt.Sprintf("username %#v does not exist", username))
438}
439
440func (p *MemoryProvider) addAdmin(admin *Admin) error {
441	p.dbHandle.Lock()
442	defer p.dbHandle.Unlock()
443	if p.dbHandle.isClosed {
444		return errMemoryProviderClosed
445	}
446	err := admin.validate()
447	if err != nil {
448		return err
449	}
450	_, err = p.adminExistsInternal(admin.Username)
451	if err == nil {
452		return fmt.Errorf("admin %#v already exists", admin.Username)
453	}
454	admin.ID = p.getNextAdminID()
455	admin.CreatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
456	admin.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
457	admin.LastLogin = 0
458	p.dbHandle.admins[admin.Username] = admin.getACopy()
459	p.dbHandle.adminsUsernames = append(p.dbHandle.adminsUsernames, admin.Username)
460	sort.Strings(p.dbHandle.adminsUsernames)
461	return nil
462}
463
464func (p *MemoryProvider) updateAdmin(admin *Admin) error {
465	p.dbHandle.Lock()
466	defer p.dbHandle.Unlock()
467	if p.dbHandle.isClosed {
468		return errMemoryProviderClosed
469	}
470	err := admin.validate()
471	if err != nil {
472		return err
473	}
474	a, err := p.adminExistsInternal(admin.Username)
475	if err != nil {
476		return err
477	}
478	admin.ID = a.ID
479	admin.CreatedAt = a.CreatedAt
480	admin.LastLogin = a.LastLogin
481	admin.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
482	p.dbHandle.admins[admin.Username] = admin.getACopy()
483	return nil
484}
485
486func (p *MemoryProvider) deleteAdmin(admin *Admin) error {
487	p.dbHandle.Lock()
488	defer p.dbHandle.Unlock()
489	if p.dbHandle.isClosed {
490		return errMemoryProviderClosed
491	}
492	_, err := p.adminExistsInternal(admin.Username)
493	if err != nil {
494		return err
495	}
496
497	delete(p.dbHandle.admins, admin.Username)
498	// this could be more efficient
499	p.dbHandle.adminsUsernames = make([]string, 0, len(p.dbHandle.admins))
500	for username := range p.dbHandle.admins {
501		p.dbHandle.adminsUsernames = append(p.dbHandle.adminsUsernames, username)
502	}
503	sort.Strings(p.dbHandle.adminsUsernames)
504	p.deleteAPIKeysWithAdmin(admin.Username)
505	return nil
506}
507
508func (p *MemoryProvider) adminExists(username string) (Admin, error) {
509	p.dbHandle.Lock()
510	defer p.dbHandle.Unlock()
511	if p.dbHandle.isClosed {
512		return Admin{}, errMemoryProviderClosed
513	}
514	return p.adminExistsInternal(username)
515}
516
517func (p *MemoryProvider) adminExistsInternal(username string) (Admin, error) {
518	if val, ok := p.dbHandle.admins[username]; ok {
519		return val.getACopy(), nil
520	}
521	return Admin{}, util.NewRecordNotFoundError(fmt.Sprintf("admin %#v does not exist", username))
522}
523
524func (p *MemoryProvider) dumpAdmins() ([]Admin, error) {
525	p.dbHandle.Lock()
526	defer p.dbHandle.Unlock()
527
528	admins := make([]Admin, 0, len(p.dbHandle.admins))
529	if p.dbHandle.isClosed {
530		return admins, errMemoryProviderClosed
531	}
532	for _, admin := range p.dbHandle.admins {
533		admins = append(admins, admin)
534	}
535	return admins, nil
536}
537
538func (p *MemoryProvider) getAdmins(limit int, offset int, order string) ([]Admin, error) {
539	admins := make([]Admin, 0, limit)
540
541	p.dbHandle.Lock()
542	defer p.dbHandle.Unlock()
543
544	if p.dbHandle.isClosed {
545		return admins, errMemoryProviderClosed
546	}
547	if limit <= 0 {
548		return admins, nil
549	}
550	itNum := 0
551	if order == OrderASC {
552		for _, username := range p.dbHandle.adminsUsernames {
553			itNum++
554			if itNum <= offset {
555				continue
556			}
557			a := p.dbHandle.admins[username]
558			admin := a.getACopy()
559			admin.HideConfidentialData()
560			admins = append(admins, admin)
561			if len(admins) >= limit {
562				break
563			}
564		}
565	} else {
566		for i := len(p.dbHandle.adminsUsernames) - 1; i >= 0; i-- {
567			itNum++
568			if itNum <= offset {
569				continue
570			}
571			username := p.dbHandle.adminsUsernames[i]
572			a := p.dbHandle.admins[username]
573			admin := a.getACopy()
574			admin.HideConfidentialData()
575			admins = append(admins, admin)
576			if len(admins) >= limit {
577				break
578			}
579		}
580	}
581
582	return admins, nil
583}
584
585func (p *MemoryProvider) updateFolderQuota(name string, filesAdd int, sizeAdd int64, reset bool) error {
586	p.dbHandle.Lock()
587	defer p.dbHandle.Unlock()
588	if p.dbHandle.isClosed {
589		return errMemoryProviderClosed
590	}
591	folder, err := p.folderExistsInternal(name)
592	if err != nil {
593		providerLog(logger.LevelWarn, "unable to update quota for folder %#v error: %v", name, err)
594		return err
595	}
596	if reset {
597		folder.UsedQuotaSize = sizeAdd
598		folder.UsedQuotaFiles = filesAdd
599	} else {
600		folder.UsedQuotaSize += sizeAdd
601		folder.UsedQuotaFiles += filesAdd
602	}
603	folder.LastQuotaUpdate = util.GetTimeAsMsSinceEpoch(time.Now())
604	p.dbHandle.vfolders[name] = folder
605	return nil
606}
607
608func (p *MemoryProvider) getUsedFolderQuota(name string) (int, int64, error) {
609	p.dbHandle.Lock()
610	defer p.dbHandle.Unlock()
611	if p.dbHandle.isClosed {
612		return 0, 0, errMemoryProviderClosed
613	}
614	folder, err := p.folderExistsInternal(name)
615	if err != nil {
616		providerLog(logger.LevelWarn, "unable to get quota for folder %#v error: %v", name, err)
617		return 0, 0, err
618	}
619	return folder.UsedQuotaFiles, folder.UsedQuotaSize, err
620}
621
622func (p *MemoryProvider) joinVirtualFoldersFields(user *User) []vfs.VirtualFolder {
623	var folders []vfs.VirtualFolder
624	for idx := range user.VirtualFolders {
625		folder := &user.VirtualFolders[idx]
626		f, err := p.addOrUpdateFolderInternal(&folder.BaseVirtualFolder, user.Username, 0, 0, 0)
627		if err == nil {
628			folder.BaseVirtualFolder = f
629			folders = append(folders, *folder)
630		}
631	}
632	return folders
633}
634
635func (p *MemoryProvider) removeUserFromFolderMapping(folderName, username string) {
636	folder, err := p.folderExistsInternal(folderName)
637	if err == nil {
638		var usernames []string
639		for _, user := range folder.Users {
640			if user != username {
641				usernames = append(usernames, user)
642			}
643		}
644		folder.Users = usernames
645		p.dbHandle.vfolders[folder.Name] = folder
646	}
647}
648
649func (p *MemoryProvider) updateFoldersMappingInternal(folder vfs.BaseVirtualFolder) {
650	p.dbHandle.vfolders[folder.Name] = folder
651	if !util.IsStringInSlice(folder.Name, p.dbHandle.vfoldersNames) {
652		p.dbHandle.vfoldersNames = append(p.dbHandle.vfoldersNames, folder.Name)
653		sort.Strings(p.dbHandle.vfoldersNames)
654	}
655}
656
657func (p *MemoryProvider) addOrUpdateFolderInternal(baseFolder *vfs.BaseVirtualFolder, username string, usedQuotaSize int64,
658	usedQuotaFiles int, lastQuotaUpdate int64) (vfs.BaseVirtualFolder, error) {
659	folder, err := p.folderExistsInternal(baseFolder.Name)
660	if err == nil {
661		// exists
662		folder.MappedPath = baseFolder.MappedPath
663		folder.Description = baseFolder.Description
664		folder.FsConfig = baseFolder.FsConfig.GetACopy()
665		if !util.IsStringInSlice(username, folder.Users) {
666			folder.Users = append(folder.Users, username)
667		}
668		p.updateFoldersMappingInternal(folder)
669		return folder, nil
670	}
671	if _, ok := err.(*util.RecordNotFoundError); ok {
672		folder = baseFolder.GetACopy()
673		folder.ID = p.getNextFolderID()
674		folder.UsedQuotaSize = usedQuotaSize
675		folder.UsedQuotaFiles = usedQuotaFiles
676		folder.LastQuotaUpdate = lastQuotaUpdate
677		folder.Users = []string{username}
678		p.updateFoldersMappingInternal(folder)
679		return folder, nil
680	}
681	return folder, err
682}
683
684func (p *MemoryProvider) folderExistsInternal(name string) (vfs.BaseVirtualFolder, error) {
685	if val, ok := p.dbHandle.vfolders[name]; ok {
686		return val, nil
687	}
688	return vfs.BaseVirtualFolder{}, util.NewRecordNotFoundError(fmt.Sprintf("folder %#v does not exist", name))
689}
690
691func (p *MemoryProvider) getFolders(limit, offset int, order string) ([]vfs.BaseVirtualFolder, error) {
692	folders := make([]vfs.BaseVirtualFolder, 0, limit)
693	var err error
694	p.dbHandle.Lock()
695	defer p.dbHandle.Unlock()
696	if p.dbHandle.isClosed {
697		return folders, errMemoryProviderClosed
698	}
699	if limit <= 0 {
700		return folders, err
701	}
702	itNum := 0
703	if order == OrderASC {
704		for _, name := range p.dbHandle.vfoldersNames {
705			itNum++
706			if itNum <= offset {
707				continue
708			}
709			f := p.dbHandle.vfolders[name]
710			folder := f.GetACopy()
711			folder.PrepareForRendering()
712			folders = append(folders, folder)
713			if len(folders) >= limit {
714				break
715			}
716		}
717	} else {
718		for i := len(p.dbHandle.vfoldersNames) - 1; i >= 0; i-- {
719			itNum++
720			if itNum <= offset {
721				continue
722			}
723			name := p.dbHandle.vfoldersNames[i]
724			f := p.dbHandle.vfolders[name]
725			folder := f.GetACopy()
726			folder.PrepareForRendering()
727			folders = append(folders, folder)
728			if len(folders) >= limit {
729				break
730			}
731		}
732	}
733	return folders, err
734}
735
736func (p *MemoryProvider) getFolderByName(name string) (vfs.BaseVirtualFolder, error) {
737	p.dbHandle.Lock()
738	defer p.dbHandle.Unlock()
739	if p.dbHandle.isClosed {
740		return vfs.BaseVirtualFolder{}, errMemoryProviderClosed
741	}
742	folder, err := p.folderExistsInternal(name)
743	if err != nil {
744		return vfs.BaseVirtualFolder{}, err
745	}
746	return folder.GetACopy(), nil
747}
748
749func (p *MemoryProvider) addFolder(folder *vfs.BaseVirtualFolder) error {
750	err := ValidateFolder(folder)
751	if err != nil {
752		return err
753	}
754
755	p.dbHandle.Lock()
756	defer p.dbHandle.Unlock()
757	if p.dbHandle.isClosed {
758		return errMemoryProviderClosed
759	}
760
761	_, err = p.folderExistsInternal(folder.Name)
762	if err == nil {
763		return fmt.Errorf("folder %#v already exists", folder.Name)
764	}
765	folder.ID = p.getNextFolderID()
766	folder.Users = nil
767	p.dbHandle.vfolders[folder.Name] = folder.GetACopy()
768	p.dbHandle.vfoldersNames = append(p.dbHandle.vfoldersNames, folder.Name)
769	sort.Strings(p.dbHandle.vfoldersNames)
770	return nil
771}
772
773func (p *MemoryProvider) updateFolder(folder *vfs.BaseVirtualFolder) error {
774	err := ValidateFolder(folder)
775	if err != nil {
776		return err
777	}
778
779	p.dbHandle.Lock()
780	defer p.dbHandle.Unlock()
781	if p.dbHandle.isClosed {
782		return errMemoryProviderClosed
783	}
784	f, err := p.folderExistsInternal(folder.Name)
785	if err != nil {
786		return err
787	}
788	folder.ID = f.ID
789	folder.LastQuotaUpdate = f.LastQuotaUpdate
790	folder.UsedQuotaFiles = f.UsedQuotaFiles
791	folder.UsedQuotaSize = f.UsedQuotaSize
792	folder.Users = f.Users
793	p.dbHandle.vfolders[folder.Name] = folder.GetACopy()
794	// now update the related users
795	for _, username := range folder.Users {
796		user, err := p.userExistsInternal(username)
797		if err == nil {
798			var folders []vfs.VirtualFolder
799			for idx := range user.VirtualFolders {
800				userFolder := &user.VirtualFolders[idx]
801				if folder.Name == userFolder.Name {
802					userFolder.BaseVirtualFolder = folder.GetACopy()
803				}
804				folders = append(folders, *userFolder)
805			}
806			user.VirtualFolders = folders
807			p.dbHandle.users[user.Username] = user
808		}
809	}
810	return nil
811}
812
813func (p *MemoryProvider) deleteFolder(folder *vfs.BaseVirtualFolder) error {
814	p.dbHandle.Lock()
815	defer p.dbHandle.Unlock()
816	if p.dbHandle.isClosed {
817		return errMemoryProviderClosed
818	}
819
820	_, err := p.folderExistsInternal(folder.Name)
821	if err != nil {
822		return err
823	}
824	for _, username := range folder.Users {
825		user, err := p.userExistsInternal(username)
826		if err == nil {
827			var folders []vfs.VirtualFolder
828			for idx := range user.VirtualFolders {
829				userFolder := &user.VirtualFolders[idx]
830				if folder.Name != userFolder.Name {
831					folders = append(folders, *userFolder)
832				}
833			}
834			user.VirtualFolders = folders
835			p.dbHandle.users[user.Username] = user
836		}
837	}
838	delete(p.dbHandle.vfolders, folder.Name)
839	p.dbHandle.vfoldersNames = []string{}
840	for name := range p.dbHandle.vfolders {
841		p.dbHandle.vfoldersNames = append(p.dbHandle.vfoldersNames, name)
842	}
843	sort.Strings(p.dbHandle.vfoldersNames)
844	return nil
845}
846
847func (p *MemoryProvider) apiKeyExistsInternal(keyID string) (APIKey, error) {
848	if val, ok := p.dbHandle.apiKeys[keyID]; ok {
849		return val.getACopy(), nil
850	}
851	return APIKey{}, util.NewRecordNotFoundError(fmt.Sprintf("API key %#v does not exist", keyID))
852}
853
854func (p *MemoryProvider) apiKeyExists(keyID string) (APIKey, error) {
855	p.dbHandle.Lock()
856	defer p.dbHandle.Unlock()
857	if p.dbHandle.isClosed {
858		return APIKey{}, errMemoryProviderClosed
859	}
860	return p.apiKeyExistsInternal(keyID)
861}
862
863func (p *MemoryProvider) addAPIKey(apiKey *APIKey) error {
864	err := apiKey.validate()
865	if err != nil {
866		return err
867	}
868
869	p.dbHandle.Lock()
870	defer p.dbHandle.Unlock()
871	if p.dbHandle.isClosed {
872		return errMemoryProviderClosed
873	}
874
875	_, err = p.apiKeyExistsInternal(apiKey.KeyID)
876	if err == nil {
877		return fmt.Errorf("API key %#v already exists", apiKey.KeyID)
878	}
879	if apiKey.User != "" {
880		if _, err := p.userExistsInternal(apiKey.User); err != nil {
881			return util.NewValidationError(fmt.Sprintf("related user %#v does not exists", apiKey.User))
882		}
883	}
884	if apiKey.Admin != "" {
885		if _, err := p.adminExistsInternal(apiKey.Admin); err != nil {
886			return util.NewValidationError(fmt.Sprintf("related admin %#v does not exists", apiKey.User))
887		}
888	}
889	apiKey.CreatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
890	apiKey.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
891	apiKey.LastUseAt = 0
892	p.dbHandle.apiKeys[apiKey.KeyID] = apiKey.getACopy()
893	p.dbHandle.apiKeysIDs = append(p.dbHandle.apiKeysIDs, apiKey.KeyID)
894	sort.Strings(p.dbHandle.apiKeysIDs)
895	return nil
896}
897
898func (p *MemoryProvider) updateAPIKey(apiKey *APIKey) error {
899	err := apiKey.validate()
900	if err != nil {
901		return err
902	}
903
904	p.dbHandle.Lock()
905	defer p.dbHandle.Unlock()
906	if p.dbHandle.isClosed {
907		return errMemoryProviderClosed
908	}
909	k, err := p.apiKeyExistsInternal(apiKey.KeyID)
910	if err != nil {
911		return err
912	}
913	if apiKey.User != "" {
914		if _, err := p.userExistsInternal(apiKey.User); err != nil {
915			return util.NewValidationError(fmt.Sprintf("related user %#v does not exists", apiKey.User))
916		}
917	}
918	if apiKey.Admin != "" {
919		if _, err := p.adminExistsInternal(apiKey.Admin); err != nil {
920			return util.NewValidationError(fmt.Sprintf("related admin %#v does not exists", apiKey.User))
921		}
922	}
923	apiKey.ID = k.ID
924	apiKey.KeyID = k.KeyID
925	apiKey.Key = k.Key
926	apiKey.CreatedAt = k.CreatedAt
927	apiKey.LastUseAt = k.LastUseAt
928	apiKey.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
929	p.dbHandle.apiKeys[apiKey.KeyID] = apiKey.getACopy()
930	return nil
931}
932
933func (p *MemoryProvider) deleteAPIKey(apiKey *APIKey) error {
934	p.dbHandle.Lock()
935	defer p.dbHandle.Unlock()
936	if p.dbHandle.isClosed {
937		return errMemoryProviderClosed
938	}
939	_, err := p.apiKeyExistsInternal(apiKey.KeyID)
940	if err != nil {
941		return err
942	}
943
944	delete(p.dbHandle.apiKeys, apiKey.KeyID)
945	p.updateAPIKeysOrdering()
946
947	return nil
948}
949
950func (p *MemoryProvider) getAPIKeys(limit int, offset int, order string) ([]APIKey, error) {
951	apiKeys := make([]APIKey, 0, limit)
952
953	p.dbHandle.Lock()
954	defer p.dbHandle.Unlock()
955
956	if p.dbHandle.isClosed {
957		return apiKeys, errMemoryProviderClosed
958	}
959	if limit <= 0 {
960		return apiKeys, nil
961	}
962	itNum := 0
963	if order == OrderDESC {
964		for i := len(p.dbHandle.apiKeysIDs) - 1; i >= 0; i-- {
965			itNum++
966			if itNum <= offset {
967				continue
968			}
969			keyID := p.dbHandle.apiKeysIDs[i]
970			k := p.dbHandle.apiKeys[keyID]
971			apiKey := k.getACopy()
972			apiKey.HideConfidentialData()
973			apiKeys = append(apiKeys, apiKey)
974			if len(apiKeys) >= limit {
975				break
976			}
977		}
978	} else {
979		for _, keyID := range p.dbHandle.apiKeysIDs {
980			itNum++
981			if itNum <= offset {
982				continue
983			}
984			k := p.dbHandle.apiKeys[keyID]
985			apiKey := k.getACopy()
986			apiKey.HideConfidentialData()
987			apiKeys = append(apiKeys, apiKey)
988			if len(apiKeys) >= limit {
989				break
990			}
991		}
992	}
993
994	return apiKeys, nil
995}
996
997func (p *MemoryProvider) dumpAPIKeys() ([]APIKey, error) {
998	p.dbHandle.Lock()
999	defer p.dbHandle.Unlock()
1000
1001	apiKeys := make([]APIKey, 0, len(p.dbHandle.apiKeys))
1002	if p.dbHandle.isClosed {
1003		return apiKeys, errMemoryProviderClosed
1004	}
1005	for _, k := range p.dbHandle.apiKeys {
1006		apiKeys = append(apiKeys, k)
1007	}
1008	return apiKeys, nil
1009}
1010
1011func (p *MemoryProvider) deleteAPIKeysWithUser(username string) {
1012	found := false
1013	for k, v := range p.dbHandle.apiKeys {
1014		if v.User == username {
1015			delete(p.dbHandle.apiKeys, k)
1016			found = true
1017		}
1018	}
1019	if found {
1020		p.updateAPIKeysOrdering()
1021	}
1022}
1023
1024func (p *MemoryProvider) deleteAPIKeysWithAdmin(username string) {
1025	found := false
1026	for k, v := range p.dbHandle.apiKeys {
1027		if v.Admin == username {
1028			delete(p.dbHandle.apiKeys, k)
1029			found = true
1030		}
1031	}
1032	if found {
1033		p.updateAPIKeysOrdering()
1034	}
1035}
1036
1037func (p *MemoryProvider) deleteSharesWithUser(username string) {
1038	found := false
1039	for k, v := range p.dbHandle.shares {
1040		if v.Username == username {
1041			delete(p.dbHandle.shares, k)
1042			found = true
1043		}
1044	}
1045	if found {
1046		p.updateSharesOrdering()
1047	}
1048}
1049
1050func (p *MemoryProvider) updateAPIKeysOrdering() {
1051	// this could be more efficient
1052	p.dbHandle.apiKeysIDs = make([]string, 0, len(p.dbHandle.apiKeys))
1053	for keyID := range p.dbHandle.apiKeys {
1054		p.dbHandle.apiKeysIDs = append(p.dbHandle.apiKeysIDs, keyID)
1055	}
1056	sort.Strings(p.dbHandle.apiKeysIDs)
1057}
1058
1059func (p *MemoryProvider) updateSharesOrdering() {
1060	// this could be more efficient
1061	p.dbHandle.sharesIDs = make([]string, 0, len(p.dbHandle.shares))
1062	for shareID := range p.dbHandle.shares {
1063		p.dbHandle.sharesIDs = append(p.dbHandle.sharesIDs, shareID)
1064	}
1065	sort.Strings(p.dbHandle.sharesIDs)
1066}
1067
1068func (p *MemoryProvider) shareExistsInternal(shareID, username string) (Share, error) {
1069	if val, ok := p.dbHandle.shares[shareID]; ok {
1070		if username != "" && val.Username != username {
1071			return Share{}, util.NewRecordNotFoundError(fmt.Sprintf("Share %#v does not exist", shareID))
1072		}
1073		return val.getACopy(), nil
1074	}
1075	return Share{}, util.NewRecordNotFoundError(fmt.Sprintf("Share %#v does not exist", shareID))
1076}
1077
1078func (p *MemoryProvider) shareExists(shareID, username string) (Share, error) {
1079	p.dbHandle.Lock()
1080	defer p.dbHandle.Unlock()
1081	if p.dbHandle.isClosed {
1082		return Share{}, errMemoryProviderClosed
1083	}
1084	return p.shareExistsInternal(shareID, username)
1085}
1086
1087func (p *MemoryProvider) addShare(share *Share) error {
1088	err := share.validate()
1089	if err != nil {
1090		return err
1091	}
1092
1093	p.dbHandle.Lock()
1094	defer p.dbHandle.Unlock()
1095	if p.dbHandle.isClosed {
1096		return errMemoryProviderClosed
1097	}
1098
1099	_, err = p.shareExistsInternal(share.ShareID, share.Username)
1100	if err == nil {
1101		return fmt.Errorf("share %#v already exists", share.ShareID)
1102	}
1103	if _, err := p.userExistsInternal(share.Username); err != nil {
1104		return util.NewValidationError(fmt.Sprintf("related user %#v does not exists", share.Username))
1105	}
1106	if !share.IsRestore {
1107		share.CreatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
1108		share.UpdatedAt = share.CreatedAt
1109		share.LastUseAt = 0
1110		share.UsedTokens = 0
1111	}
1112	if share.CreatedAt == 0 {
1113		share.CreatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
1114	}
1115	if share.UpdatedAt == 0 {
1116		share.UpdatedAt = share.CreatedAt
1117	}
1118	p.dbHandle.shares[share.ShareID] = share.getACopy()
1119	p.dbHandle.sharesIDs = append(p.dbHandle.sharesIDs, share.ShareID)
1120	sort.Strings(p.dbHandle.sharesIDs)
1121	return nil
1122}
1123
1124func (p *MemoryProvider) updateShare(share *Share) error {
1125	err := share.validate()
1126	if err != nil {
1127		return err
1128	}
1129
1130	p.dbHandle.Lock()
1131	defer p.dbHandle.Unlock()
1132	if p.dbHandle.isClosed {
1133		return errMemoryProviderClosed
1134	}
1135	s, err := p.shareExistsInternal(share.ShareID, share.Username)
1136	if err != nil {
1137		return err
1138	}
1139	if _, err := p.userExistsInternal(share.Username); err != nil {
1140		return util.NewValidationError(fmt.Sprintf("related user %#v does not exists", share.Username))
1141	}
1142	share.ID = s.ID
1143	share.ShareID = s.ShareID
1144	if !share.IsRestore {
1145		share.UsedTokens = s.UsedTokens
1146		share.CreatedAt = s.CreatedAt
1147		share.LastUseAt = s.LastUseAt
1148		share.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
1149	}
1150	if share.CreatedAt == 0 {
1151		share.CreatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
1152	}
1153	if share.UpdatedAt == 0 {
1154		share.UpdatedAt = share.CreatedAt
1155	}
1156	p.dbHandle.shares[share.ShareID] = share.getACopy()
1157	return nil
1158}
1159
1160func (p *MemoryProvider) deleteShare(share *Share) error {
1161	p.dbHandle.Lock()
1162	defer p.dbHandle.Unlock()
1163	if p.dbHandle.isClosed {
1164		return errMemoryProviderClosed
1165	}
1166	_, err := p.shareExistsInternal(share.ShareID, share.Username)
1167	if err != nil {
1168		return err
1169	}
1170
1171	delete(p.dbHandle.shares, share.ShareID)
1172	p.updateSharesOrdering()
1173
1174	return nil
1175}
1176
1177func (p *MemoryProvider) getShares(limit int, offset int, order, username string) ([]Share, error) {
1178	p.dbHandle.Lock()
1179	defer p.dbHandle.Unlock()
1180
1181	if p.dbHandle.isClosed {
1182		return []Share{}, errMemoryProviderClosed
1183	}
1184	if limit <= 0 {
1185		return []Share{}, nil
1186	}
1187	shares := make([]Share, 0, limit)
1188	itNum := 0
1189	if order == OrderDESC {
1190		for i := len(p.dbHandle.sharesIDs) - 1; i >= 0; i-- {
1191			shareID := p.dbHandle.sharesIDs[i]
1192			s := p.dbHandle.shares[shareID]
1193			if s.Username != username {
1194				continue
1195			}
1196			itNum++
1197			if itNum <= offset {
1198				continue
1199			}
1200			share := s.getACopy()
1201			share.HideConfidentialData()
1202			shares = append(shares, share)
1203			if len(shares) >= limit {
1204				break
1205			}
1206		}
1207	} else {
1208		for _, shareID := range p.dbHandle.sharesIDs {
1209			s := p.dbHandle.shares[shareID]
1210			if s.Username != username {
1211				continue
1212			}
1213			itNum++
1214			if itNum <= offset {
1215				continue
1216			}
1217			share := s.getACopy()
1218			share.HideConfidentialData()
1219			shares = append(shares, share)
1220			if len(shares) >= limit {
1221				break
1222			}
1223		}
1224	}
1225
1226	return shares, nil
1227}
1228
1229func (p *MemoryProvider) dumpShares() ([]Share, error) {
1230	p.dbHandle.Lock()
1231	defer p.dbHandle.Unlock()
1232
1233	shares := make([]Share, 0, len(p.dbHandle.shares))
1234	if p.dbHandle.isClosed {
1235		return shares, errMemoryProviderClosed
1236	}
1237	for _, s := range p.dbHandle.shares {
1238		shares = append(shares, s)
1239	}
1240	return shares, nil
1241}
1242
1243func (p *MemoryProvider) updateShareLastUse(shareID string, numTokens int) error {
1244	p.dbHandle.Lock()
1245	defer p.dbHandle.Unlock()
1246	if p.dbHandle.isClosed {
1247		return errMemoryProviderClosed
1248	}
1249	share, err := p.shareExistsInternal(shareID, "")
1250	if err != nil {
1251		return err
1252	}
1253	share.LastUseAt = util.GetTimeAsMsSinceEpoch(time.Now())
1254	share.UsedTokens += numTokens
1255	p.dbHandle.shares[share.ShareID] = share
1256	return nil
1257}
1258
1259func (p *MemoryProvider) getNextID() int64 {
1260	nextID := int64(1)
1261	for _, v := range p.dbHandle.users {
1262		if v.ID >= nextID {
1263			nextID = v.ID + 1
1264		}
1265	}
1266	return nextID
1267}
1268
1269func (p *MemoryProvider) getNextFolderID() int64 {
1270	nextID := int64(1)
1271	for _, v := range p.dbHandle.vfolders {
1272		if v.ID >= nextID {
1273			nextID = v.ID + 1
1274		}
1275	}
1276	return nextID
1277}
1278
1279func (p *MemoryProvider) getNextAdminID() int64 {
1280	nextID := int64(1)
1281	for _, a := range p.dbHandle.admins {
1282		if a.ID >= nextID {
1283			nextID = a.ID + 1
1284		}
1285	}
1286	return nextID
1287}
1288
1289func (p *MemoryProvider) clear() {
1290	p.dbHandle.Lock()
1291	defer p.dbHandle.Unlock()
1292	p.dbHandle.usernames = []string{}
1293	p.dbHandle.users = make(map[string]User)
1294	p.dbHandle.vfoldersNames = []string{}
1295	p.dbHandle.vfolders = make(map[string]vfs.BaseVirtualFolder)
1296	p.dbHandle.admins = make(map[string]Admin)
1297	p.dbHandle.adminsUsernames = []string{}
1298	p.dbHandle.apiKeys = make(map[string]APIKey)
1299	p.dbHandle.apiKeysIDs = []string{}
1300	p.dbHandle.shares = make(map[string]Share)
1301	p.dbHandle.sharesIDs = []string{}
1302}
1303
1304func (p *MemoryProvider) reloadConfig() error {
1305	if p.dbHandle.configFile == "" {
1306		providerLog(logger.LevelDebug, "no dump configuration file defined")
1307		return nil
1308	}
1309	providerLog(logger.LevelDebug, "loading dump from file: %#v", p.dbHandle.configFile)
1310	fi, err := os.Stat(p.dbHandle.configFile)
1311	if err != nil {
1312		providerLog(logger.LevelWarn, "error loading dump: %v", err)
1313		return err
1314	}
1315	if fi.Size() == 0 {
1316		err = errors.New("dump configuration file is invalid, its size must be > 0")
1317		providerLog(logger.LevelWarn, "error loading dump: %v", err)
1318		return err
1319	}
1320	if fi.Size() > 10485760 {
1321		err = errors.New("dump configuration file is invalid, its size must be <= 10485760 bytes")
1322		providerLog(logger.LevelWarn, "error loading dump: %v", err)
1323		return err
1324	}
1325	content, err := os.ReadFile(p.dbHandle.configFile)
1326	if err != nil {
1327		providerLog(logger.LevelWarn, "error loading dump: %v", err)
1328		return err
1329	}
1330	dump, err := ParseDumpData(content)
1331	if err != nil {
1332		providerLog(logger.LevelWarn, "error loading dump: %v", err)
1333		return err
1334	}
1335	p.clear()
1336
1337	if err := p.restoreFolders(&dump); err != nil {
1338		return err
1339	}
1340
1341	if err := p.restoreUsers(&dump); err != nil {
1342		return err
1343	}
1344
1345	if err := p.restoreAdmins(&dump); err != nil {
1346		return err
1347	}
1348
1349	if err := p.restoreAPIKeys(&dump); err != nil {
1350		return err
1351	}
1352
1353	if err := p.restoreShares(&dump); err != nil {
1354		return err
1355	}
1356
1357	providerLog(logger.LevelDebug, "config loaded from file: %#v", p.dbHandle.configFile)
1358	return nil
1359}
1360
1361func (p *MemoryProvider) restoreShares(dump *BackupData) error {
1362	for _, share := range dump.Shares {
1363		s, err := p.shareExists(share.ShareID, "")
1364		share := share // pin
1365		share.IsRestore = true
1366		if err == nil {
1367			share.ID = s.ID
1368			err = UpdateShare(&share, ActionExecutorSystem, "")
1369			if err != nil {
1370				providerLog(logger.LevelWarn, "error updating share %#v: %v", share.ShareID, err)
1371				return err
1372			}
1373		} else {
1374			err = AddShare(&share, ActionExecutorSystem, "")
1375			if err != nil {
1376				providerLog(logger.LevelWarn, "error adding share %#v: %v", share.ShareID, err)
1377				return err
1378			}
1379		}
1380	}
1381	return nil
1382}
1383
1384func (p *MemoryProvider) restoreAPIKeys(dump *BackupData) error {
1385	for _, apiKey := range dump.APIKeys {
1386		if apiKey.Key == "" {
1387			return fmt.Errorf("cannot restore an empty API key: %+v", apiKey)
1388		}
1389		k, err := p.apiKeyExists(apiKey.KeyID)
1390		apiKey := apiKey // pin
1391		if err == nil {
1392			apiKey.ID = k.ID
1393			err = UpdateAPIKey(&apiKey, ActionExecutorSystem, "")
1394			if err != nil {
1395				providerLog(logger.LevelWarn, "error updating API key %#v: %v", apiKey.KeyID, err)
1396				return err
1397			}
1398		} else {
1399			err = AddAPIKey(&apiKey, ActionExecutorSystem, "")
1400			if err != nil {
1401				providerLog(logger.LevelWarn, "error adding API key %#v: %v", apiKey.KeyID, err)
1402				return err
1403			}
1404		}
1405	}
1406	return nil
1407}
1408
1409func (p *MemoryProvider) restoreAdmins(dump *BackupData) error {
1410	for _, admin := range dump.Admins {
1411		a, err := p.adminExists(admin.Username)
1412		admin := admin // pin
1413		if err == nil {
1414			admin.ID = a.ID
1415			err = UpdateAdmin(&admin, ActionExecutorSystem, "")
1416			if err != nil {
1417				providerLog(logger.LevelWarn, "error updating admin %#v: %v", admin.Username, err)
1418				return err
1419			}
1420		} else {
1421			err = AddAdmin(&admin, ActionExecutorSystem, "")
1422			if err != nil {
1423				providerLog(logger.LevelWarn, "error adding admin %#v: %v", admin.Username, err)
1424				return err
1425			}
1426		}
1427	}
1428	return nil
1429}
1430
1431func (p *MemoryProvider) restoreFolders(dump *BackupData) error {
1432	for _, folder := range dump.Folders {
1433		folder := folder // pin
1434		f, err := p.getFolderByName(folder.Name)
1435		if err == nil {
1436			folder.ID = f.ID
1437			err = UpdateFolder(&folder, f.Users, ActionExecutorSystem, "")
1438			if err != nil {
1439				providerLog(logger.LevelWarn, "error updating folder %#v: %v", folder.Name, err)
1440				return err
1441			}
1442		} else {
1443			folder.Users = nil
1444			err = AddFolder(&folder)
1445			if err != nil {
1446				providerLog(logger.LevelWarn, "error adding folder %#v: %v", folder.Name, err)
1447				return err
1448			}
1449		}
1450	}
1451	return nil
1452}
1453
1454func (p *MemoryProvider) restoreUsers(dump *BackupData) error {
1455	for _, user := range dump.Users {
1456		user := user // pin
1457		u, err := p.userExists(user.Username)
1458		if err == nil {
1459			user.ID = u.ID
1460			err = UpdateUser(&user, ActionExecutorSystem, "")
1461			if err != nil {
1462				providerLog(logger.LevelWarn, "error updating user %#v: %v", user.Username, err)
1463				return err
1464			}
1465		} else {
1466			err = AddUser(&user, ActionExecutorSystem, "")
1467			if err != nil {
1468				providerLog(logger.LevelWarn, "error adding user %#v: %v", user.Username, err)
1469				return err
1470			}
1471		}
1472	}
1473	return nil
1474}
1475
1476// initializeDatabase does nothing, no initilization is needed for memory provider
1477func (p *MemoryProvider) initializeDatabase() error {
1478	return ErrNoInitRequired
1479}
1480
1481func (p *MemoryProvider) migrateDatabase() error {
1482	return ErrNoInitRequired
1483}
1484
1485func (p *MemoryProvider) revertDatabase(targetVersion int) error {
1486	return errors.New("memory provider does not store data, revert not possible")
1487}
1488
1489func (p *MemoryProvider) resetDatabase() error {
1490	return errors.New("memory provider does not store data, reset not possible")
1491}
1492