start work on the backoffice project

This commit is contained in:
Nikolaj Geisle
2022-03-30 15:58:46 +02:00
parent 05a08bef63
commit 57ed0b7b4d
27 changed files with 99 additions and 87 deletions

View File

@@ -36,10 +36,10 @@ namespace Umbraco.Cms.Core.Editors
/// <param name="startMediaIds">The start media ids of the user being saved (can be null or empty)</param>
/// <param name="userGroupAliases">The user aliases of the user being saved (can be null or empty)</param>
/// <returns></returns>
public Attempt<string?> IsAuthorized(IUser currentUser,
public Attempt<string?> IsAuthorized(IUser? currentUser,
IUser savingUser,
IEnumerable<int> startContentIds, IEnumerable<int> startMediaIds,
IEnumerable<string> userGroupAliases)
IEnumerable<int>? startContentIds, IEnumerable<int>? startMediaIds,
IEnumerable<string>? userGroupAliases)
{
var currentIsAdmin = currentUser.IsAdmin();

View File

@@ -2,7 +2,7 @@ namespace Umbraco.Cms.Core.Notifications
{
public class UserLogoutSuccessNotification : UserNotification
{
public UserLogoutSuccessNotification(string ipAddress, string affectedUserId, string performingUserId) : base(ipAddress, affectedUserId, performingUserId)
public UserLogoutSuccessNotification(string ipAddress, string? affectedUserId, string performingUserId) : base(ipAddress, affectedUserId, performingUserId)
{
}

View File

@@ -4,7 +4,7 @@ namespace Umbraco.Cms.Core.Notifications
{
public abstract class UserNotification : INotification
{
protected UserNotification(string ipAddress, string affectedUserId, string performingUserId)
protected UserNotification(string ipAddress, string? affectedUserId, string performingUserId)
{
DateTimeUtc = DateTime.UtcNow;
IpAddress = ipAddress;
@@ -25,7 +25,7 @@ namespace Umbraco.Cms.Core.Notifications
/// <summary>
/// The user affected by the event raised
/// </summary>
public string AffectedUserId { get; }
public string? AffectedUserId { get; }
/// <summary>
/// If a user is performing an action on a different user, then this will be set. Otherwise it will be -1

View File

@@ -47,7 +47,7 @@ namespace Umbraco.Cms.Core.Security
public ContentAccess CheckPermissions(
IContent content,
IUser user,
IUser? user,
IReadOnlyList<char> permissionsToCheck)
{
if (user == null) throw new ArgumentNullException(nameof(user));
@@ -70,12 +70,12 @@ namespace Umbraco.Cms.Core.Security
public ContentAccess CheckPermissions(
IUmbracoEntity entity,
IUser user,
IUser? user,
char permissionToCheck) => CheckPermissions(entity, user, new[] { permissionToCheck });
public ContentAccess CheckPermissions(
IUmbracoEntity entity,
IUser user,
IUser? user,
IReadOnlyList<char> permissionsToCheck)
{
if (user == null) throw new ArgumentNullException(nameof(user));
@@ -159,7 +159,7 @@ namespace Umbraco.Cms.Core.Security
/// <returns></returns>
public ContentAccess CheckPermissions(
int nodeId,
IUser user,
IUser? user,
out IContent? contentItem,
IReadOnlyList<char>? permissionsToCheck = null)
{

View File

@@ -38,7 +38,7 @@ namespace Umbraco.Cms.Core.Security
/// <param name="entityService"></param>
/// <param name="nodeId">The content to lookup, if the contentItem is not specified</param>
/// <returns></returns>
public MediaAccess CheckPermissions(IUser user, int nodeId, out IMedia? media)
public MediaAccess CheckPermissions(IUser? user, int nodeId, out IMedia? media)
{
if (user == null) throw new ArgumentNullException(nameof(user));
@@ -63,7 +63,7 @@ namespace Umbraco.Cms.Core.Security
return hasPathAccess ? MediaAccess.Granted : MediaAccess.Denied;
}
public MediaAccess CheckPermissions(IMedia media, IUser user)
public MediaAccess CheckPermissions(IMedia? media, IUser? user)
{
if (user == null) throw new ArgumentNullException(nameof(user));

View File

@@ -120,7 +120,7 @@ namespace Umbraco.Cms.Core.Services
/// </summary>
/// <param name="ids">Ids of the users to retrieve</param>
/// <returns><see cref="IUser"/></returns>
IEnumerable<IUser> GetUsersById(params int[] ids);
IEnumerable<IUser> GetUsersById(params int[]? ids);
/// <summary>
/// Removes a specific section from all user groups

View File

@@ -687,9 +687,9 @@ namespace Umbraco.Cms.Core.Services
}
}
public IEnumerable<IUser> GetUsersById(params int[] ids)
public IEnumerable<IUser> GetUsersById(params int[]? ids)
{
if (ids.Length <= 0) return Enumerable.Empty<IUser>();
if (ids?.Length <= 0) return Enumerable.Empty<IUser>();
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
{

View File

@@ -10,6 +10,6 @@ namespace Umbraco.Cms.Core.Security
{
void NotifyForgotPasswordRequested(IPrincipal currentUser, string userId);
void NotifyForgotPasswordChanged(IPrincipal currentUser, string userId);
SignOutSuccessResult NotifyLogoutSuccess(IPrincipal currentUser, string userId);
SignOutSuccessResult NotifyLogoutSuccess(IPrincipal currentUser, string? userId);
}
}

View File

@@ -57,35 +57,35 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
return Task.FromResult(true);
}
int[] userIds;
int[]? userIds;
if (int.TryParse(queryString, NumberStyles.Integer, CultureInfo.InvariantCulture, out var userId))
{
userIds = new[] { userId };
}
else
{
var ids = queryString.ToString().Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries).ToList();
if (ids.Count == 0)
var ids = queryString.ToString()?.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries).ToList();
if (ids?.Count == 0)
{
// Must succeed this requirement since we cannot process it.
return Task.FromResult(true);
}
userIds = ids
userIds = ids?
.Select(x => int.TryParse(x, NumberStyles.Integer, CultureInfo.InvariantCulture, out var output) ? Attempt<int>.Succeed(output) : Attempt<int>.Fail())
.Where(x => x.Success)
.Select(x => x.Result)
.ToArray();
}
if (userIds.Length == 0)
if (userIds?.Length == 0)
{
// Must succeed this requirement since we cannot process it.
return Task.FromResult(true);
}
IEnumerable<IUser> users = _userService.GetUsersById(userIds);
var isAuth = users.All(user => _userEditorAuthorizationHelper.IsAuthorized(_backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser, user, null, null, null) != false);
var isAuth = users.All(user => _userEditorAuthorizationHelper.IsAuthorized(_backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser, user, null, null, null) != false);
return Task.FromResult(isAuth);
}

View File

@@ -34,12 +34,12 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
case var _ when _runtimeState.EnableInstaller():
return Task.FromResult(true);
default:
if (!_backOfficeSecurity.BackOfficeSecurity.IsAuthenticated())
if (!_backOfficeSecurity.BackOfficeSecurity?.IsAuthenticated() ?? false)
{
return Task.FromResult(false);
}
var userApprovalSucceeded = !requirement.RequireApproval || (_backOfficeSecurity.BackOfficeSecurity.CurrentUser?.IsApproved ?? false);
var userApprovalSucceeded = !requirement.RequireApproval || (_backOfficeSecurity.BackOfficeSecurity?.CurrentUser?.IsApproved ?? false);
return Task.FromResult(userApprovalSucceeded);
}
}

View File

@@ -42,7 +42,7 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
/// <inheritdoc/>
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, ContentPermissionsPublishBranchRequirement requirement, IContent resource)
{
IUser currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser;
IUser? currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser;
var denied = new List<IUmbracoEntity>();
var page = 0;

View File

@@ -38,7 +38,7 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
int nodeId;
if (requirement.NodeId.HasValue == false)
{
if (!HttpContextAccessor.HttpContext.Request.Query.TryGetValue(requirement.QueryStringName, out StringValues routeVal))
if (HttpContextAccessor.HttpContext is null || requirement.QueryStringName is null || !HttpContextAccessor.HttpContext.Request.Query.TryGetValue(requirement.QueryStringName, out StringValues routeVal))
{
// Must succeed this requirement since we cannot process it
return Task.FromResult(true);
@@ -61,11 +61,11 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
ContentPermissions.ContentAccess permissionResult = _contentPermissions.CheckPermissions(
nodeId,
BackOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
out IContent contentItem,
BackOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser,
out IContent? contentItem,
new[] { requirement.PermissionToCheck });
if (contentItem != null)
if (HttpContextAccessor.HttpContext is not null && contentItem is not null)
{
// Store the content item in request cache so it can be resolved in the controller without re-looking it up.
HttpContextAccessor.HttpContext.Items[typeof(IContent).ToString()] = contentItem;

View File

@@ -41,7 +41,7 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
/// <summary>
/// Gets the querystring parameter name.
/// </summary>
public string QueryStringName { get; }
public string? QueryStringName { get; }
/// <summary>
/// Gets the permission to authorize the current user against.

View File

@@ -35,12 +35,12 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
ContentPermissions.ContentAccess permissionResult = resource.NodeId.HasValue
? _contentPermissions.CheckPermissions(
resource.NodeId.Value,
_backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
out IContent _,
_backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser,
out IContent? _,
resource.PermissionsToCheck)
: _contentPermissions.CheckPermissions(
resource.Content,
_backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
_backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser,
resource.PermissionsToCheck);
return Task.FromResult(permissionResult != ContentPermissions.ContentAccess.Denied);

View File

@@ -35,7 +35,7 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
/// <inheritdoc/>
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, MediaPermissionsQueryStringRequirement requirement)
{
if (!HttpContextAccessor.HttpContext.Request.Query.TryGetValue(requirement.QueryStringName, out StringValues routeVal))
if (HttpContextAccessor.HttpContext is null || !HttpContextAccessor.HttpContext.Request.Query.TryGetValue(requirement.QueryStringName, out StringValues routeVal))
{
// Must succeed this requirement since we cannot process it.
return Task.FromResult(true);
@@ -50,9 +50,9 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
}
MediaPermissions.MediaAccess permissionResult = _mediaPermissions.CheckPermissions(
BackOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
BackOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser,
nodeId,
out IMedia mediaItem);
out IMedia? mediaItem);
if (mediaItem != null)
{

View File

@@ -18,6 +18,6 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
}
public int? NodeId { get; }
public IMedia Media { get; }
public IMedia? Media { get; }
}
}

View File

@@ -34,12 +34,12 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
{
MediaPermissions.MediaAccess permissionResult = resource.NodeId.HasValue
? _mediaPermissions.CheckPermissions(
_backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
_backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser,
resource.NodeId.Value,
out _)
: _mediaPermissions.CheckPermissions(
resource.Media,
_backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser);
_backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser);
return Task.FromResult(permissionResult != MediaPermissions.MediaAccess.Denied);
}

View File

@@ -67,7 +67,7 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
nodeId = parsedId;
return true;
}
else if (UdiParser.TryParse(argument, true, out Udi udi))
else if (UdiParser.TryParse(argument, true, out Udi? udi))
{
nodeId = EntityService.GetId(udi).Result;
return true;

View File

@@ -27,7 +27,7 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
/// <inheritdoc/>
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, SectionRequirement requirement)
{
var authorized = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser != null &&
var authorized = _backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser != null &&
requirement.SectionAliases
.Any(app => _backOfficeSecurityAccessor.BackOfficeSecurity.UserHasSectionAccess(
app, _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser));

View File

@@ -44,7 +44,7 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
.Distinct()
.ToArray();
var isAuth = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser != null &&
var isAuth = _backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser != null &&
apps.Any(app => _backOfficeSecurityAccessor.BackOfficeSecurity.UserHasSectionAccess(
app, _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser));

View File

@@ -61,7 +61,7 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
/// <inheritdoc/>
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, UserGroupRequirement requirement)
{
IUser currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser;
IUser? currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser;
var querystring = _httpContextAccessor.HttpContext?.Request.Query[requirement.QueryStringName];
if (querystring is null)
@@ -87,7 +87,7 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
_entityService,
_appCaches);
Attempt<string> isAuth = authHelper.AuthorizeGroupAccess(currentUser, intIds);
Attempt<string?> isAuth = authHelper.AuthorizeGroupAccess(currentUser, intIds);
return Task.FromResult(isAuth.Success);
}

