171 lines
5.9 KiB
Go
171 lines
5.9 KiB
Go
package web
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"gardomatic.kleiax.de/lib/client"
|
|
"github.com/julienschmidt/httprouter"
|
|
)
|
|
|
|
type accountForm struct {
|
|
CSRFToken string `form:"csrf_token"`
|
|
Name string `form:"name"`
|
|
Color string `form:"color"`
|
|
Email string `form:"email"`
|
|
CurrentPassword string `form:"current_password"`
|
|
NewPassword string `form:"new_password"`
|
|
NewPasswordConfirmation string `form:"new_password_confirmation"`
|
|
Errors map[string]string
|
|
Message string
|
|
}
|
|
|
|
func (app *application) account(w http.ResponseWriter, r *http.Request) {
|
|
user, _ := userFromContext(r.Context())
|
|
app.renderAccount(w, r, accountForm{Name: user.Name, Color: user.Color, Email: user.Email, Errors: map[string]string{}}, http.StatusOK)
|
|
}
|
|
|
|
func (app *application) accountSessionDeletePost(w http.ResponseWriter, r *http.Request) {
|
|
id := httprouter.ParamsFromContext(r.Context()).ByName("sessionID")
|
|
response, err := client.FromContext(r.Context()).DeleteAccountSession(r.Context(), id)
|
|
if err != nil {
|
|
app.handleAPIError(w, r, err)
|
|
return
|
|
}
|
|
client.ForwardCookies(w, response)
|
|
http.Redirect(w, r, webPath("account")+gardenQuerySuffix(r), http.StatusSeeOther)
|
|
}
|
|
func (app *application) accountProfilePost(w http.ResponseWriter, r *http.Request) {
|
|
var form accountForm
|
|
if err := app.decodePostForm(r, &form); err != nil {
|
|
app.clientError(w, http.StatusBadRequest)
|
|
return
|
|
}
|
|
form.Name = strings.TrimSpace(form.Name)
|
|
form.Color = strings.TrimSpace(form.Color)
|
|
form.Errors = map[string]string{}
|
|
if form.Name == "" {
|
|
form.Errors["name"] = "Ein Name ist erforderlich."
|
|
}
|
|
if len(form.Errors) == 0 {
|
|
user, _, err := client.FromContext(r.Context()).UpdateAccountProfile(r.Context(), form.Name, form.Color)
|
|
if err == nil {
|
|
form.Name, form.Color, form.Email, form.Message = user.Name, user.Color, user.Email, "Profil gespeichert."
|
|
app.renderAccount(w, r, form, http.StatusOK)
|
|
return
|
|
}
|
|
app.copyAccountError(&form, err)
|
|
if len(form.Errors) == 0 {
|
|
app.handleAPIError(w, r, err)
|
|
return
|
|
}
|
|
}
|
|
app.renderAccount(w, r, form, http.StatusUnprocessableEntity)
|
|
}
|
|
func (app *application) accountPasswordPost(w http.ResponseWriter, r *http.Request) {
|
|
var form accountForm
|
|
if err := app.decodePostForm(r, &form); err != nil {
|
|
app.clientError(w, http.StatusBadRequest)
|
|
return
|
|
}
|
|
user, _ := userFromContext(r.Context())
|
|
form.Name, form.Color, form.Email, form.Errors = user.Name, user.Color, user.Email, map[string]string{}
|
|
if form.NewPassword != form.NewPasswordConfirmation {
|
|
form.Errors["new_password_confirmation"] = "Die Passwörter stimmen nicht überein."
|
|
}
|
|
if len(form.NewPassword) < 8 {
|
|
form.Errors["new_password"] = "Mindestens 8 Zeichen erforderlich."
|
|
}
|
|
if len(form.Errors) == 0 {
|
|
_, err := client.FromContext(r.Context()).UpdateAccountPassword(r.Context(), form.CurrentPassword, form.NewPassword)
|
|
if err == nil {
|
|
form.CurrentPassword, form.NewPassword, form.NewPasswordConfirmation = "", "", ""
|
|
form.Message = "Passwort geändert."
|
|
app.renderAccount(w, r, form, http.StatusOK)
|
|
return
|
|
}
|
|
app.copyAccountError(&form, err)
|
|
if len(form.Errors) == 0 {
|
|
app.handleAPIError(w, r, err)
|
|
return
|
|
}
|
|
}
|
|
app.renderAccount(w, r, form, http.StatusUnprocessableEntity)
|
|
}
|
|
func (app *application) accountEmailPost(w http.ResponseWriter, r *http.Request) {
|
|
var form accountForm
|
|
if err := app.decodePostForm(r, &form); err != nil {
|
|
app.clientError(w, http.StatusBadRequest)
|
|
return
|
|
}
|
|
user, _ := userFromContext(r.Context())
|
|
form.Name, form.Color, form.Errors = user.Name, user.Color, map[string]string{}
|
|
form.Email = strings.TrimSpace(form.Email)
|
|
if form.Email == "" {
|
|
form.Errors["email"] = "Eine E-Mail-Adresse ist erforderlich."
|
|
}
|
|
if len(form.Errors) == 0 {
|
|
_, err := client.FromContext(r.Context()).RequestAccountEmailChange(r.Context(), form.Email, form.CurrentPassword)
|
|
if err == nil {
|
|
form.CurrentPassword = ""
|
|
form.Message = "Bestätigungslink wurde an die neue Adresse gesendet."
|
|
app.renderAccount(w, r, form, http.StatusOK)
|
|
return
|
|
}
|
|
app.copyAccountError(&form, err)
|
|
if len(form.Errors) == 0 {
|
|
app.handleAPIError(w, r, err)
|
|
return
|
|
}
|
|
}
|
|
app.renderAccount(w, r, form, http.StatusUnprocessableEntity)
|
|
}
|
|
func (app *application) accountEmailConfirm(w http.ResponseWriter, r *http.Request) {
|
|
data := app.newTemplateData(r)
|
|
data.Form = acceptInviteForm{Token: r.URL.Query().Get("token")}
|
|
app.render(w, http.StatusOK, "email_confirm.tmpl", data)
|
|
}
|
|
func (app *application) accountEmailConfirmPost(w http.ResponseWriter, r *http.Request) {
|
|
var form acceptInviteForm
|
|
if err := app.decodePostForm(r, &form); err != nil {
|
|
app.clientError(w, http.StatusBadRequest)
|
|
return
|
|
}
|
|
if _, _, err := client.FromContext(r.Context()).ConfirmAccountEmail(r.Context(), form.Token); err != nil {
|
|
app.handleAPIError(w, r, err)
|
|
return
|
|
}
|
|
http.Redirect(w, r, webPath("account"), http.StatusSeeOther)
|
|
}
|
|
func (app *application) renderAccount(w http.ResponseWriter, r *http.Request, form accountForm, status int) {
|
|
data := app.newTemplateData(r)
|
|
data.Form = form
|
|
if user, ok := userFromContext(r.Context()); ok {
|
|
data.AccountProtected = app.config.DemoAccountEmail != "" && strings.EqualFold(strings.TrimSpace(user.Email), app.config.DemoAccountEmail)
|
|
}
|
|
if !app.loadOptionalGarden(w, r, data) {
|
|
return
|
|
}
|
|
if !data.AccountProtected {
|
|
sessions, _, err := client.FromContext(r.Context()).AccountSessions(r.Context())
|
|
if err != nil {
|
|
app.handleAPIError(w, r, err)
|
|
return
|
|
}
|
|
data.AccountSessions = sessions
|
|
}
|
|
app.render(w, status, "account.tmpl", data)
|
|
}
|
|
func (app *application) copyAccountError(form *accountForm, err error) {
|
|
var apiError *client.APIError
|
|
if errors.As(err, &apiError) {
|
|
if apiError.StatusCode == http.StatusUnprocessableEntity {
|
|
form.Errors = apiError.Validation
|
|
}
|
|
if apiError.StatusCode == http.StatusUnauthorized {
|
|
form.Errors["current_password"] = "Das aktuelle Passwort ist falsch."
|
|
}
|
|
}
|
|
}
|