zeroframework/Services/DeviceCenter/ZeroFramework.DeviceCenter.API/Controllers/ConfigurationsController.cs
2023-12-05 17:22:48 +08:00

182 lines
7.4 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using System.Globalization;
using System.Reflection;
using System.Text.RegularExpressions;
using ZeroFramework.DeviceCenter.Application.Services.Permissions;
namespace ZeroFramework.DeviceCenter.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ConfigurationsController(ILogger<ConfigurationsController> logger,
IHttpContextAccessor httpContextAccessor,
IOptions<AuthorizationOptions> authorizationOptions,
IOptions<RequestLocalizationOptions> requestLocalizationOptions,
IPermissionDefinitionManager permissionDefinitionManager,
IPermissionChecker permissionChecker,
IAuthorizationService authorizationService,
IStringLocalizerFactory stringLocalizerFactory) : ControllerBase
{
private readonly ILogger<ConfigurationsController> _logger = logger ?? NullLogger<ConfigurationsController>.Instance;
private readonly AuthorizationOptions _authorizationOptions = authorizationOptions.Value;
private readonly RequestLocalizationOptions _requestLocalizationOptions = requestLocalizationOptions.Value;
private readonly IPermissionDefinitionManager _permissionDefinitionManager = permissionDefinitionManager;
private readonly IPermissionChecker _permissionChecker = permissionChecker;
private readonly IAuthorizationService _authorizationService = authorizationService;
private readonly IHttpContextAccessor _httpContextAccessor = httpContextAccessor;
private readonly IStringLocalizerFactory _stringLocalizerFactory = stringLocalizerFactory;
[HttpGet]
[AllowAnonymous]
public async Task<ApplicationConfiguration> GetAsync()
{
_logger.LogDebug("Executing ConfigurationApplicationService.GetAsync()...");
var result = new ApplicationConfiguration
{
Permissions = await GetPermissionConfigurationAsync()
};
_logger.LogDebug("Executed ConfigurationApplicationService.GetAsync().");
return result;
}
[Serializable]
public class ApplicationConfiguration
{
public PermissionConfiguration? Permissions { get; set; }
public LocalizationConfiguration? Localizations { get; set; }
}
[Serializable]
public class PermissionConfiguration
{
public Dictionary<string, bool> Policies { get; set; }
public Dictionary<string, bool> GrantedPolicies { get; set; }
public PermissionConfiguration()
{
Policies = [];
GrantedPolicies = [];
}
}
[Serializable]
public class LocalizationConfiguration
{
public IEnumerable<string>? SupportedCultures { get; set; }
public string CurrentCulture { get; set; } = CultureInfo.CurrentCulture.Name;
public Dictionary<string, Dictionary<string, string>>? Values { get; set; }
}
[NonAction]
private async Task<PermissionConfiguration> GetPermissionConfigurationAsync()
{
PermissionConfiguration permissionConfiguration = new();
IEnumerable<string> policyNames = _permissionDefinitionManager.GetPermissions().Select(p => p.Name);
PropertyInfo? policyMapProperty = typeof(AuthorizationOptions).GetProperty("PolicyMap", BindingFlags.Instance | BindingFlags.NonPublic);
if (policyMapProperty is not null)
{
object? policyMapPropertyValue = policyMapProperty.GetValue(_authorizationOptions);
if (policyMapPropertyValue is not null)
{
policyNames = policyNames.Union(((IDictionary<string, Task<AuthorizationPolicy>>)policyMapPropertyValue).Keys.ToList());
}
}
List<string> permissionPolicyNames = [];
List<string> otherPolicyNames = [];
foreach (var policyName in policyNames)
{
if (_permissionDefinitionManager.GetOrNull(policyName) is not null)
{
permissionPolicyNames.Add(policyName);
}
else
{
otherPolicyNames.Add(policyName);
}
}
foreach (var policyName in otherPolicyNames)
{
permissionConfiguration.Policies[policyName] = true;
if (_httpContextAccessor is not null && _httpContextAccessor.HttpContext is not null)
{
if ((await _authorizationService.AuthorizeAsync(_httpContextAccessor.HttpContext.User, policyName)).Succeeded)
{
permissionConfiguration.GrantedPolicies[policyName] = true;
}
}
}
MultiplePermissionGrantResult result = await _permissionChecker.IsGrantedAsync(permissionPolicyNames.ToArray());
foreach (var (key, value) in result.Result)
{
permissionConfiguration.Policies[key] = true;
if (value == PermissionGrantResult.Granted)
{
permissionConfiguration.GrantedPolicies[key] = true;
}
}
return permissionConfiguration;
}
[NonAction]
#pragma warning disable IDE0051 // Remove unused private members
private async Task<LocalizationConfiguration> GetLocalizationConfigurationAsync()
#pragma warning restore IDE0051 // Remove unused private members
{
LocalizationConfiguration localizationConfiguration = new() { Values = [] };
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
string pattern = @"^(?<location>[a-zA-Z0-9.]+).Resources.(?<baseName>[a-zA-Z0-9.]+).([a-z]+-[A-Z]+.resources)$";
foreach (Assembly assembly in assemblies)
{
AssemblyName assemblyName = assembly.GetName();
if (assemblyName.Name is not null && assemblyName.Name.StartsWith("ZeroFramework"))
{
string[] resourceNames = assembly.GetManifestResourceNames();
foreach (var resourceName in resourceNames)
{
Match match = Regex.Match(resourceName, pattern, RegexOptions.IgnoreCase);
if (match.Success)
{
string baseName = match.Groups["baseName"].Value.TrimEnd('.');
string location = match.Groups["location"].Value;
var stringLocalizer = _stringLocalizerFactory.Create(baseName, location);
var dictionary = stringLocalizer.GetAllStrings(true).ToDictionary(s => s.Name, s => s.Value);
localizationConfiguration.Values.TryAdd($"{location}.{baseName}", dictionary);
}
}
}
}
localizationConfiguration.SupportedCultures = _requestLocalizationOptions.SupportedCultures?.Select(sc => sc.Name);
return await Task.FromResult(localizationConfiguration);
}
}
}