diff --git a/provisioning/service/src/Auth/ProvisioningSasCredential.cs b/provisioning/service/src/Auth/ProvisioningSasCredential.cs deleted file mode 100644 index c003148f6c..0000000000 --- a/provisioning/service/src/Auth/ProvisioningSasCredential.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -using Azure; -using Microsoft.Azure.Devices.Common.Service.Auth; - -namespace Microsoft.Azure.Devices.Provisioning.Service.Auth -{ - /// - /// Allows authentication to the API using a Shared Access Key provided by custom implementation. - /// The PnP client is auto generated from swagger and needs to implement a specific class to pass to the protocol layer - /// unlike the rest of the clients which are hand-written. So, this implementation for authentication is specific to digital twin (PnP). - /// - internal class ProvisioningSasCredential: IAuthorizationHeaderProvider - { - private readonly AzureSasCredential _azureSasCredential; - - public ProvisioningSasCredential(AzureSasCredential azureSasCredential) - { - _azureSasCredential = azureSasCredential; - } - - public string GetAuthorizationHeader() - { - return _azureSasCredential.Signature; - } - } -} diff --git a/provisioning/service/src/Auth/ProvisioningTokenCredential.cs b/provisioning/service/src/Auth/ProvisioningTokenCredential.cs deleted file mode 100644 index fe05a70ae6..0000000000 --- a/provisioning/service/src/Auth/ProvisioningTokenCredential.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading; -using Azure.Core; -using Microsoft.Azure.Devices.Common.Service.Auth; - -namespace Microsoft.Azure.Devices.Provisioning.Service.Auth -{ - /// - /// Allows authentication to the API using a JWT token generated for Azure active directory. - /// The PnP client is auto generated from swagger and needs to implement a specific class to pass to the protocol layer - /// unlike the rest of the clients which are hand-written. so, this implementation for authentication is specific to digital twin (PnP). - /// - internal class ProvisioningTokenCredential : IAuthorizationHeaderProvider - { - private readonly TokenCredential _credential; - private readonly object _tokenLock = new object(); - private AccessToken? _cachedAccessToken; - - public ProvisioningTokenCredential(TokenCredential credential) - { - _credential = credential; - } - - // The HTTP protocol uses this method to get the bearer token for authentication. - public string GetAuthorizationHeader() - { - lock (_tokenLock) - { - // A new token is generated if it is the first time or the cached token is close to expiry. - if (!_cachedAccessToken.HasValue - || TokenHelper.IsCloseToExpiry(_cachedAccessToken.Value.ExpiresOn)) - { - _cachedAccessToken = _credential.GetToken( - new TokenRequestContext(new string[] { "https://azure-devices-provisioning.net/.default" }), - new CancellationToken()); - } - } - - return $"Bearer {_cachedAccessToken.Value.Token}"; - } - } -} diff --git a/provisioning/service/src/Auth/TokenHelper.cs b/provisioning/service/src/Auth/TokenHelper.cs deleted file mode 100644 index f98c07eac3..0000000000 --- a/provisioning/service/src/Auth/TokenHelper.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; - -namespace Microsoft.Azure.Devices.Provisioning.Service.Auth -{ - internal static class TokenHelper - { - /// - /// Determines if the given token expiry date time is close to expiry. The date and time is - /// considered close to expiry if it has less than 10 minutes relative to the current time. - /// - /// The token expiration date and time. - /// True if the token expiry has less than 10 minutes relative to the current time, otherwise false. - public static bool IsCloseToExpiry(DateTimeOffset expiry) - { - TimeSpan timeToExpiry = expiry - DateTimeOffset.UtcNow; - return timeToExpiry.TotalMinutes < 10; - } - } -} diff --git a/provisioning/service/src/Manager/EnrollmentGroupManager.cs b/provisioning/service/src/Manager/EnrollmentGroupManager.cs index 08052420f1..9cddfe1fe7 100644 --- a/provisioning/service/src/Manager/EnrollmentGroupManager.cs +++ b/provisioning/service/src/Manager/EnrollmentGroupManager.cs @@ -109,8 +109,7 @@ await contractApiHttp.RequestAsync( } internal static Query CreateQuery( - string hostName, - IAuthorizationHeaderProvider headerProvider, + ServiceConnectionString provisioningConnectionString, QuerySpecification querySpecification, HttpTransportSettings httpTransportSettings, CancellationToken cancellationToken, @@ -129,7 +128,7 @@ internal static Query CreateQuery( /* SRS_ENROLLMENT_GROUP_MANAGER_28_015: [The CreateQuery shall return a new Query for EnrollmentGroup.] */ - return new Query(hostName, headerProvider, ServiceName, querySpecification, httpTransportSettings, pageSize, cancellationToken); + return new Query(provisioningConnectionString, ServiceName, querySpecification, httpTransportSettings, pageSize, cancellationToken); } private static Uri GetEnrollmentUri(string enrollmentGroupId) diff --git a/provisioning/service/src/Manager/IndividualEnrollmentManager.cs b/provisioning/service/src/Manager/IndividualEnrollmentManager.cs index 35f9bad5e3..c4c5d40c22 100644 --- a/provisioning/service/src/Manager/IndividualEnrollmentManager.cs +++ b/provisioning/service/src/Manager/IndividualEnrollmentManager.cs @@ -150,8 +150,7 @@ await contractApiHttp.RequestAsync( } internal static Query CreateQuery( - string hostName, - IAuthorizationHeaderProvider headerProvider, + ServiceConnectionString provisioningConnectionString, QuerySpecification querySpecification, HttpTransportSettings httpTransportSettings, CancellationToken cancellationToken, @@ -169,7 +168,7 @@ internal static Query CreateQuery( } /* SRS_INDIVIDUAL_ENROLLMENT_MANAGER_21_015: [The CreateQuery shall return a new Query for IndividualEnrollments.] */ - return new Query(hostName, headerProvider, ServiceName, querySpecification, httpTransportSettings, pageSize, cancellationToken); + return new Query(provisioningConnectionString, ServiceName, querySpecification, httpTransportSettings, pageSize, cancellationToken); } private static Uri GetEnrollmentUri(string registrationId) diff --git a/provisioning/service/src/Manager/RegistrationStatusManager.cs b/provisioning/service/src/Manager/RegistrationStatusManager.cs index 044b7128f2..cd786744ff 100644 --- a/provisioning/service/src/Manager/RegistrationStatusManager.cs +++ b/provisioning/service/src/Manager/RegistrationStatusManager.cs @@ -82,8 +82,7 @@ await contractApiHttp.RequestAsync( [SuppressMessage("Microsoft.Design", "CA1068", Justification = "Public API cannot change parameter order.")] internal static Query CreateEnrollmentGroupQuery( - string hostName, - IAuthorizationHeaderProvider headerProvider, + ServiceConnectionString provisioningConnectionString, QuerySpecification querySpecification, HttpTransportSettings httpTransportSettings, CancellationToken cancellationToken, @@ -103,8 +102,7 @@ internal static Query CreateEnrollmentGroupQuery( /* SRS_REGISTRATION_STATUS_MANAGER_28_010: [The CreateQuery shall return a new Query for DeviceRegistrationState.] */ return new Query( - hostName, - headerProvider, + provisioningConnectionString, GetGetDeviceRegistrationStatus(enrollmentGroupId), querySpecification, httpTransportSettings, diff --git a/provisioning/service/src/Microsoft.Azure.Devices.Provisioning.Service.csproj b/provisioning/service/src/Microsoft.Azure.Devices.Provisioning.Service.csproj index d1fa2e37d0..9e25d16aba 100644 --- a/provisioning/service/src/Microsoft.Azure.Devices.Provisioning.Service.csproj +++ b/provisioning/service/src/Microsoft.Azure.Devices.Provisioning.Service.csproj @@ -56,7 +56,6 @@ - all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/provisioning/service/src/ProvisioningServiceClient.cs b/provisioning/service/src/ProvisioningServiceClient.cs index 216627b733..df4c53e24e 100644 --- a/provisioning/service/src/ProvisioningServiceClient.cs +++ b/provisioning/service/src/ProvisioningServiceClient.cs @@ -5,10 +5,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Azure; -using Azure.Core; using Microsoft.Azure.Devices.Common.Service.Auth; -using Microsoft.Azure.Devices.Provisioning.Service.Auth; namespace Microsoft.Azure.Devices.Provisioning.Service { @@ -68,12 +65,8 @@ namespace Microsoft.Azure.Devices.Provisioning.Service public class ProvisioningServiceClient : IDisposable { private readonly ServiceConnectionString _provisioningConnectionString; - private readonly ProvisioningTokenCredential _provisioningTokenCredential; - private readonly ProvisioningSasCredential _provisioningSasCredential; private readonly IContractApiHttp _contractApiHttp; - private string _hostName; - /// /// Create a new instance of the ProvisioningServiceClient that exposes /// the API to the Device Provisioning Service. @@ -111,75 +104,6 @@ public static ProvisioningServiceClient CreateFromConnectionString(string connec return new ProvisioningServiceClient(connectionString, httpTransportSettings); } - /// - /// Create a new instance of the ProvisioningServiceClient from the provided hostName and TokenCredential - /// that exposes the API to the Device Provisioning Service. - /// - /// - /// The string that carries the hostName that will be used for this object - /// The TokenCredential that provides authentication for this object - /// The ProvisioningServiceClient with the new instance of this object. - /// if the credential is null - public static ProvisioningServiceClient Create(string hostName, TokenCredential credential) - { - return ProvisioningServiceClient.Create(hostName, credential, new HttpTransportSettings()); - } - - /// - /// Create a new instance of the ProvisioningServiceClient from the provided hostName and TokenCredential - /// that exposes the API to the Device Provisioning Service. - /// - /// - /// The string that carries the hostName that will be used for this object - /// The TokenCredential that provides authentication for this object - /// Specifies the HTTP transport settings for the request - /// The ProvisioningServiceClient with the new instance of this object. - /// if the credential is null - public static ProvisioningServiceClient Create(string hostName, TokenCredential credential, HttpTransportSettings httpTransportSettings) - { - if (credential == null) - { - throw new ArgumentNullException(nameof(credential), "Parameter cannot be null"); - } - - return new ProvisioningServiceClient(hostName, credential, httpTransportSettings); - } - - /// - /// Create a new instance of the ProvisioningServiceClient from the provided hostName and TokenCredential - /// that exposes the API to the Device Provisioning Service. - /// - /// - /// The string that carries the host name that will be used for this object - /// The AzureSasCredential that provides authentication for this object - /// The ProvisioningServiceClient with the new instance of this object. - /// if the azureSasCredential is null - public static ProvisioningServiceClient Create(string hostName, AzureSasCredential azureSasCredential) - { - return ProvisioningServiceClient.Create(hostName, azureSasCredential, new HttpTransportSettings()); - } - - /// - /// Create a new instance of the ProvisioningServiceClient from the provided hostName and TokenCredential - /// that exposes the API to the Device Provisioning Service. - /// - /// - /// The string that carries the host name that will be used for this object - /// The AzureSasCredential that provides authentication for this object - /// Specifies the HTTP transport settings for the request - /// The ProvisioningServiceClient with the new instance of this object. - /// if the azureSasCredential is null - public static ProvisioningServiceClient Create(string hostName, AzureSasCredential azureSasCredential, HttpTransportSettings httpTransportSettings) - { - if (azureSasCredential == null) - { - throw new ArgumentNullException(nameof(azureSasCredential), "Parameter cannot be null"); - } - - return new ProvisioningServiceClient(hostName, azureSasCredential, httpTransportSettings); - } - - /// /// PRIVATE CONSTRUCTOR /// @@ -197,43 +121,12 @@ private ProvisioningServiceClient(string connectionString, HttpTransportSettings /* SRS_PROVISIONING_SERVICE_CLIENT_21_003: [The constructor shall throw ArgumentException if the ProvisioningConnectionString or one of the inner Managers failed to create a new instance.] */ /* SRS_PROVISIONING_SERVICE_CLIENT_21_004: [The constructor shall create a new instance of the ContractApiHttp class using the provided connectionString.] */ _provisioningConnectionString = ServiceConnectionString.Parse(connectionString); - _hostName = _provisioningConnectionString.HostName; _contractApiHttp = new ContractApiHttp( _provisioningConnectionString.HttpsEndpoint, _provisioningConnectionString, httpTransportSettings); } - private ProvisioningServiceClient(string hostName, TokenCredential credential, HttpTransportSettings httpTransportSettings) - { - if (string.IsNullOrWhiteSpace(hostName ?? throw new ArgumentNullException(nameof(hostName)))) - { - throw new ArgumentException($"{nameof(hostName)} cannot be empty string"); - } - - _provisioningTokenCredential = new ProvisioningTokenCredential(credential); - _hostName = hostName; - _contractApiHttp = new ContractApiHttp( - new UriBuilder("https", _hostName).Uri, - _provisioningTokenCredential, - httpTransportSettings); - } - - private ProvisioningServiceClient(string hostName, AzureSasCredential azureSasCredential, HttpTransportSettings httpTransportSettings) - { - if (string.IsNullOrWhiteSpace(hostName ?? throw new ArgumentNullException(nameof(hostName)))) - { - throw new ArgumentException($"{nameof(hostName)} cannot be empty string"); - } - - _provisioningSasCredential = new ProvisioningSasCredential(azureSasCredential); - _hostName = hostName; - _contractApiHttp = new ContractApiHttp( - new UriBuilder("https", _hostName).Uri, - _provisioningSasCredential, - httpTransportSettings); - } - /// /// Dispose the Provisioning Service Client and its dependencies. /// @@ -579,8 +472,7 @@ public Query CreateIndividualEnrollmentQuery(QuerySpecification querySpecificati { /* SRS_PROVISIONING_SERVICE_CLIENT_21_014: [The CreateIndividualEnrollmentQuery shall create a new individual enrollment query by calling the CreateQuery in the IndividualEnrollmentManager.] */ return IndividualEnrollmentManager.CreateQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, new HttpTransportSettings(), CancellationToken.None); @@ -604,8 +496,7 @@ public Query CreateIndividualEnrollmentQuery(QuerySpecification querySpecificati { /* SRS_PROVISIONING_SERVICE_CLIENT_21_014: [The CreateIndividualEnrollmentQuery shall create a new individual enrollment query by calling the CreateQuery in the IndividualEnrollmentManager.] */ return IndividualEnrollmentManager.CreateQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, httpTransportSettings, CancellationToken.None); @@ -629,8 +520,7 @@ public Query CreateIndividualEnrollmentQuery(QuerySpecification querySpecificati { /* SRS_PROVISIONING_SERVICE_CLIENT_21_014: [The CreateIndividualEnrollmentQuery shall create a new individual enrollment query by calling the CreateQuery in the IndividualEnrollmentManager.] */ return IndividualEnrollmentManager.CreateQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, new HttpTransportSettings(), cancellationToken); @@ -658,8 +548,7 @@ public Query CreateIndividualEnrollmentQuery(QuerySpecification querySpecificati { /* SRS_PROVISIONING_SERVICE_CLIENT_21_015: [The CreateIndividualEnrollmentQuery shall create a new individual enrollment query by calling the CreateQuery in the IndividualEnrollmentManager.] */ return IndividualEnrollmentManager.CreateQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, new HttpTransportSettings(), CancellationToken.None, @@ -689,8 +578,7 @@ public Query CreateIndividualEnrollmentQuery(QuerySpecification querySpecificati { /* SRS_PROVISIONING_SERVICE_CLIENT_21_015: [The CreateIndividualEnrollmentQuery shall create a new individual enrollment query by calling the CreateQuery in the IndividualEnrollmentManager.] */ return IndividualEnrollmentManager.CreateQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, new HttpTransportSettings(), cancellationToken, @@ -720,8 +608,7 @@ public Query CreateIndividualEnrollmentQuery(QuerySpecification querySpecificati { /* SRS_PROVISIONING_SERVICE_CLIENT_21_015: [The CreateIndividualEnrollmentQuery shall create a new individual enrollment query by calling the CreateQuery in the IndividualEnrollmentManager.] */ return IndividualEnrollmentManager.CreateQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, httpTransportSettings, CancellationToken.None, @@ -968,8 +855,7 @@ public Query CreateEnrollmentGroupQuery(QuerySpecification querySpecification) { /* SRS_PROVISIONING_SERVICE_CLIENT_21_021: [The createEnrollmentGroupQuery shall create a new enrolmentGroup query by calling the createQuery in the EnrollmentGroupManager.] */ return EnrollmentGroupManager.CreateQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, new HttpTransportSettings(), CancellationToken.None); @@ -993,8 +879,7 @@ public Query CreateEnrollmentGroupQuery(QuerySpecification querySpecification, H { /* SRS_PROVISIONING_SERVICE_CLIENT_21_021: [The createEnrollmentGroupQuery shall create a new enrolmentGroup query by calling the createQuery in the EnrollmentGroupManager.] */ return EnrollmentGroupManager.CreateQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, httpTransportSettings, CancellationToken.None); @@ -1018,8 +903,7 @@ public Query CreateEnrollmentGroupQuery(QuerySpecification querySpecification, C { /* SRS_PROVISIONING_SERVICE_CLIENT_21_021: [The createEnrollmentGroupQuery shall create a new enrolmentGroup query by calling the createQuery in the EnrollmentGroupManager.] */ return EnrollmentGroupManager.CreateQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, new HttpTransportSettings(), cancellationToken); @@ -1047,8 +931,7 @@ public Query CreateEnrollmentGroupQuery(QuerySpecification querySpecification, i { /* SRS_PROVISIONING_SERVICE_CLIENT_21_022: [The createEnrollmentGroupQuery shall create a new enrolmentGroup query by calling the createQuery in the EnrollmentGroupManager.] */ return EnrollmentGroupManager.CreateQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, new HttpTransportSettings(), CancellationToken.None, @@ -1078,8 +961,7 @@ public Query CreateEnrollmentGroupQuery(QuerySpecification querySpecification, i { /* SRS_PROVISIONING_SERVICE_CLIENT_21_022: [The createEnrollmentGroupQuery shall create a new enrolmentGroup query by calling the createQuery in the EnrollmentGroupManager.] */ return EnrollmentGroupManager.CreateQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, new HttpTransportSettings(), cancellationToken, @@ -1109,8 +991,7 @@ public Query CreateEnrollmentGroupQuery(QuerySpecification querySpecification, i { /* SRS_PROVISIONING_SERVICE_CLIENT_21_022: [The createEnrollmentGroupQuery shall create a new enrolmentGroup query by calling the createQuery in the EnrollmentGroupManager.] */ return EnrollmentGroupManager.CreateQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, httpTransportSettings, CancellationToken.None, @@ -1297,8 +1178,7 @@ public Query CreateEnrollmentGroupRegistrationStateQuery(QuerySpecification quer { /* SRS_PROVISIONING_SERVICE_CLIENT_21_027: [The createEnrollmentGroupRegistrationStateQuery shall create a new DeviceRegistrationState query by calling the createQuery in the registrationStatusManager.] */ return RegistrationStatusManager.CreateEnrollmentGroupQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, new HttpTransportSettings(), CancellationToken.None, @@ -1323,8 +1203,7 @@ public Query CreateEnrollmentGroupRegistrationStateQuery(QuerySpecification quer { /* SRS_PROVISIONING_SERVICE_CLIENT_21_027: [The createEnrollmentGroupRegistrationStateQuery shall create a new DeviceRegistrationState query by calling the createQuery in the registrationStatusManager.] */ return RegistrationStatusManager.CreateEnrollmentGroupQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, httpTransportSettings, CancellationToken.None, @@ -1352,8 +1231,7 @@ public Query CreateEnrollmentGroupRegistrationStateQuery( { /* SRS_PROVISIONING_SERVICE_CLIENT_21_027: [The createEnrollmentGroupRegistrationStateQuery shall create a new DeviceRegistrationState query by calling the createQuery in the registrationStatusManager.] */ return RegistrationStatusManager.CreateEnrollmentGroupQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, new HttpTransportSettings(), cancellationToken, @@ -1383,8 +1261,7 @@ public Query CreateEnrollmentGroupRegistrationStateQuery(QuerySpecification quer { /* SRS_PROVISIONING_SERVICE_CLIENT_21_028: [The createEnrollmentGroupRegistrationStateQuery shall create a new DeviceRegistrationState query by calling the createQuery in the registrationStatusManager.] */ return RegistrationStatusManager.CreateEnrollmentGroupQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, new HttpTransportSettings(), CancellationToken.None, @@ -1420,8 +1297,7 @@ public Query CreateEnrollmentGroupRegistrationStateQuery( { /* SRS_PROVISIONING_SERVICE_CLIENT_21_028: [The createEnrollmentGroupRegistrationStateQuery shall create a new DeviceRegistrationState query by calling the createQuery in the registrationStatusManager.] */ return RegistrationStatusManager.CreateEnrollmentGroupQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, httpTransportSettings, CancellationToken.None, @@ -1457,8 +1333,7 @@ public Query CreateEnrollmentGroupRegistrationStateQuery( { /* SRS_PROVISIONING_SERVICE_CLIENT_21_028: [The createEnrollmentGroupRegistrationStateQuery shall create a new DeviceRegistrationState query by calling the createQuery in the registrationStatusManager.] */ return RegistrationStatusManager.CreateEnrollmentGroupQuery( - _hostName, - GetHeaderProvider(), + _provisioningConnectionString, querySpecification, new HttpTransportSettings(), cancellationToken, @@ -1493,12 +1368,5 @@ public Task GetEnrollmentGroupAttestationAsync(string enro { return EnrollmentGroupManager.GetEnrollmentAttestationAsync(_contractApiHttp, enrollmentGroupId, cancellationToken); } - - internal IAuthorizationHeaderProvider GetHeaderProvider() - { - return _provisioningConnectionString - ?? (IAuthorizationHeaderProvider) _provisioningTokenCredential - ?? _provisioningSasCredential; - } } } diff --git a/provisioning/service/src/Query.cs b/provisioning/service/src/Query.cs index b548845891..47e6d03b60 100644 --- a/provisioning/service/src/Query.cs +++ b/provisioning/service/src/Query.cs @@ -80,86 +80,50 @@ internal Query( int pageSize, CancellationToken cancellationToken) { + /* SRS_QUERY_21_001: [The constructor shall throw ArgumentNullException if the provided serviceConnectionString is null.] */ if (serviceConnectionString == null) { throw new ArgumentNullException(nameof(serviceConnectionString)); } + /* SRS_QUERY_21_002: [The constructor shall throw ArgumentException if the provided serviceName is null or empty.] */ if (string.IsNullOrWhiteSpace(serviceName ?? throw new ArgumentNullException(nameof(serviceName)))) { throw new ArgumentException($"{nameof(serviceName)} cannot be an empty string"); } + /* SRS_QUERY_21_003: [The constructor shall throw ArgumentException if the provided querySpecification is null.] */ if (querySpecification == null) { throw new ArgumentNullException(nameof(querySpecification)); } + /* SRS_QUERY_21_004: [The constructor shall throw ArgumentException if the provided pageSize is negative.] */ if (pageSize < 0) { throw new ArgumentException($"{nameof(pageSize)} cannot be negative."); } // TODO: Refactor ContractApiHttp being created again + /* SRS_QUERY_21_005: [The constructor shall create and store a `contractApiHttp` using the provided Service Connection String.] */ _contractApiHttp = new ContractApiHttp( serviceConnectionString.HttpsEndpoint, serviceConnectionString, httpTransportSettings); + /* SRS_QUERY_21_006: [The constructor shall store the provided `pageSize`, and `cancelationToken`.] */ PageSize = pageSize; _cancellationToken = cancellationToken; + /* SRS_QUERY_21_007: [The constructor shall create and store a JSON from the provided querySpecification.] */ _querySpecificationJson = JsonConvert.SerializeObject(querySpecification); + /* SRS_QUERY_21_008: [The constructor shall create and store a queryPath adding `/query` to the provided `targetPath`.] */ _queryPath = GetQueryUri(serviceName); + /* SRS_QUERY_21_009: [The constructor shall set continuationToken and current as null.] */ ContinuationToken = null; - _hasNext = true; - } - - internal Query( - string hostName, - IAuthorizationHeaderProvider headerProvider, - string serviceName, - QuerySpecification querySpecification, - HttpTransportSettings httpTransportSettings, - int pageSize, - CancellationToken cancellationToken) - { - if (hostName == null) - { - throw new ArgumentNullException(nameof(hostName)); - } - - if (string.IsNullOrWhiteSpace(serviceName ?? throw new ArgumentNullException(nameof(serviceName)))) - { - throw new ArgumentException($"{nameof(serviceName)} cannot be an empty string"); - } - - if (querySpecification == null) - { - throw new ArgumentNullException(nameof(querySpecification)); - } - - if (pageSize < 0) - { - throw new ArgumentException($"{nameof(pageSize)} cannot be negative."); - } - - // TODO: Refactor ContractApiHttp being created again - _contractApiHttp = new ContractApiHttp( - new UriBuilder("https", hostName).Uri, - headerProvider, httpTransportSettings); - - PageSize = pageSize; - _cancellationToken = cancellationToken; - - _querySpecificationJson = JsonConvert.SerializeObject(querySpecification); - - _queryPath = GetQueryUri(serviceName); - - ContinuationToken = null; - + /* SRS_QUERY_21_010: [The constructor shall set hasNext as true.] */ _hasNext = true; } @@ -196,14 +160,17 @@ public bool HasNext() /// if the query does no have more pages to return. public async Task NextAsync(string continuationToken) { + /* SRS_QUERY_21_011: [The next shall throw IndexOutOfRangeException if the provided continuationToken is null or empty.] */ if (string.IsNullOrWhiteSpace(continuationToken)) { throw new IndexOutOfRangeException($"There is no {nameof(continuationToken)} to get pending elements."); } + /* SRS_QUERY_21_012: [The next shall store the provided continuationToken.] */ ContinuationToken = continuationToken; _hasNext = true; + /* SRS_QUERY_21_013: [The next shall return the next page of results by calling the next().] */ return await NextAsync().ConfigureAwait(false); } @@ -214,21 +181,25 @@ public async Task NextAsync(string continuationToken) /// if the query does no have more pages to return. public async Task NextAsync() { + /* SRS_QUERY_21_014: [The next shall throw IndexOutOfRangeException if the hasNext is false.] */ if (!_hasNext) { throw new IndexOutOfRangeException("There are no more pending elements"); } + /* SRS_QUERY_21_015: [If the pageSize is not 0, the next shall send the HTTP request with `x-ms-max-item-count=[pageSize]` in the header.] */ IDictionary headerParameters = new Dictionary(); if (PageSize != 0) { headerParameters.Add(PageSizeHeaderKey, PageSize.ToString(CultureInfo.InvariantCulture)); } + /* SRS_QUERY_21_016: [If the continuationToken is not null or empty, the next shall send the HTTP request with `x-ms-continuation=[continuationToken]` in the header.] */ if (!string.IsNullOrWhiteSpace(ContinuationToken)) { headerParameters.Add(ContinuationTokenHeaderKey, ContinuationToken); } + /* SRS_QUERY_21_017: [The next shall send a HTTP request with a HTTP verb `POST`.] */ ContractApiResponse httpResponse = await _contractApiHttp.RequestAsync( HttpMethod.Post, _queryPath, @@ -237,10 +208,12 @@ public async Task NextAsync() null, _cancellationToken).ConfigureAwait(false); + /* SRS_QUERY_21_018: [The next shall create and return a new instance of the QueryResult using the `x-ms-item-type` as type, `x-ms-continuation` as the next continuationToken, and the message body.] */ httpResponse.Fields.TryGetValue(ItemTypeHeaderKey, out string type); httpResponse.Fields.TryGetValue(ContinuationTokenHeaderKey, out string continuationToken); ContinuationToken = continuationToken; + /* SRS_QUERY_21_017: [The next shall set hasNext as true if the continuationToken is not null, or false if it is null.] */ _hasNext = (ContinuationToken != null); var result = new QueryResult(type, httpResponse.Body, ContinuationToken);