升级组件:Longbow.Web升级到2.2.9
#Comment OnlineUser功能整合到Longbow.Web组件中
This commit is contained in:
parent
32894af881
commit
53900a563a
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
|
|
|
@ -41,13 +41,14 @@ namespace Bootstrap.Admin.Controllers
|
|||
/// </summary>
|
||||
/// <returns>The login.</returns>
|
||||
/// <param name="onlineUserSvr"></param>
|
||||
/// <param name="ipLocator"></param>
|
||||
/// <param name="userName">User name.</param>
|
||||
/// <param name="password">Password.</param>
|
||||
/// <param name="remember">Remember.</param>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Login([FromServices]IOnlineUsers onlineUserSvr, string userName, string password, string remember)
|
||||
public async Task<IActionResult> Login([FromServices]IOnlineUsers onlineUserSvr, [FromServices]IIPLocatorProvider ipLocator, string userName, string password, string remember)
|
||||
{
|
||||
if (UserHelper.Authenticate(userName, password, loginUser => CreateLoginUser(onlineUserSvr, HttpContext, loginUser)))
|
||||
if (UserHelper.Authenticate(userName, password, loginUser => CreateLoginUser(onlineUserSvr, ipLocator, HttpContext, loginUser)))
|
||||
{
|
||||
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
identity.AddClaim(new Claim(ClaimTypes.Name, userName));
|
||||
|
@ -63,13 +64,14 @@ namespace Bootstrap.Admin.Controllers
|
|||
///
|
||||
/// </summary>
|
||||
/// <param name="onlineUserSvr"></param>
|
||||
/// <param name="ipLocator"></param>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="loginUser"></param>
|
||||
internal static void CreateLoginUser(IOnlineUsers onlineUserSvr, HttpContext context, LoginUser loginUser)
|
||||
internal static void CreateLoginUser(IOnlineUsers onlineUserSvr, IIPLocatorProvider ipLocator, HttpContext context, LoginUser loginUser)
|
||||
{
|
||||
var agent = new UserAgent(context.Request.Headers["User-Agent"]);
|
||||
loginUser.Ip = (context.Connection.RemoteIpAddress ?? IPAddress.IPv6Loopback).ToString();
|
||||
loginUser.City = onlineUserSvr.RetrieveLocaleByIp(loginUser.Ip);
|
||||
loginUser.City = ipLocator.Locate(loginUser.Ip);
|
||||
loginUser.Browser = $"{agent.Browser.Name} {agent.Browser.Version}";
|
||||
loginUser.OS = $"{agent.OS.Name} {agent.OS.Version}";
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Bootstrap.DataAccess;
|
||||
using Bootstrap.Security;
|
||||
using Longbow.Web;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
@ -28,17 +29,18 @@ namespace Bootstrap.Admin.Controllers.Api
|
|||
///
|
||||
/// </summary>
|
||||
/// <param name="onlineUserSvr"></param>
|
||||
/// <param name="ipLocator"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[HttpPost]
|
||||
public string Post([FromServices]IOnlineUsers onlineUserSvr, [FromBody]JObject value)
|
||||
public string Post([FromServices]IOnlineUsers onlineUserSvr, [FromServices]IIPLocatorProvider ipLocator, [FromBody]JObject value)
|
||||
{
|
||||
string token = null;
|
||||
dynamic user = value;
|
||||
string userName = user.userName;
|
||||
string password = user.password;
|
||||
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password) && UserHelper.Authenticate(userName, password, loginUser => AccountController.CreateLoginUser(onlineUserSvr, HttpContext, loginUser)))
|
||||
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password) && UserHelper.Authenticate(userName, password, loginUser => AccountController.CreateLoginUser(onlineUserSvr, ipLocator, HttpContext, loginUser)))
|
||||
{
|
||||
token = BootstrapAdminJwtTokenHandler.CreateToken(userName);
|
||||
}
|
||||
|
|
|
@ -29,16 +29,17 @@ namespace Bootstrap.Admin.Controllers.Api
|
|||
///
|
||||
/// </summary>
|
||||
/// <param name="onlineUserSvr"></param>
|
||||
/// <param name="ipLocator"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public bool Post([FromServices]IOnlineUsers onlineUserSvr, [FromBody]Log value)
|
||||
public bool Post([FromServices]IOnlineUsers onlineUserSvr, [FromServices]IIPLocatorProvider ipLocator, [FromBody]Log value)
|
||||
{
|
||||
var agent = new UserAgent(Request.Headers["User-Agent"]);
|
||||
value.Ip = (HttpContext.Connection.RemoteIpAddress ?? IPAddress.IPv6Loopback).ToString();
|
||||
value.Browser = $"{agent.Browser.Name} {agent.Browser.Version}";
|
||||
value.OS = $"{agent.OS.Name} {agent.OS.Version}";
|
||||
value.City = onlineUserSvr.RetrieveLocaleByIp(value.Ip);
|
||||
value.City = ipLocator.Locate(value.Ip);
|
||||
value.UserName = User.Identity.Name;
|
||||
return LogHelper.Save(value);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using Longbow.Web;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
|
|
|
@ -1,187 +0,0 @@
|
|||
using Bootstrap.DataAccess;
|
||||
using Longbow.Cache;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bootstrap.Admin
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
internal class DefaultOnlineUsers : IOnlineUsers
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, AutoExpireCacheEntry<OnlineUser>> _onlineUsers = new ConcurrentDictionary<string, AutoExpireCacheEntry<OnlineUser>>();
|
||||
private readonly ConcurrentDictionary<string, AutoExpireCacheEntry<string>> _ipLocator = new ConcurrentDictionary<string, AutoExpireCacheEntry<string>>();
|
||||
private readonly HttpClient _client;
|
||||
private readonly IEnumerable<string> _local = new string[] { "::1", "127.0.0.1" };
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
public DefaultOnlineUsers(IHttpClientFactory factory)
|
||||
{
|
||||
_client = factory.CreateClient(OnlineUsersServicesCollectionExtensions.IPSvrHttpClientName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<OnlineUser> OnlineUsers
|
||||
{
|
||||
get { return _onlineUsers.Values.Select(v => v.Value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="addValueFactory"></param>
|
||||
/// <param name="updateValueFactory"></param>
|
||||
/// <returns></returns>
|
||||
public AutoExpireCacheEntry<OnlineUser> AddOrUpdate(string key, Func<string, AutoExpireCacheEntry<OnlineUser>> addValueFactory, Func<string, AutoExpireCacheEntry<OnlineUser>, AutoExpireCacheEntry<OnlineUser>> updateValueFactory) => _onlineUsers.AddOrUpdate(key, addValueFactory, updateValueFactory);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="onlineUserCache"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryRemove(string key, out AutoExpireCacheEntry<OnlineUser> onlineUserCache) => _onlineUsers.TryRemove(key, out onlineUserCache);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
public string RetrieveLocaleByIp(string ip = null) => _ipLocator.GetOrAdd(ip, key => new AutoExpireCacheEntry<string>(IPProxy(key), 1000 * 60, __ => _ipLocator.TryRemove(key, out _))).Value;
|
||||
|
||||
private string IPProxy(string ip)
|
||||
{
|
||||
var ipSvr = DictHelper.RetrieveLocaleIPSvr();
|
||||
if (ipSvr.IsNullOrEmpty() || ipSvr.Equals("None", StringComparison.OrdinalIgnoreCase) || ip.IsNullOrEmpty() || _local.Any(p => p == ip)) return "本地连接";
|
||||
|
||||
var ipSvrUrl = DictHelper.RetrieveLocaleIPSvrUrl(ipSvr);
|
||||
if (ipSvrUrl.IsNullOrEmpty()) return "本地连接";
|
||||
|
||||
var url = $"{ipSvrUrl}{ip}";
|
||||
var task = ipSvr == "BaiDuIPSvr" ? RetrieveLocator<BaiDuIPLocator>(url) : RetrieveLocator<JuheIPLocator>(url);
|
||||
task.Wait();
|
||||
return task.Result;
|
||||
}
|
||||
|
||||
private async Task<string> RetrieveLocator<T>(string url)
|
||||
{
|
||||
var ret = default(T);
|
||||
try
|
||||
{
|
||||
ret = await _client.GetAsJsonAsync<T>(url);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.Log(new NameValueCollection()
|
||||
{
|
||||
["Url"] = url
|
||||
});
|
||||
}
|
||||
return ret?.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private class BaiDuIPLocator
|
||||
{
|
||||
/// <summary>
|
||||
/// 详细地址信息
|
||||
/// </summary>
|
||||
public string Address { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结果状态返回码
|
||||
/// </summary>
|
||||
public string Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Status == "0" ? string.Join(" ", Address.SpanSplit("|").Skip(1).Take(2)) : "XX XX";
|
||||
}
|
||||
}
|
||||
|
||||
private class JuheIPLocator
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string ResultCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Reason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public JuheIPLocatorResult Result { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public int Error_Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Error_Code != 0 ? "XX XX" : Result.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private class JuheIPLocatorResult
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Country { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Province { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string City { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Isp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Country != "中国" ? $"{Country} {Province} {Isp}" : $"{Province} {City} {Isp}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
using Longbow.Cache;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bootstrap.Admin
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface IOnlineUsers
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
IEnumerable<OnlineUser> OnlineUsers { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="addValueFactory"></param>
|
||||
/// <param name="updateValueFactory"></param>
|
||||
/// <returns></returns>
|
||||
AutoExpireCacheEntry<OnlineUser> AddOrUpdate(string key, Func<string, AutoExpireCacheEntry<OnlineUser>> addValueFactory, Func<string, AutoExpireCacheEntry<OnlineUser>, AutoExpireCacheEntry<OnlineUser>> updateValueFactory);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="onlineUserCache"></param>
|
||||
/// <returns></returns>
|
||||
bool TryRemove(string key, out AutoExpireCacheEntry<OnlineUser> onlineUserCache);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
string RetrieveLocaleByIp(string ip = null);
|
||||
}
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bootstrap.Admin
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class OnlineUser
|
||||
{
|
||||
private ConcurrentQueue<KeyValuePair<DateTime, string>> _requestUrls = new ConcurrentQueue<KeyValuePair<DateTime, string>>();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string ConnectionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public DateTime FirstAccessTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public DateTime LastAccessTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Method { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Ip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Browser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string OS { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string RequestUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IEnumerable<KeyValuePair<DateTime, string>> RequestUrls
|
||||
{
|
||||
get
|
||||
{
|
||||
return _requestUrls.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
public void AddRequestUrl(string url)
|
||||
{
|
||||
_requestUrls.Enqueue(new KeyValuePair<DateTime, string>(DateTime.Now, url));
|
||||
if (_requestUrls.Count > 5)
|
||||
{
|
||||
_requestUrls.TryDequeue(out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
using Bootstrap.Admin;
|
||||
using Bootstrap.DataAccess;
|
||||
using Longbow.Cache;
|
||||
using Longbow.Web;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class OnlineUsersMiddlewareExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="builder"></param>
|
||||
/// <returns></returns>
|
||||
public static IApplicationBuilder UseOnlineUsers(this IApplicationBuilder builder) => builder.UseWhen(context => context.Filter(), app => app.Use(async (context, next) =>
|
||||
{
|
||||
await System.Threading.Tasks.Task.Run(() =>
|
||||
{
|
||||
var user = UserHelper.RetrieveUserByUserName(context.User.Identity.Name);
|
||||
if (user == null) return;
|
||||
|
||||
var onlineUserSvr = context.RequestServices.GetRequiredService<IOnlineUsers>();
|
||||
var proxy = new Func<AutoExpireCacheEntry<OnlineUser>, Action, AutoExpireCacheEntry<OnlineUser>>((c, action) =>
|
||||
{
|
||||
var v = c.Value;
|
||||
v.UserName = user.UserName;
|
||||
v.DisplayName = user.DisplayName;
|
||||
v.LastAccessTime = DateTime.Now;
|
||||
v.Method = context.Request.Method;
|
||||
v.RequestUrl = context.Request.Path;
|
||||
v.AddRequestUrl(context.Request.Path);
|
||||
action?.Invoke();
|
||||
TraceHelper.Save(new Trace { Ip = v.Ip, RequestUrl = v.RequestUrl, LogTime = v.LastAccessTime, City = v.Location, Browser = v.Browser, OS = v.OS, UserName = v.UserName });
|
||||
return c;
|
||||
});
|
||||
onlineUserSvr.AddOrUpdate(context.Connection.Id ?? "", key =>
|
||||
{
|
||||
var agent = new UserAgent(context.Request.Headers["User-Agent"]);
|
||||
var v = new OnlineUser();
|
||||
v.ConnectionId = key;
|
||||
v.Ip = (context.Connection.RemoteIpAddress ?? IPAddress.IPv6Loopback).ToString();
|
||||
v.Location = onlineUserSvr.RetrieveLocaleByIp(v.Ip);
|
||||
v.Browser = $"{agent.Browser.Name} {agent.Browser.Version}";
|
||||
v.OS = $"{agent.OS.Name} {agent.OS.Version}";
|
||||
v.FirstAccessTime = DateTime.Now;
|
||||
return proxy(new AutoExpireCacheEntry<OnlineUser>(v, 1000 * 60, __ => onlineUserSvr.TryRemove(key, out _)), null);
|
||||
}, (key, v) => proxy(v, () => v.Reset()));
|
||||
});
|
||||
await next();
|
||||
}));
|
||||
|
||||
private static bool Filter(this HttpContext context)
|
||||
{
|
||||
var url = context.Request.Path;
|
||||
return !new string[] { "/api", "/NotiHub", "/swagger" }.Any(r => url.StartsWithSegments(r, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
using Bootstrap.Admin;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class OnlineUsersServicesCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
internal const string IPSvrHttpClientName = "IPSvr";
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddOnlineUsers(this IServiceCollection services)
|
||||
{
|
||||
services.TryAddSingleton<IOnlineUsers, DefaultOnlineUsers>();
|
||||
services.AddHttpClient(IPSvrHttpClientName, client =>
|
||||
{
|
||||
client.DefaultRequestHeaders.Connection.Add("keep-alive");
|
||||
});
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
using Bootstrap.DataAccess;
|
||||
using Bootstrap.DataAccess;
|
||||
using Bootstrap.Security.Filter;
|
||||
using Longbow.Web;
|
||||
using Longbow.Web.SignalR;
|
||||
|
@ -60,6 +60,7 @@ namespace Bootstrap.Admin
|
|||
services.AddConfigurationManager(Configuration);
|
||||
services.AddCacheManager(Configuration);
|
||||
services.AddDbAdapter();
|
||||
services.AddIPLocator(DictHelper.ConfigIPLocator);
|
||||
services.AddOnlineUsers();
|
||||
var dataProtectionBuilder = services.AddDataProtection(op => op.ApplicationDiscriminator = Configuration["ApplicationDiscriminator"])
|
||||
.SetApplicationName(Configuration["ApplicationName"])
|
||||
|
@ -127,7 +128,7 @@ namespace Bootstrap.Admin
|
|||
app.UseStaticFiles();
|
||||
app.UseAuthentication();
|
||||
app.UseBootstrapAdminAuthorization(RoleHelper.RetrieveRolesByUserName, RoleHelper.RetrieveRolesByUrl, AppHelper.RetrievesByUserName);
|
||||
app.UseOnlineUsers();
|
||||
app.UseOnlineUsers(callback: TraceHelper.Save);
|
||||
app.UseCacheManagerCorsHandler();
|
||||
app.UseSignalR(routes => { routes.MapHub<SignalRHub>("/NotiHub"); });
|
||||
app.UseMvc(routes =>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<PackageReference Include="Bootstrap.Security.DataAccess" Version="2.1.0" />
|
||||
<PackageReference Include="Longbow.Cache" Version="2.2.5" />
|
||||
<PackageReference Include="Longbow.Data" Version="2.2.6" />
|
||||
<PackageReference Include="Longbow.Web" Version="2.2.8" />
|
||||
<PackageReference Include="Longbow.Web" Version="2.2.9" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.2" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
|
@ -14,7 +14,7 @@
|
|||
<PackageReference Include="Bootstrap.Security.DataAccess" Version="2.1.0" />
|
||||
<PackageReference Include="Longbow.Data" Version="2.2.6" />
|
||||
<PackageReference Include="Longbow.Security.Cryptography" Version="1.3.0" />
|
||||
<PackageReference Include="Longbow.Web" Version="2.2.8" />
|
||||
<PackageReference Include="Longbow.Web" Version="2.2.9" />
|
||||
<PackageReference Include="Longbow.Cache" Version="2.2.5" />
|
||||
<PackageReference Include="Longbow" Version="2.2.8" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="2.2.2" />
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using Bootstrap.Security;
|
||||
using Longbow.Cache;
|
||||
using Longbow.Data;
|
||||
using Longbow.Web;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
|
@ -75,6 +77,21 @@ namespace Bootstrap.DataAccess
|
|||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="op"></param>
|
||||
public static void ConfigIPLocator(IPLocatorOption op)
|
||||
{
|
||||
var name = RetrieveLocaleIPSvr();
|
||||
if (!string.IsNullOrEmpty(name) && !name.Equals("None", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var url = RetrieveLocaleIPSvrUrl(name);
|
||||
op.Locator = string.IsNullOrEmpty(url) ? null : DefaultIPLocatorProvider.CreateLocator(name);
|
||||
op.Url = string.IsNullOrEmpty(url) ? string.Empty : $"{url}{op.IP}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存网站个性化设置
|
||||
/// </summary>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using Longbow.Data;
|
||||
using Longbow.Web;
|
||||
using Longbow.Web.Mvc;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using PetaPoco;
|
||||
using System;
|
||||
|
||||
|
@ -11,8 +13,27 @@ namespace Bootstrap.DataAccess
|
|||
/// <summary>
|
||||
/// 保存访问历史记录
|
||||
/// </summary>
|
||||
/// <param name="p"></param>
|
||||
public static void Save(Trace p) => DbContextManager.Create<Trace>().Save(p);
|
||||
/// <param name="context"></param>
|
||||
/// <param name="v"></param>
|
||||
public static void Save(HttpContext context, OnlineUser v)
|
||||
{
|
||||
if (context.User.Identity.IsAuthenticated)
|
||||
{
|
||||
var user = UserHelper.RetrieveUserByUserName(context.User.Identity.Name);
|
||||
v.UserName = user.UserName;
|
||||
v.DisplayName = user.DisplayName;
|
||||
DbContextManager.Create<Trace>().Save(new Trace
|
||||
{
|
||||
Ip = v.Ip,
|
||||
RequestUrl = v.RequestUrl,
|
||||
LogTime = v.LastAccessTime,
|
||||
City = v.Location,
|
||||
Browser = v.Browser,
|
||||
OS = v.OS,
|
||||
UserName = v.UserName
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得指定IP历史访问记录
|
||||
|
|
|
@ -1,32 +1,33 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Bootstrap.Admin.Api
|
||||
{
|
||||
public class OnlineTest : ControllerTest
|
||||
{
|
||||
public OnlineTest(BAWebHost factory) : base(factory, "api/OnlineUsers") { }
|
||||
|
||||
[Fact]
|
||||
public async void Get_Ok()
|
||||
{
|
||||
var users = await Client.GetAsJsonAsync<IEnumerable<OnlineUser>>();
|
||||
Assert.Single(users);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void GetById_Ok()
|
||||
{
|
||||
var urls = await Client.GetAsJsonAsync<IEnumerable<KeyValuePair<DateTime, string>>>("UnitTest");
|
||||
Assert.Empty(urls);
|
||||
using Longbow.Web;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Bootstrap.Admin.Api
|
||||
{
|
||||
public class OnlineTest : ControllerTest
|
||||
{
|
||||
public OnlineTest(BAWebHost factory) : base(factory, "api/OnlineUsers") { }
|
||||
|
||||
[Fact]
|
||||
public async void Get_Ok()
|
||||
{
|
||||
var users = await Client.GetAsJsonAsync<IEnumerable<OnlineUser>>();
|
||||
Assert.Single(users);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void Put_Ok()
|
||||
{
|
||||
var ret = await Client.PutAsJsonAsync<string, bool>("");
|
||||
Assert.False(ret);
|
||||
[Fact]
|
||||
public async void GetById_Ok()
|
||||
{
|
||||
var urls = await Client.GetAsJsonAsync<IEnumerable<KeyValuePair<DateTime, string>>>("UnitTest");
|
||||
Assert.Empty(urls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void Put_Ok()
|
||||
{
|
||||
var ret = await Client.PutAsJsonAsync<string, bool>("");
|
||||
Assert.False(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
using Bootstrap.DataAccess;
|
||||
using Longbow.Data;
|
||||
using Longbow.Web.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using Xunit;
|
||||
using DbManager = Longbow.Data.DbManager;
|
||||
|
||||
namespace Bootstrap.Admin.Api
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue