diff --git a/ent/migrate/migrations/20230810172042_migration-add-column-last_login.sql b/ent/migrate/migrations/20230810172042_migration-add-column-last_login.sql new file mode 100644 index 0000000..bc4b601 --- /dev/null +++ b/ent/migrate/migrations/20230810172042_migration-add-column-last_login.sql @@ -0,0 +1,6 @@ +-- create with NULL in order to allow backfilling. +ALTER TABLE "users" ADD COLUMN "last_login" timestamptz DEFAULT '1970-01-01 00:00:00+00' NULL; +-- backfill... +UPDATE "users" SET "last_login"='1970-01-01 00:00:00+00' where "last_login" is NULL; +-- set NOT NULL. +ALTER TABLE "users" ALTER COLUMN "last_login" SET NOT NULL; diff --git a/ent/migrate/migrations/atlas.sum b/ent/migrate/migrations/atlas.sum index 6950971..7edf110 100644 --- a/ent/migrate/migrations/atlas.sum +++ b/ent/migrate/migrations/atlas.sum @@ -1,2 +1,3 @@ -h1:uYC15pIvdFkiTfO7WNS9BhXbpvEiqVbxrv5XALamukc= +h1:aZmf8Qf2nCkJdRJH4OPgVG9bFSBjjwIXyfYTbApun3M= 20230810162233_baseline.sql h1:zt1JTsDsXicu34uMcu1W3rveGsy5SV7b5gJe+FCq9OM= +20230810172042_migration-add-column-last_login.sql h1:1aUceKvrtCHaV2hbmPMI6CgJvg5BSO6aoHDdUnS93mo= diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index 49fcf77..f97d3a3 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -54,6 +54,7 @@ var ( {Name: "is_active", Type: field.TypeBool, Default: true}, {Name: "created_at", Type: field.TypeTime}, {Name: "updated_at", Type: field.TypeTime}, + {Name: "last_login", Type: field.TypeTime}, } // UsersTable holds the schema information for the "users" table. UsersTable = &schema.Table{ diff --git a/ent/mutation.go b/ent/mutation.go index bedda74..5a42ea6 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -1517,6 +1517,7 @@ type UserMutation struct { is_active *bool created_at *time.Time updated_at *time.Time + last_login *time.Time clearedFields map[string]struct{} done bool oldValue func(context.Context) (*User, error) @@ -1879,6 +1880,42 @@ func (m *UserMutation) ResetUpdatedAt() { m.updated_at = nil } +// SetLastLogin sets the "last_login" field. +func (m *UserMutation) SetLastLogin(t time.Time) { + m.last_login = &t +} + +// LastLogin returns the value of the "last_login" field in the mutation. +func (m *UserMutation) LastLogin() (r time.Time, exists bool) { + v := m.last_login + if v == nil { + return + } + return *v, true +} + +// OldLastLogin returns the old "last_login" 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) OldLastLogin(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldLastLogin is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldLastLogin requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldLastLogin: %w", err) + } + return oldValue.LastLogin, nil +} + +// ResetLastLogin resets all changes to the "last_login" field. +func (m *UserMutation) ResetLastLogin() { + m.last_login = nil +} + // Where appends a list predicates to the UserMutation builder. func (m *UserMutation) Where(ps ...predicate.User) { m.predicates = append(m.predicates, ps...) @@ -1913,7 +1950,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, 7) + fields := make([]string, 0, 8) if m.username != nil { fields = append(fields, user.FieldUsername) } @@ -1935,6 +1972,9 @@ func (m *UserMutation) Fields() []string { if m.updated_at != nil { fields = append(fields, user.FieldUpdatedAt) } + if m.last_login != nil { + fields = append(fields, user.FieldLastLogin) + } return fields } @@ -1957,6 +1997,8 @@ func (m *UserMutation) Field(name string) (ent.Value, bool) { return m.CreatedAt() case user.FieldUpdatedAt: return m.UpdatedAt() + case user.FieldLastLogin: + return m.LastLogin() } return nil, false } @@ -1980,6 +2022,8 @@ func (m *UserMutation) OldField(ctx context.Context, name string) (ent.Value, er return m.OldCreatedAt(ctx) case user.FieldUpdatedAt: return m.OldUpdatedAt(ctx) + case user.FieldLastLogin: + return m.OldLastLogin(ctx) } return nil, fmt.Errorf("unknown User field %s", name) } @@ -2038,6 +2082,13 @@ func (m *UserMutation) SetField(name string, value ent.Value) error { } m.SetUpdatedAt(v) return nil + case user.FieldLastLogin: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLastLogin(v) + return nil } return fmt.Errorf("unknown User field %s", name) } @@ -2108,6 +2159,9 @@ func (m *UserMutation) ResetField(name string) error { case user.FieldUpdatedAt: m.ResetUpdatedAt() return nil + case user.FieldLastLogin: + m.ResetLastLogin() + return nil } return fmt.Errorf("unknown User field %s", name) } diff --git a/ent/runtime.go b/ent/runtime.go index eb859e8..5079eda 100644 --- a/ent/runtime.go +++ b/ent/runtime.go @@ -84,6 +84,12 @@ func init() { user.DefaultUpdatedAt = userDescUpdatedAt.Default.(func() time.Time) // user.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. user.UpdateDefaultUpdatedAt = userDescUpdatedAt.UpdateDefault.(func() time.Time) + // userDescLastLogin is the schema descriptor for last_login field. + userDescLastLogin := userFields[8].Descriptor() + // user.DefaultLastLogin holds the default value on creation for the last_login field. + user.DefaultLastLogin = userDescLastLogin.Default.(time.Time) + // user.UpdateDefaultLastLogin holds the default value on update for the last_login field. + user.UpdateDefaultLastLogin = userDescLastLogin.UpdateDefault.(func() time.Time) // userDescID is the schema descriptor for id field. userDescID := userFields[0].Descriptor() // user.DefaultID holds the default value on creation for the id field. diff --git a/ent/schema/user.go b/ent/schema/user.go index eba47cf..cad7fbf 100644 --- a/ent/schema/user.go +++ b/ent/schema/user.go @@ -42,6 +42,9 @@ func (User) Fields() []ent.Field { field.Time("updated_at"). Default(time.Now). UpdateDefault(time.Now), + field.Time("last_login"). + Default(time.Unix(0, 0)). + UpdateDefault(time.Now), } } diff --git a/ent/user.go b/ent/user.go index 103a6f8..1acbf44 100644 --- a/ent/user.go +++ b/ent/user.go @@ -31,7 +31,9 @@ type User struct { // CreatedAt holds the value of the "created_at" field. CreatedAt time.Time `json:"created_at,omitempty"` // UpdatedAt holds the value of the "updated_at" field. - UpdatedAt time.Time `json:"updated_at,omitempty"` + UpdatedAt time.Time `json:"updated_at,omitempty"` + // LastLogin holds the value of the "last_login" field. + LastLogin time.Time `json:"last_login,omitempty"` selectValues sql.SelectValues } @@ -46,7 +48,7 @@ func (*User) scanValues(columns []string) ([]any, error) { values[i] = new(sql.NullBool) case user.FieldUsername, user.FieldEmail: values[i] = new(sql.NullString) - case user.FieldCreatedAt, user.FieldUpdatedAt: + case user.FieldCreatedAt, user.FieldUpdatedAt, user.FieldLastLogin: values[i] = new(sql.NullTime) case user.FieldID: values[i] = new(uuid.UUID) @@ -113,6 +115,12 @@ func (u *User) assignValues(columns []string, values []any) error { } else if value.Valid { u.UpdatedAt = value.Time } + case user.FieldLastLogin: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field last_login", values[i]) + } else if value.Valid { + u.LastLogin = value.Time + } default: u.selectValues.Set(columns[i], values[i]) } @@ -168,6 +176,9 @@ func (u *User) String() string { builder.WriteString(", ") builder.WriteString("updated_at=") builder.WriteString(u.UpdatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("last_login=") + builder.WriteString(u.LastLogin.Format(time.ANSIC)) builder.WriteByte(')') return builder.String() } diff --git a/ent/user/user.go b/ent/user/user.go index 4c4dcb6..f5175ad 100644 --- a/ent/user/user.go +++ b/ent/user/user.go @@ -28,6 +28,8 @@ const ( FieldCreatedAt = "created_at" // FieldUpdatedAt holds the string denoting the updated_at field in the database. FieldUpdatedAt = "updated_at" + // FieldLastLogin holds the string denoting the last_login field in the database. + FieldLastLogin = "last_login" // Table holds the table name of the user in the database. Table = "users" ) @@ -42,6 +44,7 @@ var Columns = []string{ FieldIsActive, FieldCreatedAt, FieldUpdatedAt, + FieldLastLogin, } // ValidColumn reports if the column name is valid (part of the table columns). @@ -71,6 +74,10 @@ var ( DefaultUpdatedAt func() time.Time // UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field. UpdateDefaultUpdatedAt func() time.Time + // DefaultLastLogin holds the default value on creation for the "last_login" field. + DefaultLastLogin time.Time + // UpdateDefaultLastLogin holds the default value on update for the "last_login" field. + UpdateDefaultLastLogin func() time.Time // DefaultID holds the default value on creation for the "id" field. DefaultID func() uuid.UUID ) @@ -112,3 +119,8 @@ func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc() } + +// ByLastLogin orders the results by the last_login field. +func ByLastLogin(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldLastLogin, opts...).ToFunc() +} diff --git a/ent/user/where.go b/ent/user/where.go index 30ef95a..94b9012 100644 --- a/ent/user/where.go +++ b/ent/user/where.go @@ -90,6 +90,11 @@ func UpdatedAt(v time.Time) predicate.User { return predicate.User(sql.FieldEQ(FieldUpdatedAt, v)) } +// LastLogin applies equality check predicate on the "last_login" field. It's identical to LastLoginEQ. +func LastLogin(v time.Time) predicate.User { + return predicate.User(sql.FieldEQ(FieldLastLogin, v)) +} + // UsernameEQ applies the EQ predicate on the "username" field. func UsernameEQ(v string) predicate.User { return predicate.User(sql.FieldEQ(FieldUsername, v)) @@ -360,6 +365,46 @@ func UpdatedAtLTE(v time.Time) predicate.User { return predicate.User(sql.FieldLTE(FieldUpdatedAt, v)) } +// LastLoginEQ applies the EQ predicate on the "last_login" field. +func LastLoginEQ(v time.Time) predicate.User { + return predicate.User(sql.FieldEQ(FieldLastLogin, v)) +} + +// LastLoginNEQ applies the NEQ predicate on the "last_login" field. +func LastLoginNEQ(v time.Time) predicate.User { + return predicate.User(sql.FieldNEQ(FieldLastLogin, v)) +} + +// LastLoginIn applies the In predicate on the "last_login" field. +func LastLoginIn(vs ...time.Time) predicate.User { + return predicate.User(sql.FieldIn(FieldLastLogin, vs...)) +} + +// LastLoginNotIn applies the NotIn predicate on the "last_login" field. +func LastLoginNotIn(vs ...time.Time) predicate.User { + return predicate.User(sql.FieldNotIn(FieldLastLogin, vs...)) +} + +// LastLoginGT applies the GT predicate on the "last_login" field. +func LastLoginGT(v time.Time) predicate.User { + return predicate.User(sql.FieldGT(FieldLastLogin, v)) +} + +// LastLoginGTE applies the GTE predicate on the "last_login" field. +func LastLoginGTE(v time.Time) predicate.User { + return predicate.User(sql.FieldGTE(FieldLastLogin, v)) +} + +// LastLoginLT applies the LT predicate on the "last_login" field. +func LastLoginLT(v time.Time) predicate.User { + return predicate.User(sql.FieldLT(FieldLastLogin, v)) +} + +// LastLoginLTE applies the LTE predicate on the "last_login" field. +func LastLoginLTE(v time.Time) predicate.User { + return predicate.User(sql.FieldLTE(FieldLastLogin, v)) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.User) predicate.User { return predicate.User(func(s *sql.Selector) { diff --git a/ent/user_create.go b/ent/user_create.go index cb06520..1c164ae 100644 --- a/ent/user_create.go +++ b/ent/user_create.go @@ -95,6 +95,20 @@ func (uc *UserCreate) SetNillableUpdatedAt(t *time.Time) *UserCreate { return uc } +// SetLastLogin sets the "last_login" field. +func (uc *UserCreate) SetLastLogin(t time.Time) *UserCreate { + uc.mutation.SetLastLogin(t) + return uc +} + +// SetNillableLastLogin sets the "last_login" field if the given value is not nil. +func (uc *UserCreate) SetNillableLastLogin(t *time.Time) *UserCreate { + if t != nil { + uc.SetLastLogin(*t) + } + return uc +} + // SetID sets the "id" field. func (uc *UserCreate) SetID(u uuid.UUID) *UserCreate { uc.mutation.SetID(u) @@ -160,6 +174,10 @@ func (uc *UserCreate) defaults() { v := user.DefaultUpdatedAt() uc.mutation.SetUpdatedAt(v) } + if _, ok := uc.mutation.LastLogin(); !ok { + v := user.DefaultLastLogin + uc.mutation.SetLastLogin(v) + } if _, ok := uc.mutation.ID(); !ok { v := user.DefaultID() uc.mutation.SetID(v) @@ -204,6 +222,9 @@ func (uc *UserCreate) check() error { if _, ok := uc.mutation.UpdatedAt(); !ok { return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "User.updated_at"`)} } + if _, ok := uc.mutation.LastLogin(); !ok { + return &ValidationError{Name: "last_login", err: errors.New(`ent: missing required field "User.last_login"`)} + } return nil } @@ -267,6 +288,10 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) { _spec.SetField(user.FieldUpdatedAt, field.TypeTime, value) _node.UpdatedAt = value } + if value, ok := uc.mutation.LastLogin(); ok { + _spec.SetField(user.FieldLastLogin, field.TypeTime, value) + _node.LastLogin = value + } return _node, _spec } diff --git a/ent/user_update.go b/ent/user_update.go index cdaedb3..c821276 100644 --- a/ent/user_update.go +++ b/ent/user_update.go @@ -80,6 +80,12 @@ func (uu *UserUpdate) SetUpdatedAt(t time.Time) *UserUpdate { return uu } +// SetLastLogin sets the "last_login" field. +func (uu *UserUpdate) SetLastLogin(t time.Time) *UserUpdate { + uu.mutation.SetLastLogin(t) + return uu +} + // Mutation returns the UserMutation object of the builder. func (uu *UserUpdate) Mutation() *UserMutation { return uu.mutation @@ -119,6 +125,10 @@ func (uu *UserUpdate) defaults() { v := user.UpdateDefaultUpdatedAt() uu.mutation.SetUpdatedAt(v) } + if _, ok := uu.mutation.LastLogin(); !ok { + v := user.UpdateDefaultLastLogin() + uu.mutation.SetLastLogin(v) + } } // check runs all checks and user-defined validators on the builder. @@ -171,6 +181,9 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { if value, ok := uu.mutation.UpdatedAt(); ok { _spec.SetField(user.FieldUpdatedAt, field.TypeTime, value) } + if value, ok := uu.mutation.LastLogin(); ok { + _spec.SetField(user.FieldLastLogin, field.TypeTime, value) + } if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{user.Label} @@ -243,6 +256,12 @@ func (uuo *UserUpdateOne) SetUpdatedAt(t time.Time) *UserUpdateOne { return uuo } +// SetLastLogin sets the "last_login" field. +func (uuo *UserUpdateOne) SetLastLogin(t time.Time) *UserUpdateOne { + uuo.mutation.SetLastLogin(t) + return uuo +} + // Mutation returns the UserMutation object of the builder. func (uuo *UserUpdateOne) Mutation() *UserMutation { return uuo.mutation @@ -295,6 +314,10 @@ func (uuo *UserUpdateOne) defaults() { v := user.UpdateDefaultUpdatedAt() uuo.mutation.SetUpdatedAt(v) } + if _, ok := uuo.mutation.LastLogin(); !ok { + v := user.UpdateDefaultLastLogin() + uuo.mutation.SetLastLogin(v) + } } // check runs all checks and user-defined validators on the builder. @@ -364,6 +387,9 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) if value, ok := uuo.mutation.UpdatedAt(); ok { _spec.SetField(user.FieldUpdatedAt, field.TypeTime, value) } + if value, ok := uuo.mutation.LastLogin(); ok { + _spec.SetField(user.FieldLastLogin, field.TypeTime, value) + } _node = &User{config: uuo.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues