diff --git a/framework/NPin.Framework.Core/Extensions/HttpContextExtensions.cs b/framework/NPin.Framework.Core/Extensions/HttpContextExtensions.cs
index f0bca32..a94f352 100644
--- a/framework/NPin.Framework.Core/Extensions/HttpContextExtensions.cs
+++ b/framework/NPin.Framework.Core/Extensions/HttpContextExtensions.cs
@@ -1,5 +1,6 @@
-using System.Text;
-using System.Text.RegularExpressions;
+using System.Net;
+using System.Text;
+using System.Web;
using Microsoft.AspNetCore.Http;
namespace NPin.Framework.Core.Extensions;
@@ -7,93 +8,125 @@ namespace NPin.Framework.Core.Extensions;
public static class HttpContextExtensions
{
///
- /// 设置文件下载名称
- ///
- ///
- ///
- public static void FileInlineHandle(this HttpContext httpContext, string fileName)
- {
- string encodeFilename = System.Web.HttpUtility.UrlEncode(fileName, Encoding.GetEncoding("UTF-8"));
- httpContext.Response.Headers.Add("Content-Disposition", "inline;filename=" + encodeFilename);
+ /// 设置文件下载名称
+ ///
+ ///
+ ///
+ public static void FileInlineHandle(this HttpContext httpContext, string fileName)
+ {
+ string encodeFilename = HttpUtility.UrlEncode(fileName, Encoding.GetEncoding("UTF-8"));
+ httpContext.Response.Headers.Add("Content-Disposition", "inline;filename=" + encodeFilename);
+ }
- }
+ ///
+ /// 设置文件附件名称
+ ///
+ ///
+ ///
+ public static void FileAttachmentHandle(this HttpContext httpContext, string fileName)
+ {
+ string encodeFilename = HttpUtility.UrlEncode(fileName, Encoding.GetEncoding("UTF-8"));
+ httpContext.Response.Headers.Add("Content-Disposition", "attachment;filename=" + encodeFilename);
+ }
- ///
- /// 设置文件附件名称
- ///
- ///
- ///
- public static void FileAttachmentHandle(this HttpContext httpContext, string fileName)
+ ///
+ /// 获取语言种类
+ ///
+ ///
+ ///
+ public static string GetLanguage(this HttpContext httpContext)
+ {
+ string res = "zh-CN";
+ var str = httpContext.Request.Headers["Accept-Language"].FirstOrDefault();
+ if (str is not null)
{
- string encodeFilename = System.Web.HttpUtility.UrlEncode(fileName, Encoding.GetEncoding("UTF-8"));
- httpContext.Response.Headers.Add("Content-Disposition", "attachment;filename=" + encodeFilename);
-
+ res = str.Split(",")[0];
}
- ///
- /// 获取语言种类
- ///
- ///
- ///
- public static string GetLanguage(this HttpContext httpContext)
- {
- string res = "zh-CN";
- var str = httpContext.Request.Headers["Accept-Language"].FirstOrDefault();
- if (str is not null)
- {
- res = str.Split(",")[0];
- }
- return res;
+ return res;
+ }
- }
+ ///
+ /// 判断是否为异步请求
+ ///
+ ///
+ ///
+ public static bool IsAjaxRequest(this HttpRequest request)
+ {
+ string header = request.Headers["X-Requested-With"];
+ return "XMLHttpRequest".Equals(header);
+ }
+
+ ///
+ /// 获取客户端Ip
+ ///
+ ///
+ ///
+ public static string GetClientIp(this HttpContext? context)
+ {
+ if (context == null) return "";
- ///
- /// 判断是否为异步请求
- ///
- ///
- ///
- public static bool IsAjaxRequest(this HttpRequest request)
+ var result = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
+ if (string.IsNullOrEmpty(result))
{
- string header = request.Headers["X-Requested-With"];
- return "XMLHttpRequest".Equals(header);
+ result = context.Connection.RemoteIpAddress?.ToString();
}
- ///
- /// 获取客户端IP
- ///
- ///
- ///
- public static string GetClientIp(this HttpContext context)
- {
- if (context == null) return "";
- var result = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
- if (string.IsNullOrEmpty(result))
- {
- result = context.Connection.RemoteIpAddress?.ToString();
- }
- if (string.IsNullOrEmpty(result) || result.Contains("::1"))
- result = "127.0.0.1";
- result = result.Replace("::ffff:", "127.0.0.1");
+ // 解析 Ip String 到 Ipv4 或 MapToIPv4
+ // 若无法解析 IP String,强制转为本地 Ipv4
+ result = IPAddress.TryParse(result, out var ipAddr)
+ ? ipAddr.MapToIPv4().ToString()
+ : IPAddress.Loopback.ToString();
- //Ip规则效验
- var regResult = Regex.IsMatch(result, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
+ // // 本地回环 转换为 ipv4 127.0.0.1
+ // if (string.IsNullOrEmpty(result) || result.Contains("::1"))
+ // {
+ // result = "127.0.0.1";
+ // }
+ //
+ // result = result.Replace("::ffff:", "127.0.0.1");
+ //
+ // // Ip规则效验
+ // var regResult = Regex.IsMatch(result, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
+ //
+ // result = regResult ? result : "127.0.0.1";
+ return result;
+ }
- result = regResult ? result : "127.0.0.1";
- return result;
- }
+ ///
+ /// 获取客户端Ip
+ ///
+ ///
+ ///
+ public static IPAddress? GetClientIpAddress(this HttpContext? context)
+ {
+ if (context == null) return null;
- ///
- /// 获取浏览器标识
- ///
- ///
- ///
- public static string GetUserAgent(this HttpContext context)
+ var result = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
+ if (string.IsNullOrEmpty(result))
{
- return context.Request.Headers["User-Agent"];
+ result = context.Connection.RemoteIpAddress?.ToString();
}
- public static string[]? GetUserPermissions(this HttpContext context, string permissionsName)
- {
- return context.User.Claims.Where(x => x.Type == permissionsName).Select(x => x.Value).ToArray();
- }
+ // 解析 Ip String 到 IpAddress
+ // 若无法解析 IP String,强制转为本地 Ipv4
+ return IPAddress.TryParse(result, out var ipAddr)
+ ? ipAddr
+ : IPAddress.Loopback;
+ }
+
+ ///
+ /// 获取浏览器标识
+ ///
+ ///
+ ///
+ public static string GetUserAgent(this HttpContext context)
+ {
+ return context.Request.Headers["User-Agent"];
+ }
+
+ public static string[] GetUserPermissions(this HttpContext context, string permissionsName)
+ {
+ return context.User.Claims.Where(x => x.Type == permissionsName).Select(x => x.Value).ToArray();
+ }
}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain.Shared/Consts/TokenTypeConst.cs b/module/upms/NPin.Framework.Upms.Domain.Shared/Consts/TokenTypeConst.cs
new file mode 100644
index 0000000..26dcea3
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain.Shared/Consts/TokenTypeConst.cs
@@ -0,0 +1,16 @@
+namespace NPin.Framework.Upms.Domain.Shared.Consts;
+
+public class TokenTypeConst
+{
+ public const string Id = nameof(Id);
+ public const string Username = nameof(Username);
+ public const string TenantId = nameof(TenantId);
+ public const string OrgId = nameof(OrgId);
+ public const string Email = nameof(Email);
+ public const string PhoneNumber = nameof(PhoneNumber);
+ public const string Roles = nameof(Roles);
+ public const string Organizations = nameof(Organizations);
+ public const string Permission = nameof(Permission);
+ public const string RoleInfo = nameof(RoleInfo);
+ public const string Refresh = nameof(Refresh);
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain.Shared/Dtos/OrganizationDto.cs b/module/upms/NPin.Framework.Upms.Domain.Shared/Dtos/OrganizationDto.cs
new file mode 100644
index 0000000..3cdb227
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain.Shared/Dtos/OrganizationDto.cs
@@ -0,0 +1,33 @@
+namespace NPin.Framework.Upms.Domain.Shared.Dtos;
+
+public class OrganizationDto
+{
+ public Guid Id { get; set; }
+
+ public string Name { get; set; } = string.Empty;
+ public string Code { get; set; } = string.Empty;
+ public string? Remark { get; set; }
+
+ ///
+ /// 负责人ID
+ ///
+ public Guid LeaderId { get; set; }
+
+ ///
+ /// 负责人名称,仅用户展示,不存储
+ ///
+ public string Leader { get; set; }
+
+ ///
+ /// 父节点 ID
+ ///
+ public Guid ParentId { get; set; }
+
+ public bool IsDeleted { get; }
+ public DateTime CreationTime { get; } = DateTime.Now;
+ public Guid? CreatorId { get; }
+ public DateTime? LastModificationTime { get; }
+ public Guid? LastModifierId { get; }
+ public int OrderNum { get; set; }
+ public bool IsEnabled { get; set; }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain.Shared/Dtos/PostDto.cs b/module/upms/NPin.Framework.Upms.Domain.Shared/Dtos/PostDto.cs
new file mode 100644
index 0000000..d237836
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain.Shared/Dtos/PostDto.cs
@@ -0,0 +1,18 @@
+namespace NPin.Framework.Upms.Domain.Shared.Dtos;
+
+public class PostDto
+{
+ public Guid Id { get; set; }
+
+ public string Code { get; set; } = string.Empty;
+ public string Name { get; set; } = string.Empty;
+ public string? Remark { get; set; }
+
+ public bool IsDeleted { get; }
+ public DateTime CreationTime { get; } = DateTime.Now;
+ public Guid? CreatorId { get; }
+ public DateTime? LastModificationTime { get; }
+ public Guid? LastModifierId { get; }
+ public int OrderNum { get; set; }
+ public bool IsEnabled { get; set; }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain.Shared/Dtos/RoleDto.cs b/module/upms/NPin.Framework.Upms.Domain.Shared/Dtos/RoleDto.cs
new file mode 100644
index 0000000..4bdad92
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain.Shared/Dtos/RoleDto.cs
@@ -0,0 +1,29 @@
+using NPin.Framework.Upms.Domain.Shared.Enums;
+
+namespace NPin.Framework.Upms.Domain.Shared.Dtos;
+
+public class RoleFullDto
+{
+ public RoleDto Role { get; set; } = new();
+
+ // Relations
+ public HashSet OrganizationList { get; set; } = [];
+}
+
+public class RoleDto
+{
+ public Guid Id { get; set; }
+
+ public string Code { get; set; } = string.Empty;
+ public string Name { get; set; } = string.Empty;
+ public DataScopeEnum DataScope { get; set; } = DataScopeEnum.All;
+ public string? Remark { get; set; }
+
+ public bool IsDeleted { get; }
+ public DateTime CreationTime { get; } = DateTime.Now;
+ public Guid? CreatorId { get; }
+ public DateTime? LastModificationTime { get; }
+ public Guid? LastModifierId { get; }
+ public int OrderNum { get; set; }
+ public bool IsEnabled { get; set; }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain.Shared/Dtos/UserDto.cs b/module/upms/NPin.Framework.Upms.Domain.Shared/Dtos/UserDto.cs
new file mode 100644
index 0000000..275dc73
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain.Shared/Dtos/UserDto.cs
@@ -0,0 +1,51 @@
+using NPin.Framework.Upms.Domain.Shared.Enums;
+
+namespace NPin.Framework.Upms.Domain.Shared.Dtos;
+
+///
+/// 完整用户信息Dto
+/// 包括所有关联关系
+///
+public class UserFullDto
+{
+ public UserDto User { get; set; } = new();
+
+ // Relations
+ public HashSet Roles { get; set; } = [];
+ public HashSet Posts { get; set; } = [];
+ public HashSet Organizations { get; set; } = [];
+
+ public HashSet PostCodes { get; set; } = [];
+ public HashSet RoleCodes { get; set; } = [];
+ public HashSet PermissionCodes { get; set; } = [];
+}
+
+public class UserDto
+{
+ ///
+ /// 主键ID
+ ///
+ public Guid Id { get; set; }
+
+ public bool IsDeleted { get; }
+ public DateTime CreationTime { get; } = DateTime.Now;
+ public Guid? CreatorId { get; }
+ public DateTime? LastModificationTime { get; }
+ public Guid? LastModifierId { get; }
+ public bool IsEnabled { get; set; }
+ public int OrderNum { get; set; }
+
+ public string Username { get; set; } = string.Empty;
+ public string PhoneNumber { get; set; }
+ public string? Email { get; set; }
+ public string? Nickname { get; set; }
+ public string Password { get; set; } = string.Empty;
+ public string Salt { get; set; } = string.Empty;
+ public string? Introduction { get; set; }
+ public GenderEnum Gender { get; set; } = GenderEnum.Secrecy;
+ public string? IpAddr { get; set; }
+ public string? Avatar { get; set; }
+
+ // For user (metadata)
+ public Dictionary Metadata { get; set; }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain.Shared/Enums/DataScopeEnum.cs b/module/upms/NPin.Framework.Upms.Domain.Shared/Enums/DataScopeEnum.cs
index c8f2b4d..b9f4f99 100644
--- a/module/upms/NPin.Framework.Upms.Domain.Shared/Enums/DataScopeEnum.cs
+++ b/module/upms/NPin.Framework.Upms.Domain.Shared/Enums/DataScopeEnum.cs
@@ -18,12 +18,12 @@ public enum DataScopeEnum
///
/// 本部门
///
- Dept = 2,
+ Org = 2,
///
/// 部门以及子部门
///
- DeptFollow = 3,
+ OrgFollow = 3,
///
/// 只有自己
diff --git a/module/upms/NPin.Framework.Upms.Domain.Shared/Etos/LoginEventArgs.cs b/module/upms/NPin.Framework.Upms.Domain.Shared/Etos/LoginEventArgs.cs
new file mode 100644
index 0000000..3273c05
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain.Shared/Etos/LoginEventArgs.cs
@@ -0,0 +1,45 @@
+namespace NPin.Framework.Upms.Domain.Shared.Etos;
+
+///
+/// 用户登录事件参数
+///
+public class LoginEventArgs
+{
+ public Guid UserId { get; set; }
+
+ public string Username { get; set; }
+
+ public string Nickname { get; set; }
+
+ public DateTime CreationTime { get; set; }
+
+ ///
+ /// 登录地点
+ ///
+ public string? LoginLocation { get; set; }
+
+ ///
+ /// 登录Ipv4地址
+ ///
+ public string? LoginIPv4 { get; set; }
+
+ ///
+ /// 登录Ipv6地址,仅当支持Ipv6时有值
+ ///
+ public string? LoginIPv6 { get; set; }
+
+ ///
+ /// 登录浏览器
+ ///
+ public string? Browser { get; set; }
+
+ ///
+ /// 操作系统
+ ///
+ public string? Os { get; set; }
+
+ ///
+ /// 登录信息
+ ///
+ public string? LoginMsg { get; set; }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain.Shared/Etos/UserCreatedEventArgs.cs b/module/upms/NPin.Framework.Upms.Domain.Shared/Etos/UserCreatedEventArgs.cs
new file mode 100644
index 0000000..9a0b383
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain.Shared/Etos/UserCreatedEventArgs.cs
@@ -0,0 +1,9 @@
+namespace NPin.Framework.Upms.Domain.Shared.Etos;
+
+///
+/// 用户创建事件参数
+///
+public class UserCreatedEventArgs
+{
+ public Guid UserId { get; set; }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain.Shared/NPin.Framework.Upms.Domain.Shared.csproj b/module/upms/NPin.Framework.Upms.Domain.Shared/NPin.Framework.Upms.Domain.Shared.csproj
index b68603d..8fbf1da 100644
--- a/module/upms/NPin.Framework.Upms.Domain.Shared/NPin.Framework.Upms.Domain.Shared.csproj
+++ b/module/upms/NPin.Framework.Upms.Domain.Shared/NPin.Framework.Upms.Domain.Shared.csproj
@@ -8,8 +8,6 @@
-
-
diff --git a/module/upms/NPin.Framework.Upms.Domain/Authorization/DataPermissionExtensions.cs b/module/upms/NPin.Framework.Upms.Domain/Authorization/DataPermissionExtensions.cs
new file mode 100644
index 0000000..cfaa65e
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/Authorization/DataPermissionExtensions.cs
@@ -0,0 +1,16 @@
+using Volo.Abp.Data;
+
+namespace NPin.Framework.Upms.Domain.Authorization;
+
+public static class DataPermissionExtensions
+{
+ ///
+ /// 关闭数据权限
+ ///
+ ///
+ ///
+ public static IDisposable DisablePermissionHandler(this IDataFilter dataFilter)
+ {
+ return dataFilter.Disable();
+ }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Authorization/DefaultPermissionHandler.cs b/module/upms/NPin.Framework.Upms.Domain/Authorization/DefaultPermissionHandler.cs
new file mode 100644
index 0000000..91b71f0
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/Authorization/DefaultPermissionHandler.cs
@@ -0,0 +1,35 @@
+using Microsoft.AspNetCore.Http;
+using NPin.Framework.Core.Extensions;
+using NPin.Framework.Upms.Domain.Shared.Consts;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Users;
+
+namespace NPin.Framework.Upms.Domain.Authorization;
+
+///
+/// 默认权限处理器
+///
+public class DefaultPermissionHandler : IPermissionHandler, ITransientDependency
+{
+ private readonly ICurrentUser _currentUser;
+ private readonly IHttpContextAccessor _httpContextAccessor;
+
+ public DefaultPermissionHandler(ICurrentUser currentUser, IHttpContextAccessor httpContextAccessor)
+ {
+ _currentUser = currentUser;
+ _httpContextAccessor = httpContextAccessor;
+ }
+
+ public bool IsPass(string permission)
+ {
+ var permissions = _httpContextAccessor.HttpContext.GetUserPermissions(TokenTypeConst.Permission);
+
+ // 超级管理员
+ if (permissions.Contains("*:*:*"))
+ {
+ return true;
+ }
+
+ return permissions.Contains(permission);
+ }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Authorization/IPermissionHandler.cs b/module/upms/NPin.Framework.Upms.Domain/Authorization/IPermissionHandler.cs
new file mode 100644
index 0000000..a2c4808
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/Authorization/IPermissionHandler.cs
@@ -0,0 +1,6 @@
+namespace NPin.Framework.Upms.Domain.Authorization;
+
+public interface IPermissionHandler
+{
+ bool IsPass(string permission);
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Authorization/PermissionAttribute.cs b/module/upms/NPin.Framework.Upms.Domain/Authorization/PermissionAttribute.cs
new file mode 100644
index 0000000..de3e5c3
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/Authorization/PermissionAttribute.cs
@@ -0,0 +1,12 @@
+namespace NPin.Framework.Upms.Domain.Authorization;
+
+[AttributeUsage(AttributeTargets.Method)]
+public class PermissionAttribute: Attribute
+{
+ internal string Code { get; set; }
+
+ public PermissionAttribute(string code)
+ {
+ Code = code;
+ }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Authorization/PermissionGlobalAttribute.cs b/module/upms/NPin.Framework.Upms.Domain/Authorization/PermissionGlobalAttribute.cs
new file mode 100644
index 0000000..8aa862b
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/Authorization/PermissionGlobalAttribute.cs
@@ -0,0 +1,45 @@
+using System.Net;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Http;
+
+namespace NPin.Framework.Upms.Domain.Authorization;
+
+///
+/// 权限处理器
+///
+internal class PermissionGlobalAttribute : ActionFilterAttribute, ITransientDependency
+{
+ private readonly IPermissionHandler _permissionHandler;
+
+ public PermissionGlobalAttribute(IPermissionHandler permissionHandler)
+ {
+ _permissionHandler = permissionHandler;
+ }
+
+ public override void OnActionExecuting(ActionExecutingContext context)
+ {
+ if (context.ActionDescriptor is not ControllerActionDescriptor controllerActionDescriptor) return;
+ var perAttribute = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true)
+ .FirstOrDefault(a => a.GetType() == typeof(PermissionAttribute)) as PermissionAttribute;
+ // 无权限标识,通过
+ if (perAttribute is null) return;
+
+ var passed = _permissionHandler.IsPass(perAttribute.Code);
+ if (passed) return;
+
+ var model = new RemoteServiceErrorInfo
+ {
+ Code = "403",
+ Message = "您无权访问,请联系管理员",
+ Details = $"您无权访问该接口-{context.HttpContext.Request.Path.Value}"
+ };
+ var content = new ObjectResult(new { error = model })
+ {
+ StatusCode = (int)HttpStatusCode.Forbidden
+ };
+ context.Result = content;
+ }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Authorization/RefreshTokenMiddleware.cs b/module/upms/NPin.Framework.Upms.Domain/Authorization/RefreshTokenMiddleware.cs
new file mode 100644
index 0000000..38ec12a
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/Authorization/RefreshTokenMiddleware.cs
@@ -0,0 +1,49 @@
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using NPin.Framework.Upms.Domain.Shared.Consts;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Security.Claims;
+
+namespace NPin.Framework.Upms.Domain.Authorization;
+
+///
+/// RefreshToken 处理中间件
+///
+public class RefreshTokenMiddleware : IMiddleware, ITransientDependency
+{
+ public async Task InvokeAsync(HttpContext context, RequestDelegate next)
+ {
+ var refreshToken = context.Request.Headers["refresh_token"].ToString();
+ if (!refreshToken.IsNullOrEmpty())
+ {
+ var authResult = await context.AuthenticateAsync(TokenTypeConst.Refresh);
+ // Token刷新成功
+ if (authResult.Succeeded)
+ {
+ var userId = Guid.Parse(authResult.Principal.FindFirst(AbpClaimTypes.UserId).Value);
+ // TODO
+ // var accessToken =
+ // var refreshToken =
+ context.Response.Headers["access_token"] = "";
+ context.Response.Headers["refresh_token"] = "";
+
+ // 请求头替换
+ context.Request.Headers["Authorization"] = $"Bearer {""}";
+ }
+ }
+ await next(context);
+ }
+}
+
+///
+/// 扩展
+///
+public static class RefreshTokenExtensions
+{
+ public static IApplicationBuilder UseRefreshToken(this IApplicationBuilder builder)
+ {
+ builder.UseMiddleware();
+ return builder;
+ }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Authorization/SocialAggregateRoot.cs b/module/upms/NPin.Framework.Upms.Domain/Authorization/SocialAggregateRoot.cs
new file mode 100644
index 0000000..11e3d14
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/Authorization/SocialAggregateRoot.cs
@@ -0,0 +1,46 @@
+using SqlSugar;
+using Volo.Abp.Auditing;
+using Volo.Abp.Data;
+using Volo.Abp.Domain.Entities;
+
+namespace NPin.Framework.Upms.Domain.Authorization;
+
+[SugarTable("Social", "第三方授权表")]
+public class SocialAggregateRoot: AggregateRoot, ISoftDelete, IHasCreationTime
+{
+ [SugarColumn(IsPrimaryKey = true)]
+ public override Guid Id { get; protected set; }
+
+ public Guid UserId { get; set; }
+
+ public string OpenId { get; set; }
+
+ public string? UnionId { get; set; }
+
+ public string Name { get; set; }
+
+ public string Type { get; set; }
+
+ public bool IsDeleted { get; }
+ public DateTime CreationTime { get; }
+
+ [SugarColumn(IsIgnore = true)]
+ public override ExtraPropertyDictionary ExtraProperties { get; protected set; }
+
+ public SocialAggregateRoot()
+ {
+ }
+
+ public SocialAggregateRoot(string type, Guid userId, string openId, string? unionId)
+ {
+ UserId = userId;
+ OpenId = openId;
+ UnionId = unionId;
+ Type = type;
+ }
+
+ public SocialAggregateRoot(string type, Guid userId, string openId, string? unionId, string name): this(type, userId, openId, unionId)
+ {
+ Name = name;
+ }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Entities/LoginLogEntity.cs b/module/upms/NPin.Framework.Upms.Domain/Entities/LoginLogEntity.cs
new file mode 100644
index 0000000..da55bc8
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/Entities/LoginLogEntity.cs
@@ -0,0 +1,81 @@
+using System.Net;
+using System.Net.Sockets;
+using IPTools.Core;
+using Microsoft.AspNetCore.Http;
+using NPin.Framework.Core.Extensions;
+using SqlSugar;
+using UAParser;
+using Volo.Abp.Auditing;
+using Volo.Abp.Domain.Entities;
+
+namespace NPin.Framework.Upms.Domain.Entities;
+
+[SugarTable("LoginLog", "登录日志表")]
+public class LoginLogEntity : Entity, ICreationAuditedObject
+{
+ [SugarColumn(IsPrimaryKey = true)] public override Guid Id { get; protected set; }
+
+ public DateTime CreationTime { get; }
+ public Guid? CreatorId { get; }
+
+ [SugarColumn(ColumnDescription = "登录用户")]
+ public string? LoginUser { get; set; }
+
+ [SugarColumn(ColumnDescription = "登录用户ID")]
+ public Guid LoginUserId { get; set; }
+
+ [SugarColumn(ColumnDescription = "登录地点")]
+ public string? LoginLocation { get; set; }
+
+ [SugarColumn(ColumnDescription = "Ipv4")]
+ public string? LoginIPv4 { get; set; }
+
+ [SugarColumn(ColumnDescription = "Ipv6")]
+ public string? LoginIPv6 { get; set; }
+
+ [SugarColumn(ColumnDescription = "浏览器")]
+ public string? Browser { get; set; }
+
+ [SugarColumn(ColumnDescription = "操作系统")]
+ public string? Os { get; set; }
+
+ [SugarColumn(ColumnDescription = "登录信息")]
+ public string? LoginMsg { get; set; }
+
+ public static LoginLogEntity GetInfoByHttpContext(HttpContext httpContext)
+ {
+ // var ipInfo = httpContext.GetRemoteIpInfo();
+ string ipv4AddrStr = null;
+ string ipv6AddrStr = null;
+ var ipAddr = httpContext.GetClientIpAddress();
+ if (ipAddr != null)
+ {
+ switch (ipAddr.AddressFamily)
+ {
+ case AddressFamily.InterNetwork:
+ ipv4AddrStr = ipAddr.ToString();
+ break;
+ case AddressFamily.InterNetworkV6:
+ ipv6AddrStr = ipAddr.ToString();
+ break;
+ }
+ }
+
+ var location = IPAddress.IsLoopback(ipAddr)
+ ? new IpInfo { Province = "本地", City = "本机" }
+ : IpTool.Search(ipAddr.ToString());
+
+ var clientInfo = GetClientInfo(httpContext);
+
+ return new LoginLogEntity
+ {
+ Browser = clientInfo.Device.Family,
+ Os = clientInfo.OS.ToString(),
+ LoginIPv4 = ipv4AddrStr,
+ LoginIPv6 = ipv6AddrStr,
+ LoginLocation = $"{location.Country}-{location.Province}-{location.City}"
+ };
+
+ ClientInfo GetClientInfo(HttpContext ctx) => Parser.GetDefault().Parse(ctx.GetUserAgent());
+ }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Entities/RoleEntity.cs b/module/upms/NPin.Framework.Upms.Domain/Entities/RoleEntity.cs
index e52d8e6..c0bbc3f 100644
--- a/module/upms/NPin.Framework.Upms.Domain/Entities/RoleEntity.cs
+++ b/module/upms/NPin.Framework.Upms.Domain/Entities/RoleEntity.cs
@@ -20,7 +20,7 @@ public class RoleEntity : Entity, ISoftDelete, IAuditedObject, IOrderNum,
[SugarColumn(ColumnDescription = "角色数据权限范围")]
public DataScopeEnum DataScope { get; set; } = DataScopeEnum.All;
-
+
[SugarColumn(ColumnDescription = "描述")]
public string? Remark { get; set; }
@@ -31,4 +31,12 @@ public class RoleEntity : Entity, ISoftDelete, IAuditedObject, IOrderNum,
public Guid? LastModifierId { get; }
public int OrderNum { get; set; }
public bool IsEnabled { get; set; }
+
+ #region 导航
+
+ [Navigate(typeof(RoleOrganizationEntity), nameof(RoleOrganizationEntity.RoleId),
+ nameof(RoleOrganizationEntity.OrgId))]
+ public List OrganizationList { get; set; }
+
+ #endregion
}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Entities/RoleOrganizationEntity.cs b/module/upms/NPin.Framework.Upms.Domain/Entities/RoleOrganizationEntity.cs
new file mode 100644
index 0000000..8bcf629
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/Entities/RoleOrganizationEntity.cs
@@ -0,0 +1,16 @@
+using SqlSugar;
+using Volo.Abp.Domain.Entities;
+
+namespace NPin.Framework.Upms.Domain.Entities;
+
+[SugarTable("RelRoleOrganization", "角色-机构 关系表")]
+public class RoleOrganizationEntity : Entity
+{
+ [SugarColumn(IsPrimaryKey = true)] public override Guid Id { get; protected set; }
+
+ [SugarColumn(ColumnDescription = "角色ID")]
+ public Guid RoleId { get; set; }
+
+ [SugarColumn(ColumnDescription = "机构ID")]
+ public Guid OrgId { get; set; }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Entities/UserEntity.cs b/module/upms/NPin.Framework.Upms.Domain/Entities/UserEntity.cs
index b8858fc..c7ba9f9 100644
--- a/module/upms/NPin.Framework.Upms.Domain/Entities/UserEntity.cs
+++ b/module/upms/NPin.Framework.Upms.Domain/Entities/UserEntity.cs
@@ -88,6 +88,9 @@ public class UserEntity : Entity, ISoftDelete, IAuditedObject, IEnabled, I
[Navigate(typeof(UserPostEntity), nameof(UserPostEntity.UserId), nameof(UserPostEntity.PostId))]
public List Posts { get; set; }
+ ///
+ /// 所在的组织机构列表,多对多
+ ///
[Navigate(typeof(UserOrganizationEntity), nameof(UserOrganizationEntity.UserId),
nameof(UserOrganizationEntity.OrganizationId))]
public List Organizations { get; set; }
diff --git a/module/upms/NPin.Framework.Upms.Domain/EventHandlers/LoginEventHandler.cs b/module/upms/NPin.Framework.Upms.Domain/EventHandlers/LoginEventHandler.cs
new file mode 100644
index 0000000..b1ad395
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/EventHandlers/LoginEventHandler.cs
@@ -0,0 +1,32 @@
+using Mapster;
+using Microsoft.Extensions.Logging;
+using NPin.Framework.Upms.Domain.Entities;
+using NPin.Framework.Upms.Domain.Shared.Etos;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Domain.Repositories;
+using Volo.Abp.EventBus;
+
+namespace NPin.Framework.Upms.Domain.EventHandlers;
+
+public class LoginEventHandler : ILocalEventHandler, ITransientDependency
+{
+ private readonly ILogger _logger;
+ private readonly IRepository _repository;
+
+ public LoginEventHandler(ILogger logger, IRepository repository)
+ {
+ _logger = logger;
+ _repository = repository;
+ }
+
+ public async Task HandleEventAsync(LoginEventArgs eventData)
+ {
+ _logger.LogInformation($"用户[{eventData.UserId}:{eventData.Username}]登录");
+ var loginLogEntity = eventData.Adapt();
+ loginLogEntity.LoginMsg = $"{eventData.Username}登录系统";
+ loginLogEntity.LoginUser = eventData.Username;
+ loginLogEntity.LoginUserId = eventData.UserId;
+ // 插入
+ await _repository.InsertAsync(loginLogEntity);
+ }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Extensions/CurrentUserExtensions.cs b/module/upms/NPin.Framework.Upms.Domain/Extensions/CurrentUserExtensions.cs
new file mode 100644
index 0000000..9e5e1d2
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/Extensions/CurrentUserExtensions.cs
@@ -0,0 +1,42 @@
+using NPin.Framework.Upms.Domain.Shared.Consts;
+using Volo.Abp.Users;
+
+namespace NPin.Framework.Upms.Domain.Extensions;
+
+public static class CurrentUserExtensions
+{
+ ///
+ /// 获取用户权限代码列表
+ ///
+ ///
+ ///
+ public static List GetPermissions(this ICurrentUser currentUser)
+ {
+ return currentUser.FindClaims(TokenTypeConst.Permission)
+ .Select(x => x.Value)
+ .ToList();
+ }
+
+ ///
+ /// 获取用户组织机构ID列表
+ ///
+ ///
+ ///
+ public static List GetOrganizationIds(this ICurrentUser currentUser)
+ {
+ return currentUser.FindClaims(TokenTypeConst.Organizations)
+ .Select(x => Guid.Parse(x.Value))
+ .ToList();
+ }
+
+ ///
+ /// 用户是否是通过Refresh进来的
+ ///
+ ///
+ ///
+ public static bool IsRefreshToken(this ICurrentUser currentUser)
+ {
+ var valOrNull = currentUser.FindClaim(TokenTypeConst.Refresh)?.Value;
+ return valOrNull is not null && bool.Parse(valOrNull);
+ }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Managers/AccountManager.cs b/module/upms/NPin.Framework.Upms.Domain/Managers/AccountManager.cs
new file mode 100644
index 0000000..16f4c04
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/Managers/AccountManager.cs
@@ -0,0 +1,12 @@
+using Volo.Abp.Domain.Services;
+
+namespace NPin.Framework.Upms.Domain.Managers;
+
+public interface IAccountManager
+{
+}
+
+public class AccountManager : DomainService, IAccountManager
+{
+ // private readonly
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/NPinFrameworkUpmsDomainModule.cs b/module/upms/NPin.Framework.Upms.Domain/NPinFrameworkUpmsDomainModule.cs
index 9163450..4ab292e 100644
--- a/module/upms/NPin.Framework.Upms.Domain/NPinFrameworkUpmsDomainModule.cs
+++ b/module/upms/NPin.Framework.Upms.Domain/NPinFrameworkUpmsDomainModule.cs
@@ -1,6 +1,9 @@
using Microsoft.Extensions.DependencyInjection;
using NPin.Framework.Caching.FreeRedis;
+using NPin.Framework.Upms.Domain.Authorization;
+using NPin.Framework.Upms.Domain.OperLog;
using NPin.Framework.Upms.Domain.Shared;
+using NPin.Framework.Upms.Domain.Shared.Options;
using Volo.Abp.AspNetCore.SignalR;
using Volo.Abp.Caching;
using Volo.Abp.Domain;
@@ -23,10 +26,11 @@ public class NPinFrameworkUpmsDomainModule : AbpModule
var configuration = services.GetConfiguration();
services.AddControllers(opts =>
{
- // opts.Filters.Add()
+ opts.Filters.Add();
+ opts.Filters.Add();
});
-
+
// 配置短信
- // Configure();
+ Configure(configuration.GetSection(nameof(AliyunOptions)));
}
}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/OperLog/OperLogGlobalAttribute.cs b/module/upms/NPin.Framework.Upms.Domain/OperLog/OperLogGlobalAttribute.cs
new file mode 100644
index 0000000..eb60a52
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/OperLog/OperLogGlobalAttribute.cs
@@ -0,0 +1,79 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using NPin.Framework.Core.Extensions;
+using NPin.Framework.Upms.Domain.Shared.OperLog;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Domain.Repositories;
+using Volo.Abp.Users;
+
+namespace NPin.Framework.Upms.Domain.OperLog;
+
+public class OperLogGlobalAttribute : ActionFilterAttribute, ITransientDependency
+{
+ private readonly ILogger _logger;
+ private IRepository _repository;
+ private ICurrentUser _currentUser;
+
+ public OperLogGlobalAttribute(ILogger logger, IRepository repository,
+ ICurrentUser currentUser)
+ {
+ _logger = logger;
+ _repository = repository;
+ _currentUser = currentUser;
+ }
+
+ public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
+ {
+ // 获取执行结果
+ var resultContext = await next.Invoke();
+
+ // 判断是否在 控制器方法 上
+ if (resultContext.ActionDescriptor is not ControllerActionDescriptor contextActionDescriptor) return;
+
+ // 查找特性
+ var operLogAttribute = contextActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true)
+ .FirstOrDefault(a => a.GetType() == typeof(OperLogAttribute)) as OperLogAttribute;
+ // 无特性表达式 直接返回 不处理
+ if (operLogAttribute is null) return;
+
+ // 获取Ip
+ var logEntity = OperationLogEntity.GetInfoByHttpContext(resultContext.HttpContext);
+
+ logEntity.OperType = operLogAttribute.OperType;
+ logEntity.Title = operLogAttribute.Title;
+ logEntity.RequestMethod = resultContext.HttpContext.Request.Method;
+ logEntity.Method = resultContext.HttpContext.Request.Path.Value;
+ logEntity.OperUser = _currentUser.UserName;
+
+ // 请求结果保存
+ if (operLogAttribute.IsSaveResponseData)
+ {
+ if (resultContext.Result is ContentResult { ContentType: "application/json" } result)
+ {
+ logEntity.RequestResult = result.Content?.Replace("\r\n", "").Trim();
+ }
+
+ if (resultContext.Result is JsonResult result2)
+ {
+ logEntity.RequestResult = result2.Value?.ToString();
+ }
+
+ if (resultContext.Result is ObjectResult result3)
+ {
+ logEntity.RequestResult = JsonConvert.SerializeObject(result3);
+ }
+ }
+
+ // 请求参数保存
+ if (operLogAttribute.IsSaveRequestData)
+ {
+ // 不建议保存 比较吃性能
+ // logEntity.RequestParam = context.HttpContext.GetRequestValue();
+ }
+
+ await _repository.InsertAsync(logEntity);
+ }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/OperLog/OperationLogEntity.cs b/module/upms/NPin.Framework.Upms.Domain/OperLog/OperationLogEntity.cs
new file mode 100644
index 0000000..246adab
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/OperLog/OperationLogEntity.cs
@@ -0,0 +1,86 @@
+using System.Net;
+using System.Net.Sockets;
+using IPTools.Core;
+using Microsoft.AspNetCore.Http;
+using NPin.Framework.Core.Extensions;
+using NPin.Framework.Upms.Domain.Entities;
+using NPin.Framework.Upms.Domain.Shared.OperLog;
+using SqlSugar;
+using UAParser;
+using Volo.Abp.Auditing;
+using Volo.Abp.Domain.Entities;
+
+namespace NPin.Framework.Upms.Domain.OperLog;
+
+[SugarTable("OperationLog", "操作日志记录表")]
+public class OperationLogEntity: Entity, ICreationAuditedObject
+{
+ [SugarColumn(IsPrimaryKey = true)]
+ public override Guid Id { get; protected set; }
+
+ [SugarColumn(ColumnDescription = "日志标题")]
+ public string? Title { get; set; }
+
+ [SugarColumn(ColumnDescription = "操作类型")]
+ public OperTypeEnum OperType { get; set; }
+
+ [SugarColumn(ColumnDescription = "请求方式")]
+ public string? RequestMethod { get; set; }
+
+ [SugarColumn(ColumnDescription = "操作者")]
+ public string? OperUser { get; set; }
+
+ [SugarColumn(ColumnDescription = "操作者Ipv4")]
+ public string? OperIPv4 { get; set; }
+
+ [SugarColumn(ColumnDescription = "操作者Ipv6")]
+ public string? OperIPv6 { get; set; }
+
+ [SugarColumn(ColumnDescription = "操作地点")]
+ public string? OperLocation { get; set; }
+
+ [SugarColumn(ColumnDescription = "操作方法")]
+ public string? Method { get; set; }
+
+ [SugarColumn(ColumnDescription = "请求参数")]
+ public string? RequestParam { get; set; }
+
+ [SugarColumn(ColumnDescription = "请求结果", Length = 9999)]
+ public string? RequestResult { get; set; }
+
+ public DateTime CreationTime { get; }
+ public Guid? CreatorId { get; }
+
+ public static OperationLogEntity GetInfoByHttpContext(HttpContext httpContext)
+ {
+ // var ipInfo = httpContext.GetRemoteIpInfo();
+ string ipv4AddrStr = null;
+ string ipv6AddrStr = null;
+ IpInfo info = new IpInfo { Province = "本地", City = "本机" };
+
+ var ipAddr = httpContext.GetClientIpAddress();
+ if (ipAddr != null)
+ {
+ switch (ipAddr.AddressFamily)
+ {
+ case AddressFamily.InterNetwork:
+ ipv4AddrStr = ipAddr.ToString();
+ break;
+ case AddressFamily.InterNetworkV6:
+ ipv6AddrStr = ipAddr.ToString();
+ break;
+ }
+
+ if (!IPAddress.IsLoopback(ipAddr))
+ {
+ info = IpTool.Search(ipAddr.ToString());
+ }
+ }
+ return new OperationLogEntity
+ {
+ OperIPv4 = ipv4AddrStr,
+ OperIPv6 = ipv6AddrStr,
+ OperLocation = $"{info.Country}-{info.Province}-{info.City}"
+ };
+ }
+}
\ No newline at end of file
diff --git a/module/upms/NPin.Framework.Upms.Domain/Repositories/IUserRepository.cs b/module/upms/NPin.Framework.Upms.Domain/Repositories/IUserRepository.cs
new file mode 100644
index 0000000..5703863
--- /dev/null
+++ b/module/upms/NPin.Framework.Upms.Domain/Repositories/IUserRepository.cs
@@ -0,0 +1,9 @@
+using NPin.Framework.SqlSugarCore.Abstractions;
+using NPin.Framework.Upms.Domain.Entities;
+
+namespace NPin.Framework.Upms.Domain.Repositories;
+
+public interface IUserRepository: ISqlSugarRepository
+{
+ // Task<>
+}
\ No newline at end of file
diff --git a/src/NPin.Application.Contracts/NPin.Application.Contracts.csproj b/src/NPin.Application.Contracts/NPin.Application.Contracts.csproj
index 660a61e..9254605 100644
--- a/src/NPin.Application.Contracts/NPin.Application.Contracts.csproj
+++ b/src/NPin.Application.Contracts/NPin.Application.Contracts.csproj
@@ -9,6 +9,7 @@
+
diff --git a/src/NPin.Application.Contracts/NPinApplicationContractsModule.cs b/src/NPin.Application.Contracts/NPinApplicationContractsModule.cs
index ba75ed5..858d596 100644
--- a/src/NPin.Application.Contracts/NPinApplicationContractsModule.cs
+++ b/src/NPin.Application.Contracts/NPinApplicationContractsModule.cs
@@ -1,12 +1,14 @@
using NPin.Domain.Shared;
using NPin.Framework.Ddd.Application.Contracts;
using NPin.Framework.TenantManagement.Application.Contracts;
+using NPin.Framework.Upms.Application.Contracts;
namespace NPin.Application.Contracts;
[DependsOn(
typeof(NPinDomainSharedModule),
- // TODO RBAC
+ //
+ typeof(NPinFrameworkUpmsApplicationContractsModule),
// TODO Bbs
typeof(NPinFrameworkTenantManagementApplicationContractsModule),
typeof(NPinFrameworkDddApplicationContractsModule)
diff --git a/src/NPin.Application/NPin.Application.csproj b/src/NPin.Application/NPin.Application.csproj
index a20842a..f5d0cbe 100644
--- a/src/NPin.Application/NPin.Application.csproj
+++ b/src/NPin.Application/NPin.Application.csproj
@@ -3,6 +3,7 @@
+
diff --git a/src/NPin.Application/NPinApplicationModule.cs b/src/NPin.Application/NPinApplicationModule.cs
index 7b67707..868f71c 100644
--- a/src/NPin.Application/NPinApplicationModule.cs
+++ b/src/NPin.Application/NPinApplicationModule.cs
@@ -2,13 +2,16 @@
using NPin.Domain;
using NPin.Framework.Ddd.Application;
using NPin.Framework.TenantManagement.Application;
+using NPin.Framework.Upms.Application;
namespace NPin.Application;
[DependsOn(
typeof(NPinApplicationContractsModule),
typeof(NPinDomainModule),
- // TODO rbac bbs
+ //
+ typeof(NPinFrameworkUpmsApplicationModule),
+ // TODO bbs
typeof(NPinFrameworkTenantManagementApplicationModule),
// TODO code-gen
typeof(NPinFrameworkDddApplicationModule)
diff --git a/src/NPin.Domain.Shared/NPin.Domain.Shared.csproj b/src/NPin.Domain.Shared/NPin.Domain.Shared.csproj
index 2fc014b..1848662 100644
--- a/src/NPin.Domain.Shared/NPin.Domain.Shared.csproj
+++ b/src/NPin.Domain.Shared/NPin.Domain.Shared.csproj
@@ -14,5 +14,6 @@
+
diff --git a/src/NPin.Domain.Shared/NPinDomainSharedModule.cs b/src/NPin.Domain.Shared/NPinDomainSharedModule.cs
index 56ef87d..4e40d3b 100644
--- a/src/NPin.Domain.Shared/NPinDomainSharedModule.cs
+++ b/src/NPin.Domain.Shared/NPinDomainSharedModule.cs
@@ -1,10 +1,11 @@
using NPin.Framework.AuditLogging.Domain.Shared;
+using NPin.Framework.Upms.Domain.Shared;
using Volo.Abp.Domain;
namespace NPin.Domain.Shared;
[DependsOn(
- // TODO RBAC
+ typeof(NPinFrameworkUpmsDomainSharedModule),
// TODO BBS
typeof(NPinFrameworkAuditLoggingDomainSharedModule),
typeof(AbpDddDomainSharedModule)
diff --git a/src/NPin.Domain/NPin.Domain.csproj b/src/NPin.Domain/NPin.Domain.csproj
index 85839a9..65d25f5 100644
--- a/src/NPin.Domain/NPin.Domain.csproj
+++ b/src/NPin.Domain/NPin.Domain.csproj
@@ -13,6 +13,7 @@
+
diff --git a/src/NPin.Domain/NPinDomainModule.cs b/src/NPin.Domain/NPinDomainModule.cs
index 68f3ec9..3aaf49b 100644
--- a/src/NPin.Domain/NPinDomainModule.cs
+++ b/src/NPin.Domain/NPinDomainModule.cs
@@ -2,6 +2,7 @@
using NPin.Framework.AuditLogging.Domain;
using NPin.Framework.Mapster;
using NPin.Framework.TenantManagement.Domain;
+using NPin.Framework.Upms.Domain;
using Volo.Abp.Caching;
using Volo.Abp.Domain;
@@ -11,7 +12,7 @@ namespace NPin.Domain;
typeof(NPinDomainSharedModule),
//
typeof(NPinFrameworkTenantManagementDomainModule),
- // TODO Rbac
+ typeof(NPinFrameworkUpmsDomainModule),
// TODO Bbs
typeof(NPinFrameworkAuditLoggingDomainModule),
//
diff --git a/src/NPin.SqlSugarCore/NPin.SqlSugarCore.csproj b/src/NPin.SqlSugarCore/NPin.SqlSugarCore.csproj
index 52477d4..4abaa0a 100644
--- a/src/NPin.SqlSugarCore/NPin.SqlSugarCore.csproj
+++ b/src/NPin.SqlSugarCore/NPin.SqlSugarCore.csproj
@@ -11,6 +11,7 @@
+
diff --git a/src/NPin.SqlSugarCore/NPinDbContext.cs b/src/NPin.SqlSugarCore/NPinDbContext.cs
index 0ba18b9..bd91538 100644
--- a/src/NPin.SqlSugarCore/NPinDbContext.cs
+++ b/src/NPin.SqlSugarCore/NPinDbContext.cs
@@ -1,6 +1,11 @@
-namespace NPin.SqlSugarCore;
+using NPin.Framework.Upms.SqlSugarCore;
+using Volo.Abp.DependencyInjection;
-public class NPinDbContext
+namespace NPin.SqlSugarCore;
+
+public class NPinDbContext: NPinUpmsDbContext
{
-
+ public NPinDbContext(IAbpLazyServiceProvider lazyServiceProvider) : base(lazyServiceProvider)
+ {
+ }
}
\ No newline at end of file
diff --git a/src/NPin.SqlSugarCore/NPinSqlSugarCoreModule.cs b/src/NPin.SqlSugarCore/NPinSqlSugarCoreModule.cs
index bf90ce1..3af713a 100644
--- a/src/NPin.SqlSugarCore/NPinSqlSugarCoreModule.cs
+++ b/src/NPin.SqlSugarCore/NPinSqlSugarCoreModule.cs
@@ -3,12 +3,15 @@ using NPin.Framework.AuditLogging.SqlSugarCore;
using NPin.Framework.Mapster;
using NPin.Framework.SqlSugarCore;
using NPin.Framework.TenantManagement.SqlSugarCore;
+using NPin.Framework.Upms.SqlSugarCore;
namespace NPin.SqlSugarCore;
[DependsOn(
typeof(NPinDomainModule),
- // TODO rbac bbs codegen
+ typeof(NPinFrameworkUpmsSqlSugarCoreModule),
+ // TODO bbs
+ // TODO codegen
typeof(NPinFrameworkAuditLoggingSqlSugarCoreModule),
typeof(NPinFrameworkTenantManagementSqlSugarCoreModule),
//
@@ -19,7 +22,7 @@ public class NPinSqlSugarCoreModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
- // context.Services.AddNPinDbContext();
+ context.Services.AddNPinDbContext();
// 默认不开放,可根据项目需要是否直接对外开放db
// context.Services.AddTransient(x => x.GetRequiredService().SqlSugarClient);
}
diff --git a/src/NPin.Web/GeoLite2-City.mmdb b/src/NPin.Web/GeoLite2-City.mmdb
new file mode 100644
index 0000000..f5e23dc
Binary files /dev/null and b/src/NPin.Web/GeoLite2-City.mmdb differ