// 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); } } }