File: ApplicationModels\AuthorizationPageApplicationModelProviderTest.cs
Web Access
Project: src\src\Mvc\Mvc.RazorPages\test\Microsoft.AspNetCore.Mvc.RazorPages.Test.csproj (Microsoft.AspNetCore.Mvc.RazorPages.Test)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Reflection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.Extensions.Options;
 
namespace Microsoft.AspNetCore.Mvc.ApplicationModels;
 
public class AuthorizationPageApplicationModelProviderTest
{
    private readonly IOptions<MvcOptions> OptionsWithoutEndpointRouting = Options.Create(new MvcOptions { EnableEndpointRouting = false });
 
    [Fact]
    public void OnProvidersExecuting_IgnoresAttributesOnHandlerMethods()
    {
        // Arrange
        var policyProvider = new DefaultAuthorizationPolicyProvider(Options.Create(new AuthorizationOptions()));
        var authorizationProvider = new AuthorizationPageApplicationModelProvider(policyProvider, OptionsWithoutEndpointRouting);
        var typeInfo = typeof(PageWithAuthorizeHandlers).GetTypeInfo();
        var context = GetApplicationProviderContext(typeInfo);
 
        // Act
        authorizationProvider.OnProvidersExecuting(context);
 
        // Assert
        Assert.Collection(
            context.PageApplicationModel.Filters,
            f => Assert.IsType<PageHandlerPageFilter>(f),
            f => Assert.IsType<HandleOptionsRequestsPageFilter>(f));
    }
 
    private class PageWithAuthorizeHandlers : Page
    {
        public ModelWithAuthorizeHandlers Model => null;
 
        public override Task ExecuteAsync() => throw new NotImplementedException();
    }
 
    public class ModelWithAuthorizeHandlers : PageModel
    {
        [Authorize]
        public void OnGet()
        {
        }
    }
 
    [Fact]
    public void OnProvidersExecuting_DoesNothingWithEndpointRouting()
    {
        // Arrange
        var policyProvider = new DefaultAuthorizationPolicyProvider(Options.Create(new AuthorizationOptions()));
        var authorizationProvider = new AuthorizationPageApplicationModelProvider(policyProvider, Options.Create(new MvcOptions()));
        var typeInfo = typeof(TestPage).GetTypeInfo();
        var context = GetApplicationProviderContext(typeInfo);
 
        // Act
        authorizationProvider.OnProvidersExecuting(context);
 
        // Assert
        Assert.Collection(
            context.PageApplicationModel.Filters,
            f => Assert.IsType<PageHandlerPageFilter>(f),
            f => Assert.IsType<HandleOptionsRequestsPageFilter>(f));
    }
 
    [Fact]
    public void OnProvidersExecuting_AddsAuthorizeFilter_IfModelHasAuthorizationAttributes()
    {
        // Arrange
        var policyProvider = new DefaultAuthorizationPolicyProvider(Options.Create(new AuthorizationOptions()));
        var authorizationProvider = new AuthorizationPageApplicationModelProvider(policyProvider, OptionsWithoutEndpointRouting);
        var context = GetApplicationProviderContext(typeof(TestPage).GetTypeInfo());
 
        // Act
        authorizationProvider.OnProvidersExecuting(context);
 
        // Assert
        Assert.Collection(
            context.PageApplicationModel.Filters,
            f => Assert.IsType<PageHandlerPageFilter>(f),
            f => Assert.IsType<HandleOptionsRequestsPageFilter>(f),
            f => Assert.IsType<AuthorizeFilter>(f));
    }
 
    private class TestPage : Page
    {
        public TestModel Model => null;
 
        public override Task ExecuteAsync() => throw new NotImplementedException();
    }
 
    [Authorize]
    private class TestModel : PageModel
    {
        public virtual void OnGet()
        {
        }
    }
 
    [Fact]
    public void OnProvidersExecuting_CollatesAttributesFromInheritedTypes()
    {
        // Arrange
        var options = Options.Create(new AuthorizationOptions());
        options.Value.AddPolicy("Base", policy => policy.RequireClaim("Basic").RequireClaim("Basic2"));
        options.Value.AddPolicy("Derived", policy => policy.RequireClaim("Derived"));
 
        var policyProvider = new DefaultAuthorizationPolicyProvider(options);
        var authorizationProvider = new AuthorizationPageApplicationModelProvider(policyProvider, OptionsWithoutEndpointRouting);
 
        var context = GetApplicationProviderContext(typeof(TestPageWithDerivedModel).GetTypeInfo());
 
        // Act
        authorizationProvider.OnProvidersExecuting(context);
 
        // Assert
        AuthorizeFilter authorizeFilter = null;
        Assert.Collection(
            context.PageApplicationModel.Filters,
            f => Assert.IsType<PageHandlerPageFilter>(f),
            f => Assert.IsType<HandleOptionsRequestsPageFilter>(f),
            f => authorizeFilter = Assert.IsType<AuthorizeFilter>(f));
 
        // Basic + Basic2 + Derived authorize
        Assert.Equal(3, authorizeFilter.Policy.Requirements.Count);
    }
 
    private class TestPageWithDerivedModel : Page
    {
        public DerivedModel Model => null;
 
        public override Task ExecuteAsync() => throw new NotImplementedException();
    }
 
    [Authorize(Policy = "Base")]
    public class BaseModel : PageModel
    {
    }
 
    [Authorize(Policy = "Derived")]
    private class DerivedModel : BaseModel
    {
        public virtual void OnGet()
        {
        }
    }
 
    [Fact]
    public void OnProvidersExecuting_AddsAllowAnonymousFilter()
    {
        // Arrange
        var policyProvider = new DefaultAuthorizationPolicyProvider(Options.Create(new AuthorizationOptions()));
        var authorizationProvider = new AuthorizationPageApplicationModelProvider(policyProvider, OptionsWithoutEndpointRouting);
        var context = GetApplicationProviderContext(typeof(PageWithAnonymousModel).GetTypeInfo());
 
        // Act
        authorizationProvider.OnProvidersExecuting(context);
 
        // Assert
        Assert.Collection(
            context.PageApplicationModel.Filters,
            f => Assert.IsType<PageHandlerPageFilter>(f),
            f => Assert.IsType<HandleOptionsRequestsPageFilter>(f),
            f => Assert.IsType<AllowAnonymousFilter>(f));
    }
 
    private class PageWithAnonymousModel : Page
    {
        public AnonymousModel Model => null;
 
        public override Task ExecuteAsync() => throw new NotImplementedException();
    }
 
    [AllowAnonymous]
    public class AnonymousModel : PageModel
    {
        public void OnGet() { }
    }
 
    private static PageApplicationModelProviderContext GetApplicationProviderContext(TypeInfo typeInfo)
    {
        var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
 
        var defaultProvider = new DefaultPageApplicationModelProvider(
            modelMetadataProvider,
            Options.Create(new RazorPagesOptions()),
            new DefaultPageApplicationModelPartsProvider(modelMetadataProvider));
 
        var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
        defaultProvider.OnProvidersExecuting(context);
 
        return context;
    }
}