65 lines
1.6 KiB
Go
65 lines
1.6 KiB
Go
package db
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
|
|
"github.com/jacek/pamietnik/backend/internal/domain"
|
|
)
|
|
|
|
type UserStore struct {
|
|
pool *pgxpool.Pool
|
|
}
|
|
|
|
func NewUserStore(pool *pgxpool.Pool) *UserStore {
|
|
return &UserStore{pool: pool}
|
|
}
|
|
|
|
// SeedAdminUser creates an admin user if no users exist yet.
|
|
// Returns (true, nil) if the user was created, (false, nil) if users already exist.
|
|
func SeedAdminUser(ctx context.Context, pool *pgxpool.Pool, username, passwordHash string) (bool, error) {
|
|
var count int
|
|
if err := pool.QueryRow(ctx, `SELECT COUNT(*) FROM users`).Scan(&count); err != nil {
|
|
return false, fmt.Errorf("count users: %w", err)
|
|
}
|
|
if count > 0 {
|
|
return false, nil
|
|
}
|
|
_, err := pool.Exec(ctx,
|
|
`INSERT INTO users (username, password_hash, is_admin) VALUES ($1, $2, true)`,
|
|
username, passwordHash,
|
|
)
|
|
if err != nil {
|
|
return false, fmt.Errorf("insert admin: %w", err)
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
// ListUsers returns all users ordered by created_at.
|
|
func (s *UserStore) ListUsers(ctx context.Context) ([]domain.User, error) {
|
|
rows, err := s.pool.Query(ctx,
|
|
`SELECT user_id, username, is_admin, created_at FROM users ORDER BY created_at`,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var users []domain.User
|
|
for rows.Next() {
|
|
var u domain.User
|
|
if err := rows.Scan(&u.UserID, &u.Username, &u.IsAdmin, &u.CreatedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
users = append(users, u)
|
|
}
|
|
return users, rows.Err()
|
|
}
|
|
|
|
// DeleteUser removes a user by ID.
|
|
func (s *UserStore) DeleteUser(ctx context.Context, userID string) error {
|
|
_, err := s.pool.Exec(ctx, `DELETE FROM users WHERE user_id = $1`, userID)
|
|
return err
|
|
}
|