diff --git a/src/Enclave.Sdk/Clients/AuthorityClient.cs b/src/Enclave.Sdk/Clients/AuthorityClient.cs deleted file mode 100644 index ec19132..0000000 --- a/src/Enclave.Sdk/Clients/AuthorityClient.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Enclave.Sdk.Api.Clients.Interfaces; - -namespace Enclave.Sdk.Api.Clients; - -internal class AuthorityClient : ClientBase, IAuthorityClient -{ - private readonly string _orgRoute; - - public AuthorityClient(HttpClient httpClient, string orgRoute) - : base(httpClient) - { - _orgRoute = orgRoute; - } -} diff --git a/src/Enclave.Sdk/Clients/ClientBase.cs b/src/Enclave.Sdk/Clients/ClientBase.cs index 64f5a21..3fafe03 100644 --- a/src/Enclave.Sdk/Clients/ClientBase.cs +++ b/src/Enclave.Sdk/Clients/ClientBase.cs @@ -32,7 +32,7 @@ protected ClientBase(HttpClient httpClient) /// the object to encode. /// String content of object. /// throws if data provided is null. - protected StringContent CreateJsonContent(TModel data) + protected static StringContent CreateJsonContent(TModel data) { if (data is null) { @@ -51,7 +51,7 @@ protected StringContent CreateJsonContent(TModel data) /// the object type to deserialise to. /// httpContent from the API call. /// the object of type specified. - protected async Task DeserialiseAsync(HttpContent httpContent) + protected static async Task DeserialiseAsync(HttpContent httpContent) { if (httpContent is null) { diff --git a/src/Enclave.Sdk/Clients/DNSClient.cs b/src/Enclave.Sdk/Clients/DNSClient.cs index 7f31bda..2c0508d 100644 --- a/src/Enclave.Sdk/Clients/DNSClient.cs +++ b/src/Enclave.Sdk/Clients/DNSClient.cs @@ -35,11 +35,11 @@ public async Task GetPropertiesSummaryAsync() } /// - public async Task> GetZonesAsync(int? pageNumber = null, int? perPage = null) + public async Task> GetZonesAsync(int? pageNumber = null, int? perPage = null) { var queryString = BuildQueryString(null, null, pageNumber, perPage); - var model = await HttpClient.GetFromJsonAsync>($"{_orgRoute}/dns/zones?{queryString}"); + var model = await HttpClient.GetFromJsonAsync>($"{_orgRoute}/dns/zones?{queryString}"); EnsureNotNull(model); @@ -47,7 +47,7 @@ public async Task> GetZonesAsync(int? pageN } /// - public async Task CreateZoneAsync(DnsZoneCreate createModel) + public async Task CreateZoneAsync(DnsZoneCreate createModel) { if (createModel is null) { @@ -56,7 +56,7 @@ public async Task CreateZoneAsync(DnsZoneCreate createModel) var result = await HttpClient.PostAsJsonAsync($"{_orgRoute}/dns/zones", createModel, Constants.JsonSerializerOptions); - var model = await DeserialiseAsync(result.Content); + var model = await DeserialiseAsync(result.Content); EnsureNotNull(model); @@ -64,9 +64,9 @@ public async Task CreateZoneAsync(DnsZoneCreate createModel) } /// - public async Task GetZoneAsync(DnsZoneId dnsZoneId) + public async Task GetZoneAsync(DnsZoneId dnsZoneId) { - var model = await HttpClient.GetFromJsonAsync($"{_orgRoute}/dns/zones/{dnsZoneId}", Constants.JsonSerializerOptions); + var model = await HttpClient.GetFromJsonAsync($"{_orgRoute}/dns/zones/{dnsZoneId}", Constants.JsonSerializerOptions); EnsureNotNull(model); @@ -74,7 +74,7 @@ public async Task GetZoneAsync(DnsZoneId dnsZoneId) } /// - public async Task UpdateZoneAsync(DnsZoneId dnsZoneId, PatchBuilder builder) + public async Task UpdateZoneAsync(DnsZoneId dnsZoneId, PatchBuilder builder) { if (builder is null) { @@ -86,7 +86,7 @@ public async Task UpdateZoneAsync(DnsZoneId dnsZoneId, PatchBuilder result.EnsureSuccessStatusCode(); - var model = await DeserialiseAsync(result.Content); + var model = await DeserialiseAsync(result.Content); EnsureNotNull(model); @@ -94,13 +94,13 @@ public async Task UpdateZoneAsync(DnsZoneId dnsZoneId, PatchBuilder } /// - public async Task DeleteZoneAsync(DnsZoneId dnsZoneId) + public async Task DeleteZoneAsync(DnsZoneId dnsZoneId) { var result = await HttpClient.DeleteAsync($"{_orgRoute}/dns/zones/{dnsZoneId}"); result.EnsureSuccessStatusCode(); - var model = await DeserialiseAsync(result.Content); + var model = await DeserialiseAsync(result.Content); EnsureNotNull(model); @@ -108,7 +108,7 @@ public async Task DeleteZoneAsync(DnsZoneId dnsZoneId) } /// - public async Task> GetRecordsAsync( + public async Task> GetRecordsAsync( DnsZoneId? dnsZoneId = null, string? hostname = null, int? pageNumber = null, @@ -116,7 +116,7 @@ public async Task> GetRecordsAsync( { var queryString = BuildQueryString(dnsZoneId, hostname, pageNumber, perPage); - var model = await HttpClient.GetFromJsonAsync>($"{_orgRoute}/dns/records?{queryString}"); + var model = await HttpClient.GetFromJsonAsync>($"{_orgRoute}/dns/records?{queryString}"); EnsureNotNull(model); @@ -124,7 +124,7 @@ public async Task> GetRecordsAsync( } /// - public async Task CreateRecordAsync(DnsRecordCreate createModel) + public async Task CreateRecordAsync(DnsRecordCreate createModel) { if (createModel is null) { @@ -133,7 +133,7 @@ public async Task CreateRecordAsync(DnsRecordCreate createModel) var result = await HttpClient.PostAsJsonAsync($"{_orgRoute}/dns/records", createModel, Constants.JsonSerializerOptions); - var model = await DeserialiseAsync(result.Content); + var model = await DeserialiseAsync(result.Content); EnsureNotNull(model); @@ -178,9 +178,9 @@ public async Task DeleteRecordsAsync(IEnumerable records) } /// - public async Task GetRecordAsync(DnsRecordId dnsRecordId) + public async Task GetRecordAsync(DnsRecordId dnsRecordId) { - var model = await HttpClient.GetFromJsonAsync($"{_orgRoute}/dns/records/{dnsRecordId}", Constants.JsonSerializerOptions); + var model = await HttpClient.GetFromJsonAsync($"{_orgRoute}/dns/records/{dnsRecordId}", Constants.JsonSerializerOptions); EnsureNotNull(model); @@ -188,7 +188,7 @@ public async Task GetRecordAsync(DnsRecordId dnsRecordId) } /// - public async Task UpdateRecordAsync(DnsRecordId dnsRecordId, PatchBuilder builder) + public async Task UpdateRecordAsync(DnsRecordId dnsRecordId, PatchBuilder builder) { if (builder is null) { @@ -200,7 +200,7 @@ public async Task UpdateRecordAsync(DnsRecordId dnsRecordId, Patc result.EnsureSuccessStatusCode(); - var model = await DeserialiseAsync(result.Content); + var model = await DeserialiseAsync(result.Content); EnsureNotNull(model); @@ -208,13 +208,13 @@ public async Task UpdateRecordAsync(DnsRecordId dnsRecordId, Patc } /// - public async Task DeleteRecordAsync(DnsRecordId dnsRecordId) + public async Task DeleteRecordAsync(DnsRecordId dnsRecordId) { var result = await HttpClient.DeleteAsync($"{_orgRoute}/dns/records/{dnsRecordId}"); result.EnsureSuccessStatusCode(); - var model = await DeserialiseAsync(result.Content); + var model = await DeserialiseAsync(result.Content); EnsureNotNull(model); diff --git a/src/Enclave.Sdk/Clients/EnrolledSystemsClient.cs b/src/Enclave.Sdk/Clients/EnrolledSystemsClient.cs new file mode 100644 index 0000000..0ade948 --- /dev/null +++ b/src/Enclave.Sdk/Clients/EnrolledSystemsClient.cs @@ -0,0 +1,245 @@ +using System.Collections.Generic; +using System.Net.Http.Json; +using System.Web; +using Enclave.Sdk.Api.Clients.Interfaces; +using Enclave.Sdk.Api.Data; +using Enclave.Sdk.Api.Data.EnrolledSystems; +using Enclave.Sdk.Api.Data.EnrolledSystems.Enum; +using Enclave.Sdk.Api.Data.Pagination; +using Enclave.Sdk.Api.Data.PatchModel; + +namespace Enclave.Sdk.Api.Clients; + +/// +internal class EnrolledSystemsClient : ClientBase, IEnrolledSystemsClient +{ + private readonly string _orgRoute; + + /// + /// Consutructor which will be called by when it's created. + /// + /// an instance of httpClient with a baseURL referencing the API. + /// The organisation API route. + public EnrolledSystemsClient(HttpClient httpClient, string orgRoute) + : base(httpClient) + { + _orgRoute = orgRoute; + } + + /// + public async Task> GetSystemsAsync( + int? enrolmentKeyId = null, + string? searchTerm = null, + bool? includeDisabled = null, + SystemQuerySortMode? sortOrder = null, + string? dnsName = null, + int? pageNumber = null, + int? perPage = null) + { + var queryString = BuildQueryString(enrolmentKeyId, searchTerm, includeDisabled, sortOrder, dnsName, pageNumber, perPage); + + var model = await HttpClient.GetFromJsonAsync>($"{_orgRoute}/systems?{queryString}", Constants.JsonSerializerOptions); + + EnsureNotNull(model); + + return model; + } + + /// + public async Task RevokeSystemsAsync(params SystemId[] systemIds) + { + using var content = CreateJsonContent(new + { + systemIds = systemIds, + }); + + using var request = new HttpRequestMessage + { + Content = content, + Method = HttpMethod.Delete, + RequestUri = new Uri($"{HttpClient.BaseAddress}{_orgRoute}/systems"), + }; + + var result = await HttpClient.SendAsync(request); + + result.EnsureSuccessStatusCode(); + + var model = await DeserialiseAsync(result.Content); + + EnsureNotNull(model); + + return model.SystemsRevoked; + } + + /// + public async Task RevokeSystemsAsync(IEnumerable systemIds) + { + return await RevokeSystemsAsync(systemIds.ToArray()); + } + + /// + public async Task GetAsync(SystemId systemId) + { + var model = await HttpClient.GetFromJsonAsync($"{_orgRoute}/systems/{systemId}", Constants.JsonSerializerOptions); + + EnsureNotNull(model); + + return model; + } + + /// + public async Task UpdateAsync(SystemId systemId, PatchBuilder builder) + { + if (builder is null) + { + throw new ArgumentNullException(nameof(builder)); + } + + using var encoded = CreateJsonContent(builder.Send()); + var result = await HttpClient.PatchAsync($"{_orgRoute}/systems/{systemId}", encoded); + + result.EnsureSuccessStatusCode(); + + var model = await DeserialiseAsync(result.Content); + + EnsureNotNull(model); + + return model; + } + + /// + public async Task RevokeAsync(SystemId systemId) + { + var result = await HttpClient.DeleteAsync($"{_orgRoute}/systems/{systemId}"); + + result.EnsureSuccessStatusCode(); + + var model = await DeserialiseAsync(result.Content); + + EnsureNotNull(model); + + return model; + } + + /// + public async Task EnableAsync(SystemId systemId) + { + var result = await HttpClient.PutAsync($"{_orgRoute}/systems/{systemId}/enable", null); + + var model = await DeserialiseAsync(result.Content); + + EnsureNotNull(model); + + return model; + } + + /// + public async Task DisableAsync(SystemId systemId) + { + var result = await HttpClient.PutAsync($"{_orgRoute}/systems/{systemId}/disable", null); + + var model = await DeserialiseAsync(result.Content); + + EnsureNotNull(model); + + return model; + } + + /// + public async Task BulkEnableAsync(params SystemId[] systemIds) + { + var requestModel = new + { + systemIds = systemIds, + }; + + var result = await HttpClient.PutAsJsonAsync($"{_orgRoute}/systems/enable", requestModel, Constants.JsonSerializerOptions); + + result.EnsureSuccessStatusCode(); + + var model = await DeserialiseAsync(result.Content); + + EnsureNotNull(model); + + return model.SystemsUpdated; + } + + /// + public async Task BulkEnableAsync(IEnumerable systemIds) + { + return await BulkEnableAsync(systemIds.ToArray()); + } + + /// + public async Task BulkDisableAsync(params SystemId[] systemIds) + { + var requestModel = new + { + systemIds = systemIds, + }; + + var result = await HttpClient.PutAsJsonAsync($"{_orgRoute}/systems/disable", requestModel, Constants.JsonSerializerOptions); + + result.EnsureSuccessStatusCode(); + + var model = await DeserialiseAsync(result.Content); + + EnsureNotNull(model); + + return model.SystemsUpdated; + } + + /// + public async Task BulkDisableAsync(IEnumerable systemIds) + { + return await BulkDisableAsync(systemIds.ToArray()); + } + + private static string? BuildQueryString( + int? enrolmentKeyId = null, + string? searchTerm = null, + bool? includeDisabled = null, + SystemQuerySortMode? sortOrder = null, + string? dnsName = null, + int? pageNumber = null, + int? perPage = null) + { + var queryString = HttpUtility.ParseQueryString(string.Empty); + if (enrolmentKeyId is not null) + { + queryString.Add("enrolment_key", enrolmentKeyId.ToString()); + } + + if (searchTerm is not null) + { + queryString.Add("search", searchTerm); + } + + if (includeDisabled is not null) + { + queryString.Add("include_disabled", includeDisabled.ToString()); + } + + if (sortOrder is not null) + { + queryString.Add("sort", sortOrder.ToString()); + } + + if (dnsName is not null) + { + queryString.Add("dns", dnsName); + } + + if (pageNumber is not null) + { + queryString.Add("page", pageNumber.ToString()); + } + + if (perPage is not null) + { + queryString.Add("per_page", perPage.ToString()); + } + + return queryString.ToString(); + } +} diff --git a/src/Enclave.Sdk/Clients/EnrolmentKeysClient.cs b/src/Enclave.Sdk/Clients/EnrolmentKeysClient.cs index 2a93a19..84a3f8d 100644 --- a/src/Enclave.Sdk/Clients/EnrolmentKeysClient.cs +++ b/src/Enclave.Sdk/Clients/EnrolmentKeysClient.cs @@ -26,7 +26,7 @@ public EnrolmentKeysClient(HttpClient httpClient, string orgRoute) } /// - public async Task> GetEnrolmentKeysAsync( + public async Task> GetEnrolmentKeysAsync( string? searchTerm = null, bool? includeDisabled = null, EnrolmentKeySortOrder? sortOrder = null, @@ -35,7 +35,7 @@ public async Task> GetEnrolmentKeysAs { var queryString = BuildQueryString(searchTerm, includeDisabled, sortOrder, pageNumber, perPage); - var model = await HttpClient.GetFromJsonAsync>($"{_orgRoute}/enrolment-keys?{queryString}"); + var model = await HttpClient.GetFromJsonAsync>($"{_orgRoute}/enrolment-keys?{queryString}"); EnsureNotNull(model); @@ -43,7 +43,7 @@ public async Task> GetEnrolmentKeysAs } /// - public async Task CreateAsync(EnrolmentKeyCreate createModel) + public async Task CreateAsync(EnrolmentKeyCreate createModel) { if (createModel is null) { @@ -52,7 +52,7 @@ public async Task CreateAsync(EnrolmentKeyCreate createModel) var result = await HttpClient.PostAsJsonAsync($"{_orgRoute}/enrolment-keys", createModel, Constants.JsonSerializerOptions); - var model = await DeserialiseAsync(result.Content); + var model = await DeserialiseAsync(result.Content); EnsureNotNull(model); @@ -60,9 +60,9 @@ public async Task CreateAsync(EnrolmentKeyCreate createModel) } /// - public async Task GetAsync(EnrolmentKeyId enrolmentKeyId) + public async Task GetAsync(EnrolmentKeyId enrolmentKeyId) { - var model = await HttpClient.GetFromJsonAsync($"{_orgRoute}/enrolment-keys/{enrolmentKeyId}", Constants.JsonSerializerOptions); + var model = await HttpClient.GetFromJsonAsync($"{_orgRoute}/enrolment-keys/{enrolmentKeyId}", Constants.JsonSerializerOptions); EnsureNotNull(model); @@ -70,7 +70,7 @@ public async Task GetAsync(EnrolmentKeyId enrolmentKeyId) } /// - public async Task UpdateAsync(EnrolmentKeyId enrolmentKeyId, PatchBuilder builder) + public async Task UpdateAsync(EnrolmentKeyId enrolmentKeyId, PatchBuilder builder) { if (builder is null) { @@ -82,7 +82,7 @@ public async Task UpdateAsync(EnrolmentKeyId enrolmentKeyId, P result.EnsureSuccessStatusCode(); - var model = await DeserialiseAsync(result.Content); + var model = await DeserialiseAsync(result.Content); EnsureNotNull(model); @@ -90,11 +90,11 @@ public async Task UpdateAsync(EnrolmentKeyId enrolmentKeyId, P } /// - public async Task EnableAsync(EnrolmentKeyId enrolmentKeyId) + public async Task EnableAsync(EnrolmentKeyId enrolmentKeyId) { var result = await HttpClient.PutAsync($"{_orgRoute}/enrolment-keys/{enrolmentKeyId}/enable", null); - var model = await DeserialiseAsync(result.Content); + var model = await DeserialiseAsync(result.Content); EnsureNotNull(model); @@ -102,11 +102,11 @@ public async Task EnableAsync(EnrolmentKeyId enrolmentKeyId) } /// - public async Task DisableAsync(EnrolmentKeyId enrolmentKeyId) + public async Task DisableAsync(EnrolmentKeyId enrolmentKeyId) { var result = await HttpClient.PutAsync($"{_orgRoute}/enrolment-keys/{enrolmentKeyId}/disable", null); - var model = await DeserialiseAsync(result.Content); + var model = await DeserialiseAsync(result.Content); EnsureNotNull(model); diff --git a/src/Enclave.Sdk/Clients/Interfaces/IAuthorityClient.cs b/src/Enclave.Sdk/Clients/Interfaces/IAuthorityClient.cs deleted file mode 100644 index 49b89d6..0000000 --- a/src/Enclave.Sdk/Clients/Interfaces/IAuthorityClient.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Enclave.Sdk.Api.Clients.Interfaces; - -public interface IAuthorityClient -{ -} \ No newline at end of file diff --git a/src/Enclave.Sdk/Clients/Interfaces/IDnsClient.cs b/src/Enclave.Sdk/Clients/Interfaces/IDnsClient.cs index 401ac21..ddedbcc 100644 --- a/src/Enclave.Sdk/Clients/Interfaces/IDnsClient.cs +++ b/src/Enclave.Sdk/Clients/Interfaces/IDnsClient.cs @@ -22,21 +22,21 @@ public interface IDnsClient /// Which page number do you want to return. /// How many items per page. /// A paginated response model with links to get the previous, next, first and last pages. - Task> GetZonesAsync(int? pageNumber = null, int? perPage = null); + Task> GetZonesAsync(int? pageNumber = null, int? perPage = null); /// /// Creates a DNS Zone using a Model. /// /// The model needed to create a DNS Zone. - /// The created DNS Zone as a . - Task CreateZoneAsync(DnsZoneCreate createModel); + /// The created DNS Zone as a . + Task CreateZoneAsync(DnsZoneCreate createModel); /// /// Gets the details of a specific DNS Zone. /// /// The DNS Zone ID that you want to get. /// A full DNS Zone object. - Task GetZoneAsync(DnsZoneId dnsZoneId); + Task GetZoneAsync(DnsZoneId dnsZoneId); /// /// Patch request to update a DNS Zone. @@ -44,14 +44,14 @@ public interface IDnsClient /// The DNS Zone ID that you want to update. /// An instance of used to setup our patch request. /// A full DNS Zone object. - Task UpdateZoneAsync(DnsZoneId dnsZoneId, PatchBuilder builder); + Task UpdateZoneAsync(DnsZoneId dnsZoneId, PatchBuilder builder); /// /// Delete a DNS Zone and it's associated record. This is irriversable. /// /// The DNS Zone ID that you want to update. /// The deleted DNS Zone object. - Task DeleteZoneAsync(DnsZoneId dnsZoneId); + Task DeleteZoneAsync(DnsZoneId dnsZoneId); /// /// Gets a paginated list of DNS records. @@ -61,7 +61,7 @@ public interface IDnsClient /// Which page number do you want to return. /// How many items per page. /// A paginated response model with links to get the previous, next, first and last pages. - Task> GetRecordsAsync( + Task> GetRecordsAsync( DnsZoneId? dnsZoneId = null, string? hostname = null, int? pageNumber = null, @@ -70,9 +70,9 @@ Task> GetRecordsAsync( /// /// Create a DNS Record using a model. /// - /// The model needed to create a DNS Record + /// The model needed to create a DNS Record. /// The created DNS Record as . - Task CreateRecordAsync(DnsRecordCreate createModel); + Task CreateRecordAsync(DnsRecordCreate createModel); /// /// Delete multiple DNS Records. @@ -92,8 +92,8 @@ Task> GetRecordsAsync( /// Get a detailed DNS Record. /// /// The id of the DNS Record you want to get. - /// A detailed DNS Record object - Task GetRecordAsync(DnsRecordId dnsRecordId); + /// A detailed DNS Record object. + Task GetRecordAsync(DnsRecordId dnsRecordId); /// /// Patch request to update a DNS Record. @@ -101,12 +101,12 @@ Task> GetRecordsAsync( /// The DNS Record ID that you want to update. /// An instance of used to setup our patch request. /// A full DNS Record object. - Task UpdateRecordAsync(DnsRecordId dnsRecordId, PatchBuilder builder); + Task UpdateRecordAsync(DnsRecordId dnsRecordId, PatchBuilder builder); /// /// Delete a single DNS Record. /// /// The DNS Record ID that you want to delete. /// The deleted DNS Record object. - Task DeleteRecordAsync(DnsRecordId dnsRecordId); + Task DeleteRecordAsync(DnsRecordId dnsRecordId); } \ No newline at end of file diff --git a/src/Enclave.Sdk/Clients/Interfaces/IEnrolledSystemsClient.cs b/src/Enclave.Sdk/Clients/Interfaces/IEnrolledSystemsClient.cs new file mode 100644 index 0000000..d4547a5 --- /dev/null +++ b/src/Enclave.Sdk/Clients/Interfaces/IEnrolledSystemsClient.cs @@ -0,0 +1,111 @@ +using Enclave.Sdk.Api.Data; +using Enclave.Sdk.Api.Data.EnrolledSystems; +using Enclave.Sdk.Api.Data.EnrolledSystems.Enum; +using Enclave.Sdk.Api.Data.Pagination; +using Enclave.Sdk.Api.Data.PatchModel; + +namespace Enclave.Sdk.Api.Clients.Interfaces; + +/// +/// Provides operations to get, create, and manipulate Enrolled Systems. +/// +public interface IEnrolledSystemsClient +{ + /// + /// Gets a paginated list of Systems which can be searched and iterated upon. + /// + /// The Enrolment Key Id which the systems are associated to. + /// Search for systems with a partial match on description and system ID. + /// Should include disabled Systems. + /// Sort order for the pagination. + /// Searches for systems that will answer to the specified DNS name. + /// Which page number do you want to return. + /// How many per page. + /// A paginated response model with links to get the previous, next, first and last pages. + Task> GetSystemsAsync( + int? enrolmentKeyId = null, + string? searchTerm = null, + bool? includeDisabled = null, + SystemQuerySortMode? sortOrder = null, + string? dnsName = null, + int? pageNumber = null, + int? perPage = null); + + /// + /// Permanetly revoke multiple systems. + /// + /// The System Ids to revoke. + /// The number of systems revoked. + Task RevokeSystemsAsync(params SystemId[] systemIds); + + /// + /// Permanetly revoke multiple systems. + /// + /// The System Ids to revoke. + /// The number of systems revoked. + Task RevokeSystemsAsync(IEnumerable systemIds); + + /// + /// Retrieve a Detailed System model. + /// + /// The SystemId to Get. + /// A Full System Model. + Task GetAsync(SystemId systemId); + + /// + /// Update an Enrolled System. + /// + /// The Id of the Enrolled System to update. + /// An instance of used to setup our patch request. + /// An Enrolled System. + Task UpdateAsync(SystemId systemId, PatchBuilder builder); + + /// + /// Revoke a system permanetly. + /// + /// The id of the Enrolled System to revoke. + /// The revoked Enrolled System. + Task RevokeAsync(SystemId systemId); + + /// + /// Enable an Enrolled System. + /// + /// The Id of the Enrolled System to enable. + /// A detailed Enrolment Key. + Task EnableAsync(SystemId systemId); + + /// + /// Disable an Enrolled System. + /// + /// The Id of the Enrolled System to disable. + /// A detailed Enrolment Key. + Task DisableAsync(SystemId systemId); + + /// + /// Bulk enable mutliple Enrolled System. + /// + /// An array of Enrolled System Ids to enable. + /// The number of keys modified. + Task BulkEnableAsync(params SystemId[] systemIds); + + /// + /// Bulk enable mutliple Enrolled System. + /// + /// An array of Enrolled System Ids to enable. + /// The number of keys modified. + Task BulkEnableAsync(IEnumerable systemIds); + + /// + /// Bulk disable mutliple Enrolled System. + /// + /// An array of Enrolled System Ids to disable. + /// The number of keys modified. + Task BulkDisableAsync(params SystemId[] systemIds); + + /// + /// Bulk disable mutliple Enrolled System. + /// + /// An array of Enrolled System Ids to disable. + /// The number of keys modified. + Task BulkDisableAsync(IEnumerable systemIds); +} \ No newline at end of file diff --git a/src/Enclave.Sdk/Clients/Interfaces/IEnrolmentKeysClient.cs b/src/Enclave.Sdk/Clients/Interfaces/IEnrolmentKeysClient.cs index f1f0f68..43a11ab 100644 --- a/src/Enclave.Sdk/Clients/Interfaces/IEnrolmentKeysClient.cs +++ b/src/Enclave.Sdk/Clients/Interfaces/IEnrolmentKeysClient.cs @@ -20,21 +20,21 @@ public interface IEnrolmentKeysClient /// Which page number do you want to return. /// How many Enrolment Keys per page. /// A paginated response model with links to get the previous, next, first and last pages. - Task> GetEnrolmentKeysAsync(string? searchTerm = null, bool? includeDisabled = null, EnrolmentKeySortOrder? sortOrder = null, int? pageNumber = null, int? perPage = null); + Task> GetEnrolmentKeysAsync(string? searchTerm = null, bool? includeDisabled = null, EnrolmentKeySortOrder? sortOrder = null, int? pageNumber = null, int? perPage = null); /// /// Creates an Enrolment Key using a Model. /// /// The model needed to create an Enrolment Key. - /// The created Enrolment Key as a . - Task CreateAsync(EnrolmentKeyCreate createModel); + /// The created Enrolment Key as a . + Task CreateAsync(EnrolmentKeyCreate createModel); /// /// Gets a detailed Enrolment Key model. /// /// The Id of the Enrolment Key to get. /// A detailed Enrolment Key. - Task GetAsync(EnrolmentKeyId enrolmentKeyId); + Task GetAsync(EnrolmentKeyId enrolmentKeyId); /// /// Patch request to update the EnrolmentKey. @@ -43,21 +43,21 @@ public interface IEnrolmentKeysClient /// The Id of the Enrolment Key to update. /// An instance of used to setup our patch request. /// A detailed Enrolment Key. - Task UpdateAsync(EnrolmentKeyId enrolmentKeyId, PatchBuilder builder); + Task UpdateAsync(EnrolmentKeyId enrolmentKeyId, PatchBuilder builder); /// /// Enable an Enrolment Key. /// /// The Id of the Enrolment Key to enable. /// A detailed Enrolment Key. - Task EnableAsync(EnrolmentKeyId enrolmentKeyId); + Task EnableAsync(EnrolmentKeyId enrolmentKeyId); /// /// Disable an Enrolment Key. /// /// The Id of the Enrolment Key to disable. /// A detailed Enrolment Key. - Task DisableAsync(EnrolmentKeyId enrolmentKeyId); + Task DisableAsync(EnrolmentKeyId enrolmentKeyId); /// /// Bulk enable mutliple Enrolment Keys. diff --git a/src/Enclave.Sdk/Clients/Interfaces/ILogsClient.cs b/src/Enclave.Sdk/Clients/Interfaces/ILogsClient.cs index 11595fd..e28c9a4 100644 --- a/src/Enclave.Sdk/Clients/Interfaces/ILogsClient.cs +++ b/src/Enclave.Sdk/Clients/Interfaces/ILogsClient.cs @@ -1,5 +1,18 @@ -namespace Enclave.Sdk.Api.Clients.Interfaces; +using Enclave.Sdk.Api.Data.Logging; +using Enclave.Sdk.Api.Data.Pagination; +namespace Enclave.Sdk.Api.Clients.Interfaces; + +/// +/// Access and search for logs. +/// public interface ILogsClient { + /// + /// Gets a paginated list of logs which can be searched and interated upon. + /// + /// Which page number do you want to return. + /// How many per page. + /// A paginated response model with links to get the previous, next, first and last pages. + Task> GetLogsAsync(int? pageNumber = null, int? perPage = null); } \ No newline at end of file diff --git a/src/Enclave.Sdk/Clients/Interfaces/IOrganisationClient.cs b/src/Enclave.Sdk/Clients/Interfaces/IOrganisationClient.cs index 828f38d..5cff80b 100644 --- a/src/Enclave.Sdk/Clients/Interfaces/IOrganisationClient.cs +++ b/src/Enclave.Sdk/Clients/Interfaces/IOrganisationClient.cs @@ -16,11 +16,6 @@ public interface IOrganisationClient /// AccountOrganisation Organisation { get; } - /// - /// An instance of associated with the current organisaiton. - /// - IAuthorityClient Authority { get; } - /// /// An instance of associated with the current organisaiton. /// @@ -42,9 +37,9 @@ public interface IOrganisationClient IPoliciesClient Policies { get; } /// - /// An instance of associated with the current organisaiton. + /// An instance of associated with the current organisaiton. /// - ISystemsClient Systems { get; } + IEnrolledSystemsClient EnrolledSystems { get; } /// /// An instance of associated with the current organisaiton. diff --git a/src/Enclave.Sdk/Clients/Interfaces/IPoliciesClient.cs b/src/Enclave.Sdk/Clients/Interfaces/IPoliciesClient.cs index f4a4246..5f2d690 100644 --- a/src/Enclave.Sdk/Clients/Interfaces/IPoliciesClient.cs +++ b/src/Enclave.Sdk/Clients/Interfaces/IPoliciesClient.cs @@ -12,13 +12,13 @@ namespace Enclave.Sdk.Api.Clients.Interfaces; public interface IPoliciesClient { /// - /// Gets a paginated list of Policies which can be searched and interated upon. + /// Gets a paginated list of Policies which can be searched and iterated upon. /// /// A partial matching search term. /// Include the disabled Policies in the results. /// Sort order for the pagination. /// Which page number do you want to return. - /// How many tags per page. + /// How many per page. /// A paginated response model with links to get the previous, next, first and last pages. Task> GetPoliciesAsync( string? searchTerm = null, diff --git a/src/Enclave.Sdk/Clients/Interfaces/ISystemsClient.cs b/src/Enclave.Sdk/Clients/Interfaces/ISystemsClient.cs deleted file mode 100644 index b0cf022..0000000 --- a/src/Enclave.Sdk/Clients/Interfaces/ISystemsClient.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Enclave.Sdk.Api.Clients.Interfaces; - -public interface ISystemsClient -{ -} \ No newline at end of file diff --git a/src/Enclave.Sdk/Clients/Interfaces/ITagsClient.cs b/src/Enclave.Sdk/Clients/Interfaces/ITagsClient.cs index 39647d1..d0e7039 100644 --- a/src/Enclave.Sdk/Clients/Interfaces/ITagsClient.cs +++ b/src/Enclave.Sdk/Clients/Interfaces/ITagsClient.cs @@ -14,7 +14,7 @@ public interface ITagsClient /// A partial matching search term. /// Sort order for the pagination. /// Which page number do you want to return. - /// How many tags per page. + /// How many per page. /// A paginated response model with links to get the previous, next, first and last pages. Task> GetAsync(string? searchTerm = null, TagQuerySortOrder? sortOrder = null, int? pageNumber = null, int? perPage = null); } \ No newline at end of file diff --git a/src/Enclave.Sdk/Clients/Interfaces/IUnapprovedSystemsClient.cs b/src/Enclave.Sdk/Clients/Interfaces/IUnapprovedSystemsClient.cs index ab78f45..d0535e6 100644 --- a/src/Enclave.Sdk/Clients/Interfaces/IUnapprovedSystemsClient.cs +++ b/src/Enclave.Sdk/Clients/Interfaces/IUnapprovedSystemsClient.cs @@ -18,9 +18,9 @@ public interface IUnapprovedSystemsClient /// A partial matching search term. /// Sort order for the pagination. /// Which page number do you want to return. - /// How many tags per page. + /// How many per page. /// A paginated response model with links to get the previous, next, first and last pages. - Task> GetSystemsAsync( + Task> GetSystemsAsync( int? enrolmentKeyId = null, string? searchTerm = null, UnapprovedSystemQuerySortMode? sortOrder = null, @@ -46,7 +46,7 @@ Task> GetSystemsAsync( /// /// The system Id you want to get. /// A Detailed Unapproved System Model. - Task GetAsync(SystemId systemId); + Task GetAsync(SystemId systemId); /// /// Patch request to update an Unapproved System. @@ -54,14 +54,14 @@ Task> GetSystemsAsync( /// The system Id you want to update. /// An instance of used to setup our patch request. /// An updated Detailed Unapproved System model. - Task UpdateAsync(SystemId systemId, PatchBuilder builder); + Task UpdateAsync(SystemId systemId, PatchBuilder builder); /// /// Decline an Unapproved System. /// /// The system Id you want to decline. /// The declined System. - Task DeclineAsync(SystemId systemId); + Task DeclineAsync(SystemId systemId); /// /// Approve a System. diff --git a/src/Enclave.Sdk/Clients/LogsClient.cs b/src/Enclave.Sdk/Clients/LogsClient.cs index 35518a6..6ea546f 100644 --- a/src/Enclave.Sdk/Clients/LogsClient.cs +++ b/src/Enclave.Sdk/Clients/LogsClient.cs @@ -1,14 +1,52 @@ +using System.Net.Http.Json; +using System.Web; using Enclave.Sdk.Api.Clients.Interfaces; +using Enclave.Sdk.Api.Data.Logging; +using Enclave.Sdk.Api.Data.Pagination; namespace Enclave.Sdk.Api.Clients; +/// internal class LogsClient : ClientBase, ILogsClient { private readonly string _orgRoute; + /// + /// Constructor which will be called by when it's created. + /// + /// an instance of httpClient with a baseURL referencing the API. + /// the orgRoute which specifies the orgId. public LogsClient(HttpClient httpClient, string orgRoute) : base(httpClient) { _orgRoute = orgRoute; } + + /// + public async Task> GetLogsAsync(int? pageNumber = null, int? perPage = null) + { + var queryString = BuildQueryString(pageNumber, perPage); + + var model = await HttpClient.GetFromJsonAsync>($"{_orgRoute}/logs?{queryString}"); + + EnsureNotNull(model); + + return model; + } + + private static string? BuildQueryString(int? pageNumber, int? perPage) + { + var queryString = HttpUtility.ParseQueryString(string.Empty); + if (pageNumber is not null) + { + queryString.Add("page", pageNumber.ToString()); + } + + if (perPage is not null) + { + queryString.Add("per_page", perPage.ToString()); + } + + return queryString.ToString(); + } } diff --git a/src/Enclave.Sdk/Clients/OrganisationClient.cs b/src/Enclave.Sdk/Clients/OrganisationClient.cs index 3c039ff..2a10d30 100644 --- a/src/Enclave.Sdk/Clients/OrganisationClient.cs +++ b/src/Enclave.Sdk/Clients/OrganisationClient.cs @@ -24,18 +24,18 @@ public OrganisationClient(HttpClient httpClient, AccountOrganisation currentOrga Organisation = currentOrganisation; _orgRoute = $"org/{Organisation.OrgId}"; - EnrolmentKeys = new EnrolmentKeysClient(httpClient, _orgRoute); Dns = new DnsClient(httpClient, _orgRoute); - UnapprovedSystems = new UnapprovedSystemsClient(httpClient, _orgRoute); + EnrolmentKeys = new EnrolmentKeysClient(httpClient, _orgRoute); + Logs = new LogsClient(httpClient, _orgRoute); Policies = new PoliciesClient(httpClient, _orgRoute); + EnrolledSystems = new EnrolledSystemsClient(httpClient, _orgRoute); + Tags = new TagsClient(httpClient, _orgRoute); + UnapprovedSystems = new UnapprovedSystemsClient(httpClient, _orgRoute); } /// public AccountOrganisation Organisation { get; } - /// - public IAuthorityClient Authority => throw new NotImplementedException(); - /// public IDnsClient Dns { get; } @@ -43,16 +43,16 @@ public OrganisationClient(HttpClient httpClient, AccountOrganisation currentOrga public IEnrolmentKeysClient EnrolmentKeys { get; } /// - public ILogsClient Logs => throw new NotImplementedException(); + public ILogsClient Logs { get; } /// public IPoliciesClient Policies { get; } /// - public ISystemsClient Systems => throw new NotImplementedException(); + public IEnrolledSystemsClient EnrolledSystems { get; } /// - public ITagsClient Tags => throw new NotImplementedException(); + public ITagsClient Tags { get; } /// public IUnapprovedSystemsClient UnapprovedSystems { get; } diff --git a/src/Enclave.Sdk/Clients/SystemsClient.cs b/src/Enclave.Sdk/Clients/SystemsClient.cs deleted file mode 100644 index b629dad..0000000 --- a/src/Enclave.Sdk/Clients/SystemsClient.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Enclave.Sdk.Api.Clients.Interfaces; - -namespace Enclave.Sdk.Api.Clients; - -internal class SystemsClient : ClientBase, ISystemsClient -{ - private readonly string _orgRoute; - - public SystemsClient(HttpClient httpClient, string orgRoute) - : base(httpClient) - { - _orgRoute = orgRoute; - } -} diff --git a/src/Enclave.Sdk/Clients/UnapprovedSystemsClient.cs b/src/Enclave.Sdk/Clients/UnapprovedSystemsClient.cs index feae06a..cd549e4 100644 --- a/src/Enclave.Sdk/Clients/UnapprovedSystemsClient.cs +++ b/src/Enclave.Sdk/Clients/UnapprovedSystemsClient.cs @@ -27,7 +27,7 @@ public UnapprovedSystemsClient(HttpClient httpClient, string orgRoute) } /// - public async Task> GetSystemsAsync( + public async Task> GetSystemsAsync( int? enrolmentKeyId = null, string? searchTerm = null, UnapprovedSystemQuerySortMode? sortOrder = null, @@ -36,7 +36,7 @@ public async Task> GetSystemsAsync( { var queryString = BuildQueryString(enrolmentKeyId, searchTerm, sortOrder, pageNumber, perPage); - var model = await HttpClient.GetFromJsonAsync>($"{_orgRoute}/unapproved-systems?{queryString}"); + var model = await HttpClient.GetFromJsonAsync>($"{_orgRoute}/unapproved-systems?{queryString}"); EnsureNotNull(model); @@ -76,9 +76,9 @@ public async Task DeclineSystems(IEnumerable systemIds) } /// - public async Task GetAsync(SystemId systemId) + public async Task GetAsync(SystemId systemId) { - var model = await HttpClient.GetFromJsonAsync($"{_orgRoute}/unapproved-systems/{systemId}", Constants.JsonSerializerOptions); + var model = await HttpClient.GetFromJsonAsync($"{_orgRoute}/unapproved-systems/{systemId}", Constants.JsonSerializerOptions); EnsureNotNull(model); @@ -86,7 +86,7 @@ public async Task GetAsync(SystemId systemId) } /// - public async Task UpdateAsync(SystemId systemId, PatchBuilder builder) + public async Task UpdateAsync(SystemId systemId, PatchBuilder builder) { if (builder is null) { @@ -98,7 +98,7 @@ public async Task UpdateAsync(SystemId systemId, PatchBu result.EnsureSuccessStatusCode(); - var model = await DeserialiseAsync(result.Content); + var model = await DeserialiseAsync(result.Content); EnsureNotNull(model); @@ -106,13 +106,13 @@ public async Task UpdateAsync(SystemId systemId, PatchBu } /// - public async Task DeclineAsync(SystemId systemId) + public async Task DeclineAsync(SystemId systemId) { var result = await HttpClient.DeleteAsync($"{_orgRoute}/unapproved-systems/{systemId}"); result.EnsureSuccessStatusCode(); - var model = await DeserialiseAsync(result.Content); + var model = await DeserialiseAsync(result.Content); EnsureNotNull(model); diff --git a/src/Enclave.Sdk/Constants.cs b/src/Enclave.Sdk/Constants.cs index 38af783..5373998 100644 --- a/src/Enclave.Sdk/Constants.cs +++ b/src/Enclave.Sdk/Constants.cs @@ -9,7 +9,6 @@ public static JsonSerializerOptions JsonSerializerOptions { get { - var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, diff --git a/src/Enclave.Sdk/Data/Account/UserOrganisationRole.cs b/src/Enclave.Sdk/Data/Account/UserOrganisationRole.cs index d5af46d..72fcb83 100644 --- a/src/Enclave.Sdk/Data/Account/UserOrganisationRole.cs +++ b/src/Enclave.Sdk/Data/Account/UserOrganisationRole.cs @@ -1,7 +1,17 @@ namespace Enclave.Sdk.Api.Data.Account; +/// +/// The User roles. +/// public enum UserOrganisationRole { + /// + /// The owner of the organisation. + /// Owner, + + /// + /// An Admin of the organisaiton. + /// Admin, } \ No newline at end of file diff --git a/src/Enclave.Sdk/Data/Dns/FullDnsRecord.cs b/src/Enclave.Sdk/Data/Dns/DnsRecord.cs similarity index 92% rename from src/Enclave.Sdk/Data/Dns/FullDnsRecord.cs rename to src/Enclave.Sdk/Data/Dns/DnsRecord.cs index bfbd959..a07e456 100644 --- a/src/Enclave.Sdk/Data/Dns/FullDnsRecord.cs +++ b/src/Enclave.Sdk/Data/Dns/DnsRecord.cs @@ -1,4 +1,5 @@ -using Enclave.Sdk.Api.Data.SystemManagement; +using Enclave.Sdk.Api.Data.EnrolledSystems; +using Enclave.Sdk.Api.Data.SystemManagement; using Enclave.Sdk.Api.Data.Tags; namespace Enclave.Sdk.Api.Data.Dns; @@ -6,9 +7,8 @@ namespace Enclave.Sdk.Api.Data.Dns; /// /// Detailed model representing a DNS record. /// -public class FullDnsRecord +public class DnsRecord { - /// /// The ID of the record. /// diff --git a/src/Enclave.Sdk/Data/Dns/DnsRecordId.cs b/src/Enclave.Sdk/Data/Dns/DnsRecordId.cs index 0982fb0..12423c4 100644 --- a/src/Enclave.Sdk/Data/Dns/DnsRecordId.cs +++ b/src/Enclave.Sdk/Data/Dns/DnsRecordId.cs @@ -2,6 +2,9 @@ namespace Enclave.Sdk.Api.Data.Dns; +/// +/// An int backed Dns Record Id. +/// [TypedId(IdBackingType.Int)] public readonly partial struct DnsRecordId { diff --git a/src/Enclave.Sdk/Data/Dns/BasicDnsRecord.cs b/src/Enclave.Sdk/Data/Dns/DnsRecordSummary.cs similarity index 88% rename from src/Enclave.Sdk/Data/Dns/BasicDnsRecord.cs rename to src/Enclave.Sdk/Data/Dns/DnsRecordSummary.cs index 391719f..8a24104 100644 --- a/src/Enclave.Sdk/Data/Dns/BasicDnsRecord.cs +++ b/src/Enclave.Sdk/Data/Dns/DnsRecordSummary.cs @@ -1,12 +1,13 @@ -using Enclave.Sdk.Api.Data.SystemManagement; +using Enclave.Sdk.Api.Data.EnrolledSystems; +using Enclave.Sdk.Api.Data.SystemManagement; using Enclave.Sdk.Api.Data.Tags; namespace Enclave.Sdk.Api.Data.Dns; /// -/// Basic model representing a summary of a DNS record. +/// Model representing a summary of a DNS record. /// -public class BasicDnsRecord +public class DnsRecordSummary { /// /// The ID of the record. diff --git a/src/Enclave.Sdk/Data/Dns/FullDnsZone.cs b/src/Enclave.Sdk/Data/Dns/DnsZone.cs similarity index 97% rename from src/Enclave.Sdk/Data/Dns/FullDnsZone.cs rename to src/Enclave.Sdk/Data/Dns/DnsZone.cs index cf05753..6c8809a 100644 --- a/src/Enclave.Sdk/Data/Dns/FullDnsZone.cs +++ b/src/Enclave.Sdk/Data/Dns/DnsZone.cs @@ -3,7 +3,7 @@ /// /// Detailed model representing a DNS zone. /// -public class FullDnsZone +public class DnsZone { /// /// The ID of the zone. diff --git a/src/Enclave.Sdk/Data/Dns/DnsZoneId.cs b/src/Enclave.Sdk/Data/Dns/DnsZoneId.cs index 17694d4..19a491a 100644 --- a/src/Enclave.Sdk/Data/Dns/DnsZoneId.cs +++ b/src/Enclave.Sdk/Data/Dns/DnsZoneId.cs @@ -2,6 +2,9 @@ namespace Enclave.Sdk.Api.Data.Dns; +/// +/// An int backed Dns Zone Id. +/// [TypedId(IdBackingType.Int)] public readonly partial struct DnsZoneId { diff --git a/src/Enclave.Sdk/Data/Dns/BasicDnsZone.cs b/src/Enclave.Sdk/Data/Dns/DnsZoneSummary.cs similarity index 91% rename from src/Enclave.Sdk/Data/Dns/BasicDnsZone.cs rename to src/Enclave.Sdk/Data/Dns/DnsZoneSummary.cs index 9a2a8cf..d7dca28 100644 --- a/src/Enclave.Sdk/Data/Dns/BasicDnsZone.cs +++ b/src/Enclave.Sdk/Data/Dns/DnsZoneSummary.cs @@ -1,9 +1,9 @@ namespace Enclave.Sdk.Api.Data.Dns; /// -/// Basic model representing a summary of a DNS record. +/// Model representing a summary of a DNS record. /// -public class BasicDnsZone +public class DnsZoneSummary { /// /// The ID of the zone. diff --git a/src/Enclave.Sdk/Data/EnrolledSystems/BulkSystemRevokedResult.cs b/src/Enclave.Sdk/Data/EnrolledSystems/BulkSystemRevokedResult.cs new file mode 100644 index 0000000..69ea5b2 --- /dev/null +++ b/src/Enclave.Sdk/Data/EnrolledSystems/BulkSystemRevokedResult.cs @@ -0,0 +1,12 @@ +namespace Enclave.Sdk.Api.Data.EnrolledSystems; + +/// +/// The result of a bulk system revocation. +/// +public class BulkSystemRevokedResult +{ + /// + /// How many systems were actually revoked. + /// + public int SystemsRevoked { get; set; } +} diff --git a/src/Enclave.Sdk/Data/EnrolledSystems/BulkSystemUpdateResult.cs b/src/Enclave.Sdk/Data/EnrolledSystems/BulkSystemUpdateResult.cs new file mode 100644 index 0000000..9bdd241 --- /dev/null +++ b/src/Enclave.Sdk/Data/EnrolledSystems/BulkSystemUpdateResult.cs @@ -0,0 +1,12 @@ +namespace Enclave.Sdk.Api.Data.EnrolledSystems; + +/// +/// Defines the result of a bulk system update. +/// +public class BulkSystemUpdateResult +{ + /// + /// The number of systems actually updated. + /// + public int SystemsUpdated { get; set; } +} diff --git a/src/Enclave.Sdk/Data/EnrolledSystems/EnrolledSystem.cs b/src/Enclave.Sdk/Data/EnrolledSystems/EnrolledSystem.cs new file mode 100644 index 0000000..b9f337b --- /dev/null +++ b/src/Enclave.Sdk/Data/EnrolledSystems/EnrolledSystem.cs @@ -0,0 +1,105 @@ +using Enclave.Sdk.Api.Data.EnrolledSystems.Enum; +using Enclave.Sdk.Api.Data.Tags; + +namespace Enclave.Sdk.Api.Data.EnrolledSystems; + +/// +/// A detailed model representing a single system. +/// +public class EnrolledSystem +{ + /// + /// Unique ID for the System. + /// + public SystemId SystemId { get; init; } = default!; + + /// + /// The configured description of the system. + /// + public string? Description { get; init; } + + /// + /// The type of the system. + /// + public SystemType Type { get; init; } + + /// + /// A value indicating the current state of the system from Enclave's perspective. + /// + public SystemState State { get; init; } + + /// + /// Indicates a UTC timestamp when the system connected to the Enclave SaaS. + /// + public DateTime? ConnectedAt { get; init; } + + /// + /// Indicates a UTC timestamp when Enclave last interacted with the system. + /// + public DateTime? LastSeen { get; init; } + + /// + /// Contains a timestamp indicating when the system was enrolled into the account. + /// + public DateTime EnrolledAt { get; init; } + + /// + /// The ID of the enrolment key used to enrol the system. + /// + public int EnrolmentKeyId { get; init; } + + /// + /// The description of the enrolment key used to enrol the system. + /// + public string? EnrolmentKeyDescription { get; init; } + + /// + /// Whether or not the system is enabled. + /// + public bool IsEnabled { get; init; } + + /// + /// The IP address the system is connected from. + /// + public string? ConnectedFrom { get; init; } + + /// + /// The locally-defined host name of the system. + /// + public string? Hostname { get; init; } + + /// + /// The platform type for this system; possible values are Windows, Linux or Darwin. + /// + public string? PlatformType { get; init; } + + /// + /// The version of the operating system. + /// + public string? OSVersion { get; init; } + + /// + /// The Enclave product version. + /// + public string? EnclaveVersion { get; init; } + + /// + /// The tags assigned to the system. + /// + public IReadOnlyList Tags { get; init; } = Array.Empty(); + + /// + /// The set of DNS entries applied to the system. + /// + public IReadOnlyList Dns { get; init; } = Array.Empty(); + + /// + /// Any additional notes attached to the system. + /// + public string? Notes { get; init; } + + /// + /// Defines the number of minutes this system will be retained after a non-graceful disconnect. + /// + public int? DisconnectedRetentionMinutes { get; init; } +} diff --git a/src/Enclave.Sdk/Data/EnrolledSystems/EnrolledSystemSummary.cs b/src/Enclave.Sdk/Data/EnrolledSystems/EnrolledSystemSummary.cs new file mode 100644 index 0000000..a5fbc19 --- /dev/null +++ b/src/Enclave.Sdk/Data/EnrolledSystems/EnrolledSystemSummary.cs @@ -0,0 +1,95 @@ +using Enclave.Sdk.Api.Data.EnrolledSystems.Enum; +using Enclave.Sdk.Api.Data.Tags; + +namespace Enclave.Sdk.Api.Data.EnrolledSystems; + +/// +/// A basic model representing a single system. +/// +public class EnrolledSystemSummary +{ + /// + /// Unique ID for the System. + /// + public SystemId SystemId { get; init; } = default!; + + /// + /// The configured description of the system. + /// + public string? Description { get; init; } + + /// + /// The type of the system. + /// + public SystemType Type { get; init; } + + /// + /// A value indicating the current state of the system from Enclave's perspective. + /// + public SystemState State { get; init; } + + /// + /// Indicates a UTC timestamp when the system connected to the Enclave SaaS. + /// + public DateTime? ConnectedAt { get; init; } + + /// + /// Indicates a UTC timestamp when Enclave last interacted with the system. + /// + public DateTime? LastSeen { get; init; } + + /// + /// Contains a timestamp indicating when the system was enrolled into the account. + /// + public DateTime EnrolledAt { get; init; } + + /// + /// The ID of the enrolment key used to enrol the system. + /// + public int EnrolmentKeyId { get; init; } + + /// + /// The description of the enrolment key used to enrol the system. + /// + public string EnrolmentKeyDescription { get; init; } = default!; + + /// + /// Whether or not the system is enabled. + /// + public bool IsEnabled { get; init; } + + /// + /// The IP address the system is connected from. + /// + public string? ConnectedFrom { get; init; } + + /// + /// The locally-defined host name of the system. + /// + public string? Hostname { get; init; } + + /// + /// The platform type for this system; possible values are Windows, Linux or Darwin. + /// + public string? PlatformType { get; init; } + + /// + /// The version of the operating system. + /// + public string? OSVersion { get; init; } + + /// + /// The Enclave product version. + /// + public string? EnclaveVersion { get; init; } + + /// + /// The tags assigned to the system. + /// + public IReadOnlyList? Tags { get; init; } + + /// + /// Defines the number of minutes this system will be retained after a non-graceful disconnect. + /// + public int? DisconnectedRetentionMinutes { get; init; } +} diff --git a/src/Enclave.Sdk/Data/EnrolledSystems/Enum/SystemQuerySortMode.cs b/src/Enclave.Sdk/Data/EnrolledSystems/Enum/SystemQuerySortMode.cs new file mode 100644 index 0000000..9864272 --- /dev/null +++ b/src/Enclave.Sdk/Data/EnrolledSystems/Enum/SystemQuerySortMode.cs @@ -0,0 +1,27 @@ +namespace Enclave.Sdk.Api.Data.EnrolledSystems.Enum; + +/// +/// System Query Sort order used when making a System request. +/// +public enum SystemQuerySortMode +{ + /// + /// Sort by recently enrolled. + /// + RecentlyEnrolled, + + /// + /// Sort by recently connected. + /// + RecentlyConnected, + + /// + /// Sort by description. + /// + Description, + + /// + /// Sort by enrolment key. + /// + EnrolmentKeyUsed, +} \ No newline at end of file diff --git a/src/Enclave.Sdk/Data/SystemManagement/SystemState.cs b/src/Enclave.Sdk/Data/EnrolledSystems/Enum/SystemState.cs similarity index 88% rename from src/Enclave.Sdk/Data/SystemManagement/SystemState.cs rename to src/Enclave.Sdk/Data/EnrolledSystems/Enum/SystemState.cs index 646307b..251bb3d 100644 --- a/src/Enclave.Sdk/Data/SystemManagement/SystemState.cs +++ b/src/Enclave.Sdk/Data/EnrolledSystems/Enum/SystemState.cs @@ -1,4 +1,4 @@ -namespace Enclave.Sdk.Api.Data.SystemManagement; +namespace Enclave.Sdk.Api.Data.EnrolledSystems.Enum; /// /// The possible states of an enrolled system. diff --git a/src/Enclave.Sdk/Data/EnrolledSystems/Enum/SystemType.cs b/src/Enclave.Sdk/Data/EnrolledSystems/Enum/SystemType.cs new file mode 100644 index 0000000..bce91a5 --- /dev/null +++ b/src/Enclave.Sdk/Data/EnrolledSystems/Enum/SystemType.cs @@ -0,0 +1,19 @@ +namespace Enclave.Sdk.Api.Data.EnrolledSystems.Enum; + +/// +/// Defines the types of Systems. +/// +public enum SystemType +{ + /// + /// For workstations, laptops, servers, and other systems that are relatively long-lived or manually provisioned. + /// Systems remain in your Enclave Organisation if they stop running. + /// + GeneralPurpose, + + /// + /// For containers, kubernetes pods, and other systems that are temporary, short-lived or automatically provisioned. + /// Systems are automatically removed from your Enclave Organisation when they stop/disconnect. + /// + Ephemeral, +} diff --git a/src/Enclave.Sdk/Data/EnrolledSystems/SystemDnsEntry.cs b/src/Enclave.Sdk/Data/EnrolledSystems/SystemDnsEntry.cs new file mode 100644 index 0000000..c84ff5c --- /dev/null +++ b/src/Enclave.Sdk/Data/EnrolledSystems/SystemDnsEntry.cs @@ -0,0 +1,45 @@ +using Enclave.Sdk.Api.Data.Dns; +using Enclave.Sdk.Api.Data.Tags; + +namespace Enclave.Sdk.Api.Data.EnrolledSystems; + +/// +/// Represents a single system DNS entry. +/// +public class SystemDnsEntry +{ + /// + /// The FQDN (Fully Qualified Domain Name) of the entry. + /// + public string Fqdn { get; init; } = default!; + + /// + /// The zone ID the DNS entry came from. + /// + public DnsZoneId? FromZoneId { get; init; } + + /// + /// The zone Name the DNS entry came from. + /// + public string? FromZoneName { get; init; } + + /// + /// The DNS record ID the DNS entry came from. + /// + public DnsRecordId? FromRecordId { get; init; } + + /// + /// The DNS record name the DNS entry came from. + /// + public string? FromRecordName { get; init; } + + /// + /// Indicates whether the DNS entry was directly assigned to this specific system. + /// + public bool FromDirectAssignment { get; init; } + + /// + /// Contains the set of tags on the system that caused it to be assigned this name. + /// + public IReadOnlyList? Tags { get; init; } +} diff --git a/src/Enclave.Sdk/Data/EnrolmentKeys/FullEnrolmentKey.cs b/src/Enclave.Sdk/Data/EnrolmentKeys/EnrolmentKey.cs similarity index 98% rename from src/Enclave.Sdk/Data/EnrolmentKeys/FullEnrolmentKey.cs rename to src/Enclave.Sdk/Data/EnrolmentKeys/EnrolmentKey.cs index 6723d9a..2e84c11 100644 --- a/src/Enclave.Sdk/Data/EnrolmentKeys/FullEnrolmentKey.cs +++ b/src/Enclave.Sdk/Data/EnrolmentKeys/EnrolmentKey.cs @@ -6,7 +6,7 @@ namespace Enclave.Sdk.Api.Data.EnrolmentKeys; /// /// Represents a single Enclave Enrolment Key. /// -public class FullEnrolmentKey +public class EnrolmentKey { /// /// The ID of the enrolment key. diff --git a/src/Enclave.Sdk/Data/EnrolmentKeys/EnrolmentKeyId.cs b/src/Enclave.Sdk/Data/EnrolmentKeys/EnrolmentKeyId.cs index c651970..d26a553 100644 --- a/src/Enclave.Sdk/Data/EnrolmentKeys/EnrolmentKeyId.cs +++ b/src/Enclave.Sdk/Data/EnrolmentKeys/EnrolmentKeyId.cs @@ -2,6 +2,9 @@ namespace Enclave.Sdk.Api.Data.EnrolmentKeys; +/// +/// An int backed Enrolment Key Id. +/// [TypedId(IdBackingType.Int)] public partial struct EnrolmentKeyId { diff --git a/src/Enclave.Sdk/Data/EnrolmentKeys/SimpleEnrolmentKey.cs b/src/Enclave.Sdk/Data/EnrolmentKeys/EnrolmentKeySummary.cs similarity index 98% rename from src/Enclave.Sdk/Data/EnrolmentKeys/SimpleEnrolmentKey.cs rename to src/Enclave.Sdk/Data/EnrolmentKeys/EnrolmentKeySummary.cs index c5e2b9d..7ecaf73 100644 --- a/src/Enclave.Sdk/Data/EnrolmentKeys/SimpleEnrolmentKey.cs +++ b/src/Enclave.Sdk/Data/EnrolmentKeys/EnrolmentKeySummary.cs @@ -6,7 +6,7 @@ namespace Enclave.Sdk.Api.Data.EnrolmentKeys; /// /// Represents a single Enclave Enrolment Key. /// -public class SimpleEnrolmentKey +public class EnrolmentKeySummary { /// /// The ID of the enrolment key. diff --git a/src/Enclave.Sdk/Data/EnrolmentKeys/Enum/ApprovalMode.cs b/src/Enclave.Sdk/Data/EnrolmentKeys/Enum/ApprovalMode.cs index bf1ddad..8c3b64c 100644 --- a/src/Enclave.Sdk/Data/EnrolmentKeys/Enum/ApprovalMode.cs +++ b/src/Enclave.Sdk/Data/EnrolmentKeys/Enum/ApprovalMode.cs @@ -1,7 +1,17 @@ namespace Enclave.Sdk.Api.Data.EnrolmentKeys.Enum; +/// +/// System Approval Mode. +/// public enum ApprovalMode { + /// + /// Automatically approve systems. + /// Automatic, + + /// + /// Manually approve systems. + /// Manual, } \ No newline at end of file diff --git a/src/Enclave.Sdk/Data/EnrolmentKeys/Enum/EnrolmentKeySortOrder.cs b/src/Enclave.Sdk/Data/EnrolmentKeys/Enum/EnrolmentKeySortOrder.cs index 0da202c..fa62bef 100644 --- a/src/Enclave.Sdk/Data/EnrolmentKeys/Enum/EnrolmentKeySortOrder.cs +++ b/src/Enclave.Sdk/Data/EnrolmentKeys/Enum/EnrolmentKeySortOrder.cs @@ -1,9 +1,27 @@ namespace Enclave.Sdk.Api.Data.EnrolmentKeys.Enum; +/// +/// Enrolment Key Sort Order used when making an Enrolment Key request. +/// public enum EnrolmentKeySortOrder { + /// + /// Sort by Description. + /// Description, + + /// + /// Sort by Last Used. + /// LastUsed, + + /// + /// Sort By Approval Mode. + /// ApprovalMode, + + /// + /// Sort by Uses Remaining. + /// UsesRemaining, } \ No newline at end of file diff --git a/src/Enclave.Sdk/Data/Logging/Enum/ActivityLogLevel.cs b/src/Enclave.Sdk/Data/Logging/Enum/ActivityLogLevel.cs new file mode 100644 index 0000000..11b52d6 --- /dev/null +++ b/src/Enclave.Sdk/Data/Logging/Enum/ActivityLogLevel.cs @@ -0,0 +1,22 @@ +namespace Enclave.Sdk.Api.Data.Logging.Enum; + +/// +/// Log Error Type. +/// +public enum ActivityLogLevel +{ + /// + /// Information log level. + /// + Information, + + /// + /// Warning Log. + /// + Warning, + + /// + /// Error Log. + /// + Error, +} \ No newline at end of file diff --git a/src/Enclave.Sdk/Data/Logging/LogEntry.cs b/src/Enclave.Sdk/Data/Logging/LogEntry.cs new file mode 100644 index 0000000..e40c6d5 --- /dev/null +++ b/src/Enclave.Sdk/Data/Logging/LogEntry.cs @@ -0,0 +1,34 @@ +using Enclave.Sdk.Api.Data.Logging.Enum; + +namespace Enclave.Sdk.Api.Data.Logging; + +/// +/// Model for a single log entry. +/// +public class LogEntry +{ + /// + /// The UTC timestamp of the log event. + /// + public DateTime TimeStamp { get; set; } + + /// + /// The log level. + /// + public ActivityLogLevel Level { get; set; } + + /// + /// The log message. + /// + public string Message { get; set; } = default!; + + /// + /// The user responsible for the event (if known). + /// + public string? UserName { get; set; } + + /// + /// The IP address from which the action was carried out. + /// + public string? IpAddress { get; set; } +} \ No newline at end of file diff --git a/src/Enclave.Sdk/Data/Organisations/Enum/OrganisationPlan.cs b/src/Enclave.Sdk/Data/Organisations/Enum/OrganisationPlan.cs index 8ed8025..c845afa 100644 --- a/src/Enclave.Sdk/Data/Organisations/Enum/OrganisationPlan.cs +++ b/src/Enclave.Sdk/Data/Organisations/Enum/OrganisationPlan.cs @@ -1,8 +1,22 @@ namespace Enclave.Sdk.Api.Data.Organisations.Enum; +/// +/// An Enum describing the types of plan. +/// public enum OrganisationPlan { + /// + /// Starter Organisation Plan. + /// Starter = 0, + + /// + /// Pro Organisaiton Plan. + /// Pro = 1, + + /// + /// Business Organisaiton Plan. + /// Business = 2, } diff --git a/src/Enclave.Sdk/Data/Organisations/OrganisationId.cs b/src/Enclave.Sdk/Data/Organisations/OrganisationId.cs index d528681..287aa09 100644 --- a/src/Enclave.Sdk/Data/Organisations/OrganisationId.cs +++ b/src/Enclave.Sdk/Data/Organisations/OrganisationId.cs @@ -3,7 +3,7 @@ namespace Enclave.Sdk.Api.Data.Organisations; /// -/// OrganisaitonId struct to distinguish between Id types. +/// OrganisationId struct to distinguish between Id types. /// [TypedId] public readonly partial struct OrganisationId diff --git a/src/Enclave.Sdk/Data/Organisations/OrganisationUser.cs b/src/Enclave.Sdk/Data/Organisations/OrganisationUser.cs index 59b7519..03c2f41 100644 --- a/src/Enclave.Sdk/Data/Organisations/OrganisationUser.cs +++ b/src/Enclave.Sdk/Data/Organisations/OrganisationUser.cs @@ -38,7 +38,13 @@ public class OrganisationUser public UserOrganisationRole Role { get; init; } } +/// +/// Top Level model for organisation user requests. +/// public class OrganisationUsersTopLevel { + /// + /// A list of Organisation Users. + /// public IReadOnlyList? Users { get; init; } } \ No newline at end of file diff --git a/src/Enclave.Sdk/Data/Pagination/PaginatedResponseModel.cs b/src/Enclave.Sdk/Data/Pagination/PaginatedResponseModel.cs index 6018bb9..17e9de4 100644 --- a/src/Enclave.Sdk/Data/Pagination/PaginatedResponseModel.cs +++ b/src/Enclave.Sdk/Data/Pagination/PaginatedResponseModel.cs @@ -9,15 +9,15 @@ public class PaginatedResponseModel /// /// Metadata for the paginated data. /// - public PaginationMetadata Metadata { get; init; } + public PaginationMetadata Metadata { get; init; } = default!; /// /// The related links for the current page of data. /// - public PaginationLinks Links { get; init; } + public PaginationLinks Links { get; init; } = default!; /// /// The requested page of items. /// - public IEnumerable Items { get; init; } + public IEnumerable Items { get; init; } = default!; } \ No newline at end of file diff --git a/src/Enclave.Sdk/Data/Pagination/PaginationLinks.cs b/src/Enclave.Sdk/Data/Pagination/PaginationLinks.cs index d72c346..4445eae 100644 --- a/src/Enclave.Sdk/Data/Pagination/PaginationLinks.cs +++ b/src/Enclave.Sdk/Data/Pagination/PaginationLinks.cs @@ -8,7 +8,7 @@ public class PaginationLinks /// /// The first page of data. /// - public Uri First { get; init; } + public Uri? First { get; init; } /// /// The previous page of data (or null if this is the first page). @@ -23,5 +23,5 @@ public class PaginationLinks /// /// The last page of data. /// - public Uri Last { get; init; } + public Uri? Last { get; init; } } \ No newline at end of file diff --git a/src/Enclave.Sdk/Data/PatchModel/SystemPatch.cs b/src/Enclave.Sdk/Data/PatchModel/EnrolledSystemPatch.cs similarity index 93% rename from src/Enclave.Sdk/Data/PatchModel/SystemPatch.cs rename to src/Enclave.Sdk/Data/PatchModel/EnrolledSystemPatch.cs index a87292e..78d2287 100644 --- a/src/Enclave.Sdk/Data/PatchModel/SystemPatch.cs +++ b/src/Enclave.Sdk/Data/PatchModel/EnrolledSystemPatch.cs @@ -3,7 +3,7 @@ /// /// Defines the modifiable properties of a system. /// -public class SystemPatch : IPatchModel +public class EnrolledSystemPatch : IPatchModel { /// /// The system description. diff --git a/src/Enclave.Sdk/Data/PatchModel/IPatchModel.cs b/src/Enclave.Sdk/Data/PatchModel/IPatchModel.cs index 96e0059..2b3f768 100644 --- a/src/Enclave.Sdk/Data/PatchModel/IPatchModel.cs +++ b/src/Enclave.Sdk/Data/PatchModel/IPatchModel.cs @@ -1,5 +1,9 @@ namespace Enclave.Sdk.Api.Data.PatchModel; +/// +/// An interface for use with a PatchBuilder. +/// +[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1040:Avoid empty interfaces", Justification = "Useful for using PatchBuilder")] public interface IPatchModel { } \ No newline at end of file diff --git a/src/Enclave.Sdk/Data/Policies/Enum/PolicyAclProtocol.cs b/src/Enclave.Sdk/Data/Policies/Enum/PolicyAclProtocol.cs index 880fb8a..a4d7bed 100644 --- a/src/Enclave.Sdk/Data/Policies/Enum/PolicyAclProtocol.cs +++ b/src/Enclave.Sdk/Data/Policies/Enum/PolicyAclProtocol.cs @@ -5,8 +5,23 @@ /// public enum PolicyAclProtocol { + /// + /// Any Protocol. + /// Any, + + /// + /// Tcp. + /// Tcp, + + /// + /// Udp. + /// Udp, + + /// + /// Icmp. + /// Icmp, } diff --git a/src/Enclave.Sdk/Data/Policies/Enum/PolicySortOrder.cs b/src/Enclave.Sdk/Data/Policies/Enum/PolicySortOrder.cs index c6ad0d1..c46565d 100644 --- a/src/Enclave.Sdk/Data/Policies/Enum/PolicySortOrder.cs +++ b/src/Enclave.Sdk/Data/Policies/Enum/PolicySortOrder.cs @@ -1,7 +1,17 @@ namespace Enclave.Sdk.Api.Data.Policies.Enum; +/// +/// The sort order when making a Policy Request. +/// public enum PolicySortOrder { + /// + /// Sort by description. + /// Description, + + /// + /// Sort by recently created. + /// RecentlyCreated, } \ No newline at end of file diff --git a/src/Enclave.Sdk/Data/Policies/PolicyId.cs b/src/Enclave.Sdk/Data/Policies/PolicyId.cs index ecd7df8..6f8e191 100644 --- a/src/Enclave.Sdk/Data/Policies/PolicyId.cs +++ b/src/Enclave.Sdk/Data/Policies/PolicyId.cs @@ -2,6 +2,9 @@ namespace Enclave.Sdk.Api.Data.Policies; +/// +/// An int backed Policy Id. +/// [TypedId(IdBackingType.Int)] public partial struct PolicyId { diff --git a/src/Enclave.Sdk/Data/SystemId.cs b/src/Enclave.Sdk/Data/SystemId.cs new file mode 100644 index 0000000..4156752 --- /dev/null +++ b/src/Enclave.Sdk/Data/SystemId.cs @@ -0,0 +1,11 @@ +using TypedIds; + +namespace Enclave.Sdk.Api.Data; + +/// +/// A String backed System Id. +/// +[TypedId(IdBackingType.String)] +public partial struct SystemId +{ +} diff --git a/src/Enclave.Sdk/Data/SystemManagement/SystemReference.cs b/src/Enclave.Sdk/Data/SystemManagement/SystemReference.cs index a14eb27..fa24d19 100644 --- a/src/Enclave.Sdk/Data/SystemManagement/SystemReference.cs +++ b/src/Enclave.Sdk/Data/SystemManagement/SystemReference.cs @@ -1,4 +1,6 @@ -namespace Enclave.Sdk.Api.Data.SystemManagement; +using Enclave.Sdk.Api.Data.EnrolledSystems.Enum; + +namespace Enclave.Sdk.Api.Data.SystemManagement; /// /// Defines a system reference model. @@ -13,7 +15,7 @@ public class SystemReference /// /// The System ID. /// - public string Id { get; init; } + public string Id { get; init; } = default!; /// /// The local hostname of the system (if known). diff --git a/src/Enclave.Sdk/Data/Tags/TagQuerySortOrder.cs b/src/Enclave.Sdk/Data/Tags/TagQuerySortOrder.cs index d44057f..13c6d99 100644 --- a/src/Enclave.Sdk/Data/Tags/TagQuerySortOrder.cs +++ b/src/Enclave.Sdk/Data/Tags/TagQuerySortOrder.cs @@ -1,8 +1,22 @@ namespace Enclave.Sdk.Api.Data.Tags; +/// +/// The sort order used for a Tag Query. +/// public enum TagQuerySortOrder { + /// + /// Sort Alphabetically. + /// Alphabetical, + + /// + /// Sort by recently used Tags. + /// RecentlyUsed, + + /// + /// Sort by number of Referenced Systems. + /// ReferencedSystems, } \ No newline at end of file diff --git a/src/Enclave.Sdk/Data/UnaprrovedSystems/Enum/SystemType.cs b/src/Enclave.Sdk/Data/UnaprrovedSystems/Enum/SystemType.cs index 9aa78a2..a69868d 100644 --- a/src/Enclave.Sdk/Data/UnaprrovedSystems/Enum/SystemType.cs +++ b/src/Enclave.Sdk/Data/UnaprrovedSystems/Enum/SystemType.cs @@ -1,7 +1,19 @@ namespace Enclave.Sdk.Api.Data.UnaprrovedSystems.Enum; +/// +/// Defines the types of Enrolment Keys. +/// public enum SystemType { + /// + /// For workstations, laptops, servers, and other systems that are relatively long-lived or manually provisioned. + /// Systems remain in your Enclave Organisation if they stop running. + /// GeneralPurpose, + + /// + /// For containers, kubernetes pods, and other systems that are temporary, short-lived or automatically provisioned. + /// Systems are automatically removed from your Enclave Organisation when they stop/disconnect. + /// Ephemeral, } diff --git a/src/Enclave.Sdk/Data/UnaprrovedSystems/SystemId.cs b/src/Enclave.Sdk/Data/UnaprrovedSystems/SystemId.cs deleted file mode 100644 index 2906730..0000000 --- a/src/Enclave.Sdk/Data/UnaprrovedSystems/SystemId.cs +++ /dev/null @@ -1,8 +0,0 @@ -using TypedIds; - -namespace Enclave.Sdk.Api.Data.UnaprrovedSystems; - -[TypedId(IdBackingType.String)] -public partial struct SystemId -{ -} diff --git a/src/Enclave.Sdk/Data/UnaprrovedSystems/UnapprovedSystem.cs b/src/Enclave.Sdk/Data/UnaprrovedSystems/UnapprovedSystem.cs index d6e149b..5a4aa06 100644 --- a/src/Enclave.Sdk/Data/UnaprrovedSystems/UnapprovedSystem.cs +++ b/src/Enclave.Sdk/Data/UnaprrovedSystems/UnapprovedSystem.cs @@ -46,7 +46,12 @@ public class UnapprovedSystem /// /// The description of the enrolment key used to enrol the system. /// - public string? EnrolmentKeyDescription { get; init; } + public string EnrolmentKeyDescription { get; init; } = default!; + + /// + /// Any additional notes for the system. + /// + public string? Notes { get; init; } /// /// The locally-defined host name of the system. diff --git a/src/Enclave.Sdk/Data/UnaprrovedSystems/UnapprovedSystemDetail.cs b/src/Enclave.Sdk/Data/UnaprrovedSystems/UnapprovedSystemSummary.cs similarity index 89% rename from src/Enclave.Sdk/Data/UnaprrovedSystems/UnapprovedSystemDetail.cs rename to src/Enclave.Sdk/Data/UnaprrovedSystems/UnapprovedSystemSummary.cs index cd7d8af..148bd73 100644 --- a/src/Enclave.Sdk/Data/UnaprrovedSystems/UnapprovedSystemDetail.cs +++ b/src/Enclave.Sdk/Data/UnaprrovedSystems/UnapprovedSystemSummary.cs @@ -6,7 +6,7 @@ namespace Enclave.Sdk.Api.Data.UnaprrovedSystems; /// /// Model representing an unapproved system. /// -public class UnapprovedSystemDetail +public class UnapprovedSystemSummary { /// /// The system ID. @@ -46,12 +46,7 @@ public class UnapprovedSystemDetail /// /// The description of the enrolment key used to enrol the system. /// - public string EnrolmentKeyDescription { get; init; } = default!; - - /// - /// Any additional notes for the system. - /// - public string? Notes { get; init; } + public string? EnrolmentKeyDescription { get; init; } /// /// The locally-defined host name of the system. diff --git a/src/Enclave.Sdk/Exceptions/ProblemDetailsException.cs b/src/Enclave.Sdk/Exceptions/ProblemDetailsException.cs index af74bfc..676c931 100644 --- a/src/Enclave.Sdk/Exceptions/ProblemDetailsException.cs +++ b/src/Enclave.Sdk/Exceptions/ProblemDetailsException.cs @@ -1,15 +1,29 @@ namespace Enclave.Sdk.Api.Exceptions; -internal class ProblemDetailsException : Exception +/// +/// An Exception to display the details of an Http Problem Details. +/// +public class ProblemDetailsException : Exception { + /// + /// The Problem Details. + /// public ProblemDetails ProblemDetails { get; } + /// + /// The HttpResponse message. + /// public HttpResponseMessage Response { get; } + /// + /// Constructor for setting up the problem details exception. + /// + /// The problem details from the HTTP response. + /// The HTTP Response message. public ProblemDetailsException(ProblemDetails problemDetails, HttpResponseMessage response) - : base(problemDetails.Title) + : base(problemDetails?.Title) { - ProblemDetails = problemDetails; + ProblemDetails = problemDetails!; Response = response; } } \ No newline at end of file diff --git a/src/Enclave.Sdk/Handlers/ProblemDetailsHttpMessageHandler.cs b/src/Enclave.Sdk/Handlers/ProblemDetailsHttpMessageHandler.cs index 5bbedfb..b063236 100644 --- a/src/Enclave.Sdk/Handlers/ProblemDetailsHttpMessageHandler.cs +++ b/src/Enclave.Sdk/Handlers/ProblemDetailsHttpMessageHandler.cs @@ -7,7 +7,9 @@ internal sealed class ProblemDetailsHttpMessageHandler : DelegatingHandler { public ProblemDetailsHttpMessageHandler() #pragma warning disable CA2000 // Dispose objects before losing scope - : base(new HttpClientHandler()) { } + : base(new HttpClientHandler()) + { + } #pragma warning restore CA2000 // Dispose objects before losing scope protected override async Task SendAsync(HttpRequestMessage request, CancellationToken ct) diff --git a/tests/Enclave.Sdk.Api.Tests/Clients/DnsClientTests.cs b/tests/Enclave.Sdk.Api.Tests/Clients/DnsClientTests.cs index f1cd38e..86ae32d 100644 --- a/tests/Enclave.Sdk.Api.Tests/Clients/DnsClientTests.cs +++ b/tests/Enclave.Sdk.Api.Tests/Clients/DnsClientTests.cs @@ -68,11 +68,11 @@ public async Task Should_return_a_Dns_summary_when_calling_GetPropertiesSummaryA public async Task Should_return_a_paginated_response_model_when_calling_GetZonesAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new BasicDnsZone { Name = "test"} + new DnsZoneSummary { Name = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -97,11 +97,11 @@ public async Task Should_return_a_paginated_response_model_when_calling_GetZones public async Task Should_make_a_call_to_api_with_page_quertString_when_calling_GetZonesAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new BasicDnsZone { Name = "test"} + new DnsZoneSummary { Name = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -128,11 +128,11 @@ public async Task Should_make_a_call_to_api_with_page_quertString_when_calling_G public async Task Should_make_a_call_to_api_with_per_page_quertString_when_calling_GetZonesAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new BasicDnsZone { Name = "test"} + new DnsZoneSummary { Name = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -159,7 +159,7 @@ public async Task Should_make_a_call_to_api_with_per_page_quertString_when_calli public async Task Should_return_a_full_dns_zone_when_calling_CreateZoneAsync() { // Arrange - var response = new FullDnsZone + var response = new DnsZone { Id = DnsZoneId.FromInt(123), Name = "test", @@ -185,7 +185,7 @@ public async Task Should_return_a_full_dns_zone_when_calling_CreateZoneAsync() public async Task Should_return_a_full_dns_zone_when_calling_GetZoneAsync() { // Arrange - var response = new FullDnsZone + var response = new DnsZone { Id = DnsZoneId.FromInt(123), Name = "test", @@ -211,7 +211,7 @@ public async Task Should_return_a_full_dns_zone_when_calling_GetZoneAsync() public async Task Should_return_a_full_dns_zone_when_calling_UpdateZoneAsync() { // Arrange - var response = new FullDnsZone + var response = new DnsZone { Id = DnsZoneId.FromInt(123), Name = "New Name", @@ -239,7 +239,7 @@ public async Task Should_return_a_full_dns_zone_when_calling_UpdateZoneAsync() public async Task Should_return_a_full_dns_zone_when_calling_DeleteZoneAsync() { // Arrange - var response = new FullDnsZone + var response = new DnsZone { Id = DnsZoneId.FromInt(123), Name = "New Name", @@ -265,11 +265,11 @@ public async Task Should_return_a_full_dns_zone_when_calling_DeleteZoneAsync() public async Task Should_return_a_paginated_response_model_when_calling_GetRecordsAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new BasicDnsRecord { Name = "test"} + new DnsRecordSummary { Name = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -294,11 +294,11 @@ public async Task Should_return_a_paginated_response_model_when_calling_GetRecor public async Task Should_make_a_call_to_api_with_zoneId_quertString_when_calling_GetRecordsAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new BasicDnsRecord { Name = "test"} + new DnsRecordSummary { Name = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -325,11 +325,11 @@ public async Task Should_make_a_call_to_api_with_zoneId_quertString_when_calling public async Task Should_make_a_call_to_api_with_hostname_quertString_when_calling_GetRecordsAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new BasicDnsRecord { Name = "test"} + new DnsRecordSummary { Name = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -357,11 +357,11 @@ public async Task Should_make_a_call_to_api_with_hostname_quertString_when_calli public async Task Should_make_a_call_to_api_with_page_quertString_when_calling_GetRecordsAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new BasicDnsRecord { Name = "test"} + new DnsRecordSummary { Name = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -388,11 +388,11 @@ public async Task Should_make_a_call_to_api_with_page_quertString_when_calling_G public async Task Should_make_a_call_to_api_with_per_page_quertString_when_calling_GetRecordsAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new BasicDnsRecord { Name = "test"} + new DnsRecordSummary { Name = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -419,7 +419,7 @@ public async Task Should_make_a_call_to_api_with_per_page_quertString_when_calli public async Task Should_return_a_full_dns_record_model_when_calling_CreateRecordAsync() { // Arrange - var response = new FullDnsRecord + var response = new DnsRecord { Id = DnsRecordId.FromInt(123), Name = "Name", @@ -478,7 +478,7 @@ public async Task Should_return_full_dns_record_when_calling_GetRecordAsync() { // Arrange var id = DnsRecordId.FromInt(123); - var response = new FullDnsRecord + var response = new DnsRecord { Id = id, Name = "Name", @@ -505,7 +505,7 @@ public async Task Should_return_full_dns_record_when_calling_UpdateRecordAsync() { // Arrange var id = DnsRecordId.FromInt(123); - var response = new FullDnsRecord + var response = new DnsRecord { Id = id, Name = "New Name", @@ -535,7 +535,7 @@ public async Task Should_return_full_dns_record_when_calling_DeleteRecord() { // Arrange var id = DnsRecordId.FromInt(123); - var response = new FullDnsRecord + var response = new DnsRecord { Id = id, Name = "Name", diff --git a/tests/Enclave.Sdk.Api.Tests/Clients/EnrolledSystemClientTests.cs b/tests/Enclave.Sdk.Api.Tests/Clients/EnrolledSystemClientTests.cs new file mode 100644 index 0000000..a5610a2 --- /dev/null +++ b/tests/Enclave.Sdk.Api.Tests/Clients/EnrolledSystemClientTests.cs @@ -0,0 +1,470 @@ +using Enclave.Sdk.Api.Clients; +using Enclave.Sdk.Api.Data.Account; +using Enclave.Sdk.Api.Data.EnrolledSystems; +using Enclave.Sdk.Api.Data.Pagination; +using FluentAssertions; +using NUnit.Framework; +using System.Text.Json; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; +using WireMock.FluentAssertions; +using Enclave.Sdk.Api.Data.EnrolledSystems.Enum; +using Enclave.Sdk.Api.Data.Organisations; +using Enclave.Sdk.Api.Data; +using Enclave.Sdk.Api.Data.PatchModel; + +namespace Enclave.Sdk.Api.Tests.Clients; + +public class EnrolledSystemClientTests +{ + private EnrolledSystemsClient _enrolledSystemsClient; + private WireMockServer _server; + private string _orgRoute; + private JsonSerializerOptions _serializerOptions = new() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + + [SetUp] + public void Setup() + { + _server = WireMockServer.Start(); + + var httpClient = new HttpClient + { + BaseAddress = new Uri(_server.Urls[0]), + }; + + var organisationId = OrganisationId.New(); + _orgRoute = $"/org/{organisationId}"; + + _enrolledSystemsClient = new EnrolledSystemsClient(httpClient, $"org/{organisationId}"); + } + + [Test] + public async Task Should_return_a_paginated_response_model_when_calling_GetSystemsAsync() + { + // Arrange + var response = new PaginatedResponseModel + { + Items = new List + { + new EnrolledSystemSummary { Description = "test"} + }, + Links = new PaginationLinks(), + Metadata = new PaginationMetadata(), + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems").UsingGet()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + // Act + var result = await _enrolledSystemsClient.GetSystemsAsync(); + + // Assert + result.Should().NotBeNull(); + } + + [Test] + public async Task Should_make_a_call_to_api_with_enrolment_key_quertString_when_calling_GetSystemsAsync() + { + // Arrange + var response = new PaginatedResponseModel + { + Items = new List + { + new EnrolledSystemSummary { Description = "test"} + }, + Links = new PaginationLinks(), + Metadata = new PaginationMetadata(), + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems").UsingGet()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + var enrolmentKeyId = 123; + + // Act + await _enrolledSystemsClient.GetSystemsAsync(enrolmentKeyId: enrolmentKeyId); + + // Assert + _server.Should().HaveReceivedACall().AtAbsoluteUrl($"{_server.Urls[0]}{_orgRoute}/systems?enrolment_key={enrolmentKeyId}"); + } + + [Test] + public async Task Should_make_a_call_to_api_with_search_quertString_when_calling_GetSystemsAsync() + { + // Arrange + var response = new PaginatedResponseModel + { + Items = new List + { + new EnrolledSystemSummary { Description = "test"} + }, + Links = new PaginationLinks(), + Metadata = new PaginationMetadata(), + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems").UsingGet()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + var searchTerm = "term"; + + // Act + await _enrolledSystemsClient.GetSystemsAsync(searchTerm: searchTerm); + + // Assert + _server.Should().HaveReceivedACall().AtAbsoluteUrl($"{_server.Urls[0]}{_orgRoute}/systems?search={searchTerm}"); + } + + [Test] + public async Task Should_make_a_call_to_api_with_include_disabled_quertString_when_calling_GetSystemsAsync() + { + // Arrange + var response = new PaginatedResponseModel + { + Items = new List + { + new EnrolledSystemSummary { Description = "test"} + }, + Links = new PaginationLinks(), + Metadata = new PaginationMetadata(), + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems").UsingGet()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + var includeDisabled = true; + + // Act + await _enrolledSystemsClient.GetSystemsAsync(includeDisabled: includeDisabled); + + // Assert + _server.Should().HaveReceivedACall().AtAbsoluteUrl($"{_server.Urls[0]}{_orgRoute}/systems?include_disabled={includeDisabled}"); + } + + [Test] + public async Task Should_make_a_call_to_api_with_sort_quertString_when_calling_GetSystemsAsync() + { + // Arrange + var response = new PaginatedResponseModel + { + Items = new List + { + new EnrolledSystemSummary { Description = "test"} + }, + Links = new PaginationLinks(), + Metadata = new PaginationMetadata(), + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems").UsingGet()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + var sortOrder = SystemQuerySortMode.RecentlyConnected; + + // Act + await _enrolledSystemsClient.GetSystemsAsync(sortOrder: sortOrder); + + // Assert + _server.Should().HaveReceivedACall().AtAbsoluteUrl($"{_server.Urls[0]}{_orgRoute}/systems?sort={sortOrder}"); + } + + [Test] + public async Task Should_make_a_call_to_api_with_dns_quertString_when_calling_GetSystemsAsync() + { + // Arrange + var response = new PaginatedResponseModel + { + Items = new List + { + new EnrolledSystemSummary { Description = "test"} + }, + Links = new PaginationLinks(), + Metadata = new PaginationMetadata(), + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems").UsingGet()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + var dnsName = "test.dns"; + + // Act + await _enrolledSystemsClient.GetSystemsAsync(dnsName: dnsName); + + // Assert + _server.Should().HaveReceivedACall().AtAbsoluteUrl($"{_server.Urls[0]}{_orgRoute}/systems?dns={dnsName}"); + } + + [Test] + public async Task Should_make_a_call_to_api_with_page_quertString_when_calling_GetSystemsAsync() + { + // Arrange + var response = new PaginatedResponseModel + { + Items = new List + { + new EnrolledSystemSummary { Description = "test"} + }, + Links = new PaginationLinks(), + Metadata = new PaginationMetadata(), + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems").UsingGet()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + var page = 12; + + // Act + await _enrolledSystemsClient.GetSystemsAsync(pageNumber: page); + + // Assert + _server.Should().HaveReceivedACall().AtAbsoluteUrl($"{_server.Urls[0]}{_orgRoute}/systems?page={page}"); + } + + [Test] + public async Task Should_make_a_call_to_api_with_per_page_quertString_when_calling_GetSystemsAsync() + { + // Arrange + var response = new PaginatedResponseModel + { + Items = new List + { + new EnrolledSystemSummary { Description = "test"} + }, + Links = new PaginationLinks(), + Metadata = new PaginationMetadata(), + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems").UsingGet()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + var page = 12; + + // Act + await _enrolledSystemsClient.GetSystemsAsync(perPage: page); + + // Assert + _server.Should().HaveReceivedACall().AtAbsoluteUrl($"{_server.Urls[0]}{_orgRoute}/systems?per_page={page}"); + } + + [Test] + public async Task Should_return_number_of_revoked_systems_when_calling_RevokeSystemsAsync() + { + // Arrange + var response = new BulkSystemRevokedResult + { + SystemsRevoked = 2, + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems").UsingDelete()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + // Act + var result = await _enrolledSystemsClient.RevokeSystemsAsync(SystemId.FromString("asdf"), SystemId.FromString("asdf3")); + + // Assert + result.Should().Be(2); + } + + [Test] + public async Task Should_return_the_updated_system_when_calling_UpdateAsync() + { + // Arrange + var response = new EnrolledSystem + { + SystemId = SystemId.FromString("system1"), + Description = "new description", + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems/{response.SystemId}").UsingPatch()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + var builder = new PatchBuilder().Set(e => e.Description, "new description"); + + // Act + var result = await _enrolledSystemsClient.UpdateAsync(response.SystemId, builder); + + // Assert + result.Should().NotBeNull(); + result.Description.Should().Be(response.Description); + } + + [Test] + public async Task Should_return_the_revoked_system_when_calling_RevokeAsync() + { + // Arrange + var response = new EnrolledSystem + { + SystemId = SystemId.FromString("system1"), + Description = "description", + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems/{response.SystemId}").UsingDelete()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + // Act + var result = await _enrolledSystemsClient.RevokeAsync(response.SystemId); + + // Assert + result.Should().NotBeNull(); + result.SystemId.Should().Be(response.SystemId); + } + + [Test] + public async Task Should_return_the_enabled_system_when_calling_EnableAsync() + { + // Arrange + var response = new EnrolledSystem + { + SystemId = SystemId.FromString("system1"), + Description = "description", + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems/{response.SystemId}/enable").UsingPut()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + // Act + var result = await _enrolledSystemsClient.EnableAsync(response.SystemId); + + // Assert + result.Should().NotBeNull(); + result.SystemId.Should().Be(response.SystemId); + } + + [Test] + public async Task Should_return_the_disabled_system_when_calling_DisableAsync() + { + // Arrange + var response = new EnrolledSystem + { + SystemId = SystemId.FromString("system1"), + Description = "description", + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems/{response.SystemId}/disable").UsingPut()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + // Act + var result = await _enrolledSystemsClient.DisableAsync(response.SystemId); + + // Assert + result.Should().NotBeNull(); + result.SystemId.Should().Be(response.SystemId); + } + + [Test] + public async Task Should_return_number_of_enabled_systems_when_calling_BulkEnableAsync() + { + // Arrange + var response = new BulkSystemUpdateResult + { + SystemsUpdated = 2, + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems/enable").UsingPut()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + // Act + var result = await _enrolledSystemsClient.BulkEnableAsync(SystemId.FromString("asdf"), SystemId.FromString("asdf3")); + + // Assert + result.Should().Be(2); + } + + [Test] + public async Task Should_return_number_of_disabled_systems_when_calling_BulkDisableAsync() + { + // Arrange + var response = new BulkSystemUpdateResult + { + SystemsUpdated = 2, + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/systems/disable").UsingPut()) + .RespondWith( + Response.Create() + .WithSuccess() + .WithHeader("Content-Type", "application/json") + .WithBody(JsonSerializer.Serialize(response, _serializerOptions))); + + // Act + var result = await _enrolledSystemsClient.BulkDisableAsync(SystemId.FromString("asdf"), SystemId.FromString("asdf3")); + + // Assert + result.Should().Be(2); + } + + +} diff --git a/tests/Enclave.Sdk.Api.Tests/Clients/EnrolmentKeyClientTests.cs b/tests/Enclave.Sdk.Api.Tests/Clients/EnrolmentKeyClientTests.cs index 2e11759..b830ed9 100644 --- a/tests/Enclave.Sdk.Api.Tests/Clients/EnrolmentKeyClientTests.cs +++ b/tests/Enclave.Sdk.Api.Tests/Clients/EnrolmentKeyClientTests.cs @@ -46,11 +46,11 @@ public void Setup() public async Task Should_return_paginated_response_when_calling_GetEnrolmentKeysAsync() { // Arrange - var response = new PaginatedResponseModel() + var response = new PaginatedResponseModel() { - Items = new List + Items = new List { - new SimpleEnrolmentKey(), + new EnrolmentKeySummary(), }, }; @@ -75,11 +75,11 @@ public async Task Should_return_paginated_response_when_calling_GetEnrolmentKeys public async Task Should_make_call_to_api_with_search_queryString_when_calling_GetEnrolmentKeysAsync() { // Arrange - var response = new PaginatedResponseModel() + var response = new PaginatedResponseModel() { - Items = new List + Items = new List { - new SimpleEnrolmentKey(), + new EnrolmentKeySummary(), }, }; @@ -104,11 +104,11 @@ public async Task Should_make_call_to_api_with_search_queryString_when_calling_G public async Task Should_make_call_to_api_with_include_disabled_queryString_when_calling_GetEnrolmentKeysAsync() { // Arrange - var response = new PaginatedResponseModel() + var response = new PaginatedResponseModel() { - Items = new List + Items = new List { - new SimpleEnrolmentKey(), + new EnrolmentKeySummary(), }, }; @@ -133,11 +133,11 @@ public async Task Should_make_call_to_api_with_include_disabled_queryString_when public async Task Should_make_call_to_api_with_sort_queryString_when_calling_GetEnrolmentKeysAsync() { // Arrange - var response = new PaginatedResponseModel() + var response = new PaginatedResponseModel() { - Items = new List + Items = new List { - new SimpleEnrolmentKey(), + new EnrolmentKeySummary(), }, }; @@ -162,11 +162,11 @@ public async Task Should_make_call_to_api_with_sort_queryString_when_calling_Get public async Task Should_make_call_to_api_with_page_queryString_when_calling_GetEnrolmentKeysAsync() { // Arrange - var response = new PaginatedResponseModel() + var response = new PaginatedResponseModel() { - Items = new List + Items = new List { - new SimpleEnrolmentKey(), + new EnrolmentKeySummary(), }, }; @@ -191,11 +191,11 @@ public async Task Should_make_call_to_api_with_page_queryString_when_calling_Get public async Task Should_make_call_to_api_with_per_page_queryString_when_calling_GetEnrolmentKeysAsync() { // Arrange - var response = new PaginatedResponseModel() + var response = new PaginatedResponseModel() { - Items = new List + Items = new List { - new SimpleEnrolmentKey(), + new EnrolmentKeySummary(), }, }; @@ -220,7 +220,7 @@ public async Task Should_make_call_to_api_with_per_page_queryString_when_calling public async Task Should_return_a_full_enrolment_key_model_when_calling_CreateAsync() { // Arrange - var response = new FullEnrolmentKey(); + var response = new EnrolmentKey(); var createModel = new EnrolmentKeyCreate(); @@ -245,7 +245,7 @@ public async Task Should_return_a_full_enrolment_key_model_when_calling_CreateAs public async Task Should_return_a_full_enrolment_key_model_when_calling_GetAsync() { // Arrange - var response = new FullEnrolmentKey(); + var response = new EnrolmentKey(); var enrolmentKeyId = EnrolmentKeyId.FromInt(12); @@ -270,7 +270,7 @@ public async Task Should_return_a_full_enrolment_key_model_when_calling_GetAsync public async Task Should_return_a_full_enrolment_key_model_when_calling_UpdateAsync() { // Arrange - var response = new FullEnrolmentKey(); + var response = new EnrolmentKey(); var enrolmentKeyId = EnrolmentKeyId.FromInt(12); @@ -296,7 +296,7 @@ public async Task Should_return_a_full_enrolment_key_model_when_calling_UpdateAs public async Task Should_return_a_full_enrolment_key_model_when_calling_EnableAsync() { // Arrange - var response = new FullEnrolmentKey(); + var response = new EnrolmentKey(); var enrolmentKeyId = EnrolmentKeyId.FromInt(12); @@ -319,7 +319,7 @@ public async Task Should_return_a_full_enrolment_key_model_when_calling_EnableAs public async Task Should_return_a_full_enrolment_key_model_when_calling_DisableAsync() { // Arrange - var response = new FullEnrolmentKey(); + var response = new EnrolmentKey(); var enrolmentKeyId = EnrolmentKeyId.FromInt(12); diff --git a/tests/Enclave.Sdk.Api.Tests/Clients/LogsClientTests.cs b/tests/Enclave.Sdk.Api.Tests/Clients/LogsClientTests.cs new file mode 100644 index 0000000..50f3344 --- /dev/null +++ b/tests/Enclave.Sdk.Api.Tests/Clients/LogsClientTests.cs @@ -0,0 +1,125 @@ +using Enclave.Sdk.Api.Clients; +using Enclave.Sdk.Api.Data.Logging; +using Enclave.Sdk.Api.Data.Organisations; +using Enclave.Sdk.Api.Data.Pagination; +using NUnit.Framework; +using System.Text.Json; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; +using WireMock.FluentAssertions; +using FluentAssertions; + +namespace Enclave.Sdk.Api.Tests.Clients; + +public class LogsClientTests +{ + private LogsClient _logsClient; + private WireMockServer _server; + private string _orgRoute; + private JsonSerializerOptions _serializerOptions = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + + [SetUp] + public void Setup() + { + _server = WireMockServer.Start(); + + var httpClient = new HttpClient + { + BaseAddress = new Uri(_server.Urls[0]), + }; + + var organisationId = OrganisationId.New(); + _orgRoute = $"/org/{organisationId}"; + + + _logsClient = new LogsClient(httpClient, $"org/{organisationId}"); + } + + [Test] + public async Task Should_return_a_list_of_logs_in_pagination_format() + { + // Arrange + var responseModel = new PaginatedResponseModel + { + Items = new List + { + new LogEntry { }, + new LogEntry { }, + }, + Links = new PaginationLinks(), + Metadata = new PaginationMetadata(), + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/logs").UsingGet()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithBody(JsonSerializer.Serialize(responseModel, _serializerOptions))); + + // Act + var result = await _logsClient.GetLogsAsync(); + + // Assert + result.Should().NotBeNull(); + result.Items.Should().NotBeNull(); + } + + [Test] + public async Task Should_make_call_to_api_with_page_queryString() + { + // Arrange + var pageNumber = 1; + + var responseModel = new PaginatedResponseModel + { + Items = new List(), + Links = new PaginationLinks(), + Metadata = new PaginationMetadata(), + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/logs").UsingGet()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithBody(JsonSerializer.Serialize(responseModel, _serializerOptions))); + + // Act + var result = await _logsClient.GetLogsAsync(pageNumber: pageNumber); + + // Assert + _server.Should().HaveReceivedACall().AtAbsoluteUrl($"{_server.Urls[0]}{_orgRoute}/logs?page={pageNumber}"); + } + + [Test] + public async Task Should_make_call_to_api_with_per_page_queryString() + { + // Arrange + var perPage = 1; + + var responseModel = new PaginatedResponseModel + { + Items = new List(), + Links = new PaginationLinks(), + Metadata = new PaginationMetadata(), + }; + + _server + .Given(Request.Create().WithPath($"{_orgRoute}/logs").UsingGet()) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithBody(JsonSerializer.Serialize(responseModel, _serializerOptions))); + + // Act + var result = await _logsClient.GetLogsAsync(perPage: perPage); + + // Assert + _server.Should().HaveReceivedACall().AtAbsoluteUrl($"{_server.Urls[0]}{_orgRoute}/logs?per_page={perPage}"); + } +} diff --git a/tests/Enclave.Sdk.Api.Tests/Clients/UnapprovedSystemsClientTests.cs b/tests/Enclave.Sdk.Api.Tests/Clients/UnapprovedSystemsClientTests.cs index 9f20c36..df2cc8b 100644 --- a/tests/Enclave.Sdk.Api.Tests/Clients/UnapprovedSystemsClientTests.cs +++ b/tests/Enclave.Sdk.Api.Tests/Clients/UnapprovedSystemsClientTests.cs @@ -44,11 +44,11 @@ public UnapprovedSystemsClientTests() public async Task Should_return_a_paginated_response_model_when_calling_GetSystemsAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new UnapprovedSystem { Description = "test"} + new UnapprovedSystemSummary { Description = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -73,11 +73,11 @@ public async Task Should_return_a_paginated_response_model_when_calling_GetSyste public async Task Should_make_a_call_to_api_with_enrolment_key_quertString_when_calling_GetSystemsAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new UnapprovedSystem { Description = "test"} + new UnapprovedSystemSummary { Description = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -104,11 +104,11 @@ public async Task Should_make_a_call_to_api_with_enrolment_key_quertString_when_ public async Task Should_make_a_call_to_api_with_search_quertString_when_calling_GetSystemsAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new UnapprovedSystem { Description = "test"} + new UnapprovedSystemSummary { Description = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -136,11 +136,11 @@ public async Task Should_make_a_call_to_api_with_search_quertString_when_calling public async Task Should_make_a_call_to_api_with_sort_quertString_when_calling_GetSystemsAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new UnapprovedSystem { Description = "test"} + new UnapprovedSystemSummary { Description = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -167,11 +167,11 @@ public async Task Should_make_a_call_to_api_with_sort_quertString_when_calling_G public async Task Should_make_a_call_to_api_with_page_quertString_when_calling_GetSystemsAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new UnapprovedSystem { Description = "test"} + new UnapprovedSystemSummary { Description = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -198,11 +198,11 @@ public async Task Should_make_a_call_to_api_with_page_quertString_when_calling_G public async Task Should_make_a_call_to_api_with_per_page_quertString_when_calling_GetSystemsAsync() { // Arrange - var response = new PaginatedResponseModel + var response = new PaginatedResponseModel { - Items = new List + Items = new List { - new UnapprovedSystem { Description = "test"} + new UnapprovedSystemSummary { Description = "test"} }, Links = new PaginationLinks(), Metadata = new PaginationMetadata(), @@ -252,7 +252,7 @@ public async Task Should_return_number_of_declined_systems_when_calling_DeclineS public async Task Should_return_unapproved_system_detail_model_when_calling_GetAsync() { // Arrange - var response = new UnapprovedSystemDetail + var response = new UnapprovedSystem { SystemId = SystemId.FromString("newId"), }; @@ -277,7 +277,7 @@ public async Task Should_return_unapproved_system_detail_model_when_calling_GetA public async Task Should_return_unapproved_system_detail_model_when_calling_UpdateAsync() { // Arrange - var response = new UnapprovedSystemDetail + var response = new UnapprovedSystem { SystemId = SystemId.FromString("newId"), }; @@ -304,7 +304,7 @@ public async Task Should_return_unapproved_system_detail_model_when_calling_Upda public async Task Should_return_unapproved_system_detail_model_when_calling_DeclineAsync() { // Arrange - var response = new UnapprovedSystemDetail + var response = new UnapprovedSystem { SystemId = SystemId.FromString("newId"), }; @@ -329,7 +329,7 @@ public async Task Should_return_unapproved_system_detail_model_when_calling_Decl public async Task Should_not_throw_an_error_when_calling_ApproveAsync() { // Arrange - var response = new UnapprovedSystemDetail + var response = new UnapprovedSystem { SystemId = SystemId.FromString("newId"), };