From a912362488a7f0c09868041d68fb671914e224a5 Mon Sep 17 00:00:00 2001
From: Argo Zhang <5196060@qq.com>
Date: Mon, 4 Mar 2019 01:27:04 +0800
Subject: [PATCH 1/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8A=9F=E8=83=BD?=
=?UTF-8?q?=EF=BC=9ASQLServer=20=E6=95=B0=E6=8D=AE=E5=BA=93=E4=B8=8B?=
=?UTF-8?q?=E7=99=BB=E5=BD=95=E4=BF=A1=E6=81=AF=E8=AE=B0=E5=BD=95=E5=88=B0?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E4=B8=AD=20link=20#IS7RM?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Controllers/AccountController.cs | 22 ++++++-
.../Controllers/Api/LoginController.cs | 5 +-
Bootstrap.DataAccess/Helper/LoginHelper.cs | 17 +++++
Bootstrap.DataAccess/Helper/UserHelper.cs | 17 ++++-
Bootstrap.DataAccess/LoginUser.cs | 64 +++++++++++++++++++
DatabaseScripts/Install.sql | 32 +++++++++-
6 files changed, 151 insertions(+), 6 deletions(-)
create mode 100644 Bootstrap.DataAccess/Helper/LoginHelper.cs
create mode 100644 Bootstrap.DataAccess/LoginUser.cs
diff --git a/Bootstrap.Admin/Controllers/AccountController.cs b/Bootstrap.Admin/Controllers/AccountController.cs
index 56433c25..c5fa9ed1 100644
--- a/Bootstrap.Admin/Controllers/AccountController.cs
+++ b/Bootstrap.Admin/Controllers/AccountController.cs
@@ -2,9 +2,11 @@
using Bootstrap.DataAccess;
using Longbow;
using Longbow.Configuration;
+using Longbow.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Linq;
@@ -34,13 +36,14 @@ namespace Bootstrap.Admin.Controllers
/// Login the specified userName, password and remember.
///
/// The login.
+ ///
/// User name.
/// Password.
/// Remember.
[HttpPost]
- public async Task Login(string userName, string password, string remember)
+ public async Task Login([FromServices]IOnlineUsers onlineUserSvr, string userName, string password, string remember)
{
- if (UserHelper.Authenticate(userName, password))
+ if (UserHelper.Authenticate(userName, password, loginUser => CreateLoginUser(onlineUserSvr, HttpContext, loginUser)))
{
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Name, userName));
@@ -51,6 +54,21 @@ namespace Bootstrap.Admin.Controllers
return Redirect(originUrl);
}
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ internal static void CreateLoginUser(IOnlineUsers onlineUserSvr, HttpContext context, LoginUser loginUser)
+ {
+ var agent = new UserAgent(context.Request.Headers["User-Agent"]);
+ loginUser.Ip = context.Connection.RemoteIpAddress?.ToString();
+ loginUser.City = onlineUserSvr.RetrieveLocaleByIp(loginUser.Ip);
+ loginUser.Browser = $"{agent.Browser.Name} {agent.Browser.Version}";
+ loginUser.OS = $"{agent.OS.Name} {agent.OS.Version}";
+ }
+
///
/// Logout this instance.
///
diff --git a/Bootstrap.Admin/Controllers/Api/LoginController.cs b/Bootstrap.Admin/Controllers/Api/LoginController.cs
index ad81582f..425a276b 100644
--- a/Bootstrap.Admin/Controllers/Api/LoginController.cs
+++ b/Bootstrap.Admin/Controllers/Api/LoginController.cs
@@ -19,17 +19,18 @@ namespace Bootstrap.Admin.Controllers.Api
///
///
///
+ ///
///
///
[AllowAnonymous]
[HttpPost]
- public string Post([FromBody]JObject value)
+ public string Post([FromServices]IOnlineUsers onlineUserSvr, [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))
+ if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password) && UserHelper.Authenticate(userName, password, loginUser => AccountController.CreateLoginUser(onlineUserSvr, HttpContext, loginUser)))
{
token = BootstrapAdminJwtTokenHandler.CreateToken(userName);
}
diff --git a/Bootstrap.DataAccess/Helper/LoginHelper.cs b/Bootstrap.DataAccess/Helper/LoginHelper.cs
new file mode 100644
index 00000000..31b9e057
--- /dev/null
+++ b/Bootstrap.DataAccess/Helper/LoginHelper.cs
@@ -0,0 +1,17 @@
+using Longbow.Data;
+
+namespace Bootstrap.DataAccess
+{
+ ///
+ ///
+ ///
+ public static class LoginHelper
+ {
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static bool Log(LoginUser user) => DbContextManager.Create().Log(user);
+ }
+}
diff --git a/Bootstrap.DataAccess/Helper/UserHelper.cs b/Bootstrap.DataAccess/Helper/UserHelper.cs
index eaf761e3..e92f5607 100644
--- a/Bootstrap.DataAccess/Helper/UserHelper.cs
+++ b/Bootstrap.DataAccess/Helper/UserHelper.cs
@@ -1,6 +1,7 @@
using Bootstrap.Security;
using Longbow.Cache;
using Longbow.Data;
+using System;
using System.Collections.Generic;
namespace Bootstrap.DataAccess
@@ -29,7 +30,21 @@ namespace Bootstrap.DataAccess
///
///
///
- public static bool Authenticate(string userName, string password) => DbContextManager.Create().Authenticate(userName, password);
+ public static bool Authenticate(string userName, string password, Action config)
+ {
+ var loginUser = new LoginUser()
+ {
+ UserName = userName,
+ LoginTime = DateTime.Now,
+ Result = "登录失败"
+ };
+ config(loginUser);
+ if (string.IsNullOrEmpty(loginUser.Ip)) loginUser.Ip = System.Net.IPAddress.IPv6Loopback.ToString();
+ var ret = DbContextManager.Create().Authenticate(userName, password);
+ if (ret) loginUser.Result = "登录成功";
+ LoginHelper.Log(loginUser);
+ return ret;
+ }
///
/// 查询所有的新注册用户
diff --git a/Bootstrap.DataAccess/LoginUser.cs b/Bootstrap.DataAccess/LoginUser.cs
new file mode 100644
index 00000000..44f159a2
--- /dev/null
+++ b/Bootstrap.DataAccess/LoginUser.cs
@@ -0,0 +1,64 @@
+using PetaPoco;
+using System;
+
+namespace Bootstrap.DataAccess
+{
+ ///
+ ///
+ ///
+ [TableName("LoginLogs")]
+ public class LoginUser
+ {
+ ///
+ ///
+ ///
+ public string Id { get; set; }
+
+ ///
+ ///
+ ///
+ public string UserName { get; set; }
+
+ ///
+ ///
+ ///
+ public DateTime LoginTime { get; set; }
+
+ ///
+ ///
+ ///
+ public string Ip { get; set; }
+
+ ///
+ ///
+ ///
+ public string Browser { get; set; }
+
+ ///
+ ///
+ ///
+ public string OS { get; set; }
+
+ ///
+ ///
+ ///
+ public string City { get; set; }
+
+ ///
+ ///
+ ///
+ public string Result { get; set; }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual bool Log(LoginUser user)
+ {
+ var db = DbManager.Create();
+ db.Save(user);
+ return true;
+ }
+ }
+}
diff --git a/DatabaseScripts/Install.sql b/DatabaseScripts/Install.sql
index d472fd1e..cab77854 100644
--- a/DatabaseScripts/Install.sql
+++ b/DatabaseScripts/Install.sql
@@ -473,4 +473,34 @@ EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'显示名称'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'注册时间' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'RejectUsers', @level2type=N'COLUMN',@level2name=N'RegisterTime'
-GO
\ No newline at end of file
+GO
+
+/****** Object: Table [dbo].[LoginLogs] Script Date: 03/03/2019 20:05:42 ******/
+SET ANSI_NULLS ON
+GO
+
+SET QUOTED_IDENTIFIER ON
+GO
+
+SET ANSI_PADDING ON
+GO
+
+CREATE TABLE [dbo].[LoginLogs](
+ [ID] [int] IDENTITY(1,1) NOT NULL,
+ [UserName] [varchar](50) NOT NULL,
+ [LoginTime] [datetime] NOT NULL,
+ [Ip] [varchar](15) NOT NULL,
+ [OS] [varchar](50) NULL,
+ [Browser] [varchar](50) NULL,
+ [City] [nvarchar](50) NULL,
+ [Result] [nvarchar](50) NOT NULL,
+ CONSTRAINT [PK_LoginLogs] PRIMARY KEY CLUSTERED
+(
+ [ID] ASC
+)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+) ON [PRIMARY]
+
+GO
+
+SET ANSI_PADDING OFF
+GO
From 9924d8c3c40689dcf4daab050ac51df8295c8a20 Mon Sep 17 00:00:00 2001
From: Argo Zhang <5196060@qq.com>
Date: Mon, 4 Mar 2019 01:34:43 +0800
Subject: [PATCH 2/5] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=84=9A=E6=9C=AC?=
=?UTF-8?q?=EF=BC=9A=E5=AE=8C=E5=96=84SQLite=E7=AD=89=E6=95=B0=E6=8D=AE?=
=?UTF-8?q?=E5=BA=93=E8=84=9A=E6=9C=AC=20link=20#IS7RM?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
DatabaseScripts/MySQL/install.sql | 11 +++++++++++
DatabaseScripts/Postgresql/install.sql | 11 +++++++++++
DatabaseScripts/SQLite/Install.sql | 11 +++++++++++
3 files changed, 33 insertions(+)
diff --git a/DatabaseScripts/MySQL/install.sql b/DatabaseScripts/MySQL/install.sql
index 47c5f1f3..c137175c 100644
--- a/DatabaseScripts/MySQL/install.sql
+++ b/DatabaseScripts/MySQL/install.sql
@@ -144,4 +144,15 @@ CREATE TABLE RejectUsers(
RejectedBy VARCHAR (50) NOT NULL,
RejectedTime DATETIME NOT NULL,
RejectedReason VARCHAR (50) NULL
+);
+
+CREATE TABLE LoginLogs(
+ ID INTEGER PRIMARY KEY Auto_increment,
+ UserName VARCHAR (50) NOT NULL,
+ LoginTime DATETIME NOT NULL,
+ Ip VARCHAR NOT NULL,
+ OS VARCHAR (50) NULL,
+ Browser VARCHAR (50) NULL,
+ City VARCHAR (50) NULL,
+ Result VARCHAR (50) NOT NULL
);
\ No newline at end of file
diff --git a/DatabaseScripts/Postgresql/install.sql b/DatabaseScripts/Postgresql/install.sql
index b7c7a485..9ee63029 100644
--- a/DatabaseScripts/Postgresql/install.sql
+++ b/DatabaseScripts/Postgresql/install.sql
@@ -144,4 +144,15 @@ CREATE TABLE RejectUsers(
RejectedBy VARCHAR (50) NOT NULL,
RejectedTime DATE NOT NULL,
RejectedReason VARCHAR (50) NULL
+);
+
+CREATE TABLE RejectUsers(
+ ID SERIAL PRIMARY KEY,
+ UserName VARCHAR (50) NOT NULL,
+ LoginTime DATE NOT NULL,
+ Ip VARCHAR NOT NULL,
+ OS VARCHAR (50) NULL,
+ Browser VARCHAR (50) NULL,
+ City VARCHAR (50) NULL,
+ Result VARCHAR (50) NOT NULL
);
\ No newline at end of file
diff --git a/DatabaseScripts/SQLite/Install.sql b/DatabaseScripts/SQLite/Install.sql
index e99bb794..d284c8f4 100644
--- a/DatabaseScripts/SQLite/Install.sql
+++ b/DatabaseScripts/SQLite/Install.sql
@@ -144,4 +144,15 @@ CREATE TABLE RejectUsers(
[RejectedBy] VARCHAR (50) NOT NULL COLLATE NOCASE,
[RejectedTime] DATETIME NOT NULL,
[RejectedReason] VARCHAR (50) NULL
+);
+
+CREATE TABLE LoginLogs(
+ [ID] INTEGER PRIMARY KEY,
+ [UserName] VARCHAR (50) NOT NULL COLLATE NOCASE,
+ [LoginTime] DATETIME NOT NULL,
+ [Ip] VARCHAR (15) NOT NULL,
+ [OS] VARCHAR (50) NULL,
+ [Browser] VARCHAR (50) NULL,
+ [City] VARCHAR (50) NULL,
+ [Result] VARCHAR (50) NOT NULL
);
\ No newline at end of file
From 348438896c3bd5f70d8a197ba1d89e2bf365383b Mon Sep 17 00:00:00 2001
From: Argo Zhang <5196060@qq.com>
Date: Mon, 4 Mar 2019 02:41:53 +0800
Subject: [PATCH 3/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8A=9F=E8=83=BD?=
=?UTF-8?q?=EF=BC=9A=E5=A2=9E=E5=8A=A0MongoDB=E6=95=B0=E6=8D=AE=E5=BA=93?=
=?UTF-8?q?=E5=AF=B9=E7=99=BB=E5=BD=95=E6=97=A5=E5=BF=97=E6=94=AF=E6=8C=81?=
=?UTF-8?q?=20link=20#IS7RM?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Bootstrap.DataAccess.MongoDB/DbManager.cs | 20 ++++++++++++++++++++
Bootstrap.DataAccess.MongoDB/LoginUser.cs | 19 +++++++++++++++++++
2 files changed, 39 insertions(+)
create mode 100644 Bootstrap.DataAccess.MongoDB/LoginUser.cs
diff --git a/Bootstrap.DataAccess.MongoDB/DbManager.cs b/Bootstrap.DataAccess.MongoDB/DbManager.cs
index fb3cc457..75f6b98c 100644
--- a/Bootstrap.DataAccess.MongoDB/DbManager.cs
+++ b/Bootstrap.DataAccess.MongoDB/DbManager.cs
@@ -116,6 +116,17 @@ namespace Bootstrap.DataAccess.MongoDB
return DBAccess.GetCollection("Navigations");
}
}
+
+ ///
+ ///
+ ///
+ public static IMongoCollection LoginUsers
+ {
+ get
+ {
+ return DBAccess.GetCollection("LoginLogs");
+ }
+ }
#endregion
private static void InitDb()
@@ -220,6 +231,15 @@ namespace Bootstrap.DataAccess.MongoDB
md.IdMemberMap.SetIgnoreIfDefault(true);
});
}
+ if (!BsonClassMap.IsClassMapRegistered(typeof(DataAccess.LoginUser)))
+ {
+ BsonClassMap.RegisterClassMap(md =>
+ {
+ md.AutoMap();
+ md.IdMemberMap.SetSerializer(new StringSerializer(BsonType.ObjectId));
+ md.IdMemberMap.SetIgnoreIfDefault(true);
+ });
+ }
}
}
}
diff --git a/Bootstrap.DataAccess.MongoDB/LoginUser.cs b/Bootstrap.DataAccess.MongoDB/LoginUser.cs
new file mode 100644
index 00000000..80859b21
--- /dev/null
+++ b/Bootstrap.DataAccess.MongoDB/LoginUser.cs
@@ -0,0 +1,19 @@
+namespace Bootstrap.DataAccess.MongoDB
+{
+ ///
+ ///
+ ///
+ public class LoginUser : DataAccess.LoginUser
+ {
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override bool Log(DataAccess.LoginUser user)
+ {
+ DbManager.LoginUsers.InsertOne(user);
+ return true;
+ }
+ }
+}
From 64c2e102901ab953485e7b8456379610af65cb1d Mon Sep 17 00:00:00 2001
From: Argo Zhang <5196060@qq.com>
Date: Mon, 4 Mar 2019 13:21:04 +0800
Subject: [PATCH 4/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8A=9F=E8=83=BD?=
=?UTF-8?q?=EF=BC=9A=E5=A2=9E=E5=8A=A0=E7=99=BB=E5=BD=95=E6=97=A5=E5=BF=97?=
=?UTF-8?q?=E9=A1=B5=E9=9D=A2Admin/Logins=20link=20#IS7RM?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Controllers/AdminController.cs | 6 ++++
.../Controllers/Api/LoginController.cs | 9 ++++++
Bootstrap.Admin/Views/Admin/Logins.cshtml | 29 +++++++++++++++++
Bootstrap.Admin/Views/Admin/Logs.cshtml | 2 +-
Bootstrap.Admin/appsettings.json | 1 +
Bootstrap.Admin/wwwroot/js/logins.js | 31 +++++++++++++++++++
Bootstrap.DataAccess.MongoDB/LoginUser.cs | 11 ++++++-
Bootstrap.DataAccess/Helper/LoginHelper.cs | 21 +++++++++++--
Bootstrap.DataAccess/LoginUser.cs | 16 +++++++++-
DatabaseScripts/InitData.sql | 4 ++-
.../MongoDB/BootstrapAdmin.Navigations.json | 26 +++++++++++++++-
DatabaseScripts/MySQL/initData.sql | 4 ++-
DatabaseScripts/Postgresql/initData.sql | 4 ++-
DatabaseScripts/SQLite/InitData.sql | 4 ++-
UnitTest/Bootstrap.Admin/Api/LoginTest.cs | 11 ++++++-
.../Bootstrap.Admin/Controllers/AdminTest.cs | 3 +-
16 files changed, 170 insertions(+), 12 deletions(-)
create mode 100644 Bootstrap.Admin/Views/Admin/Logins.cshtml
create mode 100644 Bootstrap.Admin/wwwroot/js/logins.js
diff --git a/Bootstrap.Admin/Controllers/AdminController.cs b/Bootstrap.Admin/Controllers/AdminController.cs
index a4ea5266..3d864ccd 100644
--- a/Bootstrap.Admin/Controllers/AdminController.cs
+++ b/Bootstrap.Admin/Controllers/AdminController.cs
@@ -52,6 +52,12 @@ namespace Bootstrap.Admin.Controllers
///
public ActionResult Logs() => View(new NavigatorBarModel(this));
+ ///
+ ///
+ ///
+ ///
+ public ActionResult Logins() => View(new NavigatorBarModel(this));
+
///
///
///
diff --git a/Bootstrap.Admin/Controllers/Api/LoginController.cs b/Bootstrap.Admin/Controllers/Api/LoginController.cs
index 425a276b..592163b2 100644
--- a/Bootstrap.Admin/Controllers/Api/LoginController.cs
+++ b/Bootstrap.Admin/Controllers/Api/LoginController.cs
@@ -3,6 +3,8 @@ using Bootstrap.Security;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
+using System.Collections.Generic;
+using System.Linq;
namespace Bootstrap.Admin.Controllers.Api
{
@@ -16,6 +18,13 @@ namespace Bootstrap.Admin.Controllers.Api
[ApiController]
public class LoginController : ControllerBase
{
+ ///
+ /// 获得登录历史记录
+ ///
+ ///
+ [HttpGet]
+ public IEnumerable Get() => LoginHelper.Retrieves();
+
///
///
///
diff --git a/Bootstrap.Admin/Views/Admin/Logins.cshtml b/Bootstrap.Admin/Views/Admin/Logins.cshtml
new file mode 100644
index 00000000..3caa048f
--- /dev/null
+++ b/Bootstrap.Admin/Views/Admin/Logins.cshtml
@@ -0,0 +1,29 @@
+@model NavigatorBarModel
+@{
+ ViewBag.Title = "登录日志";
+}
+@section css {
+
+
+
+
+
+
+}
+@section javascript {
+
+
+
+
+
+
+
+
+
+}
+
\ No newline at end of file
diff --git a/Bootstrap.Admin/Views/Admin/Logs.cshtml b/Bootstrap.Admin/Views/Admin/Logs.cshtml
index a93083ea..ca009ff5 100644
--- a/Bootstrap.Admin/Views/Admin/Logs.cshtml
+++ b/Bootstrap.Admin/Views/Admin/Logs.cshtml
@@ -1,6 +1,6 @@
@model NavigatorBarModel
@{
- ViewBag.Title = "系统日志";
+ ViewBag.Title = "操作日志";
}
@section css {
diff --git a/Bootstrap.Admin/appsettings.json b/Bootstrap.Admin/appsettings.json
index 15dbe2ae..276bcdbd 100644
--- a/Bootstrap.Admin/appsettings.json
+++ b/Bootstrap.Admin/appsettings.json
@@ -65,6 +65,7 @@
"KeepExceptionsPeriod": 12,
"KeepLogsPeriod": 12,
"CookieExpiresDays": 7,
+ "KeepLoginLogsPeriod": 7,
"LongbowCache": {
"Enabled": true,
"CorsItems": [
diff --git a/Bootstrap.Admin/wwwroot/js/logins.js b/Bootstrap.Admin/wwwroot/js/logins.js
new file mode 100644
index 00000000..5bb832eb
--- /dev/null
+++ b/Bootstrap.Admin/wwwroot/js/logins.js
@@ -0,0 +1,31 @@
+// 登录日志
+$(function () {
+ var apiUrl = "api/Login";
+ var $table = $('table').smartTable({
+ url: apiUrl,
+ method: "get",
+ sidePagination: "client",
+ showToggle: false,
+ showRefresh: false,
+ showColumns: false,
+ columns: [
+ {
+ title: "序号", formatter: function (value, row, index) {
+ var options = $table.bootstrapTable('getOptions');
+ return options.pageSize * (options.pageNumber - 1) + index + 1;
+ }
+ },
+ { title: "登陆名称", field: "UserName" },
+ { title: "登录时间", field: "LoginTime" },
+ { title: "主机", field: "Ip" },
+ { title: "登录地点", field: "City" },
+ { title: "浏览器", field: "Browser" },
+ { title: "操作系统", field: "OS" },
+ { title: "登录结果", field: "Result" }
+ ]
+ });
+
+ $('#refreshUsers').tooltip().on('click', function () {
+ $table.bootstrapTable('refresh');
+ });
+});
\ No newline at end of file
diff --git a/Bootstrap.DataAccess.MongoDB/LoginUser.cs b/Bootstrap.DataAccess.MongoDB/LoginUser.cs
index 80859b21..5d46434f 100644
--- a/Bootstrap.DataAccess.MongoDB/LoginUser.cs
+++ b/Bootstrap.DataAccess.MongoDB/LoginUser.cs
@@ -1,4 +1,7 @@
-namespace Bootstrap.DataAccess.MongoDB
+using MongoDB.Driver;
+using System.Collections.Generic;
+
+namespace Bootstrap.DataAccess.MongoDB
{
///
///
@@ -15,5 +18,11 @@
DbManager.LoginUsers.InsertOne(user);
return true;
}
+
+ ///
+ ///
+ ///
+ ///
+ public override IEnumerable Retrieves() => DbManager.LoginUsers.Find(FilterDefinition.Empty).SortByDescending(user => user.LoginTime).ToList();
}
}
diff --git a/Bootstrap.DataAccess/Helper/LoginHelper.cs b/Bootstrap.DataAccess/Helper/LoginHelper.cs
index 31b9e057..20844f2a 100644
--- a/Bootstrap.DataAccess/Helper/LoginHelper.cs
+++ b/Bootstrap.DataAccess/Helper/LoginHelper.cs
@@ -1,4 +1,6 @@
-using Longbow.Data;
+using Longbow.Cache;
+using Longbow.Data;
+using System.Collections.Generic;
namespace Bootstrap.DataAccess
{
@@ -7,11 +9,26 @@ namespace Bootstrap.DataAccess
///
public static class LoginHelper
{
+ ///
+ ///
+ ///
+ public const string RetrieveLoginLogsDataKey = "LoginHelper-Retrieves";
+
///
///
///
///
///
- public static bool Log(LoginUser user) => DbContextManager.Create().Log(user);
+ public static bool Log(LoginUser user)
+ {
+ var ret = DbContextManager.Create().Log(user);
+ if (ret) CacheManager.Clear(RetrieveLoginLogsDataKey);
+ return ret;
+ }
+
+ ///
+ /// 查询一个月内所有登录信息
+ ///
+ public static IEnumerable Retrieves() => CacheManager.GetOrAdd(RetrieveLoginLogsDataKey, key => DbContextManager.Create().Retrieves());
}
}
diff --git a/Bootstrap.DataAccess/LoginUser.cs b/Bootstrap.DataAccess/LoginUser.cs
index 44f159a2..0dc50135 100644
--- a/Bootstrap.DataAccess/LoginUser.cs
+++ b/Bootstrap.DataAccess/LoginUser.cs
@@ -1,5 +1,8 @@
-using PetaPoco;
+using Longbow;
+using Longbow.Configuration;
+using PetaPoco;
using System;
+using System.Collections.Generic;
namespace Bootstrap.DataAccess
{
@@ -60,5 +63,16 @@ namespace Bootstrap.DataAccess
db.Save(user);
return true;
}
+
+ ///
+ ///
+ ///
+ protected const string KeepLoginLogsPeriodKey = "KeepLoginLogsPeriod";
+
+ ///
+ ///
+ ///
+ ///
+ public virtual IEnumerable Retrieves() => DbManager.Create().Fetch("Where LoginTime > @0 Order by LoginTime desc", DateTime.Today.AddDays(0 - LgbConvert.ReadValue(ConfigurationManager.AppSettings[KeepLoginLogsPeriodKey], 7)));
}
}
diff --git a/DatabaseScripts/InitData.sql b/DatabaseScripts/InitData.sql
index 68719da3..9062d4fe 100644
--- a/DatabaseScripts/InitData.sql
+++ b/DatabaseScripts/InitData.sql
@@ -45,7 +45,9 @@ INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [C
INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (10, 0, N'站内消息', 100, N'fa fa-envelope', N'~/Admin/Messages', N'0')
INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (11, 0, N'任务管理', 110, N'fa fa fa-tasks', N'~/Admin/Tasks', N'0')
INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (12, 0, N'通知管理', 120, N'fa fa-bell', N'~/Admin/Notifications', N'0')
-INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (13, 0, N'系统日志', 130, N'fa fa-gears', N'~/Admin/Logs', N'0')
+INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (13, 0, N'日志管理', 130, N'fa fa-gears', N'#', N'0')
+INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (20, 13, N'操作日志', 10, N'fa fa-edit', N'~/Admin/Logs', N'0')
+INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (21, 13, N'登录日志', 20, N'fa fa-user-circle-o', N'~/Admin/Logins', N'0')
INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (14, 0, N'在线用户', 140, N'fa fa-users', N'~/Admin/Online', N'0')
INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (15, 0, N'程序异常', 150, N'fa fa-cubes', N'~/Admin/Exceptions', N'0')
INSERT [dbo].[Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (16, 0, N'工具集合', 160, N'fa fa-gavel', N'#', N'0')
diff --git a/DatabaseScripts/MongoDB/BootstrapAdmin.Navigations.json b/DatabaseScripts/MongoDB/BootstrapAdmin.Navigations.json
index e00a5823..0fd52445 100644
--- a/DatabaseScripts/MongoDB/BootstrapAdmin.Navigations.json
+++ b/DatabaseScripts/MongoDB/BootstrapAdmin.Navigations.json
@@ -146,15 +146,39 @@
{
"_id": ObjectId("5bd7b8445fa31256f77e4b9c"),
"ParentId": "0",
- "Name": "系统日志",
+ "Name": "日志管理",
"Order": NumberInt(130),
"Icon": "fa fa-gears",
+ "Url": "#",
+ "Category": "0",
+ "Target": "_self",
+ "IsResource": NumberInt(0),
+ "Application": "0"
+ },
+ {
+ "_id": ObjectId("5bd9b3d868aa001661776f57"),
+ "ParentId": "5bd7b8445fa31256f77e4b9c",
+ "Name": "操作日志",
+ "Order": NumberInt(10),
+ "Icon": "fa fa-edit",
"Url": "~/Admin/Logs",
"Category": "0",
"Target": "_self",
"IsResource": NumberInt(0),
"Application": "0"
},
+ {
+ "_id": ObjectId("5bd9b3d868aa001661776f58"),
+ "ParentId": "5bd7b8445fa31256f77e4b9c",
+ "Name": "登录日志",
+ "Order": NumberInt(20),
+ "Icon": "fa fa-user-circle-o",
+ "Url": "~/Admin/Logins",
+ "Category": "0",
+ "Target": "_self",
+ "IsResource": NumberInt(0),
+ "Application": "0"
+ },
{
"_id": ObjectId("5bd7b8445fa31256f77e4b89"),
"ParentId": "0",
diff --git a/DatabaseScripts/MySQL/initData.sql b/DatabaseScripts/MySQL/initData.sql
index d02e41e7..f06c3b2d 100644
--- a/DatabaseScripts/MySQL/initData.sql
+++ b/DatabaseScripts/MySQL/initData.sql
@@ -42,7 +42,9 @@ INSERT INTO Navigations (ID, ParentId, Name, `Order`, Icon, Url, Category) VALUE
INSERT INTO Navigations (ID, ParentId, Name, `Order`, Icon, Url, Category) VALUES (10, 0, '站内消息', 100, 'fa fa-envelope', '~/Admin/Messages', '0');
INSERT INTO Navigations (ID, ParentId, Name, `Order`, Icon, Url, Category) VALUES (11, 0, '任务管理', 110, 'fa fa fa-tasks', '~/Admin/Tasks', '0');
INSERT INTO Navigations (ID, ParentId, Name, `Order`, Icon, Url, Category) VALUES (12, 0, '通知管理', 120, 'fa fa-bell', '~/Admin/Notifications', '0');
-INSERT INTO Navigations (ID, ParentId, Name, `Order`, Icon, Url, Category) VALUES (13, 0, '系统日志', 130, 'fa fa-gears', '~/Admin/Logs', '0');
+INSERT INTO Navigations (ID, ParentId, Name, `Order`, Icon, Url, Category) VALUES (13, 0, '系统日志', 130, 'fa fa-gears', '#', '0');
+INSERT INTO Navigations (ID, ParentId, Name, `Order`, Icon, Url, Category) VALUES (20, 13, '操作日志', 10, 'fa fa-edit', '~/Admin/Logs', '0');
+INSERT INTO Navigations (ID, ParentId, Name, `Order`, Icon, Url, Category) VALUES (21, 13, '登录日志', 20, 'fa fa-user-circle-o', '~/Admin/Logins', '0');
INSERT INTO Navigations (ID, ParentId, Name, `Order`, Icon, Url, Category) VALUES (14, 0, '在线用户', 140, 'fa fa-users', '~/Admin/Online', '0');
INSERT INTO Navigations (ID, ParentId, Name, `Order`, Icon, Url, Category) VALUES (15, 0, '程序异常', 150, 'fa fa-cubes', '~/Admin/Exceptions', '0');
INSERT INTO Navigations (ID, ParentId, Name, `Order`, Icon, Url, Category) VALUES (16, 0, '工具集合', 160, 'fa fa-gavel', '#', '0');
diff --git a/DatabaseScripts/Postgresql/initData.sql b/DatabaseScripts/Postgresql/initData.sql
index abbcc8ab..e9cd5335 100644
--- a/DatabaseScripts/Postgresql/initData.sql
+++ b/DatabaseScripts/Postgresql/initData.sql
@@ -42,7 +42,9 @@ INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '站内消息', 100, 'fa fa-envelope', '~/Admin/Messages', '0');
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '任务管理', 110, 'fa fa fa-tasks', '~/Admin/Tasks', '0');
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '通知管理', 120, 'fa fa-bell', '~/Admin/Notifications', '0');
-INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '系统日志', 130, 'fa fa-gears', '~/Admin/Logs', '0');
+INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '系统日志', 130, 'fa fa-gears', '#', '0');
+INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (currval('navigations_id_seq') - 1, 0, '操作日志', 10, 'fa fa-edit', '~/Admin/Logs', '0');
+INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (currval('navigations_id_seq') - 2, 0, '登录日志', 20, 'fa fa-user-circle-o', '~/Admin/Logins', '0');
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '在线用户', 140, 'fa fa-users', '~/Admin/Online', '0');
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '程序异常', 150, 'fa fa-cubes', '~/Admin/Exceptions', '0');
INSERT INTO Navigations (ParentId, Name, "order", Icon, Url, Category) VALUES (0, '工具集合', 160, 'fa fa-gavel', '#', '0');
diff --git a/DatabaseScripts/SQLite/InitData.sql b/DatabaseScripts/SQLite/InitData.sql
index fadaf135..b0137ba0 100644
--- a/DatabaseScripts/SQLite/InitData.sql
+++ b/DatabaseScripts/SQLite/InitData.sql
@@ -39,7 +39,9 @@ INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Ca
INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (10, 0, '站内消息', 100, 'fa fa-envelope', '~/Admin/Messages', '0');
INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (11, 0, '任务管理', 110, 'fa fa fa-tasks', '~/Admin/Tasks', '0');
INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (12, 0, '通知管理', 120, 'fa fa-bell', '~/Admin/Notifications', '0');
-INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (13, 0, '系统日志', 130, 'fa fa-gears', '~/Admin/Logs', '0');
+INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (13, 0, '系统日志', 130, 'fa fa-gears', '#', '0');
+INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (20, 13, '操作日志', 10, 'fa fa-edit', '~/Admin/Logs', '0');
+INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (21, 13, '登录日志', 20, 'fa fa-user-circle-o', '~/Admin/Logins', '0');
INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (14, 0, '在线用户', 140, 'fa fa-users', '~/Admin/Online', '0');
INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (15, 0, '程序异常', 150, 'fa fa-cubes', '~/Admin/Exceptions', '0');
INSERT INTO [Navigations] ([ID], [ParentId], [Name], [Order], [Icon], [Url], [Category]) VALUES (16, 0, '工具集合', 160, 'fa fa-gavel', '#', '0');
diff --git a/UnitTest/Bootstrap.Admin/Api/LoginTest.cs b/UnitTest/Bootstrap.Admin/Api/LoginTest.cs
index 7c275c2a..6e18b793 100644
--- a/UnitTest/Bootstrap.Admin/Api/LoginTest.cs
+++ b/UnitTest/Bootstrap.Admin/Api/LoginTest.cs
@@ -1,4 +1,6 @@
-using System.Net.Http;
+using Bootstrap.DataAccess;
+using System.Collections.Generic;
+using System.Net.Http;
using Xunit;
namespace Bootstrap.Admin.Api
@@ -7,6 +9,13 @@ namespace Bootstrap.Admin.Api
{
public LoginTest(BAWebHost factory) : base(factory, "api/Login") { }
+ [Fact]
+ public async void Login_Get()
+ {
+ var users = await Client.GetAsJsonAsync>();
+ Assert.NotEmpty(users);
+ }
+
[Fact]
public async void Login_Ok()
{
diff --git a/UnitTest/Bootstrap.Admin/Controllers/AdminTest.cs b/UnitTest/Bootstrap.Admin/Controllers/AdminTest.cs
index 80acdc5b..9a58e1cb 100644
--- a/UnitTest/Bootstrap.Admin/Controllers/AdminTest.cs
+++ b/UnitTest/Bootstrap.Admin/Controllers/AdminTest.cs
@@ -14,7 +14,8 @@ namespace Bootstrap.Admin.Controllers
[InlineData("Dicts", "字典表维护")]
[InlineData("Roles", "角色管理")]
[InlineData("Menus", "菜单管理")]
- [InlineData("Logs", "系统日志")]
+ [InlineData("Logs", "操作日志")]
+ [InlineData("Logins", "登录日志")]
[InlineData("FAIcon", "图标集")]
[InlineData("IconView", "图标分类")]
[InlineData("Settings", "网站设置")]
From 5fb873ff1b2fc522793a768671256a0abc0e1762 Mon Sep 17 00:00:00 2001
From: Argo Zhang <5196060@qq.com>
Date: Mon, 4 Mar 2019 15:32:08 +0800
Subject: [PATCH 5/5] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E4=BB=B6?=
=?UTF-8?q?=EF=BC=9ASQLite=E6=95=B0=E6=8D=AE=E6=96=87=E4=BB=B6=E6=9B=B4?=
=?UTF-8?q?=E6=96=B0=EF=BC=8C=E5=A2=9E=E5=8A=A0LoginLogs=E8=A1=A8=20link?=
=?UTF-8?q?=20#IS7RM?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
UnitTest/DB/UnitTest.db | Bin 81920 -> 81920 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/UnitTest/DB/UnitTest.db b/UnitTest/DB/UnitTest.db
index 75955d9b735548c319db112f4a16dcd9daccbc72..e5cacefdd4ea5595203efedea837fc9ae783167e 100644
GIT binary patch
delta 639
zcmZo@U~On%oggh3%)r1P0>m(Ie4>sqWAMg=YB>xFANPreu~N>4fRi;pJvf=1^r)<_FpReDm(-
zyXQmnF*HFmrl%$r6)SJn>Ak_ktN?U9`vfiVJpOe4c>ZvHe|~p4Nv=9@UG>8^tVv_>V0!(a@AexJb
zO#(zSGqH(-XeK6BF%||+MkZEKAeU2=RRlzdY_6H#(ICdjmdC)K#uvc5jwhab0+$iT
zclM=hc|d1`u$ecR2(pXI%QLo^mn0_Tq=G{WNEE{vBF;gsjv=lJA&yQyt_m>W$&IWE
z)0s3Fjab1VlNq_Br~lJqlx6Y{p1grYoZYD?zZ@7FAU2D0W=SQ8F*%V-Y_bCrI}?}Y
W_ND5K(Hv~Npd==+oy~yp7e4^1=bhC6
delta 359
zcmZo@U~On%oggj9%)r1P0>z9#`q)GrV@BqU3EA?ph6;wpRwgD^#zsa4hL*Yp#<~Uw
zq0KMkWfBa;xTP5QPw;p0d-DtNUFDn0m&B*Z`;K=#Z!xbi&o7?+JPkZSJi^@fxfgSn
zaC>n}Z59-G#>J;6#?8Pe$tbJJFV4X)I(bKzGNb6^J6)QLBAeN|TNpXbdAS)lRGE}j
zC-e2n^3>@&rsQVk>HFlT7jM?-y}`sR$FDk>eS(&7E`KV2EPp7!FTX3lEx#$hF25?!
zf`@$JY;r6NjErJTY_cF)l!;9SM2j%7NrPx%CN?P$EyTno38Dp=*d#!-027-yh~{Eq
z69duAOl+bcnu&>3goS~Vk!f?y{Eh|@4)&!C{Aqjvyz6-4xhHTLaeQZA3beMDefv^%
S#%K;UU?2j)b~XdXU;F?^z(X_u