feat: 增加用户登录名称验证
This commit is contained in:
parent
e0fd45f15a
commit
f8870109c3
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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! }));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue