adds create user func
This commit is contained in:
parent
c8e33884c0
commit
f59593e9e8
1
go.mod
1
go.mod
@ -10,4 +10,5 @@ require (
|
|||||||
github.com/jmoiron/sqlx v1.2.0
|
github.com/jmoiron/sqlx v1.2.0
|
||||||
github.com/spf13/viper v1.7.1
|
github.com/spf13/viper v1.7.1
|
||||||
github.com/stretchr/testify v1.5.1
|
github.com/stretchr/testify v1.5.1
|
||||||
|
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
|
||||||
)
|
)
|
||||||
|
@ -40,6 +40,10 @@ func (e *errorStore) SelectUserByID(id int) (*models.User, error) {
|
|||||||
return nil, e.error
|
return nil, e.error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *errorStore) InsertUser(user *models.User) (int, error) {
|
||||||
|
return 0, e.error
|
||||||
|
}
|
||||||
|
|
||||||
func (e *errorStore) ConnectionLive() error {
|
func (e *errorStore) ConnectionLive() error {
|
||||||
return e.error
|
return e.error
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ type Store interface {
|
|||||||
InsertPlan(plan *Plan) (int, error)
|
InsertPlan(plan *Plan) (int, error)
|
||||||
SelectActionsByPlanID(plan *Plan) ([]*Action, error)
|
SelectActionsByPlanID(plan *Plan) ([]*Action, error)
|
||||||
SelectUserByID(id int) (*User, error)
|
SelectUserByID(id int) (*User, error)
|
||||||
|
InsertUser(user *User) (int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Model represents a current model item.
|
// Model represents a current model item.
|
||||||
|
@ -47,6 +47,10 @@ func (ms *multiStore) SelectUserByID(id int) (*models.User, error) {
|
|||||||
return &models.User{UserID: int64(id), Username: "test", DisplayName: "Ted Est", Password: []byte("oh no")}, nil
|
return &models.User{UserID: int64(id), Username: "test", DisplayName: "Ted Est", Password: []byte("oh no")}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ms *multiStore) InsertUser(user *models.User) (int, error) {
|
||||||
|
return int(user.UserID), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ms *multiStore) ConnectionLive() error {
|
func (ms *multiStore) ConnectionLive() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
// User represents the full DB user field, for inserts and compares.
|
// User represents the full DB user field, for inserts and compares.
|
||||||
// No reason to return the hashed pw on the route though.
|
// No reason to return the hashed pw on the route though.
|
||||||
type User struct {
|
type User struct {
|
||||||
@ -34,3 +39,38 @@ func (u *User) NoPassword() *UserNoPassword {
|
|||||||
DisplayName: u.DisplayName,
|
DisplayName: u.DisplayName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateUserRequest represents a desired user creation.
|
||||||
|
type CreateUserRequest struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateUser takes in a create user request and returns the ID of the newly created user.
|
||||||
|
func (m *Model) CreateUser(req *CreateUserRequest) (int, error) {
|
||||||
|
if req.Username == "" {
|
||||||
|
return -1, fmt.Errorf("No username provided")
|
||||||
|
}
|
||||||
|
if req.Password == "" {
|
||||||
|
return -1, fmt.Errorf("No password provided")
|
||||||
|
}
|
||||||
|
hash, err := hashPassword(req.Password)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
|
||||||
|
desiredUser := &User{
|
||||||
|
Username: req.Username,
|
||||||
|
DisplayName: req.DisplayName,
|
||||||
|
Password: hash,
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.InsertUser(desiredUser)
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashPassword hashes a password
|
||||||
|
func hashPassword(password string) ([]byte, error) {
|
||||||
|
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 11)
|
||||||
|
return bytes, err
|
||||||
|
}
|
||||||
|
@ -31,16 +31,49 @@ func TestErrorUsers(t *testing.T) {
|
|||||||
assert.NotNil(err)
|
assert.NotNil(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUserNoPassword(t *testing.T) {
|
func TestCreateUser(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
id := int64(3)
|
|
||||||
username := "test"
|
username := "test"
|
||||||
displayName := "Ted Est"
|
displayName := "Ted Est"
|
||||||
pass := []byte("abc")
|
pass := "abc"
|
||||||
u := &models.User{UserID: id, Username: username, DisplayName: displayName, Password: pass}
|
u := &models.CreateUserRequest{Username: username, DisplayName: displayName, Password: pass}
|
||||||
|
|
||||||
unp := u.NoPassword()
|
ss := &multiStore{
|
||||||
assert.EqualValues(id, unp.UserID)
|
[]*models.Action{},
|
||||||
assert.Equal(username, unp.Username)
|
[]*models.Plan{}}
|
||||||
assert.Equal(displayName, unp.DisplayName)
|
m := models.New(ss)
|
||||||
|
|
||||||
|
_, err := m.CreateUser(u)
|
||||||
|
assert.Nil(err)
|
||||||
|
}
|
||||||
|
func TestCreateUserFailValidation(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
username := ""
|
||||||
|
displayName := "Ted Est"
|
||||||
|
pass := "abc"
|
||||||
|
u := &models.CreateUserRequest{Username: username, DisplayName: displayName, Password: pass}
|
||||||
|
|
||||||
|
ss := &multiStore{
|
||||||
|
[]*models.Action{},
|
||||||
|
[]*models.Plan{}}
|
||||||
|
m := models.New(ss)
|
||||||
|
|
||||||
|
_, err := m.CreateUser(u)
|
||||||
|
assert.NotNil(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateUserFailValidationPassword(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
username := "aoeu"
|
||||||
|
displayName := "Ted Est"
|
||||||
|
pass := ""
|
||||||
|
u := &models.CreateUserRequest{Username: username, DisplayName: displayName, Password: pass}
|
||||||
|
|
||||||
|
ss := &multiStore{
|
||||||
|
[]*models.Action{},
|
||||||
|
[]*models.Plan{}}
|
||||||
|
m := models.New(ss)
|
||||||
|
|
||||||
|
_, err := m.CreateUser(u)
|
||||||
|
assert.NotNil(err)
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,10 @@ func (ms *multiStore) SelectUserByID(id int) (*models.User, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ms *multiStore) InsertUser(user *models.User) (int, error) {
|
||||||
|
return int(user.UserID), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ms *multiStore) ConnectionLive() error {
|
func (ms *multiStore) ConnectionLive() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -119,6 +123,10 @@ func (e *errorStore) SelectUserByID(id int) (*models.User, error) {
|
|||||||
return nil, e.error
|
return nil, e.error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *errorStore) InsertUser(user *models.User) (int, error) {
|
||||||
|
return 0, e.error
|
||||||
|
}
|
||||||
|
|
||||||
func (e *errorStore) ConnectionLive() error {
|
func (e *errorStore) ConnectionLive() error {
|
||||||
return e.error
|
return e.error
|
||||||
}
|
}
|
||||||
@ -168,6 +176,10 @@ func (e *onlyCreateStore) SelectUserByID(id int) (*models.User, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *onlyCreateStore) InsertUser(user *models.User) (int, error) {
|
||||||
|
return 0, e.error
|
||||||
|
}
|
||||||
|
|
||||||
func (e *onlyCreateStore) ConnectionLive() error {
|
func (e *onlyCreateStore) ConnectionLive() error {
|
||||||
return e.error
|
return e.error
|
||||||
}
|
}
|
||||||
|
@ -143,3 +143,19 @@ func (store *postgresStore) SelectUserByID(id int) (*models.User, error) {
|
|||||||
}
|
}
|
||||||
return &user, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (store *postgresStore) InsertUser(user *models.User) (int, error) {
|
||||||
|
queryString := store.db.Rebind("INSERT INTO users (username, display_name, password) VALUES (?, ?, ?) RETURNING user_id")
|
||||||
|
tx := store.db.MustBegin()
|
||||||
|
var id int
|
||||||
|
err := tx.Get(&id, queryString, user.Username, user.DisplayName, user.Password)
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ package store_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"gitea.deepak.science/deepak/gogmagog/models"
|
||||||
"github.com/DATA-DOG/go-sqlmock"
|
"github.com/DATA-DOG/go-sqlmock"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"testing"
|
"testing"
|
||||||
@ -62,3 +63,90 @@ func TestErrUserByID(t *testing.T) {
|
|||||||
t.Errorf("unfulfilled expectations: %s", err)
|
t.Errorf("unfulfilled expectations: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInsertUser(t *testing.T) {
|
||||||
|
// setup
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
str, mock := getDbMock(t)
|
||||||
|
username := "test"
|
||||||
|
displayName := "Tom Est"
|
||||||
|
password := []byte("ABC€")
|
||||||
|
usr := &models.User{Username: username, DisplayName: displayName, Password: password}
|
||||||
|
|
||||||
|
idToUse := 8
|
||||||
|
|
||||||
|
rows := sqlmock.NewRows([]string{"user_id"}).AddRow(8)
|
||||||
|
|
||||||
|
mock.ExpectBegin()
|
||||||
|
mock.ExpectQuery(`^INSERT INTO users \(username, display_name, password\) VALUES \(\$1, \$2, \$3\) RETURNING user_id$`).
|
||||||
|
WithArgs(username, displayName, password).
|
||||||
|
WillReturnRows(rows)
|
||||||
|
mock.ExpectCommit()
|
||||||
|
|
||||||
|
// function under test
|
||||||
|
insertedId, err := str.InsertUser(usr)
|
||||||
|
// check results
|
||||||
|
assert.Nil(err)
|
||||||
|
assert.EqualValues(idToUse, insertedId)
|
||||||
|
if err := mock.ExpectationsWereMet(); err != nil {
|
||||||
|
t.Errorf("unfulfilled expectations: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInsertUserErr(t *testing.T) {
|
||||||
|
// setup
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
str, mock := getDbMock(t)
|
||||||
|
username := "test"
|
||||||
|
displayName := "Tom Est"
|
||||||
|
password := []byte("ABC€")
|
||||||
|
usr := &models.User{Username: username, DisplayName: displayName, Password: password}
|
||||||
|
|
||||||
|
mock.ExpectBegin()
|
||||||
|
mock.ExpectQuery(`^INSERT INTO users \(username, display_name, password\) VALUES \(\$1, \$2, \$3\) RETURNING user_id$`).
|
||||||
|
WithArgs(username, displayName, password).
|
||||||
|
WillReturnError(fmt.Errorf("example error"))
|
||||||
|
mock.ExpectRollback()
|
||||||
|
|
||||||
|
// function under test
|
||||||
|
_, err := str.InsertUser(usr)
|
||||||
|
// check results
|
||||||
|
assert.NotNil(err)
|
||||||
|
if err := mock.ExpectationsWereMet(); err != nil {
|
||||||
|
t.Errorf("unfulfilled expectations: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInsertUserCommitErr(t *testing.T) {
|
||||||
|
// setup
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
str, mock := getDbMock(t)
|
||||||
|
username := "test"
|
||||||
|
displayName := "Tom Est"
|
||||||
|
password := []byte("ABC€")
|
||||||
|
usr := &models.User{Username: username, DisplayName: displayName, Password: password}
|
||||||
|
|
||||||
|
idToUse := 8
|
||||||
|
|
||||||
|
rows := sqlmock.NewRows([]string{"user_id"}).AddRow(idToUse)
|
||||||
|
|
||||||
|
mock.ExpectBegin()
|
||||||
|
mock.ExpectQuery(`^INSERT INTO users \(username, display_name, password\) VALUES \(\$1, \$2, \$3\) RETURNING user_id$`).
|
||||||
|
WithArgs(username, displayName, password).
|
||||||
|
WillReturnRows(rows)
|
||||||
|
mock.ExpectCommit().WillReturnError(fmt.Errorf("another error example"))
|
||||||
|
|
||||||
|
// function under test
|
||||||
|
_, err := str.InsertUser(usr)
|
||||||
|
// check results
|
||||||
|
assert.NotNil(err)
|
||||||
|
if err := mock.ExpectationsWereMet(); err != nil {
|
||||||
|
t.Errorf("unfulfilled expectations: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user