Can Metalama add an aspect to a class? Thinking of creating a runtime AuthorizeAspectAttribute. #260
-
I'm new to using Metalama. I have implemented Field and Property Aspects thus far. I have also implement a shared ProjectFabric Aspect for adding Aspect to multiple Properties across multiple projects. Our project is using .Net 8 & Blazor Server Side app. I am considering the idea to create an Aspect that implements runtime Authorization. The @ attribute [Authorize] applied in the .razor file is considered a AttributeTargets.Class for usage. I cannot find any information on how it is "wired" to the class or executed (when or how). If anyone would be so generous as to offer a few beginning suggestions or pointers on what to look for I'd appreciate it. I am unsure if this can be combined with custom AuthorizationMiddleware or if that's the right or wrong way to approach this. I am unable to find any information on the web how the @Attribute [Authorize] works in a Blazor context other than the attribute is a "class" attribute. Thank you in advance for any constructive responses you may provide. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
All For example, if you have Home.razor with this content: @page "/"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app. It generates this C# code (simplified): namespace BlazorApp.Components.Pages
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using System.Net.Http;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Components.Web;
using static Microsoft.AspNetCore.Components.Web.RenderMode;
using Microsoft.AspNetCore.Components.Web.Virtualization;
using Microsoft.JSInterop;
using BlazorApp;
using BlazorApp.Client;
using BlazorApp.Components;
using Microsoft.AspNetCore.Authorization;
[Authorize]
[RouteAttribute("/")]
public partial class Home : ComponentBase
{
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
__builder.OpenComponent<PageTitle>(0);
__builder.AddAttribute(1, "ChildContent", (RenderFragment)((__builder2) => {
__builder2.AddContent(2, "Home");
}
));
__builder.CloseComponent();
__builder.AddMarkupContent(3, "\r\n\r\n");
__builder.AddMarkupContent(4, "<h1>Hello, world!</h1>\r\n\r\nWelcome to your new app.\r\n");
}
}
} It's then up to other parts of the Blazor runtime to interpret this attribute. From Metalama's point of view, you should be able to treat this generated class as any other class. For example, a useless aspect that just adds class AuthorizeAspect : TypeAspect
{
public override void BuildAspect(IAspectBuilder<INamedType> builder)
{
base.BuildAspect(builder);
builder.Advice.IntroduceAttribute(builder.Target, AttributeConstruction.Create(typeof(AuthorizeAttribute)));
}
} And would be applied like this: @attribute [AuthorizeAspect] Though it's not quite clear to me what you're actually trying to achieve or how Metalama fits into that. I think it would make sense to first figure out what you need to do in terms of plain C#/Blazor and only then consider how to use Metalama to improve on that. |
Beta Was this translation helpful? Give feedback.
It seems to me that the main thing you need is to restrict access as soon as the underlying data changes and, as I understand it, you should be able to achieve that using
CookieAuthenticationEvents.ValidatePrincipal
.Though since you also need a dynamic list of allowed roles, doing this with role-based authorization would require that the roles in your data are not the same as the roles in the app, but are dynamically mapped between each other. And I'm not sure this would be a good idea.
So you probably should consider either claims- or policy-based authorization, both of which allow you to execute code when authorizing an user.