diff --git a/OpenSRS.NET.Tests/DomainClientTests.cs b/OpenSRS.NET.Tests/DomainClientTests.cs index 5a9700a..86bb950 100644 --- a/OpenSRS.NET.Tests/DomainClientTests.cs +++ b/OpenSRS.NET.Tests/DomainClientTests.cs @@ -76,4 +76,48 @@ public async Task CreateDnsZoneAsync_ReturnsParsedResult() var result = await client.CreateDnsZoneAsync(request); Assert.IsType(result); } + + [Fact] + public async Task GetDnsZoneAsync_ReturnsParsedResult() + { + var client = new TestOpenSRSClient(); + var request = new GetDnsZoneRequest { Domain = "example.com" }; + var result = await client.GetDnsZoneAsync(request); + Assert.IsType(result); + } + + [Fact] + public async Task SetDnsZoneAsync_ReturnsParsedResult() + { + var client = new TestOpenSRSClient(); + var request = new SetDnsZoneRequest { Domain = "example.com" }; + var result = await client.SetDnsZoneAsync(request); + Assert.IsType(result); + } + + [Fact] + public async Task ResetDnsZoneAsync_ReturnsParsedResult() + { + var client = new TestOpenSRSClient(); + var request = new ResetDnsZoneRequest { Domain = "example.com" }; + var result = await client.ResetDnsZoneAsync(request); + Assert.IsType(result); + } + + [Fact] + public async Task ForceDnsNameserversAsync_ReturnsParsedResult() + { + var client = new TestOpenSRSClient(); + var request = new ForceDnsNameserversRequest { Domain = "example.com" }; + var result = await client.ForceDnsNameserversAsync(request); + Assert.IsType(result); + } + + [Fact] + public async Task DeleteDnsZoneAsync_CompletesSuccessfully() + { + var client = new TestOpenSRSClient(); + var request = new DeleteDnsZoneRequest { Domain = "example.com" }; + await client.DeleteDnsZoneAsync(request); + } } \ No newline at end of file diff --git a/OpenSRS.NET/Actions/ForceDnsNameserversRequest.cs b/OpenSRS.NET/Actions/ForceDnsNameserversRequest.cs new file mode 100644 index 0000000..3a1b99b --- /dev/null +++ b/OpenSRS.NET/Actions/ForceDnsNameserversRequest.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +namespace OpenSRS.NET.Actions +{ + public sealed class ForceDnsNameserversRequest : OpenSRSRequest + { + public ForceDnsNameserversRequest() : base("FORCE_DNS_NAMESERVERS", "DOMAIN") { } + + public string Domain { get; set; } + + public override Dictionary GetParameters() + { + return new Dictionary { + { "domain", Domain } + }; + } + } +} diff --git a/OpenSRS.NET/Actions/ForceDnsNameserversResult.cs b/OpenSRS.NET/Actions/ForceDnsNameserversResult.cs new file mode 100644 index 0000000..8cb8833 --- /dev/null +++ b/OpenSRS.NET/Actions/ForceDnsNameserversResult.cs @@ -0,0 +1,29 @@ +using OpenSRS.NET.Models; +using System.Xml.Linq; +using System.Xml.XPath; + +namespace OpenSRS.NET.Actions +{ + public sealed class ForceDnsNameserversResult + { + public static ForceDnsNameserversResult Parse(string text) + { + var result = new ForceDnsNameserversResult(); + + var doc = XDocument.Parse(text); + + var itemEl = doc.XPathSelectElement(@"/OPS_envelope/body/data_block/dt_assoc"); + + var response = ResponseDetails.FromEl(itemEl); + if (!response.IsSuccess) + { + throw new OpenSRSException(response.ResponseText) + { + ResponseCode = response.ResponseCode + }; + } + + return result; + } + } +} diff --git a/OpenSRS.NET/Actions/GetDnsZoneRequest.cs b/OpenSRS.NET/Actions/GetDnsZoneRequest.cs new file mode 100644 index 0000000..2b94f69 --- /dev/null +++ b/OpenSRS.NET/Actions/GetDnsZoneRequest.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +namespace OpenSRS.NET.Actions +{ + public sealed class GetDnsZoneRequest : OpenSRSRequest + { + public GetDnsZoneRequest() : base("GET_DNS_ZONE", "DOMAIN") { } + + public string Domain { get; set; } + + public override Dictionary GetParameters() + { + return new Dictionary { + { "domain", Domain } + }; + } + } +} diff --git a/OpenSRS.NET/Actions/GetDnsZoneResult.cs b/OpenSRS.NET/Actions/GetDnsZoneResult.cs new file mode 100644 index 0000000..0898ad5 --- /dev/null +++ b/OpenSRS.NET/Actions/GetDnsZoneResult.cs @@ -0,0 +1,97 @@ +using OpenSRS.NET.Models; +using System.Linq; +using System.Runtime.Serialization; +using System.Xml.Linq; +using System.Xml.XPath; + +namespace OpenSRS.NET.Actions +{ + public sealed class GetDnsZoneResult + { + public DnsRecordSet RecordSet { get; set; } = new DnsRecordSet(); + + [DataMember(Name = "nameservers_ok")] + public bool NameserversOK { get; set; } + + public static GetDnsZoneResult Parse(string text) + { + var result = new GetDnsZoneResult(); + + var doc = XDocument.Parse(text); + + var itemEl = doc.XPathSelectElement(@"/OPS_envelope/body/data_block/dt_assoc"); + + var response = ResponseDetails.FromEl(itemEl); + if (!response.IsSuccess) + { + throw new OpenSRSException(response.ResponseText) + { + ResponseCode = response.ResponseCode + }; + } + + XElement recordsArray = doc.XPathSelectElement(@"//item[@key=""records""]/dt_assoc"); + if (recordsArray != null) + { + foreach (var record in recordsArray.Descendants()) + { + switch (record.Attribute("key")?.Value) + { + case "A": + var AItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var AItem in AItems) + { + result.RecordSet.A.Add(new ARecord { Address = System.Net.IPAddress.Parse(AItem["ip_address"]), Subdomain = AItem["subdomain"] }); + } + break; + case "AAAA": + var AAAAItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var AItem in AAAAItems) + { + result.RecordSet.AAAA.Add(new AAAARecord { Address = System.Net.IPAddress.Parse(AItem["ip_address"]), Subdomain = AItem["subdomain"] }); + } + break; + case "CNAME": + var CNItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var CNItem in CNItems) + { + result.RecordSet.CNAME.Add(new CNAMERecord { HostName = CNItem["hostname"], Subdomain = CNItem["subdomain"] }); + } + break; + case "MX": + var MXItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var MXItem in MXItems) + { + result.RecordSet.MX.Add(new MXRecord { Priority = int.Parse(MXItem["priority"]), HostName = MXItem["hostname"], Subdomain = MXItem["subdomain"] }); + } + break; + case "TXT": + var TXTItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var TXTItem in TXTItems) + { + result.RecordSet.TXT.Add(new TXTRecord { Text = TXTItem["text"], Subdomain = TXTItem["subdomain"] }); + } + break; + case "SRV": + var SRVItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var SRVItem in SRVItems) + { + result.RecordSet.SRV.Add(new SRVRecord { HostName = SRVItem["hostname"], Priority = int.Parse(SRVItem["priority"]), Port = int.Parse(SRVItem["port"]), Weight = int.Parse(SRVItem["weight"]), Subdomain = SRVItem["subdomain"] }); + } + break; + default: + break; + } + } + } + + var nameserversOkEl = doc.XPathSelectElement(@"//item[@key=""nameservers_ok""]"); + if (nameserversOkEl != null) + { + result.NameserversOK = int.Parse(nameserversOkEl.Value) == 1; + } + + return result; + } + } +} diff --git a/OpenSRS.NET/Actions/ResetDnsZoneRequest.cs b/OpenSRS.NET/Actions/ResetDnsZoneRequest.cs new file mode 100644 index 0000000..ca2da9e --- /dev/null +++ b/OpenSRS.NET/Actions/ResetDnsZoneRequest.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace OpenSRS.NET.Actions +{ + public sealed class ResetDnsZoneRequest : OpenSRSRequest + { + public ResetDnsZoneRequest() : base("RESET_DNS_ZONE", "DOMAIN") { } + + public string Domain { get; set; } + + public string DnsTemplate { get; set; } + + public override Dictionary GetParameters() + { + return new Dictionary { + { "domain", Domain }, + { "dns_template", DnsTemplate } + }; + } + } +} diff --git a/OpenSRS.NET/Actions/ResetDnsZoneResult.cs b/OpenSRS.NET/Actions/ResetDnsZoneResult.cs new file mode 100644 index 0000000..c217b1e --- /dev/null +++ b/OpenSRS.NET/Actions/ResetDnsZoneResult.cs @@ -0,0 +1,97 @@ +using OpenSRS.NET.Models; +using System.Linq; +using System.Runtime.Serialization; +using System.Xml.Linq; +using System.Xml.XPath; + +namespace OpenSRS.NET.Actions +{ + public sealed class ResetDnsZoneResult + { + public DnsRecordSet RecordSet { get; set; } = new DnsRecordSet(); + + [DataMember(Name = "nameservers_ok")] + public bool NameserversOK { get; set; } + + public static ResetDnsZoneResult Parse(string text) + { + var result = new ResetDnsZoneResult(); + + var doc = XDocument.Parse(text); + + var itemEl = doc.XPathSelectElement(@"/OPS_envelope/body/data_block/dt_assoc"); + + var response = ResponseDetails.FromEl(itemEl); + if (!response.IsSuccess) + { + throw new OpenSRSException(response.ResponseText) + { + ResponseCode = response.ResponseCode + }; + } + + XElement recordsArray = doc.XPathSelectElement(@"//item[@key=""records""]/dt_assoc"); + if (recordsArray != null) + { + foreach (var record in recordsArray.Descendants()) + { + switch (record.Attribute("key")?.Value) + { + case "A": + var AItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var AItem in AItems) + { + result.RecordSet.A.Add(new ARecord { Address = System.Net.IPAddress.Parse(AItem["ip_address"]), Subdomain = AItem["subdomain"] }); + } + break; + case "AAAA": + var AAAAItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var AItem in AAAAItems) + { + result.RecordSet.AAAA.Add(new AAAARecord { Address = System.Net.IPAddress.Parse(AItem["ip_address"]), Subdomain = AItem["subdomain"] }); + } + break; + case "CNAME": + var CNItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var CNItem in CNItems) + { + result.RecordSet.CNAME.Add(new CNAMERecord { HostName = CNItem["hostname"], Subdomain = CNItem["subdomain"] }); + } + break; + case "MX": + var MXItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var MXItem in MXItems) + { + result.RecordSet.MX.Add(new MXRecord { Priority = int.Parse(MXItem["priority"]), HostName = MXItem["hostname"], Subdomain = MXItem["subdomain"] }); + } + break; + case "TXT": + var TXTItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var TXTItem in TXTItems) + { + result.RecordSet.TXT.Add(new TXTRecord { Text = TXTItem["text"], Subdomain = TXTItem["subdomain"] }); + } + break; + case "SRV": + var SRVItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var SRVItem in SRVItems) + { + result.RecordSet.SRV.Add(new SRVRecord { HostName = SRVItem["hostname"], Priority = int.Parse(SRVItem["priority"]), Port = int.Parse(SRVItem["port"]), Weight = int.Parse(SRVItem["weight"]), Subdomain = SRVItem["subdomain"] }); + } + break; + default: + break; + } + } + } + + var nameserversOkEl = doc.XPathSelectElement(@"//item[@key=""nameservers_ok""]"); + if (nameserversOkEl != null) + { + result.NameserversOK = int.Parse(nameserversOkEl.Value) == 1; + } + + return result; + } + } +} diff --git a/OpenSRS.NET/Actions/SetDnsZoneRequest.cs b/OpenSRS.NET/Actions/SetDnsZoneRequest.cs new file mode 100644 index 0000000..52159d5 --- /dev/null +++ b/OpenSRS.NET/Actions/SetDnsZoneRequest.cs @@ -0,0 +1,22 @@ +using OpenSRS.NET.Models; +using System.Collections.Generic; + +namespace OpenSRS.NET.Actions +{ + public sealed class SetDnsZoneRequest : OpenSRSRequest + { + public SetDnsZoneRequest() : base("SET_DNS_ZONE", "DOMAIN") { } + + public string Domain { get; set; } + + public DnsRecordSet Records { get; set; } + + public override Dictionary GetParameters() + { + return new Dictionary { + { "domain", Domain }, + { "records", Records?.ToDtAssoc() } + }; + } + } +} diff --git a/OpenSRS.NET/Actions/SetDnsZoneResult.cs b/OpenSRS.NET/Actions/SetDnsZoneResult.cs new file mode 100644 index 0000000..faf5a16 --- /dev/null +++ b/OpenSRS.NET/Actions/SetDnsZoneResult.cs @@ -0,0 +1,97 @@ +using OpenSRS.NET.Models; +using System.Linq; +using System.Runtime.Serialization; +using System.Xml.Linq; +using System.Xml.XPath; + +namespace OpenSRS.NET.Actions +{ + public sealed class SetDnsZoneResult + { + public DnsRecordSet RecordSet { get; set; } = new DnsRecordSet(); + + [DataMember(Name = "nameservers_ok")] + public bool NameserversOK { get; set; } + + public static SetDnsZoneResult Parse(string text) + { + var result = new SetDnsZoneResult(); + + var doc = XDocument.Parse(text); + + var itemEl = doc.XPathSelectElement(@"/OPS_envelope/body/data_block/dt_assoc"); + + var response = ResponseDetails.FromEl(itemEl); + if (!response.IsSuccess) + { + throw new OpenSRSException(response.ResponseText) + { + ResponseCode = response.ResponseCode + }; + } + + XElement recordsArray = doc.XPathSelectElement(@"//item[@key=""records""]/dt_assoc"); + if (recordsArray != null) + { + foreach (var record in recordsArray.Descendants()) + { + switch (record.Attribute("key")?.Value) + { + case "A": + var AItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var AItem in AItems) + { + result.RecordSet.A.Add(new ARecord { Address = System.Net.IPAddress.Parse(AItem["ip_address"]), Subdomain = AItem["subdomain"] }); + } + break; + case "AAAA": + var AAAAItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var AItem in AAAAItems) + { + result.RecordSet.AAAA.Add(new AAAARecord { Address = System.Net.IPAddress.Parse(AItem["ip_address"]), Subdomain = AItem["subdomain"] }); + } + break; + case "CNAME": + var CNItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var CNItem in CNItems) + { + result.RecordSet.CNAME.Add(new CNAMERecord { HostName = CNItem["hostname"], Subdomain = CNItem["subdomain"] }); + } + break; + case "MX": + var MXItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var MXItem in MXItems) + { + result.RecordSet.MX.Add(new MXRecord { Priority = int.Parse(MXItem["priority"]), HostName = MXItem["hostname"], Subdomain = MXItem["subdomain"] }); + } + break; + case "TXT": + var TXTItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var TXTItem in TXTItems) + { + result.RecordSet.TXT.Add(new TXTRecord { Text = TXTItem["text"], Subdomain = TXTItem["subdomain"] }); + } + break; + case "SRV": + var SRVItems = ResponseHelper.ReadArray(record.Descendants("dt_array").First()); + foreach (var SRVItem in SRVItems) + { + result.RecordSet.SRV.Add(new SRVRecord { HostName = SRVItem["hostname"], Priority = int.Parse(SRVItem["priority"]), Port = int.Parse(SRVItem["port"]), Weight = int.Parse(SRVItem["weight"]), Subdomain = SRVItem["subdomain"] }); + } + break; + default: + break; + } + } + } + + var nameserversOkEl = doc.XPathSelectElement(@"//item[@key=""nameservers_ok""]"); + if (nameserversOkEl != null) + { + result.NameserversOK = int.Parse(nameserversOkEl.Value) == 1; + } + + return result; + } + } +} diff --git a/OpenSRS.NET/DomainClient.cs b/OpenSRS.NET/DomainClient.cs index 9d2088f..bb61824 100644 --- a/OpenSRS.NET/DomainClient.cs +++ b/OpenSRS.NET/DomainClient.cs @@ -13,5 +13,10 @@ public partial class OpenSRSClient public async Task GetOrderInfoAsync(GetOrderInfoRequest request) => GetOrderInfoResult.Parse(await SendAsync(request).ConfigureAwait(false)); public async Task CreateDnsZoneAsync(CreateDnsZoneRequest request) => CreateDnsZoneResult.Parse(await SendAsync(request).ConfigureAwait(false)); + public async Task GetDnsZoneAsync(GetDnsZoneRequest request) => GetDnsZoneResult.Parse(await SendAsync(request).ConfigureAwait(false)); + public async Task SetDnsZoneAsync(SetDnsZoneRequest request) => SetDnsZoneResult.Parse(await SendAsync(request).ConfigureAwait(false)); + public async Task ResetDnsZoneAsync(ResetDnsZoneRequest request) => ResetDnsZoneResult.Parse(await SendAsync(request).ConfigureAwait(false)); + public async Task ForceDnsNameserversAsync(ForceDnsNameserversRequest request) => ForceDnsNameserversResult.Parse(await SendAsync(request).ConfigureAwait(false)); + public async Task DeleteDnsZoneAsync(DeleteDnsZoneRequest request) => await SendAsync(request).ConfigureAwait(false); } }