package db import ( "context" "time" "github.com/jackc/pgx/v5" ) // Workstation represents a registered client machine. type Workstation struct { ID string Name string UserID string Hostname string LastSeen time.Time CreatedAt time.Time } // WorkstationRepository provides workstation database operations. type WorkstationRepository struct { db *DB } // NewWorkstationRepository creates a new workstation repository. func NewWorkstationRepository(db *DB) *WorkstationRepository { return &WorkstationRepository{db: db} } // Upsert registers a workstation, updating hostname and last_seen if it already exists. func (r *WorkstationRepository) Upsert(ctx context.Context, w *Workstation) error { return r.db.pool.QueryRow(ctx, ` INSERT INTO workstations (name, user_id, hostname) VALUES ($1, $2, $3) ON CONFLICT (user_id, name) DO UPDATE SET hostname = EXCLUDED.hostname, last_seen = now() RETURNING id, last_seen, created_at `, w.Name, w.UserID, w.Hostname).Scan(&w.ID, &w.LastSeen, &w.CreatedAt) } // GetByID returns a workstation by its ID. func (r *WorkstationRepository) GetByID(ctx context.Context, id string) (*Workstation, error) { w := &Workstation{} err := r.db.pool.QueryRow(ctx, ` SELECT id, name, user_id, hostname, last_seen, created_at FROM workstations WHERE id = $1 `, id).Scan(&w.ID, &w.Name, &w.UserID, &w.Hostname, &w.LastSeen, &w.CreatedAt) if err == pgx.ErrNoRows { return nil, nil } if err != nil { return nil, err } return w, nil } // ListByUser returns all workstations for a user. func (r *WorkstationRepository) ListByUser(ctx context.Context, userID string) ([]*Workstation, error) { rows, err := r.db.pool.Query(ctx, ` SELECT id, name, user_id, hostname, last_seen, created_at FROM workstations WHERE user_id = $1 ORDER BY name `, userID) if err != nil { return nil, err } defer rows.Close() var workstations []*Workstation for rows.Next() { w := &Workstation{} if err := rows.Scan(&w.ID, &w.Name, &w.UserID, &w.Hostname, &w.LastSeen, &w.CreatedAt); err != nil { return nil, err } workstations = append(workstations, w) } return workstations, rows.Err() } // Touch updates a workstation's last_seen timestamp. func (r *WorkstationRepository) Touch(ctx context.Context, id string) error { _, err := r.db.pool.Exec(ctx, ` UPDATE workstations SET last_seen = now() WHERE id = $1 `, id) return err } // Delete removes a workstation. func (r *WorkstationRepository) Delete(ctx context.Context, id string) error { _, err := r.db.pool.Exec(ctx, `DELETE FROM workstations WHERE id = $1`, id) return err }