Skip to content

Commit

Permalink
refactor(EF)!: remove useless specialized stores
Browse files Browse the repository at this point in the history
BREAKING CHANGE: EF SchemeDefinition doesn't exist any more. ExtenalProvider
is used instead. The DB schema changes
  • Loading branch information
github-actions committed Apr 21, 2021
1 parent ae2c3fc commit 3b48e80
Show file tree
Hide file tree
Showing 49 changed files with 1,955 additions and 306 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,27 @@ public static DynamicAuthenticationBuilder AddTheIdServerHttpStore(this DynamicA
public static DynamicAuthenticationBuilder AddTheIdServerHttpStore<TSchemeDefinition>(this DynamicAuthenticationBuilder builder, Func<IServiceProvider, Task<HttpClient>> getHttpClient = null)
where TSchemeDefinition : SchemeDefinitionBase, new()
{
var services = builder.Services;
services
.AddTransient<IDynamicProviderStore<TSchemeDefinition>, DynamicProviderStore<TSchemeDefinition>>()
.AddTransient<IAuthenticationSchemeOptionsSerializer, AuthenticationSchemeOptionsSerializer>();
builder.AddTheIdServerStore<TSchemeDefinition>();
if (getHttpClient != null)
{
services.AddIdentityServer4AdminHttpStores(getHttpClient);
builder.Services.AddIdentityServer4AdminHttpStores(getHttpClient);
}
return builder;
}

public static DynamicAuthenticationBuilder AddTheIdServerStore(this DynamicAuthenticationBuilder builder)
{
return builder.AddTheIdServerStore<SchemeDefinition>();
}

public static DynamicAuthenticationBuilder AddTheIdServerStore<TSchemeDefinition>(this DynamicAuthenticationBuilder builder)
where TSchemeDefinition : SchemeDefinitionBase, new()
{
builder.Services
.AddTransient<IDynamicProviderStore<TSchemeDefinition>, DynamicProviderStore<TSchemeDefinition>>()
.AddTransient<IAuthenticationSchemeOptionsSerializer, AuthenticationSchemeOptionsSerializer>();

return builder;
}
}
}
23 changes: 5 additions & 18 deletions src/Aguacongas.TheIdServer.Identity/UserOnlyStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,10 @@ public async override Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> clai
AssertNotNull(claims, nameof(claims));

var userClaims = await GetUserClaimsAsync(user).ConfigureAwait(false);
var toRemove = userClaims.Where(c => claims.Any(cl => cl.Type == c.ClaimType && cl.Value == c.ClaimValue));
var toRemove = userClaims.Items.Where(c => claims.Any(cl => cl.Type == c.ClaimType && cl.Value == c.ClaimValue));
foreach (var claim in toRemove)
{
await _claimStore.DeleteAsync(claim.Id.ToString(), cancellationToken).ConfigureAwait(false);
await _claimStore.DeleteAsync(claim.Id, cancellationToken).ConfigureAwait(false);
}
}

Expand Down Expand Up @@ -617,13 +617,12 @@ protected override async Task SaveUserTokensAsync(TUser user, IEnumerable<Identi
}
}

protected virtual async Task<List<IdentityUserClaim<string>>> GetUserClaimsAsync(TUser user)
protected virtual Task<PageResponse<UserClaim>> GetUserClaimsAsync(TUser user)
{
var response = await _claimStore.GetAsync(new PageRequest
return _claimStore.GetAsync(new PageRequest
{
Filter = $"{nameof(UserClaim.UserId)} eq '{user.Id}'"
}).ConfigureAwait(false);
return response.Items.Select(CreateIdentityUserClaim).ToList();
});
}

protected virtual async Task<List<IdentityUserLogin<string>>> GetUserLoginsAsync(string userId)
Expand All @@ -646,18 +645,6 @@ private IdentityUserToken<string> IdentityUserToken(UserToken entity)
};
}

private IdentityUserClaim<string> CreateIdentityUserClaim(UserClaim entity)
{
return new IdentityUserClaim<string>
{
UserId = entity.UserId,
ClaimType = entity.ClaimType,
ClaimValue = entity.ClaimValue,

Id = int.Parse(entity.Id)
};
}

