Added DNS Records for Zone actions
This commit is contained in:
600
Extensions/Cloudflare.Zones/DnsRecordsExtensions.cs
Normal file
600
Extensions/Cloudflare.Zones/DnsRecordsExtensions.cs
Normal file
@@ -0,0 +1,600 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AMWD.Net.Api.Cloudflare.Zones.Internals.Requests;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// Extends the <see cref="ICloudflareClient"/> with methods for working with zones.
|
||||
/// </summary>
|
||||
public static class DnsRecordsExtensions
|
||||
{
|
||||
private static readonly IReadOnlyCollection<DnsRecordType> _dataComponentTypes = [
|
||||
DnsRecordType.Caa,
|
||||
DnsRecordType.Cert,
|
||||
DnsRecordType.DnsKey,
|
||||
DnsRecordType.Ds,
|
||||
DnsRecordType.Https,
|
||||
DnsRecordType.Loc,
|
||||
DnsRecordType.NaPtr,
|
||||
DnsRecordType.SMimeA,
|
||||
DnsRecordType.Srv,
|
||||
DnsRecordType.SshFp,
|
||||
DnsRecordType.SvcB,
|
||||
DnsRecordType.TlsA,
|
||||
DnsRecordType.Uri,
|
||||
];
|
||||
|
||||
private static readonly IReadOnlyCollection<DnsRecordType> _priorityTypes = [
|
||||
DnsRecordType.Mx,
|
||||
DnsRecordType.Srv,
|
||||
DnsRecordType.Uri,
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// List, search, sort, and filter a zones' DNS records.
|
||||
/// </summary>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="zoneId">The zone ID.</param>
|
||||
/// <param name="options">Filter options (optional).</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<IReadOnlyList<DnsRecord>>> ListDnsRecords(this ICloudflareClient client, string zoneId, ListDnsRecordsFilter? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
return client.GetAsync<IReadOnlyList<DnsRecord>>($"zones/{zoneId}/dns_records", options, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new DNS record for a zone.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <list type="bullet">
|
||||
/// <item>A/AAAA records cannot exist on the same name as CNAME records.</item>
|
||||
/// <item>NS records cannot exist on the same name as any other record type.</item>
|
||||
/// <item>Domain names are always represented in Punycode, even if Unicode characters were used when creating the record.</item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="request">The request information.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<DnsRecord>> CreateDnsRecord(this ICloudflareClient client, CreateDnsRecordRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
request.ZoneId.ValidateCloudflareId();
|
||||
|
||||
var req = ValidateDnsRecordRequest(request);
|
||||
|
||||
return client.PostAsync<DnsRecord, InternalDnsRecordRequest>($"zones/{request.ZoneId}/dns_records", req, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a Batch of DNS Record API calls to be executed together.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// Although Cloudflare will execute the batched operations in a single database transaction,
|
||||
/// Cloudflare's distributed KV store must treat each record change as a single key-value pair.
|
||||
/// This means that the propagation of changes is not atomic.
|
||||
/// See <see href="https://developers.cloudflare.com/dns/manage-dns-records/how-to/batch-record-changes/">the documentation</see> for more information.
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// The operations you specify within the batch request body are always executed in the following order
|
||||
/// <list type="number">
|
||||
/// <item>Deletes (delete)</item>
|
||||
/// <item>Updates (patch)</item>
|
||||
/// <item>Overwrites (put)</item>
|
||||
/// <item>Creates (post)</item>
|
||||
/// </list>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="request">The request information.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<BatchDnsRecordsResult>> BatchDnsRecords(this ICloudflareClient client, BatchDnsRecordsRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
request.ZoneId.ValidateCloudflareId();
|
||||
|
||||
// Validate Deletes
|
||||
var deletes = new List<InternalDnsRecordId>();
|
||||
foreach (string recordId in request.DnsRecordIdsToDelete)
|
||||
{
|
||||
recordId.ValidateCloudflareId();
|
||||
deletes.Add(new InternalDnsRecordId { Id = recordId });
|
||||
}
|
||||
|
||||
// Validate Updates
|
||||
var updates = new List<InternalBatchUpdateRequest>();
|
||||
foreach (var update in request.DnsRecordsToUpdate)
|
||||
{
|
||||
update.Id.ValidateCloudflareId();
|
||||
if (update.ZoneId != request.ZoneId)
|
||||
throw new ArgumentException($"The ZoneId of the update request ({update.ZoneId}) does not match the ZoneId of the batch request ({request.ZoneId}).");
|
||||
|
||||
var baseReq = ValidateDnsRecordRequest(update);
|
||||
updates.Add(new InternalBatchUpdateRequest(update.Id, baseReq));
|
||||
}
|
||||
|
||||
// Validate Overwrites
|
||||
var overwrites = new List<InternalBatchUpdateRequest>();
|
||||
foreach (var overwrite in request.DnsRecordsToOverwrite)
|
||||
{
|
||||
overwrite.Id.ValidateCloudflareId();
|
||||
if (overwrite.ZoneId != request.ZoneId)
|
||||
throw new ArgumentException($"The ZoneId of the overwrite request ({overwrite.ZoneId}) does not match the ZoneId of the batch request ({request.ZoneId}).");
|
||||
|
||||
var baseReq = ValidateDnsRecordRequest(overwrite);
|
||||
overwrites.Add(new InternalBatchUpdateRequest(overwrite.Id, baseReq));
|
||||
}
|
||||
|
||||
// Validate Creates
|
||||
var creates = new List<InternalDnsRecordRequest>();
|
||||
foreach (var create in request.DnsRecordsToCreate)
|
||||
creates.Add(ValidateDnsRecordRequest(create));
|
||||
|
||||
var req = new InternalBatchRequest();
|
||||
|
||||
if (deletes.Count > 0)
|
||||
req.Deletes = deletes;
|
||||
|
||||
if (updates.Count > 0)
|
||||
req.Patches = updates;
|
||||
|
||||
if (overwrites.Count > 0)
|
||||
req.Puts = overwrites;
|
||||
|
||||
if (creates.Count > 0)
|
||||
req.Posts = creates;
|
||||
|
||||
return client.PostAsync<BatchDnsRecordsResult, InternalBatchRequest>($"zones/{request.ZoneId}/dns_records/batch", req, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// You can export your <see href="https://en.wikipedia.org/wiki/Zone_file">BIND config</see> through this endpoint.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// See <see href="https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/">the documentation</see> for more information.
|
||||
/// </remarks>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="zoneId">The zone ID.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<string>> ExportDnsRecords(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
return client.GetAsync<string>($"zones/{zoneId}/dns_records/export", cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// You can upload your BIND config through this endpoint.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// See the documentation for more information.
|
||||
/// </remarks>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="request">The request information.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<ImportDnsRecordsResult>> ImportDnsRecords(this ICloudflareClient client, ImportDnsRecordsRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
request.ZoneId.ValidateCloudflareId();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.File))
|
||||
throw new ArgumentNullException(nameof(request.File));
|
||||
|
||||
var req = new MultipartFormDataContent();
|
||||
|
||||
if (request.Proxied.HasValue)
|
||||
req.Add(new StringContent(request.Proxied.Value.ToString().ToLowerInvariant()), "proxied");
|
||||
|
||||
byte[] content = File.Exists(request.File)
|
||||
? File.ReadAllBytes(request.File)
|
||||
: Encoding.UTF8.GetBytes(request.File);
|
||||
|
||||
req.Add(new ByteArrayContent(content), "file");
|
||||
|
||||
return client.PostAsync<ImportDnsRecordsResult, MultipartFormDataContent>($"zones/{request.ZoneId}/dns_records/import", req, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan for common DNS records on your domain and automatically add them to your zone.
|
||||
/// <br/>
|
||||
/// Useful if you haven't updated your nameservers yet.
|
||||
/// </summary>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="zoneId">The zone ID.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<ImportDnsRecordsResult>> ScanDnsRecords(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
return client.PostAsync<ImportDnsRecordsResult, object>($"zones/{zoneId}/dns_records/scan", null, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a DNS record.
|
||||
/// </summary>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="zoneId">The zone ID.</param>
|
||||
/// <param name="dnsRecordId">The record ID.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<IdResponse>> DeleteDnsRecord(this ICloudflareClient client, string zoneId, string dnsRecordId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
dnsRecordId.ValidateCloudflareId();
|
||||
return client.DeleteAsync<IdResponse>($"zones/{zoneId}/dns_records/{dnsRecordId}", cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns details for a DNS record.
|
||||
/// </summary>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="zoneId">The zone ID.</param>
|
||||
/// <param name="dnsRecordId">The record ID.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<DnsRecord>> DnsRecordDetails(this ICloudflareClient client, string zoneId, string dnsRecordId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
dnsRecordId.ValidateCloudflareId();
|
||||
return client.GetAsync<DnsRecord>($"zones/{zoneId}/dns_records/{dnsRecordId}", cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update an existing DNS record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <list type="bullet">
|
||||
/// <item>A/AAAA records cannot exist on the same name as CNAME records.</item>
|
||||
/// <item>NS records cannot exist on the same name as any other record type.</item>
|
||||
/// <item>Domain names are always represented in Punycode, even if Unicode characters were used when creating the record.</item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="request">The request information.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<DnsRecord>> UpdateDnsRecord(this ICloudflareClient client, UpdateDnsRecordRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
request.ZoneId.ValidateCloudflareId();
|
||||
request.Id.ValidateCloudflareId();
|
||||
|
||||
var req = ValidateDnsRecordRequest(request);
|
||||
|
||||
return client.PatchAsync<DnsRecord, InternalDnsRecordRequest>($"zones/{request.ZoneId}/dns_records/{request.Id}", req, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overwrite an existing DNS record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <list type="bullet">
|
||||
/// <item>A/AAAA records cannot exist on the same name as CNAME records.</item>
|
||||
/// <item>NS records cannot exist on the same name as any other record type.</item>
|
||||
/// <item>Domain names are always represented in Punycode, even if Unicode characters were used when creating the record.</item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="request">The request information.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<DnsRecord>> OverwriteDnsRecord(this ICloudflareClient client, OverwriteDnsRecordRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
request.ZoneId.ValidateCloudflareId();
|
||||
request.Id.ValidateCloudflareId();
|
||||
|
||||
var req = ValidateDnsRecordRequest(request);
|
||||
|
||||
return client.PutAsync<DnsRecord, InternalDnsRecordRequest>($"zones/{request.ZoneId}/dns_records/{request.Id}", req, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
private static InternalDnsRecordRequest ValidateDnsRecordRequest(CreateDnsRecordRequest request)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(request.Name))
|
||||
throw new ArgumentNullException(nameof(request.Name));
|
||||
|
||||
if (!Enum.IsDefined(typeof(DnsRecordType), request.Type))
|
||||
throw new ArgumentOutOfRangeException(nameof(request.Type), request.Type, "Value must be one of the 'ZoneDnsRecordType' enum values.");
|
||||
|
||||
var req = new InternalDnsRecordRequest(request.Type, request.Name)
|
||||
{
|
||||
Comment = request.Comment?.Trim(),
|
||||
Proxied = request.Proxied,
|
||||
Tags = request.Tags?.Where(t => !string.IsNullOrWhiteSpace(t)).ToList()
|
||||
};
|
||||
|
||||
if (!_dataComponentTypes.Contains(request.Type) && string.IsNullOrWhiteSpace(request.Content))
|
||||
throw new ArgumentNullException(nameof(request.Content));
|
||||
else
|
||||
req.Content = request.Content?.Trim();
|
||||
|
||||
if (request.Type == DnsRecordType.Cname && request.Settings != null && request.Settings is DnsRecord.CnameSettings cnameSettings)
|
||||
req.Settings = new DnsRecord.CnameSettings(cnameSettings.FlattenCname);
|
||||
|
||||
if (_dataComponentTypes.Contains(request.Type) && request.Data == null)
|
||||
throw new ArgumentNullException(nameof(request.Data));
|
||||
|
||||
if (_priorityTypes.Contains(request.Type))
|
||||
{
|
||||
if (!request.Priority.HasValue)
|
||||
throw new ArgumentNullException(nameof(request.Priority));
|
||||
|
||||
req.Priority = request.Priority.Value;
|
||||
}
|
||||
|
||||
if (request.Ttl.HasValue)
|
||||
{
|
||||
if (request.Ttl == 1)
|
||||
{
|
||||
req.Ttl = 1;
|
||||
}
|
||||
else if (request.Ttl < 30 || 86400 < request.Ttl)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(request.Ttl), request.Ttl, "Value must be between 60 (Enterprise: 30) and 86400.");
|
||||
}
|
||||
else
|
||||
{
|
||||
req.Ttl = request.Ttl;
|
||||
}
|
||||
}
|
||||
|
||||
switch (request.Type)
|
||||
{
|
||||
case DnsRecordType.Caa:
|
||||
if (request.Data is DnsRecord.CaaData caaData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(caaData.Tag))
|
||||
throw new ArgumentNullException(nameof(caaData.Tag));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(caaData.Value))
|
||||
throw new ArgumentNullException(nameof(caaData.Value));
|
||||
|
||||
req.Data = new DnsRecord.CaaData(caaData.Flags, caaData.Tag, caaData.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'CaaData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsRecordType.Cert:
|
||||
if (request.Data is DnsRecord.CertData certData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(certData.Certificate))
|
||||
throw new ArgumentNullException(nameof(certData.Certificate));
|
||||
|
||||
req.Data = new DnsRecord.CertData(certData.Algorithm, certData.Certificate, certData.KeyTag, certData.Type);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'CertData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsRecordType.DnsKey:
|
||||
if (request.Data is DnsRecord.DnsKeyData dnsKeyData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dnsKeyData.PublicKey))
|
||||
throw new ArgumentNullException(nameof(dnsKeyData.PublicKey));
|
||||
|
||||
req.Data = new DnsRecord.DnsKeyData(dnsKeyData.Algorithm, dnsKeyData.Flags, dnsKeyData.Protocol, dnsKeyData.PublicKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'DnsKeyData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsRecordType.Ds:
|
||||
if (request.Data is DnsRecord.DsData dsData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dsData.Digest))
|
||||
throw new ArgumentNullException(nameof(dsData.Digest));
|
||||
|
||||
req.Data = new DnsRecord.DsData(dsData.Algorithm, dsData.Digest, dsData.DigestType, dsData.KeyTag);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'DsData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsRecordType.Https:
|
||||
if (request.Data is DnsRecord.HttpsData httpsData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(httpsData.Target))
|
||||
throw new ArgumentNullException(nameof(httpsData.Target));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(httpsData.Value))
|
||||
throw new ArgumentNullException(nameof(httpsData.Value));
|
||||
|
||||
req.Data = new DnsRecord.HttpsData(httpsData.Priority, httpsData.Target, httpsData.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'HttpsData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsRecordType.Loc:
|
||||
if (request.Data is DnsRecord.LocData locData)
|
||||
{
|
||||
if (locData.LatitudeDegrees < 0 || 90 < locData.LatitudeDegrees)
|
||||
throw new ArgumentOutOfRangeException(nameof(locData.LatitudeDegrees), locData.LatitudeDegrees, "Value must be between 0 and 90.");
|
||||
|
||||
if (locData.LatitudeMinutes < 0 || 59 < locData.LatitudeMinutes)
|
||||
throw new ArgumentOutOfRangeException(nameof(locData.LatitudeMinutes), locData.LatitudeMinutes, "Value must be between 0 and 59.");
|
||||
|
||||
if (locData.LatitudeSeconds < 0 || 59.999 < locData.LatitudeSeconds)
|
||||
throw new ArgumentOutOfRangeException(nameof(locData.LatitudeSeconds), locData.LatitudeSeconds, "Value must be between 0 and 59.999.");
|
||||
|
||||
if (!Enum.IsDefined(typeof(DnsRecord.LatitudeDirection), locData.LatitudeDirection))
|
||||
throw new ArgumentOutOfRangeException(nameof(locData.LatitudeDirection), locData.LatitudeDirection, "Value must be one of the 'ZoneDnsRecord.LatitudeDirection' enum values.");
|
||||
|
||||
if (locData.LongitudeDegrees < 0 || 180 < locData.LongitudeDegrees)
|
||||
throw new ArgumentOutOfRangeException(nameof(locData.LongitudeDegrees), locData.LongitudeDegrees, "Value must be between 0 and 180.");
|
||||
|
||||
if (locData.LongitudeMinutes < 0 || 59 < locData.LongitudeMinutes)
|
||||
throw new ArgumentOutOfRangeException(nameof(locData.LongitudeMinutes), locData.LongitudeMinutes, "Value must be between 0 and 59.");
|
||||
|
||||
if (locData.LongitudeSeconds < 0 || 59.999 < locData.LongitudeSeconds)
|
||||
throw new ArgumentOutOfRangeException(nameof(locData.LongitudeSeconds), locData.LongitudeSeconds, "Value must be between 0 and 59.999.");
|
||||
|
||||
if (!Enum.IsDefined(typeof(DnsRecord.LongitudeDirection), locData.LongitudeDirection))
|
||||
throw new ArgumentOutOfRangeException(nameof(locData.LongitudeDirection), locData.LongitudeDirection, "Value must be one of the 'ZoneDnsRecord.LongitudeDirection' enum values.");
|
||||
|
||||
if (locData.Altitude < -100_000 || 42_849_672.95 < locData.Altitude)
|
||||
throw new ArgumentOutOfRangeException(nameof(locData.Altitude), locData.Altitude, "Value must be between -100,000.00 and 42,849,672.95.");
|
||||
|
||||
if (locData.Size < 0 || 90_000_000 < locData.Size)
|
||||
throw new ArgumentOutOfRangeException(nameof(locData.Size), locData.Size, "Value must be between 0 and 90,000,000.");
|
||||
|
||||
if (locData.PrecisionHorizontal < 0 || 90_000_000 < locData.PrecisionHorizontal)
|
||||
throw new ArgumentOutOfRangeException(nameof(locData.PrecisionHorizontal), locData.PrecisionHorizontal, "Value must be between 0 and 90,000,000.");
|
||||
|
||||
if (locData.PrecisionVertical < 0 || 90_000_000 < locData.PrecisionVertical)
|
||||
throw new ArgumentOutOfRangeException(nameof(locData.PrecisionVertical), locData.PrecisionVertical, "Value must be between 0 and 90,000,000.");
|
||||
|
||||
req.Data = new DnsRecord.LocData(
|
||||
latitudeDegrees: locData.LatitudeDegrees,
|
||||
latitudeMinutes: locData.LatitudeMinutes,
|
||||
latitudeSeconds: Math.Floor(locData.LatitudeSeconds * 1000) / 1000, // Truncate to 3 decimal places
|
||||
latitudeDirection: locData.LatitudeDirection,
|
||||
longitudeDegrees: locData.LongitudeDegrees,
|
||||
longitudeMinutes: locData.LongitudeMinutes,
|
||||
longitudeSeconds: Math.Floor(locData.LongitudeSeconds * 1000) / 1000, // Truncate to 3 decimal places
|
||||
longitudeDirection: locData.LongitudeDirection,
|
||||
altitude: Math.Floor(locData.Altitude * 100) / 100, // Truncate to 2 decimal places
|
||||
size: locData.Size,
|
||||
precisionHorizontal: locData.PrecisionHorizontal,
|
||||
precisionVertical: locData.PrecisionVertical
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'LocData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsRecordType.NaPtr:
|
||||
if (request.Data is DnsRecord.NaPtrData naPtrData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(naPtrData.Flags))
|
||||
throw new ArgumentNullException(nameof(naPtrData.Flags));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(naPtrData.Regex))
|
||||
throw new ArgumentNullException(nameof(naPtrData.Regex));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(naPtrData.Replacement))
|
||||
throw new ArgumentNullException(nameof(naPtrData.Replacement));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(naPtrData.Service))
|
||||
throw new ArgumentNullException(nameof(naPtrData.Service));
|
||||
|
||||
req.Data = new DnsRecord.NaPtrData(
|
||||
naPtrData.Flags,
|
||||
naPtrData.Order,
|
||||
naPtrData.Preference,
|
||||
naPtrData.Regex,
|
||||
naPtrData.Replacement,
|
||||
naPtrData.Service
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'NaPtrData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsRecordType.SMimeA:
|
||||
if (request.Data is DnsRecord.SMimeAData sMimeAData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sMimeAData.Certificate))
|
||||
throw new ArgumentNullException(nameof(sMimeAData.Certificate));
|
||||
|
||||
req.Data = new DnsRecord.SMimeAData(sMimeAData.Certificate, sMimeAData.MatchingType, sMimeAData.Selector, sMimeAData.Usage);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'SMimeAData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsRecordType.Srv:
|
||||
if (request.Data is DnsRecord.SrvData srvData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(srvData.Target))
|
||||
throw new ArgumentNullException(nameof(srvData.Target));
|
||||
|
||||
req.Data = new DnsRecord.SrvData(srvData.Port, srvData.Priority, srvData.Target, srvData.Weight);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'SrvData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsRecordType.SshFp:
|
||||
if (request.Data is DnsRecord.SshFpData sshFpData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sshFpData.Fingerprint))
|
||||
throw new ArgumentNullException(nameof(sshFpData.Fingerprint));
|
||||
|
||||
req.Data = new DnsRecord.SshFpData(sshFpData.Algorithm, sshFpData.Fingerprint, sshFpData.Type);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'SshFpData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsRecordType.SvcB:
|
||||
if (request.Data is DnsRecord.SvcBData svcBData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(svcBData.Target))
|
||||
throw new ArgumentNullException(nameof(svcBData.Target));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(svcBData.Value))
|
||||
throw new ArgumentNullException(nameof(svcBData.Value));
|
||||
|
||||
req.Data = new DnsRecord.SvcBData(svcBData.Priority, svcBData.Target, svcBData.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'SvcBData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsRecordType.TlsA:
|
||||
if (request.Data is DnsRecord.TlsAData tlsAData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tlsAData.Certificate))
|
||||
throw new ArgumentNullException(nameof(tlsAData.Certificate));
|
||||
|
||||
req.Data = new DnsRecord.TlsAData(tlsAData.Certificate, tlsAData.MatchingType, tlsAData.Selector, tlsAData.Usage);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'TlsAData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
|
||||
case DnsRecordType.Uri:
|
||||
if (request.Data is DnsRecord.UriData uriData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(uriData.Target))
|
||||
throw new ArgumentNullException(nameof(uriData.Target));
|
||||
|
||||
req.Data = new DnsRecord.UriData(uriData.Target, uriData.Weight);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Value must be of type 'UriData'.", nameof(request.Data));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return req;
|
||||
}
|
||||
}
|
||||
}
|
||||
269
Extensions/Cloudflare.Zones/Enums/DnsRecordType.cs
Normal file
269
Extensions/Cloudflare.Zones/Enums/DnsRecordType.cs
Normal file
@@ -0,0 +1,269 @@
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// DNS record types.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A list with short description can be found <see href="https://en.wikipedia.org/wiki/List_of_DNS_record_types">@wikipedia</see>.
|
||||
/// </remarks>
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum DnsRecordType : int
|
||||
{
|
||||
/// <summary>
|
||||
/// Address record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a 32-bit IPv4 address, most commonly used to map hostnames to an IP address of the host, but it is also used for DNSBLs, storing subnet masks in RFC 1101, etc.
|
||||
/// <code>
|
||||
/// example.com. 3600 IN A 93.184.215.14
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "A")]
|
||||
A = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Name server record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Delegates a DNS zone to use the given authoritative name servers.
|
||||
/// <code>
|
||||
/// example.com. 86400 IN NS a.iana-servers.net.
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "NS")]
|
||||
Ns = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Canonical name record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alias of one name to another: the DNS lookup will continue by retrying the lookup with the new name.
|
||||
/// <code>
|
||||
/// autodiscover.example.com. 86400 IN CNAME mail.example.com.
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "CNAME")]
|
||||
Cname = 5,
|
||||
|
||||
/// <summary>
|
||||
/// PTR Resource Record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Pointer to a canonical name. Unlike a CNAME, DNS processing stops and just the name is returned. The most common use is for implementing reverse DNS lookups, but other uses include such things as DNS-SD.
|
||||
/// <code>
|
||||
/// 14.215.184.93.in-addr.arpa. 86400 IN PTR example.com.
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "PTR")]
|
||||
Ptr = 12,
|
||||
|
||||
/// <summary>
|
||||
/// Mail exchange record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// List of mail exchange servers that accept email for a domain.
|
||||
/// <code>
|
||||
/// example.com. 43200 IN MX 0 mail.example.com.
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "MX")]
|
||||
Mx = 15,
|
||||
|
||||
/// <summary>
|
||||
/// Text record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Originally for arbitrary human-readable text in a DNS record. Since the early 1990s, however, this record more often carries machine-readable data, such as specified by RFC 1464, opportunistic encryption, Sender Policy Framework, DKIM, DMARC, DNS-SD, etc.
|
||||
/// <br/>
|
||||
/// More information about TXT records on <see href="https://www.cloudflare.com/learning/dns/dns-records/dns-txt-record/">Cloudflare</see>.
|
||||
/// <code>
|
||||
/// example.com. 86400 IN TXT "v=spf1 -all"
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "TXT")]
|
||||
Txt = 16,
|
||||
|
||||
/// <summary>
|
||||
/// IPv6 address record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns a 128-bit IPv6 address, most commonly used to map hostnames to an IP address of the host.
|
||||
/// <code>
|
||||
/// example.com. 3600 IN AAAA 2606:2800:21f:cb07:6820:80da:af6b:8b2c
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "AAAA")]
|
||||
Aaaa = 28,
|
||||
|
||||
/// <summary>
|
||||
/// Location record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Specifies a geographical location associated with a domain name.
|
||||
/// <code>
|
||||
/// SW1A2AA.find.me.uk. 2592000 IN LOC 51 30 12.748 N 0 7 39.611 W 0.00m 0.00m 0.00m 0.00m
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "LOC")]
|
||||
Loc = 29,
|
||||
|
||||
/// <summary>
|
||||
/// Service locator.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Generalized service location record, used for newer protocols instead of creating protocol-specific records such as MX.
|
||||
/// <code>
|
||||
/// _autodiscover._tcp.example.com. 604800 IN SRV 1 0 443 mail.example.com.
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "SRV")]
|
||||
Srv = 33,
|
||||
|
||||
/// <summary>
|
||||
/// Naming Authority Pointer.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Allows regular-expression-based rewriting of domain names which can then be used as URIs, further domain names to lookups, etc.
|
||||
/// <code>
|
||||
/// example.com. 86400 IN NAPTR 100 10 "S" "SIP+D2T" "" _sip._tcp.example.com.
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "NAPTR")]
|
||||
NaPtr = 35,
|
||||
|
||||
/// <summary>
|
||||
/// Certificate record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Stores PKIX, SPKI, PGP, etc.
|
||||
/// <code>
|
||||
/// example.com. 86400 IN CERT 2 77 2 TUlJQ1l6Q0NBY3lnQXdJQkFnSUJBREFOQmdrcWh
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "CERT")]
|
||||
Cert = 37,
|
||||
|
||||
/// <summary>
|
||||
/// Delegation signer.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The record used to identify the DNSSEC signing key of a delegated zone.
|
||||
/// <code>
|
||||
/// example.com. 86400 IN DS 370 13 2 BE74359954660069D5C63D200C39F5603827D7DD02B56F120EE9F3A8 6764247C
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "DS")]
|
||||
Ds = 43,
|
||||
|
||||
/// <summary>
|
||||
/// SSH Public Key Fingerprint.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Resource record for publishing SSH public host key fingerprints in the DNS, in order to aid in verifying the authenticity of the host. RFC 6594 defines ECC SSH keys and SHA-256 hashes. See the IANA SSHFP RR parameters registry for details.
|
||||
/// <code>
|
||||
/// example.com. 600 IN SSHFP 2 1 123456789abcdef67890123456789abcdef67890
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "SSHFP")]
|
||||
SshFp = 44,
|
||||
|
||||
/// <summary>
|
||||
/// DNS Key record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The key record used in DNSSEC. Uses the same format as the KEY record.
|
||||
/// <code>
|
||||
/// example.com. 3600 IN DNSKEY 256 3 13 OtuN/SL9sE+SDQ0tOLeezr1KzUNi77FflTjxQylUhm3V7m13Vz9tYQuc SGK0pyxISo9CQsszubAwJSypq3li3g==
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "DNSKEY")]
|
||||
DnsKey = 48,
|
||||
|
||||
/// <summary>
|
||||
/// TLSA certificate association.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A record for DANE. RFC 6698 defines "The TLSA DNS resource record is used to associate a TLS server certificate or public key with the domain name where the record is found, thus forming a 'TLSA certificate association'".
|
||||
/// <code>
|
||||
/// _443._tcp.example.com. 3600 IN TLSA 3 0 18cb0fc6c527506a053f4f14c8464bebbd6dede2738d11468dd953d7d6a3021f1
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "TLSA")]
|
||||
TlsA = 52,
|
||||
|
||||
/// <summary>
|
||||
/// S/MIME cert association.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Associates an S/MIME certificate with a domain name for sender authentication.
|
||||
/// <code>
|
||||
/// example.com. 3600 IN SMIMEA 0 0 0 keyKEY1234keyKEY
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "SMIMEA")]
|
||||
SMimeA = 53,
|
||||
|
||||
/// <summary>
|
||||
/// OpenPGP public key record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A DNS-based Authentication of Named Entities (DANE) method for publishing and locating OpenPGP public keys in DNS for a specific email address using an OPENPGPKEY DNS resource record.
|
||||
/// <code>
|
||||
/// 00d8d3f11739d2f3537099982b4674c29fc59a8fda350fca1379613a._openpgpkey.example.com. 3600 IN OPENPGPKEY a2V5S0VZMTIzNGtleUtFWQ==
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "OPENPGPKEY")]
|
||||
OpenPgpgKey = 61,
|
||||
|
||||
/// <summary>
|
||||
/// Service Binding.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// RR that improves performance for clients that need to resolve many resources to access a domain.
|
||||
/// <code>
|
||||
/// example.com. 3600 IN SVCB 1 . alpn="h2,http/1.1"
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "SVCB")]
|
||||
SvcB = 64,
|
||||
|
||||
/// <summary>
|
||||
/// HTTPS Binding.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// RR that improves performance for clients that need to resolve many resources to access a domain.
|
||||
/// <code>
|
||||
/// example.com. 3600 IN HTTPS 1 svc.example.com. alpn=h2
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "HTTPS")]
|
||||
Https = 65,
|
||||
|
||||
/// <summary>
|
||||
/// Uniform Resource Identifier.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Can be used for publishing mappings from hostnames to URIs.
|
||||
/// <code>
|
||||
/// _ftp._tcp.example.com. 3600 IN URI 10 1 "ftp://ftp.example.com/public"
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "URI")]
|
||||
Uri = 256,
|
||||
|
||||
/// <summary>
|
||||
/// Certification Authority Authorization
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// DNS Certification Authority Authorization, constraining acceptable CAs for a host/domain.
|
||||
/// <code>
|
||||
/// example.com. 604800 IN CAA 0 issue "letsencrypt.org"
|
||||
/// </code>
|
||||
/// </remarks>
|
||||
[EnumMember(Value = "CAA")]
|
||||
Caa = 257,
|
||||
}
|
||||
}
|
||||
42
Extensions/Cloudflare.Zones/Enums/DnsRecordsOrderBy.cs
Normal file
42
Extensions/Cloudflare.Zones/Enums/DnsRecordsOrderBy.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// Possible fields to order DNS records by.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum DnsRecordsOrderBy
|
||||
{
|
||||
/// <summary>
|
||||
/// Order by record type.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "type")]
|
||||
Type = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Order by record name.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "name")]
|
||||
Name = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Order by record content.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "content")]
|
||||
Content = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Order by record TTL.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "ttl")]
|
||||
Ttl = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Order by record proxied.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "proxied")]
|
||||
Proxied = 5
|
||||
}
|
||||
}
|
||||
402
Extensions/Cloudflare.Zones/Filters/ListDnsRecordsFilter.cs
Normal file
402
Extensions/Cloudflare.Zones/Filters/ListDnsRecordsFilter.cs
Normal file
@@ -0,0 +1,402 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// Filter for listing DNS records.
|
||||
/// </summary>
|
||||
public class ListDnsRecordsFilter : IQueryParameterFilter
|
||||
{
|
||||
#region Comment
|
||||
|
||||
/// <summary>
|
||||
/// Exact value of the DNS record comment.
|
||||
/// This is a convenience alias for <see cref="CommentExact"/>.
|
||||
/// </summary>
|
||||
public string? Comment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If this parameter is present, only records <em>without</em> a comment are returned.
|
||||
/// </summary>
|
||||
public bool? CommentAbsent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Substring of the DNS record comment.
|
||||
/// Comment filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? CommentContains { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Suffix of the DNS record comment.
|
||||
/// Comment filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? CommentEndsWith { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Exact value of the DNS record comment.
|
||||
/// Comment filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? CommentExact { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If this parameter is present, only records <em>with</em> a comment are returned.
|
||||
/// </summary>
|
||||
public bool? CommentPresent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Prefix of the DNS record comment.
|
||||
/// Comment filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? CommentStartsWith { get; set; }
|
||||
|
||||
#endregion Comment
|
||||
|
||||
#region Content
|
||||
|
||||
/// <summary>
|
||||
/// Exact value of the DNS record Content.
|
||||
/// This is a convenience alias for <see cref="ContentExact"/>.
|
||||
/// </summary>
|
||||
public string? Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Substring of the DNS record Content.
|
||||
/// Content filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? ContentContains { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Suffix of the DNS record Content.
|
||||
/// Content filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? ContentEndsWith { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Exact value of the DNS record Content.
|
||||
/// Content filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? ContentExact { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Prefix of the DNS record Content.
|
||||
/// Content filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? ContentStartsWith { get; set; }
|
||||
|
||||
#endregion Content
|
||||
|
||||
/// <summary>
|
||||
/// Direction to order DNS records in.
|
||||
/// </summary>
|
||||
public SortDirection? Direction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to match all search requirements or at least one (any).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// If set to <see cref="FilterMatchType.All"/>, acts like a logical AND between filters.
|
||||
/// <br/>
|
||||
/// If set to <see cref="FilterMatchType.Any"/>, acts like a logical OR instead.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Note that the interaction between tag filters is controlled by the <see cref="TagMatch"/> parameter instead.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public FilterMatchType? Match { get; set; }
|
||||
|
||||
#region Name
|
||||
|
||||
/// <summary>
|
||||
/// Exact value of the DNS record Name.
|
||||
/// This is a convenience alias for <see cref="NameExact"/>.
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Substring of the DNS record Name.
|
||||
/// Name filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? NameContains { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Suffix of the DNS record Name.
|
||||
/// Name filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? NameEndsWith { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Exact value of the DNS record Name.
|
||||
/// Name filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? NameExact { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Prefix of the DNS record Name.
|
||||
/// Name filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? NameStartsWith { get; set; }
|
||||
|
||||
#endregion Name
|
||||
|
||||
/// <summary>
|
||||
/// Field to order DNS records by.
|
||||
/// </summary>
|
||||
public DnsRecordsOrderBy? OrderBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Page number of paginated results.
|
||||
/// </summary>
|
||||
// >= 1
|
||||
public int? Page { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of DNS records per page.
|
||||
/// </summary>
|
||||
// >= 1 <= 5_000_000
|
||||
public int? PerPage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the record is receiving the performance and security benefits of Cloudflare.
|
||||
/// </summary>
|
||||
public bool? Proxied { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allows searching in multiple properties of a DNS record simultaneously.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This parameter is intended for human users, not automation.
|
||||
/// Its exact behavior is intentionally left unspecified and is subject to change in the future.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <em>
|
||||
/// This parameter works independently of the <see cref="Match"/> setting.
|
||||
/// <br/>
|
||||
/// For automated searches, please use the other available parameters.
|
||||
/// </em>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public string? Search { get; set; }
|
||||
|
||||
#region Tag
|
||||
|
||||
/// <summary>
|
||||
/// Condition on the DNS record tag.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Parameter values can be of the form <c><tag-name>:<tag-value></c> to search for an exact name:value pair,
|
||||
/// or just <c><tag-name></c> to search for records with a specific tag name regardless of its value.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This is a convenience shorthand for the more powerful <c>tag.<predicate></c> parameters.
|
||||
/// <br/>
|
||||
/// Examples:
|
||||
/// <list type="bullet">
|
||||
/// <item><c>tag=important</c> is equivalent to <c>tag.present=important</c></item>
|
||||
/// <item><c>tag=team:DNS</c> is equivalent to <c>tag.exact=team:DNS</c></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public string? Tag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of a tag which must <em>not</em> be present on the DNS record.
|
||||
/// Tag filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? TagAbsent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A tag and value, of the form <c><tag-name>:<tag-value></c>.
|
||||
/// Tag filters are case-insensitive.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The API will only return DNS records that have a tag named <c><tag-name></c> whose value contains <c><tag-value></c>.
|
||||
/// </remarks>
|
||||
public string? TagContains { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A tag and value, of the form <c><tag-name>:<tag-value></c>.
|
||||
/// Tag filters are case-insensitive.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The API will only return DNS records that have a tag named <c><tag-name></c> whose value ends with <c><tag-value></c>.
|
||||
/// </remarks>
|
||||
public string? TagEndsWith { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A tag and value, of the form <c><tag-name>:<tag-value></c>.
|
||||
/// Tag filters are case-insensitive.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The API will only return DNS records that have a tag named <c><tag-name></c> whose value is <c><tag-value></c>.
|
||||
/// </remarks>
|
||||
public string? TagExact { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of a tag which must be present on the DNS record.
|
||||
/// Tag filters are case-insensitive.
|
||||
/// </summary>
|
||||
public string? TagPresent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A tag and value, of the form <c><tag-name>:<tag-value></c>.
|
||||
/// Tag filters are case-insensitive.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The API will only return DNS records that have a tag named <c><tag-name></c> whose value starts with <c><tag-value></c>.
|
||||
/// </remarks>
|
||||
public string? TagStartsWith { get; set; }
|
||||
|
||||
#endregion Tag
|
||||
|
||||
/// <summary>
|
||||
/// Whether to match all tag search requirements or at least one (any).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// If set to <see cref="FilterMatchType.All"/>, acts like a logical AND between filters.
|
||||
/// <br/>
|
||||
/// If set to <see cref="FilterMatchType.Any"/>, acts like a logical OR instead.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Note that the regular <see cref="Match"/> parameter is still used to combine the resulting condition with other filters that aren't related to tags.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public FilterMatchType? TagMatch { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Record type.
|
||||
/// </summary>
|
||||
public DnsRecordType? Type { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDictionary<string, string> GetQueryParameters()
|
||||
{
|
||||
var dict = new Dictionary<string, string>();
|
||||
|
||||
#pragma warning disable CS8602, CS8604 // There will be no null value below.
|
||||
|
||||
#region Comment
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Comment))
|
||||
dict.Add("comment", Comment.Trim());
|
||||
|
||||
if (CommentAbsent.HasValue && CommentAbsent.Value)
|
||||
dict.Add("comment.absent", "true");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(CommentContains))
|
||||
dict.Add("comment.contains", CommentContains.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(CommentEndsWith))
|
||||
dict.Add("comment.endswith", CommentEndsWith.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(CommentExact))
|
||||
dict.Add("comment.exact", CommentExact.Trim());
|
||||
|
||||
if (CommentPresent.HasValue && CommentPresent.Value)
|
||||
dict.Add("comment.present", "true");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(CommentStartsWith))
|
||||
dict.Add("comment.startswith", CommentStartsWith.Trim());
|
||||
|
||||
#endregion Comment
|
||||
|
||||
#region Content
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Content))
|
||||
dict.Add("content", Content.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(ContentContains))
|
||||
dict.Add("content.contains", ContentContains.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(ContentEndsWith))
|
||||
dict.Add("content.endswith", ContentEndsWith.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(ContentExact))
|
||||
dict.Add("content.exact", ContentExact.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(ContentStartsWith))
|
||||
dict.Add("content.startswith", ContentStartsWith.Trim());
|
||||
|
||||
#endregion Content
|
||||
|
||||
if (Direction.HasValue && Enum.IsDefined(typeof(SortDirection), Direction.Value))
|
||||
dict.Add("direction", Direction.Value.GetEnumMemberValue());
|
||||
|
||||
if (Match.HasValue && Enum.IsDefined(typeof(FilterMatchType), Match.Value))
|
||||
dict.Add("match", Match.Value.GetEnumMemberValue());
|
||||
|
||||
#region Name
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Name))
|
||||
dict.Add("name", Name.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(NameContains))
|
||||
dict.Add("name.contains", NameContains.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(NameEndsWith))
|
||||
dict.Add("name.endswith", NameEndsWith.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(NameExact))
|
||||
dict.Add("name.exact", NameExact.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(NameStartsWith))
|
||||
dict.Add("name.startswith", NameStartsWith.Trim());
|
||||
|
||||
#endregion Name
|
||||
|
||||
if (OrderBy.HasValue && Enum.IsDefined(typeof(DnsRecordsOrderBy), OrderBy.Value))
|
||||
dict.Add("order", OrderBy.Value.GetEnumMemberValue());
|
||||
|
||||
if (Page.HasValue && Page.Value >= 1)
|
||||
dict.Add("page", Page.Value.ToString());
|
||||
|
||||
if (PerPage.HasValue && PerPage.Value >= 1 && PerPage.Value <= 5_000_000)
|
||||
dict.Add("per_page", PerPage.Value.ToString());
|
||||
|
||||
if (Proxied.HasValue)
|
||||
dict.Add("proxied", Proxied.Value.ToString().ToLowerInvariant());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Search))
|
||||
dict.Add("search", Search.Trim());
|
||||
|
||||
#region Tag
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Tag))
|
||||
dict.Add("tag", Tag.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(TagAbsent))
|
||||
dict.Add("tag.absent", TagAbsent.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(TagContains))
|
||||
dict.Add("tag.contains", TagContains.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(TagEndsWith))
|
||||
dict.Add("tag.endswith", TagEndsWith.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(TagExact))
|
||||
dict.Add("tag.exact", TagExact.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(TagPresent))
|
||||
dict.Add("tag.present", TagPresent.Trim());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(TagStartsWith))
|
||||
dict.Add("tag.startswith", TagStartsWith.Trim());
|
||||
|
||||
#endregion Tag
|
||||
|
||||
if (TagMatch.HasValue && Enum.IsDefined(typeof(FilterMatchType), TagMatch.Value))
|
||||
dict.Add("tag_match", TagMatch.Value.GetEnumMemberValue());
|
||||
|
||||
if (Type.HasValue && Enum.IsDefined(typeof(DnsRecordType), Type.Value))
|
||||
dict.Add("type", Type.Value.GetEnumMemberValue());
|
||||
|
||||
#pragma warning restore CS8602, CS8604
|
||||
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones.Internals.Requests
|
||||
{
|
||||
internal class InternalBatchRequest
|
||||
{
|
||||
[JsonProperty("deletes")]
|
||||
public IList<InternalDnsRecordId>? Deletes { get; set; }
|
||||
|
||||
[JsonProperty("patches")]
|
||||
public IList<InternalBatchUpdateRequest>? Patches { get; set; }
|
||||
|
||||
[JsonProperty("puts")]
|
||||
public IList<InternalBatchUpdateRequest>? Puts { get; set; }
|
||||
|
||||
[JsonProperty("posts")]
|
||||
public IList<InternalDnsRecordRequest>? Posts { get; set; }
|
||||
}
|
||||
|
||||
internal class InternalDnsRecordId
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public string? Id { get; set; }
|
||||
}
|
||||
|
||||
internal class InternalBatchUpdateRequest(string id, InternalDnsRecordRequest baseInstance)
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; } = id;
|
||||
|
||||
[JsonProperty("comment")]
|
||||
public string? Comment { get; set; } = baseInstance.Comment;
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; } = baseInstance.Name;
|
||||
|
||||
[JsonProperty("proxied")]
|
||||
public bool Proxied { get; set; } = baseInstance.Proxied;
|
||||
|
||||
[JsonProperty("settings")]
|
||||
public object? Settings { get; set; } = baseInstance.Settings;
|
||||
|
||||
[JsonProperty("tags")]
|
||||
public IList<string>? Tags { get; set; } = baseInstance.Tags;
|
||||
|
||||
[JsonProperty("ttl")]
|
||||
public int? Ttl { get; set; } = baseInstance.Ttl;
|
||||
|
||||
[JsonProperty("data")]
|
||||
public object? Data { get; set; } = baseInstance.Data;
|
||||
|
||||
[JsonProperty("content")]
|
||||
public string? Content { get; set; } = baseInstance.Content;
|
||||
|
||||
[JsonProperty("priority")]
|
||||
public ushort? Priority { get; set; } = baseInstance.Priority;
|
||||
|
||||
[JsonProperty("type")]
|
||||
public DnsRecordType Type { get; set; } = baseInstance.Type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones.Internals.Requests
|
||||
{
|
||||
internal class InternalDnsRecordRequest
|
||||
{
|
||||
public InternalDnsRecordRequest(DnsRecordType type, string name)
|
||||
{
|
||||
Type = type;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
[JsonProperty("comment")]
|
||||
public string? Comment { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("proxied")]
|
||||
public bool Proxied { get; set; }
|
||||
|
||||
[JsonProperty("settings")]
|
||||
public object? Settings { get; set; }
|
||||
|
||||
[JsonProperty("tags")]
|
||||
public IList<string>? Tags { get; set; }
|
||||
|
||||
[JsonProperty("ttl")]
|
||||
public int? Ttl { get; set; }
|
||||
|
||||
[JsonProperty("data")]
|
||||
public object? Data { get; set; }
|
||||
|
||||
[JsonProperty("content")]
|
||||
public string? Content { get; set; }
|
||||
|
||||
[JsonProperty("priority")]
|
||||
public ushort? Priority { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public DnsRecordType Type { get; set; }
|
||||
}
|
||||
}
|
||||
34
Extensions/Cloudflare.Zones/Models/BatchDnsRecordsResult.cs
Normal file
34
Extensions/Cloudflare.Zones/Models/BatchDnsRecordsResult.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// The DNS batch execution response.
|
||||
/// </summary>
|
||||
public class BatchDnsRecordsResult
|
||||
{
|
||||
/// <summary>
|
||||
/// The deleted records.
|
||||
/// </summary>
|
||||
[JsonProperty("deletes")]
|
||||
public IList<DnsRecord>? DeletedRecords { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The updated records.
|
||||
/// </summary>
|
||||
[JsonProperty("patches")]
|
||||
public IList<DnsRecord>? UpdatedRecords { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The overwritten records.
|
||||
/// </summary>
|
||||
[JsonProperty("puts")]
|
||||
public IList<DnsRecord>? OverwrittenRecords { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The created records.
|
||||
/// </summary>
|
||||
[JsonProperty("posts")]
|
||||
public IList<DnsRecord>? CreatedRecords { get; set; }
|
||||
}
|
||||
}
|
||||
618
Extensions/Cloudflare.Zones/Models/DnsRecord.cs
Normal file
618
Extensions/Cloudflare.Zones/Models/DnsRecord.cs
Normal file
@@ -0,0 +1,618 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// DNS record.
|
||||
/// </summary>
|
||||
public class DnsRecord
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifier.
|
||||
/// </summary>
|
||||
[JsonProperty("id")]
|
||||
public string? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Identifier of the zone.
|
||||
/// </summary>
|
||||
[JsonProperty("zone_id")]
|
||||
public string? ZoneId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the zone.
|
||||
/// </summary>
|
||||
[JsonProperty("zone_name")]
|
||||
public string? ZoneName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DNS record name (or @ for the zone apex) in Punycode.
|
||||
/// </summary>
|
||||
[JsonProperty("name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Record type.
|
||||
/// </summary>
|
||||
[JsonProperty("type")]
|
||||
public DnsRecordType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A valid record content.
|
||||
/// </summary>
|
||||
[JsonProperty("content")]
|
||||
public string? Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Components associated with the record.
|
||||
/// </summary>
|
||||
[JsonProperty("data")]
|
||||
public object? Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the record can be proxied by Cloudflare or not.
|
||||
/// </summary>
|
||||
[JsonProperty("proxiable")]
|
||||
public bool Proxiable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the record is receiving the performance and security benefits of Cloudflare.
|
||||
/// </summary>
|
||||
[JsonProperty("proxied")]
|
||||
public bool Proxied { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Time To Live (TTL) of the DNS record in seconds. Setting to 1 means 'automatic'.
|
||||
/// Value must be between 60 and 86400, <em>with the minimum reduced to 30 for Enterprise zones</em>.
|
||||
/// </summary>
|
||||
/// <value>Unit: seconds. Range: <c>60 <=</c> X <c><= 86400</c></value>
|
||||
[JsonProperty("ttl")]
|
||||
public int Ttl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Settings for the DNS record.
|
||||
/// </summary>
|
||||
[JsonProperty("settings")]
|
||||
public object? Settings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Extra Cloudflare-specific information about the record.
|
||||
/// </summary>
|
||||
[JsonProperty("meta")]
|
||||
public DnsRecordMeta? Meta { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Comments or notes about the DNS record. This field has no effect on DNS responses.
|
||||
/// </summary>
|
||||
[JsonProperty("comment")]
|
||||
public string? Comment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Custom tags for the DNS record. This field has no effect on DNS responses.
|
||||
/// </summary>
|
||||
[JsonProperty("tags")]
|
||||
public IList<string>? Tags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When the record was created.
|
||||
/// </summary>
|
||||
[JsonProperty("created_on")]
|
||||
public DateTime CreatedOn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When the record was last modified.
|
||||
/// </summary>
|
||||
[JsonProperty("modified_on")]
|
||||
public DateTime ModifiedOn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When the record comment was last modified. Omitted if there is no comment.
|
||||
/// </summary>
|
||||
[JsonProperty("comment_modified_on")]
|
||||
public DateTime? CommentModifiedOn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When the record tags were last modified. Omitted if there are no tags.
|
||||
/// </summary>
|
||||
[JsonProperty("tags_modified_on")]
|
||||
public DateTime? TagsModifiedOn { get; set; }
|
||||
|
||||
#region Type definitions for data fields
|
||||
|
||||
/// <summary>
|
||||
/// Components of a CAA record.
|
||||
/// </summary>
|
||||
public class CaaData(byte flags, string tag, string value)
|
||||
{
|
||||
/// <summary>
|
||||
/// Flags for the CAA record
|
||||
/// </summary>
|
||||
/// <value>Range: <c>0 <=</c> X <c><= 255</c></value>
|
||||
[JsonProperty("flags")]
|
||||
public byte Flags { get; set; } = flags;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the property controlled by this record (e.g.: issue, issuewild, iodef).
|
||||
/// </summary>
|
||||
[JsonProperty("tag")]
|
||||
public string Tag { get; set; } = tag;
|
||||
|
||||
/// <summary>
|
||||
/// Value of the record. This field's semantics depend on the chosen tag.
|
||||
/// </summary>
|
||||
[JsonProperty("value")]
|
||||
public string Value { get; set; } = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Components of a CERT record.
|
||||
/// </summary>
|
||||
public class CertData(byte algorithm, string certificate, ushort keyTag, ushort type)
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm of the certificate
|
||||
/// </summary>
|
||||
[JsonProperty("algorithm")]
|
||||
public byte Algorithm { get; set; } = algorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Base64 encoded certificate.
|
||||
/// </summary>
|
||||
[JsonProperty("certificate")]
|
||||
public string Certificate { get; set; } = certificate;
|
||||
|
||||
/// <summary>
|
||||
/// Key tag.
|
||||
/// </summary>
|
||||
[JsonProperty("key_tag")]
|
||||
public ushort KeyTag { get; set; } = keyTag;
|
||||
|
||||
/// <summary>
|
||||
/// Type.
|
||||
/// </summary>
|
||||
[JsonProperty("type")]
|
||||
public ushort Type { get; set; } = type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Components of a DNSKEY record.
|
||||
/// </summary>
|
||||
public class DnsKeyData(byte algorithm, ushort flags, byte protocol, string publicKey)
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm of the certificate
|
||||
/// </summary>
|
||||
[JsonProperty("algorithm")]
|
||||
public byte Algorithm { get; set; } = algorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Algorithm of the certificate
|
||||
/// </summary>
|
||||
[JsonProperty("flags")]
|
||||
public ushort Flags { get; set; } = flags;
|
||||
|
||||
/// <summary>
|
||||
/// Algorithm of the certificate
|
||||
/// </summary>
|
||||
[JsonProperty("protocol")]
|
||||
public byte Protocol { get; set; } = protocol;
|
||||
|
||||
/// <summary>
|
||||
/// Public key.
|
||||
/// </summary>
|
||||
[JsonProperty("public_key")]
|
||||
public string PublicKey { get; set; } = publicKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Components of a DS record.
|
||||
/// </summary>
|
||||
public class DsData(byte algorithm, string digest, byte digestType, ushort keyTag)
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm of the certificate
|
||||
/// </summary>
|
||||
[JsonProperty("algorithm")]
|
||||
public byte Algorithm { get; set; } = algorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Digest.
|
||||
/// </summary>
|
||||
[JsonProperty("digest")]
|
||||
public string Digest { get; set; } = digest;
|
||||
|
||||
/// <summary>
|
||||
/// Digest type.
|
||||
/// </summary>
|
||||
[JsonProperty("digest_type")]
|
||||
public byte DigestType { get; set; } = digestType;
|
||||
|
||||
/// <summary>
|
||||
/// Key tag.
|
||||
/// </summary>
|
||||
[JsonProperty("key_tag")]
|
||||
public ushort KeyTag { get; set; } = keyTag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Components of an HTTPS record.
|
||||
/// </summary>
|
||||
public class HttpsData(ushort priority, string target, string value)
|
||||
{
|
||||
/// <summary>
|
||||
/// Priority.
|
||||
/// </summary>
|
||||
[JsonProperty("priority")]
|
||||
public ushort Priority { get; set; } = priority;
|
||||
|
||||
/// <summary>
|
||||
/// Target.
|
||||
/// </summary>
|
||||
[JsonProperty("target")]
|
||||
public string Target { get; set; } = target;
|
||||
|
||||
/// <summary>
|
||||
/// Value.
|
||||
/// </summary>
|
||||
[JsonProperty("Value")]
|
||||
public string Value { get; set; } = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Components of a LOC record.
|
||||
/// </summary>
|
||||
public class LocData(int latitudeDegrees, int latitudeMinutes, double latitudeSeconds, LatitudeDirection latitudeDirection,
|
||||
int longitudeDegrees, int longitudeMinutes, double longitudeSeconds, LongitudeDirection longitudeDirection,
|
||||
double altitude, int size, int precisionHorizontal, int precisionVertical)
|
||||
{
|
||||
/// <summary>
|
||||
/// Degrees of latitude.
|
||||
/// </summary>
|
||||
/// <value>Unit: degree. Range: <c>0 <= X <= 90</c></value>
|
||||
[JsonProperty("lat_degrees")]
|
||||
public int LatitudeDegrees { get; set; } = latitudeDegrees;
|
||||
|
||||
/// <summary>
|
||||
/// Minutes of latitude.
|
||||
/// </summary>
|
||||
/// <value>Unit: minute. Range: <c>0 <= X <= 59</c></value>
|
||||
[JsonProperty("lat_minutes")]
|
||||
public int LatitudeMinutes { get; set; } = latitudeMinutes;
|
||||
|
||||
/// <summary>
|
||||
/// Seconds of latitude.
|
||||
/// </summary>
|
||||
/// <value>Unit: second. Range: <c>0 <= X <= 59.999</c></value>
|
||||
[JsonProperty("lat_seconds")]
|
||||
public double LatitudeSeconds { get; set; } = latitudeSeconds;
|
||||
|
||||
/// <summary>
|
||||
/// Latitude direction.
|
||||
/// </summary>
|
||||
[JsonProperty("lat_direction")]
|
||||
public LatitudeDirection LatitudeDirection { get; set; } = latitudeDirection;
|
||||
|
||||
/// <summary>
|
||||
/// Degrees of longitude.
|
||||
/// </summary>
|
||||
/// <value>Unit: degree. Range: <c>0 <= X <= 180</c></value>
|
||||
[JsonProperty("long_degrees")]
|
||||
public int LongitudeDegrees { get; set; } = longitudeDegrees;
|
||||
|
||||
/// <summary>
|
||||
/// Minutes of longitude.
|
||||
/// </summary>
|
||||
/// <value>Unit: minute. Range: <c>0 <= X <= 59</c></value>
|
||||
[JsonProperty("long_minutes")]
|
||||
public int LongitudeMinutes { get; set; } = longitudeMinutes;
|
||||
|
||||
/// <summary>
|
||||
/// Seconds of longitude.
|
||||
/// </summary>
|
||||
/// <value>Unit: second. Range: <c>0 <= X <= 59.999</c></value>
|
||||
[JsonProperty("long_seconds")]
|
||||
public double LongitudeSeconds { get; set; } = longitudeSeconds;
|
||||
|
||||
/// <summary>
|
||||
/// Longitude direction.
|
||||
/// </summary>
|
||||
[JsonProperty("long_direction")]
|
||||
public LongitudeDirection LongitudeDirection { get; set; } = longitudeDirection;
|
||||
|
||||
/// <summary>
|
||||
/// Altitude of location in meters.
|
||||
/// </summary>
|
||||
/// <value>Unit: meter. Range: <c>-100_000.00 <= X <= 42_849_672.95</c></value>
|
||||
[JsonProperty("altitude")]
|
||||
public double Altitude { get; set; } = altitude;
|
||||
|
||||
/// <summary>
|
||||
/// Size of location in meters.
|
||||
/// </summary>
|
||||
/// <value>Unit: meter. Range: <c>0 <= X <= 90_000_000</c></value>
|
||||
[JsonProperty("size")]
|
||||
public int Size { get; set; } = size;
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal precision of location.
|
||||
/// </summary>
|
||||
/// <value>Unit: meter. Range: <c>0 <= X <= 90_000_000</c></value>
|
||||
[JsonProperty("precision_horz")]
|
||||
public int PrecisionHorizontal { get; set; } = precisionHorizontal;
|
||||
|
||||
/// <summary>
|
||||
/// Vertical precision of location.
|
||||
/// </summary>
|
||||
/// <value>Unit: meter. Range: <c>0 <= X <= 90_000_000</c></value>
|
||||
[JsonProperty("precision_vert")]
|
||||
public int PrecisionVertical { get; set; } = precisionVertical;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Components of a NAPTR record.
|
||||
/// </summary>
|
||||
public class NaPtrData(string flags, ushort order, ushort preference, string regex, string replacement, string service)
|
||||
{
|
||||
/// <summary>
|
||||
/// Flags.
|
||||
/// </summary>
|
||||
[JsonProperty("flags")]
|
||||
public string Flags { get; set; } = flags;
|
||||
|
||||
/// <summary>
|
||||
/// Order.
|
||||
/// </summary>
|
||||
[JsonProperty("order")]
|
||||
public ushort Order { get; set; } = order;
|
||||
|
||||
/// <summary>
|
||||
/// Preference.
|
||||
/// </summary>
|
||||
[JsonProperty("preference")]
|
||||
public ushort Preference { get; set; } = preference;
|
||||
|
||||
/// <summary>
|
||||
/// Service.
|
||||
/// </summary>
|
||||
[JsonProperty("regex")]
|
||||
public string Regex { get; set; } = regex;
|
||||
|
||||
/// <summary>
|
||||
/// Replacement.
|
||||
/// </summary>
|
||||
[JsonProperty("replacement")]
|
||||
public string Replacement { get; set; } = replacement;
|
||||
|
||||
/// <summary>
|
||||
/// Service.
|
||||
/// </summary>
|
||||
[JsonProperty("service")]
|
||||
public string Service { get; set; } = service;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Components of a SMIMEA record.
|
||||
/// </summary>
|
||||
public class SMimeAData(string certificate, byte matchingType, byte selector, byte usage)
|
||||
{
|
||||
/// <summary>
|
||||
/// Certificate.
|
||||
/// </summary>
|
||||
[JsonProperty("certificate")]
|
||||
public string Certificate { get; set; } = certificate;
|
||||
|
||||
/// <summary>
|
||||
/// Matching type.
|
||||
/// </summary>
|
||||
[JsonProperty("matching_type")]
|
||||
public byte MatchingType { get; set; } = matchingType;
|
||||
|
||||
/// <summary>
|
||||
/// Selector.
|
||||
/// </summary>
|
||||
[JsonProperty("selector")]
|
||||
public byte Selector { get; set; } = selector;
|
||||
|
||||
/// <summary>
|
||||
/// Usage.
|
||||
/// </summary>
|
||||
[JsonProperty("usage")]
|
||||
public byte Usage { get; set; } = usage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Components of a SRV record.
|
||||
/// </summary>
|
||||
public class SrvData(ushort port, ushort priority, string target, ushort weight)
|
||||
{
|
||||
/// <summary>
|
||||
/// The port of the service.
|
||||
/// </summary>
|
||||
[JsonProperty("port")]
|
||||
public ushort Port { get; set; } = port;
|
||||
|
||||
/// <summary>
|
||||
/// The priority of the service.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Required for <see cref="DnsRecordType.Mx"/>, <see cref="DnsRecordType.Srv"/> and <see cref="DnsRecordType.Uri"/> records; unused by other record types.
|
||||
/// Records with lower priorities are preferred.
|
||||
/// </remarks>
|
||||
[JsonProperty("priority")]
|
||||
public ushort Priority { get; set; } = priority;
|
||||
|
||||
/// <summary>
|
||||
/// A valid hostname.
|
||||
/// </summary>
|
||||
[JsonProperty("target")]
|
||||
public string Target { get; set; } = target;
|
||||
|
||||
/// <summary>
|
||||
/// The weight of the record.
|
||||
/// </summary>
|
||||
[JsonProperty("weight")]
|
||||
public ushort Weight { get; set; } = weight;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Components of a SSHFP record.
|
||||
/// </summary>
|
||||
public class SshFpData(byte algorithm, string fingerprint, byte type)
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm.
|
||||
/// </summary>
|
||||
[JsonProperty("algorithm")]
|
||||
public byte Algorithm { get; set; } = algorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Fingerprint.
|
||||
/// </summary>
|
||||
[JsonProperty("fingerprint")]
|
||||
public string Fingerprint { get; set; } = fingerprint;
|
||||
|
||||
/// <summary>
|
||||
/// Type.
|
||||
/// </summary>
|
||||
[JsonProperty("type")]
|
||||
public byte Type { get; set; } = type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Components of a SVCB record.
|
||||
/// </summary>
|
||||
public class SvcBData(ushort priority, string target, string value)
|
||||
{
|
||||
/// <summary>
|
||||
/// The priority of the service binding.
|
||||
/// </summary>
|
||||
[JsonProperty("priority")]
|
||||
public ushort Priority { get; set; } = priority;
|
||||
|
||||
/// <summary>
|
||||
/// A valid target.
|
||||
/// </summary>
|
||||
[JsonProperty("target")]
|
||||
public string Target { get; set; } = target;
|
||||
|
||||
/// <summary>
|
||||
/// The value of the service binding.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// e.g. <c>alpn="h3,h2" ipv4hint="127.0.0.1" ipv6hint="::1"</c>
|
||||
/// </remarks>
|
||||
[JsonProperty("value")]
|
||||
public string Value { get; set; } = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Components of a TLSA record.
|
||||
/// </summary>
|
||||
public class TlsAData(string certificate, byte matchingType, byte selector, byte usage)
|
||||
{
|
||||
/// <summary>
|
||||
/// Certificate.
|
||||
/// </summary>
|
||||
[JsonProperty("certificate")]
|
||||
public string Certificate { get; set; } = certificate;
|
||||
|
||||
/// <summary>
|
||||
/// Matching type.
|
||||
/// </summary>
|
||||
[JsonProperty("matching_type")]
|
||||
public byte MatchingType { get; set; } = matchingType;
|
||||
|
||||
/// <summary>
|
||||
/// Selector.
|
||||
/// </summary>
|
||||
[JsonProperty("selector")]
|
||||
public byte Selector { get; set; } = selector;
|
||||
|
||||
/// <summary>
|
||||
/// Usage.
|
||||
/// </summary>
|
||||
[JsonProperty("usage")]
|
||||
public byte Usage { get; set; } = usage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Components of a URI record.
|
||||
/// </summary>
|
||||
public class UriData(string target, ushort weight)
|
||||
{
|
||||
/// <summary>
|
||||
/// A valid target.
|
||||
/// </summary>
|
||||
[JsonProperty("target")]
|
||||
public string Target { get; set; } = target;
|
||||
|
||||
/// <summary>
|
||||
/// The weight of the record.
|
||||
/// </summary>
|
||||
[JsonProperty("weight")]
|
||||
public ushort Weight { get; set; } = weight;
|
||||
}
|
||||
|
||||
#region Enums for data fields
|
||||
|
||||
/// <summary>
|
||||
/// Directions for latitude.
|
||||
/// </summary>
|
||||
public enum LatitudeDirection
|
||||
{
|
||||
/// <summary>
|
||||
/// North.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "N")]
|
||||
North = 1,
|
||||
|
||||
/// <summary>
|
||||
/// South.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "S")]
|
||||
South = 2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Directions for longitude.
|
||||
/// </summary>
|
||||
public enum LongitudeDirection
|
||||
{
|
||||
/// <summary>
|
||||
/// East.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "E")]
|
||||
East = 1,
|
||||
|
||||
/// <summary>
|
||||
/// West.
|
||||
/// </summary>
|
||||
[EnumMember(Value = "W")]
|
||||
West = 2
|
||||
}
|
||||
|
||||
#endregion Enums for data fields
|
||||
|
||||
#endregion Type definitions for data fields
|
||||
|
||||
#region Type definitions for settings fields
|
||||
|
||||
/// <summary>
|
||||
/// Settings for the DNS record.
|
||||
/// </summary>
|
||||
public class CnameSettings(bool flattenCname)
|
||||
{
|
||||
/// <summary>
|
||||
/// If enabled, causes the CNAME record to be resolved externally and the resulting address records (e.g., A and AAAA) to be returned instead of the CNAME record itself.
|
||||
/// This setting has no effect on proxied records, which are always flattened.
|
||||
/// </summary>
|
||||
[JsonProperty("flatten_cname")]
|
||||
public bool FlattenCname { get; set; } = flattenCname;
|
||||
}
|
||||
|
||||
#endregion Type definitions for settings fields
|
||||
}
|
||||
}
|
||||
26
Extensions/Cloudflare.Zones/Models/DnsRecordMeta.cs
Normal file
26
Extensions/Cloudflare.Zones/Models/DnsRecordMeta.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// Extra Cloudflare-specific information about the record.
|
||||
/// </summary>
|
||||
public class DnsRecordMeta
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether the record was automatically added.
|
||||
/// </summary>
|
||||
[JsonProperty("auto_added")]
|
||||
public bool AutoAdded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the record is managed by apps.
|
||||
/// </summary>
|
||||
[JsonProperty("managed_by_apps")]
|
||||
public bool ManagedByApps { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the record is managed by argo tunnel.
|
||||
/// </summary>
|
||||
[JsonProperty("managed_by_argo_tunnel")]
|
||||
public bool ManagedByArgoTunnel { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// The deleted zone.
|
||||
/// The deleted id.
|
||||
/// </summary>
|
||||
public class ZoneIdResponse
|
||||
public class IdResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifier.
|
||||
20
Extensions/Cloudflare.Zones/Models/ImportDnsRecordsResult.cs
Normal file
20
Extensions/Cloudflare.Zones/Models/ImportDnsRecordsResult.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// The DNS records import result.
|
||||
/// </summary>
|
||||
public class ImportDnsRecordsResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of DNS records added.
|
||||
/// </summary>
|
||||
[JsonProperty("recs_added")]
|
||||
public int? RecordsAdded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total number of DNS records parsed.
|
||||
/// </summary>
|
||||
[JsonProperty("total_records_parsed")]
|
||||
public int? TotalRecordsParsed { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
/// The nameserver type.
|
||||
/// </summary>
|
||||
[JsonProperty("type")]
|
||||
public virtual NameserverType Type { get; set; }
|
||||
public NameserverType Type { get; set; }
|
||||
|
||||
// TODO: DEPRECATED? - not available on API request.
|
||||
///// <summary>
|
||||
@@ -17,6 +17,6 @@
|
||||
///// </summary>
|
||||
///// <value>Range: <c>1 <=</c> X <c><= 5</c></value>
|
||||
//[JsonProperty("ns_set")]
|
||||
//public virtual int NameserverSet { get; set; }
|
||||
//public int NameserverSet { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,34 +31,34 @@
|
||||
/// </summary>
|
||||
/// <value>Unit: seconds. Range: <c>86400 <=</c> X <c><= 2419200</c></value>
|
||||
[JsonProperty("expire")]
|
||||
public virtual int Expire { get; set; }
|
||||
public int Expire { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time to live (TTL) for negative caching of records within the zone.
|
||||
/// </summary>
|
||||
/// <value>Unit: seconds. Range: <c>60 <=</c> X <c><= 86400</c></value>
|
||||
[JsonProperty("min_ttl")]
|
||||
public virtual int MinimumTtl { get; set; }
|
||||
public int MinimumTtl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The primary nameserver, which may be used for outbound zone transfers.
|
||||
/// </summary>
|
||||
[JsonProperty("mname", NullValueHandling = NullValueHandling.Include)]
|
||||
public virtual string PrimaryNameserver { get; set; }
|
||||
public string PrimaryNameserver { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Time in seconds after which secondary servers should re-check the SOA record to see if the zone has been updated.
|
||||
/// </summary>
|
||||
/// <value>Unit: seconds. Range: <c>600 <=</c> X <c><= 86400</c></value>
|
||||
[JsonProperty("refresh")]
|
||||
public virtual int Refresh { get; set; }
|
||||
public int Refresh { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Time in seconds after which secondary servers should retry queries after the primary server was unresponsive.
|
||||
/// </summary>
|
||||
/// <value>Unit: seconds. Range: <c>600 <=</c> X <c><= 86400</c></value>
|
||||
[JsonProperty("retry")]
|
||||
public virtual int Retry { get; set; }
|
||||
public int Retry { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The email address of the zone administrator, with the first label representing the local part of the email address.
|
||||
@@ -71,13 +71,13 @@
|
||||
/// test\.user.example.org => test.user@example.org
|
||||
/// </remarks>
|
||||
[JsonProperty("rname", NullValueHandling = NullValueHandling.Include)]
|
||||
public virtual string ZoneAdministrator { get; set; }
|
||||
public string ZoneAdministrator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The time to live (TTL) of the SOA record itself.
|
||||
/// </summary>
|
||||
/// <value>Unit: seconds. Range: <c>300 <=</c> X <c><= 86400</c></value>
|
||||
[JsonProperty("ttl")]
|
||||
public virtual int Ttl { get; set; }
|
||||
public int Ttl { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// Batch of DNS Record API calls to be executed together.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Execution order: Delete, Update, Overwrite, Create
|
||||
/// </remarks>
|
||||
public class BatchDnsRecordsRequest(string zoneId)
|
||||
{
|
||||
/// <summary>
|
||||
/// The zone identifier.
|
||||
/// </summary>
|
||||
public string ZoneId { get; set; } = zoneId;
|
||||
|
||||
/// <summary>
|
||||
/// The DNS record identifiers to delete.
|
||||
/// </summary>
|
||||
public IList<string> DnsRecordIdsToDelete { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// The DNS records to update.
|
||||
/// </summary>
|
||||
public IList<UpdateDnsRecordRequest> DnsRecordsToUpdate { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// The DNS records to overwrite.
|
||||
/// </summary>
|
||||
public IList<OverwriteDnsRecordRequest> DnsRecordsToOverwrite { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// The DNS records to create.
|
||||
/// </summary>
|
||||
public IList<CreateDnsRecordRequest> DnsRecordsToCreate { get; set; } = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// Request to create a new DNS record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initializes a new instance of the <see cref="CreateDnsRecordRequest"/> class.
|
||||
/// </remarks>
|
||||
/// <param name="zoneId">The zone identifier.</param>
|
||||
/// <param name="name">DNS record name (or @ for the zone apex).</param>
|
||||
/// <param name="type">Record type.</param>
|
||||
public class CreateDnsRecordRequest(string zoneId, string name, DnsRecordType type)
|
||||
{
|
||||
/// <summary>
|
||||
/// The zone identifier.
|
||||
/// </summary>
|
||||
public string ZoneId { get; set; } = zoneId;
|
||||
|
||||
/// <summary>
|
||||
/// Comments or notes about the DNS record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field has no effect on DNS responses.
|
||||
/// </remarks>
|
||||
public string? Comment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DNS record name (or @ for the zone apex) in Punycode.
|
||||
/// </summary>
|
||||
public string Name { get; set; } = name;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the record is receiving the performance and security benefits of Cloudflare.
|
||||
/// </summary>
|
||||
public bool Proxied { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Settings for the DNS record.
|
||||
/// </summary>
|
||||
public object? Settings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Custom tags for the DNS record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field has no effect on DNS responses.
|
||||
/// </remarks>
|
||||
public IList<string>? Tags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Time To Live (TTL) of the DNS record in seconds.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Setting to <c>1</c> means 'automatic'.
|
||||
/// Value must be between <c>60</c> and <c>86400</c>, <em>with the minimum reduced to 30 for Enterprise zones</em>.
|
||||
/// </remarks>
|
||||
public int? Ttl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Components of a record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <strong>Caution:</strong> This field has priority over the <see cref="Content"/> field.
|
||||
/// </remarks>
|
||||
public object? Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A valid content.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <strong>Caution:</strong> This field has no effect for record types with specific <see cref="Data"/> values.
|
||||
/// </remarks>
|
||||
public string? Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A priority.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Required for <see cref="DnsRecordType.Mx"/>, <see cref="DnsRecordType.Srv"/> and <see cref="DnsRecordType.Uri"/> records; unused by other record types.
|
||||
/// Records with lower priorities are preferred.
|
||||
/// </remarks>
|
||||
public ushort? Priority { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Record type.
|
||||
/// </summary>
|
||||
public DnsRecordType Type { get; set; } = type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// Request to import DNS records from a BIND configuration file.
|
||||
/// </summary>
|
||||
public class ImportDnsRecordsRequest(string zoneId, string file)
|
||||
{
|
||||
/// <summary>
|
||||
/// The zone identifier.
|
||||
/// </summary>
|
||||
public string ZoneId { get; set; } = zoneId;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not proxiable records should receive the performance and security benefits of Cloudflare.
|
||||
/// </summary>
|
||||
public bool? Proxied { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// BIND config to import.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the property is an absolute path, the content of that file will be used as the BIND configuration.
|
||||
/// <br />
|
||||
/// Otherwise the property will be treated as BIND configuration itself.
|
||||
/// </remarks>
|
||||
public string File { get; set; } = file;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// Request to overwrite a DNS record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initializes a new instance of the <see cref="OverwriteDnsRecordRequest"/> class.
|
||||
/// </remarks>
|
||||
/// <param name="id">The DNS record identifier.</param>
|
||||
/// <param name="zoneId">The zone identifier.</param>
|
||||
/// <param name="name">DNS record name (or @ for the zone apex).</param>
|
||||
/// <param name="type">Record type.</param>
|
||||
public class OverwriteDnsRecordRequest(string id, string zoneId, string name, DnsRecordType type) : CreateDnsRecordRequest(zoneId, name, type)
|
||||
{
|
||||
/// <summary>
|
||||
/// The DNS record identifier.
|
||||
/// </summary>
|
||||
public string Id { get; set; } = id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
/// <summary>
|
||||
/// Request to update a DNS record.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initializes a new instance of the <see cref="UpdateDnsRecordRequest"/> class.
|
||||
/// </remarks>
|
||||
/// <param name="id">The DNS record identifier.</param>
|
||||
/// <param name="zoneId">The zone identifier.</param>
|
||||
/// <param name="name">DNS record name (or @ for the zone apex).</param>
|
||||
/// <param name="type">Record type.</param>
|
||||
public class UpdateDnsRecordRequest(string id, string zoneId, string name, DnsRecordType type) : CreateDnsRecordRequest(zoneId, name, type)
|
||||
{
|
||||
/// <summary>
|
||||
/// The DNS record identifier.
|
||||
/// </summary>
|
||||
public string Id { get; set; } = id;
|
||||
}
|
||||
}
|
||||
@@ -21,14 +21,14 @@ namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="zoneId">The zone ID.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<ZoneIdResponse>> PurgeCachedContent(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
|
||||
public static Task<CloudflareResponse<IdResponse>> PurgeCachedContent(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
var req = new InternalPurgeCacheRequest
|
||||
{
|
||||
PurgeEverything = true
|
||||
};
|
||||
return client.PostAsync<ZoneIdResponse, InternalPurgeCacheRequest>($"zones/{zoneId}/purge_cache", req, cancellationToken: cancellationToken);
|
||||
return client.PostAsync<IdResponse, InternalPurgeCacheRequest>($"zones/{zoneId}/purge_cache", req, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -56,7 +56,7 @@ namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
/// <param name="zoneId">The zone ID.</param>
|
||||
/// <param name="urls">List of URLs to purge.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<ZoneIdResponse>> PurgeCachedContentByUrl(this ICloudflareClient client, string zoneId, IReadOnlyList<ZonePurgeCachedUrlRequest> urls, CancellationToken cancellationToken = default)
|
||||
public static Task<CloudflareResponse<IdResponse>> PurgeCachedContentByUrl(this ICloudflareClient client, string zoneId, IReadOnlyList<ZonePurgeCachedUrlRequest> urls, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
req.Urls = urls.Where(u => !string.IsNullOrWhiteSpace(u.Url)).Select(u => u.Url).ToList();
|
||||
}
|
||||
|
||||
return client.PostAsync<ZoneIdResponse, InternalPurgeCacheRequest>($"zones/{zoneId}/purge_cache", req, cancellationToken: cancellationToken);
|
||||
return client.PostAsync<IdResponse, InternalPurgeCacheRequest>($"zones/{zoneId}/purge_cache", req, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -101,7 +101,7 @@ namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
/// <param name="zoneId">The zone ID.</param>
|
||||
/// <param name="tags">List of tags to purge.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<ZoneIdResponse>> PurgeCachedContentByTag(this ICloudflareClient client, string zoneId, IReadOnlyList<string> tags, CancellationToken cancellationToken = default)
|
||||
public static Task<CloudflareResponse<IdResponse>> PurgeCachedContentByTag(this ICloudflareClient client, string zoneId, IReadOnlyList<string> tags, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
Tags = tags.Where(t => !string.IsNullOrWhiteSpace(t)).ToList()
|
||||
};
|
||||
return client.PostAsync<ZoneIdResponse, InternalPurgeCacheRequest>($"zones/{zoneId}/purge_cache", req, cancellationToken: cancellationToken);
|
||||
return client.PostAsync<IdResponse, InternalPurgeCacheRequest>($"zones/{zoneId}/purge_cache", req, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -135,7 +135,7 @@ namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
/// <param name="zoneId">The zone ID.</param>
|
||||
/// <param name="hosts">List of hostnames to purge.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<ZoneIdResponse>> PurgeCachedContentByHost(this ICloudflareClient client, string zoneId, IReadOnlyList<string> hosts, CancellationToken cancellationToken = default)
|
||||
public static Task<CloudflareResponse<IdResponse>> PurgeCachedContentByHost(this ICloudflareClient client, string zoneId, IReadOnlyList<string> hosts, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
Hostnames = hosts.Where(h => !string.IsNullOrWhiteSpace(h)).ToList()
|
||||
};
|
||||
return client.PostAsync<ZoneIdResponse, InternalPurgeCacheRequest>($"zones/{zoneId}/purge_cache", req, cancellationToken: cancellationToken);
|
||||
return client.PostAsync<IdResponse, InternalPurgeCacheRequest>($"zones/{zoneId}/purge_cache", req, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -169,7 +169,7 @@ namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
/// <param name="zoneId">The zone ID.</param>
|
||||
/// <param name="prefixes">List of prefixes to purge.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<ZoneIdResponse>> PurgeCachedContentByPrefix(this ICloudflareClient client, string zoneId, IReadOnlyList<string> prefixes, CancellationToken cancellationToken = default)
|
||||
public static Task<CloudflareResponse<IdResponse>> PurgeCachedContentByPrefix(this ICloudflareClient client, string zoneId, IReadOnlyList<string> prefixes, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
{
|
||||
Prefixes = prefixes.Where(h => !string.IsNullOrWhiteSpace(h)).ToList()
|
||||
};
|
||||
return client.PostAsync<ZoneIdResponse, InternalPurgeCacheRequest>($"zones/{zoneId}/purge_cache", req, cancellationToken: cancellationToken);
|
||||
return client.PostAsync<IdResponse, InternalPurgeCacheRequest>($"zones/{zoneId}/purge_cache", req, cancellationToken: cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,10 +69,10 @@ namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="zoneId">The zone ID.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<ZoneIdResponse>> DeleteZone(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
|
||||
public static Task<CloudflareResponse<IdResponse>> DeleteZone(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
return client.DeleteAsync<ZoneIdResponse>($"zones/{zoneId}", cancellationToken: cancellationToken);
|
||||
return client.DeleteAsync<IdResponse>($"zones/{zoneId}", cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -116,10 +116,10 @@ namespace AMWD.Net.Api.Cloudflare.Zones
|
||||
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
|
||||
/// <param name="zoneId">The zone ID.</param>
|
||||
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
|
||||
public static Task<CloudflareResponse<ZoneIdResponse>> RerunActivationCheck(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
|
||||
public static Task<CloudflareResponse<IdResponse>> RerunActivationCheck(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
zoneId.ValidateCloudflareId();
|
||||
return client.PutAsync<ZoneIdResponse, object>($"zones/{zoneId}/activation_check", null, cancellationToken);
|
||||
return client.PutAsync<IdResponse, object>($"zones/{zoneId}/activation_check", null, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user