2021-09-11 20:38:38 +01:00
|
|
|
package store
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
2021-09-13 22:16:13 +01:00
|
|
|
"fmt"
|
2021-09-11 20:38:38 +01:00
|
|
|
|
|
|
|
sq "github.com/Masterminds/squirrel"
|
|
|
|
|
2021-09-12 17:57:42 +01:00
|
|
|
"git.ctrlz.es/mgdelacroix/craban/model"
|
2021-09-11 20:38:38 +01:00
|
|
|
)
|
|
|
|
|
2021-09-13 13:52:00 +01:00
|
|
|
var userColumns = []string{"id", "name", "mail", "username", "password", "admin"}
|
2021-09-11 20:38:38 +01:00
|
|
|
|
|
|
|
type UserStore struct {
|
|
|
|
Conn *sql.DB
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewUserStore(s *Store) *UserStore {
|
|
|
|
return &UserStore{Conn: s.Conn}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (us *UserStore) Q() sq.StatementBuilderType {
|
|
|
|
return sq.StatementBuilder.RunWith(us.Conn)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (us *UserStore) usersFromRows(rows *sql.Rows) ([]*model.User, error) {
|
|
|
|
users := []*model.User{}
|
|
|
|
|
|
|
|
for rows.Next() {
|
|
|
|
var user model.User
|
|
|
|
|
|
|
|
err := rows.Scan(
|
|
|
|
&user.ID,
|
|
|
|
&user.Name,
|
|
|
|
&user.Mail,
|
|
|
|
&user.Username,
|
|
|
|
&user.Password,
|
2021-09-13 13:52:00 +01:00
|
|
|
&user.Admin,
|
2021-09-11 20:38:38 +01:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
users = append(users, &user)
|
|
|
|
}
|
|
|
|
|
|
|
|
return users, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (us *UserStore) GetByID(id int) (*model.User, error) {
|
2021-09-13 14:21:37 +01:00
|
|
|
return us.getUserByCondition(sq.Eq{"id": id})
|
|
|
|
}
|
2021-09-11 20:38:38 +01:00
|
|
|
|
2021-09-13 14:21:37 +01:00
|
|
|
func (us *UserStore) GetByUsername(username string) (*model.User, error) {
|
|
|
|
return us.getUserByCondition(sq.Eq{"username": username})
|
|
|
|
}
|
2021-09-11 20:38:38 +01:00
|
|
|
|
2021-09-13 14:21:37 +01:00
|
|
|
func (us *UserStore) getUserByCondition(condition sq.Eq) (*model.User, error) {
|
|
|
|
users, err := us.getUsersByCondition(condition)
|
2021-09-13 11:46:43 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return users[0], nil
|
|
|
|
}
|
|
|
|
|
2021-09-13 14:21:37 +01:00
|
|
|
func (us *UserStore) getUsersByCondition(condition sq.Eq) ([]*model.User, error) {
|
|
|
|
rows, err := us.Q().Select(userColumns...).
|
2021-09-13 11:46:43 +01:00
|
|
|
From("users").
|
2021-09-13 14:21:37 +01:00
|
|
|
Where(condition).
|
|
|
|
Query()
|
2021-09-13 11:46:43 +01:00
|
|
|
if err != nil {
|
2021-09-13 22:16:13 +01:00
|
|
|
return nil, fmt.Errorf("cannot get users: %w", err)
|
2021-09-13 11:46:43 +01:00
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
users, err := us.usersFromRows(rows)
|
2021-09-11 20:38:38 +01:00
|
|
|
if err != nil {
|
2021-09-13 22:16:13 +01:00
|
|
|
return nil, fmt.Errorf("cannot get users from rows: %w", err)
|
2021-09-11 20:38:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(users) == 0 {
|
|
|
|
return nil, sql.ErrNoRows
|
|
|
|
}
|
|
|
|
|
2021-09-13 14:21:37 +01:00
|
|
|
return users, nil
|
2021-09-11 20:38:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (us *UserStore) Create(user *model.User) (*model.User, error) {
|
|
|
|
query := us.Q().Insert("users").
|
2021-09-11 22:50:53 +01:00
|
|
|
Columns(userColumns[1:]...).
|
2021-09-13 13:52:00 +01:00
|
|
|
Values(user.Name, user.Mail, user.Username, user.Password, user.Admin)
|
2021-09-11 20:38:38 +01:00
|
|
|
|
|
|
|
res, err := query.Exec()
|
|
|
|
if err != nil {
|
2021-09-13 22:16:13 +01:00
|
|
|
return nil, fmt.Errorf("cannot insert user: %w", err)
|
2021-09-11 20:38:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
id, err := res.LastInsertId()
|
|
|
|
if err != nil {
|
2021-09-13 22:16:13 +01:00
|
|
|
return nil, fmt.Errorf("cannot get last insert id for created user: %w", err)
|
2021-09-11 20:38:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return us.GetByID(int(id))
|
|
|
|
}
|
2021-09-13 11:16:25 +01:00
|
|
|
|
|
|
|
// ToDo: add pagination and filtering
|
|
|
|
func (us *UserStore) List() ([]*model.User, error) {
|
2021-09-13 14:21:37 +01:00
|
|
|
return us.getUsersByCondition(sq.Eq{})
|
2021-09-13 11:16:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (us *UserStore) DeleteByUsername(username string) error {
|
2021-09-13 22:22:04 +01:00
|
|
|
// ToDo: add transaction
|
|
|
|
// ToDo: manage user owned games, probably at app level
|
|
|
|
|
2021-09-13 22:21:31 +01:00
|
|
|
user, err := us.GetByUsername(username)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("cannot get user for deletion: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = us.Q().Delete("users").
|
2021-09-13 11:16:25 +01:00
|
|
|
Where(sq.Eq{"username": username}).
|
|
|
|
Exec()
|
2021-09-13 22:21:31 +01:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("cannot delete user: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = us.Q().Delete("gamemembers").
|
|
|
|
Where(sq.Eq{"user_id": user.ID}).
|
|
|
|
Exec()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("cannot delete game members when deleting user: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2021-09-13 11:16:25 +01:00
|
|
|
}
|