private static IdentityUserLogin<string> CreateIdentityUserLogin(UserLogin entity)
{
return new IdentityUserLogin<string>
Expand Down
3 changes: 1 addition & 2 deletions src/Aguacongas.TheIdServer/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"LETSENCRYPT": "let's encrypt"
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5443;http://localhost:5000"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ public ExternalController(
[HttpGet]
public async Task<IActionResult> Challenge(string provider, string returnUrl)
{
if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/";
if (string.IsNullOrEmpty(returnUrl))
{
returnUrl = "~/";
}

// validate returnUrl - either it is a valid OIDC URL or back to a local page
if (!Url.IsLocalUrl(returnUrl) && !_interaction.IsValidReturnUrl(returnUrl))
Expand Down
10 changes: 6 additions & 4 deletions src/Aguacongas.TheIdServer/SeedData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ namespace Aguacongas.TheIdServer
static class SeedData
{
public static void EnsureSeedData(IConfiguration configuration)
{

{
var services = new ServiceCollection();
var startup = new Startup(configuration, null);
startup.ConfigureServices(services);
Expand All @@ -44,8 +43,11 @@ public static void EnsureSeedData(IConfiguration configuration)
appcontext.Database.Migrate();
}

SeedUsers(scope, configuration);
SeedConfiguration(scope, configuration);
if (configuration.GetValue<bool>("Seed"))
{
SeedUsers(scope, configuration);
SeedConfiguration(scope, configuration);
}
}

public static void SeedConfiguration(IServiceScope scope, IConfiguration configuration)
Expand Down
37 changes: 7 additions & 30 deletions src/Aguacongas.TheIdServer/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,26 +158,8 @@ void configureOptions(IdentityServerOptions options)
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});

if (isProxy)
{
mvcBuilder.AddIdentityServerAdmin<ApplicationUser, Auth.SchemeDefinition>()
.AddTheIdServerHttpStore();
}
else if (DbType == DbTypes.RavenDb)
{
mvcBuilder.AddIdentityServerAdmin<ApplicationUser, RavenDbStore.SchemeDefinition>()
.AddRavenDbStore();
}
else if (DbType == DbTypes.MongoDb)
{
mvcBuilder.AddIdentityServerAdmin<ApplicationUser, Auth.SchemeDefinition>()
.AddMongoDbStore();
}
else
{
mvcBuilder.AddIdentityServerAdmin<ApplicationUser, SchemeDefinition>()
.AddEntityFrameworkStore<ConfigurationDbContext>();
}
mvcBuilder.AddIdentityServerAdmin<ApplicationUser, Auth.SchemeDefinition>()
.AddTheIdServerStore();

services.AddRemoteAuthentication<RemoteAuthenticationState, RemoteUserAccount, OidcProviderOptions>();
services.AddScoped<LazyAssemblyLoader>()
Expand Down Expand Up @@ -301,22 +283,17 @@ public void Configure(IApplicationBuilder app)
endpoints.MapFallbackToPage("/_Host");
});

LoadDynamicConfiguration(app, isProxy);
LoadDynamicConfiguration(app);
}

private void LoadDynamicConfiguration(IApplicationBuilder app, bool isProxy)
private void LoadDynamicConfiguration(IApplicationBuilder app)
{
if (isProxy || DbType == DbTypes.MongoDb)
{
app.LoadDynamicAuthenticationConfiguration<Auth.SchemeDefinition>();
return;
}
if (DbType == DbTypes.RavenDb)
{
app.LoadDynamicAuthenticationConfiguration<RavenDbStore.SchemeDefinition>();
return;
}
app.LoadDynamicAuthenticationConfiguration<SchemeDefinition>();
app.LoadDynamicAuthenticationConfiguration<Auth.SchemeDefinition>();
}

private void AddForceHttpsSchemeMiddleware(IApplicationBuilder app)
Expand Down Expand Up @@ -468,9 +445,9 @@ private void AddDefaultServices(IServiceCollection services)
}
else
{
services.AddTransient<ISchemeChangeSubscriber, SchemeChangeSubscriber<SchemeDefinition>>()
services.AddTransient<ISchemeChangeSubscriber, SchemeChangeSubscriber<Auth.SchemeDefinition>>()
.AddIdentityServer4AdminEntityFrameworkStores(options => options.UseDatabaseFromConfiguration(Configuration))
.AddConfigurationEntityFrameworkStores(options => options.UseDatabaseFromConfiguration(Configuration))
.AddConfigurationEntityFrameworkStores<Auth.SchemeDefinition>(options => options.UseDatabaseFromConfiguration(Configuration))
.AddOperationalEntityFrameworkStores(options => options.UseDatabaseFromConfiguration(Configuration));

identityBuilder.AddTheIdServerStores();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ protected async Task SetSelectedValue(string value)
protected override void OnParametersSet()
{
base.OnParametersSet();
_fieldIdentifier = base.FieldIdentifier;
_fieldIdentifier = FieldIdentifier;
}

protected override void OnInitialized()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Aguacongas.IdentityServer.Store;
using Aguacongas.IdentityServer.Store.Entity;
using Aguacongas.TheIdServer.BlazorApp.Infrastructure.Services;
using Aguacongas.TheIdServer.BlazorApp.Models;
using Aguacongas.TheIdServer.BlazorApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
Expand Down Expand Up @@ -81,13 +82,7 @@ protected Task OnFilterChanged(string filter)
return;
}
var propertyArray = SelectProperties.Split(',');
var expressionArray = new string[propertyArray.Length];
for (int i = 0; i < propertyArray.Length; i++)
{
expressionArray[i] = $"contains({propertyArray[i]},'{filter.Replace("'", "''")}')";
}
_pageRequest.Filter = string.Join(" or ", expressionArray);
_pageRequest.Filter = CreateRequestFilter(filter);
var page = await AdminStore.GetAsync(_pageRequest, token)
.ConfigureAwait(false);
Expand All @@ -99,6 +94,17 @@ await InvokeAsync(() => StateHasChanged())
}, TaskScheduler.Default);
}

