navidrome/engine/users.go

64 lines
1.4 KiB
Go

package engine
import (
"context"
"crypto/md5"
"encoding/hex"
"fmt"
"strings"
"github.com/deluan/navidrome/engine/auth"
"github.com/deluan/navidrome/model"
)
type Users interface {
Authenticate(ctx context.Context, username, password, token, salt, jwt string) (*model.User, error)
}
func NewUsers(ds model.DataStore) Users {
return &users{ds}
}
type users struct {
ds model.DataStore
}
func (u *users) Authenticate(ctx context.Context, username, pass, token, salt, jwt string) (*model.User, error) {
user, err := u.ds.User(ctx).FindByUsername(username)
if err == model.ErrNotFound {
return nil, model.ErrInvalidAuth
}
if err != nil {
return nil, err
}
valid := false
switch {
case jwt != "":
claims, err := auth.Validate(jwt)
valid = err == nil && claims["sub"] == username
case pass != "":
if strings.HasPrefix(pass, "enc:") {
if dec, err := hex.DecodeString(pass[4:]); err == nil {
pass = string(dec)
}
}
valid = pass == user.Password
case token != "":
t := fmt.Sprintf("%x", md5.Sum([]byte(user.Password+salt)))
valid = t == token
}
if !valid {
return nil, model.ErrInvalidAuth
}
// TODO: Find a way to update LastAccessAt without causing too much retention in the DB
//go func() {
// err := u.ds.User(ctx).UpdateLastAccessAt(user.ID)
// if err != nil {
// log.Error(ctx, "Could not update user's lastAccessAt", "user", user.UserName)
// }
//}()
return user, nil
}