// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Umbraco.Cms.Core.Editors;
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Extensions;
namespace Umbraco.Cms.Web.BackOffice.Authorization
{
///
/// If the users being edited is an admin then we must ensure that the current user is also an admin.
///
public class AdminUsersHandler : MustSatisfyRequirementAuthorizationHandler
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IUserService _userService;
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
private readonly UserEditorAuthorizationHelper _userEditorAuthorizationHelper;
///
/// Initializes a new instance of the class.
///
/// Accessor for the HTTP context of the current request.
/// Service for user related operations.
/// Accessor for back-office security.
/// Helper for user authorization checks.
public AdminUsersHandler(
IHttpContextAccessor httpContextAccessor,
IUserService userService,
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
UserEditorAuthorizationHelper userEditorAuthorizationHelper)
{
_httpContextAccessor = httpContextAccessor;
_userService = userService;
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
_userEditorAuthorizationHelper = userEditorAuthorizationHelper;
}
///
protected override Task IsAuthorized(AuthorizationHandlerContext context, AdminUsersRequirement requirement)
{
StringValues? queryString = _httpContextAccessor.HttpContext?.Request.Query[requirement.QueryStringName];
if (!queryString.HasValue || !queryString.Value.Any())
{
// Must succeed this requirement since we cannot process it.
return Task.FromResult(true);
}
int[] userIds;
if (int.TryParse(queryString, out var userId))
{
userIds = new[] { userId };
}
else
{
var ids = _httpContextAccessor.HttpContext.Request.Query.Where(x => x.Key == requirement.QueryStringName).ToList();
if (ids.Count == 0)
{
// Must succeed this requirement since we cannot process it.
return Task.FromResult(true);
}
userIds = ids
.Select(x => x.Value.ToString())
.Select(x => x.TryConvertTo()).Where(x => x.Success).Select(x => x.Result).ToArray();
}
if (userIds.Length == 0)
{
// Must succeed this requirement since we cannot process it.
return Task.FromResult(true);
}
IEnumerable users = _userService.GetUsersById(userIds);
var isAuth = users.All(user => _userEditorAuthorizationHelper.IsAuthorized(_backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser, user, null, null, null) != false);
return Task.FromResult(isAuth);
}
}
}