diff --git a/src/Skybrud.Umbraco.Redirects/Config/RedirectsContentAppSettings.cs b/src/Skybrud.Umbraco.Redirects/Config/RedirectsContentAppSettings.cs
index 5a4797b..e8b6cf6 100644
--- a/src/Skybrud.Umbraco.Redirects/Config/RedirectsContentAppSettings.cs
+++ b/src/Skybrud.Umbraco.Redirects/Config/RedirectsContentAppSettings.cs
@@ -13,6 +13,10 @@ public class RedirectsContentAppSettings {
public bool Enabled { get; set; } = true;
///
+ /// Gets or sets whether the user's start nodes should filter which redirects they have access to. Default is .
+ ///
+ public bool UseStartNodes { get; set; } = false;
+
/// Gets or sets a list of content types and media types where the content app should or should not be shown.
/// The format follows Umbraco's show option - eg. +content/* enables the content app for all
/// content.
diff --git a/src/Skybrud.Umbraco.Redirects/Controllers/Api/RedirectsController.cs b/src/Skybrud.Umbraco.Redirects/Controllers/Api/RedirectsController.cs
index 808048d..bff63bb 100644
--- a/src/Skybrud.Umbraco.Redirects/Controllers/Api/RedirectsController.cs
+++ b/src/Skybrud.Umbraco.Redirects/Controllers/Api/RedirectsController.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Mvc;
@@ -12,12 +13,17 @@
using Skybrud.Umbraco.Redirects.Models.Api;
using Skybrud.Umbraco.Redirects.Models.Options;
using Skybrud.Umbraco.Redirects.Services;
+using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Web.BackOffice.Controllers;
using Umbraco.Cms.Web.Common.Attributes;
+using Umbraco.Cms.Web.Common.UmbracoContext;
+using Umbraco.Extensions;
#pragma warning disable 1591
@@ -61,13 +67,15 @@ public RedirectsController(ILogger logger, IRedirectsServic
[HttpGet]
public ActionResult GetRootNodes() {
- RedirectRootNode[] rootNodes = _redirects.GetRootNodes();
-
- return new JsonResult(new {
- total = rootNodes.Length,
- items = rootNodes.Select(x => new RedirectRootNodeModel(x, _backOffice))
- });
+ var rootNodes = _backOffice.Settings.ContentApp.UseStartNodes
+ ? _redirects.GetRootNodes(_backOffice.CurrentUser)
+ : _redirects.GetRootNodes();
+ return new JsonResult(new
+ {
+ total = rootNodes.Length,
+ items = rootNodes.Select(x => new RedirectRootNodeModel(x, _backOffice))
+ });
}
[HttpPost]
@@ -255,12 +263,15 @@ public ActionResult DeleteRedirect(Guid redirectId) {
/// The maximum amount of redirects to be returned per page.
/// The type of redirects that should be returned.
/// The text that the returned redirects should match.
- /// The root node key that the returned redirects should match. null means all redirects. means all global redirects.
+ /// An array of root node keys that the returned redirects should match. null means all redirects. means all global redirects.
/// A list of redirects.
[HttpGet]
- public ActionResult GetRedirects(int page = 1, int limit = 20, string? type = null, string? text = null, Guid? rootNodeKey = null) {
+ public ActionResult GetRedirects(int page = 1, int limit = 20, string? type = null, string? text = null, [FromQuery] Guid[]? rootNodeKeys = null) {
try {
+ var rootKeys = _backOffice.Settings.ContentApp.UseStartNodes
+ ? _redirects.GetRootNodes(_backOffice.CurrentUser!).Select(p => p.Key)
+ : _redirects.GetRootNodes().Select(p => p.Key);
// Initialize the search options
RedirectsSearchOptions options = new() {
@@ -268,7 +279,7 @@ public ActionResult GetRedirects(int page = 1, int limit = 20, string? type = nu
Limit = limit,
Type = EnumUtils.ParseEnum(type, RedirectTypeFilter.All),
Text = text,
- RootNodeKey = rootNodeKey
+ RootNodeKeys = (rootNodeKeys != null && rootNodeKeys.Any()) ? rootNodeKeys : rootKeys.ToArray()
};
// Make the search for redirects via the redirects service
@@ -369,7 +380,6 @@ private ActionResult Error(RedirectsException ex) {
};
}
-
}
}
\ No newline at end of file
diff --git a/src/Skybrud.Umbraco.Redirects/Models/RedirectRootNode.cs b/src/Skybrud.Umbraco.Redirects/Models/RedirectRootNode.cs
index ab84fce..dc677e6 100644
--- a/src/Skybrud.Umbraco.Redirects/Models/RedirectRootNode.cs
+++ b/src/Skybrud.Umbraco.Redirects/Models/RedirectRootNode.cs
@@ -36,6 +36,12 @@ public class RedirectRootNode {
[JsonProperty("icon")]
public string Icon { get; }
+ ///
+ /// Gets the path of the root node.
+ ///
+ [JsonProperty("path")]
+ public IEnumerable Path { get; set; }
+
///
/// Gets the domains asscoiated with the root node.
///
@@ -45,6 +51,7 @@ private RedirectRootNode(IContent content, IEnumerable? domains)
Id = content.Id;
Key = content.Key;
Name = content.Name!;
+ Path = content.Path.Split(',', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse);
Icon = content.ContentType.Icon!;
Domains = domains?.Select(x => x.Name).ToArray() ?? Array.Empty();
}
diff --git a/src/Skybrud.Umbraco.Redirects/Services/IRedirectsService.cs b/src/Skybrud.Umbraco.Redirects/Services/IRedirectsService.cs
index 7dc67a2..ca625dd 100644
--- a/src/Skybrud.Umbraco.Redirects/Services/IRedirectsService.cs
+++ b/src/Skybrud.Umbraco.Redirects/Services/IRedirectsService.cs
@@ -1,9 +1,13 @@
using System;
using System.Collections.Generic;
+using System.Linq;
+
using Microsoft.AspNetCore.Http;
using Skybrud.Umbraco.Redirects.Models;
using Skybrud.Umbraco.Redirects.Models.Options;
+using Umbraco.Cms.Core.Models.Membership;
+
namespace Skybrud.Umbraco.Redirects.Services {
///
@@ -116,6 +120,35 @@ public interface IRedirectsService {
/// An array of representing the root nodes.
RedirectRootNode[] GetRootNodes();
+ ///
+ /// Returns an array of all rode nodes configured in Umbraco.
+ ///
+ /// An with potential root node access restrictions.
+ /// An array of representing the root nodes the user has access to.
+ RedirectRootNode[] GetRootNodes(IUser user)
+ {
+ var rootNodes = GetRootNodes();
+ HashSet rootNodeIds = new();
+
+ if (user.StartContentIds != null)
+ {
+ foreach (var rootNodeId in user.StartContentIds)
+ {
+ rootNodeIds.Add(rootNodeId);
+ }
+ }
+
+ foreach (var group in user.Groups)
+ {
+ if (group.StartContentId != null)
+ {
+ rootNodeIds.Add(group.StartContentId.Value);
+ }
+ }
+
+ return rootNodes.Where(rootNode => rootNodeIds.Any(x => rootNode.Path.Contains(x))).ToArray();
+ }
+
///
/// Returns an array of redirects where the destination matches the specified and .
///
diff --git a/src/Skybrud.Umbraco.Redirects/Services/RedirectsSearchOptions.cs b/src/Skybrud.Umbraco.Redirects/Services/RedirectsSearchOptions.cs
index 68872df..54129b3 100644
--- a/src/Skybrud.Umbraco.Redirects/Services/RedirectsSearchOptions.cs
+++ b/src/Skybrud.Umbraco.Redirects/Services/RedirectsSearchOptions.cs
@@ -33,12 +33,19 @@ public class RedirectsSearchOptions {
///
public string? Text { get; set; }
- ///
- /// Gets or sets the key the returned redirects should match. indicates all global
- /// redirects. Default is null, in which case this filter is disabled.
- ///
+ ///
+ /// Gets or sets the key the returned redirects should match. indicates all global
+ /// redirects. Default is null, in which case this filter is disabled.
+ ///
+ [Obsolete("Obsoleted in favour of RootNodeKeys, as a user may have access to more than one root node.")]
public Guid? RootNodeKey { get; set; }
+ ///
+ /// Gets or sets the key the returned redirects should match. indicates all global
+ /// redirects. Default is null, in which case this filter is disabled.
+ ///
+ public Guid[] RootNodeKeys { get; set; }
+
#endregion
#region Constructors
diff --git a/src/Skybrud.Umbraco.Redirects/Services/RedirectsService.cs b/src/Skybrud.Umbraco.Redirects/Services/RedirectsService.cs
index 33ba602..2514eaf 100644
--- a/src/Skybrud.Umbraco.Redirects/Services/RedirectsService.cs
+++ b/src/Skybrud.Umbraco.Redirects/Services/RedirectsService.cs
@@ -13,6 +13,7 @@
using Skybrud.Umbraco.Redirects.Models;
using Skybrud.Umbraco.Redirects.Models.Dtos;
using Skybrud.Umbraco.Redirects.Models.Options;
+using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
@@ -368,7 +369,11 @@ public RedirectsSearchResult GetRedirects(RedirectsSearchOptions options) {
var sql = scope.SqlContext.Sql().Select().From();
// Search by the rootNodeId
- if (options.RootNodeKey != null) sql = sql.Where(x => x.RootKey == options.RootNodeKey.Value);
+ if (options.RootNodeKeys != null && options.RootNodeKeys.Any()) {
+ sql = sql.Where(x => options.RootNodeKeys.Contains(x.RootKey));
+ } else if (options.RootNodeKey != null) {
+ sql = sql.Where(x => x.RootKey == options.RootNodeKey);
+ }
// Search by the type
if (options.Type != RedirectTypeFilter.All) {
@@ -397,6 +402,7 @@ public RedirectsSearchResult GetRedirects(RedirectsSearchOptions options) {
||
(x.Path.Contains(url) && x.QueryString.Contains(query))
));
+
}
}
@@ -460,19 +466,17 @@ public IEnumerable GetAllRedirects() {
/// Returns an array of all rode nodes configured in Umbraco.
///
/// An array of representing the root nodes.
- public RedirectRootNode[] GetRootNodes() {
-
- // Multiple domains may be configured for a single node, so we need to group the domains before proceeding
- var domainsByRootNodeId = GetDomains().GroupBy(x => x.RootNodeId);
-
- return (
- from domainGroup in domainsByRootNodeId
- let content = _contentService.GetById(domainGroup.First().RootNodeId)
- where content is { Trashed: false }
- orderby content.Id
- select RedirectRootNode.GetFromContent(content, domainGroup)
- ).ToArray();
-
+ public RedirectRootNode[] GetRootNodes()
+ {
+ var domainsByRootNodeId = GetDomains().GroupBy(x => x.RootNodeId);
+
+ return (
+ from domainGroup in domainsByRootNodeId
+ let content = _contentService.GetById(domainGroup.First().RootNodeId)
+ where content is { Trashed: false }
+ orderby content.Id
+ select RedirectRootNode.GetFromContent(content, domainGroup)
+ ).ToArray();
}
///
diff --git a/src/Skybrud.Umbraco.Redirects/wwwroot/Scripts/Controllers/Dashboards/Default.js b/src/Skybrud.Umbraco.Redirects/wwwroot/Scripts/Controllers/Dashboards/Default.js
index 604a4f5..7cbf000 100644
--- a/src/Skybrud.Umbraco.Redirects/wwwroot/Scripts/Controllers/Dashboards/Default.js
+++ b/src/Skybrud.Umbraco.Redirects/wwwroot/Scripts/Controllers/Dashboards/Default.js
@@ -113,7 +113,7 @@
// Any filters?
if (vm.filters.rootNode && vm.filters.rootNode.key) {
- args.rootNodeKey = vm.filters.rootNode.key;
+ args.rootNodeKeys = vm.filters.rootNode.key;
vm.activeFilters++;
}