网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
using System.ComponentModel;
using System.IdentityModel.Tokens.Jwt;
using System.Web;
using AngleSharp;
using Dpz.Core.EnumLibrary;
using Dpz.Core.Public.ViewModel.V4;
using Dpz.Core.Service.ObjectStorage.Services;
using Dpz.Core.Service.V4.Services;
using Dpz.Core.Web.Models;
using Dpz.Core.Web.Pager;
using Ganss.Xss;
using Markdig;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using IConfiguration = Microsoft.Extensions.Configuration.IConfiguration;

namespace Dpz.Core.Web.Library;

public static class WebToolsExtensions
{
    public static readonly string Version = Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "";

    public const string DefaultGroupId = "5e09be6ae22e4d3b7810b6c7";

    public static readonly Dictionary<int, string> Wind = new()
    {
        { 0, "静风" },
        { 1, "软风" },
        { 2, "轻风" },
        { 3, "微风" },
        { 4, "和风" },
        { 5, "清风" },
        { 6, "强风" },
        { 7, "疾风" },
        { 8, "大风" },
        { 9, "强大风" },
        { 10, "超强大风" },
        { 11, "暴风" },
        { 12, "飓风" },
    };

    /// <summary>
    /// 系统启动时间
    /// </summary>
    public static readonly DateTime StartTime = new(2018, 2, 11, 13, 56, 24, DateTimeKind.Local);

    /// <summary>
    /// 根据Identity反射获取当前用户信息
    /// 未授权用户返回 null
    /// </summary>
    /// <param name="principal"></param>
    /// <returns></returns>
    public static VmUserInfo? GetIdentity(this ClaimsPrincipal principal)
    {
        if (principal.IsLogin())
        {
            var userInfo = new VmUserInfo();
            foreach (var claims in principal.Claims)
            {
                var property = typeof(VmUserInfo).GetProperty(claims.Type);
                if (property == null) continue;
                if (property.PropertyType == typeof(DateTime?))
                {
                    property.SetValue(userInfo, DateTime.Parse(claims.Value));
                }
                else if (property.PropertyType == typeof(Sex))
                {
                    var sex = Enum.Parse(typeof(Sex), claims.Value);
                    property.SetValue(userInfo, sex);
                }
                else if (property.PropertyType == typeof(bool?))
                {
                    bool.TryParse(claims.Value, out var result);
                    property.SetValue(userInfo, result);
                }
                else if (property.PropertyType == typeof(Permissions?))
                {
                    if (Enum.TryParse(claims.Value, out Permissions permissions))
                    {
                        property.SetValue(userInfo, permissions);
                    }
                }
                else
                {
                    typeof(VmUserInfo).GetProperty(claims.Type)?.SetValue(userInfo, claims.Value);
                }
            }

            return userInfo;
        }

        return null;
    }

    public static VmUserInfo GetStrictIdentity(this ClaimsPrincipal principal)
    {
        return principal.GetIdentity() ?? throw new InvalidCredentialException();
    }

    public static VmUserInfo? GetIdentity(this HttpContext httpContext, TokenManagement? token)
    {
        if (token?.Secret == null)
        {
            return httpContext.User.GetIdentity();
        }

        var validated = httpContext.ValidationJwtBearer(token);
        if (!validated)
            return null;
        return httpContext.User.GetIdentity();
    }

