start work on the backoffice project
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,6 @@ namespace Umbraco.Cms.Web.BackOffice.Authorization
|
||||
}
|
||||
|
||||
public int? NodeId { get; }
|
||||
public IMedia Media { get; }
|
||||
public IMedia? Media { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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() }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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' ">
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user