diff --git a/.gitignore b/.gitignore index 2d0b03e5c73fad5da998f1fe145604b17a18b4d3..97caac8e6b959dce0db392b20e870803eea67f07 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ useradm +build.sh diff --git a/cmd/user/create.go b/cmd/user/create.go index 455b98e5c7431cf9c97e6e51bc2957d99139b3d1..7022dee12cbb9b7fd3549db896b367b4dea397f1 100644 --- a/cmd/user/create.go +++ b/cmd/user/create.go @@ -27,6 +27,7 @@ func init() { CreateCmd.Flags().StringP("shell", "s", "/bin/bash", "Full path to shell ") CreateCmd.Flags().StringP("homedir", "d", "", "Home directory path (/home/group/login if empty)") CreateCmd.Flags().StringP("password", "p", "", "User password (auto-generated if empty)") + CreateCmd.Flags().StringP("status", "a", "Free", "User status (Blocked/Free)") // Required Flags CreateCmd.MarkFlagRequired("name") @@ -77,6 +78,10 @@ func createUserFunc(cmd *cobra.Command, args []string) error { if err != nil { return err } + userStatus, err := cmd.Flags().GetString("status") + if err != nil { + return err + } user := model.User{ Name: userName, @@ -88,6 +93,7 @@ func createUserFunc(cmd *cobra.Command, args []string) error { Shell: userShell, Homedir: userHomedir, Password: ifThenElse(userPassword != "", "[set]", "[auto-generate]"), + Status: userStatus, } fmt.Println(user.ToString()) diff --git a/cmd/user/delete.go b/cmd/user/delete.go index a55844e6e4486dbfa191367d9690501b6ff0a4c9..27773082a3acbb1e452d6cb5272bd9b022b68531 100644 --- a/cmd/user/delete.go +++ b/cmd/user/delete.go @@ -4,5 +4,5 @@ import "github.com/spf13/cobra" var DeleteCmd = &cobra.Command{ Use: "delete", - Short: "Deleta a user", + Short: "Delete a user", } diff --git a/cmd/user/mod.go b/cmd/user/mod.go index 66b2a59260670752a4dfaef7b037a22177feef45..5dc5b03217cb95a57819f84c26bdfcdbbb40e1ec 100644 --- a/cmd/user/mod.go +++ b/cmd/user/mod.go @@ -1,8 +1,151 @@ package user -import "github.com/spf13/cobra" +import ( + "os" + "fmt" + "bufio" + "errors" + "strings" + "crypto/rand" + + "github.com/spf13/cobra" + "gitlab.c3sl.ufpr.br/tss24/useradm/model" +) var ModCmd = &cobra.Command{ Use: "mod", Short: "Modify user information", + RunE: modifyUserFunc, +} + +func init() { + ModCmd.Flags().StringP("grr", "r", "", "New user GRR") + ModCmd.Flags().StringP("shell", "s", "", "New user shell") + ModCmd.Flags().StringP("login", "l", "", "User login name") + ModCmd.Flags().StringP("homedir", "d", "", "New user home") + ModCmd.Flags().BoolP ("unblock", "u", false, "Unblocks the user") + ModCmd.Flags().StringP("group", "g", "", "New user initial group") + ModCmd.Flags().StringP("path", "w", "", "Create Webdir, path/login") + ModCmd.Flags().StringP("name", "n", "", "New user full name (use quotes for spaces)") + ModCmd.Flags().StringP("password", "p", "", "New password in plain text (use \"auto\" to autogenerate)") + ModCmd.Flags().BoolP ("block", "b", false, "Block the user (changes the password and sets their shell to /bin/false)") + + ModCmd.MarkFlagRequired("login") + + ModCmd.Flags().BoolP("confirm", "y", false, "Skip confirmation prompt") +} + +func modifyUserFunc(cmd *cobra.Command, args []string) error { + confirm, err := cmd.Flags().GetBool("confirm") + if err != nil { + return err + } + block, err := cmd.Flags().GetBool("block") + if err != nil { + return err + } + unblock, err := cmd.Flags().GetBool("unblock") + if err != nil { + return err + } + userNameNew, err := cmd.Flags().GetString("name") + if err != nil { + return err + } + userGroupNew, err := cmd.Flags().GetString("group") + if err != nil { + return err + } + userGRRNew, err := cmd.Flags().GetString("grr") + if err != nil { + return err + } + userPathNew, err := cmd.Flags().GetString("path") + if err != nil { + return err + } + userLogin, err := cmd.Flags().GetString("login") + if err != nil { + return err + } + userShellNew, err := cmd.Flags().GetString("shell") + if err != nil { + return err + } + userHomedirNew, err := cmd.Flags().GetString("homedir") + if err != nil { + return err + } + userPasswordNew, err := cmd.Flags().GetString("password") + if err != nil { + return err + } + if block && unblock { + return errors.New("Can't block and unblock at the same time!\n") + } + + var userStatusNew string + if block { + userShellNew = "/bin/false" + userStatusNew = "Blocked!" + userPasswordNew = "auto" + } else if unblock { + userShellNew = "/bin/bash" + userStatusNew = "Free!" + userPasswordNew = "auto" + } + + userMod := model.User{ + Name: userNameNew, + Group: userGroupNew, + GRR: userGRRNew, + Path: userPathNew, + Login: userLogin, + Shell: userShellNew, + Homedir: userHomedirNew, + Password: userPasswordNew, + Status: userStatusNew, + } + + if cmd.Flags().Changed("password") || block || unblock { + if userPasswordNew == "auto" { + userPasswordNew = generatePassword() + userMod.Password = "[auto-generated]" + } else { + userMod.Password = "[explicitly set]" + } + } else { + userMod.Password = "[unchanged]" + } + + fmt.Println(userMod.ToString()) + + if !confirm { + fmt.Print("Proceed with user update? [y/N] ") + reader := bufio.NewReader(os.Stdin) + response, _ := reader.ReadString('\n') + if strings.TrimSpace(strings.ToLower(response)) != "y" { + fmt.Fprintln(os.Stderr, "Aborted.") + os.Exit(1) + } + } + + fmt.Println("Done!") + + fmt.Println(userPasswordNew) + + return nil +} + +func generatePassword() string { + const charset = "@*()=+[];,.?123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ" + b := make([]byte, 20) + if _, err := rand.Read(b); err != nil { + panic(err) + } + for i := range b { + b[i] = charset[int(b[i])%len(charset)] + } + return string(b) } + diff --git a/model/user.go b/model/user.go index 0036ff13ed7e763f2ee7817b83e394838d635ef3..116f8e92ab8d5e5c2c9e32ff75fc400f940505f8 100644 --- a/model/user.go +++ b/model/user.go @@ -4,12 +4,13 @@ import "fmt" type User struct { GRR string - Ltype string Path string Name string + Ltype string Login string Group string Shell string + Status string Homedir string Password string } @@ -23,6 +24,7 @@ func (u *User) ToString() string { Shell: %s HomeDir: %s Password: %s - WebPath: %s`, - u.Name, u.Login, u.Ltype, u.Group, u.Shell, u.Homedir, u.Password, u.Path) + WebPath: %s + Status: %s`, + u.Name, u.Login, u.Ltype, u.Group, u.Shell, u.Homedir, u.Password, u.Path, u.Status) }