2016-02-01 12:59:10 +01:00
package controllers
import (
"bytes"
2016-02-24 07:31:52 +01:00
"net/http"
2016-02-01 12:59:10 +01:00
"os"
"regexp"
"text/template"
2016-06-16 08:10:35 +02:00
"github.com/astaxie/beego"
2016-02-01 12:59:10 +01:00
"github.com/vmware/harbor/dao"
"github.com/vmware/harbor/models"
"github.com/vmware/harbor/utils"
2016-03-30 14:49:43 +02:00
"github.com/vmware/harbor/utils/log"
2016-02-01 12:59:10 +01:00
)
2016-02-26 11:35:55 +01:00
type messageDetail struct {
2016-02-01 12:59:10 +01:00
Hint string
2016-02-25 07:00:29 +01:00
URL string
UUID string
2016-02-01 12:59:10 +01:00
}
2016-02-26 11:35:55 +01:00
// SendEmail verifies the Email address and contact SMTP server to send reset password Email.
2016-02-25 07:00:29 +01:00
func ( cc * CommonController ) SendEmail ( ) {
2016-02-01 12:59:10 +01:00
2016-02-25 07:00:29 +01:00
email := cc . GetString ( "email" )
2016-02-01 12:59:10 +01:00
2016-02-23 21:02:08 +01:00
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 )
if ! pass {
2016-02-25 07:00:29 +01:00
cc . CustomAbort ( http . StatusBadRequest , "email_content_illegal" )
2016-02-23 21:02:08 +01:00
} else {
2016-02-01 12:59:10 +01:00
queryUser := models . User { Email : email }
exist , err := dao . UserExists ( queryUser , "email" )
if err != nil {
2016-03-30 14:49:43 +02:00
log . Errorf ( "Error occurred in UserExists: %v" , err )
2016-02-25 07:00:29 +01:00
cc . CustomAbort ( http . StatusInternalServerError , "Internal error." )
2016-02-01 12:59:10 +01:00
}
if ! exist {
2016-02-25 07:00:29 +01:00
cc . CustomAbort ( http . StatusNotFound , "email_does_not_exist" )
2016-02-01 12:59:10 +01:00
}
messageTemplate , err := template . ParseFiles ( "views/reset-password-mail.tpl" )
if err != nil {
2016-03-30 14:49:43 +02:00
log . Errorf ( "Parse email template file failed: %v" , err )
2016-02-25 07:00:29 +01:00
cc . CustomAbort ( http . StatusInternalServerError , err . Error ( ) )
2016-02-01 12:59:10 +01:00
}
message := new ( bytes . Buffer )
2016-02-25 07:00:29 +01:00
harborURL := os . Getenv ( "HARBOR_URL" )
if harborURL == "" {
harborURL = "localhost"
2016-02-01 12:59:10 +01:00
}
uuid , err := dao . GenerateRandomString ( )
if err != nil {
2016-03-30 14:49:43 +02:00
log . Errorf ( "Error occurred in GenerateRandomString: %v" , err )
2016-02-25 07:00:29 +01:00
cc . CustomAbort ( http . StatusInternalServerError , "Internal error." )
2016-02-01 12:59:10 +01:00
}
2016-02-26 11:35:55 +01:00
err = messageTemplate . Execute ( message , messageDetail {
2016-06-23 12:15:58 +02:00
Hint : cc . Tr ( "Warning: You're receiving this because you're requesting for changing password in Harbor, if it is not your operation, please ignore; otherwise, please click the link below" ) ,
2016-02-25 07:00:29 +01:00
URL : harborURL ,
UUID : uuid ,
2016-02-01 12:59:10 +01:00
} )
if err != nil {
2016-03-30 14:49:43 +02:00
log . Errorf ( "Message template error: %v" , err )
2016-02-25 07:00:29 +01:00
cc . CustomAbort ( http . StatusInternalServerError , "internal_error" )
2016-02-01 12:59:10 +01:00
}
config , err := beego . AppConfig . GetSection ( "mail" )
if err != nil {
2016-03-30 14:49:43 +02:00
log . Errorf ( "Can not load app.conf: %v" , err )
2016-02-25 07:00:29 +01:00
cc . CustomAbort ( http . StatusInternalServerError , "internal_error" )
2016-02-01 12:59:10 +01:00
}
mail := utils . Mail {
From : config [ "from" ] ,
To : [ ] string { email } ,
2016-02-25 07:00:29 +01:00
Subject : cc . Tr ( "reset_email_subject" ) ,
2016-02-01 12:59:10 +01:00
Message : message . String ( ) }
err = mail . SendMail ( )
if err != nil {
2016-03-30 14:49:43 +02:00
log . Errorf ( "Send email failed: %v" , err )
2016-02-25 07:00:29 +01:00
cc . CustomAbort ( http . StatusInternalServerError , "send_email_failed" )
2016-02-01 12:59:10 +01:00
}
2016-02-26 03:15:01 +01:00
user := models . User { ResetUUID : uuid , Email : email }
2016-02-26 04:26:54 +01:00
dao . UpdateUserResetUUID ( user )
2016-02-01 12:59:10 +01:00
}
}
2016-06-16 08:10:35 +02:00
// ForgotPasswordController handles requests to /forgot_password
type ForgotPasswordController struct {
BaseController
}
// Get renders forgot password page
func ( fpc * ForgotPasswordController ) Get ( ) {
fpc . Forward ( "Forgot Password" , "forgot-password.htm" )
}
2016-02-26 11:35:55 +01:00
// ResetPasswordController handles request to /resetPassword
2016-02-01 12:59:10 +01:00
type ResetPasswordController struct {
BaseController
}
2016-02-26 11:35:55 +01:00
// Get checks if reset_uuid in the reset link is valid and render the result page for user to reset password.
2016-02-01 12:59:10 +01:00
func ( rpc * ResetPasswordController ) Get ( ) {
2016-02-25 07:00:29 +01:00
resetUUID := rpc . GetString ( "reset_uuid" )
if resetUUID == "" {
2016-03-30 14:49:43 +02:00
log . Error ( "Reset uuid is blank." )
2016-02-24 07:31:52 +01:00
rpc . Redirect ( "/" , http . StatusFound )
2016-02-25 04:48:22 +01:00
return
2016-02-23 21:02:08 +01:00
}
2016-02-26 03:15:01 +01:00
queryUser := models . User { ResetUUID : resetUUID }
2016-02-01 12:59:10 +01:00
user , err := dao . GetUser ( queryUser )
if err != nil {
2016-03-30 14:49:43 +02:00
log . Errorf ( "Error occurred in GetUser: %v" , err )
2016-02-24 07:31:52 +01:00
rpc . CustomAbort ( http . StatusInternalServerError , "Internal error." )
2016-02-01 12:59:10 +01:00
}
if user != nil {
2016-02-26 03:15:01 +01:00
rpc . Data [ "ResetUuid" ] = user . ResetUUID
2016-06-16 08:10:35 +02:00
rpc . Forward ( "Reset Password" , "reset-password.htm" )
2016-02-01 12:59:10 +01:00
} else {
2016-02-24 07:31:52 +01:00
rpc . Redirect ( "/" , http . StatusFound )
2016-02-01 12:59:10 +01:00
}
}
2016-02-26 11:35:55 +01:00
// ResetPassword handles request from the reset page and reset password
2016-02-25 07:00:29 +01:00
func ( cc * CommonController ) ResetPassword ( ) {
2016-02-01 12:59:10 +01:00
2016-02-25 07:00:29 +01:00
resetUUID := cc . GetString ( "reset_uuid" )
if resetUUID == "" {
cc . CustomAbort ( http . StatusBadRequest , "Reset uuid is blank." )
2016-02-23 21:02:08 +01:00
}
2016-02-01 12:59:10 +01:00
2016-02-26 03:15:01 +01:00
queryUser := models . User { ResetUUID : resetUUID }
2016-02-01 12:59:10 +01:00
user , err := dao . GetUser ( queryUser )
if err != nil {
2016-03-30 14:49:43 +02:00
log . Errorf ( "Error occurred in GetUser: %v" , err )
2016-02-25 07:00:29 +01:00
cc . CustomAbort ( http . StatusInternalServerError , "Internal error." )
2016-02-01 12:59:10 +01:00
}
2016-02-23 21:02:08 +01:00
if user == nil {
2016-03-30 14:49:43 +02:00
log . Error ( "User does not exist" )
2016-02-25 07:00:29 +01:00
cc . CustomAbort ( http . StatusBadRequest , "User does not exist" )
2016-02-23 21:02:08 +01:00
}
2016-02-01 12:59:10 +01:00
2016-02-25 07:00:29 +01:00
password := cc . GetString ( "password" )
2016-02-01 12:59:10 +01:00
if password != "" {
user . Password = password
2016-02-24 13:44:46 +01:00
err = dao . ResetUserPassword ( * user )
if err != nil {
2016-03-30 14:49:43 +02:00
log . Errorf ( "Error occurred in ResetUserPassword: %v" , err )
2016-02-25 07:00:29 +01:00
cc . CustomAbort ( http . StatusInternalServerError , "Internal error." )
2016-02-24 13:44:46 +01:00
}
2016-02-01 12:59:10 +01:00
} else {
2016-02-25 07:00:29 +01:00
cc . CustomAbort ( http . StatusBadRequest , "password_is_required" )
2016-02-01 12:59:10 +01:00
}
}