mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-05 05:27:37 +03:00
63 lines
1.4 KiB
Go
63 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
|
|
}
|