Documentation
¶
Overview ¶
Package hover implements the Hover DNS provider client.
Hover ships no official API. This package mimics the browser-side authentication flow exercised by pjslauta/hover-dyn-dns:
- POST https://www.hover.com/signin (username, password) with CSRF `_token` parsed from the signin page.
- POST https://www.hover.com/signin/totp (code, _token).
- Subsequent requests carry the session cookie jar.
TOTP codes are RFC 6238 (HMAC-SHA1, 30s window, 6 digits).
Index ¶
- type Client
- func (c *Client) CreateRecord(ctx context.Context, domainID string, rec DNSRecord) (*DNSRecord, error)
- func (c *Client) DeleteRecord(ctx context.Context, recordID string) error
- func (c *Client) GetDomain(ctx context.Context, domain string) (*Domain, error)
- func (c *Client) ListRecords(ctx context.Context, domain string) ([]DNSRecord, error)
- func (c *Client) Login(ctx context.Context) error
- func (c *Client) UpdateRecord(ctx context.Context, recordID string, rec DNSRecord) error
- type Credentials
- type DNSRecord
- type Domain
- type TOTPSecret
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
UserAgent string
// contains filtered or unexported fields
}
Client is a Hover account-portal client. Concurrency-safe; the underlying cookie jar serialises across goroutines via mu.
func NewClient ¶
func NewClient(creds Credentials, httpClient *http.Client) (*Client, error)
NewClient returns a fresh Client. Pass http=nil for an internal jar-backed http.Client. Tests inject a stub to redirect requests.
func (*Client) CreateRecord ¶
func (c *Client) CreateRecord(ctx context.Context, domainID string, rec DNSRecord) (*DNSRecord, error)
CreateRecord adds a new DNS record for the domain.
func (*Client) DeleteRecord ¶
DeleteRecord removes a record by ID.
func (*Client) GetDomain ¶
GetDomain returns the full Domain struct (including the hover-assigned ID) for the named zone. The ID is required when creating new records via CreateRecord; the human-readable name is not accepted by the POST /api/dns endpoint.
func (*Client) ListRecords ¶
ListRecords returns records for the named zone. Caller MUST pass the apex domain (e.g. "example.com").
func (*Client) Login ¶
Login performs a full authentication cycle against Hover's control panel. It is safe to call when already authenticated — it re-authenticates only when the session is older than sessionStaleAfter (1 hour). Safe for concurrent use; the internal mutex serialises calls.
The underlying auth flow (derived from pjslauta/hover-dyn-dns):
- GET https://www.hover.com/signin → extract CSRF _token
- POST https://www.hover.com/signin (username + password + _token)
- Probe https://www.hover.com/signin/totp for a TOTP form. If a _token is present → account has MFA enabled → submit TOTP code. If the CSRF token is absent → MFA is not enabled → skip.
- Session cookies are stored in the jar for subsequent API calls.
type Credentials ¶
type Credentials struct {
Username string
Password string
TOTPSecret TOTPSecret
}
Credentials carries the operator-provided login material.
type DNSRecord ¶
type DNSRecord struct {
ID string `json:"id,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
Content string `json:"content"`
TTL int `json:"ttl,omitempty"`
}
DNSRecord mirrors Hover's internal API record shape.
type Domain ¶
type Domain struct {
ID string `json:"id"`
Name string `json:"domain_name"`
Records []DNSRecord `json:"entries"`
}
Domain is the API shape returned by GET /api/domains.
type TOTPSecret ¶
type TOTPSecret struct {
// contains filtered or unexported fields
}
TOTPSecret holds a decoded HOTP key. Construct via ParseBase32.
func ParseBase32 ¶
func ParseBase32(seed string) (TOTPSecret, error)
ParseBase32 parses a Google-Authenticator-style base32 seed (case- insensitive, padding optional) into a TOTPSecret. Spaces are stripped so users can paste from the Hover 2FA setup dialog.
func (TOTPSecret) Code ¶
func (s TOTPSecret) Code() string
Code returns the 6-digit code for the current wall-clock time.