View File

@@ -127,7 +127,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
[Authorize(Policy = AuthorizationPolicies.BackOfficeAccess)] // Needed to enforce the principle set on the request, if one exists.
public IDictionary<string, object> GetPasswordConfig(int userId)
{
Attempt<int?> currentUserId = _backofficeSecurityAccessor.BackOfficeSecurity.GetUserId();
Attempt<int?> currentUserId = _backofficeSecurityAccessor.BackOfficeSecurity?.GetUserId() ?? Attempt<int?>.Fail();
return _passwordConfiguration.GetConfiguration(
currentUserId.Success
? currentUserId.Result != userId
@@ -592,7 +592,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
_logger.LogInformation("User {UserName} from IP address {RemoteIpAddress} has logged out", User.Identity == null ? "UNKNOWN" : User.Identity.Name, HttpContext.Connection.RemoteIpAddress);
var userId = result.Principal.Identity.GetUserId();
var userId = result.Principal.Identity?.GetUserId();
var args = _userManager.NotifyLogoutSuccess(User, userId);
if (!args.SignOutRedirectUrl.IsNullOrWhiteSpace())
{
@@ -612,13 +612,17 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
/// <param name="user"></param>
/// <param name="principal"></param>
/// <returns></returns>
private UserDetail GetUserDetail(IUser user)
private UserDetail? GetUserDetail(IUser? user)
{
if (user == null) throw new ArgumentNullException(nameof(user));
var userDetail = _umbracoMapper.Map<UserDetail>(user);
// update the userDetail and set their remaining seconds
userDetail.SecondsUntilTimeout = _globalSettings.TimeOut.TotalSeconds;
if (userDetail is not null)
{
// update the userDetail and set their remaining seconds
userDetail.SecondsUntilTimeout = _globalSettings.TimeOut.TotalSeconds;
}
return userDetail;
}

View File

@@ -13,7 +13,9 @@ using Umbraco.Cms.Core.Features;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Mail;
using Umbraco.Cms.Core.Media;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Models.TemplateQuery;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Trees;
using Umbraco.Cms.Core.WebAssets;
@@ -24,6 +26,7 @@ using Umbraco.Cms.Web.BackOffice.Routing;
using Umbraco.Cms.Web.BackOffice.Security;
using Umbraco.Cms.Web.BackOffice.Trees;
using Umbraco.Cms.Web.Common.Attributes;
using Umbraco.Cms.Web.Common.Models;
using Umbraco.Extensions;
namespace Umbraco.Cms.Web.BackOffice.Controllers
@@ -136,7 +139,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
// TODO: This is ultra confusing! this same key is used for different things, when returning the full app when authenticated it is this URL but when not auth'd it's actually the ServerVariables address
// so based on compat and how things are currently working we need to replace the serverVarsJs one
((Dictionary<string, object>)defaults["umbracoUrls"])["serverVarsJs"]
((Dictionary<string, object?>)defaults["umbracoUrls"])["serverVarsJs"]
= _linkGenerator.GetPathByAction(
nameof(BackOfficeController.ServerVariables),
ControllerExtensions.GetControllerName<BackOfficeController>(),
@@ -156,7 +159,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
var defaultVals = new Dictionary<string, object>
{
{
"umbracoUrls", new Dictionary<string, object>
"umbracoUrls", new Dictionary<string, object?>
{
// TODO: Add 'umbracoApiControllerBaseUrl' which people can use in JS
// to prepend their URL. We could then also use this in our own resources instead of
@@ -186,15 +189,15 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
},
{
"userApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<UsersController>(
controller => controller.PostSaveUser(null))
controller => controller.PostSaveUser(new UserSave()))
},
{
"userGroupsApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<UserGroupsController>(
controller => controller.PostSaveUserGroup(null))
controller => controller.PostSaveUserGroup(new UserGroupSave()))
},
{
"contentApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<ContentController>(
controller => controller.PostSave(null))
controller => controller.PostSave(new ContentItemSave()))
},
{
"publicAccessApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<PublicAccessController>(
@@ -218,7 +221,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
},
{
"treeApplicationApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<ApplicationTreeController>(
controller => controller.GetApplicationTrees(null, null, null, TreeUse.None))
controller => controller.GetApplicationTrees(string.Empty, string.Empty, FormCollection.Empty, TreeUse.None))
},
{
"contentTypeApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<ContentTypeController>(
@@ -234,15 +237,15 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
},
{
"macroApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<MacrosController>(
controller => controller.Create(null))
controller => controller.Create(string.Empty))
},
{
"authenticationApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<AuthenticationController>(
controller => controller.PostLogin(null))
controller => controller.PostLogin(new LoginModel()))
},
{
"currentUserApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<CurrentUserController>(
controller => controller.PostChangePassword(null))
controller => controller.PostChangePassword(new ChangingPasswordModel()))
},
{
"entityApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<EntityController>(
@@ -254,7 +257,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
},
{
"dashboardApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<DashboardController>(
controller => controller.GetDashboard(null))
controller => controller.GetDashboard(string.Empty))
},
{
"logApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<LogController>(
@@ -302,15 +305,15 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
},
{
"memberTreeBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<MemberTreeController>(
controller => controller.GetNodes("-1", null))
controller => controller.GetNodes("-1", FormCollection.Empty))
},
{
"mediaTreeBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<MediaTreeController>(
controller => controller.GetNodes("-1", null))
controller => controller.GetNodes("-1", FormCollection.Empty))
},
{
"contentTreeBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<ContentTreeController>(
controller => controller.GetNodes("-1", null))
controller => controller.GetNodes("-1", FormCollection.Empty))
},
{
"tagsDataBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<TagsDataController>(
@@ -326,7 +329,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
},
{
"templateQueryApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<TemplateQueryController>(
controller => controller.PostTemplateQuery(null))
controller => controller.PostTemplateQuery(new QueryModel()))
},
{
"codeFileApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<CodeFileController>(
@@ -370,11 +373,11 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
},
{
"tinyMceApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<TinyMceController>(
controller => controller.UploadImage(null))
controller => controller.UploadImage(new FormFileCollection()))
},
{
"imageUrlGeneratorApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<ImageUrlGeneratorController>(
controller => controller.GetCropUrl(null, null, null, null))
controller => controller.GetCropUrl(string.Empty, null, null, null))
},
{
"elementTypeApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl<ElementTypeController>(
@@ -481,10 +484,10 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
private class PluginTree
{
[DataMember(Name = "alias")]
public string Alias { get; set; }
public string? Alias { get; set; }
[DataMember(Name = "packageFolder")]
public string PackageFolder { get; set; }
public string? PackageFolder { get; set; }
}
private IEnumerable<PluginTree> GetPluginTrees()
@@ -520,10 +523,10 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
/// Returns the server variables regarding the application state
/// </summary>
/// <returns></returns>
private Dictionary<string, object> GetApplicationState()
private Dictionary<string, object?> GetApplicationState()
{
var version = _runtimeState.SemanticVersion.ToSemanticStringWithoutBuild();
var app = new Dictionary<string, object>
var app = new Dictionary<string, object?>
{
// add versions - see UmbracoVersion for details & differences
@@ -531,7 +534,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
{ "version", version },
// the assembly version (eg "8.0.0")
{ "assemblyVersion", _umbracoVersion.AssemblyVersion.ToString() }
{ "assemblyVersion", _umbracoVersion.AssemblyVersion?.ToString() }
};

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
@@ -33,17 +34,19 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
/// <param name="currentUser"></param>
/// <param name="groupIds"></param>
/// <returns></returns>
public Attempt<string> AuthorizeGroupAccess(IUser currentUser, params int[] groupIds)
public Attempt<string?> AuthorizeGroupAccess(IUser? currentUser, params int[] groupIds)
{
if (currentUser.IsAdmin())
return Attempt<string>.Succeed();
if (currentUser?.IsAdmin() ?? false)
{
return Attempt<string?>.Succeed();
}
var groups = _userService.GetAllUserGroups(groupIds.ToArray());
var groupAliases = groups.Select(x => x.Alias).ToArray();
var userGroups = currentUser.Groups.Select(x => x.Alias).ToArray();
var userGroups = currentUser?.Groups.Select(x => x.Alias).ToArray() ?? Array.Empty<string>();
var missingAccess = groupAliases.Except(userGroups).ToArray();
return missingAccess.Length == 0
? Attempt<string>.Succeed()
? Attempt<string?>.Succeed()
: Attempt.Fail("User is not a member of " + string.Join(", ", missingAccess));
}
@@ -53,10 +56,10 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
/// <param name="currentUser"></param>
/// <param name="groupAliases"></param>
/// <returns></returns>
public Attempt<string> AuthorizeGroupAccess(IUser currentUser, params string[] groupAliases)
public Attempt<string?> AuthorizeGroupAccess(IUser currentUser, params string[] groupAliases)
{
if (currentUser.IsAdmin())
return Attempt<string>.Succeed();
return Attempt<string?>.Succeed();
var existingGroups = _userService.GetUserGroupsByAlias(groupAliases);
@@ -65,32 +68,32 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
// We're dealing with new groups,
// so authorization should be given to any user with access to Users section
if (currentUser.AllowedSections.Contains(Constants.Applications.Users))
return Attempt<string>.Succeed();
return Attempt<string?>.Succeed();
}
var userGroups = currentUser.Groups.Select(x => x.Alias).ToArray();
var missingAccess = groupAliases.Except(userGroups).ToArray();
return missingAccess.Length == 0
? Attempt<string>.Succeed()
? Attempt<string?>.Succeed()
: Attempt.Fail("User is not a member of " + string.Join(", ", missingAccess));
}
/// <summary>
/// Authorize that the user is not adding a section to the group that they don't have access to
/// </summary>
public Attempt<string> AuthorizeSectionChanges(
public Attempt<string?> AuthorizeSectionChanges(
IUser currentUser,
IEnumerable<string> existingSections,
IEnumerable<string> proposedAllowedSections)
{
if (currentUser.IsAdmin())
return Attempt<string>.Succeed();
return Attempt<string?>.Succeed();
var sectionsAdded = proposedAllowedSections.Except(existingSections).ToArray();
var sectionAccessMissing = sectionsAdded.Except(currentUser.AllowedSections).ToArray();
return sectionAccessMissing.Length > 0
? Attempt.Fail("Current user doesn't have access to add these sections " + string.Join(", ", sectionAccessMissing))
: Attempt<string>.Succeed();
: Attempt<string?>.Succeed();
}
/// <summary>
@@ -102,7 +105,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
/// <param name="currentMediaStartId"></param>
/// <param name="proposedMediaStartId"></param>
/// <returns></returns>
public Attempt<string> AuthorizeStartNodeChanges(IUser currentUser,
public Attempt<string?> AuthorizeStartNodeChanges(IUser currentUser,
int? currentContentStartId,
int? proposedContentStartId,
int? currentMediaStartId,
@@ -128,7 +131,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
}
}
return Attempt<string>.Succeed();
return Attempt<string?>.Succeed();
}
}
}

View File

@@ -36,7 +36,7 @@ namespace Umbraco.Cms.Web.BackOffice.PropertyEditors
/// <returns></returns>
///
[AllowHttpJsonConfigration]
public IEnumerable<TagModel> GetTags(string tagGroup, string culture, string query = null)
public IEnumerable<TagModel> GetTags(string tagGroup, string? culture, string? query = null)
{
if (culture == string.Empty) culture = null;

View File

@@ -7,6 +7,8 @@
<PackageId>Umbraco.Cms.Web.BackOffice</PackageId>
<Title>Umbraco CMS Back Office</Title>
<Description>Contains the Back Office assembly needed to run the back office of Umbraco Cms. This package only contains the assembly, and can be used for package development. Use the template in the Umbraco.Templates package to setup Umbraco</Description>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">

View File

@@ -204,7 +204,7 @@ namespace Umbraco.Cms.Web.Common.Security
(currentUserId, ip) => new UserLoginSuccessNotification(ip, userId, currentUserId)
);
public SignOutSuccessResult NotifyLogoutSuccess(IPrincipal currentUser, string userId)
public SignOutSuccessResult NotifyLogoutSuccess(IPrincipal currentUser, string? userId)
{
var notification = Notify(currentUser,
(currentUserId, ip) => new UserLogoutSuccessNotification(ip, userId, currentUserId)