✨ Add commands to manage users
This commit is contained in:
+131
@@ -0,0 +1,131 @@
|
||||
// Copyright (c) 2020, Andreas Schneider
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the <organization> nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type CmdUser struct {
|
||||
CmdList CmdUserList `cmd:"" name:"list" help:"List all users."`
|
||||
CmdAdd CmdUserAdd `cmd:"" name:"add" help:"Add a user."`
|
||||
CmdUpdate CmdUserUpdate `cmd:"" name:"update" help:"Update a user."`
|
||||
CmdDelete CmdUserDelete `cmd:"" name:"delete" help:"Delete a user."`
|
||||
}
|
||||
|
||||
type CmdUserList struct{}
|
||||
|
||||
func (cmd CmdUserList) Run(app *app) error {
|
||||
users, err := app.userStore.GetUsers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
fmt.Printf("* %s (%s)\n", user.Username, user.Role)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type CmdUserAdd struct {
|
||||
Username string `arg:"" name:"username" help:"The username to be added."`
|
||||
Password string `name:"password" help:"The password of the new user."`
|
||||
Role GlobalRole `name:"role" default:"user" help:"Role of the user. 'admin' or ' user'"`
|
||||
}
|
||||
|
||||
func (cmd CmdUserAdd) Run(app *app) error {
|
||||
switch cmd.Role {
|
||||
case GlobalRoleUser:
|
||||
case GlobalRoleAdmin:
|
||||
default:
|
||||
return fmt.Errorf("invalid user role")
|
||||
}
|
||||
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(cmd.Password), 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot hash password: %w", err)
|
||||
}
|
||||
|
||||
user := User{
|
||||
Username: cmd.Username,
|
||||
Password: string(hash),
|
||||
Role: cmd.Role,
|
||||
}
|
||||
return app.userStore.AddUser(user)
|
||||
}
|
||||
|
||||
type CmdUserUpdate struct {
|
||||
Username string `arg:"" name:"username" help:"The username of the user to be updated."`
|
||||
Password string `name:"password" help:"Update the password, if set."`
|
||||
Role GlobalRole `name:"role" default:"user" help:"Update the role, if set. 'admin' or ' user'"`
|
||||
}
|
||||
|
||||
func (cmd CmdUserUpdate) Run(app *app) error {
|
||||
user, err := app.userStore.GetUser(cmd.Username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
changed := false
|
||||
|
||||
if cmd.Role != "" && cmd.Role != user.Role {
|
||||
switch cmd.Role {
|
||||
case GlobalRoleUser:
|
||||
case GlobalRoleAdmin:
|
||||
default:
|
||||
return fmt.Errorf("invalid user role")
|
||||
}
|
||||
|
||||
user.Role = cmd.Role
|
||||
changed = true
|
||||
}
|
||||
|
||||
if cmd.Password != "" {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(cmd.Password), 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot hash password: %w", err)
|
||||
}
|
||||
user.Password = string(hash)
|
||||
changed = true
|
||||
}
|
||||
|
||||
if !changed {
|
||||
// Nothing changed. Nothing to write. Not different from a successful write to the user.
|
||||
return nil
|
||||
}
|
||||
|
||||
return app.userStore.Update(user)
|
||||
}
|
||||
|
||||
type CmdUserDelete struct {
|
||||
Username string `arg:"" name:"username" help:"The username of the user to be deleted."`
|
||||
}
|
||||
|
||||
func (cmd CmdUserDelete) Run(app *app) error {
|
||||
return app.userStore.RemoveUser(cmd.Username)
|
||||
}
|
||||
Reference in New Issue
Block a user