Added user email verification support.

This commit is contained in:
mikestefanello 2022-01-08 15:32:18 -05:00
parent feb11bbe5b
commit ea46a38f68
31 changed files with 417 additions and 85 deletions

View file

@ -6,11 +6,10 @@ import (
"errors"
"fmt"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/user"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/user"
)
// ent aliases to avoid import conflicts in user's code.

View file

@ -6,7 +6,6 @@ import (
"context"
"github.com/mikestefanello/pagoda/ent"
// required by schema hooks.
_ "github.com/mikestefanello/pagoda/ent/runtime"

View file

@ -35,6 +35,7 @@ var (
{Name: "name", Type: field.TypeString},
{Name: "email", Type: field.TypeString, Unique: true},
{Name: "password", Type: field.TypeString},
{Name: "verified", Type: field.TypeBool, Default: false},
{Name: "created_at", Type: field.TypeTime},
}
// UsersTable holds the schema information for the "users" table.

View file

@ -452,6 +452,7 @@ type UserMutation struct {
name *string
email *string
password *string
verified *bool
created_at *time.Time
clearedFields map[string]struct{}
owner map[int]struct{}
@ -649,6 +650,42 @@ func (m *UserMutation) ResetPassword() {
m.password = nil
}
// SetVerified sets the "verified" field.
func (m *UserMutation) SetVerified(b bool) {
m.verified = &b
}
// Verified returns the value of the "verified" field in the mutation.
func (m *UserMutation) Verified() (r bool, exists bool) {
v := m.verified
if v == nil {
return
}
return *v, true
}
// OldVerified returns the old "verified" field's value of the User entity.
// If the User object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *UserMutation) OldVerified(ctx context.Context) (v bool, err error) {
if !m.op.Is(OpUpdateOne) {
return v, fmt.Errorf("OldVerified is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, fmt.Errorf("OldVerified requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldVerified: %w", err)
}
return oldValue.Verified, nil
}
// ResetVerified resets all changes to the "verified" field.
func (m *UserMutation) ResetVerified() {
m.verified = nil
}
// SetCreatedAt sets the "created_at" field.
func (m *UserMutation) SetCreatedAt(t time.Time) {
m.created_at = &t
@ -758,7 +795,7 @@ func (m *UserMutation) Type() string {
// order to get all numeric fields that were incremented/decremented, call
// AddedFields().
func (m *UserMutation) Fields() []string {
fields := make([]string, 0, 4)
fields := make([]string, 0, 5)
if m.name != nil {
fields = append(fields, user.FieldName)
}
@ -768,6 +805,9 @@ func (m *UserMutation) Fields() []string {
if m.password != nil {
fields = append(fields, user.FieldPassword)
}
if m.verified != nil {
fields = append(fields, user.FieldVerified)
}
if m.created_at != nil {
fields = append(fields, user.FieldCreatedAt)
}
@ -785,6 +825,8 @@ func (m *UserMutation) Field(name string) (ent.Value, bool) {
return m.Email()
case user.FieldPassword:
return m.Password()
case user.FieldVerified:
return m.Verified()
case user.FieldCreatedAt:
return m.CreatedAt()
}
@ -802,6 +844,8 @@ func (m *UserMutation) OldField(ctx context.Context, name string) (ent.Value, er
return m.OldEmail(ctx)
case user.FieldPassword:
return m.OldPassword(ctx)
case user.FieldVerified:
return m.OldVerified(ctx)
case user.FieldCreatedAt:
return m.OldCreatedAt(ctx)
}
@ -834,6 +878,13 @@ func (m *UserMutation) SetField(name string, value ent.Value) error {
}
m.SetPassword(v)
return nil
case user.FieldVerified:
v, ok := value.(bool)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetVerified(v)
return nil
case user.FieldCreatedAt:
v, ok := value.(time.Time)
if !ok {
@ -899,6 +950,9 @@ func (m *UserMutation) ResetField(name string) error {
case user.FieldPassword:
m.ResetPassword()
return nil
case user.FieldVerified:
m.ResetVerified()
return nil
case user.FieldCreatedAt:
m.ResetCreatedAt()
return nil

View file

@ -7,10 +7,9 @@ import (
"strings"
"time"
"entgo.io/ent/dialect/sql"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/user"
"entgo.io/ent/dialect/sql"
)
// PasswordToken is the model entity for the PasswordToken schema.

View file

@ -5,10 +5,9 @@ package passwordtoken
import (
"time"
"github.com/mikestefanello/pagoda/ent/predicate"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/mikestefanello/pagoda/ent/predicate"
)
// ID filters vertices based on their ID field.

View file

@ -8,11 +8,10 @@ import (
"fmt"
"time"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/user"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/user"
)
// PasswordTokenCreate is the builder for creating a PasswordToken entity.

View file

@ -6,12 +6,11 @@ import (
"context"
"fmt"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/predicate"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/predicate"
)
// PasswordTokenDelete is the builder for deleting a PasswordToken entity.

View file

@ -8,13 +8,12 @@ import (
"fmt"
"math"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/predicate"
"github.com/mikestefanello/pagoda/ent/user"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/predicate"
"github.com/mikestefanello/pagoda/ent/user"
)
// PasswordTokenQuery is the builder for querying PasswordToken entities.

View file

@ -8,13 +8,12 @@ import (
"fmt"
"time"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/predicate"
"github.com/mikestefanello/pagoda/ent/user"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/predicate"
"github.com/mikestefanello/pagoda/ent/user"
)
// PasswordTokenUpdate is the builder for updating PasswordToken entities.

View file

@ -2,4 +2,4 @@
package ent
// The schema-stitching logic is generated in goweb/ent/runtime/runtime.go
// The schema-stitching logic is generated in github.com/mikestefanello/pagoda/ent/runtime/runtime.go

View file

@ -40,8 +40,12 @@ func init() {
userDescPassword := userFields[2].Descriptor()
// user.PasswordValidator is a validator for the "password" field. It is called by the builders before save.
user.PasswordValidator = userDescPassword.Validators[0].(func(string) error)
// userDescVerified is the schema descriptor for verified field.
userDescVerified := userFields[3].Descriptor()
// user.DefaultVerified holds the default value on creation for the verified field.
user.DefaultVerified = userDescVerified.Default.(bool)
// userDescCreatedAt is the schema descriptor for created_at field.
userDescCreatedAt := userFields[3].Descriptor()
userDescCreatedAt := userFields[4].Descriptor()
// user.DefaultCreatedAt holds the default value on creation for the created_at field.
user.DefaultCreatedAt = userDescCreatedAt.Default.(func() time.Time)
}

View file

@ -29,6 +29,8 @@ func (User) Fields() []ent.Field {
field.String("password").
Sensitive().
NotEmpty(),
field.Bool("verified").
Default(false),
field.Time("created_at").
Default(time.Now).
Immutable(),

View file

@ -7,9 +7,8 @@ import (
"strings"
"time"
"github.com/mikestefanello/pagoda/ent/user"
"entgo.io/ent/dialect/sql"
"github.com/mikestefanello/pagoda/ent/user"
)
// User is the model entity for the User schema.
@ -23,6 +22,8 @@ type User struct {
Email string `json:"email,omitempty"`
// Password holds the value of the "password" field.
Password string `json:"-"`
// Verified holds the value of the "verified" field.
Verified bool `json:"verified,omitempty"`
// CreatedAt holds the value of the "created_at" field.
CreatedAt time.Time `json:"created_at,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
@ -53,6 +54,8 @@ func (*User) scanValues(columns []string) ([]interface{}, error) {
values := make([]interface{}, len(columns))
for i := range columns {
switch columns[i] {
case user.FieldVerified:
values[i] = new(sql.NullBool)
case user.FieldID:
values[i] = new(sql.NullInt64)
case user.FieldName, user.FieldEmail, user.FieldPassword:
@ -98,6 +101,12 @@ func (u *User) assignValues(columns []string, values []interface{}) error {
} else if value.Valid {
u.Password = value.String
}
case user.FieldVerified:
if value, ok := values[i].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field verified", values[i])
} else if value.Valid {
u.Verified = value.Bool
}
case user.FieldCreatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field created_at", values[i])
@ -142,6 +151,8 @@ func (u *User) String() string {
builder.WriteString(", email=")
builder.WriteString(u.Email)
builder.WriteString(", password=<sensitive>")
builder.WriteString(", verified=")
builder.WriteString(fmt.Sprintf("%v", u.Verified))
builder.WriteString(", created_at=")
builder.WriteString(u.CreatedAt.Format(time.ANSIC))
builder.WriteByte(')')

View file

@ -19,6 +19,8 @@ const (
FieldEmail = "email"
// FieldPassword holds the string denoting the password field in the database.
FieldPassword = "password"
// FieldVerified holds the string denoting the verified field in the database.
FieldVerified = "verified"
// FieldCreatedAt holds the string denoting the created_at field in the database.
FieldCreatedAt = "created_at"
// EdgeOwner holds the string denoting the owner edge name in mutations.
@ -40,6 +42,7 @@ var Columns = []string{
FieldName,
FieldEmail,
FieldPassword,
FieldVerified,
FieldCreatedAt,
}
@ -57,7 +60,7 @@ func ValidColumn(column string) bool {
// package on the initialization of the application. Therefore,
// it should be imported in the main as follows:
//
// import _ "goweb/ent/runtime"
// import _ "github.com/mikestefanello/pagoda/ent/runtime"
//
var (
Hooks [1]ent.Hook
@ -67,6 +70,8 @@ var (
EmailValidator func(string) error
// PasswordValidator is a validator for the "password" field. It is called by the builders before save.
PasswordValidator func(string) error
// DefaultVerified holds the default value on creation for the "verified" field.
DefaultVerified bool
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
DefaultCreatedAt func() time.Time
)

View file

@ -5,10 +5,9 @@ package user
import (
"time"
"github.com/mikestefanello/pagoda/ent/predicate"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/mikestefanello/pagoda/ent/predicate"
)
// ID filters vertices based on their ID field.
@ -115,6 +114,13 @@ func Password(v string) predicate.User {
})
}
// Verified applies equality check predicate on the "verified" field. It's identical to VerifiedEQ.
func Verified(v bool) predicate.User {
return predicate.User(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldVerified), v))
})
}
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
func CreatedAt(v time.Time) predicate.User {
return predicate.User(func(s *sql.Selector) {
@ -455,6 +461,20 @@ func PasswordContainsFold(v string) predicate.User {
})
}
// VerifiedEQ applies the EQ predicate on the "verified" field.
func VerifiedEQ(v bool) predicate.User {
return predicate.User(func(s *sql.Selector) {
s.Where(sql.EQ(s.C(FieldVerified), v))
})
}
// VerifiedNEQ applies the NEQ predicate on the "verified" field.
func VerifiedNEQ(v bool) predicate.User {
return predicate.User(func(s *sql.Selector) {
s.Where(sql.NEQ(s.C(FieldVerified), v))
})
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.User {
return predicate.User(func(s *sql.Selector) {

View file

@ -8,11 +8,10 @@ import (
"fmt"
"time"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/user"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/user"
)
// UserCreate is the builder for creating a User entity.
@ -40,6 +39,20 @@ func (uc *UserCreate) SetPassword(s string) *UserCreate {
return uc
}
// SetVerified sets the "verified" field.
func (uc *UserCreate) SetVerified(b bool) *UserCreate {
uc.mutation.SetVerified(b)
return uc
}
// SetNillableVerified sets the "verified" field if the given value is not nil.
func (uc *UserCreate) SetNillableVerified(b *bool) *UserCreate {
if b != nil {
uc.SetVerified(*b)
}
return uc
}
// SetCreatedAt sets the "created_at" field.
func (uc *UserCreate) SetCreatedAt(t time.Time) *UserCreate {
uc.mutation.SetCreatedAt(t)
@ -142,6 +155,10 @@ func (uc *UserCreate) ExecX(ctx context.Context) {
// defaults sets the default values of the builder before save.
func (uc *UserCreate) defaults() error {
if _, ok := uc.mutation.Verified(); !ok {
v := user.DefaultVerified
uc.mutation.SetVerified(v)
}
if _, ok := uc.mutation.CreatedAt(); !ok {
if user.DefaultCreatedAt == nil {
return fmt.Errorf("ent: uninitialized user.DefaultCreatedAt (forgotten import ent/runtime?)")
@ -178,6 +195,9 @@ func (uc *UserCreate) check() error {
return &ValidationError{Name: "password", err: fmt.Errorf(`ent: validator failed for field "password": %w`, err)}
}
}
if _, ok := uc.mutation.Verified(); !ok {
return &ValidationError{Name: "verified", err: errors.New(`ent: missing required field "verified"`)}
}
if _, ok := uc.mutation.CreatedAt(); !ok {
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "created_at"`)}
}
@ -232,6 +252,14 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
})
_node.Password = value
}
if value, ok := uc.mutation.Verified(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeBool,
Value: value,
Column: user.FieldVerified,
})
_node.Verified = value
}
if value, ok := uc.mutation.CreatedAt(); ok {
_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
Type: field.TypeTime,

View file

@ -6,12 +6,11 @@ import (
"context"
"fmt"
"github.com/mikestefanello/pagoda/ent/predicate"
"github.com/mikestefanello/pagoda/ent/user"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/mikestefanello/pagoda/ent/predicate"
"github.com/mikestefanello/pagoda/ent/user"
)
// UserDelete is the builder for deleting a User entity.

View file

@ -9,13 +9,12 @@ import (
"fmt"
"math"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/predicate"
"github.com/mikestefanello/pagoda/ent/user"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/predicate"
"github.com/mikestefanello/pagoda/ent/user"
)
// UserQuery is the builder for querying User entities.

View file

@ -6,13 +6,12 @@ import (
"context"
"fmt"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/predicate"
"github.com/mikestefanello/pagoda/ent/user"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/mikestefanello/pagoda/ent/passwordtoken"
"github.com/mikestefanello/pagoda/ent/predicate"
"github.com/mikestefanello/pagoda/ent/user"
)
// UserUpdate is the builder for updating User entities.
@ -46,6 +45,20 @@ func (uu *UserUpdate) SetPassword(s string) *UserUpdate {
return uu
}
// SetVerified sets the "verified" field.
func (uu *UserUpdate) SetVerified(b bool) *UserUpdate {
uu.mutation.SetVerified(b)
return uu
}
// SetNillableVerified sets the "verified" field if the given value is not nil.
func (uu *UserUpdate) SetNillableVerified(b *bool) *UserUpdate {
if b != nil {
uu.SetVerified(*b)
}
return uu
}
// AddOwnerIDs adds the "owner" edge to the PasswordToken entity by IDs.
func (uu *UserUpdate) AddOwnerIDs(ids ...int) *UserUpdate {
uu.mutation.AddOwnerIDs(ids...)
@ -206,6 +219,13 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
Column: user.FieldPassword,
})
}
if value, ok := uu.mutation.Verified(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeBool,
Value: value,
Column: user.FieldVerified,
})
}
if uu.mutation.OwnerCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
@ -297,6 +317,20 @@ func (uuo *UserUpdateOne) SetPassword(s string) *UserUpdateOne {
return uuo
}
// SetVerified sets the "verified" field.
func (uuo *UserUpdateOne) SetVerified(b bool) *UserUpdateOne {
uuo.mutation.SetVerified(b)
return uuo
}
// SetNillableVerified sets the "verified" field if the given value is not nil.
func (uuo *UserUpdateOne) SetNillableVerified(b *bool) *UserUpdateOne {
if b != nil {
uuo.SetVerified(*b)
}
return uuo
}
// AddOwnerIDs adds the "owner" edge to the PasswordToken entity by IDs.
func (uuo *UserUpdateOne) AddOwnerIDs(ids ...int) *UserUpdateOne {
uuo.mutation.AddOwnerIDs(ids...)
@ -481,6 +515,13 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error)
Column: user.FieldPassword,
})
}
if value, ok := uuo.mutation.Verified(); ok {
_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
Type: field.TypeBool,
Value: value,
Column: user.FieldVerified,
})
}
if uuo.mutation.OwnerCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,