refactor: Improve error handling in PowerDNSAPIClient and streamline response processing fix: Update RecordController to directly return records without unnecessary mapping refactor: Update DomainRepository and RecordRepository to remove nullable types for IDs fix: Change User domains fetch strategy to lazy loading for performance improvement fix: Enhance user authentication handling in UserFilter to ensure authenticated user presence refactor: Improve DomainService to enforce ownership checks before domain deletion refactor: Update RecordService to streamline record retrieval and ensure proper domain association test: Add OpenAPI generation test to validate API documentation endpoint test: Implement PowerDNSAPIClient tests to verify HTTP method usage and error handling test: Create DomainService tests to validate domain ownership and deletion logic test: Add application-test.properties for in-memory database configuration during tests
7.1 KiB
Cloudflare compatible PowerDNS API Server
A Kotlin and Spring Boot API that exposes Cloudflare-style zone and DNS record endpoints backed by PowerDNS and MariaDB. API requests use Authorization: Bearer <API_KEY>.
Build and run
Use JDK 25. The Gradle wrapper selects the Java 25 toolchain for compilation.
./gradlew test bootJar
./gradlew bootRun
bootRun activates the dev profile. Supply the environment variables below before starting the app. Tests use an in-memory H2 database and do not require MariaDB or PowerDNS.
| Variable | Description |
|---|---|
DB_HOST |
MariaDB host |
DB_PORT |
MariaDB port, usually 3306 |
DB_NAME |
Database name |
DB_USER |
Database user |
DB_PASSWORD |
Database password |
PDNS_API_KEY |
PowerDNS HTTP API key |
PDNS_API_URL |
PowerDNS HTTP API base URL, for example http://pdns:8081 |
PDNS_NS |
Comma-separated nameservers, for example ns1.example.com,ns2.example.com |
Update API documentation
./gradlew updateDocs
This task starts the app in a test context, writes the current OpenAPI 3.1 specification to openapi.json, and refreshes the generated API section below. generateOpenApi and updateReadme are also available separately. The documentation task uses H2 and does not contact PowerDNS.
API reference
Generated from openapi.json. Do not edit this section by hand.
Endpoints
| Method | Path | Summary | Request body | Success response |
|---|---|---|---|---|
GET |
/zones |
Get all domains | — | 200: ApiResponseDTOListDomainResponseDTO |
POST |
/zones |
Create domain | DomainRequestDTO | 200: ApiResponseDTODomainResponseDTO |
GET |
/zones/{cfid} |
Get domain | — | 200: ApiResponseDTODomainResponseDTO |
DELETE |
/zones/{domain_id} |
Delete domain | — | 200: ApiResponseDTODeleteResponseWithId |
GET |
/zones/{zone_id}/dns_records |
Get all records | — | 200: ApiResponseDTOListRecordResponseDTO |
POST |
/zones/{zone_id}/dns_records |
Add Record by ID | RecordRequestDTO | 200: ApiResponseDTORecordResponseDTO |
GET |
/zones/{zone_id}/dns_records/{dns_record_id} |
Get Record by ID | — | 200: ApiResponseDTORecordResponseDTO |
PUT |
/zones/{zone_id}/dns_records/{dns_record_id} |
Update Record by ID | RecordRequestDTO | 200: ApiResponseDTORecordResponseDTO |
DELETE |
/zones/{zone_id}/dns_records/{dns_record_id} |
Remove Record by ID | — | 200: ApiResponseDTODeleteResponseWithId |
Schemas
ApiResponseDTO
| Field | Type | Required | Description |
|---|---|---|---|
success |
boolean | No | — |
errors |
array of ErrorOrMessage | No | — |
messages |
array of ErrorOrMessage | No | — |
result |
— | No | — |
ApiResponseDTODeleteResponseWithId
| Field | Type | Required | Description |
|---|---|---|---|
success |
boolean | No | — |
errors |
array of ErrorOrMessage | No | — |
messages |
array of ErrorOrMessage | No | — |
result |
DeleteResponseWithId or null | No | — |
ApiResponseDTODomainResponseDTO
| Field | Type | Required | Description |
|---|---|---|---|
success |
boolean | No | — |
errors |
array of ErrorOrMessage | No | — |
messages |
array of ErrorOrMessage | No | — |
result |
DomainResponseDTO or null | No | — |
ApiResponseDTOListDomainResponseDTO
| Field | Type | Required | Description |
|---|---|---|---|
success |
boolean | No | — |
errors |
array of ErrorOrMessage | No | — |
messages |
array of ErrorOrMessage | No | — |
result |
array of DomainResponseDTO or null | No | — |
ApiResponseDTOListRecordResponseDTO
| Field | Type | Required | Description |
|---|---|---|---|
success |
boolean | No | — |
errors |
array of ErrorOrMessage | No | — |
messages |
array of ErrorOrMessage | No | — |
result |
array of RecordResponseDTO or null | No | — |
ApiResponseDTORecordResponseDTO
| Field | Type | Required | Description |
|---|---|---|---|
success |
boolean | No | — |
errors |
array of ErrorOrMessage | No | — |
messages |
array of ErrorOrMessage | No | — |
result |
RecordResponseDTO or null | No | — |
DeleteResponseWithId
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | No | — |
DomainRequestDTO
Request DTO for Domain
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | No | Domain name(TLD) |
DomainResponseDTO
Response DTO for Domain
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | No | Domain CFID |
name |
string | No | Domain name(TLD) |
ErrorOrMessage
| Field | Type | Required | Description |
|---|---|---|---|
code |
integer | No | — |
message |
string | No | — |
RecordRequestDTO
Request DTO for Record
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | No | Record type |
name |
string | No | Host name |
value |
string | No | Record data |
ttl |
integer | No | TTL (Time to Live) |
priority |
integer or null | No | Priority |
proxied |
boolean | No | Proxied: cloudflare api compatibility |
comment |
string | No | comment |
RecordResponseDTO
Response DTO for Record
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | No | Record ID |
type |
string | No | Record type |
name |
string | No | Record name |
content |
string | No | Record content |
zoneId |
string | No | Zone(TLD) ID |
zoneName |
string | No | Zone name(TLD) |
createdOn |
string | No | Record creation time |
modifiedOn |
string | No | Record modification time |
priority |
integer or null | No | Record priority |
proxiable |
boolean | No | is proxyable: must false |
proxied |
boolean | No | is proxied: must false |
ttl |
integer | No | Record TTL |
locked |
boolean | No | Record is locked: must false |
comment |
string or null | No | Record comments |