feat: получение записей домена
This commit is contained in:
@@ -24,9 +24,13 @@ ext {
|
|||||||
junitVersion = "5.9.2"
|
junitVersion = "5.9.2"
|
||||||
jacksonVersion = "2.15.3"
|
jacksonVersion = "2.15.3"
|
||||||
slf4jVersion = "2.0.16"
|
slf4jVersion = "2.0.16"
|
||||||
|
lombokVersion = "1.18.34"
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
annotationProcessor("org.projectlombok:lombok:$lombokVersion")
|
||||||
|
compileOnly("org.projectlombok:lombok:$lombokVersion")
|
||||||
|
|
||||||
implementation("org.apache.httpcomponents.client5:httpclient5:5.5")
|
implementation("org.apache.httpcomponents.client5:httpclient5:5.5")
|
||||||
implementation("org.apache.commons:commons-lang3:3.18.0")
|
implementation("org.apache.commons:commons-lang3:3.18.0")
|
||||||
implementation("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion")
|
implementation("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion")
|
||||||
|
|||||||
49
src/main/java/ru/di9/ihc/DomainRecord.java
Normal file
49
src/main/java/ru/di9/ihc/DomainRecord.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package ru.di9.ihc;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
public class DomainRecord {
|
||||||
|
private final int id;
|
||||||
|
private final boolean readOnly;
|
||||||
|
private final RecordType type;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String content;
|
||||||
|
private Integer priority;
|
||||||
|
|
||||||
|
public DomainRecord(int id, boolean readOnly, String name, RecordType type, String content, Integer priority) {
|
||||||
|
this.id = id;
|
||||||
|
this.readOnly = readOnly;
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
this.content = content;
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
if (readOnly) {
|
||||||
|
throw new RuntimeException("READ ONLY RECORD");
|
||||||
|
}
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
if (readOnly) {
|
||||||
|
throw new RuntimeException("READ ONLY RECORD");
|
||||||
|
}
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPriority(Integer priority) {
|
||||||
|
if (readOnly) {
|
||||||
|
throw new RuntimeException("READ ONLY RECORD");
|
||||||
|
}
|
||||||
|
if (!RecordType.MX.equals(type) && !RecordType.SRV.equals(type)) {
|
||||||
|
throw new RuntimeException("NOT SUPPORT SET PRIORITY FOR " + type.name() + " RECORD");
|
||||||
|
}
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/main/java/ru/di9/ihc/DomainRecordsResponse.java
Normal file
22
src/main/java/ru/di9/ihc/DomainRecordsResponse.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package ru.di9.ihc;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public record DomainRecordsResponse(Data data) {
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public record Data(List<Record> records) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Record(
|
||||||
|
int id,
|
||||||
|
boolean readOnly,
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
|
String content,
|
||||||
|
Integer prio
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,9 +16,7 @@ import org.jsoup.select.Elements;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class IhcClient {
|
public class IhcClient {
|
||||||
private final String baseUrl;
|
private final String baseUrl;
|
||||||
@@ -90,4 +88,45 @@ public class IhcClient {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<DomainRecord> getDomainRecords(int domainId) {
|
||||||
|
if (!isAuth) {
|
||||||
|
throw new RuntimeException("IS NOT AUTH");
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost(URI.create("%s/dnsZone/records".formatted(baseUrl)));
|
||||||
|
httpPost.setHeader("Accept", "application/json");
|
||||||
|
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
|
||||||
|
httpPost.setHeader("Referer", "%s/dnsZone/index/%d".formatted(baseUrl, domainId));
|
||||||
|
httpPost.setEntity(new UrlEncodedFormEntity(List.of(
|
||||||
|
new BasicNameValuePair("id", String.valueOf(domainId))
|
||||||
|
)));
|
||||||
|
|
||||||
|
try {
|
||||||
|
return httpClient.execute(httpPost, resp -> {
|
||||||
|
if (resp.getCode() != 200) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
DomainRecordsResponse response = mapper.readValue(resp.getEntity().getContent(), DomainRecordsResponse.class);
|
||||||
|
List<DomainRecord> list = new ArrayList<>();
|
||||||
|
|
||||||
|
for (DomainRecordsResponse.Record rec : response.data().records()) {
|
||||||
|
list.add(new DomainRecord(
|
||||||
|
rec.id(),
|
||||||
|
rec.readOnly(),
|
||||||
|
rec.name(),
|
||||||
|
RecordType.valueOf(rec.type()),
|
||||||
|
rec.content(),
|
||||||
|
rec.prio()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
list.sort(Comparator.comparingInt(DomainRecord::getId));
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/main/java/ru/di9/ihc/RecordType.java
Normal file
13
src/main/java/ru/di9/ihc/RecordType.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package ru.di9.ihc;
|
||||||
|
|
||||||
|
public enum RecordType {
|
||||||
|
SOA,
|
||||||
|
A,
|
||||||
|
AAAA,
|
||||||
|
CNAME,
|
||||||
|
MX,
|
||||||
|
TXT,
|
||||||
|
SRV,
|
||||||
|
NS,
|
||||||
|
CAA
|
||||||
|
}
|
||||||
79
src/test/java/ru/di9/ihc/GetDomainRecordsTest.java
Normal file
79
src/test/java/ru/di9/ihc/GetDomainRecordsTest.java
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package ru.di9.ihc;
|
||||||
|
|
||||||
|
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||||
|
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.commons.lang3.RandomUtils;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.github.tomakehurst.wiremock.client.WireMock.get;
|
||||||
|
import static com.github.tomakehurst.wiremock.client.WireMock.post;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class GetDomainRecordsTest {
|
||||||
|
static int port;
|
||||||
|
static WireMockServer wireMockServer;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
static void beforeAll() {
|
||||||
|
port = RandomUtils.nextInt(9000, 9999);
|
||||||
|
wireMockServer = new WireMockServer(port);
|
||||||
|
wireMockServer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
static void afterAll() {
|
||||||
|
wireMockServer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void after() {
|
||||||
|
wireMockServer.resetAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test() throws IOException {
|
||||||
|
wireMockServer.stubFor(post("/j_spring_security_check?ajax=true")
|
||||||
|
.willReturn(WireMock.okJson("""
|
||||||
|
{"redirect":{"url":"/"},"alert":{"type":"none","message":""}}""")));
|
||||||
|
wireMockServer.stubFor(get("/dnsZone/list")
|
||||||
|
.willReturn(WireMock.ok(IOUtils.resourceToString("/ihc-dns.html", StandardCharsets.UTF_8))
|
||||||
|
.withHeader("Content-Type", "text/html")));
|
||||||
|
wireMockServer.stubFor(post("/dnsZone/records")
|
||||||
|
.willReturn(WireMock.okJson(IOUtils.resourceToString("/ihc-domain.json", StandardCharsets.UTF_8))));
|
||||||
|
|
||||||
|
var ihc = new IhcClient("http://localhost:%d".formatted(port));
|
||||||
|
ihc.auth("user1", "passwd1");
|
||||||
|
Integer domainId = ihc.getDomains().getFirst().getValue();
|
||||||
|
List<DomainRecord> domainRecords = ihc.getDomainRecords(domainId);
|
||||||
|
|
||||||
|
assertEquals(7, domainRecords.size());
|
||||||
|
|
||||||
|
DomainRecord record1 = domainRecords.getFirst();
|
||||||
|
assertEquals(7000001, record1.getId());
|
||||||
|
assertTrue(record1.isReadOnly());
|
||||||
|
assertEquals(RecordType.SOA, record1.getType());
|
||||||
|
assertEquals("", record1.getName());
|
||||||
|
assertEquals("ns1.ihc.ru. info.ihc.ru. 2014120801 10800 3600 604800 3600", record1.getContent());
|
||||||
|
assertNull(record1.getPriority());
|
||||||
|
|
||||||
|
assertThrows(RuntimeException.class, () -> record1.setName("xx"));
|
||||||
|
|
||||||
|
DomainRecord record2 = domainRecords.get(4);
|
||||||
|
assertEquals(7000005, record2.getId());
|
||||||
|
assertFalse(record2.isReadOnly());
|
||||||
|
assertEquals(RecordType.MX, record2.getType());
|
||||||
|
assertEquals("", record2.getName());
|
||||||
|
assertEquals("mx.yandex.ru", record2.getContent());
|
||||||
|
assertEquals(10, record2.getPriority());
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> record2.setName("xx"));
|
||||||
|
}
|
||||||
|
}
|
||||||
72
src/test/resources/ihc-domain.json
Normal file
72
src/test/resources/ihc-domain.json
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"alert": {
|
||||||
|
"type": "none",
|
||||||
|
"message": ""
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"errors": [],
|
||||||
|
"messages": [],
|
||||||
|
"domain": {
|
||||||
|
"name": "example-1.ru",
|
||||||
|
"id": 111111
|
||||||
|
},
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"readOnly": true,
|
||||||
|
"id": 7000001,
|
||||||
|
"name": "",
|
||||||
|
"type": "SOA",
|
||||||
|
"content": "ns1.ihc.ru. info.ihc.ru. 2014120801 10800 3600 604800 3600",
|
||||||
|
"prio": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"readOnly": true,
|
||||||
|
"id": 7000002,
|
||||||
|
"name": "",
|
||||||
|
"type": "NS",
|
||||||
|
"content": "ns1.ihc.ru",
|
||||||
|
"prio": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"readOnly": true,
|
||||||
|
"id": 7000003,
|
||||||
|
"name": "",
|
||||||
|
"type": "NS",
|
||||||
|
"content": "ns2.ihc.ru",
|
||||||
|
"prio": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"readOnly": false,
|
||||||
|
"id": 7000004,
|
||||||
|
"name": "yamail-XXXXXXXXXXXX",
|
||||||
|
"type": "CNAME",
|
||||||
|
"content": "mail.yandex.ru",
|
||||||
|
"prio": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"readOnly": false,
|
||||||
|
"id": 7000005,
|
||||||
|
"name": "",
|
||||||
|
"type": "MX",
|
||||||
|
"content": "mx.yandex.ru",
|
||||||
|
"prio": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"readOnly": false,
|
||||||
|
"id": 7000006,
|
||||||
|
"name": "",
|
||||||
|
"type": "A",
|
||||||
|
"content": "127.0.0.1",
|
||||||
|
"prio": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"readOnly": false,
|
||||||
|
"id": 7000007,
|
||||||
|
"name": "_acme-challenge",
|
||||||
|
"type": "TXT",
|
||||||
|
"content": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||||
|
"prio": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user