Select Git revision
accounts.go
accounts.go 10.28 KiB
package repl
import (
"errors"
"fmt"
"strings"
"git.lyda.ie/kevin/bulletin/ask"
"git.lyda.ie/kevin/bulletin/dclish"
"git.lyda.ie/kevin/bulletin/key"
"git.lyda.ie/kevin/bulletin/storage"
"git.lyda.ie/kevin/bulletin/this"
"git.lyda.ie/kevin/bulletin/users"
)
// ActionUser handles the USER command - it prints out help for all the
// USER subcommands. This is new to the Go version of BULLETIN.
func ActionUser(cmd *dclish.Command) error {
fmt.Println(cmd.Description)
return nil
}
// ActionUserAdd handles the `USER ADD` command. This is used to add a
// new user. This is new to the Go version of BULLETIN.
func ActionUserAdd(cmd *dclish.Command) error {
ctx := storage.Context()
login := strings.ToUpper(cmd.Args[0])
u, err := users.ValidExistingLogin(this.Q, login)
if err != nil {
fmt.Printf("ERROR: %s.\n", err)
return nil
}
if u.Login != "" {
fmt.Println("ERROR: User already exists.")
return nil
}
u, err = this.Q.AddUser(ctx, storage.AddUserParams{
Login: login,
Name: cmd.Args[1],
})
if err != nil {
fmt.Printf("ERROR: %s.\n", err)
return nil
}
if u.Login == "" {
fmt.Println("ERROR: Failed to make user; unknown reason.")
return nil
}
return nil
}
// ActionUserList handles the `USER LIST` command. This lists all the
// users. For now this is limited to only the admin users.
//
// This is new to the Go version of BULLETIN.
func ActionUserList(_ *dclish.Command) error {
if this.User.Admin == 0 {
fmt.Println("ERROR: You are not an admin.")
return nil
}
ctx := storage.Context()
userlist, err := this.Q.ListUsers(ctx)
if err != nil {
fmt.Printf("ERROR: Failed to list users (%s).\n", err)
return nil
}
for _, u := range userlist {
fmt.Printf("%s\n", u)
}
return nil
}
// ActionUserDelete handles the `USER DELETE` command. This will delete
// the named user. Only the admin can use this command.
//
// This is new to the Go version of BULLETIN.
func ActionUserDelete(cmd *dclish.Command) error {
if this.User.Admin == 0 {
fmt.Println("ERROR: You are not an admin.")
return nil
}
u, err := users.ValidExistingLogin(this.Q, cmd.Args[0])
if err != nil || u.Login == "" {
fmt.Println("ERROR: User not found.")
return nil
}
ctx := storage.Context()
err = this.Q.DeleteUser(ctx, u.Login)
if err != nil {
fmt.Printf("ERROR: Failed to delete user (%s).\n", err)
return nil
}
fmt.Println("User deleted.")
return nil
}
func actionUserEnable(cmd *dclish.Command, disabled int64, doing string) error {
if this.User.Admin == 0 {
fmt.Println("ERROR: You are not an admin.")
return nil
}
u, err := users.ValidExistingLogin(this.Q, cmd.Args[0])
if err != nil || u.Login == "" {
fmt.Println("ERROR: User not found.")
return nil
}
if u.Disabled == disabled {
fmt.Printf("User already %sd.\n", doing)
return nil
}
ctx := storage.Context()
err = this.Q.UpdateUserDisabled(ctx, disabled, u.Login)
if err != nil {
fmt.Printf("ERROR: Failed to %s user (%s).\n", doing, err)
return nil
}
fmt.Printf("User %sd.\n", doing)
return nil
}
// ActionUserEnable handles the `USER ENABLE` command. This enables
// a user. Only the admin can use this command.
//
// This is new to the Go version of BULLETIN.
func ActionUserEnable(cmd *dclish.Command) error {
return actionUserEnable(cmd, 0, "enable")
}
// ActionUserDisable handles the `USER DISABLE` command. This disables
// a user. Only the admin can use this command.
//
// This is new to the Go version of BULLETIN.
func ActionUserDisable(cmd *dclish.Command) error {
return actionUserEnable(cmd, 1, "disable")
}
func actionUserAdmin(cmd *dclish.Command, admin int64, doing string) error {
if this.User.Admin == 0 {
fmt.Println("ERROR: You are not an admin.")
return nil
}
u, err := users.ValidExistingLogin(this.Q, cmd.Args[0])
if err != nil || u.Login == "" {
return errors.New("User not found")
}
if u.Login == this.User.Login || u.Login == "SYSTEM" {
return errors.New("Invalid user given")
}
if u.Admin == admin {
fmt.Printf("User is already %s.\n", doing)
return nil
}
ctx := storage.Context()
err = this.Q.UpdateUserAdmin(ctx, admin, u.Login)
if err != nil {
return fmt.Errorf("Failed to make user %s (%s)", doing, err)
}
fmt.Printf("User is now %s.\n", doing)
return nil
}
// ActionUserAdmin handles the `USER ADMIN` command. This makes the given
// user an admin. Only the admin can use this command.
//
// This is new to the Go version of BULLETIN.
func ActionUserAdmin(cmd *dclish.Command) error {
return actionUserAdmin(cmd, 1, "an admin")
}
// ActionUserNoadmin handles the `USER NOADMIN` command. This removes the
// admin bit from a given user. Only the admin can use this command.
//
// This is new to the Go version of BULLETIN.
func ActionUserNoadmin(cmd *dclish.Command) error {
return actionUserAdmin(cmd, 0, "not an admin")
}
func actionUserMod(cmd *dclish.Command, mod int64, doing string) error {
if this.User.Admin == 0 {
fmt.Println("ERROR: You are not an admin.")
return nil
}
u, err := users.ValidExistingLogin(this.Q, cmd.Args[0])
if err != nil || u.Login == "" {
fmt.Println("ERROR: User not found.")
return nil
}
if u.Moderator == mod {
fmt.Printf("User is already %s.\n", doing)
return nil
}
ctx := storage.Context()
err = this.Q.UpdateUserMod(ctx, mod, u.Login)
if err != nil {
fmt.Printf("ERROR: Failed to make user %s (%s).\n", doing, err)
return nil
}
fmt.Printf("User is now %s.\n", doing)
return nil
}
// ActionUserMod handles the `USER MOD` command. Makes given the user a
// moderator. Only the admin can use this command.
//
// This is new to the Go version of BULLETIN.
func ActionUserMod(cmd *dclish.Command) error {
return actionUserMod(cmd, 1, "a moderator")
}
// ActionUserNomod handles the `USER NOMOD` command. Removes the
// moderator bit from the given user. Only the admin can use this command.
//
// This is new to the Go version of BULLETIN.
func ActionUserNomod(cmd *dclish.Command) error {
return actionUserMod(cmd, 0, "not a moderator")
}
// ActionUserName handles the `USER NAME` command. Updates the user's
// name. Only the admin can use the two argument version of this command.
//
// This is new to the Go version of BULLETIN.
func ActionUserName(cmd *dclish.Command) error {
if len(cmd.Args) == 2 && this.User.Admin == 0 {
fmt.Println("ERROR: You are not an admin.")
return nil
}
login := this.User.Login
name := cmd.Args[0]
if len(cmd.Args) == 2 {
login = strings.ToUpper(cmd.Args[0])
name = cmd.Args[1]
_, err := users.ValidExistingLogin(this.Q, login)
if err != nil {
fmt.Printf("ERROR: %s.\n", err)
return nil
}
}
ctx := storage.Context()
err := this.Q.UpdateUserName(ctx, name, login)
if err != nil {
fmt.Printf("ERROR: Failed to update user name (%s).\n", err)
}
return nil
}
// ActionSSH handles the `SSH` command. This prints the help for all the
// SSH commands. These are used to manage the authorized_keys file.
// These are new to the Go version of BULLETIN.
func ActionSSH(cmd *dclish.Command) error {
fmt.Println(cmd.Description)
return nil
}
// ActionSSHAdd handles the `SSH ADD` command. This adds a given ssh key
// to the authorized_keys file for the given user. An admin can add
// a new public key for another user.
//
// This is new to the Go version of BULLETIN.
func ActionSSHAdd(cmd *dclish.Command) error {
if this.User.Admin == 0 && len(cmd.Args) == 1 {
fmt.Println("ERROR: You are not an admin.")
return nil
}
login := this.User.Login
if len(cmd.Args) == 1 {
login = cmd.Args[0]
}
u, err := users.ValidExistingLogin(this.Q, login)
if err != nil || u.Login == "" {
fmt.Println("ERROR: User not found.")
return nil
}
sshkey, err := ask.GetLine("Enter ssh public key: ")
if err != nil {
fmt.Printf("ERROR: Failed to read ssh key (%s).\n", err)
return nil
}
key.Add(u.Login, sshkey)
fmt.Println("Key is added.")
return nil
}
// ActionSSHList handles the `SSH LIST` command. This lists all the
// public keys for this user. An admin can list public keys for another
// user.
//
// This is new to the Go version of BULLETIN.
func ActionSSHList(cmd *dclish.Command) error {
if this.User.Admin == 0 && len(cmd.Args) == 1 {
fmt.Println("ERROR: You are not an admin.")
return nil
}
login := this.User.Login
if len(cmd.Args) == 1 {
login = cmd.Args[0]
}
u, err := users.ValidExistingLogin(this.Q, login)
if err != nil || u.Login == "" {
fmt.Println("ERROR: User not found.")
return nil
}
keys, err := key.List(login)
if err != nil {
fmt.Printf("ERROR: Problem listing keys (%s).\n", err)
return nil
}
fmt.Printf("The %d keys:\n %s\n", len(keys), strings.Join(keys, "\n "))
return nil
}
// ActionSSHDelete handles the `SSH DELETE` command. Removes ssh public
// keys for a user. And admin can specify a different user to remove
// public keys for.
//
// This is new to the Go version of BULLETIN.
func ActionSSHDelete(cmd *dclish.Command) error {
if this.User.Admin == 0 && len(cmd.Args) == 1 {
fmt.Println("ERROR: You are not an admin.")
return nil
}
login := this.User.Login
if len(cmd.Args) == 1 {
login = cmd.Args[0]
}
u, err := users.ValidExistingLogin(this.Q, login)
if err != nil || u.Login == "" {
fmt.Println("ERROR: User not found.")
return nil
}
keys, err := key.List(login)
if err != nil {
fmt.Printf("ERROR: Problem listing keys (%s).\n", err)
return nil
}
if len(keys) == 0 {
fmt.Println("No keys to delete.")
return nil
}
choice, err := ask.Choose("Choose a key to delete:", keys)
if err != nil {
fmt.Printf("ERROR: Problem choosing key (%s).\n", err)
return nil
}
if choice < 0 {
fmt.Println("Aborted.")
return nil
}
err = key.Delete(keys[choice])
if err != nil {
fmt.Printf("ERROR: Problem deleting key (%s).\n", err)
return nil
}
fmt.Println("Key deleted.")
return nil
}
// ActionSSHFetch handles the `SSH FETCH` command. This command pulls
// public keys from code sites. It's the quickest way to
// add a number of keys for a user. An admin can do this
// for another user.
//
// This is new to the Go version of BULLETIN.
func ActionSSHFetch(cmd *dclish.Command) error {
login := this.User.Login
sitename := cmd.Args[0]
username := cmd.Args[1]
if len(cmd.Args) == 3 && this.User.Admin == 0 {
fmt.Println("ERROR: You are not an admin.")
return nil
}
if len(cmd.Args) == 3 {
login = cmd.Args[0]
sitename = cmd.Args[1]
username = cmd.Args[2]
}
fmt.Print(key.Fetch(login, sitename, username))
return nil
}