Daniel Ponte
dea092d448
Closes #14 Reviewed-on: #102 Co-authored-by: Daniel Ponte <amigan@gmail.com> Co-committed-by: Daniel Ponte <amigan@gmail.com>
121 lines
2.7 KiB
Go
121 lines
2.7 KiB
Go
package users
|
|
|
|
import (
|
|
"context"
|
|
|
|
"dynatron.me/x/stillbox/internal/cache"
|
|
"dynatron.me/x/stillbox/pkg/database"
|
|
)
|
|
|
|
type Store interface {
|
|
// GetUser gets a user by UID.
|
|
GetUser(ctx context.Context, username string) (*User, error)
|
|
|
|
// UserPrefs gets the preferences for the specified user and app name.
|
|
UserPrefs(ctx context.Context, username string, appName string) ([]byte, error)
|
|
|
|
// SetUserPrefs sets the preferences for the specified user and app name.
|
|
SetUserPrefs(ctx context.Context, username string, appName string, prefs []byte) error
|
|
|
|
// Invalidate clears the user cache.
|
|
Invalidate()
|
|
|
|
// UpdateUser updates a user's record
|
|
UpdateUser(ctx context.Context, username string, user UserUpdate) error
|
|
|
|
// GetUserByAPIKey gets a user by API key.
|
|
GetAPIKey(ctx context.Context, key string) (database.GetAPIKeyRow, error)
|
|
}
|
|
|
|
type postgresStore struct {
|
|
cache.Cache[string, *User]
|
|
db database.Store
|
|
}
|
|
|
|
func NewStore(db database.Store) *postgresStore {
|
|
return &postgresStore{
|
|
Cache: cache.New[string, *User](),
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
type storeCtxKey string
|
|
|
|
const StoreCtxKey storeCtxKey = "store"
|
|
|
|
func CtxWithStore(ctx context.Context, s Store) context.Context {
|
|
return context.WithValue(ctx, StoreCtxKey, s)
|
|
}
|
|
|
|
func FromCtx(ctx context.Context) Store {
|
|
s, ok := ctx.Value(StoreCtxKey).(Store)
|
|
if !ok {
|
|
panic("no users store in context")
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
func (s *postgresStore) Invalidate() {
|
|
s.Clear()
|
|
}
|
|
|
|
type UserUpdate struct {
|
|
Email *string `json:"email"`
|
|
IsAdmin *bool `json:"isAdmin"`
|
|
}
|
|
|
|
func (s *postgresStore) UpdateUser(ctx context.Context, username string, user UserUpdate) error {
|
|
dbu, err := s.db.UpdateUser(ctx, username, user.Email, user.IsAdmin)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
s.Set(username, fromDBUser(dbu))
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *postgresStore) GetUser(ctx context.Context, username string) (*User, error) {
|
|
u, has := s.Get(username)
|
|
if has {
|
|
return u, nil
|
|
}
|
|
|
|
dbu, err := s.db.GetUserByUsername(ctx, username)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
u = fromDBUser(dbu)
|
|
s.Set(username, u)
|
|
|
|
return u, nil
|
|
}
|
|
|
|
func (s *postgresStore) UserPrefs(ctx context.Context, username string, appName string) ([]byte, error) {
|
|
u, err := s.GetUser(ctx, username)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
prefs, err := s.db.GetAppPrefs(ctx, appName, int(u.ID))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return []byte(prefs), err
|
|
}
|
|
|
|
func (s *postgresStore) SetUserPrefs(ctx context.Context, username string, appName string, prefs []byte) error {
|
|
u, err := s.GetUser(ctx, username)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return s.db.SetAppPrefs(ctx, appName, prefs, int(u.ID))
|
|
}
|
|
|
|
func (s *postgresStore) GetAPIKey(ctx context.Context, b64hash string) (database.GetAPIKeyRow, error) {
|
|
return s.db.GetAPIKey(ctx, b64hash)
|
|
}
|