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

V15: Notification Hub #17776

Open
wants to merge 29 commits into
base: v15/dev
Choose a base branch
from
Open

Conversation

nikolajlauridsen
Copy link
Contributor

@nikolajlauridsen nikolajlauridsen commented Dec 11, 2024

Creates a SignalR hub that relays server events to the backoffice frontend.

Terminology

  • ServerEvent - Some event that has happened on the server, the default events map to the notifications
  • EventSource - The source of the event, I.E. "Document", "Media", etc. this is just a string and can be anything
  • EventType - The type of event, for instance, Created, Deleted, etc. This is also just a string and can be anything
  • Routing - In the context of server events routing means ensuring that the event gets to the connections which are authorized for it.

Details

Each event consists of:

  • EventType
  • EventSource
  • Key - The key of the entity the event is about

These default events are

  • Created
  • Updated
  • Deleted
  • Trashed

The events come from a single hub using a single method notify. Upon connecting, the user is authorized to receive certain events. This means that users with only DocumentTreeAccess will only see document events, and so on.

Additionally, it's also possible to notify a specific user. This still goes through the notify method and notifies all the users' connections. It is used to notify a specific user that they've been updated.

Events are routed using the "group" concept in SignalR, every event source is its own group. An IEventSourceAuthorizer is then used to authorize a user (using a ClaimsPrincipal) for one or more event sources (groups), if a user is approved it's added to the group. This means that an authorizer is required for each event source for the routing to be used. If authorization is not required the IServerEventRouter.BroadcastEventAsync method can instead be used, this sends the event to all connected users.

If a user is updated, the authorization is re-run ensuring that any permission changes are reflected in the event routing.

This means to extend this you must:

  1. Implement an IEventSourceAuthorizer
  2. Add it to the EventSourceAuthorizerCollection
  3. Create and route an event using IServerEventRouter.RouteEventAsync, this can be done from anywhere, but a notification handler is an ideal place

If you want to authorize using a standard .Net Core policy you can use the EventSourcePolicyAuthorizer abstract class, and specify which event sources should be authorized using which policy.

Note that the event source authorized by the IEventSourceAuthorizer must be the same as the one your ServeEvent for the event to be routed anywhere

Example of adding event authorizer

private static IUmbracoBuilder AddAuthorizers(this IUmbracoBuilder builder)
    {
        builder.EventSourceAuthorizers()
            .Append<DocumentEventAuthorizer>();
        return builder;
    }

Testing

  • Extract this zip file in you wwwroot folder: js.zip
  • Create a simple content node
  • In the template for the content node add the following HTML:
@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@{
	Layout = null;
}

<div class="container">
    <h1>Messages:</h1>
    <div class="row p-1">
        <div class="col-6">
            <ul id="messagesList"></ul>
        </div>
    </div>
</div>
<script src="~/js/signalr/dist/browser/signalr.js"></script>
<script src="~/js/event.js"></script>
  • Login to the backoffice
  • Copy your auth token:
    image
  • Replace YOUR-ACCESS-TOKEN-HERE with that token in the wwwroot/js/event.js file
  • Go the the front page (or hard reset it)
  • A SignalR connection should now be active
  • Do actions like creating, updating, deleting, content, media, data types, etc. and verify that they're displayed on the front page

Note: The auth token is short lived, so it may expire

@nikolajlauridsen nikolajlauridsen changed the base branch from contrib to v15/dev December 11, 2024 13:48
@nikolajlauridsen nikolajlauridsen marked this pull request as ready for review December 20, 2024 10:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant