feat: 增加用户登录名称验证

This commit is contained in:
Argo-Tianyi 2022-01-05 08:26:40 +08:00
parent e0fd45f15a
commit f8870109c3
8 changed files with 140 additions and 15 deletions

View File

@ -11,6 +11,10 @@ namespace BootstrapAdmin.DataAccess.Models
/// 获得/设置 系统登录用户名
/// </summary>
[Display(Name = "登录名称")]
[Required(ErrorMessage = "{0}不可为空")]
[RegularExpression("^[a-zA-Z0-9_@.]*$", ErrorMessage = "")]
[MaxLength(16, ErrorMessage = "{0}不能超过 16 个字符")]
[NotNull]
public string? UserName { get; set; }
/// <summary>
@ -18,7 +22,8 @@ namespace BootstrapAdmin.DataAccess.Models
/// </summary>
[Display(Name = "显示名称")]
[Required(ErrorMessage = "{0}不可为空")]
[MaxLength(50, ErrorMessage = "{0}不能超过 50 个字符")]
[MaxLength(20, ErrorMessage = "{0}不能超过 20 个字符")]
[NotNull]
public string? DisplayName { get; set; }
/// <summary>
@ -49,6 +54,8 @@ namespace BootstrapAdmin.DataAccess.Models
/// </summary>
[Display(Name = "密码")]
[Required(ErrorMessage = "{0}不可为空")]
[MaxLength(16, ErrorMessage = "{0}不能超过 16 个字符")]
[NotNull]
public string? Password { get; set; }
/// <summary>
@ -78,6 +85,7 @@ namespace BootstrapAdmin.DataAccess.Models
/// 获得/设置 用户的申请理由
/// </summary>
[Display(Name = "说明")]
[NotNull]
public string? Description { get; set; }
/// <summary>
@ -90,6 +98,7 @@ namespace BootstrapAdmin.DataAccess.Models
/// </summary>
[Display(Name = "新密码")]
[Required(ErrorMessage = "{0}不可为空")]
[MaxLength(16, ErrorMessage = "{0}不能超过 16 个字符")]
[NotNull]
public string? NewPassword { get; set; }
@ -99,6 +108,7 @@ namespace BootstrapAdmin.DataAccess.Models
[Display(Name = "确认密码")]
[Required(ErrorMessage = "{0}不可为空")]
[Compare("NewPassword", ErrorMessage = "{0}与{1}不一致")]
[MaxLength(16, ErrorMessage = "{0}不能超过 16 个字符")]
[NotNull]
public string? ConfirmPassword { get; set; }

View File

@ -43,12 +43,14 @@ class BootstrapAdminConventionMapper : ConventionMapper
{
var ci = base.GetColumnInfo(pocoProperty);
var resultColumns = new List<string>
{
nameof(Models.User.Period),
nameof(Models.User.NewPassword),
nameof(Models.User.ConfirmPassword),
nameof(Models.User.IsReset)
};
{
nameof(Models.User.Password),
nameof(Models.User.PassSalt),
nameof(Models.User.NewPassword),
nameof(Models.User.ConfirmPassword),
nameof(Models.User.Period),
nameof(Models.User.IsReset)
};
ci.ResultColumn = resultColumns.Any(c => c == ci.ColumnName);
return ci;
}

View File

@ -2,7 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.DataAccess.PetaPoco.Extensions;
using BootstrapAdmin.Web.Core;
using BootstrapAdmin.Web.Extensions;
using BootstrapBlazor.Components;
using PetaPoco;
@ -17,10 +19,12 @@ class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class,
{
private IDatabase Database { get; }
private IUser UserService { get; }
/// <summary>
/// 构造函数
/// </summary>
public DefaultDataService(IDatabase db) => Database = db;
public DefaultDataService(IDatabase db, IUser userService) => (Database, UserService) = (db, userService);
/// <summary>
/// 删除方法
@ -43,13 +47,20 @@ class DefaultDataService<TModel> : DataServiceBase<TModel> where TModel : class,
/// <returns></returns>
public override async Task<bool> SaveAsync(TModel model, ItemChangedType changedType)
{
if (changedType == ItemChangedType.Add)
if (model is User user)
{
await Database.InsertAsync(model);
UserService.SaveUser(user.Id, user.UserName, user.DisplayName, user.NewPassword);
}
else
{
await Database.UpdateAsync(model);
if (changedType == ItemChangedType.Add)
{
await Database.InsertAsync(model);
}
else
{
await Database.UpdateAsync(model);
}
}
return true;
}

View File

@ -172,4 +172,19 @@ class UserService : BaseDatabase, IUser
}
return ret;
}
public bool SaveUser(string? id, string userName, string displayName, string password)
{
var salt = LgbCryptography.GenerateSalt();
var pwd = LgbCryptography.ComputeHash(password, salt);
if (string.IsNullOrEmpty(id))
{
Database.Execute("INSERT INTO Users (UserName, Password, PassSalt, DisplayName, RegisterTime, ApprovedTime, ApprovedBy, [Description]) values (@0, @1, @2, @3, @4, @4, 'system', '系统默认创建');", userName, pwd, salt, displayName, DateTime.Now);
}
else
{
Database.Update<User>("set Password = @1, PassSalt = @2, DisplayName = @3 where Id = @0", id, pwd, salt, displayName);
}
return true;
}
}

View File

