192 lines
4.1 KiB
Go
192 lines
4.1 KiB
Go
package management
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"fmt"
|
|
d "playback-device-server/data"
|
|
"time"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
const DEFAULT_USERNAME = "admin"
|
|
const MIN_PASSWORD_LENGTH = 6
|
|
|
|
type UserManager struct {
|
|
userDatabase *d.UserDatabase
|
|
}
|
|
|
|
func (um *UserManager) Initialize(userDatabase *d.UserDatabase) error {
|
|
um.userDatabase = userDatabase
|
|
|
|
exists, error := um.UsernameExists(DEFAULT_USERNAME)
|
|
if error != nil {
|
|
return error
|
|
}
|
|
|
|
if !exists {
|
|
password, error := generateRandomPassword(MIN_PASSWORD_LENGTH)
|
|
if error != nil {
|
|
return error
|
|
}
|
|
|
|
log.Info().Str("username", DEFAULT_USERNAME).Str("password", password).Msg("creating default admin user")
|
|
|
|
user := d.User{Username: DEFAULT_USERNAME, Password: password, IsAdmin: true}
|
|
_, error = um.CreateUser(&user)
|
|
if error != nil {
|
|
return error
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (um *UserManager) CreateUser(user *d.User) (string, error) {
|
|
exists, error := um.UsernameExists(user.Username)
|
|
if error != nil {
|
|
return "", error
|
|
}
|
|
if exists {
|
|
return "", fmt.Errorf("User '%s' already exists", user.Username)
|
|
}
|
|
|
|
if !isValidPassword(user.Password) {
|
|
return "", fmt.Errorf("invalid password")
|
|
}
|
|
|
|
id, error := um.userDatabase.CreateUser(user.Username, user.Password, user.IsAdmin)
|
|
if error != nil {
|
|
return "", error
|
|
}
|
|
return id, nil
|
|
}
|
|
|
|
func (um *UserManager) UsernameExists(username string) (bool, error) {
|
|
exists, error := um.userDatabase.UsernameExists(username)
|
|
if error != nil {
|
|
return false, error
|
|
}
|
|
return exists, nil
|
|
}
|
|
|
|
func (um *UserManager) UserIdExists(id string) (bool, error) {
|
|
exists, error := um.userDatabase.UserIdExists(id)
|
|
if error != nil {
|
|
return false, error
|
|
}
|
|
return exists, nil
|
|
}
|
|
|
|
func (um *UserManager) Login(username, password string) (string, error) {
|
|
exists, error := um.UsernameExists(username)
|
|
if error != nil {
|
|
return "", error
|
|
}
|
|
if !exists {
|
|
return "", fmt.Errorf("user '%s' doesn't exist", username)
|
|
}
|
|
|
|
correct, error := um.userDatabase.CheckCredentials(username, password)
|
|
if error != nil {
|
|
return "", error
|
|
}
|
|
if !correct {
|
|
return "", fmt.Errorf("wrong password")
|
|
}
|
|
|
|
user, error := um.userDatabase.GetUserByUsername(username)
|
|
if error != nil {
|
|
return "", error
|
|
}
|
|
|
|
expiryDate := time.Now().AddDate(0, 0, 30)
|
|
token, error := um.userDatabase.CreateSession(user.ID, expiryDate)
|
|
if error != nil {
|
|
return "", error
|
|
}
|
|
|
|
return token, nil
|
|
}
|
|
|
|
func (um *UserManager) GetSession(sessionToken string) (*d.UserSession, error) {
|
|
session, error := um.userDatabase.GetSession(sessionToken)
|
|
if error != nil {
|
|
return nil, error
|
|
}
|
|
return session, nil
|
|
}
|
|
|
|
func (um *UserManager) GetUserById(id string) (*d.User, error) {
|
|
user, error := um.userDatabase.GetUserById(id)
|
|
if error != nil {
|
|
return nil, error
|
|
}
|
|
return user, nil
|
|
}
|
|
|
|
func (um *UserManager) UpdateUser(user *d.User) error {
|
|
error := um.userDatabase.UpdateUser(user)
|
|
return error
|
|
}
|
|
|
|
func (um *UserManager) UpdatePassword(currentPassword string, newPassword string, user *d.User) error {
|
|
correct, error := um.userDatabase.CheckCredentials(user.Username, currentPassword)
|
|
if error != nil {
|
|
return error
|
|
}
|
|
if !correct {
|
|
return fmt.Errorf("wrong password")
|
|
}
|
|
|
|
if !isValidPassword(user.Password) {
|
|
return fmt.Errorf("invalid password")
|
|
}
|
|
|
|
error = um.userDatabase.UpdatePassword(user.ID, newPassword)
|
|
return error
|
|
}
|
|
|
|
func (um *UserManager) DeleteSession(token string) error {
|
|
error := um.userDatabase.DeleteSessionByToken(token)
|
|
if error != nil {
|
|
return error
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (um *UserManager) GetUsers() (*[]d.User, error) {
|
|
users, error := um.userDatabase.GetUsers()
|
|
|
|
return users, error
|
|
}
|
|
|
|
func (um *UserManager) DeleteUser(ID string) error {
|
|
error := um.userDatabase.DeleteUser(ID)
|
|
|
|
return error
|
|
}
|
|
|
|
func isValidPassword(password string) bool {
|
|
return len(password) >= MIN_PASSWORD_LENGTH
|
|
}
|
|
|
|
func generateRandomPassword(length int) (string, error) {
|
|
numBytes := length * 3 / 4 // Base64 encoding increases length by 4/3
|
|
|
|
randomBytes := make([]byte, numBytes)
|
|
_, err := rand.Read(randomBytes)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
password := base64.URLEncoding.EncodeToString(randomBytes)
|
|
|
|
if len(password) > length {
|
|
password = password[:length]
|
|
}
|
|
|
|
return password, nil
|
|
}
|