Skip to content

More IResult Implementations #32738

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

Merged
merged 9 commits into from
May 16, 2021
22 changes: 17 additions & 5 deletions src/Mvc/Mvc.Core/src/ChallengeResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

Expand All @@ -13,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc
/// <summary>
/// An <see cref="ActionResult"/> that on execution invokes <see cref="M:HttpContext.ChallengeAsync"/>.
/// </summary>
public class ChallengeResult : ActionResult
public class ChallengeResult : ActionResult, IResult
{
/// <summary>
/// Initializes a new instance of <see cref="ChallengeResult"/>.
Expand Down Expand Up @@ -90,14 +91,25 @@ public ChallengeResult(IList<string> authenticationSchemes, AuthenticationProper
public AuthenticationProperties? Properties { get; set; }

/// <inheritdoc />
public override async Task ExecuteResultAsync(ActionContext context)
public override Task ExecuteResultAsync(ActionContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}

var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
return ExecuteAsync(context.HttpContext);
}

/// <inheritdoc />
Task IResult.ExecuteAsync(HttpContext httpContext)
{
return ExecuteAsync(httpContext);
}

private async Task ExecuteAsync(HttpContext httpContext)
{
var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<ChallengeResult>();

logger.ChallengeResultExecuting(AuthenticationSchemes);
Expand All @@ -106,12 +118,12 @@ public override async Task ExecuteResultAsync(ActionContext context)
{
foreach (var scheme in AuthenticationSchemes)
{
await context.HttpContext.ChallengeAsync(scheme, Properties);
await httpContext.ChallengeAsync(scheme, Properties);
}
}
else
{
await context.HttpContext.ChallengeAsync(Properties);
await httpContext.ChallengeAsync(Properties);
}
}
}
Expand Down
22 changes: 17 additions & 5 deletions src/Mvc/Mvc.Core/src/ForbidResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

Expand All @@ -13,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc
/// <summary>
/// An <see cref="ActionResult"/> that on execution invokes <see cref="M:HttpContext.ForbidAsync"/>.
/// </summary>
public class ForbidResult : ActionResult
public class ForbidResult : ActionResult, IResult
{
/// <summary>
/// Initializes a new instance of <see cref="ForbidResult"/>.
Expand Down Expand Up @@ -90,14 +91,25 @@ public ForbidResult(IList<string> authenticationSchemes, AuthenticationPropertie
public AuthenticationProperties? Properties { get; set; }

/// <inheritdoc />
public override async Task ExecuteResultAsync(ActionContext context)
public override Task ExecuteResultAsync(ActionContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}

var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
return ExecuteAsync(context.HttpContext);
}

/// <inheritdoc />
Task IResult.ExecuteAsync(HttpContext httpContext)
{
return ExecuteAsync(httpContext);
}

private async Task ExecuteAsync(HttpContext httpContext)
{
var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<ForbidResult>();

logger.ForbidResultExecuting(AuthenticationSchemes);
Expand All @@ -106,12 +118,12 @@ public override async Task ExecuteResultAsync(ActionContext context)
{
for (var i = 0; i < AuthenticationSchemes.Count; i++)
{
await context.HttpContext.ForbidAsync(AuthenticationSchemes[i], Properties);
await httpContext.ForbidAsync(AuthenticationSchemes[i], Properties);
}
}
else
{
await context.HttpContext.ForbidAsync(Properties);
await httpContext.ForbidAsync(Properties);
}
}
}
Expand Down
20 changes: 16 additions & 4 deletions src/Mvc/Mvc.Core/src/SignInResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
Expand All @@ -14,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc
/// <summary>
/// An <see cref="ActionResult"/> that on execution invokes <see cref="M:HttpContext.SignInAsync"/>.
/// </summary>
public class SignInResult : ActionResult
public class SignInResult : ActionResult, IResult
{
/// <summary>
/// Initializes a new instance of <see cref="SignInResult"/> with the
Expand Down Expand Up @@ -78,19 +79,30 @@ public SignInResult(string? authenticationScheme, ClaimsPrincipal principal, Aut
public AuthenticationProperties? Properties { get; set; }

/// <inheritdoc />
public override async Task ExecuteResultAsync(ActionContext context)
public override Task ExecuteResultAsync(ActionContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}

var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
return ExecuteAsync(context.HttpContext);
}

/// <inheritdoc />
Task IResult.ExecuteAsync(HttpContext httpContext)
{
return ExecuteAsync(httpContext);
}

private Task ExecuteAsync(HttpContext httpContext)
{
var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<SignInResult>();

logger.SignInResultExecuting(AuthenticationScheme, Principal);

await context.HttpContext.SignInAsync(AuthenticationScheme, Principal, Properties);
return httpContext.SignInAsync(AuthenticationScheme, Principal, Properties);
}
}
}
22 changes: 17 additions & 5 deletions src/Mvc/Mvc.Core/src/SignOutResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
Expand All @@ -14,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc
/// <summary>
/// An <see cref="ActionResult"/> that on execution invokes <see cref="M:HttpContext.SignOutAsync"/>.
/// </summary>
public class SignOutResult : ActionResult
public class SignOutResult : ActionResult, IResult
{
/// <summary>
/// Initializes a new instance of <see cref="SignOutResult"/> with the default sign out scheme.
Expand Down Expand Up @@ -88,13 +89,24 @@ public SignOutResult(IList<string> authenticationSchemes, AuthenticationProperti
public AuthenticationProperties? Properties { get; set; }

/// <inheritdoc />
public override async Task ExecuteResultAsync(ActionContext context)
public override Task ExecuteResultAsync(ActionContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}

return ExecuteAsync(context.HttpContext);
}

/// <inheritdoc />
Task IResult.ExecuteAsync(HttpContext httpContext)
{
return ExecuteAsync(httpContext);
}

private async Task ExecuteAsync(HttpContext httpContext)
{
if (AuthenticationSchemes == null)
{
throw new InvalidOperationException(
Expand All @@ -103,20 +115,20 @@ public override async Task ExecuteResultAsync(ActionContext context)
/* type: */ nameof(SignOutResult)));
}

var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<SignOutResult>();

logger.SignOutResultExecuting(AuthenticationSchemes);

if (AuthenticationSchemes.Count == 0)
{
await context.HttpContext.SignOutAsync(Properties);
await httpContext.SignOutAsync(Properties);
}
else
{
for (var i = 0; i < AuthenticationSchemes.Count; i++)
{
await context.HttpContext.SignOutAsync(AuthenticationSchemes[i], Properties);
await httpContext.SignOutAsync(AuthenticationSchemes[i], Properties);
}
}
}
Expand Down
43 changes: 40 additions & 3 deletions src/Mvc/Mvc.Core/test/ChallengeResultTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc
public class ChallengeResultTest
{
[Fact]
public async Task ChallengeResult_Execute()
public async Task ChallengeResult_ExecuteResultAsync()
{
// Arrange
var result = new ChallengeResult("", null);
Expand All @@ -43,7 +43,7 @@ public async Task ChallengeResult_Execute()
}

[Fact]
public async Task ChallengeResult_ExecuteNoSchemes()
public async Task ChallengeResult_ExecuteResultAsync_NoSchemes()
{
// Arrange
var result = new ChallengeResult(new string[] { }, null);
Expand All @@ -67,6 +67,43 @@ public async Task ChallengeResult_ExecuteNoSchemes()
auth.Verify(c => c.ChallengeAsync(httpContext.Object, null, null), Times.Exactly(1));
}

[Fact]
public async Task ChallengeResult_ExecuteAsync()
{
// Arrange
var result = new ChallengeResult("", null);

var auth = new Mock<IAuthenticationService>();

var httpContext = new Mock<HttpContext>();
httpContext.SetupGet(c => c.RequestServices)
.Returns(CreateServices().AddSingleton(auth.Object).BuildServiceProvider());

// Act
await ((IResult)result).ExecuteAsync(httpContext.Object);

// Assert
auth.Verify(c => c.ChallengeAsync(httpContext.Object, "", null), Times.Exactly(1));
}

[Fact]
public async Task ChallengeResult_ExecuteAsync_NoSchemes()
{
// Arrange
var result = new ChallengeResult(new string[] { }, null);

var auth = new Mock<IAuthenticationService>();
var httpContext = new Mock<HttpContext>();
httpContext.SetupGet(c => c.RequestServices)
.Returns(CreateServices().AddSingleton(auth.Object).BuildServiceProvider());

// Act
await ((IResult)result).ExecuteAsync(httpContext.Object);

// Assert
auth.Verify(c => c.ChallengeAsync(httpContext.Object, null, null), Times.Exactly(1));
}

private static IServiceCollection CreateServices()
{
var services = new ServiceCollection();
Expand All @@ -75,4 +112,4 @@ private static IServiceCollection CreateServices()
return services;
}
}
}
}
64 changes: 64 additions & 0 deletions src/Mvc/Mvc.Core/test/SignInResultTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,70 @@ public async Task ExecuteResultAsync_InvokesSignInAsyncOnConfiguredScheme()
auth.Verify();
}

