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