Add password reset

This commit is contained in:
kolaente 2020-08-13 16:36:25 +02:00
parent caa6cf81f8
commit 922e688720
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
3 changed files with 73 additions and 38 deletions

View File

@ -33,10 +33,11 @@ import (
)
var (
userFlagUsername string
userFlagEmail string
userFlagPassword string
userFlagAvatar = "default"
userFlagUsername string
userFlagEmail string
userFlagPassword string
userFlagAvatar = "default"
userFlagResetPasswordDirectly bool
)
func init() {
@ -53,10 +54,49 @@ func init() {
userUpdateCmd.Flags().StringVarP(&userFlagEmail, "email", "e", "", "The new email address of the user.")
userUpdateCmd.Flags().StringVarP(&userFlagAvatar, "avatar-provider", "a", "", "The new avatar provider of the new user.")
// Reset PW flags
userResetPasswordCmd.Flags().BoolVarP(&userFlagResetPasswordDirectly, "direct", "d", false, "If provided, reset the password directly instead of sending the user a reset mail.")
userResetPasswordCmd.Flags().StringVarP(&userFlagPassword, "password", "p", "", "The new password of the user. Only used in combination with --direct. You will be asked to enter it if not provided through the flag.")
userCmd.AddCommand(userListCmd, userCreateCmd, userUpdateCmd, userResetPasswordCmd, userChangeEnabledCmd)
rootCmd.AddCommand(userCmd)
}
func getPasswordFromFlagOrInput() (pw string) {
pw = userFlagPassword
if userFlagPassword == "" {
fmt.Print("Enter Password: ")
bytePW, err := terminal.ReadPassword(syscall.Stdin)
if err != nil {
log.Fatalf("Error reading password: %s", err)
}
fmt.Printf("\nConfirm Password: ")
byteConfirmPW, err := terminal.ReadPassword(syscall.Stdin)
if err != nil {
log.Fatalf("Error reading password: %s", err)
}
if string(bytePW) != string(byteConfirmPW) {
log.Critical("Passwords don't match!")
}
fmt.Printf("\n")
pw = strings.TrimSpace(string(bytePW))
}
return
}
func getUserFromArg(arg string) *user.User {
id, err := strconv.ParseInt(arg, 10, 64)
if err != nil {
log.Fatalf("Invalid user id: %s", err)
}
u, err := user.GetUserByID(id)
if err != nil {
log.Fatalf("Could not get user: %s", err)
}
return u
}
var userCmd = &cobra.Command{
Use: "user",
Short: "Manage users locally through the cli.",
@ -106,28 +146,10 @@ var userCreateCmd = &cobra.Command{
initialize.FullInit()
},
Run: func(cmd *cobra.Command, args []string) {
if userFlagPassword == "" {
fmt.Print("Enter Password: ")
bytePW, err := terminal.ReadPassword(syscall.Stdin)
if err != nil {
log.Fatalf("Error reading password: %s", err)
}
fmt.Printf("\nConfirm Password: ")
byteConfirmPW, err := terminal.ReadPassword(syscall.Stdin)
if err != nil {
log.Fatalf("Error reading password: %s", err)
}
if string(bytePW) != string(byteConfirmPW) {
log.Critical("Passwords don't match!")
}
userFlagPassword = strings.TrimSpace(string(bytePW))
}
u := &user.User{
Username: userFlagUsername,
Email: userFlagEmail,
Password: userFlagPassword,
Password: getPasswordFromFlagOrInput(),
}
_, err := user.CreateUser(u)
if err != nil {
@ -146,15 +168,7 @@ var userUpdateCmd = &cobra.Command{
initialize.FullInit()
},
Run: func(cmd *cobra.Command, args []string) {
id, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
log.Fatalf("Invalid user id: %s", err)
}
u, err := user.GetUserByID(id)
if err != nil {
log.Fatalf("Could not get user: %s", err)
}
u := getUserFromArg(args[0])
if userFlagUsername != "" {
u.Username = userFlagUsername
@ -166,7 +180,7 @@ var userUpdateCmd = &cobra.Command{
u.AvatarProvider = userFlagAvatar
}
_, err = user.UpdateUser(u)
_, err := user.UpdateUser(u)
if err != nil {
log.Fatalf("Error updating the user: %s", err)
}
@ -176,13 +190,29 @@ var userUpdateCmd = &cobra.Command{
}
var userResetPasswordCmd = &cobra.Command{
Use: "reset-password",
Use: "reset-password [user id]",
Short: "Reset a users password, either through mailing them a reset link or directly.",
PreRun: func(cmd *cobra.Command, args []string) {
initialize.FullInit()
},
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
// need flags
u := getUserFromArg(args[0])
// By default we reset as usual, only with specific flag directly.
if userFlagResetPasswordDirectly {
err := user.UpdateUserPassword(u, getPasswordFromFlagOrInput())
if err != nil {
log.Fatalf("Could not update user password: %s", err)
}
fmt.Println("Password updated successfully.")
} else {
err := user.RequestUserPasswordResetToken(u)
if err != nil {
log.Fatalf("Could not send password reset email: %s", err)
}
fmt.Println("Password reset email sent successfully.")
}
},
}

View File

@ -72,7 +72,7 @@ func UserRequestResetPasswordToken(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, err)
}
err := user.RequestUserPasswordResetToken(&pwTokenReset)
err := user.RequestUserPasswordResetTokenByEmail(&pwTokenReset)
if err != nil {
return handler.HandleHTTPError(err, c)
}

View File

@ -82,8 +82,8 @@ type PasswordTokenRequest struct {
Email string `json:"email" valid:"email,length(0|250)" maxLength:"250"`
}
// RequestUserPasswordResetToken inserts a random token to reset a users password into the databsse
func RequestUserPasswordResetToken(tr *PasswordTokenRequest) (err error) {
// RequestUserPasswordResetTokenByEmail inserts a random token to reset a users password into the databsse
func RequestUserPasswordResetTokenByEmail(tr *PasswordTokenRequest) (err error) {
if tr.Email == "" {
return ErrNoUsernamePassword{}
}
@ -94,6 +94,11 @@ func RequestUserPasswordResetToken(tr *PasswordTokenRequest) (err error) {
return
}
return RequestUserPasswordResetToken(user)
}
// RequestUserPasswordResetToken sends a user a password reset email.
func RequestUserPasswordResetToken(user *User) (err error) {
// Generate a token and save it
user.PasswordResetToken = utils.MakeRandomString(400)