-
Notifications
You must be signed in to change notification settings - Fork 43
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
Basic PR for #154 #156
base: v4/main
Are you sure you want to change the base?
Basic PR for #154 #156
Changes from 6 commits
623d388
7393261
883228e
350d545
76e3ca9
2032d40
a928c17
e3b86bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<RedirectsController> 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.UserStartNodes | ||
? _redirects.GetRootNodes(_backOffice.CurrentUser).ToArray() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My bad, caught it. |
||
: _redirects.GetRootNodes(); | ||
|
||
return new JsonResult(new | ||
{ | ||
total = rootNodes.Length, | ||
items = rootNodes.Select(x => new RedirectRootNodeModel(x, _backOffice)) | ||
}); | ||
} | ||
|
||
[HttpPost] | ||
|
@@ -255,20 +263,23 @@ public ActionResult DeleteRedirect(Guid redirectId) { | |
/// <param name="limit">The maximum amount of redirects to be returned per page.</param> | ||
/// <param name="type">The type of redirects that should be returned.</param> | ||
/// <param name="text">The text that the returned redirects should match.</param> | ||
/// <param name="rootNodeKey">The root node key that the returned redirects should match. <c>null</c> means all redirects. <see cref="Guid.Empty"/> means all global redirects.</param> | ||
/// <param name="rootNodeKeys">An array of root node keys that the returned redirects should match. <c>null</c> means all redirects. <see cref="Guid.Empty"/> means all global redirects.</param> | ||
/// <returns>A list of redirects.</returns> | ||
[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.UserStartNodes | ||
? _redirects.GetRootNodes(_backOffice.CurrentUser).Select(p => p.Key) | ||
: _redirects.GetRootNodes().Select(p => p.Key); | ||
|
||
// Initialize the search options | ||
RedirectsSearchOptions options = new() { | ||
Page = page, | ||
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) { | |
}; | ||
|
||
} | ||
|
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,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; | ||
|
@@ -366,7 +367,11 @@ public RedirectsSearchResult GetRedirects(RedirectsSearchOptions options) { | |
var sql = scope.SqlContext.Sql().Select<RedirectDto>().From<RedirectDto>(); | ||
|
||
// Search by the rootNodeId | ||
if (options.RootNodeKey != null) sql = sql.Where<RedirectDto>(x => x.RootKey == options.RootNodeKey.Value); | ||
if (options.RootNodeKeys != null && options.RootNodeKeys.Any()) { | ||
sql = sql.Where<RedirectDto>(x => options.RootNodeKeys.Contains(x.RootKey)); | ||
} else if (options.RootNodeKey != null) { | ||
sql = sql.Where<RedirectDto>(x => x.RootKey == options.RootNodeKey); | ||
} | ||
|
||
// Search by the type | ||
if (options.Type != RedirectTypeFilter.All) { | ||
|
@@ -395,6 +400,7 @@ public RedirectsSearchResult GetRedirects(RedirectsSearchOptions options) { | |
|| | ||
(x.Path.Contains(url) && x.QueryString.Contains(query)) | ||
)); | ||
|
||
} | ||
} | ||
|
||
|
@@ -453,19 +459,46 @@ public IEnumerable<IRedirect> GetAllRedirects() { | |
/// Returns an array of all rode nodes configured in Umbraco. | ||
/// </summary> | ||
/// <returns>An array of <see cref="RedirectRootNode"/> representing the root nodes.</returns> | ||
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(); | ||
} | ||
|
||
/// <summary> | ||
/// Returns an array of all rode nodes configured in Umbraco. | ||
/// </summary> | ||
/// <param name="user">An <see cref="IUser"/> with potential root node access restrictions.</param> | ||
/// <returns>An array of <see cref="RedirectRootNode"/> representing the root nodes the user has access to.</returns> | ||
public RedirectRootNode[] GetRootNodes(IUser user) | ||
{ | ||
var rootNodes = GetRootNodes(); | ||
HashSet<int> 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(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is still a breaking change as you're introducing a new method. It's probably not very likely, but developers may choose to write their own implementation of the C# 8 introduces default interface methods. So as the method doesn't use any dependencies, you should be able to move the method body to the interface instead. This ensures that we can add a new method without it being a breaking change. Hope that makes sense 😉 |
||
} | ||
|
||
/// <summary> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry - I made a mistake in my description about this property. My intention was to indicate whether to use starts nodes as the basis for permissions.
Could you rename this to
UseStartsNodes
?The XML summary is also slightly wrong, as the default is
false
and nottrue
. Andlanword
should belangword
.