package repository import ( "context" "errors" "fmt" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "github.com/panelhosting/panel/internal/models" ) var ErrServerNotFound = errors.New("server not found") type ServerRepository struct { pool *pgxpool.Pool } func NewServerRepository(pool *pgxpool.Pool) *ServerRepository { return &ServerRepository{pool: pool} } func (r *ServerRepository) Count(ctx context.Context) (int64, error) { var count int64 err := r.pool.QueryRow(ctx, `SELECT COUNT(*) FROM servers`).Scan(&count) return count, err } func (r *ServerRepository) CreateDefault(ctx context.Context, name, hostname, ip string) (*models.Server, error) { const q = ` INSERT INTO servers (name, hostname, ip_address, status) VALUES ($1, $2, $3::inet, 'online') RETURNING id, uuid, name, hostname, ip_address::text, ssh_port, status, agent_version, os_info, resources, settings, last_seen_at, created_at, updated_at ` var s models.Server err := r.pool.QueryRow(ctx, q, name, hostname, ip).Scan( &s.ID, &s.UUID, &s.Name, &s.Hostname, &s.IPAddress, &s.SSHPort, &s.Status, &s.AgentVersion, &s.OSInfo, &s.Resources, &s.Settings, &s.LastSeenAt, &s.CreatedAt, &s.UpdatedAt, ) if err != nil { return nil, fmt.Errorf("create server: %w", err) } return &s, nil } func (r *ServerRepository) GetFirst(ctx context.Context) (*models.Server, error) { const q = ` SELECT id, uuid, name, hostname, ip_address::text, ssh_port, status, agent_version, os_info, resources, settings, last_seen_at, created_at, updated_at FROM servers ORDER BY id LIMIT 1 ` var s models.Server err := r.pool.QueryRow(ctx, q).Scan( &s.ID, &s.UUID, &s.Name, &s.Hostname, &s.IPAddress, &s.SSHPort, &s.Status, &s.AgentVersion, &s.OSInfo, &s.Resources, &s.Settings, &s.LastSeenAt, &s.CreatedAt, &s.UpdatedAt, ) if errors.Is(err, pgx.ErrNoRows) { return nil, ErrServerNotFound } if err != nil { return nil, fmt.Errorf("get first server: %w", err) } return &s, nil } func (r *ServerRepository) GetByID(ctx context.Context, id int64) (*models.Server, error) { const q = ` SELECT id, uuid, name, hostname, ip_address::text, ssh_port, status, agent_version, os_info, resources, settings, last_seen_at, created_at, updated_at FROM servers WHERE id = $1 ` var s models.Server err := r.pool.QueryRow(ctx, q, id).Scan( &s.ID, &s.UUID, &s.Name, &s.Hostname, &s.IPAddress, &s.SSHPort, &s.Status, &s.AgentVersion, &s.OSInfo, &s.Resources, &s.Settings, &s.LastSeenAt, &s.CreatedAt, &s.UpdatedAt, ) if errors.Is(err, pgx.ErrNoRows) { return nil, ErrServerNotFound } if err != nil { return nil, fmt.Errorf("get server: %w", err) } return &s, nil } func (r *ServerRepository) GrantAccess(ctx context.Context, userID, serverID int64, canManage bool) error { const q = ` INSERT INTO server_access (user_id, server_id, can_manage) VALUES ($1, $2, $3) ON CONFLICT (user_id, server_id) DO NOTHING ` _, err := r.pool.Exec(ctx, q, userID, serverID, canManage) return err }