package user import ( "net/http" "strings" "time" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" "github.com/shroff/phylum/server/internal/core/errors" ) var ErrNotFound = errors.NewError(http.StatusNotFound, "user_not_found", "no such user") func (m manager) ListUsers(since *time.Time) ([]User, error) { s := pgtype.Timestamp{ Valid: true, } if since != nil { s.Time = *since } const q = "SELECT id, email, display_name, home, permissions FROM users WHERE modified > $1::TIMESTAMP" if rows, err := m.db.Query(q, s); err != nil { return nil, err } else { return pgx.CollectRows(rows, scanUser) } } func (m manager) UserByEmail(email string) (User, error) { const q = "SELECT id, email, display_name, home, permissions FROM users WHERE email = $1" if rows, err := m.db.Query(q, strings.ToLower(email)); err != nil { return User{}, err } else if u, err := pgx.CollectExactlyOneRow(rows, scanUser); err != nil { if errors.Is(err, pgx.ErrNoRows) { err = ErrNotFound } return User{}, err } else { return u, nil } } func (m manager) userPasswordHashByEmail(email string) (user User, passwordHash string, err error) { const q = "SELECT id, email, display_name, home, permissions, password_hash FROM users WHERE email = $1" row := m.db.QueryRow(q, strings.ToLower(email)) err = row.Scan( &user.ID, &user.Email, &user.DisplayName, &user.Home, &user.Permissions, &passwordHash) if errors.Is(err, pgx.ErrNoRows) { err = ErrNotFound } return } func (m manager) UserHome(email string) (pgtype.UUID, error) { const q = "SELECT home FROM users WHERE email = $1" row := m.db.QueryRow(q, strings.ToLower(email)) var id pgtype.UUID if err := row.Scan(&id); err == nil { if !id.Valid { err = ErrNotFound } return id, err } else { if errors.Is(err, pgx.ErrNoRows) { err = ErrNotFound } return pgtype.UUID{}, err } }