Merge pull request !5 from Argo-QQ/dev-#IS7V2
This commit is contained in:
commit
7ddd94c162
|
@ -1,9 +1,12 @@
|
||||||
using Bootstrap.DataAccess;
|
using Bootstrap.DataAccess;
|
||||||
|
using Longbow.Web;
|
||||||
using Longbow.Web.SignalR;
|
using Longbow.Web.SignalR;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Bootstrap.Admin.Controllers.Api
|
namespace Bootstrap.Admin.Controllers.Api
|
||||||
|
@ -41,15 +44,20 @@ namespace Bootstrap.Admin.Controllers.Api
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重置密码调用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userName"></param>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
[HttpPut("{userName}")]
|
||||||
|
public bool Put(string userName, [FromBody]User user) => UserHelper.ResetPassword(userName, user.Password);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 忘记密码调用
|
/// 忘记密码调用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="user"></param>
|
/// <param name="user"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPut]
|
[HttpPut]
|
||||||
public bool Put([FromBody]User user)
|
public bool Put([FromBody]ResetUser user) => UserHelper.ForgotPassword(user);
|
||||||
{
|
|
||||||
return UserHelper.ForgotPassword(user.UserName, user.DisplayName, user.Description);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,9 @@ namespace Bootstrap.Admin.Controllers.Api
|
||||||
case "group":
|
case "group":
|
||||||
ret = UserHelper.RetrievesByGroupId(id);
|
ret = UserHelper.RetrievesByGroupId(id);
|
||||||
break;
|
break;
|
||||||
|
case "reset":
|
||||||
|
ret = UserHelper.RetrieveResetReasonsByUserName(id).Select(u => new { u.Key, u.Value });
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,8 @@ namespace Bootstrap.Admin.Query
|
||||||
u.RegisterTime,
|
u.RegisterTime,
|
||||||
u.ApprovedTime,
|
u.ApprovedTime,
|
||||||
u.ApprovedBy,
|
u.ApprovedBy,
|
||||||
u.Description
|
u.Description,
|
||||||
|
u.IsReset
|
||||||
});
|
});
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,7 +162,7 @@
|
||||||
<span class="fa fa-user-plus"></span>
|
<span class="fa fa-user-plus"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" id="f_userName" autocomplete="off" class="form-control" placeholder="登陆账号不可为空" minlength="4" maxlength="50" remote="api/Register" data-remote-msg="此用户已存在" data-valid="true" />
|
<input type="text" id="f_userName" autocomplete="off" class="form-control" placeholder="登陆账号不可为空" minlength="4" maxlength="50" data-valid="true" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -178,7 +178,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="f_desc">申请理由:</label>
|
<label for="f_desc">申请理由:</label>
|
||||||
<textarea id="f_desc" class="form-control" placeholder="申请理由,500字以内" rows="3" maxlength="500" data-valid="true"></textarea>
|
<textarea id="f_desc" class="form-control" placeholder="申请理由,500字以内" rows="3" maxlength="500" data-valid="true">我是用户XXX,我的手机号是XXXXXX,由于密码忘记,请将密码重置为123,登录后我自行更改,谢谢管理员</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|
|
@ -71,4 +71,42 @@
|
||||||
@section customModal {
|
@section customModal {
|
||||||
@await Html.PartialAsync("RoleConfig")
|
@await Html.PartialAsync("RoleConfig")
|
||||||
@await Html.PartialAsync("GroupConfig")
|
@await Html.PartialAsync("GroupConfig")
|
||||||
|
<div class="modal fade" id="dialogReset" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="myResetModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
|
||||||
|
<div class="modal-content" data-toggle="LgbValidate" data-valid-button="#btnReset" data-valid-modal="#dialogReset">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="myResetModalLabel">重置密码窗口</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form class="form-inline">
|
||||||
|
<div class="form-row" id="resetForm">
|
||||||
|
<div class="form-group col-sm-6">
|
||||||
|
<label class="control-label" for="password">登录密码</label>
|
||||||
|
<input type="password" class="form-control" id="resetPassword" placeholder="不可为空,50字以内" maxlength="50" data-valid="true" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-sm-6">
|
||||||
|
<label class="control-label" for="confirm">确认密码</label>
|
||||||
|
<input type="password" class="form-control" id="resetConfirm" placeholder="与登陆密码一致,50字以内" maxlength="50" equalTo="#resetPassword" data-valid="true" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-sm-12">
|
||||||
|
<label class="control-label" for="resetReason">重置原因</label>
|
||||||
|
<textarea class="form-control flex-sm-fill" id="resetReason" rows="3" readonly="readonly"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||||
|
<i class="fa fa-times"></i>
|
||||||
|
<span>关闭</span>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-primary" id="btnReset">
|
||||||
|
<i class="fa fa-save"></i>
|
||||||
|
<span>保存</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
|
@ -34,8 +34,8 @@
|
||||||
<script src="~/lib/toastr.js/toastr.min.js"></script>
|
<script src="~/lib/toastr.js/toastr.min.js"></script>
|
||||||
<script src="~/lib/dcjqaccordion/js/jquery.cookie.js"></script>
|
<script src="~/lib/dcjqaccordion/js/jquery.cookie.js"></script>
|
||||||
<script src="~/js/common-scripts.js" asp-append-version="true"></script>
|
<script src="~/js/common-scripts.js" asp-append-version="true"></script>
|
||||||
<script src="~/js/log.js" asp-append-version="true"></script>
|
|
||||||
@RenderSection("javascript", false)
|
@RenderSection("javascript", false)
|
||||||
|
<script src="~/js/log.js" asp-append-version="true"></script>
|
||||||
}
|
}
|
||||||
@await Html.PartialAsync("navigator")
|
@await Html.PartialAsync("navigator")
|
||||||
<section id="main-content" class="main-content">
|
<section id="main-content" class="main-content">
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
},
|
},
|
||||||
'#btnSubmitMenu': function () {
|
'#btnSubmitMenu': function () {
|
||||||
this.log({ crud: '分配菜单' });
|
this.log({ crud: '分配菜单' });
|
||||||
|
},
|
||||||
|
'#btnReset': function () {
|
||||||
|
this.log({ crud: '重置密码' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
$('#btnForgot').on('click', function () {
|
$('#btnForgot').on('click', function () {
|
||||||
$.bc({
|
$.bc({
|
||||||
url: "api/Register",
|
url: "api/Register",
|
||||||
data: { UserName: $('#f_userName').val(), DisplayName: $('#f_displayName').val(), Description: $('#f_desc').val() },
|
data: { UserName: $('#f_userName').val(), DisplayName: $('#f_displayName').val(), Reason: $('#f_desc').val() },
|
||||||
modal: '#dialogForgot',
|
modal: '#dialogForgot',
|
||||||
method: "put",
|
method: "put",
|
||||||
callback: function (result) {
|
callback: function (result) {
|
||||||
|
|
|
@ -5,8 +5,12 @@
|
||||||
var $dialogGroup = $("#dialogGroup");
|
var $dialogGroup = $("#dialogGroup");
|
||||||
var $dialogGroupHeader = $('#myGroupModalLabel');
|
var $dialogGroupHeader = $('#myGroupModalLabel');
|
||||||
var $dialogGroupForm = $('#groupForm');
|
var $dialogGroupForm = $('#groupForm');
|
||||||
|
var $dialogReset = $('#dialogReset');
|
||||||
|
var $dialogResetHeader = $('#myResetModalLabel');
|
||||||
|
var $resetReason = $('#resetReason');
|
||||||
|
var $table = $('table');
|
||||||
|
|
||||||
$('table').lgbTable({
|
$table.lgbTable({
|
||||||
url: User.url,
|
url: User.url,
|
||||||
dataBinder: {
|
dataBinder: {
|
||||||
map: {
|
map: {
|
||||||
|
@ -62,6 +66,9 @@
|
||||||
return $(element).val();
|
return $(element).val();
|
||||||
}).toArray();
|
}).toArray();
|
||||||
$.bc({ id: userId, url: Group.url, method: 'put', data: groupIds, query: { type: "user" }, title: Group.title, modal: '#dialogGroup' });
|
$.bc({ id: userId, url: Group.url, method: 'put', data: groupIds, query: { type: "user" }, title: Group.title, modal: '#dialogGroup' });
|
||||||
|
},
|
||||||
|
'#btnReset': function (row) {
|
||||||
|
$.bc({ id: row.UserName, url: 'api/Register', method: 'put', data: { password: $('#resetPassword').val() }, modal: "#dialogReset", title: "重置密码", callback: function (result) { if (result) $table.bootstrapTable('refresh'); } });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
callback: function (data) {
|
callback: function (data) {
|
||||||
|
@ -86,7 +93,30 @@
|
||||||
{ title: "注册时间", field: "RegisterTime", sortable: true },
|
{ title: "注册时间", field: "RegisterTime", sortable: true },
|
||||||
{ title: "授权时间", field: "ApprovedTime", sortable: true },
|
{ title: "授权时间", field: "ApprovedTime", sortable: true },
|
||||||
{ title: "授权人", field: "ApprovedBy", sortable: true },
|
{ title: "授权人", field: "ApprovedBy", sortable: true },
|
||||||
{ title: "说明", field: "Description", sortable: false }
|
{ title: "说明", field: "Description", sortable: false },
|
||||||
|
{
|
||||||
|
title: "操作", field: "IsReset", formatter: function (value, row, index) {
|
||||||
|
return value === 1 ? '<button class="reset btn btn-danger"><i class="fa fa-remove"></i><span>重置</span></button>' : '';
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
'click .reset': function (e, value, row, index) {
|
||||||
|
$table.bootstrapTable('uncheckAll');
|
||||||
|
$table.bootstrapTable('check', index);
|
||||||
|
$dialogResetHeader.text($.format("{0} - 重置密码窗口", row.UserName));
|
||||||
|
$.bc({
|
||||||
|
id: row.UserName, url: User.url, method: 'post', query: { type: "reset" }, callback: function (result) {
|
||||||
|
if ($.isArray(result)) {
|
||||||
|
var reason = result.map(function (v, index) {
|
||||||
|
return $.format("{0}: {1}", v.Key, v.Value);
|
||||||
|
}).join('\n');
|
||||||
|
$resetReason.text(reason);
|
||||||
|
$dialogReset.modal('show');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -127,6 +127,17 @@ namespace Bootstrap.DataAccess.MongoDB
|
||||||
return DBAccess.GetCollection<DataAccess.LoginUser>("LoginLogs");
|
return DBAccess.GetCollection<DataAccess.LoginUser>("LoginLogs");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public static IMongoCollection<DataAccess.ResetUser> ResetUsers
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return DBAccess.GetCollection<DataAccess.ResetUser>("ResetUsers");
|
||||||
|
}
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private static void InitDb()
|
private static void InitDb()
|
||||||
|
@ -240,6 +251,15 @@ namespace Bootstrap.DataAccess.MongoDB
|
||||||
md.IdMemberMap.SetIgnoreIfDefault(true);
|
md.IdMemberMap.SetIgnoreIfDefault(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (!BsonClassMap.IsClassMapRegistered(typeof(DataAccess.ResetUser)))
|
||||||
|
{
|
||||||
|
BsonClassMap.RegisterClassMap<DataAccess.ResetUser>(md =>
|
||||||
|
{
|
||||||
|
md.AutoMap();
|
||||||
|
md.IdMemberMap.SetSerializer(new StringSerializer(BsonType.ObjectId));
|
||||||
|
md.IdMemberMap.SetIgnoreIfDefault(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Bootstrap.DataAccess.MongoDB
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class ResetUser : DataAccess.ResetUser
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override DataAccess.ResetUser RetrieveUserByUserName(string userName) => DbManager.ResetUsers.Find(user => user.UserName.ToLowerInvariant() == userName.ToLowerInvariant()).FirstOrDefault();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override IEnumerable<KeyValuePair<DateTime, string>> RetrieveResetReasonsByUserName(string userName) => DbManager.ResetUsers.Find(user => user.UserName.ToLowerInvariant() == userName.ToLowerInvariant()).ToList().OrderByDescending(user => user.ResetTime).Select(user => new KeyValuePair<DateTime, string>(user.ResetTime, user.Reason));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userName"></param>
|
||||||
|
public override void DeleteByUserName(string userName) => DbManager.ResetUsers.DeleteMany(User => User.UserName.ToLowerInvariant() == userName.ToLowerInvariant());
|
||||||
|
}
|
||||||
|
}
|
|
@ -85,7 +85,8 @@ namespace Bootstrap.DataAccess.MongoDB
|
||||||
.Include(u => u.ApprovedBy)
|
.Include(u => u.ApprovedBy)
|
||||||
.Include(u => u.Description)
|
.Include(u => u.Description)
|
||||||
.Include(u => u.Groups)
|
.Include(u => u.Groups)
|
||||||
.Include(u => u.Roles);
|
.Include(u => u.Roles)
|
||||||
|
.Include(u => u.IsReset);
|
||||||
return DbManager.Users.Find(user => user.ApprovedTime != DateTime.MinValue).Project<User>(project).ToList();
|
return DbManager.Users.Find(user => user.ApprovedTime != DateTime.MinValue).Project<User>(project).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,8 +113,9 @@ namespace Bootstrap.DataAccess.MongoDB
|
||||||
ApprovedBy = user.ApprovedBy,
|
ApprovedBy = user.ApprovedBy,
|
||||||
Roles = new List<string>(),
|
Roles = new List<string>(),
|
||||||
Groups = new List<string>(),
|
Groups = new List<string>(),
|
||||||
Icon = $"{DictHelper.RetrieveIconFolderPath()}default.jpg",
|
Icon = "default.jpg",
|
||||||
Description = user.Description
|
Description = user.Description,
|
||||||
|
IsReset = 0
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -251,5 +253,37 @@ namespace Bootstrap.DataAccess.MongoDB
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override bool ForgotPassword(DataAccess.ResetUser user)
|
||||||
|
{
|
||||||
|
DbManager.Users.UpdateOne(md => md.UserName.ToLowerInvariant() == user.UserName.ToLowerInvariant(), Builders<User>.Update.Set(md => md.IsReset, 1));
|
||||||
|
user.ResetTime = DateTime.Now;
|
||||||
|
DbManager.ResetUsers.InsertOne(user);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userName"></param>
|
||||||
|
/// <param name="password"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override bool ResetPassword(string userName, string password)
|
||||||
|
{
|
||||||
|
var ret = false;
|
||||||
|
var resetUser = UserHelper.RetrieveResetUserByUserName(userName);
|
||||||
|
if (resetUser == null) return ret;
|
||||||
|
|
||||||
|
var passSalt = LgbCryptography.GenerateSalt();
|
||||||
|
var newPassword = LgbCryptography.ComputeHash(password, passSalt);
|
||||||
|
DbManager.Users.UpdateOne(User => User.UserName.ToLowerInvariant() == userName.ToLowerInvariant(), Builders<User>.Update.Set(md => md.Password, newPassword).Set(md => md.PassSalt, passSalt).Set(md => md.IsReset, 0));
|
||||||
|
DbManager.ResetUsers.DeleteMany(user => user.UserName.ToLowerInvariant() == userName.ToLowerInvariant());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,14 +128,15 @@ namespace Bootstrap.DataAccess
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userName"></param>
|
/// <param name="userName"></param>
|
||||||
/// <param name="displayName"></param>
|
/// <param name="password"></param>
|
||||||
/// <param name="desc"></param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static bool ForgotPassword(string userName, string displayName, string desc)
|
public static bool ResetPassword(string userName, string password) => DbContextManager.Create<User>().ResetPassword(userName, password);
|
||||||
{
|
|
||||||
// UNDONE 忘记密码涉及到安全问题,防止用户恶意重置其他用户,待定
|
/// <summary>
|
||||||
return true;
|
///
|
||||||
}
|
/// </summary>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
public static bool ForgotPassword(ResetUser user) => DbContextManager.Create<User>().ForgotPassword(user);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
@ -236,5 +237,19 @@ namespace Bootstrap.DataAccess
|
||||||
/// <param name="userName"></param>
|
/// <param name="userName"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static BootstrapUser RetrieveUserByUserName(string userName) => CacheManager.GetOrAdd(string.Format("{0}-{1}", RetrieveUsersByNameDataKey, userName), k => DbContextManager.Create<User>().RetrieveUserByUserName(userName), RetrieveUsersByNameDataKey);
|
public static BootstrapUser RetrieveUserByUserName(string userName) => CacheManager.GetOrAdd(string.Format("{0}-{1}", RetrieveUsersByNameDataKey, userName), k => DbContextManager.Create<User>().RetrieveUserByUserName(userName), RetrieveUsersByNameDataKey);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过登录账号获得用户信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static ResetUser RetrieveResetUserByUserName(string userName) => DbContextManager.Create<ResetUser>().RetrieveUserByUserName(userName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过登录账户获得重置密码原因
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<KeyValuePair<DateTime, string>> RetrieveResetReasonsByUserName(string userName) => DbContextManager.Create<ResetUser>().RetrieveResetReasonsByUserName(userName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
using PetaPoco;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Bootstrap.DataAccess
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[TableName("ResetUsers")]
|
||||||
|
public class ResetUser
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 用户主键ID
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string UserName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string DisplayName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string Reason { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public DateTime ResetTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual bool Save()
|
||||||
|
{
|
||||||
|
DbManager.Create().Save(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual ResetUser RetrieveUserByUserName(string userName) => DbManager.Create().FirstOrDefault<ResetUser>("where UserName = @0 order by ResetTime desc", userName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual void DeleteByUserName(string userName) => DbManager.Create().Delete<ResetUser>("where UserName = @0", userName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual IEnumerable<KeyValuePair<DateTime, string>> RetrieveResetReasonsByUserName(string userName) => DbManager.Create().Fetch<ResetUser>("where UserName = @0 order by ResetTime desc", userName).Select(user => new KeyValuePair<DateTime, string>(user.ResetTime, user.Reason));
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
using Bootstrap.Security.DataAccess;
|
using Bootstrap.Security.DataAccess;
|
||||||
using Longbow.Data;
|
using Longbow.Data;
|
||||||
using Longbow.Security.Cryptography;
|
using Longbow.Security.Cryptography;
|
||||||
|
using PetaPoco;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -68,6 +69,12 @@ namespace Bootstrap.DataAccess
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string NewPassword { get; set; }
|
public string NewPassword { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 是否重置密码
|
||||||
|
/// </summary>
|
||||||
|
[Ignore]
|
||||||
|
public int IsReset { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证用户登陆账号与密码正确
|
/// 验证用户登陆账号与密码正确
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -114,7 +121,7 @@ namespace Bootstrap.DataAccess
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual IEnumerable<User> Retrieves() => DbManager.Create().Fetch<User>("select ID, UserName, DisplayName, RegisterTime, ApprovedTime, ApprovedBy, Description from Users Where ApprovedTime is not null");
|
public virtual IEnumerable<User> Retrieves() => DbManager.Create().Fetch<User>("select u.ID, u.UserName, u.DisplayName, RegisterTime, ApprovedTime, ApprovedBy, Description, ru.IsReset from Users u left join (select 1 as IsReset, UserName from ResetUsers group by UserName) ru on u.UserName = ru.UserName Where ApprovedTime is not null");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询所有的新注册用户
|
/// 查询所有的新注册用户
|
||||||
|
@ -149,6 +156,48 @@ namespace Bootstrap.DataAccess
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userName"></param>
|
||||||
|
/// <param name="password"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual bool ResetPassword(string userName, string password)
|
||||||
|
{
|
||||||
|
var ret = false;
|
||||||
|
var resetUser = UserHelper.RetrieveResetUserByUserName(userName);
|
||||||
|
if (resetUser == null) return ret;
|
||||||
|
|
||||||
|
string sql = "set Password = @0, PassSalt = @1 where UserName = @2";
|
||||||
|
var passSalt = LgbCryptography.GenerateSalt();
|
||||||
|
var newPassword = LgbCryptography.ComputeHash(password, passSalt);
|
||||||
|
var db = DbManager.Create();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
db.BeginTransaction();
|
||||||
|
ret = db.Update<User>(sql, newPassword, passSalt, userName) == 1;
|
||||||
|
if (ret) db.Execute("delete from ResetUsers where UserName = @0", userName);
|
||||||
|
db.CompleteTransaction();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
db.AbortTransaction();
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual bool ForgotPassword(ResetUser user)
|
||||||
|
{
|
||||||
|
user.ResetTime = DateTime.Now;
|
||||||
|
return user.Save();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 新建前台User View调用/注册用户调用
|
/// 新建前台User View调用/注册用户调用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -507,3 +507,30 @@ GO
|
||||||
|
|
||||||
SET ANSI_PADDING OFF
|
SET ANSI_PADDING OFF
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
/****** Object: Table [dbo].[ResetUsers] Script Date: 03/05/2019 12:28:32 ******/
|
||||||
|
SET ANSI_NULLS ON
|
||||||
|
GO
|
||||||
|
|
||||||
|
SET QUOTED_IDENTIFIER ON
|
||||||
|
GO
|
||||||
|
|
||||||
|
SET ANSI_PADDING ON
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE TABLE [dbo].[ResetUsers](
|
||||||
|
[Id] [int] IDENTITY(1,1) NOT NULL,
|
||||||
|
[UserName] [varchar](50) NOT NULL,
|
||||||
|
[DisplayName] [nvarchar](50) NOT NULL,
|
||||||
|
[Reason] [nvarchar](500) NOT NULL,
|
||||||
|
[ResetTime] [datetime] NOT NULL,
|
||||||
|
CONSTRAINT [PK_ResetUsers] 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
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"Icon": "default.jpg",
|
"Icon": "default.jpg",
|
||||||
"Css": null,
|
"Css": null,
|
||||||
"App": null,
|
"App": null,
|
||||||
|
"IsReset": 0,
|
||||||
"Roles": [
|
"Roles": [
|
||||||
"5bd7cc105fa31256f77e4eb7"
|
"5bd7cc105fa31256f77e4eb7"
|
||||||
],
|
],
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
"Icon": "default.jpg",
|
"Icon": "default.jpg",
|
||||||
"Css": null,
|
"Css": null,
|
||||||
"App": null,
|
"App": null,
|
||||||
|
"IsReset": 0,
|
||||||
"Groups": [
|
"Groups": [
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
|
@ -158,3 +158,11 @@ CREATE TABLE LoginLogs(
|
||||||
City VARCHAR (50) NULL,
|
City VARCHAR (50) NULL,
|
||||||
Result VARCHAR (50) NOT NULL
|
Result VARCHAR (50) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE ResetUsers(
|
||||||
|
ID INTEGER PRIMARY KEY Auto_increment,
|
||||||
|
UserName VARCHAR (50) NOT NULL,
|
||||||
|
DisplayName VARCHAR (50) NOT NULL,
|
||||||
|
Reason VARCHAR (500) NOT NULL,
|
||||||
|
ResetTime DATETIME NOT NULL
|
||||||
|
);
|
|
@ -158,3 +158,11 @@ CREATE TABLE RejectUsers(
|
||||||
City VARCHAR (50) NULL,
|
City VARCHAR (50) NULL,
|
||||||
Result VARCHAR (50) NOT NULL
|
Result VARCHAR (50) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE ResetUsers(
|
||||||
|
ID SERIAL PRIMARY KEY,
|
||||||
|
UserName VARCHAR (50) NOT NULL,
|
||||||
|
DisplayName VARCHAR (50) NOT NULL,
|
||||||
|
Reason VARCHAR (500) NOT NULL,
|
||||||
|
ResetTime DATE NOT NULL
|
||||||
|
);
|
||||||
|
|
|
@ -158,3 +158,11 @@ CREATE TABLE LoginLogs(
|
||||||
[City] VARCHAR (50) NULL,
|
[City] VARCHAR (50) NULL,
|
||||||
[Result] VARCHAR (50) NOT NULL
|
[Result] VARCHAR (50) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE ResetUsers(
|
||||||
|
[ID] INTEGER PRIMARY KEY,
|
||||||
|
[UserName] VARCHAR (50) NOT NULL COLLATE NOCASE,
|
||||||
|
[DisplayName] VARCHAR (50) NOT NULL,
|
||||||
|
[Reason] VARCHAR (500) NOT NULL,
|
||||||
|
[ResetTime] DATETIME NOT NULL
|
||||||
|
);
|
|
@ -76,10 +76,15 @@ namespace Bootstrap.Admin
|
||||||
public HttpClient CreateClient(string baseAddress)
|
public HttpClient CreateClient(string baseAddress)
|
||||||
{
|
{
|
||||||
var client = CreateDefaultClient(new Uri($"http://localhost/{baseAddress}/"), new RedirectHandler(7), new CookieContainerHandler(_cookie));
|
var client = CreateDefaultClient(new Uri($"http://localhost/{baseAddress}/"), new RedirectHandler(7), new CookieContainerHandler(_cookie));
|
||||||
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.1 Safari/605.1.15");
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void ConfigureClient(HttpClient client)
|
||||||
|
{
|
||||||
|
base.ConfigureClient(client);
|
||||||
|
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.1 Safari/605.1.15");
|
||||||
|
}
|
||||||
|
|
||||||
private readonly CookieContainer _cookie = new CookieContainer();
|
private readonly CookieContainer _cookie = new CookieContainer();
|
||||||
|
|
||||||
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||||
|
|
|
@ -25,5 +25,26 @@ namespace Bootstrap.Admin.Api
|
||||||
|
|
||||||
nusr.Delete(nusr.RetrieveNewUsers().Where(u => u.UserName == nusr.UserName).Select(u => u.Id));
|
nusr.Delete(nusr.RetrieveNewUsers().Where(u => u.UserName == nusr.UserName).Select(u => u.Id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void Put_Ok()
|
||||||
|
{
|
||||||
|
var user = new ResetUser() { DisplayName = "UnitTest", UserName = "UnitTest", Reason = "UnitTest" };
|
||||||
|
var resp = await Client.PutAsJsonAsync<ResetUser, bool>(user);
|
||||||
|
Assert.True(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void Put_UserName()
|
||||||
|
{
|
||||||
|
var user = new User() { Password = "1" };
|
||||||
|
var resp = await Client.PutAsJsonAsync<User, bool>("UnitTest", user);
|
||||||
|
Assert.False(resp);
|
||||||
|
|
||||||
|
// 重置Admin密码
|
||||||
|
await Client.PutAsJsonAsync<ResetUser, bool>(new ResetUser { UserName = "Admin", DisplayName = "Administrator", Reason = "UnitTest" });
|
||||||
|
resp = await Client.PutAsJsonAsync<User, bool>("Admin", new User() { Password = "123789" });
|
||||||
|
Assert.True(resp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,9 @@ namespace Bootstrap.Admin.Api
|
||||||
var gid = new Group().Retrieves().Where(r => r.GroupName == "Admin").First().Id;
|
var gid = new Group().Retrieves().Where(r => r.GroupName == "Admin").First().Id;
|
||||||
ret = await Client.PostAsJsonAsync<string, IEnumerable<object>>($"{gid}?type=group", string.Empty);
|
ret = await Client.PostAsJsonAsync<string, IEnumerable<object>>($"{gid}?type=group", string.Empty);
|
||||||
Assert.NotNull(ret);
|
Assert.NotNull(ret);
|
||||||
|
|
||||||
|
ret = await Client.PostAsJsonAsync<string, IEnumerable<object>>("UnitTest?type=reset", string.Empty);
|
||||||
|
Assert.NotNull(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
using System;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Bootstrap.DataAccess
|
||||||
|
{
|
||||||
|
[Collection("SQLServerContext")]
|
||||||
|
public class ResetUserTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Save_Ok()
|
||||||
|
{
|
||||||
|
var resetUser = new ResetUser()
|
||||||
|
{
|
||||||
|
UserName = "UnitTest",
|
||||||
|
Reason = "UnitTest",
|
||||||
|
DisplayName = "UnitTest",
|
||||||
|
ResetTime = DateTime.Now
|
||||||
|
};
|
||||||
|
var db = DbManager.Create();
|
||||||
|
db.Save(resetUser);
|
||||||
|
var count = db.ExecuteScalar<int>("select count(Id) from ResetUsers");
|
||||||
|
Assert.True(count > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RetrieveUserByUserName_Ok()
|
||||||
|
{
|
||||||
|
var resetUser = new ResetUser()
|
||||||
|
{
|
||||||
|
UserName = "UnitTest",
|
||||||
|
Reason = "UnitTest",
|
||||||
|
DisplayName = "UnitTest",
|
||||||
|
ResetTime = DateTime.Now
|
||||||
|
};
|
||||||
|
var db = DbManager.Create();
|
||||||
|
db.Save(resetUser);
|
||||||
|
|
||||||
|
var user = resetUser.RetrieveUserByUserName(resetUser.UserName);
|
||||||
|
Assert.Equal("UnitTest", user.UserName);
|
||||||
|
Assert.Equal("UnitTest", user.DisplayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DeleteByUserName_Ok()
|
||||||
|
{
|
||||||
|
var resetUser = new ResetUser()
|
||||||
|
{
|
||||||
|
UserName = "UnitTest",
|
||||||
|
Reason = "UnitTest",
|
||||||
|
DisplayName = "UnitTest",
|
||||||
|
ResetTime = DateTime.Now
|
||||||
|
};
|
||||||
|
var db = DbManager.Create();
|
||||||
|
db.Save(resetUser);
|
||||||
|
|
||||||
|
resetUser.DeleteByUserName(resetUser.UserName);
|
||||||
|
var count = db.ExecuteScalar<int>("select count(Id) from ResetUsers");
|
||||||
|
Assert.Equal(0, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RetrieveResetReasonsByUserName_Ok()
|
||||||
|
{
|
||||||
|
var resetUser = new ResetUser()
|
||||||
|
{
|
||||||
|
UserName = "UnitTest",
|
||||||
|
Reason = "UnitTest",
|
||||||
|
DisplayName = "UnitTest",
|
||||||
|
ResetTime = DateTime.Now
|
||||||
|
};
|
||||||
|
var db = DbManager.Create();
|
||||||
|
db.Save(resetUser);
|
||||||
|
|
||||||
|
var reasons = resetUser.RetrieveResetReasonsByUserName(resetUser.UserName);
|
||||||
|
Assert.NotEmpty(reasons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Loading…
Reference in New Issue