newsbox/models/user.go
Adriano Caloiaro 8ae801ae5f
Initial commit
2023-02-15 08:57:48 -08:00

118 lines
4.5 KiB
Go

package models
import (
"encoding/json"
"log"
"strings"
"time"
"github.com/gobuffalo/nulls"
"github.com/gobuffalo/pop/v6"
"github.com/gobuffalo/validate/v3"
"github.com/gobuffalo/validate/v3/validators"
"github.com/gofrs/uuid"
"github.com/pkg/errors"
"golang.org/x/crypto/bcrypt"
)
// User is a generated model from buffalo-auth, it serves as the base for username/password authentication.
type User struct {
ID uuid.UUID `json:"id" db:"id"`
Name string `json:"name" db:"name" form:"name"`
Username string `json:"username" db:"username" form:"username"`
Email nulls.String `json:"email" db:"email" form:"email"`
PasswordHash string `json:"password_hash" db:"password_hash"`
Provider string `json:"provider" db:"provider"`
ProviderID string `json:"provider_id" db:"provider_id"`
Password string `json:"-" db:"-" form:"password"`
PasswordConfirmation string `json:"-" db:"-" form:"password_confirmation"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
EmailVerification UserEmailVerification `has_one:"user_email_verification" fk_id:"owner_id"`
Preferences UserPreference `has_one:"user_preference" fk_id:"owner_id" form:"preferences"`
}
// Create wraps up the pattern of encrypting the password and
// running validations. Useful when writing tests.
func (u *User) Create(tx *pop.Connection) (*validate.Errors, error) {
emailStr := u.Email.Interface().(string)
u.Email = nulls.NewString(strings.ToLower(emailStr))
ph, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return validate.NewErrors(), errors.WithStack(err)
}
u.PasswordHash = string(ph)
return tx.ValidateAndCreate(u)
}
// String is not required by pop and may be deleted
func (u User) String() string {
ju, _ := json.Marshal(u)
return string(ju)
}
// Users is not required by pop and may be deleted
type Users []User
// String is not required by pop and may be deleted
func (u Users) String() string {
ju, _ := json.Marshal(u)
return string(ju)
}
// Validate gets run every time you call a "pop.Validate*" (pop.ValidateAndSave, pop.ValidateAndCreate, pop.ValidateAndUpdate) method.
// This method is not required and may be deleted.
func (u *User) Validate(tx *pop.Connection) (*validate.Errors, error) {
var err error
return validate.Validate(
&validators.EmailIsPresent{Field: u.Email.Interface().(string), Name: "Email", Message: "Not a valid email address"},
&validators.FuncValidator{
Field: u.Email.Interface().(string),
Name: "Email",
Message: "%s is already taken",
Fn: func() bool {
var b bool
q := tx.Where("email = ?", u.Email)
if u.ID != uuid.Nil {
q = q.Where("id != ?", u.ID)
}
b, err = q.Exists(u)
if err != nil {
return false
}
return !b
},
},
), err
}
// ValidateCreate gets run every time you call "pop.ValidateAndCreate" method.
// This method is not required and may be deleted.
func (u *User) ValidateCreate(tx *pop.Connection) (*validate.Errors, error) {
var err error
return validate.Validate(
&validators.StringIsPresent{Field: u.Password, Name: "Password"},
&validators.StringsMatch{Name: "Password", Field: u.Password, Field2: u.PasswordConfirmation, Message: "Password does not match confirmation"},
), err
}
// ValidateUpdate gets run every time you call "pop.ValidateAndUpdate" method.
// This method is not required and may be deleted.
func (u *User) ValidateUpdate(tx *pop.Connection) (*validate.Errors, error) {
log.Println(u.Preferences)
if u.Password != "" || u.PasswordConfirmation != "" {
ph, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return validate.NewErrors(), errors.WithStack(err)
}
u.PasswordHash = string(ph)
return validate.Validate(
&validators.StringIsPresent{Field: u.Password, Name: "Password", Message: "Password must not be empty"},
&validators.StringIsPresent{Field: u.PasswordConfirmation, Name: "PasswordConfirmation", Message: "Confirmation must be present"},
&validators.StringsMatch{Name: "Password", Field: u.Password, Field2: u.PasswordConfirmation, Message: "Password does not match confirmation"},
), nil
}
return validate.NewErrors(), nil
}