diff --git a/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.netcoreapp.cs b/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.netcoreapp.cs index 1ed5ecbf0e..6ce83a6bcf 100644 --- a/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.netcoreapp.cs +++ b/src/Components/Authorization/ref/Microsoft.AspNetCore.Components.Authorization.netcoreapp.cs @@ -23,6 +23,8 @@ namespace Microsoft.AspNetCore.Components.Authorization public Microsoft.AspNetCore.Components.RenderFragment Authorizing { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } [Microsoft.AspNetCore.Components.ParameterAttribute] public Microsoft.AspNetCore.Components.RenderFragment NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public object Resource { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } protected override void Render(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } } public partial class AuthorizeView : Microsoft.AspNetCore.Components.Authorization.AuthorizeViewCore diff --git a/src/Components/Authorization/src/AuthorizeRouteView.cs b/src/Components/Authorization/src/AuthorizeRouteView.cs index 2d7ea76698..b236dfd158 100644 --- a/src/Components/Authorization/src/AuthorizeRouteView.cs +++ b/src/Components/Authorization/src/AuthorizeRouteView.cs @@ -54,6 +54,12 @@ namespace Microsoft.AspNetCore.Components.Authorization [Parameter] public RenderFragment Authorizing { get; set; } + /// + /// The resource to which access is being controlled. + /// + [Parameter] + public object Resource { get; set; } + [CascadingParameter] private Task ExistingCascadedAuthenticationState { get; set; } @@ -82,6 +88,7 @@ namespace Microsoft.AspNetCore.Components.Authorization builder.AddAttribute(2, nameof(AuthorizeRouteViewCore.Authorized), _renderAuthorizedDelegate); builder.AddAttribute(3, nameof(AuthorizeRouteViewCore.Authorizing), _renderAuthorizingDelegate); builder.AddAttribute(4, nameof(AuthorizeRouteViewCore.NotAuthorized), _renderNotAuthorizedDelegate); + builder.AddAttribute(5, nameof(AuthorizeRouteViewCore.Resource), Resource); builder.CloseComponent(); } diff --git a/src/Components/Authorization/test/AuthorizeRouteViewTest.cs b/src/Components/Authorization/test/AuthorizeRouteViewTest.cs index 5a3a5683c7..9951014a51 100644 --- a/src/Components/Authorization/test/AuthorizeRouteViewTest.cs +++ b/src/Components/Authorization/test/AuthorizeRouteViewTest.cs @@ -76,6 +76,78 @@ namespace Microsoft.AspNetCore.Components.Authorization edit => AssertPrependText(batch, edit, "Hello from the page with message: Hello, world!")); } + [Fact] + public void AuthorizesWhenResourceIsSet() + { + // Arrange + var routeData = new RouteData(typeof(TestPageRequiringAuthorization), new Dictionary + { + { nameof(TestPageRequiringAuthorization.Message), "Hello, world!" } + }); + var resource = "foo"; + _testAuthorizationService.NextResult = AuthorizationResult.Success(); + + // Act + _renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary + { + { nameof(AuthorizeRouteView.RouteData), routeData }, + { nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) }, + { nameof(AuthorizeRouteView.Resource), resource } + })); + + // Assert: renders layout + var batch = _renderer.Batches.Single(); + var layoutDiff = batch.GetComponentDiffs().Single(); + Assert.Collection(layoutDiff.Edits, + edit => AssertPrependText(batch, edit, "Layout starts here"), + edit => + { + Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type); + AssertFrame.Component(batch.ReferenceFrames[edit.ReferenceFrameIndex]); + }, + edit => AssertPrependText(batch, edit, "Layout ends here")); + + // Assert: renders page + var pageDiff = batch.GetComponentDiffs().Single(); + Assert.Collection(pageDiff.Edits, + edit => AssertPrependText(batch, edit, "Hello from the page with message: Hello, world!")); + + // Assert: Asserts that the Resource is present and set to "foo" + Assert.Collection(_testAuthorizationService.AuthorizeCalls, call=> + { + Assert.Equal(resource, call.resource.ToString()); + }); + } + + [Fact] + public void NotAuthorizedWhenResourceMissing() + { + // Arrange + var routeData = new RouteData(typeof(TestPageRequiringAuthorization), EmptyParametersDictionary); + _testAuthorizationService.NextResult = AuthorizationResult.Failed(); + + // Act + _renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary + { + { nameof(AuthorizeRouteView.RouteData), routeData }, + { nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) }, + })); + + // Assert: renders layout containing "not authorized" message + var batch = _renderer.Batches.Single(); + var layoutDiff = batch.GetComponentDiffs().Single(); + Assert.Collection(layoutDiff.Edits, + edit => AssertPrependText(batch, edit, "Layout starts here"), + edit => AssertPrependText(batch, edit, "Not authorized"), + edit => AssertPrependText(batch, edit, "Layout ends here")); + + // Assert: Asserts that the Resource is Null + Assert.Collection(_testAuthorizationService.AuthorizeCalls, call=> + { + Assert.Null(call.resource); + }); + } + [Fact] public void WhenNotAuthorized_RendersDefaultNotAuthorizedContentInsideLayout() {