Merge remote-tracking branch 'origin/v14/dev' into v14/dev

This commit is contained in:
Bjarke Berg
2024-04-29 08:23:11 +02:00
9 changed files with 382 additions and 26 deletions

View File

@@ -16,6 +16,7 @@ public class BackOfficeApplicationManager : OpenIdDictApplicationManagerBase, IB
private readonly IRuntimeState _runtimeState;
private readonly Uri? _backOfficeHost;
private readonly string _authorizeCallbackPathName;
private readonly string _authorizeCallbackLogoutPathName;
public BackOfficeApplicationManager(
IOpenIddictApplicationManager applicationManager,
@@ -28,6 +29,7 @@ public class BackOfficeApplicationManager : OpenIdDictApplicationManagerBase, IB
_runtimeState = runtimeState;
_backOfficeHost = securitySettings.Value.BackOfficeHost;
_authorizeCallbackPathName = securitySettings.Value.AuthorizeCallbackPathName;
_authorizeCallbackLogoutPathName = securitySettings.Value.AuthorizeCallbackLogoutPathName;
}
public async Task EnsureBackOfficeApplicationAsync(Uri backOfficeUrl, CancellationToken cancellationToken = default)
@@ -112,7 +114,7 @@ public class BackOfficeApplicationManager : OpenIdDictApplicationManagerBase, IB
PostLogoutRedirectUris =
{
CallbackUrl(_authorizeCallbackPathName),
CallbackUrl($"{_authorizeCallbackPathName.EnsureEndsWith("/")}logout")
CallbackUrl(_authorizeCallbackLogoutPathName),
},
Permissions =
{
@@ -122,8 +124,8 @@ public class BackOfficeApplicationManager : OpenIdDictApplicationManagerBase, IB
OpenIddictConstants.Permissions.Endpoints.Revocation,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.ResponseTypes.Code
}
OpenIddictConstants.Permissions.ResponseTypes.Code,
},
};
}

View File

@@ -26,6 +26,7 @@ public class SecuritySettings
internal const int StaticMemberDefaultLockoutTimeInMinutes = 30 * 24 * 60;
internal const int StaticUserDefaultLockoutTimeInMinutes = 30 * 24 * 60;
internal const string StaticAuthorizeCallbackPathName = "/umbraco";
internal const string StaticAuthorizeCallbackLogoutPathName = "/umbraco/logout";
internal const string StaticAuthorizeCallbackErrorPathName = "/umbraco/error";
/// <summary>
@@ -113,11 +114,20 @@ public class SecuritySettings
public Uri? BackOfficeHost { get; set; }
/// <summary>
/// The path to use for authorization callback. Will be appended to the BackOfficeHost.
/// Gets or sets the path to use for authorization callback. Will be appended to the BackOfficeHost.
/// </summary>
[DefaultValue(StaticAuthorizeCallbackPathName)]
public string AuthorizeCallbackPathName { get; set; } = StaticAuthorizeCallbackPathName;
/// <summary>
/// Gets or sets the path to use for authorization callback logout. Will be appended to the BackOfficeHost.
/// </summary>
[DefaultValue(StaticAuthorizeCallbackLogoutPathName)]
public string AuthorizeCallbackLogoutPathName { get; set; } = StaticAuthorizeCallbackLogoutPathName;
/// <summary>
/// Gets or sets the path to use for authorization callback error. Will be appended to the BackOfficeHost.
/// </summary>
[DefaultValue(StaticAuthorizeCallbackErrorPathName)]
public string AuthorizeCallbackErrorPathName { get; set; } = StaticAuthorizeCallbackErrorPathName;
}

View File

@@ -1,3 +1,11 @@
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Editors;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
using Umbraco.Extensions;
namespace Umbraco.Cms.Core.PropertyEditors;
[DataEditor(
@@ -9,4 +17,65 @@ public class MemberGroupPickerPropertyEditor : DataEditor
public MemberGroupPickerPropertyEditor(IDataValueEditorFactory dataValueEditorFactory)
: base(dataValueEditorFactory)
=> SupportsReadOnly = true;
protected override IDataValueEditor CreateValueEditor() =>
DataValueEditorFactory.Create<MemberGroupPickerPropertyValueEditor>(Attribute!);
private class MemberGroupPickerPropertyValueEditor : DataValueEditor
{
private readonly IMemberGroupService _memberGroupService;
public MemberGroupPickerPropertyValueEditor(
IShortStringHelper shortStringHelper,
IJsonSerializer jsonSerializer,
IIOHelper ioHelper,
DataEditorAttribute attribute,
IMemberGroupService memberGroupService)
: base(shortStringHelper, jsonSerializer, ioHelper, attribute)
=> _memberGroupService = memberGroupService;
public override object? ToEditor(IProperty property, string? culture = null, string? segment = null)
{
// the stored value is a CSV of member group integer IDs - need to transform them into the corresponding member group keys
var value = base.ToEditor(property, culture, segment);
if (value is not string stringValue || stringValue.IsNullOrWhiteSpace())
{
return value;
}
var memberGroupIds = stringValue
.Split(Constants.CharArrays.Comma)
.Select(memberGroupIdStringValue =>
int.TryParse(memberGroupIdStringValue, out int memberId) ? memberId : -1)
.Where(id => id > 0)
.ToArray();
IEnumerable<IMemberGroup> memberGroups = _memberGroupService.GetByIdsAsync(memberGroupIds).GetAwaiter().GetResult();
return string.Join(',', memberGroups.Select(group => group.Key));
}
public override object? FromEditor(ContentPropertyData editorValue, object? currentValue)
{
// the editor value is a CSV of member group keys - need to store a CSV of the corresponding member group integer IDs
if (editorValue.Value is not string stringValue)
{
return null;
}
Guid[] memberGroupKeys = stringValue
.Split(Constants.CharArrays.Comma)
.Select(memberGroupKeyStringValue => Guid.TryParse(memberGroupKeyStringValue, out Guid memberGroupKey)
? memberGroupKey
: Guid.Empty)
.Where(memberGroupKey => memberGroupKey != Guid.Empty)
.ToArray();
IMemberGroup[] memberGroups = memberGroupKeys
.Select(memberGroupKey => _memberGroupService.GetAsync(memberGroupKey).GetAwaiter().GetResult())
.WhereNotNull()
.ToArray();
return string.Join(',', memberGroups.Select(memberGroup => memberGroup.Id));
}
}
}

View File

@@ -56,7 +56,7 @@ internal class TemporaryFileUploadValidator : IValueValidator
}
ContentSettings contentSettings = _getContentSettings();
if (contentSettings.IsFileAllowedForUpload(extension) || (_validateFileType != null && _validateFileType(extension, dataTypeConfiguration) == false))
if (contentSettings.IsFileAllowedForUpload(extension) is false || (_validateFileType != null && _validateFileType(extension, dataTypeConfiguration) == false))
{
yield return new ValidationResult(
$"The file type for file name \"{temporaryFile.FileName}\" is not valid for upload",