onasty/internal/store/psql/userepo/userepo.go(view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
package userepo
import (
"context"
"errors"
"github.com/gofrs/uuid/v5"
"github.com/henvic/pgq"
"github.com/jackc/pgx/v5"
"github.com/olexsmir/onasty/internal/dtos"
"github.com/olexsmir/onasty/internal/models"
"github.com/olexsmir/onasty/internal/store/psqlutil"
)
type UserStorer interface {
Create(ctx context.Context, inp dtos.CreateUserDTO) (uuid.UUID, error)
GetUserByCredentials(ctx context.Context, email, password string) (dtos.UserDTO, error)
CheckIfUserExists(ctx context.Context, id uuid.UUID) (bool, error)
}
var _ UserStorer = (*UserRepo)(nil)
type UserRepo struct {
db *psqlutil.DB
}
func New(db *psqlutil.DB) *UserRepo {
return &UserRepo{
db: db,
}
}
func (r *UserRepo) Create(ctx context.Context, inp dtos.CreateUserDTO) (uuid.UUID, error) {
query, args, err := pgq.
Insert("users").
Columns("username", "email", "password", "created_at", "last_login_at").
Values(inp.Username, inp.Email, inp.Password, inp.CreatedAt, inp.LastLoginAt).
Returning("id").
SQL()
if err != nil {
return uuid.UUID{}, err
}
var id uuid.UUID
err = r.db.QueryRow(ctx, query, args...).Scan(&id)
// FIXME: somehow this does return errors but i can't errors.Is them in api layer
if psqlutil.IsDuplicateErr(err, "users_username_key") {
return uuid.UUID{}, models.ErrUsernameIsAlreadyInUse
}
if psqlutil.IsDuplicateErr(err, "users_email_key") {
return uuid.UUID{}, models.ErrUserEmailIsAlreadyInUse
}
return id, err
}
func (r *UserRepo) GetUserByCredentials(
ctx context.Context,
email, password string,
) (dtos.UserDTO, error) {
query, args, err := pgq.
Select("id", "username", "email", "password", "created_at", "last_login_at").
From("users").
Where(pgq.Eq{
"email": email,
"password": password,
}).
SQL()
if err != nil {
return dtos.UserDTO{}, err
}
var user dtos.UserDTO
err = r.db.QueryRow(ctx, query, args...).
Scan(&user.ID, &user.Username, &user.Email, &user.Password, &user.CreatedAt, &user.LastLoginAt)
if errors.Is(err, pgx.ErrNoRows) {
return dtos.UserDTO{}, models.ErrUserNotFound
}
return user, err
}
func (r *UserRepo) CheckIfUserExists(ctx context.Context, id uuid.UUID) (bool, error) {
var exists bool
err := r.db.QueryRow(
ctx,
`SELECT EXISTS(SELECT 1 FROM users WHERE id = $1)`,
id.String(),
).Scan(&exists)
if errors.Is(err, pgx.ErrNoRows) {
return false, models.ErrUserNotFound
}
return exists, err
}
|