Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DI-1345] Data Import 2.3 .NET 8 Update - Update Restharp #71

Merged
merged 2 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DataImport.Common/DataImport.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
</PackageReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="RestSharp" Version="106.15.0" />
<PackageReference Include="RestSharp" Version="110.2.0" />
<PackageReference Include="CsvHelper" Version="31.0.3" />
<PackageReference Include="Rijndael256" Version="3.2.0" />
<PackageReference Include="Serilog" Version="3.1.1" />
Expand Down
6 changes: 2 additions & 4 deletions DataImport.Common/Helpers/OAuthRequestWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public string GetAccessCode(ApiServer apiServer, string encryptionKey)
var authUrl = new Uri(apiServer.AuthUrl);
var oauthClient = new RestClient(authUrl.GetLeftPart(UriPartial.Authority));

var accessCodeRequest = new RestRequest(authUrl.AbsolutePath, Method.POST);
var accessCodeRequest = new RestRequest(authUrl.AbsolutePath, Method.Post);
var apiServerKey = !string.IsNullOrEmpty(encryptionKey)
? Decrypt(apiServer.Key, encryptionKey)
: apiServer.Key;
Expand Down Expand Up @@ -58,7 +58,7 @@ public string GetBearerToken(ApiServer apiServer, string encryptionKey, string a
var tokenUrl = new Uri(apiServer.TokenUrl);
var oauthClient = new RestClient(tokenUrl.GetLeftPart(UriPartial.Authority));

var bearerTokenRequest = new RestRequest(tokenUrl.AbsolutePath, Method.POST);
var bearerTokenRequest = new RestRequest(tokenUrl.AbsolutePath, Method.Post);

var apiServerKey = !string.IsNullOrEmpty(encryptionKey)
? Decrypt(apiServer.Key, encryptionKey)
Expand All @@ -79,9 +79,7 @@ public string GetBearerToken(ApiServer apiServer, string encryptionKey, string a
bearerTokenRequest.AddParameter("grant_type", "client_credentials");
}


var bearerTokenResponse = oauthClient.Execute<BearerTokenResponse>(bearerTokenRequest);

if (bearerTokenResponse.StatusCode != HttpStatusCode.OK)
throw new AuthenticationException("Unable to retrieve an access token. Error message: " +
bearerTokenResponse.ErrorMessage);
Expand Down
7 changes: 6 additions & 1 deletion DataImport.Common/Helpers/OdsApiTokenRetriever.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System;
using DataImport.Common.ExtensionMethods;
using DataImport.Models;
using System.Text.Json.Serialization;

namespace DataImport.Common.Helpers
{
Expand Down Expand Up @@ -45,9 +46,13 @@ internal class AccessCodeResponse

internal class BearerTokenResponse
{
[JsonPropertyName("access_token")]
public string AccessToken { get; set; }
public string ExpiresIn { get; set; }
[JsonPropertyName("expires_in")]
public int ExpiresIn { get; set; }
[JsonPropertyName("token_type")]
public string TokenType { get; set; }
[JsonPropertyName("error")]
public string Error { get; set; }
}
}
17 changes: 17 additions & 0 deletions DataImport.Common/IRestClientOptionsWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
// Licensed to the Ed-Fi Alliance under one or more agreements.
// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0.
// See the LICENSE and NOTICES files in the project root for more information.

using System;
using RestSharp.Authenticators;

namespace DataImport.EdFi.UnitTests.Api
{
public interface IRestClientOptionsWrapper
{
IAuthenticator Authenticator { get; set; }

Uri BaseUrl { get; set; }
}
}
32 changes: 32 additions & 0 deletions DataImport.Common/RestClientOptionsWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: Apache-2.0
// Licensed to the Ed-Fi Alliance under one or more agreements.
// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0.
// See the LICENSE and NOTICES files in the project root for more information.

using System;
using RestSharp;
using RestSharp.Authenticators;

namespace DataImport.EdFi.UnitTests.Api
{
public class RestClientOptionsWrapper : IRestClientOptionsWrapper
{
private readonly RestClientOptions _options;
public RestClientOptionsWrapper(RestClientOptions options)
{
_options = options;
}

public IAuthenticator Authenticator
{
get => _options.Authenticator;
set => _options.Authenticator = value;
}

public Uri BaseUrl
{
get => _options.BaseUrl;
set => _options.BaseUrl = value;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
// See the LICENSE and NOTICES files in the project root for more information.

using System;
using DataImport.Common.ExtensionMethods;
using DataImport.EdFi.Api.EnrollmentComposite;
using DataImport.Models;
using FakeItEasy;
using Microsoft.Extensions.Options;
using NUnit.Framework;
using RestSharp;
using RestSharp.Authenticators;
using Shouldly;

namespace DataImport.EdFi.UnitTests.Api.EnrollmentComposite
Expand All @@ -34,15 +38,16 @@ public void Given_suite2_version260_then_should_not_reset_client_url()
const string Year = "2199";

const string InitialUrl = "https://example.com";
var restClient = A.Fake<IRestClient>();
restClient.BaseUrl = new Uri(InitialUrl);
RestClientOptions options = new RestClientOptions();
options.BaseUrl = new Uri(InitialUrl);
var restClient = new RestClient(options);

// Act
var _ = new EnrollmentApiTss(restClient, ApiVersion, Year);
var enrollmentApi = new EnrollmentApiTss(restClient, ApiVersion, Year);

// Assert
restClient.BaseUrl.ShouldNotBeNull();
restClient.BaseUrl.ToString().ShouldBe($"{InitialUrl}/");
enrollmentApi.Client.Options.BaseUrl.ShouldNotBeNull();
enrollmentApi.Client.Options.BaseUrl.ToString().ShouldBe($"{InitialUrl}/");
}

[TestCase("3.1.1", "2129", "/composites/v1/2129/")]
Expand All @@ -54,16 +59,54 @@ public void Given_suite_3_then_should_modify_the_url(string apiVersion, string y
// Arrange
const string InitialUrl = "https://example.com/v3/data/";
const string ExpectedUrl = "https://example.com/v3";
RestClientOptions options = new RestClientOptions();
options.BaseUrl = new Uri(InitialUrl);
var restClient = new RestClient(options);

var restClient = A.Fake<IRestClient>();
restClient.BaseUrl = new Uri(InitialUrl);
// Act
var enrollmentApi = new EnrollmentApiTss(restClient, apiVersion, year);

// Assert
enrollmentApi.Client.Options.BaseUrl.ShouldNotBeNull();
enrollmentApi.Client.Options.BaseUrl.ToString().ShouldBe(ExpectedUrl);
}

[Test]
public void Given_suite2_version260_then_should_have_the_authenticator()
{
// Arrange
const string ApiVersion = "2.6.0";
const string Year = "2199";
const string InitialUrl = "https://example.com/v3/data/";
RestClientOptions options = new RestClientOptions();
options.BaseUrl = new Uri(InitialUrl);
options.Authenticator = A.Fake<IAuthenticator>();
var restClient = new RestClient(options);

// Act
var enrollmentApi = new EnrollmentApiTss(restClient, ApiVersion, Year);

// Assert
enrollmentApi.Client.Options.Authenticator.ShouldNotBeNull();
}

[TestCase("3.1.1", "2129")]
[TestCase("3.1.1", null)]
[TestCase("5.1.0", "2129")]
[TestCase("5.1.0", null)]
public void Given_suite_3_then_should_have_the_authenticator(string apiVersion, string year)
{
const string InitialUrl = "https://example.com/v3/data/";
RestClientOptions options = new RestClientOptions();
options.BaseUrl = new Uri(InitialUrl);
options.Authenticator = A.Fake<IAuthenticator>();
var restClient = new RestClient(options);

// Act
var _ = new EnrollmentApiTss(restClient, apiVersion, year);
var enrollmentApi = new EnrollmentApiTss(restClient, apiVersion, year);

// Assert
restClient.BaseUrl.ShouldNotBeNull();
restClient.BaseUrl.ToString().ShouldBe(ExpectedUrl);
enrollmentApi.Client.Options.Authenticator.ShouldNotBeNull();
}
}
}
10 changes: 6 additions & 4 deletions DataImport.EdFi/Api/DescriptorsApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,17 @@ public DescriptorsApi(IRestClient client)

public List<Descriptor> GetAllDescriptors(string descriptorPath, int? offset = null, int? limit = null)
{
var request = new RestRequest($"/{descriptorPath}", Method.GET) { RequestFormat = DataFormat.Json };
var request = new RestRequest($"/{descriptorPath}", Method.Get) { RequestFormat = DataFormat.Json };

if (offset != null)
request.AddParameter("offset", offset);
request.AddParameter("offset", offset, ParameterType.HttpHeader);
if (limit != null)
request.AddParameter("limit", limit);
request.AddParameter("limit", limit, ParameterType.HttpHeader);
request.AddHeader("Accept", "application/json");

var response = _client.Execute<List<Descriptor>>(request);
var clientExecute = _client.ExecuteAsync<List<Descriptor>>(request);
clientExecute.Wait();
var response = clientExecute.Result;
if (response.StatusCode == HttpStatusCode.NotFound)
throw new DescriptorNotFoundException(new Exception($"Descriptor '{descriptorPath}' could not be found."));

Expand Down
86 changes: 56 additions & 30 deletions DataImport.EdFi/Api/EnrollmentComposite/EnrollmentApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace DataImport.EdFi.Api.EnrollmentComposite
{
public class EnrollmentApi
{
protected readonly IRestClient Client;
public readonly IRestClient Client;
private readonly string _apiVersion;
private readonly IMapper _mapper;
protected readonly string CompositePath;
Expand All @@ -29,84 +29,110 @@ public EnrollmentApi(IRestClient client, string apiVersion, string year, IMapper
if (!apiVersion.IsOdsV2())
{
CompositePath = year == null ? "/composites/v1" : $"/composites/v1/{year}";
var baseUrl = Common.Helpers.UrlUtility.RemoveAfterLastInstanceOf(Client.BaseUrl.ToString().Trim(), "/data/");
Client.BaseUrl = new Uri(baseUrl);
var baseUrl = Common.Helpers.UrlUtility.RemoveAfterLastInstanceOf(Client.Options.BaseUrl.ToString().Trim(), "/data/");
var options = new RestClientOptions();
options.Authenticator = client.Options.Authenticator;
options.BaseUrl = new Uri(baseUrl);
Client = new RestClient(options);
}
}

public List<School> GetAllSchools(int? offset = null, int? limit = null)
{
var request = _apiVersion.IsOdsV2()
? new RestRequest("/enrollment/schools", Method.GET)
: new RestRequest($"{CompositePath}/ed-fi/enrollment/schools", Method.GET);
? new RestRequest("/enrollment/schools", Method.Get)
: new RestRequest($"{CompositePath}/ed-fi/enrollment/schools", Method.Get);
request.RequestFormat = DataFormat.Json;

if (offset != null)
request.AddParameter("offset", offset);
request.AddParameter("offset", offset, ParameterType.HttpHeader);
if (limit != null)
request.AddParameter("limit", limit);

return _apiVersion.IsOdsV2()
? Client.Execute<List<ModelsV25.EnrollmentComposite.School>>(request).Data
.Select(_mapper.Map<School>).ToList()
: Client.Execute<List<School>>(request).Data;
request.AddParameter("limit", limit, ParameterType.HttpHeader);
if (!_apiVersion.IsOdsV2())
{
var clientExecute =
Client.ExecuteAsync<List<School>>(request);
clientExecute.Wait();
return clientExecute.Result.Data;
}
else
{
var clientExecute =
Client.ExecuteAsync<List<ModelsV25.EnrollmentComposite.School>>(request);
clientExecute.Wait();
return clientExecute.Result.Data
.Select(_mapper.Map<School>).ToList();
}
}

public List<Section> GetSectionsBySchoolId(string schoolId, int? offset = null, int? limit = null)
{
var request = _apiVersion.IsOdsV2()
? new RestRequest("/enrollment/schools/{school_id}/sections", Method.GET)
: new RestRequest($"{CompositePath}/ed-fi/enrollment/schools/{{school_id}}/sections", Method.GET);
? new RestRequest("/enrollment/schools/{school_id}/sections", Method.Get)
: new RestRequest($"{CompositePath}/ed-fi/enrollment/schools/{{school_id}}/sections", Method.Get);
request.RequestFormat = DataFormat.Json;

request.AddUrlSegment("school_id", schoolId);
if (schoolId == null)
throw new ArgumentException("API method call is missing required parameters");
if (offset != null)
request.AddParameter("offset", offset);
request.AddParameter("offset", offset, ParameterType.HttpHeader);
if (limit != null)
request.AddParameter("limit", limit);
request.AddParameter("limit", limit, ParameterType.HttpHeader);

return _apiVersion.IsOdsV2()
? Client.Execute<List<ModelsV25.EnrollmentComposite.Section>>(request).Data
.Select(_mapper.Map<Section>).ToList()
: Client.Execute<List<Section>>(request).Data;
if (!_apiVersion.IsOdsV2())
{
var clientExecute = Client.ExecuteAsync<List<Section>>(request);
clientExecute.Wait();
return clientExecute.Result.Data;
}
else
{
var clientExecute = Client.ExecuteAsync<List<ModelsV25.EnrollmentComposite.Section>>(request);
clientExecute.Wait();
return clientExecute.Result.Data
.Select(_mapper.Map<Section>).ToList();
}
}

public List<Student> GetStudentsBySchoolId(string schoolId, int? offset = null, int? limit = null)
{
var request = _apiVersion.IsOdsV2()
? new RestRequest("/enrollment/schools/{school_id}/students", Method.GET)
: new RestRequest($"{CompositePath}/ed-fi/enrollment/schools/{{school_id}}/students", Method.GET);
? new RestRequest("/enrollment/schools/{school_id}/students", Method.Get)
: new RestRequest($"{CompositePath}/ed-fi/enrollment/schools/{{school_id}}/students", Method.Get);
request.RequestFormat = DataFormat.Json;

request.AddUrlSegment("school_id", schoolId);
if (schoolId == null)
throw new ArgumentException("API method call is missing required parameters");
if (offset != null)
request.AddParameter("offset", offset);
request.AddParameter("offset", offset, ParameterType.HttpHeader);
if (limit != null)
request.AddParameter("limit", limit);
var response = Client.Execute<List<Student>>(request);
request.AddParameter("limit", limit, ParameterType.HttpHeader);
var clientExecute = Client.ExecuteAsync<List<Student>>(request);
clientExecute.Wait();
var response = clientExecute.Result;

return response.Data;
}

public List<Staff> GetStaffsBySchoolId(string schoolId, int? offset = null, int? limit = null)
{
var request = _apiVersion.IsOdsV2()
? new RestRequest("/enrollment/schools/{school_id}/staffs", Method.GET)
: new RestRequest($"{CompositePath}/ed-fi/enrollment/schools/{{school_id}}/staffs", Method.GET);
? new RestRequest("/enrollment/schools/{school_id}/staffs", Method.Get)
: new RestRequest($"{CompositePath}/ed-fi/enrollment/schools/{{school_id}}/staffs", Method.Get);
request.RequestFormat = DataFormat.Json;

request.AddUrlSegment("school_id", schoolId);
if (schoolId == null)
throw new ArgumentException("API method call is missing required parameters");
if (offset != null)
request.AddParameter("offset", offset);
request.AddParameter("offset", offset, ParameterType.HttpHeader);
if (limit != null)
request.AddParameter("limit", limit);
var response = Client.Execute<List<Staff>>(request);
request.AddParameter("limit", limit, ParameterType.HttpHeader);
var clientExecute = Client.ExecuteAsync<List<Staff>>(request);
clientExecute.Wait();
var response = clientExecute.Result;

return response.Data;
}
Expand Down
Loading