Compare commits

..

5 Commits

7 changed files with 138 additions and 18 deletions

1
.gitignore vendored
View File

@ -9,6 +9,7 @@
*.so *.so
*.dylib *.dylib
go-cook go-cook
*.db
# Test binary, built with `go test -c` # Test binary, built with `go test -c`
*.test *.test

8
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,8 @@
{
"cSpell.words": [
"glebarez",
"gocook",
"huandu",
"sqlbuilder"
]
}

5
Justfile Normal file
View File

@ -0,0 +1,5 @@
migrate-up:
GOOSE_DRIVER=sqlite3 GOOSE_DBSTRING=./gocook.db goose -dir ./api/migrations up
migrate-down:
GOOSE_DRIVER=sqlite3 GOOSE_DBSTRING=./gocook.db goose -dir ./api/migrations down

View File

@ -0,0 +1,16 @@
-- +goose Up
-- +goose StatementBegin
SELECT 'up SQL query';
CREATE TABLE USERS (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Hash TEXT NOT NULL,
CreatedAt DATETIME NOT NULL,
LastUpdated DATETIME NOT NULL
)
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
SELECT 'down SQL query';
DROP TABLE IF EXISTS USERS;
-- +goose StatementEnd

View File

@ -1,6 +1,11 @@
package models package models
import "time"
type UserModel struct { type UserModel struct {
Id int
Name string Name string
Hash string Hash string
CreatedAt time.Time
LastUpdated time.Time
} }

View File

@ -2,9 +2,9 @@ package repositories
import ( import (
"database/sql" "database/sql"
"go-cook/api/models"
"errors"
"fmt" "fmt"
"go-cook/api/models"
"time"
"github.com/huandu/go-sqlbuilder" "github.com/huandu/go-sqlbuilder"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@ -25,25 +25,77 @@ func (ur UserRepository) GetByName(name string) (models.UserModel, error) {
builder := sqlbuilder.NewSelectBuilder() builder := sqlbuilder.NewSelectBuilder()
builder.Select("*").From("users").Where( builder.Select("*").From("users").Where(
builder.E("Name", name), builder.E("Name", name),
); )
query, args := builder.Build()
rows, err := ur.connection.Query(query, args...)
if err != nil {
return models.UserModel{}, err
}
return models.UserModel{}, errors.New("user was not found") return ur.processRows(rows)[0], nil
} }
func (ur UserRepository) NewUser(name string, password string) (int, error) { func (ur UserRepository) NewUser(name, password string) (int64, error) {
passwordBytes := []byte(password) passwordBytes := []byte(password)
hash, err := bcrypt.GenerateFromPassword(passwordBytes, bcrypt.DefaultCost) hash, err := bcrypt.GenerateFromPassword(passwordBytes, bcrypt.DefaultCost)
if err != nil { if err != nil {
return 0, err return 0, err
} }
fmt.Println(hash)
query := sqlbuilder.NewInsertBuilder() dt := time.Now()
query.InsertInto("users") queryBuilder := sqlbuilder.NewInsertBuilder()
query.Cols("name", "hash") queryBuilder.InsertInto("users")
query.Values(name, string(hash)) queryBuilder.Cols("Name", "Hash", "LastUpdated", "CreatedAt")
ur.connection.Query(query.Build()) 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 return 1, 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
}

View File

@ -1,7 +1,40 @@
package repositories_test package repositories_test
import "testing" import (
"database/sql"
"go-cook/api/repositories"
"log"
"testing"
func TestNewUser(t *testing.T) { _ "github.com/glebarez/go-sqlite"
)
func TestCanCreateNewUser(t *testing.T) {
db, err := sql.Open("sqlite", "../../gocook.db")
if err != nil {
log.Println("unable to open connection")
t.FailNow()
}
defer db.Close()
repo := repositories.NewUserRepository(db)
updated, err := repo.NewUser("testing", "NotSecure")
if err != nil {
log.Println(err)
t.FailNow()
}
log.Println(updated)
}
func TestCanFindUserInTable(t *testing.T) {
db, err := sql.Open("sqlite", "../../gocook.db")
if err != nil {
log.Println("unable to open connection")
t.FailNow()
}
defer db.Close()
repo := repositories.NewUserRepository(db)
repo.GetByName("testing")
} }