Creating backend to handler password resets
This commit is contained in:
		@ -14,6 +14,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/go-chi/chi/v5"
 | 
						"github.com/go-chi/chi/v5"
 | 
				
			||||||
	"github.com/stripe/stripe-go/v79"
 | 
						"github.com/stripe/stripe-go/v79"
 | 
				
			||||||
 | 
						"golang.org/x/crypto/bcrypt"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type stripePayload struct {
 | 
					type stripePayload struct {
 | 
				
			||||||
@ -465,3 +466,45 @@ func (app *application) SendPasswordResetEmail(w http.ResponseWriter, r *http.Re
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	app.writeJSON(w, http.StatusCreated, resp)
 | 
						app.writeJSON(w, http.StatusCreated, resp)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (app *application) ResetPassword(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						var payload struct {
 | 
				
			||||||
 | 
							Email    string `json:"email"`
 | 
				
			||||||
 | 
							Password string `json:"password"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := app.readJSON(w, r, &payload)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							app.errorLog.Println(err)
 | 
				
			||||||
 | 
							app.badRequest(w, r, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						user, err := app.DB.GetUserByEmail(payload.Email)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							app.errorLog.Println(err)
 | 
				
			||||||
 | 
							app.badRequest(w, r, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						newHash, err := bcrypt.GenerateFromPassword([]byte(payload.Password), 12)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							app.errorLog.Println(err)
 | 
				
			||||||
 | 
							app.badRequest(w, r, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = app.DB.UpdatePasswordForUser(user, string(newHash))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							app.badRequest(w, r, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var resp struct {
 | 
				
			||||||
 | 
							Error   bool   `json:"error"`
 | 
				
			||||||
 | 
							Message string `json:"message"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						resp.Error = false
 | 
				
			||||||
 | 
						resp.Message = "Password reset."
 | 
				
			||||||
 | 
						app.writeJSON(w, http.StatusCreated, resp)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -27,13 +27,14 @@ func (app *application) routes() http.Handler {
 | 
				
			|||||||
	mux.Route("/api/admin", func(mux chi.Router) {
 | 
						mux.Route("/api/admin", func(mux chi.Router) {
 | 
				
			||||||
		mux.Use(app.Auth)
 | 
							mux.Use(app.Auth)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mux.Get("/test", func(w http.ResponseWriter, r *http.Request) {
 | 
							// mux.Get("/test", func(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
			w.Write([]byte("got in"))
 | 
							// 	w.Write([]byte("got in"))
 | 
				
			||||||
		})
 | 
							// })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mux.Post("/virtual-terminal-succeeded", app.VirtualTerminalPaymentSucceeded)
 | 
							mux.Post("/virtual-terminal-succeeded", app.VirtualTerminalPaymentSucceeded)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	mux.Post("/api/forgot-password", app.SendPasswordResetEmail)
 | 
						mux.Post("/api/forgot-password", app.SendPasswordResetEmail)
 | 
				
			||||||
 | 
						mux.Post("/api/reset-password", app.ResetPassword)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return mux
 | 
						return mux
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,7 @@
 | 
				
			|||||||
        <p>
 | 
					        <p>
 | 
				
			||||||
            <a href="{{.Link}}">{{.Link}}</a>
 | 
					            <a href="{{.Link}}">{{.Link}}</a>
 | 
				
			||||||
        </p>
 | 
					        </p>
 | 
				
			||||||
 | 
					        <p>This link expires in 10 minutes.</p>
 | 
				
			||||||
        <p>
 | 
					        <p>
 | 
				
			||||||
            --
 | 
					            --
 | 
				
			||||||
            <br>
 | 
					            <br>
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,8 @@ Click on the link below to get started:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
{{.Link}}
 | 
					{{.Link}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This link expires in 10 minutes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--
 | 
					--
 | 
				
			||||||
Widget Co.
 | 
					Widget Co.
 | 
				
			||||||
{{ end }}
 | 
					{{ end }}
 | 
				
			||||||
 | 
				
			|||||||
@ -340,6 +340,13 @@ func (app *application) ShowResetPassword(w http.ResponseWriter, r *http.Request
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// make sure not expired
 | 
				
			||||||
 | 
						expired := signer.Expired(testURL, 10)
 | 
				
			||||||
 | 
						if expired {
 | 
				
			||||||
 | 
							app.errorLog.Println("Link expired")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data := make(map[string]interface{})
 | 
						data := make(map[string]interface{})
 | 
				
			||||||
	data["email"] = r.URL.Query().Get("email")
 | 
						data["email"] = r.URL.Query().Get("email")
 | 
				
			||||||
	if err := app.renderTemplate(w, r, "reset-password", &templateData{
 | 
						if err := app.renderTemplate(w, r, "reset-password", &templateData{
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,7 @@ Reset Password
 | 
				
			|||||||
<script type="module">
 | 
					<script type="module">
 | 
				
			||||||
    import {reset} from "/static/js/login.js"
 | 
					    import {reset} from "/static/js/login.js"
 | 
				
			||||||
    document.getElementById("reset-btn").addEventListener("click", () => {
 | 
					    document.getElementById("reset-btn").addEventListener("click", () => {
 | 
				
			||||||
        reset({{.API}});
 | 
					        reset({{.API}}, {{index .Data "email"}});
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
{{end}}
 | 
					{{end}}
 | 
				
			||||||
 | 
				
			|||||||
@ -280,3 +280,16 @@ func (m *DBModel) Authenticate(email, password string) (int, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return id, nil
 | 
						return id, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *DBModel) UpdatePasswordForUser(u User, hash string) error {
 | 
				
			||||||
 | 
						ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
 | 
				
			||||||
 | 
						defer cancel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stmt := `UPDATE users SET password = ? where id = ?`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := m.DB.ExecContext(ctx, stmt, hash, u.ID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -81,7 +81,7 @@ export function forgot(api) {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function reset(api) {
 | 
					export function reset(api, email) {
 | 
				
			||||||
    let form = document.getElementById("reset-form");
 | 
					    let form = document.getElementById("reset-form");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (form.checkValidity() === false) {
 | 
					    if (form.checkValidity() === false) {
 | 
				
			||||||
@ -98,7 +98,8 @@ export function reset(api) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let payload = {
 | 
					    let payload = {
 | 
				
			||||||
        email: document.getElementById("email").value,
 | 
					        password: document.getElementById("password").value,
 | 
				
			||||||
 | 
					        email: email,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const requestOptions = {
 | 
					    const requestOptions = {
 | 
				
			||||||
@ -116,6 +117,9 @@ export function reset(api) {
 | 
				
			|||||||
            console.log(response)
 | 
					            console.log(response)
 | 
				
			||||||
            if (response.error === false) {
 | 
					            if (response.error === false) {
 | 
				
			||||||
                showSuccess("reset-messages", "Password reset")
 | 
					                showSuccess("reset-messages", "Password reset")
 | 
				
			||||||
 | 
					                setTimeout(function () {
 | 
				
			||||||
 | 
					                    location.href = "/login"
 | 
				
			||||||
 | 
					                }, 2000)
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                showError("reset-messages", response.message)
 | 
					                showError("reset-messages", response.message)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user