GroupZonesController
class GroupZonesController extends PublicApiController (View source)
Constants
| protected MAX_PAGE_SIZE |
|
Properties
| protected PDO | $db | from BaseController | |
| protected array | $requestData | from BaseController | |
| protected MessageService | $messageService | from BaseController | |
| protected ConfigurationManager | $config | from BaseController | |
| protected LoggerInterface | $logger | from PublicApiController | |
| protected Request | $request | from AbstractApiController | |
| protected array | $pathParameters | from PublicApiController | |
| protected int | $authenticatedUserId | from PublicApiController | |
| protected ApiKeyScope|null | $apiKeyScope | Permission scope of the API key used for this request. Null when the request authenticated via HTTP Basic auth or no key scope could be resolved, in which case {self::getApiKeyScope()} returns an unrestricted scope. |
from PublicApiController |
Methods
Handle group zone-related requests
PublicApiController constructor
API requests authenticate per call with an API key or HTTP Basic credentials, so there is no session-bound form token to check.
Get a module config value with legacy fallback.
Renders a template with the given parameters.
Build a PdnsCapabilities snapshot from the session-cached PowerDNS version. Constant-time and synchronous - never triggers detection, never makes a network call. Safe to call from render() on every page.
Capabilities to use when filtering selectable record types, or null to skip version filtering entirely.
Trigger a session-cached refresh of PowerDNS version + capabilities.
Redirects to a specified URL with optional arguments.
Sets a message to be displayed for a specific script.
Checks a condition and displays an error message if the condition is true.
Renders a pagination widget for a paginated listing.
Check if the logged-in user has the given permission
Whether the logged-in user wants the page to span the full browser width
Check if the logged-in user owns the given zone directly or via group membership
Stops the request unless the current user may open the zone (showError exits).
The zone service the API uses, told what the connected server supports.
What the enabled modules offer for a capability (wizard actions, lookup links, export formats), honouring each module's admin restriction.
Why the current user cannot pick any zone owner (groups_only mode), or null.
Owner and groups of the add-zone forms, checked against the shared ownership rules.
No description
No description
No description
Group names keyed by id, for the group column of the zone lists.
Rebuilds ordername/auth after a record write so signed zones keep answering.
Flash the outcome of a zone write to a page: the given text on success, the result's reason on failure.
Sets the current page identifier used for navigation highlighting.
Checks if the user has a specific permission and displays an error message if not.
Displays an error message.
Gets a safe value from the request data.
Sets validation constraints for the request data.
Displays the first validation error.
Adds a system-wide message that will be displayed on any page
Override to record every public API response in the audit log
Return an error response
Extract a string value from input array.
Extract an integer value from input array.
Extract a boolean value from input array.
Extract an integer value that also accepts JSON booleans and "true"/"false" strings.
Extract a template ID from input. Accepts string IDs, "none", and JSON integers.
Authenticate the API request using API key or HTTP Basic auth
Check if the current API endpoint requires authentication Can be overridden in child classes for public endpoints
Return API response with standard format
Return API error response
Pick the right "cannot edit this zone's records" message: read-only zones (Secondary, Consumer) replicate from a primary and are rejected for a different reason than a missing edit permission. Keeps the public error contract accurate for both cases.
Get the permission scope of the API key for this request. Requests without a key scope (Basic auth, or an unresolvable key) are treated as unrestricted.
Reject the request with 403 when the API key's read-only/operation scope does not permit the HTTP method. This is a request-global gate.
Operations the current request performs, all of which the API key must permit. Defaults to the single operation implied by the HTTP method.
Send a 403 for an operation the API key may not perform, and stop.
Guard a zone-scoped endpoint against the API key's zone restriction.
Apply V2 record-content formatting.
The API wording for a refused record write: a duplicate and a backend fault keep the contract strings, every other refusal carries the manager's reason.
Record names are stored as punycode and always carry the zone suffix.
Strip quotes from single-string TXT records for V2 API responses
Handle exception and return JSON error response
Details
void
run()
Handle group zone-related requests
__construct(array $request, array $pathParameters = [])
PublicApiController constructor
protected bool
requiresCsrfValidation()
API requests authenticate per call with an API key or HTTP Basic credentials, so there is no session-bound form token to check.
bool
isPost()
Checks if the current request is a POST request.
ConfigurationManager
getConfig()
Gets the application configuration.
protected mixed
getModuleConfig(string $module, string $key, mixed $default = null)
Get a module config value with legacy fallback.
Checks modules.
void
render(string $template, array $params)
Renders a template with the given parameters.
protected PdnsCapabilities
getPdnsCapabilities()
Build a PdnsCapabilities snapshot from the session-cached PowerDNS version. Constant-time and synchronous - never triggers detection, never makes a network call. Safe to call from render() on every page.
Controllers that want a freshly-detected version should call refreshPdnsCapabilities() explicitly before rendering so they own the latency cost rather than imposing it on every other page.
protected PdnsCapabilities|null
getRecordTypeCapabilities()
Capabilities to use when filtering selectable record types, or null to skip version filtering entirely.
Only API backends can report their PowerDNS version, so only there can we safely hide types a newer-than-server feature would need. On SQL backends the version is never known, and strict-unknown filtering would wrongly and permanently drop valid types (HTTPS, SVCB, ZONEMD, ...) from every form. Returning null there leaves the configured/default type list intact.
protected void
refreshPdnsCapabilities()
Trigger a session-cached refresh of PowerDNS version + capabilities.
Makes at most one API call per minute (rate-limited via the session
timestamp pdns_version_last_attempt) and is a no-op when no PowerDNS
API is configured. Runs in both API and SQL backend modes: the
version display is useful in either mode whenever pdns_api is
configured, even though capability gates only matter for API mode.
Page renders that don't call this just read whatever is already cached.
void
validateCsrfToken()
Validates the CSRF token from the request.
void
redirect(string $url, array $args = [])
Redirects to a specified URL with optional arguments.
Automatically prepends base_url_prefix for subfolder deployments.
void
setMessage(string $script, string $type, string $content)
Sets a message to be displayed for a specific script.
array|null
getMessages(string $script)
Gets messages for a specific script.
void
checkCondition(bool $condition, string $errorMessage)
Checks a condition and displays an error message if the condition is true.
protected UserPreferenceService
createUserPreferenceService()
No description
protected UserTimezoneService
createUserTimezoneService()
No description
protected PaginationService
createPaginationService()
No description
protected string
presentPagination(int $totalItems, int $itemsPerPage, string $path, array $queryParams = [])
Renders a pagination widget for a paginated listing.
$path is the route with the {PageNumber} placeholder already in place
(e.g. '/zones/forward?start={PageNumber}'). $queryParams are extra
key => value pairs appended urlencoded, in order, skipping absent and blank values.
protected DnsBackendProvider
createDnsBackendProvider()
No description
protected DnsDataService
createDnsDataService()
No description
protected ZoneRepositoryInterface
createZoneRepository()
No description
protected DomainRepositoryInterface
createDomainRepository()
No description
protected RecordRepositoryInterface
createRecordRepository()
No description
protected UserRepository
createUserRepository()
No description
protected PermissionService
createPermissionService()
No description
protected UserManagementService
createUserManagementService()
No description
protected ApiPermissionService
createApiPermissionService()
No description
protected bool
hasPermission(string $permission)
Check if the logged-in user has the given permission
protected bool
getWideLayout()
Whether the logged-in user wants the page to span the full browser width
protected bool
isZoneOwner(int $zoneId)
Check if the logged-in user owns the given zone directly or via group membership
protected void
requireZoneView(int $zoneId)
Stops the request unless the current user may open the zone (showError exits).
protected UserGroupRepositoryInterface
createUserGroupRepository()
No description
protected ZoneManagementService
createZoneManagementService()
The zone service the API uses, told what the connected server supports.
protected ModuleRegistry
moduleRegistry()
Enabled modules, loaded once per request.
protected array
moduleCapabilityData(string $capability, array $context = [])
What the enabled modules offer for a capability (wizard actions, lookup links, export formats), honouring each module's admin restriction.
protected bool
moduleProvides(string $capability)
No description
protected AuditService
createAuditService()
No description
protected ZoneMetadataService
createZoneMetadataService()
No description
protected ZoneSigningService
createZoneSigningService()
No description
protected ZoneCreateOwnershipResolver
createZoneCreateOwnershipResolver()
No description
protected string|null
zoneOwnerOptionsBlocker()
Why the current user cannot pick any zone owner (groups_only mode), or null.
protected ZoneOwnershipResolution
resolveZoneOwnershipFromForm(Request $request)
Owner and groups of the add-zone forms, checked against the shared ownership rules.
protected UserGroupMemberRepositoryInterface
createUserGroupMemberRepository()
No description
protected DbPermissionTemplateRepository
createPermissionTemplateRepository()
No description
protected PermissionTemplateWriteService
createPermissionTemplateWriteService()
No description
protected DashboardStatsService
createDashboardStatsService()
No description
protected ZoneEditService
createZoneEditService()
No description
protected ZoneListPermissionService
createZoneListPermissionService()
No description
protected array
groupNamesById()
Group names keyed by id, for the group column of the zone lists.
protected ZoneGroupRepositoryInterface
createZoneGroupRepository()
No description
protected ReverseTtlResolver
createReverseTtlResolver()
No description
protected RecordManagerInterface
createRecordManager()
No description
protected SOARecordManagerInterface
createSOARecordManager()
No description
protected DnssecProvider
createDnssecProvider()
No description
protected void
rectifyZoneAfterWrite(string $zoneName)
Rebuilds ordername/auth after a record write so signed zones keep answering.
Call after the transaction commits: the rectifier reads committed rows.
protected RecordManagerService
createRecordManagerService()
No description
protected RecordAddService
createRecordAddService()
No description
protected ReverseRecordCreator
createReverseRecordCreator()
No description
protected BatchReverseRecordCreator
createBatchReverseRecordCreator()
No description
protected DomainManagerInterface
createDomainManager()
No description
protected CatalogZoneService
createCatalogZoneService()
No description
protected RepositoryFactory
getRepositoryFactory(DnsBackendProvider|null $backendProvider = null)
No description
protected int|null
getCurrentUserId()
Get current user ID
protected void
reportZoneWrite(string $script, ZoneWriteResult $result, string $successMessage)
Flash the outcome of a zone write to a page: the given text on success, the result's reason on failure.
protected UserContextService
getUserContextService()
Get the user context service
protected void
setCurrentPage(string $page)
Sets the current page identifier used for navigation highlighting.
protected void
setPageTitle(string $title)
Sets the page title displayed in the header.
void
checkPermission(string $permission, string $errorMessage)
Checks if the user has a specific permission and displays an error message if not.
void
showError(string $error, string|null $recordName = null)
Displays an error message.
array
getRequest()
Gets the request data.
string
getSafeRequestValue(string $key)
Gets a safe value from the request data.
void
setValidationConstraints(array $constraints)
Sets validation constraints for the request data.
void
setRequestRules(array $rules)
Sets validation rules for the request data.
bool
doValidateRequest(array|null $data = null)
Validates the request data.
void
showFirstValidationError(array|null $data = null)
Displays the first validation error.
void
addSystemMessage(string $type, string $content)
Adds a system-wide message that will be displayed on any page
protected bool
isJsonRequest()
Checks if the current request is a JSON request
protected array|null
getJsonInput()
Get JSON input from request body
protected JsonResponse
returnJsonResponse(mixed $data, int $status = 200, array $headers = [])
Override to record every public API response in the audit log
protected JsonResponse
returnErrorResponse(string $message, int $status = 400, string|null $code = null)
Return an error response
protected string|null
inputString(array $input, string $key, string|null $default = null)
Extract a string value from input array.
Returns default only when key is absent; returns null for present non-string values so callers can distinguish missing from malformed.
protected int|null
inputInt(array $input, string $key, int|null $default = null)
Extract an integer value from input array.
Accepts integers and numeric strings. Returns default when key is absent; returns null for present non-numeric values.
protected bool|null
inputBool(array $input, string $key, bool|null $default = null)
Extract a boolean value from input array.
Accepts native booleans, int 1/0, and strings "1"/"0"/"true"/"false" for form-encoded compatibility. Returns default when key is absent; returns null for present invalid values.
protected int|null
inputIntFromBool(array $input, string $key, int|null $default = 0)
Extract an integer value that also accepts JSON booleans and "true"/"false" strings.
Use for fields like 'disabled' where the API documents boolean but stores as int. Returns default when key is absent; returns null for present invalid values.
protected string
inputTemplate(array $input)
Extract a template ID from input. Accepts string IDs, "none", and JSON integers.
Rejects booleans, arrays, and non-numeric strings.
protected void
authenticateApiRequest()
Authenticate the API request using API key or HTTP Basic auth
protected string|null
getApiKeyFromRequest()
Get API key from request headers
protected bool
validateApiKey(string|null $apiKey)
Validate the API key
protected bool
requiresAuthentication()
Check if the current API endpoint requires authentication Can be overridden in child classes for public endpoints
protected JsonResponse
returnApiResponse(mixed $data, bool $success = true, string|null $message = null, int $status = 200, array $additionalFields = [])
Return API response with standard format
protected JsonResponse
returnApiError(string $message, int $status = 400, mixed $data = null, array $headers = [])
Return API error response
protected string
zoneEditDeniedMessage(string|null $zoneType)
Pick the right "cannot edit this zone's records" message: read-only zones (Secondary, Consumer) replicate from a primary and are rejected for a different reason than a missing edit permission. Keeps the public error contract accurate for both cases.
protected int
getAuthenticatedUserId()
Get the authenticated user ID (stateless)
protected string
getAuthenticatedUsername()
No description
protected ApiKeyScope
getApiKeyScope()
Get the permission scope of the API key for this request. Requests without a key scope (Basic auth, or an unresolvable key) are treated as unrestricted.
protected void
enforceApiKeyMethodScope()
Reject the request with 403 when the API key's read-only/operation scope does not permit the HTTP method. This is a request-global gate.
protected array
requiredApiKeyOperations()
Operations the current request performs, all of which the API key must permit. Defaults to the single operation implied by the HTTP method.
Override for endpoints where the method is not a 1:1 operation mapping: return the exact set (e.g. [create, update] for an upsert), or [] to skip the central check and enforce the operation scope inside the handler.
protected void
sendApiKeyOperationForbidden()
Send a 403 for an operation the API key may not perform, and stop.
protected JsonResponse|null
enforceApiKeyZoneScope(int $zoneId)
Guard a zone-scoped endpoint against the API key's zone restriction.
Returns a 403 response when the zone is out of scope, or null when allowed.
Callers return the response directly: if (($r = $this->enforceApiKeyZoneScope($id)) !== null) { return $r; }
protected string
formatV2RecordContent(string $type, string $content)
Apply V2 record-content formatting.
V2 always quotes single-string TXT records, even when dns.txt_auto_quote is off, so records round-trip: create quotes, read strips, update must re-quote. Used by create and update paths alike so stored content stays consistent.
protected string
recordWriteErrorMessage(RecordWriteResult $result, string $backendFailureText)
The API wording for a refused record write: a duplicate and a backend fault keep the contract strings, every other refusal carries the manager's reason.
protected string
normalizeV2RecordName(string $name, string $zoneName)
Record names are stored as punycode and always carry the zone suffix.
protected string
stripTxtQuotes(string $content, string $type)
Strip quotes from single-string TXT records for V2 API responses
V2 responses present single-string TXT content unquoted regardless of stored form (zone records are force-quoted on write, template records only when dns.txt_auto_quote is on). Multi-string TXT records (e.g., "part1" "part2") are preserved as-is since they represent long values split across multiple strings.
protected JsonResponse
handleException(Throwable $e, string $context, string $userMessage = 'An error occurred', int $statusCode = 500)
Handle exception and return JSON error response
Catches all throwables (Exception, TypeError, Error, etc.) and returns a proper JSON error response instead of letting PHP display HTML errors. Logs detailed error information for debugging.