go: save,verify a bcrypt hash of the passwd
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
leo 2023-05-03 06:30:12 +02:00
parent 5a3ce50bb2
commit a2c17693c6
Signed by: wanderer
SSH Key Fingerprint: SHA256:Dp8+iwKHSlrMEHzE3bJnPng70I7LEsa3IJXRH/U+idQ
11 changed files with 45 additions and 61 deletions

@ -38,7 +38,7 @@ var (
{Name: "id", Type: field.TypeUUID, Unique: true},
{Name: "username", Type: field.TypeString, Unique: true},
{Name: "email", Type: field.TypeString, Unique: true},
{Name: "password", Type: field.TypeString},
{Name: "password", Type: field.TypeBytes},
{Name: "is_admin", Type: field.TypeBool, Default: false},
{Name: "is_active", Type: field.TypeBool, Default: true},
{Name: "created_at", Type: field.TypeTime},

@ -1178,7 +1178,7 @@ type UserMutation struct {
id *uuid.UUID
username *string
email *string
password *string
password *[]byte
is_admin *bool
is_active *bool
created_at *time.Time
@ -1366,12 +1366,12 @@ func (m *UserMutation) ResetEmail() {
}
// SetPassword sets the "password" field.
func (m *UserMutation) SetPassword(s string) {
m.password = &s
func (m *UserMutation) SetPassword(b []byte) {
m.password = &b
}
// Password returns the value of the "password" field in the mutation.
func (m *UserMutation) Password() (r string, exists bool) {
func (m *UserMutation) Password() (r []byte, exists bool) {
v := m.password
if v == nil {
return
@ -1382,7 +1382,7 @@ func (m *UserMutation) Password() (r string, exists bool) {
// OldPassword returns the old "password" 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) OldPassword(ctx context.Context) (v string, err error) {
func (m *UserMutation) OldPassword(ctx context.Context) (v []byte, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldPassword is only allowed on UpdateOne operations")
}
@ -1670,7 +1670,7 @@ func (m *UserMutation) SetField(name string, value ent.Value) error {
m.SetEmail(v)
return nil
case user.FieldPassword:
v, ok := value.(string)
v, ok := value.([]byte)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}

@ -54,7 +54,7 @@ func init() {
// userDescPassword is the schema descriptor for password field.
userDescPassword := userFields[3].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)
user.PasswordValidator = userDescPassword.Validators[0].(func([]byte) error)
// userDescIsAdmin is the schema descriptor for is_admin field.
userDescIsAdmin := userFields[4].Descriptor()
// user.DefaultIsAdmin holds the default value on creation for the is_admin field.

@ -26,7 +26,7 @@ func (User) Fields() []ent.Field {
field.String("email").
NotEmpty().
Unique(),
field.String("password").
field.Bytes("password").
Sensitive().
NotEmpty(),
field.Bool("is_admin").

@ -22,7 +22,7 @@ type User struct {
// Email holds the value of the "email" field.
Email string `json:"email,omitempty"`
// Password holds the value of the "password" field.
Password string `json:"-"`
Password []byte `json:"-"`
// IsAdmin holds the value of the "is_admin" field.
IsAdmin bool `json:"is_admin,omitempty"`
// IsActive holds the value of the "is_active" field.
@ -38,9 +38,11 @@ func (*User) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case user.FieldPassword:
values[i] = new([]byte)
case user.FieldIsAdmin, user.FieldIsActive:
values[i] = new(sql.NullBool)
case user.FieldUsername, user.FieldEmail, user.FieldPassword:
case user.FieldUsername, user.FieldEmail:
values[i] = new(sql.NullString)
case user.FieldCreatedAt, user.FieldUpdatedAt:
values[i] = new(sql.NullTime)
@ -80,10 +82,10 @@ func (u *User) assignValues(columns []string, values []any) error {
u.Email = value.String
}
case user.FieldPassword:
if value, ok := values[i].(*sql.NullString); !ok {
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field password", values[i])
} else if value.Valid {
u.Password = value.String
} else if value != nil {
u.Password = *value
}
case user.FieldIsAdmin:
if value, ok := values[i].(*sql.NullBool); !ok {

@ -59,7 +59,7 @@ var (
// 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
PasswordValidator func([]byte) error
// DefaultIsAdmin holds the default value on creation for the "is_admin" field.
DefaultIsAdmin bool
// DefaultIsActive holds the default value on creation for the "is_active" field.

@ -66,7 +66,7 @@ func Email(v string) predicate.User {
}
// Password applies equality check predicate on the "password" field. It's identical to PasswordEQ.
func Password(v string) predicate.User {
func Password(v []byte) predicate.User {
return predicate.User(sql.FieldEQ(FieldPassword, v))
}
@ -221,70 +221,45 @@ func EmailContainsFold(v string) predicate.User {
}
// PasswordEQ applies the EQ predicate on the "password" field.
func PasswordEQ(v string) predicate.User {
func PasswordEQ(v []byte) predicate.User {
return predicate.User(sql.FieldEQ(FieldPassword, v))
}
// PasswordNEQ applies the NEQ predicate on the "password" field.
func PasswordNEQ(v string) predicate.User {
func PasswordNEQ(v []byte) predicate.User {
return predicate.User(sql.FieldNEQ(FieldPassword, v))
}
// PasswordIn applies the In predicate on the "password" field.
func PasswordIn(vs ...string) predicate.User {
func PasswordIn(vs ...[]byte) predicate.User {
return predicate.User(sql.FieldIn(FieldPassword, vs...))
}
// PasswordNotIn applies the NotIn predicate on the "password" field.
func PasswordNotIn(vs ...string) predicate.User {
func PasswordNotIn(vs ...[]byte) predicate.User {
return predicate.User(sql.FieldNotIn(FieldPassword, vs...))
}
// PasswordGT applies the GT predicate on the "password" field.
func PasswordGT(v string) predicate.User {
func PasswordGT(v []byte) predicate.User {
return predicate.User(sql.FieldGT(FieldPassword, v))
}
// PasswordGTE applies the GTE predicate on the "password" field.
func PasswordGTE(v string) predicate.User {
func PasswordGTE(v []byte) predicate.User {
return predicate.User(sql.FieldGTE(FieldPassword, v))
}
// PasswordLT applies the LT predicate on the "password" field.
func PasswordLT(v string) predicate.User {
func PasswordLT(v []byte) predicate.User {
return predicate.User(sql.FieldLT(FieldPassword, v))
}
// PasswordLTE applies the LTE predicate on the "password" field.
func PasswordLTE(v string) predicate.User {
func PasswordLTE(v []byte) predicate.User {
return predicate.User(sql.FieldLTE(FieldPassword, v))
}
// PasswordContains applies the Contains predicate on the "password" field.
func PasswordContains(v string) predicate.User {
return predicate.User(sql.FieldContains(FieldPassword, v))
}
// PasswordHasPrefix applies the HasPrefix predicate on the "password" field.
func PasswordHasPrefix(v string) predicate.User {
return predicate.User(sql.FieldHasPrefix(FieldPassword, v))
}
// PasswordHasSuffix applies the HasSuffix predicate on the "password" field.
func PasswordHasSuffix(v string) predicate.User {
return predicate.User(sql.FieldHasSuffix(FieldPassword, v))
}
// PasswordEqualFold applies the EqualFold predicate on the "password" field.
func PasswordEqualFold(v string) predicate.User {
return predicate.User(sql.FieldEqualFold(FieldPassword, v))
}
// PasswordContainsFold applies the ContainsFold predicate on the "password" field.
func PasswordContainsFold(v string) predicate.User {
return predicate.User(sql.FieldContainsFold(FieldPassword, v))
}
// IsAdminEQ applies the EQ predicate on the "is_admin" field.
func IsAdminEQ(v bool) predicate.User {
return predicate.User(sql.FieldEQ(FieldIsAdmin, v))

@ -34,8 +34,8 @@ func (uc *UserCreate) SetEmail(s string) *UserCreate {
}
// SetPassword sets the "password" field.
func (uc *UserCreate) SetPassword(s string) *UserCreate {
uc.mutation.SetPassword(s)
func (uc *UserCreate) SetPassword(b []byte) *UserCreate {
uc.mutation.SetPassword(b)
return uc
}
@ -248,7 +248,7 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
_node.Email = value
}
if value, ok := uc.mutation.Password(); ok {
_spec.SetField(user.FieldPassword, field.TypeString, value)
_spec.SetField(user.FieldPassword, field.TypeBytes, value)
_node.Password = value
}
if value, ok := uc.mutation.IsAdmin(); ok {

@ -41,8 +41,8 @@ func (uu *UserUpdate) SetEmail(s string) *UserUpdate {
}
// SetPassword sets the "password" field.
func (uu *UserUpdate) SetPassword(s string) *UserUpdate {
uu.mutation.SetPassword(s)
func (uu *UserUpdate) SetPassword(b []byte) *UserUpdate {
uu.mutation.SetPassword(b)
return uu
}
@ -160,7 +160,7 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
_spec.SetField(user.FieldEmail, field.TypeString, value)
}
if value, ok := uu.mutation.Password(); ok {
_spec.SetField(user.FieldPassword, field.TypeString, value)
_spec.SetField(user.FieldPassword, field.TypeBytes, value)
}
if value, ok := uu.mutation.IsAdmin(); ok {
_spec.SetField(user.FieldIsAdmin, field.TypeBool, value)
@ -204,8 +204,8 @@ func (uuo *UserUpdateOne) SetEmail(s string) *UserUpdateOne {
}
// SetPassword sets the "password" field.
func (uuo *UserUpdateOne) SetPassword(s string) *UserUpdateOne {
uuo.mutation.SetPassword(s)
func (uuo *UserUpdateOne) SetPassword(b []byte) *UserUpdateOne {
uuo.mutation.SetPassword(b)
return uuo
}
@ -353,7 +353,7 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error)
_spec.SetField(user.FieldEmail, field.TypeString, value)
}
if value, ok := uuo.mutation.Password(); ok {
_spec.SetField(user.FieldPassword, field.TypeString, value)
_spec.SetField(user.FieldPassword, field.TypeBytes, value)
}
if value, ok := uuo.mutation.IsAdmin(); ok {
_spec.SetField(user.FieldIsAdmin, field.TypeBool, value)

@ -11,6 +11,7 @@ import (
"strings"
"git.dotya.ml/mirre-mt/pcmt/ent"
passwd "git.dotya.ml/mirre-mt/pcmt/modules/password"
moduser "git.dotya.ml/mirre-mt/pcmt/modules/user"
"github.com/gorilla/sessions"
"github.com/labstack/echo-contrib/session"
@ -200,7 +201,7 @@ func SigninPost(client *ent.Client) echo.HandlerFunc {
if usr, err := moduser.QueryUser(ctx, client, username); err == nil {
log.Info("queried user:", &usr.ID)
if usr.Password != password {
if !passwd.Compare(usr.Password, password) {
log.Warn("wrong user credentials, redirecting to /signin")
return c.Redirect(http.StatusFound, "/signin")

@ -7,6 +7,7 @@ import (
"git.dotya.ml/mirre-mt/pcmt/ent"
"git.dotya.ml/mirre-mt/pcmt/ent/user"
passwd "git.dotya.ml/mirre-mt/pcmt/modules/password"
"git.dotya.ml/mirre-mt/pcmt/slogging"
)
@ -14,13 +15,18 @@ import (
func CreateUser(ctx context.Context, client *ent.Client, email, username, password string) (*ent.User, error) {
log := ctx.Value(CtxKey{}).(*slogging.Logger)
digest, err := passwd.GetHash(password)
if err != nil {
log.Errorf("error hashing passoword: %s", err)
return nil, errors.New("could not hash password")
}
u, err := client.User.
Create().
SetEmail(email).
SetUsername(username).
SetPassword(password).
SetPassword(digest).
Save(ctx)
// TODO: saving cleartext password, rework!
if err != nil {
log.Infof("error querying user: %q", err)