func (UserResourceHooks) Methods(res kit.Resource) []kit.Method { sendConfirmationEmail := &methods.Method{ Name: "users.send-confirmation-email", Blocking: false, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { user := r.GetUser() if user == nil { return kit.NewErrorResponse("not_authenticated", "") } if user.IsEmailConfirmed() { return kit.NewErrorResponse("email_already_confirmed", "The users email address is already confirmed") } err := registry.UserService().SendConfirmationEmail(user) if err != nil { return kit.NewErrorResponse("confirm_failed", "Could not confirm email") } return &kit.AppResponse{ Data: map[string]interface{}{"success": true}, } }, } confirmEmail := &methods.Method{ Name: "users.confirm-email", Blocking: false, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { data, ok := r.GetData().(map[string]interface{}) if !ok { return kit.NewErrorResponse("invalid_data", "Expected data dict with 'token' key") } token, ok := data["token"].(string) if !ok { return kit.NewErrorResponse("invalid_data", "Expected 'token' string key in data") } if token == "" { return kit.NewErrorResponse("empty_token", "") } _, err := registry.UserService().ConfirmEmail(token) if err != nil { return kit.NewErrorResponse("confirm_failed", "Could not confirm email") } return &kit.AppResponse{ Data: map[string]interface{}{"success": true}, } }, } requestPwReset := &methods.Method{ Name: "users.request-password-reset", Blocking: false, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { data, ok := r.GetData().(map[string]interface{}) if !ok { return kit.NewErrorResponse("invalid_data", "Expected data dict with 'user' key", true) } userIdentifier, ok := data["user"].(string) if !ok { return kit.NewErrorResponse("invalid_data", "Expected data dict with 'user' string key", true) } rawUser, err := res.Q().Filter("email", userIdentifier).Or("username", userIdentifier).First() if err != nil { return kit.NewErrorResponse(err) } if rawUser == nil { return kit.NewErrorResponse("unknown_user", fmt.Sprintf("The user %v does not exist", userIdentifier), true) } user := rawUser.(kit.User) err = registry.UserService().SendPasswordResetEmail(user) if err != nil { registry.Logger().Errorf("Could not send password reset email for user %v: %v", user, err) return kit.NewErrorResponse("reset_email_send_failed", "Could not send the reset password mail.", true) } return &kit.AppResponse{ Data: map[string]interface{}{"success": true}, } }, } pwReset := &methods.Method{ Name: "users.password-reset", Blocking: false, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { // Verify that token is in data. data, ok := r.GetData().(map[string]interface{}) if !ok { return kit.NewErrorResponse("invalid_data", "Expected 'token' key in data", true) } token, ok := data["token"].(string) if !ok { return kit.NewErrorResponse("invalid_data", "Expected 'token' string key in data", true) } if token == "" { return kit.NewErrorResponse("empty_token", "", true) } // Verify that password is in data. newPw, ok := data["password"].(string) if !ok { return kit.NewErrorResponse("invalid_passord", "Expected 'password' string key in data", true) } if newPw == "" { return kit.NewErrorResponse("empty_password", "Password may not be empty", true) } user, err := registry.UserService().ResetPassword(token, newPw) if err != nil { if err.IsPublic() { return kit.NewErrorResponse(err) } else { return kit.NewErrorResponse("password_reset_failed", "Could not reset the password.", true) } } return &kit.AppResponse{ Data: map[string]interface{}{ "success": true, "userId": user.GetId(), "userEmail": user.GetEmail(), }, } }, } changePassword := &methods.Method{ Name: "users.change-password", Blocking: false, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { // Get userId and password from request. userId := utils.GetMapStringKey(r.GetData(), "userId") if userId == "" { return kit.NewErrorResponse("no_userid", "Expected userId key in data", true) } password := utils.GetMapStringKey(r.GetData(), "password") if password == "" { return kit.NewErrorResponse("no_password", "Expected password key in data", true) } // Permission check. user := r.GetUser() if user == nil { return kit.NewErrorResponse("permission_denied", true) } // Users can only change their own password, unless they are admins. if userId != user.GetStrId() { if !(user.HasRole("admin") || user.HasPermission("users.change_passwords")) { return kit.NewErrorResponse("permission_denied", true) } } // User has the right permissions. userService := registry.UserService() // Find the user. rawUser, err := userService.UserResource().FindOne(userId) if err != nil { return kit.NewErrorResponse("db_error", true, err) } if rawUser == nil { return kit.NewErrorResponse("user_does_not_exist", true) } targetUser := rawUser.(kit.User) if err := userService.ChangePassword(targetUser, password); err != nil { return kit.NewErrorResponse(err) } // Everything worked fine. return &kit.AppResponse{ Data: map[string]interface{}{"success": true}, } }, } return []kit.Method{ AuthenticateMethod, ResumeSessionMethod, UnAuthenticateMethod, sendConfirmationEmail, confirmEmail, requestPwReset, pwReset, changePassword, } }