using System.Text; using NPin.Framework.Core.Crypt.BCrypt; using NPin.Framework.SqlSugarCore.Abstractions.Data; using NPin.Framework.Upms.Domain.Entities.ValueObjects; using NPin.Framework.Upms.Domain.Shared.Enums; using SqlSugar; using Volo.Abp.Auditing; using Volo.Abp.Domain.Entities; namespace NPin.Framework.Upms.Domain.Entities; [SugarTable("SysUser", "用户表")] [SugarIndex($"index_{nameof(Username)}", nameof(Username), OrderByType.Asc)] public class UserEntity : Entity, ISoftDelete, IAuditedObject, IEnabled, IOrderNum { #region User [SugarColumn(IsPrimaryKey = true)] public override Guid Id { get; protected set; } [SugarColumn(ColumnDescription = "用户名")] public string Username { get; set; } = string.Empty; [SugarColumn(ColumnDescription = "手机号码")] public string PhoneNumber { get; set; } [SugarColumn(ColumnDescription = "邮箱")] public string? Email { get; set; } [SugarColumn(ColumnDescription = "昵称")] public string? Nickname { get; set; } [SugarColumn(IsOwnsOne = true)] public EncryptPasswordValueObject EncryptPassword { get; set; } = new(); [SugarColumn(ColumnDescription = "简介")] public string? Introduction { get; set; } [SugarColumn(ColumnDescription = "性别")] public GenderEnum Gender { get; set; } = GenderEnum.Secrecy; [SugarColumn(ColumnDescription = "注册IP地址")] public string? IpAddr { get; set; } [SugarColumn(ColumnDescription = "头像")] public string? Avatar { get; set; } #endregion #region Implements /// /// 逻辑删除 /// public bool IsDeleted { get; set; } public DateTime CreationTime { get; set; } = DateTime.Now; public Guid? CreatorId { get; set; } public DateTime? LastModificationTime { get; set; } public Guid? LastModifierId { get; set; } /// /// 是否启用 /// public bool IsEnabled { get; set; } public int OrderNum { get; set; } #endregion #region 关联关系(导航) /// /// 用户元数据,保存可扩展数据 /// 这里不使用Json的原因是有些库不是很好支持 /// [Navigate(NavigateType.OneToMany, nameof(UserMetaEntity.UserId))] public List Metadata { get; set; } /// /// 角色列表,多对多 /// [Navigate(typeof(UserRoleEntity), nameof(UserRoleEntity.UserId), nameof(UserRoleEntity.RoleId))] public List Roles { get; set; } /// /// 岗位列表,多对多 /// [Navigate(typeof(UserPostEntity), nameof(UserPostEntity.UserId), nameof(UserPostEntity.PostId))] public List Posts { get; set; } /// /// 所在的组织机构列表,多对多 /// [Navigate(typeof(UserOrganizationEntity), nameof(UserOrganizationEntity.UserId), nameof(UserOrganizationEntity.OrganizationId))] public List Organizations { get; set; } #endregion public UserEntity() { } public UserEntity(string username, string phoneNumber, string password, string? nickname) { Username = username; PhoneNumber = phoneNumber; if (username.IsNullOrEmpty()) { username = $"用户{phoneNumber}"; } Nickname = nickname.IsNullOrWhiteSpace() ? username : nickname; EncryptPassword.Password = password; BuildPassword(); } /// /// 通过随机盐值给密码加密,使用BCrypt算法 /// /// public UserEntity BuildPassword(string? password = null) { // 若传入密码无值,则使用原本Password // 若原本Password依然无值,则抛出参数异常 password ??= EncryptPassword.Password ?? throw new ArgumentNullException(nameof(EncryptPassword.Password)); EncryptPassword.Salt = BCrypt.GenerateSalt(); EncryptPassword.Password = BCrypt.GenerateStr(password, EncryptPassword.Salt, 10); return this; } /// /// 检查密码是否一致 /// /// /// /// public bool CheckPassword(string password) { if (EncryptPassword.Salt is null) { throw new ArgumentNullException(nameof(EncryptPassword.Salt)); } return BCrypt.Check(EncryptPassword.Password, password, EncryptPassword.Salt, 10); } }