1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
| // models/user.go
package models
import (
"encoding/json"
"time"
"github.com/gobuffalo/pop"
"github.com/gobuffalo/uuid"
"github.com/gobuffalo/validate"
"github.com/gobuffalo/validate/validators"
"strings"
"github.com/pkg/errors"
"golang.org/x/crypto/bcrypt"
)
type User struct {
ID uuid.UUID `json:"id" db:"id"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
Email string `json:"email" db:"email"`
PasswordHash string `json:"password_hash" db:"password_hash"`
Password string `json:"-" db:"-"`
PasswordConfirmation string `json:"-" db:"-"`
}
// 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.StringIsPresent{Field: u.Email, Name: "Email"},
&validators.StringIsPresent{Field: u.PasswordHash, Name: "PasswordHash"},
// check to see if the email address is already taken:
&validators.FuncValidator{
Field: u.Email,
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) {
return validate.NewErrors(), nil
}
// 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) {
u.Email = strings.ToLower(strings.TrimSpace(u.Email))
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)
}
|