RbacAccessPermissionHelper.cs 2.65 KB
using System.Text.Json;

namespace FoodLabeling.Application.Helpers;

/// <summary>
/// accessPermissions 与 Menu.PermissionCode / Router 的解析辅助。
/// </summary>
public static class RbacAccessPermissionHelper
{
    /// <summary>
    /// 从路由推导权限码:/labels → menu.labels;/account-management → menu.account-management
    /// </summary>
    public static string? DerivePermissionCodeFromRouter(string? router)
    {
        var r = router?.Trim();
        if (string.IsNullOrEmpty(r))
        {
            return null;
        }

        var path = r.TrimEnd('/');
        if (path.Length == 0)
        {
            return null;
        }

        var segments = path.Split('/', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
        if (segments.Length == 0)
        {
            return null;
        }

        return "menu." + string.Join(".", segments.Select(s => s.ToLowerInvariant()));
    }

    /// <summary>
    /// 优先使用 PermissionCode;为空时按 Router 推导(与回填 SQL 规则一致)。
    /// </summary>
    public static string? GetEffectivePermissionCode(string? permissionCode, string? router)
    {
        if (!string.IsNullOrWhiteSpace(permissionCode))
        {
            return permissionCode.Trim();
        }

        return DerivePermissionCodeFromRouter(router);
    }

    /// <summary>
    /// 解析 accessPermissions 入参:支持 JSON 数组字符串(如 <c>["manage_labels"]</c>)、英文逗号分隔。
    /// </summary>
    public static List<string> ParseAccessPermissionCodes(string accessPermissions)
    {
        var raw = accessPermissions?.Trim();
        if (string.IsNullOrWhiteSpace(raw))
        {
            return new List<string>();
        }

        if (raw.StartsWith('['))
        {
            try
            {
                var fromJson = JsonSerializer.Deserialize<List<string>>(raw);
                if (fromJson is { Count: > 0 })
                {
                    return fromJson
                        .Where(c => !string.IsNullOrWhiteSpace(c))
                        .Select(c => c.Trim())
                        .Distinct(StringComparer.OrdinalIgnoreCase)
                        .ToList();
                }
            }
            catch
            {
                // fall through to delimiter split
            }
        }

        return raw
            .Split(new[] { ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
            .Where(c => !string.IsNullOrWhiteSpace(c))
            .Select(c => c.Trim())
            .Distinct(StringComparer.OrdinalIgnoreCase)
            .ToList();
    }
}