Skip to content

Commit

Permalink
Add user store
Browse files Browse the repository at this point in the history
  • Loading branch information
jfontan committed Jul 17, 2021
1 parent adf2ded commit d5f77dd
Show file tree
Hide file tree
Showing 3 changed files with 228 additions and 1 deletion.
2 changes: 1 addition & 1 deletion server/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

var (
ErrNotFound = fmt.Errorf("effect not found")
ErrNotFound = fmt.Errorf("not found")
)

type Effect struct {
Expand Down
145 changes: 145 additions & 0 deletions server/store/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package store

import (
"fmt"
"time"

"github.com/jmoiron/sqlx"
)

type Role string

const (
RoleAdmin = "admin"
RoleModerator = "moderator"
RoleUser = "user"
)

type User struct {
ID int `db:"id"`
Name string `db:"name"`
Password string `db:"password"`
Email string `db:"email"`
Role Role `db:"role"`
Active bool `db:"active"`
CreatedAt time.Time `db:"created_at"`
}

const (
sqlCreateUsers = `
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
password TEXT,
email TEXT,
role TEXT,
active INTEGER,
created_at TIMESTAMP
)
`

sqlIndexUsersName = `
CREATE INDEX IF NOT EXISTS idx_users_name ON users (name)
`
)

type Users struct {
db *sqlx.DB
}

func NewUsers(db *sqlx.DB) (*Users, error) {
u := &Users{
db: db,
}
err := u.Init()
if err != nil {
return nil, err
}
return u, nil
}

func (s *Users) Init() error {
_, err := s.db.Exec(sqlCreateUsers)
if err != nil {
return fmt.Errorf("could not create table users: %w", err)
}

_, err = s.db.Exec(sqlIndexUsersName)
if err != nil {
return fmt.Errorf("could not create users(name): %w", err)
}
return nil
}

const (
sqlSelectUser = `
SELECT * FROM users
WHERE name = ?
`

sqlInsertUser = `
INSERT INTO users (
name,
password,
email,
role,
active,
created_at
) VALUES(
:name,
:password,
:email,
:role,
:active,
:created_at
)
`

sqlUpdateUser = `
UPDATE users
SET
password = :password,
email = :email,
role = :role,
active = :active,
created_at = :created_at
WHERE name = :name
`
)

func (s *Users) User(name string) (User, error) {
var u User
r := s.db.QueryRowx(sqlSelectUser, name)
err := r.StructScan(&u)
if err != nil {
return User{}, fmt.Errorf("could not get user: %w", err)
}

return u, nil
}

func (s *Users) Add(user User) error {
if user.CreatedAt.IsZero() {
user.CreatedAt = time.Now()
}
_, err := s.db.NamedExec(sqlInsertUser, user)
if err != nil {
return fmt.Errorf("could not add user: %w", err)
}
return nil
}

func (s *Users) Update(user User) error {
r, err := s.db.NamedExec(sqlUpdateUser, user)
if err != nil {
return fmt.Errorf("could not update user: %w", err)
}
rows, err := r.RowsAffected()
if err != nil {
return fmt.Errorf("could not get affected rows: %w", err)
}
if rows == 0 {
return ErrNotFound
}
return nil
}
82 changes: 82 additions & 0 deletions server/store/user_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package store

import (
"database/sql"
"errors"
"testing"
"time"

"github.com/jmoiron/sqlx"
"github.com/stretchr/testify/require"
)

var (
testDatabase = ":memory:"
testTime = time.Date(2021, time.January, 1, 0, 0, 0, 0, time.UTC)
testUser = User{
Name: "test",
Password: "password",
Email: "email",
Role: RoleAdmin,
Active: true,
CreatedAt: testTime,
}
)

func TestUserAdd(t *testing.T) {
db, err := sqlx.Connect("sqlite", testDatabase)
require.NoError(t, err)

users, err := NewUsers(db)
require.NoError(t, err)

u, err := users.User("test")
require.Error(t, err)
require.True(t, errors.Is(err, sql.ErrNoRows))
require.Equal(t, User{}, u)

err = users.Add(testUser)
require.NoError(t, err)

u, err = users.User("test")
require.NoError(t, err)
require.Equal(t, 1, u.ID)
u.ID = 0
require.Equal(t, testUser, u)
}

func TestUserUpdate(t *testing.T) {
db, err := sqlx.Connect("sqlite", testDatabase)
require.NoError(t, err)

users, err := NewUsers(db)
require.NoError(t, err)

err = users.Add(testUser)
require.NoError(t, err)

expected := User{
Name: "test",
Password: "newpassword",
Email: "newemail",
Role: RoleModerator,
Active: false,
CreatedAt: time.Now(),
}
err = users.Update(expected)
require.NoError(t, err)

u, err := users.User("test")
require.NoError(t, err)
require.Equal(t, expected.Name, u.Name)
require.Equal(t, expected.Password, u.Password)
require.Equal(t, expected.Email, u.Email)
require.Equal(t, expected.Role, u.Role)
require.Equal(t, expected.Active, u.Active)
require.True(t, expected.CreatedAt.Equal(u.CreatedAt))

expected.Name = "inexistent"
err = users.Update(expected)
require.Error(t, err)
require.True(t, errors.Is(err, ErrNotFound))
}

0 comments on commit d5f77dd

Please sign in to comment.