mirror of
https://github.com/navidrome/navidrome.git
synced 2026-05-03 06:51:16 +00:00
Compare commits
No commits in common. "b1e5ab6fb30ab2fd045c7685917995744775cd0d" and "53641dae88df31e3bf9b1e7381586ac39e8fc26b" have entirely different histories.
b1e5ab6fb3
...
53641dae88
@ -103,7 +103,7 @@ func runList() {
|
|||||||
options := model.QueryOptions{Sort: "owner_name"}
|
options := model.QueryOptions{Sort: "owner_name"}
|
||||||
|
|
||||||
if userID != "" {
|
if userID != "" {
|
||||||
user, err := getUser(ctx, userID, ds)
|
user, err := getUser(userID, ds, ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(ctx, "Error retrieving user", "username or id", userID)
|
log.Fatal(ctx, "Error retrieving user", "username or id", userID)
|
||||||
}
|
}
|
||||||
|
|||||||
91
cmd/user.go
91
cmd/user.go
@ -22,6 +22,7 @@ var (
|
|||||||
email string
|
email string
|
||||||
libraryIds []int
|
libraryIds []int
|
||||||
name string
|
name string
|
||||||
|
password string
|
||||||
|
|
||||||
removeEmail bool
|
removeEmail bool
|
||||||
removeName bool
|
removeName bool
|
||||||
@ -35,13 +36,18 @@ func init() {
|
|||||||
|
|
||||||
userCreateCommand.Flags().StringVarP(&userID, "username", "u", "", "username")
|
userCreateCommand.Flags().StringVarP(&userID, "username", "u", "", "username")
|
||||||
|
|
||||||
|
userCreateCommand.Flags().BoolVar(&setPassword, "set-password", false, "If set, the user's new password will be prompted on the CLI")
|
||||||
|
userCreateCommand.Flags().StringVarP(&password, "password", "p", "", "Set the user's password. Note that this will be captured in terminal history")
|
||||||
|
userCreateCommand.MarkFlagsMutuallyExclusive("password", "set-password")
|
||||||
|
|
||||||
userCreateCommand.Flags().StringVarP(&email, "email", "e", "", "New user email")
|
userCreateCommand.Flags().StringVarP(&email, "email", "e", "", "New user email")
|
||||||
userCreateCommand.Flags().IntSliceVarP(&libraryIds, "library-ids", "i", []int{}, "Comma-separated list of library IDs. Set the user's accessible libraries. If empty, the user can access all libraries. This is incompatible with admin, as admin can always access all libraries")
|
userCreateCommand.Flags().IntSliceVar(&libraryIds, "library-ids", []int{}, "Set the user's accessible libraries. If empty, the user can access all libraries. This is incompatible with admin, as admin can always access all libraries")
|
||||||
|
|
||||||
userCreateCommand.Flags().BoolVarP(&setAdmin, "admin", "a", false, "If set, make the user an admin. This user will have access to every library")
|
userCreateCommand.Flags().BoolVarP(&setAdmin, "admin", "a", false, "If set, make the user an admin. This user will have access to every library")
|
||||||
userCreateCommand.Flags().StringVar(&name, "name", "", "New user's name (this is separate from username used to log in)")
|
userCreateCommand.Flags().StringVar(&name, "name", "", "New user's name (this is separate from username used to log in)")
|
||||||
|
|
||||||
_ = userCreateCommand.MarkFlagRequired("username")
|
_ = userCreateCommand.MarkFlagRequired("username")
|
||||||
|
userCreateCommand.MarkFlagsOneRequired("password", "set-password")
|
||||||
|
|
||||||
userRoot.AddCommand(userCreateCommand)
|
userRoot.AddCommand(userCreateCommand)
|
||||||
|
|
||||||
@ -64,8 +70,10 @@ func init() {
|
|||||||
userEditCommand.MarkFlagsMutuallyExclusive("name", "remove-name")
|
userEditCommand.MarkFlagsMutuallyExclusive("name", "remove-name")
|
||||||
|
|
||||||
userEditCommand.Flags().BoolVar(&setPassword, "set-password", false, "If set, the user's new password will be prompted on the CLI")
|
userEditCommand.Flags().BoolVar(&setPassword, "set-password", false, "If set, the user's new password will be prompted on the CLI")
|
||||||
|
userEditCommand.Flags().StringVarP(&password, "password", "p", "", "Set the user's password. Note that this will be captured in terminal history")
|
||||||
|
userEditCommand.MarkFlagsMutuallyExclusive("password", "set-password")
|
||||||
|
|
||||||
userEditCommand.Flags().IntSliceVarP(&libraryIds, "library-ids", "i", []int{}, "Comma-separated list of library IDs. Set the user's accessible libraries by id")
|
userEditCommand.Flags().IntSliceVar(&libraryIds, "library-ids", []int{}, "Set the user's accessible libraries by id")
|
||||||
|
|
||||||
_ = userEditCommand.MarkFlagRequired("user")
|
_ = userEditCommand.MarkFlagRequired("user")
|
||||||
userRoot.AddCommand(userEditCommand)
|
userRoot.AddCommand(userEditCommand)
|
||||||
@ -153,18 +161,12 @@ func promptPassword() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func libraryError(libraries model.Libraries) error {
|
|
||||||
ids := make([]int, len(libraries))
|
|
||||||
for idx, library := range libraries {
|
|
||||||
ids[idx] = library.ID
|
|
||||||
}
|
|
||||||
return fmt.Errorf("not all available libraries found. Requested ids: %v, Found libraries: %v", libraryIds, ids)
|
|
||||||
}
|
|
||||||
|
|
||||||
func runCreateUser() {
|
func runCreateUser() {
|
||||||
password := promptPassword()
|
|
||||||
if password == "" {
|
if password == "" {
|
||||||
log.Fatal("Empty password provided, user creation cancelled")
|
password = promptPassword()
|
||||||
|
if password == "" {
|
||||||
|
log.Fatal("Empty password provided, user creation cancelled")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
user := model.User{
|
user := model.User{
|
||||||
@ -175,10 +177,6 @@ func runCreateUser() {
|
|||||||
NewPassword: password,
|
NewPassword: password,
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Name == "" {
|
|
||||||
user.Name = userID
|
|
||||||
}
|
|
||||||
|
|
||||||
ds, ctx := getContext()
|
ds, ctx := getContext()
|
||||||
|
|
||||||
err := ds.WithTx(func(tx model.DataStore) error {
|
err := ds.WithTx(func(tx model.DataStore) error {
|
||||||
@ -198,7 +196,7 @@ func runCreateUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(user.Libraries) != len(libraryIds) {
|
if len(user.Libraries) != len(libraryIds) {
|
||||||
return libraryError(user.Libraries)
|
return fmt.Errorf("not all available libraries found. Requested ids: %v, Found libraries: %d", libraryIds, len(user.Libraries))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
user.Libraries, err = tx.Library(ctx).GetAll()
|
user.Libraries, err = tx.Library(ctx).GetAll()
|
||||||
@ -212,13 +210,7 @@ func runCreateUser() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedIds := make([]int, len(user.Libraries))
|
return nil
|
||||||
for idx, lib := range user.Libraries {
|
|
||||||
updatedIds[idx] = lib.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tx.User(ctx).SetUserLibraries(user.ID, updatedIds)
|
|
||||||
return err
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -244,7 +236,7 @@ func runDeleteUser() {
|
|||||||
return errors.New("refusing to delete the last user")
|
return errors.New("refusing to delete the last user")
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err = getUser(ctx, userID, tx)
|
user, err = getUser(userID, tx, ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -267,9 +259,7 @@ func runUserEdit() {
|
|||||||
changes := []string{}
|
changes := []string{}
|
||||||
|
|
||||||
err = ds.WithTx(func(tx model.DataStore) error {
|
err = ds.WithTx(func(tx model.DataStore) error {
|
||||||
var newLibraries model.Libraries
|
user, err = getUser(userID, tx, ctx)
|
||||||
|
|
||||||
user, err = getUser(ctx, userID, tx)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -282,10 +272,10 @@ func runUserEdit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(libraries) != len(libraryIds) {
|
if len(libraries) != len(libraryIds) {
|
||||||
return libraryError(libraries)
|
return fmt.Errorf("not all available libraries found. Requested ids: %v, Found libraries: %d", libraryIds, len(libraries))
|
||||||
}
|
}
|
||||||
|
|
||||||
newLibraries = libraries
|
user.Libraries = libraries
|
||||||
changes = append(changes, "updated library ids")
|
changes = append(changes, "updated library ids")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,8 +288,6 @@ func runUserEdit() {
|
|||||||
user.IsAdmin = true
|
user.IsAdmin = true
|
||||||
user.Libraries = libraries
|
user.Libraries = libraries
|
||||||
changes = append(changes, "set admin")
|
changes = append(changes, "set admin")
|
||||||
|
|
||||||
newLibraries = libraries
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if setRegularUser && user.IsAdmin {
|
if setRegularUser && user.IsAdmin {
|
||||||
@ -308,12 +296,12 @@ func runUserEdit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if setPassword {
|
if setPassword {
|
||||||
password := promptPassword()
|
password = promptPassword()
|
||||||
|
}
|
||||||
|
|
||||||
if password != "" {
|
if password != "" {
|
||||||
user.NewPassword = password
|
user.NewPassword = password
|
||||||
changes = append(changes, "updated password")
|
changes = append(changes, "updated password")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if email != "" && email != user.Email {
|
if email != "" && email != user.Email {
|
||||||
@ -333,38 +321,19 @@ func runUserEdit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(changes) == 0 {
|
if len(changes) == 0 {
|
||||||
|
log.Info(ctx, "No changes for user", "user", user.UserName)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err := tx.User(ctx).Put(user)
|
err = tx.User(ctx).Put(user)
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(newLibraries) > 0 {
|
|
||||||
updatedIds := make([]int, len(newLibraries))
|
|
||||||
for idx, lib := range newLibraries {
|
|
||||||
updatedIds[idx] = lib.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
err := tx.User(ctx).SetUserLibraries(user.ID, updatedIds)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(ctx, "Failed to update user", err)
|
log.Fatal(ctx, "Failed to update user", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(changes) == 0 {
|
log.Info(ctx, "Updated user", "user", user.Name, "changes", strings.Join(changes, ", "))
|
||||||
log.Info(ctx, "No changes for user", "user", user.UserName)
|
|
||||||
} else {
|
|
||||||
log.Info(ctx, "Updated user", "user", user.UserName, "changes", strings.Join(changes, ", "))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type displayLibrary struct {
|
type displayLibrary struct {
|
||||||
@ -444,7 +413,7 @@ func runUserList() {
|
|||||||
user.UpdatedAt.Format(time.RFC3339Nano),
|
user.UpdatedAt.Format(time.RFC3339Nano),
|
||||||
lastAccess,
|
lastAccess,
|
||||||
lastLogin,
|
lastLogin,
|
||||||
fmt.Sprintf("'%s'", strings.Join(paths, "|")),
|
fmt.Sprintf("'%s'", strings.Join(paths, ",")),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
w.Flush()
|
w.Flush()
|
||||||
|
|||||||
@ -3,7 +3,6 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/navidrome/navidrome/core/auth"
|
"github.com/navidrome/navidrome/core/auth"
|
||||||
"github.com/navidrome/navidrome/db"
|
"github.com/navidrome/navidrome/db"
|
||||||
@ -17,17 +16,17 @@ func getContext() (model.DataStore, context.Context) {
|
|||||||
return ds, auth.WithAdminUser(context.Background(), ds)
|
return ds, auth.WithAdminUser(context.Background(), ds)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUser(ctx context.Context, id string, ds model.DataStore) (*model.User, error) {
|
func getUser(id string, ds model.DataStore, ctx context.Context) (*model.User, error) {
|
||||||
user, err := ds.User(ctx).FindByUsername(id)
|
user, err := ds.User(ctx).FindByUsername(id)
|
||||||
|
|
||||||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||||
return nil, fmt.Errorf("finding user by name: %w", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, model.ErrNotFound) {
|
if errors.Is(err, model.ErrNotFound) {
|
||||||
user, err = ds.User(ctx).Get(id)
|
user, err = ds.User(ctx).Get(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("finding user by id: %w", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user