@ -80,4 +80,14 @@ public interface IUser
/// <param name="roles"></param>
/// <returns></returns>
bool TryCreateUserByPhone(string phone, string code, string appId, ICollection<string> roles);
/// <summary>
///
/// </summary>
/// <param name="id"></param>
/// <param name="userName"></param>
/// <param name="displayName"></param>
/// <param name="password"></param>
/// <returns></returns>
bool SaveUser(string? id, string userName, string displayName, string password);
}

View File

@ -1,20 +1,39 @@
@page "/Admin/Users"
<AdminTable TItem="DataAccess.Models.User" ExtendButtonColumnWidth="270" SortList="SortList">
<Table TItem="DataAccess.Models.User" IsBordered="true" IsStriped="true" IsMultipleSelect="true"
ExtendButtonColumnWidth="270" SortList="SortList"
ShowToolbar="true" ShowExtendButtons="true" ShowSearch="true"
UseInjectDataService="true">
<TableToolbarTemplate>
<TableToolbarButton TItem="DataAccess.Models.User" IsEnableWhenSelectedOneRow="true" Color="Color.Warning" Icon="fa fa-bank" Text="分配部门" OnClickCallback="users => OnAssignmentGroups(users.First())" />
<TableToolbarButton TItem="DataAccess.Models.User" IsEnableWhenSelectedOneRow="true" Color="Color.Info" Icon="fa fa-sitemap" Text="分配角色" OnClickCallback="users => OnAssignmentRoles(users.First())" />
</TableToolbarTemplate>
<ColumnsTemplete>
<TableColumns>
<TableColumn @bind-Field="@context.UserName" Sortable="true" Filterable="true" Searchable="true"></TableColumn>
<TableColumn @bind-Field="@context.DisplayName" Sortable="true" Filterable="true" Searchable="true"></TableColumn>
<TableColumn @bind-Field="@context.RegisterTime" Sortable="true" Filterable="true"></TableColumn>
<TableColumn @bind-Field="@context.ApprovedTime" Sortable="true" Filterable="true"></TableColumn>
<TableColumn @bind-Field="@context.ApprovedBy" Sortable="true" Filterable="true"></TableColumn>
<TableColumn @bind-Field="@context.Description" Sortable="true" Filterable="true"></TableColumn>
</ColumnsTemplete>
</TableColumns>
<EditTemplate>
<div class="row g-3 form-inline">
<div class="col-12 col-sm-6">
<BootstrapInput @bind-Value="@context.UserName" IsDisabled="GetDisabled(context.Id)" ValidateRules="UserRules" placeholder="不可为空16字以内" maxlength="16" />
</div>
<div class="col-12 col-sm-6">
<BootstrapInput @bind-Value="@context.DisplayName" placeholder="不可为空20字以内" maxlength="20" />
</div>
<div class="col-12 col-sm-6">
<BootstrapInput @bind-Value="@context.NewPassword" placeholder="不可为空16字以内" maxlength="16" />
</div>
<div class="col-12 col-sm-6">
<BootstrapInput @bind-Value="@context.ConfirmPassword" placeholder="与登陆密码一致" ShowLabel="true" maxlength="16" />
</div>
</div>
</EditTemplate>
<RowButtonTemplate>
<TableCellButton Size="Size.ExtraSmall" Color="Color.Warning" Icon="fa fa-bank" Text="分配部门" OnClick="() => OnAssignmentGroups(context)" />
<TableCellButton Size="Size.ExtraSmall" Color="Color.Info" Icon="fa fa-sitemap" Text="分配角色" OnClick="() => OnAssignmentRoles(context)" />
</RowButtonTemplate>
</AdminTable>
</Table>

View File

@ -1,6 +1,7 @@
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using BootstrapAdmin.Web.Extensions;
using BootstrapAdmin.Web.Validators;
namespace BootstrapAdmin.Web.Pages.Admin;
@ -25,8 +26,25 @@ public partial class Users
[NotNull]
private IRole? RoleService { get; set; }
[Inject]
[NotNull]
private IUser? UserService { get; set; }
private List<string> SortList { get; } = new List<string> { "UserName" };
private static bool GetDisabled(string? id) => !string.IsNullOrEmpty(id);
private List<IValidator> UserRules { get; } = new List<IValidator>();
/// <summary>
/// OnInitialized 方法
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
UserRules.Add(new UserNameValidator(UserService));
}
private async Task OnAssignmentGroups(User user)
{
var groups = GroupService.GetAll().ToSelectedItemList();

View File

@ -0,0 +1,40 @@
using BootstrapAdmin.Web.Core;
using System.ComponentModel.DataAnnotations;
namespace BootstrapAdmin.Web.Validators;
public class UserNameValidator : IValidator
{
public string? ErrorMessage { get; set; }
private IUser UserService { get; }
/// <summary>
///
/// </summary>
/// <param name="userService"></param>
public UserNameValidator(IUser userService) => UserService = userService;
/// <summary>
///
/// </summary>
/// <param name="propertyValue"></param>
/// <param name="context"></param>
/// <param name="results"></param>
public void Validate(object? propertyValue, ValidationContext context, List<ValidationResult> results)
{
var displayName = UserService.GetDisplayName(propertyValue?.ToString());
if (!string.IsNullOrEmpty(displayName))
{
ErrorMessage = $"{context.DisplayName}已存在";
}
else
{
ErrorMessage = null;
}
if (!string.IsNullOrEmpty(ErrorMessage))
{
results.Add(new ValidationResult(ErrorMessage, new string[] { context.MemberName! }));
}
}
}