Skip to content

Commit

Permalink
feat: changes OdataRepository implementation to obtain context servic…
Browse files Browse the repository at this point in the history
…e authentication token.
  • Loading branch information
lucianareginalino committed Jul 10, 2024
1 parent 500f661 commit 8f9c4b6
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 183 deletions.
4 changes: 2 additions & 2 deletions src/Liquid.Core/Liquid.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<Copyright>Avanade 2019</Copyright>
<PackageProjectUrl>https://github.com/Avanade/Liquid-Application-Framework</PackageProjectUrl>
<PackageIcon>logo.png</PackageIcon>
<Version>8.0.0-beta-06</Version>
<Version>8.0.0-beta-07</Version>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<ProjectGuid>{C33A89FC-4F4D-4274-8D0F-29456BA8F76B}</ProjectGuid>
<IsPackable>true</IsPackable>
Expand All @@ -28,7 +28,7 @@
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
<PackageReference Include="System.Memory.Data" Version="8.0.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Text.Json" Version="8.0.3" />
<PackageReference Include="System.Text.Json" Version="8.0.4" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Liquid.Core.Entities;
using Liquid.Core.Extensions.DependencyInjection;
using Liquid.Core.Implementations;
using Liquid.Core.Interfaces;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -30,6 +31,7 @@ public static IServiceCollection AddLiquidOdataRepository<TEntity, TIdentifier>(
where TEntity : LiquidEntity<TIdentifier>, new()
{
services.TryAddSingleton<IODataClientFactory, ODataClientFactory>();
services.TryAddSingleton<ILiquidContext, LiquidContext>();

services.AddOptions<ODataOptions>()
.Configure<IConfiguration>((settings, configuration) =>
Expand Down
3 changes: 1 addition & 2 deletions src/Liquid.Repository.OData/IODataClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public interface IODataClientFactory
/// Create an OData client.
/// </summary>
/// <param name="entityName">The entity name.</param>
/// <param name="token">Authorization token.</param>
IODataClient CreateODataClientAsync(string entityName, string token);
IODataClient CreateODataClientAsync(string entityName);
}
}
2 changes: 1 addition & 1 deletion src/Liquid.Repository.OData/Liquid.Repository.OData.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<Copyright>Avanade 2019</Copyright>
<PackageProjectUrl>https://github.com/Avanade/Liquid-Application-Framework</PackageProjectUrl>
<PackageIcon>logo.png</PackageIcon>
<Version>8.0.0-beta-02</Version>
<Version>8.0.0-beta-03</Version>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsPackable>true</IsPackable>
<DebugType>Full</DebugType>
Expand Down
18 changes: 15 additions & 3 deletions src/Liquid.Repository.OData/ODataClientFactory.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Extensions.Options;
using Liquid.Core.Interfaces;
using Microsoft.Extensions.Options;
using Simple.OData.Client;

namespace Liquid.Repository.OData
Expand All @@ -7,19 +8,30 @@ namespace Liquid.Repository.OData
public class ODataClientFactory : IODataClientFactory
{
private readonly IOptions<ODataOptions> _options;
private readonly ILiquidContext _context;

/// <summary>
/// Initialize a new instance of <see cref="ODataClientFactory"/>
/// </summary>
/// <param name="options"></param>
public ODataClientFactory(IOptions<ODataOptions> options)
/// <param name="context"></param>
public ODataClientFactory(IOptions<ODataOptions> options, ILiquidContext context)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
_context = context ?? throw new ArgumentNullException(nameof(context));
}

///<inheritdoc/>
public IODataClient CreateODataClientAsync(string entityName, string token)
public IODataClient CreateODataClientAsync(string entityName)
{
var token = _context.Get("OdataToken").ToString();

if (string.IsNullOrEmpty(token))
{
throw new InvalidOperationException("Token is required to perform this operation. The 'OdataToken' variable" +
" must be declared in the LiquidContext service.");
}

var settings = _options?.Value?.Settings.FirstOrDefault(x => x.EntityName == entityName);

Check warning on line 35 in src/Liquid.Repository.OData/ODataClientFactory.cs

View workflow job for this annotation

GitHub Actions / call-reusable-build-workflow / build

"Find" method should be used instead of the "FirstOrDefault" extension method. (https://rules.sonarsource.com/csharp/RSPEC-6602)

if (settings == null)
Expand Down
53 changes: 7 additions & 46 deletions src/Liquid.Repository.OData/ODataRepository.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Liquid.Core.Entities;
using Liquid.Core.Interfaces;
using Simple.OData.Client;
using System.Linq.Expressions;

namespace Liquid.Repository.OData
Expand All @@ -13,7 +12,6 @@ namespace Liquid.Repository.OData

private readonly IODataClientFactory _clientFactory;
private readonly string _entityName;
private string _token;

/// <summary>
/// Initialize a new instance of <see cref="ODataRepository{TEntity, TIdentifier}"/>
Expand All @@ -27,88 +25,51 @@ public ODataRepository(IODataClientFactory clientFactory, string entityName)
_entityName = entityName ?? throw new ArgumentNullException(nameof(entityName));
}

/// <summary>
/// Set the token to perform operations.
/// </summary>
/// <param name="token">Token to be set.</param>
public void SetToken(string token)
{
_token = token;
}

///<inheritdoc/>
public async Task AddAsync(TEntity entity)
{
if (string.IsNullOrEmpty(_token))
{
throw new InvalidOperationException("Token is required to perform this operation.");
}

var client = _clientFactory.CreateODataClientAsync(_entityName, _token);
{
var client = _clientFactory.CreateODataClientAsync(_entityName);

await client.For<TEntity>().Set(entity).InsertEntryAsync();
}

///<inheritdoc/>
public async Task<IEnumerable<TEntity>> FindAllAsync()
{
if (string.IsNullOrEmpty(_token))
{
throw new InvalidOperationException("Token is required to perform this operation.");
}

var client = _clientFactory.CreateODataClientAsync(_entityName, _token);
var client = _clientFactory.CreateODataClientAsync(_entityName);

return await client.For<TEntity>().FindEntriesAsync();
}

///<inheritdoc/>
public async Task<TEntity> FindByIdAsync(TIdentifier id)
{
if (string.IsNullOrEmpty(_token))
{
throw new InvalidOperationException("Token is required to perform this operation.");
}
var client = _clientFactory.CreateODataClientAsync(_entityName, _token);
var client = _clientFactory.CreateODataClientAsync(_entityName);

return await client.For<TEntity>().Key(id).FindEntryAsync();

Check warning on line 50 in src/Liquid.Repository.OData/ODataRepository.cs

View workflow job for this annotation

GitHub Actions / call-reusable-build-workflow / build

Possible null reference argument for parameter 'entryKey' in 'IBoundClient<TEntity> IFluentClient<TEntity, IBoundClient<TEntity>>.Key(params object[] entryKey)'.

Check warning on line 50 in src/Liquid.Repository.OData/ODataRepository.cs

View workflow job for this annotation

GitHub Actions / call-reusable-build-workflow / build

Review this call, which partially matches an overload without 'params'. The partial match is 'Simple.OData.Client.IBoundClient<TEntity> Simple.OData.Client.IFluentClient<TEntity, Simple.OData.Client.IBoundClient<TEntity>>.Key(IEnumerable<object> entryKey)'. (https://rules.sonarsource.com/csharp/RSPEC-3220)

Check warning on line 50 in src/Liquid.Repository.OData/ODataRepository.cs

View workflow job for this annotation

GitHub Actions / call-reusable-build-workflow / build

Possible null reference argument for parameter 'entryKey' in 'IBoundClient<TEntity> IFluentClient<TEntity, IBoundClient<TEntity>>.Key(params object[] entryKey)'.
}

///<inheritdoc/>
public async Task RemoveByIdAsync(TIdentifier id)
{
if (string.IsNullOrEmpty(_token))
{
throw new InvalidOperationException("Token is required to perform this operation.");
}

var client = _clientFactory.CreateODataClientAsync(_entityName, _token);
var client = _clientFactory.CreateODataClientAsync(_entityName);

await client.For<TEntity>().Key(id).DeleteEntryAsync();

Check warning on line 58 in src/Liquid.Repository.OData/ODataRepository.cs

View workflow job for this annotation

GitHub Actions / call-reusable-build-workflow / build

Possible null reference argument for parameter 'entryKey' in 'IBoundClient<TEntity> IFluentClient<TEntity, IBoundClient<TEntity>>.Key(params object[] entryKey)'.

Check warning on line 58 in src/Liquid.Repository.OData/ODataRepository.cs

View workflow job for this annotation

GitHub Actions / call-reusable-build-workflow / build

Review this call, which partially matches an overload without 'params'. The partial match is 'Simple.OData.Client.IBoundClient<TEntity> Simple.OData.Client.IFluentClient<TEntity, Simple.OData.Client.IBoundClient<TEntity>>.Key(IEnumerable<object> entryKey)'. (https://rules.sonarsource.com/csharp/RSPEC-3220)

Check warning on line 58 in src/Liquid.Repository.OData/ODataRepository.cs

View workflow job for this annotation

GitHub Actions / call-reusable-build-workflow / build

Possible null reference argument for parameter 'entryKey' in 'IBoundClient<TEntity> IFluentClient<TEntity, IBoundClient<TEntity>>.Key(params object[] entryKey)'.
}

///<inheritdoc/>
public async Task UpdateAsync(TEntity entity)
{
if (string.IsNullOrEmpty(_token))
{
throw new InvalidOperationException("Token is required to perform this operation.");
}

var client = _clientFactory.CreateODataClientAsync(_entityName, _token);
var client = _clientFactory.CreateODataClientAsync(_entityName);

await client.For<TEntity>().Set(entity).UpdateEntryAsync();
}

///<inheritdoc/>
public async Task<IEnumerable<TEntity>> WhereAsync(Expression<Func<TEntity, bool>> whereClause)
{
if (string.IsNullOrEmpty(_token))
{
throw new InvalidOperationException("Token is required to perform this operation.");
}

var client = _clientFactory.CreateODataClientAsync(_entityName, _token);
var client = _clientFactory.CreateODataClientAsync(_entityName);

return await client.For<TEntity>().Filter(whereClause).FindEntriesAsync();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Liquid.Core.Interfaces;
using Liquid.Core.Implementations;
using Liquid.Core.Interfaces;
using Liquid.Repository.OData.Extensions;
using Liquid.Repository.OData.Tests.Mock;
using Microsoft.Extensions.Configuration;
Expand Down
49 changes: 43 additions & 6 deletions test/Liquid.Repository.OData.Tests/ODataClientFactoryTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Liquid.Core.Interfaces;
using Microsoft.Extensions.Options;
using NSubstitute;

Expand All @@ -7,6 +8,7 @@ public class ODataClientFactoryTests
{
private IODataClientFactory _sut;
private IOptions<ODataOptions> _options;
private ILiquidContext _context;

public ODataClientFactoryTests()
{
Expand All @@ -26,26 +28,29 @@ public ODataClientFactoryTests()

_options.Value.Returns(settings);

_sut = new ODataClientFactory(_options);
_context = Substitute.For<ILiquidContext>();
_context.Get("OdataToken").Returns("token");

_sut = new ODataClientFactory(_options, _context);
}


[Fact]
public void ODataClientFactory_WhenEntityNameIsNotFound_ThrowException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => _sut.CreateODataClientAsync("TestEntities2", "token"));
Assert.Throws<ArgumentOutOfRangeException>(() => _sut.CreateODataClientAsync("TestEntities2"));
}

[Fact]
public void ODataClientFactory_WhenEntityNameIsNull_ThrowException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => _sut.CreateODataClientAsync(null, "token"));
Assert.Throws<ArgumentOutOfRangeException>(() => _sut.CreateODataClientAsync(null));
}

[Fact]
public void OdataClientFactory_WhenValidateCertIsFalse_ReturnClient()
{
var client = _sut.CreateODataClientAsync("TestEntities", "token");
var client = _sut.CreateODataClientAsync("TestEntities");

Assert.NotNull(client);
}
Expand All @@ -65,12 +70,44 @@ public void OdataClientFactory_WhenValidateCertIsTrue_ReturnClient()
Settings = new List<ODataSettings>() { settings }
});

var sut = new ODataClientFactory(_options);
var sut = new ODataClientFactory(_options, _context);

var client = sut.CreateODataClientAsync("TestEntities", "token");
var client = sut.CreateODataClientAsync("TestEntities");

Assert.NotNull(client);
}

[Fact]
public void OdataClientFactory_WhenTokenIsNotSet_ThrowException()
{
_context.Get("OdataToken").Returns("");

Assert.Throws<InvalidOperationException>(() => _sut.CreateODataClientAsync("TestEntities"));
}
[Fact]
public void OdataClientFactory_WhenTokenIsNull_ThrowException()
{
var context = Substitute.For<ILiquidContext>();

var sut = new ODataClientFactory(_options, context);

Assert.Throws<NullReferenceException>(() => sut.CreateODataClientAsync("TestEntities"));
}

[Fact]
public void OdataClientFactory_WhenOptionsIsNull_ThrowException()
{
_options = null;

Assert.Throws<ArgumentNullException>(() => new ODataClientFactory(_options, _context));
}

[Fact]
public void OdataClientFactory_WhenContextIsNull_ThrowException()
{
_context = null;

Assert.Throws<ArgumentNullException>(() => new ODataClientFactory(_options, _context));
}
}
}
Loading

0 comments on commit 8f9c4b6

Please sign in to comment.