PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/controllers/password.go

https://gitlab.com/e0/harbor
Go | 201 lines | 144 code | 35 blank | 22 comment | 37 complexity | 31e5535b9356c4fa656ee27035d21545 MD5 | raw file
  1. /*
  2. Copyright (c) 2016 VMware, Inc. All Rights Reserved.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package controllers
  14. import (
  15. "bytes"
  16. "net/http"
  17. "os"
  18. "regexp"
  19. "text/template"
  20. "github.com/vmware/harbor/dao"
  21. "github.com/vmware/harbor/models"
  22. "github.com/vmware/harbor/utils"
  23. "github.com/vmware/harbor/utils/log"
  24. "github.com/astaxie/beego"
  25. )
  26. // ChangePasswordController handles request to /changePassword
  27. type ChangePasswordController struct {
  28. BaseController
  29. }
  30. // Get renders the page for user to change password.
  31. func (cpc *ChangePasswordController) Get() {
  32. sessionUserID := cpc.GetSession("userId")
  33. if sessionUserID == nil {
  34. cpc.Redirect("/signIn", http.StatusFound)
  35. return
  36. }
  37. cpc.Data["Username"] = cpc.GetSession("username")
  38. cpc.ForwardTo("page_title_change_password", "change-password")
  39. }
  40. // ForgotPasswordController handles request to /forgotPassword
  41. type ForgotPasswordController struct {
  42. BaseController
  43. }
  44. // Get Renders the page for user to input Email to reset password.
  45. func (fpc *ForgotPasswordController) Get() {
  46. fpc.ForwardTo("page_title_forgot_password", "forgot-password")
  47. }
  48. type messageDetail struct {
  49. Hint string
  50. URL string
  51. UUID string
  52. }
  53. // SendEmail verifies the Email address and contact SMTP server to send reset password Email.
  54. func (cc *CommonController) SendEmail() {
  55. email := cc.GetString("email")
  56. pass, _ := regexp.MatchString(`^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$`, email)
  57. if !pass {
  58. cc.CustomAbort(http.StatusBadRequest, "email_content_illegal")
  59. } else {
  60. queryUser := models.User{Email: email}
  61. exist, err := dao.UserExists(queryUser, "email")
  62. if err != nil {
  63. log.Errorf("Error occurred in UserExists: %v", err)
  64. cc.CustomAbort(http.StatusInternalServerError, "Internal error.")
  65. }
  66. if !exist {
  67. cc.CustomAbort(http.StatusNotFound, "email_does_not_exist")
  68. }
  69. messageTemplate, err := template.ParseFiles("views/reset-password-mail.tpl")
  70. if err != nil {
  71. log.Errorf("Parse email template file failed: %v", err)
  72. cc.CustomAbort(http.StatusInternalServerError, err.Error())
  73. }
  74. message := new(bytes.Buffer)
  75. harborURL := os.Getenv("HARBOR_URL")
  76. if harborURL == "" {
  77. harborURL = "localhost"
  78. }
  79. uuid, err := dao.GenerateRandomString()
  80. if err != nil {
  81. log.Errorf("Error occurred in GenerateRandomString: %v", err)
  82. cc.CustomAbort(http.StatusInternalServerError, "Internal error.")
  83. }
  84. err = messageTemplate.Execute(message, messageDetail{
  85. Hint: cc.Tr("reset_email_hint"),
  86. URL: harborURL,
  87. UUID: uuid,
  88. })
  89. if err != nil {
  90. log.Errorf("Message template error: %v", err)
  91. cc.CustomAbort(http.StatusInternalServerError, "internal_error")
  92. }
  93. config, err := beego.AppConfig.GetSection("mail")
  94. if err != nil {
  95. log.Errorf("Can not load app.conf: %v", err)
  96. cc.CustomAbort(http.StatusInternalServerError, "internal_error")
  97. }
  98. mail := utils.Mail{
  99. From: config["from"],
  100. To: []string{email},
  101. Subject: cc.Tr("reset_email_subject"),
  102. Message: message.String()}
  103. err = mail.SendMail()
  104. if err != nil {
  105. log.Errorf("Send email failed: %v", err)
  106. cc.CustomAbort(http.StatusInternalServerError, "send_email_failed")
  107. }
  108. user := models.User{ResetUUID: uuid, Email: email}
  109. dao.UpdateUserResetUUID(user)
  110. }
  111. }
  112. // ResetPasswordController handles request to /resetPassword
  113. type ResetPasswordController struct {
  114. BaseController
  115. }
  116. // Get checks if reset_uuid in the reset link is valid and render the result page for user to reset password.
  117. func (rpc *ResetPasswordController) Get() {
  118. resetUUID := rpc.GetString("reset_uuid")
  119. if resetUUID == "" {
  120. log.Error("Reset uuid is blank.")
  121. rpc.Redirect("/", http.StatusFound)
  122. return
  123. }
  124. queryUser := models.User{ResetUUID: resetUUID}
  125. user, err := dao.GetUser(queryUser)
  126. if err != nil {
  127. log.Errorf("Error occurred in GetUser: %v", err)
  128. rpc.CustomAbort(http.StatusInternalServerError, "Internal error.")
  129. }
  130. if user != nil {
  131. rpc.Data["ResetUuid"] = user.ResetUUID
  132. rpc.ForwardTo("page_title_reset_password", "reset-password")
  133. } else {
  134. rpc.Redirect("/", http.StatusFound)
  135. }
  136. }
  137. // ResetPassword handles request from the reset page and reset password
  138. func (cc *CommonController) ResetPassword() {
  139. resetUUID := cc.GetString("reset_uuid")
  140. if resetUUID == "" {
  141. cc.CustomAbort(http.StatusBadRequest, "Reset uuid is blank.")
  142. }
  143. queryUser := models.User{ResetUUID: resetUUID}
  144. user, err := dao.GetUser(queryUser)
  145. if err != nil {
  146. log.Errorf("Error occurred in GetUser: %v", err)
  147. cc.CustomAbort(http.StatusInternalServerError, "Internal error.")
  148. }
  149. if user == nil {
  150. log.Error("User does not exist")
  151. cc.CustomAbort(http.StatusBadRequest, "User does not exist")
  152. }
  153. password := cc.GetString("password")
  154. if password != "" {
  155. user.Password = password
  156. err = dao.ResetUserPassword(*user)
  157. if err != nil {
  158. log.Errorf("Error occurred in ResetUserPassword: %v", err)
  159. cc.CustomAbort(http.StatusInternalServerError, "Internal error.")
  160. }
  161. } else {
  162. cc.CustomAbort(http.StatusBadRequest, "password_is_required")
  163. }
  164. }