diff --git a/Makefile b/Makefile index c40d451..5be7fe4 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ -.PHONY: pg -pg: +.PHONY: db +db: psql postgresql://admin:admin@localhost:5432/app -.PHONY: pg-test -pg-test: +.PHONY: db-test +db-test: psql postgresql://admin:admin@localhost:5432/app_test .PHONY: ent-gen diff --git a/controller/controller.go b/controller/controller.go index 3f5335e..8de30f5 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -173,11 +173,15 @@ func (t *Controller) SetValidationErrorMessages(c echo.Context, err error, data switch ve.Tag() { case "required": message = "%s is required." + case "email": + message = "%s must be a valid email address." + case "eqfield": + message = "%s must match." default: message = "%s is not a valid value." } - msg.Danger(c, fmt.Sprintf(message, label)) + msg.Danger(c, fmt.Sprintf(message, ""+label+"")) } } diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index 37176d9..f2d540e 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -11,7 +11,8 @@ var ( // UsersColumns holds the columns for the "users" table. UsersColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, - {Name: "username", Type: field.TypeString, Unique: true}, + {Name: "name", Type: field.TypeString}, + {Name: "email", Type: field.TypeString, Unique: true}, {Name: "password", Type: field.TypeString}, {Name: "created_at", Type: field.TypeTime}, } diff --git a/ent/mutation.go b/ent/mutation.go index 406b997..d8a8e73 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -31,7 +31,8 @@ type UserMutation struct { op Op typ string id *int - username *string + name *string + email *string password *string created_at *time.Time clearedFields map[string]struct{} @@ -119,40 +120,76 @@ func (m *UserMutation) ID() (id int, exists bool) { return *m.id, true } -// SetUsername sets the "username" field. -func (m *UserMutation) SetUsername(s string) { - m.username = &s +// SetName sets the "name" field. +func (m *UserMutation) SetName(s string) { + m.name = &s } -// Username returns the value of the "username" field in the mutation. -func (m *UserMutation) Username() (r string, exists bool) { - v := m.username +// Name returns the value of the "name" field in the mutation. +func (m *UserMutation) Name() (r string, exists bool) { + v := m.name if v == nil { return } return *v, true } -// OldUsername returns the old "username" field's value of the User entity. +// OldName returns the old "name" 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) OldUsername(ctx context.Context) (v string, err error) { +func (m *UserMutation) OldName(ctx context.Context) (v string, err error) { if !m.op.Is(OpUpdateOne) { - return v, fmt.Errorf("OldUsername is only allowed on UpdateOne operations") + return v, fmt.Errorf("OldName is only allowed on UpdateOne operations") } if m.id == nil || m.oldValue == nil { - return v, fmt.Errorf("OldUsername requires an ID field in the mutation") + return v, fmt.Errorf("OldName requires an ID field in the mutation") } oldValue, err := m.oldValue(ctx) if err != nil { - return v, fmt.Errorf("querying old value for OldUsername: %w", err) + return v, fmt.Errorf("querying old value for OldName: %w", err) } - return oldValue.Username, nil + return oldValue.Name, nil } -// ResetUsername resets all changes to the "username" field. -func (m *UserMutation) ResetUsername() { - m.username = nil +// ResetName resets all changes to the "name" field. +func (m *UserMutation) ResetName() { + m.name = nil +} + +// SetEmail sets the "email" field. +func (m *UserMutation) SetEmail(s string) { + m.email = &s +} + +// Email returns the value of the "email" field in the mutation. +func (m *UserMutation) Email() (r string, exists bool) { + v := m.email + if v == nil { + return + } + return *v, true +} + +// OldEmail returns the old "email" 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) OldEmail(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, fmt.Errorf("OldEmail is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, fmt.Errorf("OldEmail requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldEmail: %w", err) + } + return oldValue.Email, nil +} + +// ResetEmail resets all changes to the "email" field. +func (m *UserMutation) ResetEmail() { + m.email = nil } // SetPassword sets the "password" field. @@ -246,9 +283,12 @@ 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, 3) - if m.username != nil { - fields = append(fields, user.FieldUsername) + fields := make([]string, 0, 4) + if m.name != nil { + fields = append(fields, user.FieldName) + } + if m.email != nil { + fields = append(fields, user.FieldEmail) } if m.password != nil { fields = append(fields, user.FieldPassword) @@ -264,8 +304,10 @@ func (m *UserMutation) Fields() []string { // schema. func (m *UserMutation) Field(name string) (ent.Value, bool) { switch name { - case user.FieldUsername: - return m.Username() + case user.FieldName: + return m.Name() + case user.FieldEmail: + return m.Email() case user.FieldPassword: return m.Password() case user.FieldCreatedAt: @@ -279,8 +321,10 @@ func (m *UserMutation) Field(name string) (ent.Value, bool) { // database failed. func (m *UserMutation) OldField(ctx context.Context, name string) (ent.Value, error) { switch name { - case user.FieldUsername: - return m.OldUsername(ctx) + case user.FieldName: + return m.OldName(ctx) + case user.FieldEmail: + return m.OldEmail(ctx) case user.FieldPassword: return m.OldPassword(ctx) case user.FieldCreatedAt: @@ -294,12 +338,19 @@ func (m *UserMutation) OldField(ctx context.Context, name string) (ent.Value, er // type. func (m *UserMutation) SetField(name string, value ent.Value) error { switch name { - case user.FieldUsername: + case user.FieldName: v, ok := value.(string) if !ok { return fmt.Errorf("unexpected type %T for field %s", value, name) } - m.SetUsername(v) + m.SetName(v) + return nil + case user.FieldEmail: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetEmail(v) return nil case user.FieldPassword: v, ok := value.(string) @@ -364,8 +415,11 @@ func (m *UserMutation) ClearField(name string) error { // It returns an error if the field is not defined in the schema. func (m *UserMutation) ResetField(name string) error { switch name { - case user.FieldUsername: - m.ResetUsername() + case user.FieldName: + m.ResetName() + return nil + case user.FieldEmail: + m.ResetEmail() return nil case user.FieldPassword: m.ResetPassword() diff --git a/ent/runtime.go b/ent/runtime.go index c3592ee..508003d 100644 --- a/ent/runtime.go +++ b/ent/runtime.go @@ -14,16 +14,20 @@ import ( func init() { userFields := schema.User{}.Fields() _ = userFields - // userDescUsername is the schema descriptor for username field. - userDescUsername := userFields[0].Descriptor() - // user.UsernameValidator is a validator for the "username" field. It is called by the builders before save. - user.UsernameValidator = userDescUsername.Validators[0].(func(string) error) + // userDescName is the schema descriptor for name field. + userDescName := userFields[0].Descriptor() + // user.NameValidator is a validator for the "name" field. It is called by the builders before save. + user.NameValidator = userDescName.Validators[0].(func(string) error) + // userDescEmail is the schema descriptor for email field. + userDescEmail := userFields[1].Descriptor() + // user.EmailValidator is a validator for the "email" field. It is called by the builders before save. + user.EmailValidator = userDescEmail.Validators[0].(func(string) error) // userDescPassword is the schema descriptor for password field. - userDescPassword := userFields[1].Descriptor() + 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) // userDescCreatedAt is the schema descriptor for created_at field. - userDescCreatedAt := userFields[2].Descriptor() + userDescCreatedAt := userFields[3].Descriptor() // user.DefaultCreatedAt holds the default value on creation for the created_at field. user.DefaultCreatedAt = userDescCreatedAt.Default.(func() time.Time) } diff --git a/ent/schema/user.go b/ent/schema/user.go index e2195f0..1abd475 100644 --- a/ent/schema/user.go +++ b/ent/schema/user.go @@ -15,9 +15,11 @@ type User struct { // Fields of the User. func (User) Fields() []ent.Field { return []ent.Field{ - field.String("username"). - Unique(). + field.String("name"). NotEmpty(), + field.String("email"). + NotEmpty(). + Unique(), field.String("password"). Sensitive(). NotEmpty(), diff --git a/ent/user.go b/ent/user.go index a44657b..7f52873 100644 --- a/ent/user.go +++ b/ent/user.go @@ -16,8 +16,10 @@ type User struct { config `json:"-"` // ID of the ent. ID int `json:"id,omitempty"` - // Username holds the value of the "username" field. - Username string `json:"username,omitempty"` + // Name holds the value of the "name" field. + Name string `json:"name,omitempty"` + // Email holds the value of the "email" field. + Email string `json:"email,omitempty"` // Password holds the value of the "password" field. Password string `json:"-"` // CreatedAt holds the value of the "created_at" field. @@ -31,7 +33,7 @@ func (*User) scanValues(columns []string) ([]interface{}, error) { switch columns[i] { case user.FieldID: values[i] = new(sql.NullInt64) - case user.FieldUsername, user.FieldPassword: + case user.FieldName, user.FieldEmail, user.FieldPassword: values[i] = new(sql.NullString) case user.FieldCreatedAt: values[i] = new(sql.NullTime) @@ -56,11 +58,17 @@ func (u *User) assignValues(columns []string, values []interface{}) error { return fmt.Errorf("unexpected type %T for field id", value) } u.ID = int(value.Int64) - case user.FieldUsername: + case user.FieldName: if value, ok := values[i].(*sql.NullString); !ok { - return fmt.Errorf("unexpected type %T for field username", values[i]) + return fmt.Errorf("unexpected type %T for field name", values[i]) } else if value.Valid { - u.Username = value.String + u.Name = value.String + } + case user.FieldEmail: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field email", values[i]) + } else if value.Valid { + u.Email = value.String } case user.FieldPassword: if value, ok := values[i].(*sql.NullString); !ok { @@ -102,8 +110,10 @@ func (u *User) String() string { var builder strings.Builder builder.WriteString("User(") builder.WriteString(fmt.Sprintf("id=%v", u.ID)) - builder.WriteString(", username=") - builder.WriteString(u.Username) + builder.WriteString(", name=") + builder.WriteString(u.Name) + builder.WriteString(", email=") + builder.WriteString(u.Email) builder.WriteString(", password=") builder.WriteString(", created_at=") builder.WriteString(u.CreatedAt.Format(time.ANSIC)) diff --git a/ent/user/user.go b/ent/user/user.go index 72960cf..47acf2a 100644 --- a/ent/user/user.go +++ b/ent/user/user.go @@ -11,8 +11,10 @@ const ( Label = "user" // FieldID holds the string denoting the id field in the database. FieldID = "id" - // FieldUsername holds the string denoting the username field in the database. - FieldUsername = "username" + // FieldName holds the string denoting the name field in the database. + FieldName = "name" + // FieldEmail holds the string denoting the email field in the database. + FieldEmail = "email" // FieldPassword holds the string denoting the password field in the database. FieldPassword = "password" // FieldCreatedAt holds the string denoting the created_at field in the database. @@ -24,7 +26,8 @@ const ( // Columns holds all SQL columns for user fields. var Columns = []string{ FieldID, - FieldUsername, + FieldName, + FieldEmail, FieldPassword, FieldCreatedAt, } @@ -40,8 +43,10 @@ func ValidColumn(column string) bool { } var ( - // UsernameValidator is a validator for the "username" field. It is called by the builders before save. - UsernameValidator func(string) error + // NameValidator is a validator for the "name" field. It is called by the builders before save. + NameValidator func(string) error + // EmailValidator is a validator for the "email" field. It is called by the builders before save. + EmailValidator func(string) error // PasswordValidator is a validator for the "password" field. It is called by the builders before save. PasswordValidator func(string) error // DefaultCreatedAt holds the default value on creation for the "created_at" field. diff --git a/ent/user/where.go b/ent/user/where.go index c0e3261..fde4aad 100644 --- a/ent/user/where.go +++ b/ent/user/where.go @@ -92,10 +92,17 @@ func IDLTE(id int) predicate.User { }) } -// Username applies equality check predicate on the "username" field. It's identical to UsernameEQ. -func Username(v string) predicate.User { +// Name applies equality check predicate on the "name" field. It's identical to NameEQ. +func Name(v string) predicate.User { return predicate.User(func(s *sql.Selector) { - s.Where(sql.EQ(s.C(FieldUsername), v)) + s.Where(sql.EQ(s.C(FieldName), v)) + }) +} + +// Email applies equality check predicate on the "email" field. It's identical to EmailEQ. +func Email(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldEmail), v)) }) } @@ -113,22 +120,22 @@ func CreatedAt(v time.Time) predicate.User { }) } -// UsernameEQ applies the EQ predicate on the "username" field. -func UsernameEQ(v string) predicate.User { +// NameEQ applies the EQ predicate on the "name" field. +func NameEQ(v string) predicate.User { return predicate.User(func(s *sql.Selector) { - s.Where(sql.EQ(s.C(FieldUsername), v)) + s.Where(sql.EQ(s.C(FieldName), v)) }) } -// UsernameNEQ applies the NEQ predicate on the "username" field. -func UsernameNEQ(v string) predicate.User { +// NameNEQ applies the NEQ predicate on the "name" field. +func NameNEQ(v string) predicate.User { return predicate.User(func(s *sql.Selector) { - s.Where(sql.NEQ(s.C(FieldUsername), v)) + s.Where(sql.NEQ(s.C(FieldName), v)) }) } -// UsernameIn applies the In predicate on the "username" field. -func UsernameIn(vs ...string) predicate.User { +// NameIn applies the In predicate on the "name" field. +func NameIn(vs ...string) predicate.User { v := make([]interface{}, len(vs)) for i := range v { v[i] = vs[i] @@ -140,12 +147,12 @@ func UsernameIn(vs ...string) predicate.User { s.Where(sql.False()) return } - s.Where(sql.In(s.C(FieldUsername), v...)) + s.Where(sql.In(s.C(FieldName), v...)) }) } -// UsernameNotIn applies the NotIn predicate on the "username" field. -func UsernameNotIn(vs ...string) predicate.User { +// NameNotIn applies the NotIn predicate on the "name" field. +func NameNotIn(vs ...string) predicate.User { v := make([]interface{}, len(vs)) for i := range v { v[i] = vs[i] @@ -157,70 +164,181 @@ func UsernameNotIn(vs ...string) predicate.User { s.Where(sql.False()) return } - s.Where(sql.NotIn(s.C(FieldUsername), v...)) + s.Where(sql.NotIn(s.C(FieldName), v...)) }) } -// UsernameGT applies the GT predicate on the "username" field. -func UsernameGT(v string) predicate.User { +// NameGT applies the GT predicate on the "name" field. +func NameGT(v string) predicate.User { return predicate.User(func(s *sql.Selector) { - s.Where(sql.GT(s.C(FieldUsername), v)) + s.Where(sql.GT(s.C(FieldName), v)) }) } -// UsernameGTE applies the GTE predicate on the "username" field. -func UsernameGTE(v string) predicate.User { +// NameGTE applies the GTE predicate on the "name" field. +func NameGTE(v string) predicate.User { return predicate.User(func(s *sql.Selector) { - s.Where(sql.GTE(s.C(FieldUsername), v)) + s.Where(sql.GTE(s.C(FieldName), v)) }) } -// UsernameLT applies the LT predicate on the "username" field. -func UsernameLT(v string) predicate.User { +// NameLT applies the LT predicate on the "name" field. +func NameLT(v string) predicate.User { return predicate.User(func(s *sql.Selector) { - s.Where(sql.LT(s.C(FieldUsername), v)) + s.Where(sql.LT(s.C(FieldName), v)) }) } -// UsernameLTE applies the LTE predicate on the "username" field. -func UsernameLTE(v string) predicate.User { +// NameLTE applies the LTE predicate on the "name" field. +func NameLTE(v string) predicate.User { return predicate.User(func(s *sql.Selector) { - s.Where(sql.LTE(s.C(FieldUsername), v)) + s.Where(sql.LTE(s.C(FieldName), v)) }) } -// UsernameContains applies the Contains predicate on the "username" field. -func UsernameContains(v string) predicate.User { +// NameContains applies the Contains predicate on the "name" field. +func NameContains(v string) predicate.User { return predicate.User(func(s *sql.Selector) { - s.Where(sql.Contains(s.C(FieldUsername), v)) + s.Where(sql.Contains(s.C(FieldName), v)) }) } -// UsernameHasPrefix applies the HasPrefix predicate on the "username" field. -func UsernameHasPrefix(v string) predicate.User { +// NameHasPrefix applies the HasPrefix predicate on the "name" field. +func NameHasPrefix(v string) predicate.User { return predicate.User(func(s *sql.Selector) { - s.Where(sql.HasPrefix(s.C(FieldUsername), v)) + s.Where(sql.HasPrefix(s.C(FieldName), v)) }) } -// UsernameHasSuffix applies the HasSuffix predicate on the "username" field. -func UsernameHasSuffix(v string) predicate.User { +// NameHasSuffix applies the HasSuffix predicate on the "name" field. +func NameHasSuffix(v string) predicate.User { return predicate.User(func(s *sql.Selector) { - s.Where(sql.HasSuffix(s.C(FieldUsername), v)) + s.Where(sql.HasSuffix(s.C(FieldName), v)) }) } -// UsernameEqualFold applies the EqualFold predicate on the "username" field. -func UsernameEqualFold(v string) predicate.User { +// NameEqualFold applies the EqualFold predicate on the "name" field. +func NameEqualFold(v string) predicate.User { return predicate.User(func(s *sql.Selector) { - s.Where(sql.EqualFold(s.C(FieldUsername), v)) + s.Where(sql.EqualFold(s.C(FieldName), v)) }) } -// UsernameContainsFold applies the ContainsFold predicate on the "username" field. -func UsernameContainsFold(v string) predicate.User { +// NameContainsFold applies the ContainsFold predicate on the "name" field. +func NameContainsFold(v string) predicate.User { return predicate.User(func(s *sql.Selector) { - s.Where(sql.ContainsFold(s.C(FieldUsername), v)) + s.Where(sql.ContainsFold(s.C(FieldName), v)) + }) +} + +// EmailEQ applies the EQ predicate on the "email" field. +func EmailEQ(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldEmail), v)) + }) +} + +// EmailNEQ applies the NEQ predicate on the "email" field. +func EmailNEQ(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldEmail), v)) + }) +} + +// EmailIn applies the In predicate on the "email" field. +func EmailIn(vs ...string) predicate.User { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldEmail), v...)) + }) +} + +// EmailNotIn applies the NotIn predicate on the "email" field. +func EmailNotIn(vs ...string) predicate.User { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldEmail), v...)) + }) +} + +// EmailGT applies the GT predicate on the "email" field. +func EmailGT(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldEmail), v)) + }) +} + +// EmailGTE applies the GTE predicate on the "email" field. +func EmailGTE(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldEmail), v)) + }) +} + +// EmailLT applies the LT predicate on the "email" field. +func EmailLT(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldEmail), v)) + }) +} + +// EmailLTE applies the LTE predicate on the "email" field. +func EmailLTE(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldEmail), v)) + }) +} + +// EmailContains applies the Contains predicate on the "email" field. +func EmailContains(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldEmail), v)) + }) +} + +// EmailHasPrefix applies the HasPrefix predicate on the "email" field. +func EmailHasPrefix(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldEmail), v)) + }) +} + +// EmailHasSuffix applies the HasSuffix predicate on the "email" field. +func EmailHasSuffix(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldEmail), v)) + }) +} + +// EmailEqualFold applies the EqualFold predicate on the "email" field. +func EmailEqualFold(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldEmail), v)) + }) +} + +// EmailContainsFold applies the ContainsFold predicate on the "email" field. +func EmailContainsFold(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldEmail), v)) }) } diff --git a/ent/user_create.go b/ent/user_create.go index 14d7c6d..176bef7 100644 --- a/ent/user_create.go +++ b/ent/user_create.go @@ -20,9 +20,15 @@ type UserCreate struct { hooks []Hook } -// SetUsername sets the "username" field. -func (uc *UserCreate) SetUsername(s string) *UserCreate { - uc.mutation.SetUsername(s) +// SetName sets the "name" field. +func (uc *UserCreate) SetName(s string) *UserCreate { + uc.mutation.SetName(s) + return uc +} + +// SetEmail sets the "email" field. +func (uc *UserCreate) SetEmail(s string) *UserCreate { + uc.mutation.SetEmail(s) return uc } @@ -125,12 +131,20 @@ func (uc *UserCreate) defaults() { // check runs all checks and user-defined validators on the builder. func (uc *UserCreate) check() error { - if _, ok := uc.mutation.Username(); !ok { - return &ValidationError{Name: "username", err: errors.New(`ent: missing required field "username"`)} + if _, ok := uc.mutation.Name(); !ok { + return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "name"`)} } - if v, ok := uc.mutation.Username(); ok { - if err := user.UsernameValidator(v); err != nil { - return &ValidationError{Name: "username", err: fmt.Errorf(`ent: validator failed for field "username": %w`, err)} + if v, ok := uc.mutation.Name(); ok { + if err := user.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "name": %w`, err)} + } + } + if _, ok := uc.mutation.Email(); !ok { + return &ValidationError{Name: "email", err: errors.New(`ent: missing required field "email"`)} + } + if v, ok := uc.mutation.Email(); ok { + if err := user.EmailValidator(v); err != nil { + return &ValidationError{Name: "email", err: fmt.Errorf(`ent: validator failed for field "email": %w`, err)} } } if _, ok := uc.mutation.Password(); !ok { @@ -171,13 +185,21 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) { }, } ) - if value, ok := uc.mutation.Username(); ok { + if value, ok := uc.mutation.Name(); ok { _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ Type: field.TypeString, Value: value, - Column: user.FieldUsername, + Column: user.FieldName, }) - _node.Username = value + _node.Name = value + } + if value, ok := uc.mutation.Email(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: user.FieldEmail, + }) + _node.Email = value } if value, ok := uc.mutation.Password(); ok { _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ diff --git a/ent/user_query.go b/ent/user_query.go index 67de91a..02622fd 100644 --- a/ent/user_query.go +++ b/ent/user_query.go @@ -253,12 +253,12 @@ func (uq *UserQuery) Clone() *UserQuery { // Example: // // var v []struct { -// Username string `json:"username,omitempty"` +// Name string `json:"name,omitempty"` // Count int `json:"count,omitempty"` // } // // client.User.Query(). -// GroupBy(user.FieldUsername). +// GroupBy(user.FieldName). // Aggregate(ent.Count()). // Scan(ctx, &v) // @@ -280,11 +280,11 @@ func (uq *UserQuery) GroupBy(field string, fields ...string) *UserGroupBy { // Example: // // var v []struct { -// Username string `json:"username,omitempty"` +// Name string `json:"name,omitempty"` // } // // client.User.Query(). -// Select(user.FieldUsername). +// Select(user.FieldName). // Scan(ctx, &v) // func (uq *UserQuery) Select(fields ...string) *UserSelect { diff --git a/ent/user_update.go b/ent/user_update.go index 8233f0b..e48690a 100644 --- a/ent/user_update.go +++ b/ent/user_update.go @@ -26,9 +26,15 @@ func (uu *UserUpdate) Where(ps ...predicate.User) *UserUpdate { return uu } -// SetUsername sets the "username" field. -func (uu *UserUpdate) SetUsername(s string) *UserUpdate { - uu.mutation.SetUsername(s) +// SetName sets the "name" field. +func (uu *UserUpdate) SetName(s string) *UserUpdate { + uu.mutation.SetName(s) + return uu +} + +// SetEmail sets the "email" field. +func (uu *UserUpdate) SetEmail(s string) *UserUpdate { + uu.mutation.SetEmail(s) return uu } @@ -105,9 +111,14 @@ func (uu *UserUpdate) ExecX(ctx context.Context) { // check runs all checks and user-defined validators on the builder. func (uu *UserUpdate) check() error { - if v, ok := uu.mutation.Username(); ok { - if err := user.UsernameValidator(v); err != nil { - return &ValidationError{Name: "username", err: fmt.Errorf("ent: validator failed for field \"username\": %w", err)} + if v, ok := uu.mutation.Name(); ok { + if err := user.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf("ent: validator failed for field \"name\": %w", err)} + } + } + if v, ok := uu.mutation.Email(); ok { + if err := user.EmailValidator(v); err != nil { + return &ValidationError{Name: "email", err: fmt.Errorf("ent: validator failed for field \"email\": %w", err)} } } if v, ok := uu.mutation.Password(); ok { @@ -136,11 +147,18 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { } } } - if value, ok := uu.mutation.Username(); ok { + if value, ok := uu.mutation.Name(); ok { _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ Type: field.TypeString, Value: value, - Column: user.FieldUsername, + Column: user.FieldName, + }) + } + if value, ok := uu.mutation.Email(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: user.FieldEmail, }) } if value, ok := uu.mutation.Password(); ok { @@ -169,9 +187,15 @@ type UserUpdateOne struct { mutation *UserMutation } -// SetUsername sets the "username" field. -func (uuo *UserUpdateOne) SetUsername(s string) *UserUpdateOne { - uuo.mutation.SetUsername(s) +// SetName sets the "name" field. +func (uuo *UserUpdateOne) SetName(s string) *UserUpdateOne { + uuo.mutation.SetName(s) + return uuo +} + +// SetEmail sets the "email" field. +func (uuo *UserUpdateOne) SetEmail(s string) *UserUpdateOne { + uuo.mutation.SetEmail(s) return uuo } @@ -255,9 +279,14 @@ func (uuo *UserUpdateOne) ExecX(ctx context.Context) { // check runs all checks and user-defined validators on the builder. func (uuo *UserUpdateOne) check() error { - if v, ok := uuo.mutation.Username(); ok { - if err := user.UsernameValidator(v); err != nil { - return &ValidationError{Name: "username", err: fmt.Errorf("ent: validator failed for field \"username\": %w", err)} + if v, ok := uuo.mutation.Name(); ok { + if err := user.NameValidator(v); err != nil { + return &ValidationError{Name: "name", err: fmt.Errorf("ent: validator failed for field \"name\": %w", err)} + } + } + if v, ok := uuo.mutation.Email(); ok { + if err := user.EmailValidator(v); err != nil { + return &ValidationError{Name: "email", err: fmt.Errorf("ent: validator failed for field \"email\": %w", err)} } } if v, ok := uuo.mutation.Password(); ok { @@ -303,11 +332,18 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) } } } - if value, ok := uuo.mutation.Username(); ok { + if value, ok := uuo.mutation.Name(); ok { _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ Type: field.TypeString, Value: value, - Column: user.FieldUsername, + Column: user.FieldName, + }) + } + if value, ok := uuo.mutation.Email(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: user.FieldEmail, }) } if value, ok := uuo.mutation.Password(); ok { diff --git a/routes/login.go b/routes/login.go index bfb99a5..77d27a9 100644 --- a/routes/login.go +++ b/routes/login.go @@ -19,7 +19,7 @@ type ( } LoginForm struct { - Username string `form:"username" validate:"required" label:"Username"` + Email string `form:"email" validate:"required,email" label:"Email address"` Password string `form:"password" validate:"required" label:"Password"` } ) @@ -54,7 +54,7 @@ func (l *Login) Post(c echo.Context) error { // Attempt to load the user u, err := l.Container.ORM.User. Query(). - Where(user.Username(l.form.Username)). + Where(user.Email(l.form.Email)). First(c.Request().Context()) if err != nil { @@ -80,6 +80,6 @@ func (l *Login) Post(c echo.Context) error { return fail("unable to log in user", err) } - msg.Success(c, fmt.Sprintf("Welcome back, %s. You are now logged in.", u.Username)) + msg.Success(c, fmt.Sprintf("Welcome back, %s. You are now logged in.", u.Name)) return l.Redirect(c, "home") } diff --git a/routes/register.go b/routes/register.go index 7b9c239..8ab0f67 100644 --- a/routes/register.go +++ b/routes/register.go @@ -15,8 +15,10 @@ type ( } RegisterForm struct { - Username string `form:"username" validate:"required"` - Password string `form:"password" validate:"required"` + Name string `form:"name" validate:"required" label:"Name"` + Email string `form:"email" validate:"required,email" label:"Email address"` + Password string `form:"password" validate:"required" label:"Password"` + ConfirmPassword string `form:"password-confirm" validate:"required,eqfield=Password" label:"Confirm password"` // TODO validate same } ) @@ -44,7 +46,7 @@ func (r *Register) Post(c echo.Context) error { // Validate the form if err := c.Validate(r.form); err != nil { - msg.Danger(c, "All fields are required.") + r.SetValidationErrorMessages(c, err, r.form) return r.Get(c) } @@ -57,7 +59,8 @@ func (r *Register) Post(c echo.Context) error { // Attempt creating the user u, err := r.Container.ORM.User. Create(). - SetUsername(r.form.Username). + SetName(r.form.Name). + SetEmail(r.form.Email). SetPassword(pwHash). Save(c.Request().Context()) @@ -65,7 +68,7 @@ func (r *Register) Post(c echo.Context) error { return fail("unable to create user", err) } - c.Logger().Infof("user created: %s", u.Username) + c.Logger().Infof("user created: %s", u.Name) err = auth.Login(c, u.ID) if err != nil { diff --git a/templates/pages/login.gohtml b/templates/pages/login.gohtml index ce9a643..48c1369 100644 --- a/templates/pages/login.gohtml +++ b/templates/pages/login.gohtml @@ -1,9 +1,9 @@ {{define "content"}}
- +
- +
diff --git a/templates/pages/register.gohtml b/templates/pages/register.gohtml index ccf02e2..c69dd3b 100644 --- a/templates/pages/register.gohtml +++ b/templates/pages/register.gohtml @@ -1,9 +1,15 @@ {{define "content"}}
- +
- + +
+
+
+ +
+
@@ -12,6 +18,12 @@
+
+ +
+ +
+