Add password reset service
This commit is contained in:
@@ -3,6 +3,8 @@ package controllers
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
userctx "git.kealoha.me/lks/lenslocked/context"
|
||||
"git.kealoha.me/lks/lenslocked/models"
|
||||
@@ -12,11 +14,16 @@ import (
|
||||
|
||||
type Users struct {
|
||||
Templates struct {
|
||||
Signup Template
|
||||
Signin Template
|
||||
Signup Template
|
||||
Signin Template
|
||||
ForgotPass Template
|
||||
ResetUrlSent Template
|
||||
ResetPass Template
|
||||
}
|
||||
UserService *models.UserService
|
||||
SessionService *models.SessionService
|
||||
UserService *models.UserService
|
||||
SessionService *models.SessionService
|
||||
PassResetService *models.PasswordResetService
|
||||
EmailService *models.EmailService
|
||||
}
|
||||
|
||||
func (u Users) GetSignup(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -114,6 +121,87 @@ func (u Users) GetSignout(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/signin", http.StatusFound)
|
||||
}
|
||||
|
||||
func (u Users) GetForgotPassword(w http.ResponseWriter, r *http.Request) {
|
||||
var data struct {
|
||||
Email string
|
||||
}
|
||||
data.Email = r.FormValue("email")
|
||||
u.Templates.ForgotPass.Execute(w, r, data)
|
||||
}
|
||||
|
||||
func (u Users) PostForgotPassword(w http.ResponseWriter, r *http.Request) {
|
||||
var data struct {
|
||||
Email string
|
||||
}
|
||||
data.Email = r.FormValue("email")
|
||||
pwReset, err := u.PassResetService.Create(data.Email)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
vals := url.Values{
|
||||
"token": {pwReset.Token},
|
||||
}
|
||||
// TODO: Make the URL here configurable and use https
|
||||
resetURL := "http://" + r.Host + "/reset-pw?" + vals.Encode()
|
||||
fmt.Println(resetURL)
|
||||
err = u.EmailService.SendPasswordReset(data.Email, resetURL)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
u.Templates.ResetUrlSent.Execute(w, r, data)
|
||||
}
|
||||
|
||||
func (u Users) GetResetPass(w http.ResponseWriter, r *http.Request) {
|
||||
var data struct {
|
||||
Token string
|
||||
}
|
||||
data.Token = r.FormValue("token")
|
||||
u.Templates.ResetPass.Execute(w, r, data)
|
||||
}
|
||||
func (u Users) PostResetPass(w http.ResponseWriter, r *http.Request) {
|
||||
var data struct {
|
||||
Token, Password string
|
||||
}
|
||||
data.Token = r.FormValue("token")
|
||||
data.Password = r.FormValue("password")
|
||||
|
||||
user, err := u.PassResetService.Consume(data.Token)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
// TODO: Distinguish between server errors and invalid token errors.
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
err = u.UserService.UpdatePassword(user.ID, data.Password)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Sign the user in now that they have reset their password.
|
||||
// Any errors from this point onward should redirect to the sign in page.
|
||||
session, err := u.SessionService.Create(user.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
http.Redirect(w, r, "/signin", http.StatusFound)
|
||||
return
|
||||
}
|
||||
//setCookie(w, CookieSession, session.Token)
|
||||
cookie := http.Cookie{
|
||||
Name: "session",
|
||||
Value: session.Token,
|
||||
Path: "/",
|
||||
HttpOnly: true,
|
||||
}
|
||||
http.SetCookie(w, &cookie)
|
||||
http.Redirect(w, r, "/users/me", http.StatusFound)
|
||||
}
|
||||
|
||||
func (u Users) CurrentUser(w http.ResponseWriter, r *http.Request) {
|
||||
user := userctx.User(r.Context())
|
||||
if user == nil {
|
||||
@@ -123,18 +211,32 @@ func (u Users) CurrentUser(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Current user: %s\n", user.Email)
|
||||
}
|
||||
|
||||
func WithTemplates(user_service *models.UserService, session_service *models.SessionService, signup Template, signin Template) Users {
|
||||
func WithTemplates(user_service *models.UserService, session_service *models.SessionService, email_service *models.EmailService, signup, signin, forgotPass, resetUrlSent, resetPass Template) Users {
|
||||
u := Users{}
|
||||
|
||||
u.Templates.Signup = signup
|
||||
u.Templates.Signin = signin
|
||||
u.Templates.ForgotPass = forgotPass
|
||||
u.Templates.ResetUrlSent = resetUrlSent
|
||||
u.Templates.ResetPass = resetPass
|
||||
|
||||
u.UserService = user_service
|
||||
u.SessionService = session_service
|
||||
u.EmailService = email_service
|
||||
u.PassResetService = &models.PasswordResetService{
|
||||
DB: u.UserService.DB,
|
||||
Duration: time.Hour / 2,
|
||||
}
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
func Default(user_service *models.UserService, session_service *models.SessionService) Users {
|
||||
func Default(user_service *models.UserService, session_service *models.SessionService, email_service *models.EmailService) Users {
|
||||
signup_tpl := views.Must(views.FromFS(templates.FS, "signup.gohtml", "tailwind.gohtml"))
|
||||
signin_tpl := views.Must(views.FromFS(templates.FS, "signin.gohtml", "tailwind.gohtml"))
|
||||
pwReset_tpl := views.Must(views.FromFS(templates.FS, "pwReset.gohtml", "tailwind.gohtml"))
|
||||
pwResetSent_tpl := views.Must(views.FromFS(templates.FS, "pwResetSent.gohtml", "tailwind.gohtml"))
|
||||
resetPass_tpl := views.Must(views.FromFS(templates.FS, "pwChange.gohtml", "tailwind.gohtml"))
|
||||
|
||||
err := signup_tpl.TestTemplate(nil)
|
||||
if err != nil {
|
||||
@@ -144,6 +246,14 @@ func Default(user_service *models.UserService, session_service *models.SessionSe
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = pwReset_tpl.TestTemplate(nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = pwResetSent_tpl.TestTemplate(nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return WithTemplates(user_service, session_service, signup_tpl, signin_tpl)
|
||||
return WithTemplates(user_service, session_service, email_service, signup_tpl, signin_tpl, pwReset_tpl, pwResetSent_tpl, resetPass_tpl)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user