Skip to content

Commit

Permalink
downstream sources tenants tags matching
Browse files Browse the repository at this point in the history
  • Loading branch information
pavel-zhur committed Jun 24, 2024
1 parent 005d771 commit 768c6a0
Show file tree
Hide file tree
Showing 22 changed files with 266 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ public Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post"
=> RunHandler(req, request);

protected override async Task<GetSongResponse> Execute(HttpRequest httpRequest, GetSongRequest request)
=> await _commonExecutions.GetSong(request);
=> await _commonExecutions.GetSong(request.ExternalId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ public Task<IActionResult> Run(

protected override async Task<GetSourcesAndExternalIdsResponse> Execute(HttpRequest httpRequest,
GetSourcesAndExternalIdsRequest request)
=> await _commonExecutions.GetSourcesAndExternalIds(request);
=> await _commonExecutions.GetSourcesAndExternalIds(request.Uris);
}
3 changes: 2 additions & 1 deletion HarmonyDB.Index/HarmonyDB.Index.Api/Functions/V1/Ping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using OneShelf.Common.Api.WithAuthorization;

namespace HarmonyDB.Index.Api.Functions.V1
{
Expand All @@ -24,7 +25,7 @@ public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Anonymou
{
_logger.LogInformation("C# HTTP trigger function processed a request.");

await Task.WhenAll(Enumerable.Range(0, _downstreamApiClient.DownstreamSourcesCount).Select(x => _downstreamApiClient.V1Ping(x)));
await _downstreamApiClient.PingAll();

var response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
using OneShelf.Common.Api.WithAuthorization;

namespace HarmonyDB.Index.Api.Functions.VDev;

Expand All @@ -14,13 +15,17 @@ public class IndexFunctions
private readonly DownstreamApiClient _downstreamApiClient;
private readonly ProgressionsCache _progressionsCache;
private readonly LoopsStatisticsCache _loopsStatisticsCache;
private readonly SecurityContext _securityContext;

public IndexFunctions(ILogger<IndexFunctions> logger, DownstreamApiClient downstreamApiClient, ProgressionsCache progressionsCache, LoopsStatisticsCache loopsStatisticsCache)
public IndexFunctions(ILogger<IndexFunctions> logger, DownstreamApiClient downstreamApiClient, ProgressionsCache progressionsCache, LoopsStatisticsCache loopsStatisticsCache, SecurityContext securityContext)
{
_logger = logger;
_downstreamApiClient = downstreamApiClient;
_progressionsCache = progressionsCache;
_loopsStatisticsCache = loopsStatisticsCache;
_securityContext = securityContext;

_securityContext.InitService();
}

[Function(nameof(VDevSaveProgressionsIndex))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
using Microsoft.Extensions.Logging;
using OneShelf.Common;
using OneShelf.Common.Api;
using OneShelf.Common.Api.WithAuthorization;

namespace HarmonyDB.Index.Api.Functions.VInternal;

public class GetLyrics : FunctionBase<GetLyricsRequest, GetLyricsResponse>
public class GetLyrics : ServiceFunctionBase<GetLyricsRequest, GetLyricsResponse>
{
private readonly CommonExecutions _commonExecutions;

public GetLyrics(ILoggerFactory loggerFactory, CommonExecutions commonExecutions)
: base(loggerFactory)
public GetLyrics(ILoggerFactory loggerFactory, CommonExecutions commonExecutions, SecurityContext securityContext)
: base(loggerFactory, securityContext)
{
_commonExecutions = commonExecutions;
}
Expand All @@ -26,17 +27,9 @@ public Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "post")

protected override async Task<GetLyricsResponse> Execute(GetLyricsRequest request)
{
var externalId = (await _commonExecutions.GetSourcesAndExternalIds(new()
{
Identity = null!,
Uris = new Uri(request.Url).Once().ToList(),
})).Attributes.Single().Value.ExternalId;
var externalId = (await _commonExecutions.GetSourcesAndExternalIds(new Uri(request.Url).Once().ToList())).Attributes.Single().Value.ExternalId;

var chords = (await _commonExecutions.GetSong(new()
{
Identity = null!,
ExternalId = externalId,
})).Song;
var chords = (await _commonExecutions.GetSong(externalId)).Song;

return new()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@
using Microsoft.Extensions.Logging;
using OneShelf.Common;
using OneShelf.Common.Api;
using OneShelf.Common.Api.WithAuthorization;
using System.Security;
using SecurityContext = OneShelf.Common.Api.WithAuthorization.SecurityContext;

namespace HarmonyDB.Index.Api.Functions.VInternal;

public class TryImport : FunctionBase<TryImportRequest, TryImportResponse>
public class TryImport : ServiceFunctionBase<TryImportRequest, TryImportResponse>
{
private readonly CommonExecutions _commonExecutions;

public TryImport(ILoggerFactory loggerFactory, CommonExecutions commonExecutions)
: base(loggerFactory)
public TryImport(ILoggerFactory loggerFactory, CommonExecutions commonExecutions, SecurityContext securityContext)
: base(loggerFactory, securityContext)
{
_commonExecutions = commonExecutions;
}
Expand All @@ -29,17 +32,9 @@ protected override async Task<TryImportResponse> Execute(TryImportRequest reques
{
try
{
var externalId = (await _commonExecutions.GetSourcesAndExternalIds(new()
{
Identity = null!,
Uris = new Uri(request.Url).Once().ToList(),
}))!.Attributes.Single().Value.ExternalId;
var externalId = (await _commonExecutions.GetSourcesAndExternalIds(new Uri(request.Url).Once().ToList())).Attributes.Single().Value.ExternalId;

var chords = (await _commonExecutions.GetSong(new()
{
Identity = null!,
ExternalId = externalId,
}))!.Song;
var chords = (await _commonExecutions.GetSong(externalId)).Song;

if (chords.Artists?.Count(x => !string.IsNullOrWhiteSpace(x)) is (null or 0) || string.IsNullOrWhiteSpace(chords.Title))
{
Expand Down
22 changes: 9 additions & 13 deletions HarmonyDB.Index/HarmonyDB.Index.Api/Functions/VPublic/GetPublic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@
using OneShelf.Collectives.Api.Model.VInternal;
using OneShelf.Common;
using OneShelf.Common.Api;
using OneShelf.Common.Api.WithAuthorization;
using System.Security;
using SecurityContext = OneShelf.Common.Api.WithAuthorization.SecurityContext;

namespace HarmonyDB.Index.Api.Functions.VPublic;

public class GetPublic : FunctionBase<GetPublicRequest, GetPublicResponse>
public class GetPublic : AnonymousFunctionBase<GetPublicRequest, GetPublicResponse>
{
private readonly CommonExecutions _commonExecutions;
private readonly CollectivesApiClient _collectivesApiClient;

public GetPublic(ILoggerFactory loggerFactory, CollectivesApiClient collectivesApiClient, CommonExecutions commonExecutions)
: base(loggerFactory)
public GetPublic(ILoggerFactory loggerFactory, CollectivesApiClient collectivesApiClient,
CommonExecutions commonExecutions, SecurityContext securityContext)
: base(loggerFactory, securityContext)
{
_collectivesApiClient = collectivesApiClient;
_commonExecutions = commonExecutions;
Expand All @@ -37,17 +41,9 @@ protected override async Task<GetPublicResponse> Execute(GetPublicRequest getPub
Chords chords;
try
{
var externalId = (await _commonExecutions.GetSourcesAndExternalIds(new()
{
Identity = null!,
Uris = new Uri(getPublicRequest.Url).Once().ToList(),
}))!.Attributes.Single().Value.ExternalId;
var externalId = (await _commonExecutions.GetSourcesAndExternalIds(new Uri(getPublicRequest.Url).Once().ToList())).Attributes.Single().Value.ExternalId;

chords = (await _commonExecutions.GetSong(new()
{
Identity = null!,
ExternalId = externalId,
}))!.Song;
chords = (await _commonExecutions.GetSong(externalId)).Song;

if (!chords.IsPublic)
return new()
Expand Down
14 changes: 6 additions & 8 deletions HarmonyDB.Index/HarmonyDB.Index.Api/Services/CommonExecutions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using HarmonyDB.Index.DownstreamApi.Client;
using HarmonyDB.Source.Api.Client;
using HarmonyDB.Source.Api.Model.V1.Api;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using OneShelf.Common;

Expand All @@ -18,10 +16,10 @@ public CommonExecutions(ILogger<CommonExecutions> logger, DownstreamApiClient do
_downstreamApiClient = downstreamApiClient;
}

public async Task<GetSourcesAndExternalIdsResponse> GetSourcesAndExternalIds(GetSourcesAndExternalIdsRequest request)
public async Task<GetSourcesAndExternalIdsResponse> GetSourcesAndExternalIds(IReadOnlyList<Uri> uris)
{
var results = await Task.WhenAll(Enumerable.Range(0, _downstreamApiClient.DownstreamSourcesCount)
.Select(x => _downstreamApiClient.V1GetSourcesAndExternalIds(request.Identity, x, request.Uris)));
var results = await Task.WhenAll(_downstreamApiClient.GetDownstreamSourceIndices(_ => true)
.Select(x => _downstreamApiClient.V1GetSourcesAndExternalIds(x, uris)));

var all = results
.WithIndices()
Expand All @@ -40,10 +38,10 @@ public async Task<GetSourcesAndExternalIdsResponse> GetSourcesAndExternalIds(Get
};
}

public async Task<GetSongResponse> GetSong(GetSongRequest request)
public async Task<GetSongResponse> GetSong(string externalId)
{
var sourceIndex = _downstreamApiClient.GetDownstreamSourceIndexByExternalId(request.ExternalId);
var getSongResponse = await _downstreamApiClient.V1GetSong(request.Identity, sourceIndex, request.ExternalId);
var sourceIndex = _downstreamApiClient.GetDownstreamSourceIndexByExternalId(externalId);
var getSongResponse = await _downstreamApiClient.V1GetSong(sourceIndex, externalId);
getSongResponse.Song.Source = _downstreamApiClient.GetSourceTitle(getSongResponse.Song.Source);
return getSongResponse;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,42 @@
using Microsoft.Extensions.Options;
using OneShelf.Authorization.Api.Model;
using OneShelf.Common;
using OneShelf.Common.Api.WithAuthorization;

namespace HarmonyDB.Index.DownstreamApi.Client;

public class DownstreamApiClient
{
private readonly SecurityContext _securityContext;
private readonly DownstreamApiClientOptions _options;
private readonly IReadOnlyList<SourceApiClient> _clients;

public DownstreamApiClient(IHttpClientFactory httpClientFactory, IOptions<DownstreamApiClientOptions> options)
public DownstreamApiClient(IHttpClientFactory httpClientFactory, IOptions<DownstreamApiClientOptions> options, SecurityContext securityContext)
{
_securityContext = securityContext;
_options = options.Value;

_clients = _options.DownstreamSources.Select(o => new SourceApiClient(o, httpClientFactory)).ToList();
}

public int GetDownstreamSourceIndexBySourceKey(string sourceKey) => _options.DownstreamSources.WithIndices().Single(s => s.x.Sources.Any(s => s.Key == sourceKey)).i;
public int GetDownstreamSourceIndexBySourceKey(string sourceKey) => _options.DownstreamSources.WithIndices().Where(x => IsAvailable(x.x)).First(s => s.x.Sources.Any(s => s.Key == sourceKey)).i;

public IEnumerable<int> GetDownstreamSourceIndices(Func<DownstreamApiClientOptions.DownstreamSourceOptions, bool> selector) => _options.DownstreamSources.WithIndices().Where(x => selector(x.x)).Select(x => x.i);

public int DownstreamSourcesCount => _options.DownstreamSources.Count;
public IEnumerable<int> GetDownstreamSourceIndices(Func<DownstreamApiClientOptions.DownstreamSourceOptions, bool> selector) => _options.DownstreamSources.WithIndices().Where(x => selector(x.x)).Where(x => IsAvailable(x.x)).Select(x => x.i);

public string GetSourceTitle(string sourceKey) => _options.DownstreamSources.SelectMany(x => x.Sources).Single(s => s.Key == sourceKey).Title;
public string GetSourceTitle(string sourceKey) => _options.DownstreamSources.Where(IsAvailable).SelectMany(x => x.Sources).Single(s => s.Key == sourceKey).Title;

public int GetDownstreamSourceIndexByExternalId(string externalId) => _options.DownstreamSources.WithIndices().Single(s => s.x.ExternalIdPrefixes.Any(externalId.StartsWith)).i;
public int GetDownstreamSourceIndexByExternalId(string externalId) => _options.DownstreamSources.WithIndices().Where(x => IsAvailable(x.x)).Single(s => s.x.ExternalIdPrefixes.Any(externalId.StartsWith)).i;

public async Task PingAll()
{
await Task.WhenAll(Enumerable.Range(0, _options.DownstreamSources.Count).Select(V1Ping));
}

public async Task<GetProgressionsIndexResponse> VInternalGetProgressionsIndex(int sourceIndex, GetProgressionsIndexRequest request, CancellationToken cancellationToken)
=> await _clients[sourceIndex].VInternalGetProgressionsIndex(request, cancellationToken);

public async Task<GetSongResponse> V1GetSong(Identity identity, int sourceIndex, string externalId)
=> await _clients[sourceIndex].V1GetSong(identity, externalId);
public async Task<GetSongResponse> V1GetSong(int sourceIndex, string externalId)
=> await _clients[sourceIndex].V1GetSong(_securityContext.OutputIdentity, externalId);

public async Task<GetSongsResponse> V1GetSongs(Identity identity, int sourceIndex, IReadOnlyList<string> externalIds)
=> await _clients[sourceIndex].V1GetSongs(identity, externalIds);
Expand All @@ -48,6 +54,17 @@ public async Task<SearchResponse> V1Search(int sourceIndex, SearchRequest reques
public async Task<SearchHeader> V1GetSearchHeader(Identity identity, int sourceIndex, string externalId)
=> await _clients[sourceIndex].V1GetSearchHeader(identity, externalId);

public async Task<Dictionary<string, UriAttributes>> V1GetSourcesAndExternalIds(Identity identity, int sourceIndex, IEnumerable<Uri> uris)
=> await _clients[sourceIndex].V1GetSourcesAndExternalIds(identity, uris);
public async Task<Dictionary<string, UriAttributes>> V1GetSourcesAndExternalIds(int sourceIndex, IEnumerable<Uri> uris)
=> await _clients[sourceIndex].V1GetSourcesAndExternalIds(_securityContext.OutputIdentity, uris);

private bool IsAvailable(DownstreamApiClientOptions.DownstreamSourceOptions downstreamOptions)
{
var tags = _securityContext.TenantTags;

if (downstreamOptions.TenantTagsForbidden.Intersect(tags).Any()) return false;

if (downstreamOptions.TenantTagsRequired.Any() && downstreamOptions.TenantTagsRequired.Any(x => !tags.Contains(x))) return false;

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ public class DownstreamSourceOptions : ApiClientOptions<SourceApiClient>

public required bool AreProgressionsProvidedForIndexing { get; init; }

public required List<string>? TenantTagsRequired { get; init; }
public required List<string> TenantTagsRequired { get; init; } = [];

public required List<string>? TenantTagsForbidden { get; init; }
public required List<string> TenantTagsForbidden { get; init; } = [];

public required List<string> ExternalIdPrefixes { get; set; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
Expand All @@ -17,6 +17,7 @@

<ItemGroup>
<ProjectReference Include="..\..\HarmonyDB.Source\HarmonyDB.Source.Api.Client\HarmonyDB.Source.Api.Client.csproj" />
<ProjectReference Include="..\..\OneShelf.Common\OneShelf.Common.Api.WithAuthorization\OneShelf.Common.Api.WithAuthorization.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ public AuthorizationApiClient(IHttpClientFactory httpClientFactory, IOptions<Aut
_options = options.Value;
}

public async Task<CheckIdentityResponse?> CheckIdentityRespectingCode(Identity identity)
{
if (identity.Hash == _options.ServiceCode)
{
return null;
}

return await CheckIdentity(identity);
}

public async Task<CheckIdentityResponse> CheckIdentity(Identity identity)
{
using var client = _httpClientFactory.CreateClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@
public class AuthorizationApiClientOptions
{
public Uri CheckIdentityEndpoint { get; set; }

public Uri PingEndpoint { get; set; }

public string ServiceCode { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Microsoft.Extensions.Logging;

namespace OneShelf.Common.Api.WithAuthorization;

public abstract class AnonymousFunctionBase<TRequest> : FunctionBase<TRequest>
{
private readonly SecurityContext _securityContext;

protected AnonymousFunctionBase(ILoggerFactory loggerFactory, SecurityContext securityContext)
: base(loggerFactory)
{
_securityContext = securityContext;
}

protected override void OnBeforeExecution()
{
base.OnBeforeExecution();
_securityContext.InitAnonymous();
}
}

public abstract class AnonymousFunctionBase<TRequest, TResponse> : FunctionBase<TRequest, TResponse>
{
private readonly SecurityContext _securityContext;

protected AnonymousFunctionBase(ILoggerFactory loggerFactory, SecurityContext securityContext) : base(loggerFactory)
{
_securityContext = securityContext;
}

protected override void OnBeforeExecution()
{
base.OnBeforeExecution();
_securityContext.InitAnonymous();
}
}
Loading

0 comments on commit 768c6a0

Please sign in to comment.