    public static bool ValidationJwtBearer(this HttpContext httpContext, TokenManagement token)
    {
        string? bearerToken = httpContext.Request.Headers["Authorization"];
        bearerToken = bearerToken?.Replace($"{JwtBearerDefaults.AuthenticationScheme} ", "");
        if (!string.IsNullOrEmpty(bearerToken))
        {
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidIssuer = token.Issuer,
                ValidAudience = token.Audience,
                ValidateIssuer = true,
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(token.Secret)),
                ValidateLifetime = true
            };
            try
            {
                var principal =
                    new JwtSecurityTokenHandler().ValidateToken(bearerToken, tokenValidationParameters,
                        out var securityToken);
                if (principal.Identity?.IsAuthenticated == true &&
                    securityToken is JwtSecurityToken jwtSecurityToken &&
                    jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256,
                        StringComparison.InvariantCultureIgnoreCase))
                {
                    httpContext.User = principal;
                    return true;
                }
            }
            catch (Exception e)
            {
                Log.Logger.Error(e, "validation jwt fail");
                return false;
            }
        }

        return false;
    }

    public static VmUserInfo? GetIdentity(this Controller controller)
    {
        return controller.ViewData["CurrentUser"] as VmUserInfo;
    }

    public static bool IsAdmin(this ClaimsPrincipal principal)
    {
        var identity = principal.GetIdentity();
        if (identity?.Permissions == null) return false;
        return identity.Permissions.Value.HasFlag(Permissions.System);
    }

    /// <summary>
    /// 获取当前用户信息
    /// 未授权用户返回 null 
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public static async Task<VmUserInfo?> GetUserInfo(this HttpContext context)
    {
        var auth = await context.AuthenticateAsync(Program.AuthorizeCookieName);
        if (auth.Succeeded && auth.Principal?.IsLogin() == true)
        {
            return auth.Principal.GetIdentity();
        }

        return null;
    }

    public static bool IsLogin(this ClaimsPrincipal? principal)
    {
        return principal?.Identity?.IsAuthenticated == true;
    }

    /// <summary>
    /// 获取SessionId
    /// </summary>
    /// <param name="controller"></param>
    /// <returns></returns>
    public static string? SessionId(this Controller controller)
    {
        return controller.ViewData["SessionId"]?.ToString();
    }

    /// <summary>
    /// 获取IP地址
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    public static string GetIpAddress(this HttpRequest? request)
    {
        if (request == null) return "";
#if DEBUG
        return "113.110.235.52";
#endif
        var xff = request.Headers["X-Forwarded-For"];
        return string.IsNullOrEmpty(xff)
            ? request.HttpContext.Connection.RemoteIpAddress.ToString()
            : xff.ToString();
    }

    /// <summary>
    /// 设置标题
    /// </summary>
    /// <param name="controller"></param>
    /// <param name="title"></param>
    public static void SetTitle(this Controller controller, string title)
    {
        controller.ViewData["Title"] = $"{title} - 叫我阿胖";
    }


    /// <summary>
    /// 是否为ajax请求
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    public static bool IsAjax(this HttpRequest request)
    {
        var with = request.Headers["X-Requested-With"];
        return string.Equals(with, "XMLHttpRequest", StringComparison.OrdinalIgnoreCase);
    }

    public static async Task<List<SelectListItem>> ArticleTagsAsync(this IArticleService articleService)
    {
        var tags = await articleService.GetAllTagsAsync();
        return tags.Select(x => new SelectListItem(x, x)).ToList();
    }

    /// <summary>
    /// 获取枚举描述
    /// </summary>
    /// <param name="e"></param>
    /// <returns></returns>
    public static string GetDescription(this Enum e)
    {
        var value = e.ToString();
        var attribute = e.GetType().GetField(value)?.GetCustomAttribute<DescriptionAttribute>();
        return attribute?.Description ?? "";
    }

    /// <summary>
    /// 个性化显示文件大小
    /// </summary>
    /// <param name="length"></param>
    /// <returns></returns>
    public static string FileSize(this long length)
    {
        var sizeText = length + " bytes";
        if (length > 1024m && length < 1024m * 1024m * 3)
        {
            sizeText = (length / 1024m).ToString("F") + " KB";
        }
        else if (length > 1024m * 1024m * 3 && length < 1024m * 1024m * 1024m)
        {
            sizeText = (length / 1024m / 1024m).ToString("F") + " MB";
        }
        else if (length > 1024m * 1024m * 1024m)
        {
            sizeText = (length / 1024m / 1024m / 1024m).ToString("F") + " GB";
        }

        return sizeText;
    }

    public static Dictionary<string, List<string>> GetPublicAction()
    {
        var controllers = Assembly.GetExecutingAssembly().GetExportedTypes()
            .Where(x => x.Namespace == "Dpz.Core.Web.Controllers");
        var actions = controllers.ToDictionary(x => x.Name, x =>
        {
            return x.GetMethods().Where(y =>
                    y.IsPublic &&
                    y.ReturnType == typeof(Task<IActionResult>) &&
                    y.GetCustomAttribute<CheckAuthorizeAttribute>() == null)
                .Select(y => y.Name)
                .ToList();
        });
        return actions;
    }

    public static object ToGridManagerSource<T>(this IPagedList<T> source)
    {
        return new { totals = source.TotalItemCount, data = source };
    }

    public static IHtmlSanitizer CustomHtmlSanitizer(this IConfiguration configuration)
    {
        var sanitizer = new HtmlSanitizer();

        var rule = configuration.GetSection("XSS").Get<CrossSiteRule>();
        if (rule != null)
        {
            if (rule.Attributes?.Add?.Length > 0)
            {
                rule.Attributes.Add.ForEach(x => sanitizer.AllowedAttributes.Add(x));
            }

            if (rule.Attributes?.Remove?.Length > 0)
            {
                rule.Attributes.Remove.ForEach(x => sanitizer.AllowedAttributes.Remove(x));
            }

            if (rule.Tags?.Add?.Length > 0)
            {
                rule.Tags.Add.ForEach(x => sanitizer.AllowedTags.Add(x));
            }

            if (rule.Tags?.Remove?.Length > 0)
            {
                rule.Tags.Remove.ForEach(x => sanitizer.AllowedTags.Remove(x));
            }

            if (rule.CssProperties?.Add?.Length > 0)
            {
                rule.CssProperties.Add.ForEach(x => sanitizer.AllowedCssProperties.Add(x));
            }

            if (rule.CssProperties?.Remove?.Length > 0)
            {
                rule.CssProperties.Remove.ForEach(x => sanitizer.AllowedAttributes.Remove(x));
            }
        }

        return sanitizer;
    }

    /// <summary>
    /// 从markdown转成html,并从html内容中清除链接的跳转平台,并且在新标签页打开
    /// </summary>
    /// <param name="content"></param>
    /// <returns></returns>
    public static async Task<string> ClearLinkAsync(this string content)
    {
        var pipeline = new MarkdownPipelineBuilder()
            .UsePipeTables()
            .UseTaskLists()
            .UseEmphasisExtras()
            .UseAutoIdentifiers()
            .UseAdvancedExtensions()
            .DisableHtml()
            .Build();
        var detail = Markdown.ToHtml(content, pipeline);
        var context = BrowsingContext.New(Configuration.Default);
        var document = await context.OpenAsync(y => y.Content(detail));
        var images = document.GetElementsByTagName("img");
        foreach (var image in images)
        {
            var src = image.GetAttribute("src");
            image.SetAttribute("class", "lazy");
            image.SetAttribute("loading", "lazy");
            image.SetAttribute("src", $"{Program.CdnBaseAddress}/loaders/bars.svg");
            image.SetAttribute("data-src", src ?? $"{Program.CdnBaseAddress}/images/notfound.png");
        }

        var links = document.GetElementsByTagName("a");
        foreach (var item in links)
        {
            var href = item.GetAttribute("href");
            if (href != null)
            {
                var uri = new Uri(href);
                var parameters = HttpUtility.ParseQueryString(uri.Query);
                var target = parameters["target"];
                if (!string.IsNullOrEmpty(target))
                {
                    item.SetAttribute("href", target);
                }

                item.SetAttribute("target", "_blank");
            }
        }

        return document.Body?.InnerHtml ?? "";
    }

    /// <summary>
    /// 构建https的URI
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public static string ForceHttps(this string url)
    {
        var uri = new UriBuilder(url);

        var hadDefaultPort = uri.Uri.IsDefaultPort;
        uri.Scheme = Uri.UriSchemeHttps;
        uri.Port = hadDefaultPort ? -1 : uri.Port;

        return uri.ToString();
    }

    public static async Task DeleteMusicAsync(this IObjectStorageOperation objectStorageService, VmMusic music)
    {
        if (music == null)
            throw new ArgumentNullException(nameof(music));
        if (string.IsNullOrEmpty(music.MusicUrl))
            throw new ArgumentException("property MusicUrl is empty or null", nameof(music.MusicUrl));


        await objectStorageService.DeleteAsync(music.MusicUrl);

        if (!string.IsNullOrEmpty(music.CoverUrl))
            await objectStorageService.DeleteAsync(music.CoverUrl);

        if (!string.IsNullOrEmpty(music.LyricUrl))
            await objectStorageService.DeleteAsync(music.LyricUrl);
    }

    public static string GetUpyunHost(this IConfiguration configuration)
    {
        var host = configuration["upyun:Host"];
        if (string.IsNullOrEmpty(host))
            throw new Exception("no upyun.Host node");
        return host;
    }


    public static ModelStateResult CheckModelState(this ModelStateDictionary modelState)
    {
        if (modelState.IsValid)
        {
            var messages = modelState
                .SelectMany(x => x.Value?.Errors ?? new ModelErrorCollection())
                .Select(x => x.ErrorMessage)
                .Where(x => !string.IsNullOrEmpty(x))
                .ToList();
            if (messages.Count == 0)
            {
                return new ModelStateResult(false, []);
            }

            return new ModelStateResult(true, messages);
        }

        return new ModelStateResult(false, []);
    }
}
loading