using Admin.NET.Core;
using Admin.NET.Core.Options;
using Furion;
using Furion.DatabaseAccessor;
using Furion.DataEncryption;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.EventBus;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using UAParser;
using Admin.NET.Core.Entity.WmsBase;
namespace Admin.NET.Application
{
///
/// 登录授权相关服务
///
[ApiDescriptionSettings(Name = "Auth", Order = 160)]
[Route("api")]
public class AuthService : IAuthService, IDynamicApiController, ITransient
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IRepository _sysUserRep; // 用户表仓储
private readonly IRepository _wmsPdaPower;
private readonly IRepository _wmsRolePdaMenu;
private readonly IRepository _sysDictData;
private readonly ISysUserService _sysUserService; // 系统用户服务
private readonly ISysEmpService _sysEmpService; // 系统员工服务
private readonly ISysRoleService _sysRoleService; // 系统角色服务
private readonly ISysMenuService _sysMenuService; // 系统菜单服务
private readonly ISysAppService _sysAppService; // 系统应用服务
private readonly IClickWordCaptcha _captchaHandle; // 验证码服务
private readonly ISysConfigService _sysConfigService; // 验证码服务
private readonly IEventPublisher _eventPublisher;
private readonly ISysCacheService _cache;
///
/// 构造函数
///
public AuthService(IRepository sysUserRep, IRepository wmsPdaPower, IRepository wmsRolePdaMenu,
IRepository sysDictData, IHttpContextAccessor httpContextAccessor,
ISysUserService sysUserService, ISysEmpService sysEmpService, ISysRoleService sysRoleService,
ISysMenuService sysMenuService, ISysAppService sysAppService, IClickWordCaptcha captchaHandle,
ISysConfigService sysConfigService, IEventPublisher eventPublisher, ISysCacheService cache)
{
_sysUserRep = sysUserRep;
_wmsPdaPower = wmsPdaPower;
_wmsRolePdaMenu = wmsRolePdaMenu;
_sysDictData = sysDictData;
_httpContextAccessor = httpContextAccessor;
_sysUserService = sysUserService;
_sysEmpService = sysEmpService;
_sysRoleService = sysRoleService;
_sysMenuService = sysMenuService;
_sysAppService = sysAppService;
_captchaHandle = captchaHandle;
_sysConfigService = sysConfigService;
_eventPublisher = eventPublisher;
_cache = cache;
}
///
/// 用户登录
///
///
/// 默认用户名/密码:admin/admin
///
[HttpPost("login")]
[AllowAnonymous]
public string LoginAsync([Required] LoginInput input)
{
// 获取加密后的密码
var encryptPasswod = MD5Encryption.Encrypt(input.Password);
// 判断用户名和密码是否正确 忽略全局过滤器
var user = _sysUserRep
.Where(u => u.Account.Equals(input.Account) && u.Password.Equals(encryptPasswod) && u.IsDeleted == false, false, true)
.FirstOrDefault();
_ = user ?? throw Oops.Oh(ErrorCode.D1000);
// 验证账号是否被冻结
if (user.Status == CommonStatus.DISABLE)
throw Oops.Oh(ErrorCode.D1017);
//验证是否单用户登录,如果是剔除已经登录的用户
if (_sysConfigService.GetEnableSingleLoginFlag().Result)
{
var onlineUsers = _cache.GetAsync>(CommonConst.CACHE_KEY_ONLINE_USER).Result;
if (onlineUsers != null)
{
var loginuser = onlineUsers.FirstOrDefault(u => u.UserId == user.Id);
if (loginuser != null)
{
App.GetService().SingleLoginForceExist(loginuser);
}
}
}
// 员工信息
var empInfo = _sysEmpService.GetEmpInfo(user.Id).Result;
// 获取数据权限
var dataScopes = JsonUtil.ToJson(_sysUserService.GetUserDataScopeIdList(user.Id).Result);
// 生成Token令牌
//var accessToken = await _jwtBearerManager.CreateTokenAdmin(user);
var accessToken = JWTEncryption.Encrypt(new Dictionary
{
{ClaimConst.CLAINM_USERID, user.Id},
//{ClaimConst.TENANT_ID, user.TenantId},
{ClaimConst.CLAINM_ACCOUNT, user.Account},
{ClaimConst.CLAINM_NAME, user.Name},
{ClaimConst.CLAINM_SUPERADMIN, user.AdminType},
{ClaimConst.CLAINM_ORGID, empInfo.OrgId},
{ClaimConst.CLAINM_ORGNAME, empInfo.OrgName},
{ClaimConst.DATA_SCOPES, dataScopes}
});
// 设置Swagger自动登录
_httpContextAccessor.HttpContext.SigninToSwagger(accessToken);
var tokenData = JWTEncryption.ReadJwtToken(accessToken); // 解密
//var (isValid, tokenData, validationResult) = JWTEncryption.Validate(accessToken); // 验证token有效期
// 生成刷新Token令牌
var refreshToken =
JWTEncryption.GenerateRefreshToken(accessToken, App.GetOptions().ExpiredTime);
// 设置刷新Token令牌
_httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;
return accessToken;
}
///
/// 获取当前PC登录用户信息
///
///
[HttpGet("getLoginUser")]
public async Task GetLoginUserAsync()
{
var user = _sysUserRep.FirstOrDefault(u => u.Id == CurrentUserInfo.UserId, false);
if (user == null)
throw Oops.Oh(ErrorCode.D1011);
var userId = user.Id;
var httpContext = _httpContextAccessor.HttpContext;
var loginOutput = user.Adapt();
loginOutput.LastLoginTime = user.LastLoginTime = DateTimeOffset.Now;
loginOutput.LastLoginIp = user.LastLoginIp = httpContext.GetRequestIPv4();
//var ipInfo = IpTool.Search(loginOutput.LastLoginIp);
//loginOutput.LastLoginAddress = ipInfo.Country + ipInfo.Province + ipInfo.City + "[" + ipInfo.NetworkOperator + "][" + ipInfo.Latitude + ipInfo.Longitude + "]";
var client = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]);
loginOutput.LastLoginBrowser = client.UA.Family + client.UA.Major;
loginOutput.LastLoginOs = client.OS.Family + client.OS.Major;
// 员工信息
loginOutput.LoginEmpInfo = await _sysEmpService.GetEmpInfo(userId);
// 角色信息
loginOutput.Roles = await _sysRoleService.GetUserRoleList(userId);
// 权限信息
loginOutput.Permissions = await _sysMenuService.GetLoginPermissionList(userId);
// 系统所有权限信息
loginOutput.AllPermissions = await _sysMenuService.GetAllPermissionList();
// 数据范围信息(机构Id集合)
loginOutput.DataScopes = await _sysUserService.GetUserDataScopeIdList(userId);
// 具备应用信息(多系统,默认激活一个,可根据系统切换菜单),返回的结果中第一个为激活的系统
loginOutput.Apps = await _sysAppService.GetLoginApps(userId);
// 菜单信息
if (loginOutput.Apps.Count > 0)
{
var activeApp = loginOutput.Apps.FirstOrDefault(u => u.Active == YesOrNot.Y.ToString());
var defaultActiveAppCode = activeApp != null ? activeApp.Code : loginOutput.Apps.FirstOrDefault().Code;
loginOutput.Menus = await _sysMenuService.GetLoginMenusAntDesign(userId, defaultActiveAppCode);
}
// 更新用户最后登录Ip和时间
await _sysUserRep.UpdateIncludeAsync(user, new[] { nameof(SysUser.LastLoginIp), nameof(SysUser.LastLoginTime) });
// 增加登录日志
await _eventPublisher.PublishAsync(new ChannelEventSource("Create:VisLog",
new SysLogVis
{
Name = loginOutput.Name,
Success = YesOrNot.Y,
Message = "登录成功",
Ip = loginOutput.LastLoginIp,
Browser = loginOutput.LastLoginBrowser,
Os = loginOutput.LastLoginOs,
VisType = LoginType.LOGIN,
VisTime = loginOutput.LastLoginTime,
Account = loginOutput.Account
}));
return loginOutput;
}
///
/// 获取当前PDA登录用户信息
///
///
[HttpGet("getPdaLoginUser")]
public async Task GetPdaLoginUserAsync()
{
var user = _sysUserRep.FirstOrDefault(u => u.Id == CurrentUserInfo.UserId, false);
if (user == null)
throw Oops.Oh(ErrorCode.D1011);
var userId = user.Id;
var httpContext = _httpContextAccessor.HttpContext;
var loginOutput = user.Adapt();
loginOutput.LastLoginTime = user.LastLoginTime = DateTimeOffset.Now;
loginOutput.LastLoginIp = user.LastLoginIp = httpContext.GetRequestIPv4();
//var ipInfo = IpTool.Search(loginOutput.LastLoginIp);
//loginOutput.LastLoginAddress = ipInfo.Country + ipInfo.Province + ipInfo.City + "[" + ipInfo.NetworkOperator + "][" + ipInfo.Latitude + ipInfo.Longitude + "]";
var client = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]);
loginOutput.LastLoginBrowser = client.UA.Family + client.UA.Major;
loginOutput.LastLoginOs = client.OS.Family + client.OS.Major;
// 角色信息
var roleList = await _sysRoleService.GetUserRoleList(userId);
var meunIdList = _wmsRolePdaMenu.Where(n => roleList.Select(u => u.Id).Contains(n.SysRoleId)).Select(n => n.PdaMenuId).ToList();
var wmspdaPowerList = _wmsPdaPower.Where(n => meunIdList.Contains(n.Id)).Adapt>();
var dicDataList = _sysDictData.Where(p => p.TypeId == 383290718294085).ToList();
var listData = new List();
foreach (var item in dicDataList)
{
var enumValue = LesWorkShopType.FAPAOCHEJIAN;
if (item.Code == "1") enumValue = LesWorkShopType.FAPAOCHEJIAN;
else if (item.Code == "2") enumValue = LesWorkShopType.JIAOHEBANCHEJIAN;
else if (item.Code == "3") enumValue = LesWorkShopType.JHBCJ;
else if (item.Code == "4") enumValue = LesWorkShopType.RSBCJ;
else if (item.Code == "5") enumValue = LesWorkShopType.YLKCJ;
else enumValue = LesWorkShopType.TY;
if (wmspdaPowerList.Where(n => n.WorkShopType == enumValue).ToList().Count() != 0)
{
listData.Add(new wmsPdaPowerMenuOutput()
{
WorkShopName = item.Value,
WmsPdaPowerOutput = wmspdaPowerList.Where(n => n.WorkShopType == enumValue).ToList()
});
}
}
loginOutput.WmsPdaPowerOutputs = listData;
// 更新用户最后登录Ip和时间
await _sysUserRep.UpdateIncludeAsync(user, new[] { nameof(SysUser.LastLoginIp), nameof(SysUser.LastLoginTime) });
// 增加登录日志
await _eventPublisher.PublishAsync(new ChannelEventSource("Create:VisLog",
new SysLogVis
{
Name = loginOutput.Name,
Success = YesOrNot.Y,
Message = "登录成功",
Ip = loginOutput.LastLoginIp,
Browser = loginOutput.LastLoginBrowser,
Os = loginOutput.LastLoginOs,
VisType = LoginType.LOGIN,
VisTime = loginOutput.LastLoginTime,
Account = loginOutput.Account
}));
return loginOutput;
}
///
/// 退出
///
///
[HttpGet("logout")]
[AllowAnonymous]
public async Task LogoutAsync()
{
var ip = _httpContextAccessor.HttpContext.GetRequestIPv4();
_httpContextAccessor.HttpContext.SignoutToSwagger();
//_httpContextAccessor.HttpContext.Response.Headers["access-token"] = "invalid token";
// 增加退出日志
await _eventPublisher.PublishAsync(new ChannelEventSource("Create:VisLog",
new SysLogVis
{
Name = CurrentUserInfo.Name,
Success = YesOrNot.Y,
Message = "退出成功",
VisType = LoginType.LOGOUT,
VisTime = DateTimeOffset.Now,
Account = CurrentUserInfo.Account,
Ip = ip
}));
}
///
/// 获取验证码开关
///
///
[HttpGet("getCaptchaOpen")]
[AllowAnonymous]
public async Task GetCaptchaOpen()
{
return await _sysConfigService.GetCaptchaOpenFlag();
}
///
/// 获取验证码(默认点选模式)
///
///
[HttpPost("captcha/get")]
[AllowAnonymous]
[NonUnify]
public async Task GetCaptcha()
{
// 图片大小要与前端保持一致(坐标范围)
return await _captchaHandle.CreateCaptchaImage(_captchaHandle.RandomCode(4), 310, 155);
}
///
/// 校验验证码
///
///
///
[HttpPost("captcha/check")]
[AllowAnonymous]
[NonUnify]
public async Task VerificationCode(ClickWordCaptchaInput input)
{
return await _captchaHandle.CheckCode(input);
}
}
}