Several fixes and improvements#18
Open
jpmorby wants to merge 14 commits into
Open
Conversation
- Add CURLOPT_CONNECTTIMEOUT (30s) and CURLOPT_TIMEOUT (60s) to prevent hanging requests on unresponsive API endpoints - Return empty OpensrsResponse instead of passing false to constructor when curl_exec fails, preventing downstream type errors - Fix $siganture typo to $signature (cosmetic, no functional impact as the variable was used consistently) - Escape XML attribute values with htmlspecialchars() to prevent malformed XML from special characters in domain contact data - Make raw() null-safe with ?? '' fallback - Cache formatResponse() result in errors() to avoid 3 redundant parses - Return 'ERROR' instead of null from status() when XML is missing, so callers can safely compare without null checks
- Handle null from response->errors() gracefully with fallback message - Add early returns after processResponse() in getDomainContacts, getDomainInfo, getDomainIsLocked, getDomainIsPrivate, and getDomainNameServers to prevent dereferencing null responses - Add null-coalescing for attribute access (lock_state, state) to prevent undefined index errors - Replace gethostbyname() fallback with empty string for missing IPs to avoid DNS lookups that could hang or return wrong data - Guard nameserver_list iteration with ?? [] for missing key - Fix addService() blanket Input::setErrors([]) that was clearing real registration errors along with nameserver errors - Filter empty nameservers before passing to setDomainNameservers
- Add getModuleRowOrFail() helper that sets a user-friendly error when the module row cannot be found, instead of causing a fatal PHP error from accessing properties on null - Replace all 15 direct getModuleRow() calls with getModuleRowOrFail() plus early returns in: getFilteredTldPricing, manageSettings, checkAvailability, getDomainContacts, setDomainContacts, getDomainInfo, getDomainIsLocked, getDomainIsPrivate, setDomainNameservers, lockDomain, unlockDomain, registerDomain, renewDomain, getExpirationDate, getRegistrationDate - Rename misleading $domains_provisioning to $domains_ns in setDomainNameservers (it was instantiating OpensrsDomainsNs) - Add language key for module_row.missing error
- Replace deterministic password (md5 of client ID) with cryptographically random password using random_bytes() - Add null-coalescing defaults for registrar_lock and whois_privacy_state POST values to prevent PHP notices - Add null check for $client before WHOIS fields loop in addService() to prevent fatal error when client_id is missing - Wrap validateConnection() in try-catch and add null safety for response properties to prevent crashes on invalid credentials
- Remove dead foreach(range(1,10)) loops wrapping pricing API calls; the API returns all periods in a single response via all_periods=1, so the loop just overwrote the same key 10 times - Fix .FR domain validation: unset company fields (VAT ID, SIREN, trademark) for 'individual' registrants, not 'organization' ones (the condition was inverted) - Replace naive checkTransferAvailability() inverse-lookup with proper OpensrsDomainsTransfer::checkTransfer() API call that checks the transferrable attribute, with fallback to old behavior
- Mask API key in manage view, showing only last 4 characters - Change API key input to password field in add/edit row views - Remove unused $i variable in client WHOIS tab view - Namespace .FR domain language keys (fr_registrant_type) to prevent collision with .UK registrant_type keys that share the same key name - Update .FR config to reference namespaced language keys
…toreDomain - cancelService: Disables auto-renew and sets expire_action to let domain expire at end of current period via provisioning modify API - suspendService: Delegates to cancelService (standard Blesta pattern for domain modules — no OpenSRS suspend API exists) - unsuspendService: Re-enables auto-renew via provisioning modify - editService: Minimal implementation returning null to preserve existing service meta fields - restoreDomain: Wires up existing OpensrsDomainsProvisioning::redeem() method for domains in the redemption grace period - Add language keys for service lifecycle error messages
- Register tabDns/tabClientDns in service tab arrays, conditional on dns_management feature being enabled for the service - Add manageDns() private method handling: - GET: Fetches DNS zone records via OpensrsDomainsDns::getDnsZone() - POST add_record: Appends new record to zone via setDnsZone() - POST delete_record: Removes record by type and index via setDnsZone() - POST reset_zone: Resets zone to defaults via resetDnsZone() - Create tab_dns.pdt (admin view) with record table, add form, and reset button - Create tab_client_dns.pdt (client view) with Bootstrap-styled table and form matching existing client tab patterns - Add all DNS-related language keys - The OpensrsDomainsDns class already existed but was never wired into the module UI
- Create OpensrsDomainsForwarding class with get/set/create/delete
methods for domain forwarding via the OpenSRS API
- Register tabUrlForwarding/tabClientUrlForwarding in service tabs,
conditional on dns_management feature
- Add manageUrlForwarding() private method handling:
- GET: Fetches forwarding records from DNS zone
- POST set_forwarding: Adds forwarding rule with subdomain,
destination URL, and redirect type (301/302/frame)
- POST delete_forwarding: Removes forwarding rule by index
- Create tab_url_forwarding.pdt (admin) and
tab_client_url_forwarding.pdt (client) views
- Add language keys for all forwarding labels
- Create OpensrsDomainsDnssec class wrapping provisioning modify with
data='dnssec' for add/remove, and get with type='domain_auth_info'
for fetching existing DS records
- Register tabDnssec/tabClientDnssec in service tabs, conditional on
dns_management feature
- Add manageDnssec() private method handling:
- GET: Fetches existing DS records
- POST add_ds_record: Adds DS record with key_tag, algorithm,
digest_type, and digest fields
- POST delete_ds_record: Removes DS record by index
- Create tab_dnssec.pdt (admin) and tab_client_dnssec.pdt (client)
views with DS record table and add form
- Provide algorithm (3-16) and digest type (1,2,4) dropdowns with
human-readable labels
- Add all DNSSEC-related language keys
…or handling - Use type=dnssec for getDnssecRecords (was incorrectly using domain_auth_info) - Log all DNSSEC API fetches via logRequest for easier debugging - Remove erroneous Input::setErrors([]) that silently cleared preceding errors - Fix postal_code being overwritten with 00000 in setDomainContacts - Fix restoreDomain signature to match RegistrarModule parent (add array $vars = []) - Declare $logger property on OpensrsApi to fix dynamic property deprecation - Fix implicit nullable parameter deprecations across all tab and manage methods - Extract per-domain error detail from attributes.details in error responses - Move DNSSEC tabs outside dns_management feature flag (show unconditionally)
…downs Defines Opensrs.countries as a full ISO 3166-1 alpha-2 country code map at the top of the config file. Converts all free-text country inputs (owner, tech, admin, billing whois contacts and .law/.abogado jurisdiction country) to select fields backed by this lookup table. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When deleting the last DNSSEC record, the remaining empty array was serialized as <dt_assoc/> because isset([][0]) is false. OpenSRS requires <dt_array/> for the dnssec attribute, causing "Array/list expected for dnssec attribute" errors on delete. Treat empty arrays as lists so they serialize as dt_array, consistent with non-empty sequential arrays. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR brings the OpenSRS module from a minimal skeleton to a
fully-functional domain registrar module for Blesta, covering API hardening,
new management features, and UX improvements.
Bug fixes & hardening
parsing, add early returns on API failures
getModuleRow() calls; add null checks throughout
random random_bytes() passwords
→ dnssec)
data 10 times
the wrong registrant type
call
.UK keys
declaration warnings
New features
DNS records; reset to defaults
(301/302/frame)
algorithm/digest-type dropdowns
editService, restoreDomain
fields converted from free-text to select
UX
in add/edit row forms