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

Chore/improve samples and tests #183

Merged
merged 18 commits into from
Oct 10, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Improved decoratpr for AuthenticationService
  • Loading branch information
AndrewTriesToCode committed Oct 4, 2019
commit ef6ca64501bb768bca83a0210e06e8f6631c0aeb
13 changes: 13 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "test",
"command": "dotnet",
"type": "shell",
"args": [
"test"
],
"group": "test",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace Finbuckle.MultiTenant
/// <summary>
/// Finbuckle.MultiTenant.AspNetCore extensions to HttpContext.
/// </summary>
public static class HttpContextExtensions
public static class FinbuckleHttpContextExtensions
{
/// <summary>
/// Returns the current MultiTenantContext or null if there is none.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ public static FinbuckleMultiTenantBuilder WithRemoteAuthentication(this Finbuckl
{
// Replace needed instead of TryAdd...
builder.Services.Replace(ServiceDescriptor.Singleton<IAuthenticationSchemeProvider, MultiTenantAuthenticationSchemeProvider>());
builder.Services.Replace(ServiceDescriptor.Scoped<IAuthenticationService, MultiTenantAuthenticationService>());
// builder.Services.Replace(ServiceDescriptor.Scoped<IAuthenticationService, MultiTenantAuthenticationService>());

builder.Services.DecorateService<IAuthenticationService, MultiTenantAuthenticationService>();
builder.Services.TryAddSingleton<RemoteAuthenticationStrategy>();

return builder;
Expand Down Expand Up @@ -130,8 +131,8 @@ public static FinbuckleMultiTenantBuilder WithRemoteAuthentication(this Finbuckl
{
// Replace needed instead of TryAdd...
builder.Services.Replace(ServiceDescriptor.Singleton<IAuthenticationSchemeProvider, MultiTenantAuthenticationSchemeProvider>());
builder.Services.Replace(ServiceDescriptor.Scoped<IAuthenticationService, MultiTenantAuthenticationService>());

// builder.Services.Replace(ServiceDescriptor.Scoped<IAuthenticationService, MultiTenantAuthenticationService>());
builder.Services.DecorateService<IAuthenticationService, MultiTenantAuthenticationService>();
builder.Services.TryAddSingleton<RemoteAuthenticationStrategy>();

return builder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#if NETSTANDARD2_0

using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;

namespace Finbuckle.MultiTenant.AspNetCore
{
internal class MultiTenantAuthenticationService : AuthenticationService
internal class MultiTenantAuthenticationService : IAuthenticationService
{
public MultiTenantAuthenticationService(IAuthenticationSchemeProvider schemes,
IAuthenticationHandlerProvider handlers,
IClaimsTransformation transform) : base(schemes, handlers, transform)
private readonly IAuthenticationService inner;

public MultiTenantAuthenticationService(IAuthenticationService inner)
{
this.inner = inner ?? throw new System.ArgumentNullException(nameof(inner));
}

public override async Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties)
public Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme)
=> inner.AuthenticateAsync(context, scheme);

public Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties)
{
// Add tenant identifier to the properties so on the callback we can use it to set the multitenant context.
var multiTenantContext = context.GetMultiTenantContext();
Expand All @@ -39,42 +41,16 @@ public override async Task ChallengeAsync(HttpContext context, string scheme, Au
properties.Items.Add("tenantIdentifier", multiTenantContext.TenantInfo.Identifier);
}

await base.ChallengeAsync(context, scheme, properties);
return inner.ChallengeAsync(context, scheme, properties);
}
}
}

#else
public Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties)
=> inner.ForbidAsync(context, scheme, properties);

using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
public Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
=> inner.SignInAsync(context, scheme, principal, properties);

namespace Finbuckle.MultiTenant.AspNetCore
{
internal class MultiTenantAuthenticationService : AuthenticationService
{
public MultiTenantAuthenticationService(IAuthenticationSchemeProvider schemes,
IAuthenticationHandlerProvider handlers,
IClaimsTransformation transform,
IOptions<AuthenticationOptions> options) : base(schemes, handlers, transform, options)
{
}

public override async Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties)
{
// Add tenant identifier to the properties so on the callback we can use it to set the multitenant context.
var multiTenantContext = context.GetMultiTenantContext();
if (multiTenantContext.TenantInfo != null)
{
properties = properties ?? new AuthenticationProperties();
properties.Items.Add("tenantIdentifier", multiTenantContext.TenantInfo.Identifier);
}

await base.ChallengeAsync(context, scheme, properties);
}
public Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties)
=> inner.SignOutAsync(context, scheme, properties);
}
}

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2019 Andrew White
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Linq;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace Microsoft.Extensions.DependencyInjection
{
static class FinbuckleServiceCollectionExtensions
{
public static bool DecorateService<TService, TImpl>(this IServiceCollection services)
{
var existingService = services.SingleOrDefault(s => s.ServiceType == typeof(TService));
if (existingService == null)
return false;

var newService = new ServiceDescriptor(existingService.ServiceType,
sp =>
{
TService inner = (TService)ActivatorUtilities.CreateInstance(sp, existingService.ImplementationType);
return ActivatorUtilities.CreateInstance<TImpl>(sp, inner);
},
existingService.Lifetime);

if (existingService.ImplementationInstance != null)
{
newService = new ServiceDescriptor(existingService.ServiceType,
sp =>
{
TService inner = (TService)existingService.ImplementationInstance;
return ActivatorUtilities.CreateInstance<TImpl>(sp, inner);
},
existingService.Lifetime);
}
else if (existingService.ImplementationFactory != null)
{
newService = new ServiceDescriptor(existingService.ServiceType,
sp =>
{
TService inner = (TService)existingService.ImplementationFactory(sp);
return ActivatorUtilities.CreateInstance<TImpl>(sp, inner);
},
existingService.Lifetime);
}

services.Remove(existingService);
services.Add(newService);

return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,9 @@
// limitations under the License.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Finbuckle.MultiTenant;
using Finbuckle.MultiTenant.AspNetCore;
using Finbuckle.MultiTenant.Core;
using Finbuckle.MultiTenant.Stores;
using Finbuckle.MultiTenant.Strategies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Xunit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,6 @@ public void ThrowIfNullRouteConfigAddingRouteStrategy()
using Finbuckle.MultiTenant;
using Finbuckle.MultiTenant.Strategies;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Moq;
using Microsoft.AspNetCore.Mvc.Infrastructure;

public class MultiTenantBuilderExtensionsShould
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Note: MultiTenantOptionsManager is a trivial tweak of Microsoft's RouteBuilder implementation.
// Note: MultiTenantRouteBuilder is a trivial tweak of Microsoft's RouteBuilder implementation.