diff --git a/server/model/game.go b/server/model/game.go index 5478982..aafa47a 100644 --- a/server/model/game.go +++ b/server/model/game.go @@ -1,7 +1,7 @@ package model type Game struct { - ID int - UserID int - Name string + ID int `json:"id"` + UserID int `json:"user_id"` + Name string `json:"name"` } diff --git a/server/model/game_member.go b/server/model/game_member.go index f4627c8..5abc731 100644 --- a/server/model/game_member.go +++ b/server/model/game_member.go @@ -6,7 +6,7 @@ const ( ) type GameMember struct { - GameID int - UserID int - Role string + GameID int `json:"game_id"` + UserID int `json:"user_id"` + Role string `json:"role"` } diff --git a/server/services/store/game.go b/server/services/store/game.go new file mode 100644 index 0000000..9fcf80f --- /dev/null +++ b/server/services/store/game.go @@ -0,0 +1,113 @@ +package store + +import ( + "database/sql" + + sq "github.com/Masterminds/squirrel" + + "git.ctrlz.es/mgdelacroix/craban/model" +) + +var gameColumns = []string{"id", "user_id", "name"} +var gameMemberColumns = []string{"game_id", "user_id", "role"} + +type GameStore struct { + Conn *sql.DB +} + +func NewGameStore(s *Store) *GameStore { + return &GameStore{Conn: s.Conn} +} + +func (gs *GameStore) Q() sq.StatementBuilderType { + return sq.StatementBuilder.RunWith(gs.Conn) +} + +func (gs *GameStore) gamesFromRows(rows *sql.Rows) ([]*model.Game, error) { + games := []*model.Game{} + + for rows.Next() { + var game model.Game + + err := rows.Scan( + &game.ID, + &game.UserID, + &game.Name, + ) + if err != nil { + return nil, err + } + + games = append(games, &game) + } + + return games, nil +} + +func (gs *GameStore) getGameByCondition(condition sq.Eq) (*model.Game, error) { + games, err := gs.getGamesByCondition(condition) + if err != nil { + return nil, err + } + + return games[0], nil +} + +func (gs *GameStore) getGamesByCondition(condition sq.Eq) ([]*model.Game, error) { + rows, err := gs.Q().Select(userColumns...). + From("games"). + Where(condition). + Query() + if err != nil { + return nil, err + } + defer rows.Close() + + games, err := gs.gamesFromRows(rows) + if err != nil { + return nil, err + } + + if len(games) == 0 { + return nil, sql.ErrNoRows + } + + return games, nil +} + +func (gs *GameStore) GetByID(id int) (*model.Game, error) { + return gs.getGameByCondition(sq.Eq{"id": id}) +} + +func (gs *GameStore) Create(name string, userID int) (*model.Game, error) { + // ToDo: generate transaction + // ToDo: add tests + + res, err := gs.Q().Insert("games"). + Columns(gameColumns[1:]...). + Values(name, userID). + Exec() + if err != nil { + return nil, err + } + + id, err := res.LastInsertId() + if err != nil { + return nil, err + } + + game, err := gs.GetByID(int(id)) + if err != nil { + return nil, err + } + + res, err = gs.Q().Insert("gamemember"). + Columns(gameMemberColumns...). + Values(game.ID, userID, model.RoleGameMaster). + Exec() + if err != nil { + return nil, err + } + + return game, nil +} diff --git a/server/services/store/store.go b/server/services/store/store.go index f0578b3..5693420 100644 --- a/server/services/store/store.go +++ b/server/services/store/store.go @@ -13,6 +13,7 @@ type Store struct { Conn *sql.DB userStore *UserStore + gameStore *GameStore } func addPathOptions(path string) string { @@ -38,6 +39,7 @@ func NewStore(path string) (*Store, error) { // init stores s.userStore = NewUserStore(s) + s.gameStore = NewGameStore(s) return s, nil } @@ -50,6 +52,10 @@ func (s *Store) User() *UserStore { return s.userStore } +func (s *Store) Game() *GameStore { + return s.gameStore +} + func (s *Store) EnsureSchema() error { schema := ` CREATE TABLE IF NOT EXISTS users ( diff --git a/server/services/store/user.go b/server/services/store/user.go index 65935a3..e17a3b4 100644 --- a/server/services/store/user.go +++ b/server/services/store/user.go @@ -47,34 +47,27 @@ func (us *UserStore) usersFromRows(rows *sql.Rows) ([]*model.User, error) { } func (us *UserStore) GetByID(id int) (*model.User, error) { - query := us.Q().Select(userColumns...). - From("users"). - Where(sq.Eq{"id": id}) + return us.getUserByCondition(sq.Eq{"id": id}) +} - rows, err := query.Query() +func (us *UserStore) GetByUsername(username string) (*model.User, error) { + return us.getUserByCondition(sq.Eq{"username": username}) +} + +func (us *UserStore) getUserByCondition(condition sq.Eq) (*model.User, error) { + users, err := us.getUsersByCondition(condition) if err != nil { return nil, err } - defer rows.Close() - - users, err := us.usersFromRows(rows) - if err != nil { - return nil, err - } - - if len(users) == 0 { - return nil, sql.ErrNoRows - } return users[0], nil } -func (us *UserStore) GetByUsername(username string) (*model.User, error) { - query := us.Q().Select(userColumns...). +func (us *UserStore) getUsersByCondition(condition sq.Eq) ([]*model.User, error) { + rows, err := us.Q().Select(userColumns...). From("users"). - Where(sq.Eq{"username": username}) - - rows, err := query.Query() + Where(condition). + Query() if err != nil { return nil, err } @@ -89,7 +82,7 @@ func (us *UserStore) GetByUsername(username string) (*model.User, error) { return nil, sql.ErrNoRows } - return users[0], nil + return users, nil } func (us *UserStore) Create(user *model.User) (*model.User, error) { @@ -112,24 +105,7 @@ func (us *UserStore) Create(user *model.User) (*model.User, error) { // ToDo: add pagination and filtering func (us *UserStore) List() ([]*model.User, error) { - rows, err := us.Q().Select(userColumns...). - From("users"). - Query() - if err != nil { - return nil, err - } - defer rows.Close() - - users, err := us.usersFromRows(rows) - if err != nil { - return nil, err - } - - if len(users) == 0 { - return nil, sql.ErrNoRows - } - - return users, nil + return us.getUsersByCondition(sq.Eq{}) } func (us *UserStore) DeleteByUsername(username string) error {