128 lines
2.6 KiB
Go
128 lines
2.6 KiB
Go
|
package users
|
||
|
|
||
|
import (
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||
|
)
|
||
|
|
||
|
// StorageBackend is the interface to implement for a users storage.
|
||
|
type StorageBackend interface {
|
||
|
GetByID(uint) (*User, error)
|
||
|
GetByUsername(string) (*User, error)
|
||
|
Gets() ([]*User, error)
|
||
|
Save(u *User) error
|
||
|
Update(u *User, fields ...string) error
|
||
|
DeleteByID(uint) error
|
||
|
DeleteByUsername(string) error
|
||
|
}
|
||
|
|
||
|
// Storage is a users storage.
|
||
|
type Storage struct {
|
||
|
back StorageBackend
|
||
|
updated map[uint]int64
|
||
|
mux sync.RWMutex
|
||
|
}
|
||
|
|
||
|
// NewStorage creates a users storage from a backend.
|
||
|
func NewStorage(back StorageBackend) *Storage {
|
||
|
return &Storage{
|
||
|
back: back,
|
||
|
updated: map[uint]int64{},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Get allows you to get a user by its name or username. The provided
|
||
|
// id must be a string for username lookup or a uint for id lookup. If id
|
||
|
// is neither, a ErrInvalidDataType will be returned.
|
||
|
func (s *Storage) Get(id interface{}) (*User, error) {
|
||
|
var (
|
||
|
user *User
|
||
|
err error
|
||
|
)
|
||
|
|
||
|
switch id.(type) {
|
||
|
case string:
|
||
|
user, err = s.back.GetByUsername(id.(string))
|
||
|
case uint:
|
||
|
user, err = s.back.GetByID(id.(uint))
|
||
|
default:
|
||
|
return nil, errors.ErrInvalidDataType
|
||
|
}
|
||
|
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
user.Clean()
|
||
|
return user, err
|
||
|
}
|
||
|
|
||
|
// Gets gets a list of all users.
|
||
|
func (s *Storage) Gets() ([]*User, error) {
|
||
|
users, err := s.back.Gets()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
for _, user := range users {
|
||
|
user.Clean()
|
||
|
}
|
||
|
|
||
|
return users, err
|
||
|
}
|
||
|
|
||
|
// Update updates a user in the database.
|
||
|
func (s *Storage) Update(user *User, fields ...string) error {
|
||
|
err := user.Clean(fields...)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
err = s.back.Update(user, fields...)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
s.mux.Lock()
|
||
|
s.updated[user.ID] = time.Now().Unix()
|
||
|
s.mux.Unlock()
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Save saves the user in a storage.
|
||
|
func (s *Storage) Save(user *User) error {
|
||
|
if err := user.Clean(); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return s.back.Save(user)
|
||
|
}
|
||
|
|
||
|
// Delete allows you to delete a user by its name or username. The provided
|
||
|
// id must be a string for username lookup or a uint for id lookup. If id
|
||
|
// is neither, a ErrInvalidDataType will be returned.
|
||
|
func (s *Storage) Delete(id interface{}) (err error) {
|
||
|
switch id.(type) {
|
||
|
case string:
|
||
|
err = s.back.DeleteByUsername(id.(string))
|
||
|
case uint:
|
||
|
err = s.back.DeleteByID(id.(uint))
|
||
|
default:
|
||
|
err = errors.ErrInvalidDataType
|
||
|
}
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// LastUpdate gets the timestamp for the last update of an user.
|
||
|
func (s *Storage) LastUpdate(id uint) int64 {
|
||
|
s.mux.RLock()
|
||
|
defer s.mux.RUnlock()
|
||
|
if val, ok := s.updated[id]; ok {
|
||
|
return val
|
||
|
}
|
||
|
return 0
|
||
|
}
|