package repositories import ( "database/sql" "fmt" "go-cook/api/models" "time" "github.com/huandu/go-sqlbuilder" "golang.org/x/crypto/bcrypt" ) const ( TableName string = "users" ) // Creates a new instance of UserRepository with the bound sql func NewUserRepository(conn *sql.DB) UserRepository { return UserRepository{ connection: conn, } } type UserRepository struct { connection *sql.DB } func (ur UserRepository) GetByName(name string) (models.UserModel, error) { builder := sqlbuilder.NewSelectBuilder() builder.Select("*").From("users").Where( builder.E("Name", name), ) query, args := builder.Build() rows, err := ur.connection.Query(query, args...) if err != nil { return models.UserModel{}, err } return ur.processRows(rows)[0], nil } func (ur UserRepository) NewUser(name, password string) (int64, error) { passwordBytes := []byte(password) hash, err := bcrypt.GenerateFromPassword(passwordBytes, bcrypt.DefaultCost) if err != nil { return 0, err } dt := time.Now() queryBuilder := sqlbuilder.NewInsertBuilder() queryBuilder.InsertInto("users") queryBuilder.Cols("Name", "Hash", "LastUpdated", "CreatedAt") queryBuilder.Values(name, string(hash), dt, dt) query, args := queryBuilder.Build() _, err = ur.connection.Exec(query, args...) if err != nil { return 0, err } return 1, nil } func (ur UserRepository) UpdatePassword(name, password string) error { _, err := ur.GetByName(name) if err != nil { return nil } queryBuilder := sqlbuilder.NewUpdateBuilder() queryBuilder.Update(TableName) //queryBuilder.Set return nil } // If the hash matches what we have in the database, an error will not be returned. // If the user does not exist or the hash does not match, an error will be returned func (ur UserRepository) CheckUserHash(name, password string) error { record, err := ur.GetByName(name) if err != nil { return err } err = bcrypt.CompareHashAndPassword([]byte(record.Hash), []byte(password)) if err != nil { return err } return nil } func (ur UserRepository) processRows(rows *sql.Rows) []models.UserModel { items := []models.UserModel{} for rows.Next() { var id int var name string var hash string var createdAt time.Time var lastUpdated time.Time err := rows.Scan(&id, &name, &hash, &createdAt, &lastUpdated) if err != nil { fmt.Println(err) } items = append(items, models.UserModel{ Id: id, Name: name, Hash: hash, CreatedAt: createdAt, LastUpdated: lastUpdated, }) } return items }