[Fact]
public async Task ExecuteAsync_InvokesSignInAsyncOnAuthenticationManager()
{
// Arrange
var principal = new ClaimsPrincipal();
var httpContext = new Mock<HttpContext>();
var auth = new Mock<IAuthenticationService>();
auth
.Setup(c => c.SignInAsync(httpContext.Object, "", principal, null))
.Returns(Task.CompletedTask)
.Verifiable();
httpContext.Setup(c => c.RequestServices).Returns(CreateServices(auth.Object));
var result = new SignInResult("", principal, null);

// Act
await ((IResult)result).ExecuteAsync(httpContext.Object);

// Assert
auth.Verify();
}

[Fact]
public async Task ExecuteAsync_InvokesSignInAsyncOnAuthenticationManagerWithDefaultScheme()
{
// Arrange
var principal = new ClaimsPrincipal();
var httpContext = new Mock<HttpContext>();
var auth = new Mock<IAuthenticationService>();
auth
.Setup(c => c.SignInAsync(httpContext.Object, null, principal, null))
.Returns(Task.CompletedTask)
.Verifiable();
httpContext.Setup(c => c.RequestServices).Returns(CreateServices(auth.Object));
var result = new SignInResult(principal);

// Act
await ((IResult)result).ExecuteAsync(httpContext.Object);

// Assert
auth.Verify();
}

[Fact]
public async Task ExecuteAsync_InvokesSignInAsyncOnConfiguredScheme()
{
// Arrange
var principal = new ClaimsPrincipal();
var authProperties = new AuthenticationProperties();
var httpContext = new Mock<HttpContext>();
var auth = new Mock<IAuthenticationService>();
auth
.Setup(c => c.SignInAsync(httpContext.Object, "Scheme1", principal, authProperties))
.Returns(Task.CompletedTask)
.Verifiable();
httpContext.Setup(c => c.RequestServices).Returns(CreateServices(auth.Object));
var result = new SignInResult("Scheme1", principal, authProperties);

// Act
await ((IResult)result).ExecuteAsync(httpContext.Object);

// Assert
auth.Verify();
}

private static IServiceProvider CreateServices(IAuthenticationService auth)
{
return new ServiceCollection()
Expand Down
Loading