mirror of
https://github.com/acaloiaro/newsbox
synced 2026-07-21 10:12:26 +00:00
240 lines
6.8 KiB
Go
240 lines
6.8 KiB
Go
package actions
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gobuffalo/buffalo"
|
|
"github.com/gobuffalo/pop/v6"
|
|
"github.com/gobuffalo/x/responder"
|
|
"github.com/gofrs/uuid"
|
|
"github.com/pkg/errors"
|
|
|
|
"newsbox/internal"
|
|
"newsbox/mill"
|
|
"newsbox/models"
|
|
"newsbox/workers"
|
|
)
|
|
|
|
// Show gets the profile data for a user and renders it
|
|
func ShowProfile(c buffalo.Context) error {
|
|
// Get the DB connection from the context
|
|
tx, ok := c.Value("tx").(*pop.Connection)
|
|
if !ok {
|
|
return fmt.Errorf("no transaction found")
|
|
}
|
|
|
|
// Allocate an empty User
|
|
user := &models.User{}
|
|
ownerID := c.Session().Get("current_user_id").(uuid.UUID)
|
|
|
|
if err := tx.Eager().Find(user, ownerID); err != nil {
|
|
return c.Error(http.StatusNotFound, err)
|
|
}
|
|
|
|
loc := internal.ZoneLocation(user.Preferences.TimeZoneUtcOffset)
|
|
dt := time.Date(0000, 0, 0, user.Preferences.EmailHourOfDay, 00, 00, 00, loc).Hour()
|
|
dz := loc.String()
|
|
|
|
return responder.Wants("html", func(c buffalo.Context) error {
|
|
c.Set("user", user)
|
|
c.Set("delivery_time", dt)
|
|
c.Set("delivery_time_zone", dz)
|
|
|
|
return c.Render(http.StatusOK, r.HTML("profiles/show.plush.html"))
|
|
}).Wants("json", func(c buffalo.Context) error {
|
|
return c.Render(200, r.JSON(user))
|
|
}).Wants("xml", func(c buffalo.Context) error {
|
|
return c.Render(200, r.XML(user))
|
|
}).Respond(c)
|
|
}
|
|
|
|
// Edit renders a edit form for a user's profile
|
|
func EditProfile(c buffalo.Context) error {
|
|
// Get the DB connection from the context
|
|
tx, ok := c.Value("tx").(*pop.Connection)
|
|
if !ok {
|
|
return fmt.Errorf("no transaction found")
|
|
}
|
|
|
|
// Allocate an empty User
|
|
user := &models.User{}
|
|
ownerID := c.Session().Get("current_user_id").(uuid.UUID)
|
|
|
|
if err := tx.Eager().Find(user, ownerID); err != nil {
|
|
return c.Error(http.StatusNotFound, err)
|
|
}
|
|
|
|
c.Set("user", user)
|
|
return c.Render(http.StatusOK, r.HTML("profiles/edit.plush.html"))
|
|
}
|
|
|
|
// Update updates a user's profile in the DB
|
|
func UpdateProfile(c buffalo.Context) error {
|
|
// Get the DB connection from the context
|
|
tx, ok := c.Value("tx").(*pop.Connection)
|
|
if !ok {
|
|
return fmt.Errorf("no transaction found")
|
|
}
|
|
|
|
// Allocate an empty User
|
|
user := &models.User{}
|
|
ownerID := c.Session().Get("current_user_id").(uuid.UUID)
|
|
|
|
if err := tx.Find(user, ownerID); err != nil {
|
|
return c.Error(http.StatusNotFound, err)
|
|
}
|
|
|
|
// The user before any updates take place
|
|
origUser := *user
|
|
|
|
// Bind User to the html form elements
|
|
if err := c.Bind(user); err != nil {
|
|
return err
|
|
}
|
|
|
|
verrs, err := tx.ValidateAndSave(user)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if verrs.HasAny() {
|
|
return responder.Wants("html", func(c buffalo.Context) error {
|
|
// Make the errors available inside the html template
|
|
c.Set("errors", verrs)
|
|
|
|
// Render again the edit.html template that the user can
|
|
// correct the input.
|
|
c.Set("user", user)
|
|
|
|
return c.Render(http.StatusBadRequest, r.HTML("profiles/edit.plush.html"))
|
|
}).Wants("json", func(c buffalo.Context) error {
|
|
return c.Render(http.StatusBadRequest, r.JSON(verrs))
|
|
}).Wants("xml", func(c buffalo.Context) error {
|
|
return c.Render(http.StatusBadRequest, r.XML(verrs))
|
|
}).Respond(c)
|
|
}
|
|
|
|
verrs, err = tx.ValidateAndSave(&user.Preferences)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if verrs.HasAny() {
|
|
return responder.Wants("html", func(c buffalo.Context) error {
|
|
// Make the errors available inside the html template
|
|
c.Set("errors", verrs)
|
|
|
|
// Render again the edit.html template that the user can
|
|
// correct the input.
|
|
c.Set("user", user)
|
|
|
|
return c.Render(http.StatusBadRequest, r.HTML("profiles/edit.plush.html"))
|
|
}).Wants("json", func(c buffalo.Context) error {
|
|
return c.Render(http.StatusBadRequest, r.JSON(verrs))
|
|
}).Wants("xml", func(c buffalo.Context) error {
|
|
return c.Render(http.StatusBadRequest, r.XML(verrs))
|
|
}).Respond(c)
|
|
}
|
|
|
|
var emailChanged bool
|
|
if origUser.Email != user.Email {
|
|
// Remove any pre-existing email verifications to ensure that the user doesn't end up in an unfixiable state with
|
|
// multiple pending verifications
|
|
err = tx.RawQuery("DELETE FROM user_email_verifications WHERE owner_id = ?", user.ID).Exec()
|
|
if err != nil {
|
|
return errors.WithStack(err)
|
|
}
|
|
|
|
uev := &models.UserEmailVerification{OwnerID: user.ID}
|
|
err = tx.Save(uev)
|
|
if err != nil {
|
|
return errors.WithStack(err)
|
|
}
|
|
|
|
invitationAddr := user.Email.Interface().(string)
|
|
params := mill.EmailAddressChangeEmailJob{
|
|
Recipient: invitationAddr,
|
|
VerificationURL: fmt.Sprintf("%s/users/email_verification/%s", internal.BaseUrl(), uev.ID),
|
|
}
|
|
paramsJSON, _ := json.Marshal(params)
|
|
|
|
_, err = workers.W.EnqueueJob("email_address_changes", paramsJSON)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
emailChanged = true
|
|
}
|
|
|
|
return responder.Wants("html", func(c buffalo.Context) error {
|
|
if emailChanged {
|
|
c.Flash().Add("success", T.Translate(c, "profile.email.updated.success"))
|
|
} else {
|
|
// If there are no errors set a success message
|
|
c.Flash().Add("success", T.Translate(c, "profile.updated.success"))
|
|
}
|
|
// and redirect to the show page
|
|
return c.Redirect(http.StatusSeeOther, "/profile/")
|
|
}).Wants("json", func(c buffalo.Context) error {
|
|
return c.Render(http.StatusOK, r.JSON(user))
|
|
}).Wants("xml", func(c buffalo.Context) error {
|
|
return c.Render(http.StatusOK, r.XML(user))
|
|
}).Respond(c)
|
|
}
|
|
|
|
// UpdatePassword updates a user's password
|
|
func UpdatePassword(c buffalo.Context) error {
|
|
// Get the DB connection from the context
|
|
tx, ok := c.Value("tx").(*pop.Connection)
|
|
if !ok {
|
|
return fmt.Errorf("no transaction found")
|
|
}
|
|
|
|
// The user that will be bound to the form values
|
|
user := &models.User{}
|
|
ownerID := c.Session().Get("current_user_id").(uuid.UUID)
|
|
|
|
if err := tx.Find(user, ownerID); err != nil {
|
|
return c.Error(http.StatusNotFound, err)
|
|
}
|
|
|
|
// Bind user variable to form values
|
|
if err := c.Bind(user); err != nil {
|
|
return err
|
|
}
|
|
|
|
verrs, err := tx.ValidateAndUpdate(user)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if verrs.HasAny() {
|
|
return responder.Wants("html", func(c buffalo.Context) error {
|
|
// Make the errors available inside the html template
|
|
c.Set("errors", verrs)
|
|
|
|
// Render again the edit.html template that the user can
|
|
// correct the input.
|
|
c.Set("user", user)
|
|
|
|
return c.Render(http.StatusBadRequest, r.HTML("profiles/edit.plush.html"))
|
|
}).Wants("json", func(c buffalo.Context) error {
|
|
return c.Render(http.StatusBadRequest, r.JSON(verrs))
|
|
}).Respond(c)
|
|
}
|
|
|
|
return responder.Wants("html", func(c buffalo.Context) error {
|
|
// If there are no errors set a success message
|
|
c.Flash().Add("success", T.Translate(c, "user.updated.success"))
|
|
|
|
// and redirect to the show page
|
|
return c.Redirect(http.StatusSeeOther, "/profile/")
|
|
}).Wants("json", func(c buffalo.Context) error {
|
|
return c.Render(http.StatusOK, r.JSON(user))
|
|
}).Wants("xml", func(c buffalo.Context) error {
|
|
return c.Render(http.StatusOK, r.XML(user))
|
|
}).Respond(c)
|
|
}
|