protected virtual string CreateRequestFilter(string filter)
{
var propertyArray = SelectProperties.Split(',');
var expressionArray = new string[propertyArray.Length];
for (int i = 0; i < propertyArray.Length; i++)
{
expressionArray[i] = $"contains({propertyArray[i]},'{filter.Replace("'", "''")}')";
}
return string.Join(" or ", expressionArray);
}

protected void OnItemSelected(string id, bool isSelected)
{
if (isSelected)
Expand Down Expand Up @@ -136,15 +142,14 @@ private async Task GetEntityList(PageRequest pageRequest)
EntityList = page.Items;
}

private async Task GridState_OnHeaderClicked(Models.SortEventArgs e)
private async Task GridState_OnHeaderClicked(SortEventArgs e)
{
_pageRequest.OrderBy = e.OrderBy;
await GetEntityList(_pageRequest)
.ConfigureAwait(false);
StateHasChanged();
}


#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Project: Aguafrommars/TheIdServer
// Copyright (c) 2021 @Olivier Lefebvre
using Aguacongas.AspNetCore.Authentication;
using Aguacongas.IdentityServer.Store;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -46,6 +47,11 @@ public ExternalProvider Clone()

public static ExternalProvider FromEntity(Entity.ExternalProvider externalProvider)
{
if (string.IsNullOrEmpty(externalProvider.KindName))
{
var handlerTypeName = JsonSerializer.Deserialize<HandlerType>(externalProvider.SerializedHandlerType);
externalProvider.KindName = handlerTypeName.Name.Split('.').Last().Replace("Handler", "");
}
var optionsType = GetOptionsType(externalProvider);
return new ExternalProvider
{
Expand All @@ -65,10 +71,15 @@ private static TOptions Deserialize(string options, Type optionsType)
}

private static Type GetOptionsType(Entity.ExternalProvider externalProvider)
{
{
var typeName = $"{typeof(RemoteAuthenticationOptions).Namespace}.{externalProvider.KindName}Options";
var assembly = AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetType(typeName) != null);
return assembly.GetType(typeName);
}

class HandlerType
{
public string Name { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public partial class IdentityProvider
protected override void OnParametersSet()
{
base.OnParametersSet();
_isReadOnly = Entity.Provider != null;
_isReadOnly = Entity.Id != null;
}

protected override async Task OnInitializedAsync()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
GridState="GridState" />
</th>
<th class="w-25" scope="col">
<SortableHeader Property="KindName"
<SortableHeader Property="SerializedHandlerType"
Text="@Localizer["type"]"
GridState="GridState" />
</th>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Project: Aguafrommars/TheIdServer
// Copyright (c) 2021 @Olivier Lefebvre
using Aguacongas.TheIdServer.BlazorApp.Models;
using Entity = Aguacongas.IdentityServer.Store.Entity;

namespace Aguacongas.TheIdServer.BlazorApp.Pages.ExternalProviders
Expand All @@ -9,5 +10,10 @@ public partial class ExternalProviders
protected override string SelectProperties => $"{nameof(Entity.ExternalProvider.Id)},{nameof(Entity.ExternalProvider.DisplayName)},{nameof(Entity.ExternalProvider.KindName)}";

protected override string ExportExpand => $"{nameof(Models.ExternalProvider.ClaimTransformations)}";

protected override string CreateRequestFilter(string filter)
{
return base.CreateRequestFilter(filter).Replace(nameof(Entity.ExternalProvider.KindName), nameof(Entity.ExternalProvider.SerializedHandlerType));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Localization;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
Expand Down Expand Up @@ -219,7 +218,7 @@ public static void AddIdentityServerAdminFilters(this MvcOptions options)
{
var filters = options.Filters;
filters.Add<FormatFilter>();
filters.Add<SelectFilter>();
filters.Add<ExternalProviderFilter>();
filters.Add<ExceptionFilter>();
filters.Add<ActionsFilter>();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Project: Aguafrommars/TheIdServer
// Copyright (c) 2021 @Olivier Lefebvre
using Aguacongas.AspNetCore.Authentication;
using Aguacongas.IdentityServer.Store;
using Aguacongas.IdentityServer.Store.Entity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Threading.Tasks;

namespace Aguacongas.IdentityServer.Admin.Filters
{
class ExternalProviderFilter : IAsyncResultFilter
{
private readonly IAuthenticationSchemeOptionsSerializer _serializer;
public ExternalProviderFilter(IAuthenticationSchemeOptionsSerializer serializer)
{
_serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
}
public Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
var result = context.Result as ObjectResult;
var value = result?.Value;
if (value is PageResponse<ExternalProvider> page)
{
foreach (var item in page.Items)
{
SetKindName(item);
}
} else if (value is ExternalProvider provider)
{
SetKindName(provider);
}
return next();
}

private void SetKindName(ExternalProvider provider)
{
var hanlderType = _serializer.DeserializeType(provider.SerializedHandlerType);
var optionsType = hanlderType.GetAuthenticationSchemeOptionsType();
provider.KindName = optionsType.Name.Replace("Options", "");
}
}
}
Loading

0 comments on commit 3b48e80

Please sign in to comment.