diff --git a/Source/Starfish.Service/Application/ApplicationServiceModule.cs b/Source/Starfish.Service/Application/ApplicationServiceModule.cs index 26e53bc..842d90a 100644 --- a/Source/Starfish.Service/Application/ApplicationServiceModule.cs +++ b/Source/Starfish.Service/Application/ApplicationServiceModule.cs @@ -49,6 +49,8 @@ public override void ConfigureServices(ServiceConfigurationContext context) ConfigureCachingServices(context.Services); ConfigureBusServices(context.Services); + + context.Services.AddHostedService(); } private void ConfigureCachingServices(IServiceCollection services) diff --git a/Source/Starfish.Service/Application/Commands/Identity/AdministratorAssignCommand.cs b/Source/Starfish.Service/Application/Commands/Identity/AdministratorAssignCommand.cs deleted file mode 100644 index 07d704a..0000000 --- a/Source/Starfish.Service/Application/Commands/Identity/AdministratorAssignCommand.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Nerosoft.Euonia.Domain; - -namespace Nerosoft.Starfish.Application; - -public class AdministratorAssignCommand : Command -{ - public string UserId { get; set; } - - public List Roles { get; set; } -} \ No newline at end of file diff --git a/Source/Starfish.Service/Application/Commands/Identity/AdministratorDeleteCommand.cs b/Source/Starfish.Service/Application/Commands/Identity/AdministratorDeleteCommand.cs deleted file mode 100644 index 2a30718..0000000 --- a/Source/Starfish.Service/Application/Commands/Identity/AdministratorDeleteCommand.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Nerosoft.Euonia.Domain; - -namespace Nerosoft.Starfish.Application; - -public class AdministratorDeleteCommand : Command -{ - public AdministratorDeleteCommand(string userId) - { - UserId = userId; - } - - public string UserId { get; set; } -} \ No newline at end of file diff --git a/Source/Starfish.Service/Application/Commands/Identity/UserCreateCommand.cs b/Source/Starfish.Service/Application/Commands/Identity/UserCreateCommand.cs index 4d20d3b..fc88a7e 100644 --- a/Source/Starfish.Service/Application/Commands/Identity/UserCreateCommand.cs +++ b/Source/Starfish.Service/Application/Commands/Identity/UserCreateCommand.cs @@ -6,14 +6,40 @@ namespace Nerosoft.Starfish.Application; /// /// 创建用户命令 /// -public sealed class UserCreateCommand : Command +public sealed class UserCreateCommand : Command { /// - /// 构造函数 + /// 用户名 /// - /// 用户创建数据传输对象 - public UserCreateCommand(UserCreateDto data) - : base(data) - { - } + public string UserName { get; set; } + + /// + /// 密码 + /// + public string Password { get; set; } + + /// + /// 邮箱 + /// + public string Email { get; set; } + + /// + /// 电话 + /// + public string Phone { get; set; } + + /// + /// 昵称 + /// + public string NickName { get; set; } + + /// + /// 是否是管理员 + /// + public bool IsAdmin { get; set; } = false; + + /// + /// 是否是预留账号 + /// + public bool Reserved { get; set; } = false; } \ No newline at end of file diff --git a/Source/Starfish.Service/Application/Contracts/IAdministratorApplicationService.cs b/Source/Starfish.Service/Application/Contracts/IAdministratorApplicationService.cs deleted file mode 100644 index f0fd3df..0000000 --- a/Source/Starfish.Service/Application/Contracts/IAdministratorApplicationService.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Nerosoft.Euonia.Application; -using Nerosoft.Starfish.Transit; - -namespace Nerosoft.Starfish.Application; - -public interface IAdministratorApplicationService : IApplicationService -{ - Task> QueryAsync(AdministratorCriteria criteria, int skip, int count, CancellationToken cancellationToken = default); - - Task CountAsync(AdministratorCriteria criteria, CancellationToken cancellationToken = default); - - Task AssignAsync(AdministratorAssignDto data, CancellationToken cancellationToken = default); - - Task DeleteAsync(string userId, CancellationToken cancellationToken = default); -} \ No newline at end of file diff --git a/Source/Starfish.Service/Application/Contracts/IUserApplicationService.cs b/Source/Starfish.Service/Application/Contracts/IUserApplicationService.cs index aeb787e..d366678 100644 --- a/Source/Starfish.Service/Application/Contracts/IUserApplicationService.cs +++ b/Source/Starfish.Service/Application/Contracts/IUserApplicationService.cs @@ -76,4 +76,11 @@ public interface IUserApplicationService : IApplicationService /// /// Task ResetPasswordAsync(string id, string password, CancellationToken cancellationToken = default); + + /// + /// 初始化用户 + /// + /// + /// + Task InitializeAsync(CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/Source/Starfish.Service/Application/Handlers/AdministratorCommandHandler.cs b/Source/Starfish.Service/Application/Handlers/AdministratorCommandHandler.cs deleted file mode 100644 index b390baa..0000000 --- a/Source/Starfish.Service/Application/Handlers/AdministratorCommandHandler.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Nerosoft.Euonia.Bus; -using Nerosoft.Euonia.Business; -using Nerosoft.Euonia.Repository; -using Nerosoft.Starfish.Domain; -using Nerosoft.Starfish.Service; - -namespace Nerosoft.Starfish.Application; - -public class AdministratorCommandHandler : CommandHandlerBase, - IHandler, - IHandler -{ - public AdministratorCommandHandler(IUnitOfWorkManager unitOfWork, IObjectFactory factory) - : base(unitOfWork, factory) - { - } - - public Task HandleAsync(AdministratorAssignCommand message, MessageContext context, CancellationToken cancellationToken = default) - { - return ExecuteAsync(async () => - { - var business = await Factory.FetchAsync(message.UserId, cancellationToken); - business.UserId = message.UserId; - business.SetRoles(message.Roles); - if (business.Aggregate == null) - { - business.MarkAsInsert(); - } - else - { - business.MarkAsUpdate(); - } - - _ = await business.SaveAsync(false, cancellationToken); - }); - } - - public Task HandleAsync(AdministratorDeleteCommand message, MessageContext context, CancellationToken cancellationToken = default) - { - return ExecuteAsync(async () => - { - var business = await Factory.FetchAsync(message.UserId, cancellationToken); - - business.MarkAsDelete(); - - _ = await business.SaveAsync(false, cancellationToken); - }); - } -} \ No newline at end of file diff --git a/Source/Starfish.Service/Application/Handlers/UserCommandHandler.cs b/Source/Starfish.Service/Application/Handlers/UserCommandHandler.cs index 7755a3b..9a35d2d 100644 --- a/Source/Starfish.Service/Application/Handlers/UserCommandHandler.cs +++ b/Source/Starfish.Service/Application/Handlers/UserCommandHandler.cs @@ -31,11 +31,13 @@ public Task HandleAsync(UserCreateCommand message, MessageContext context, Cance return ExecuteAsync(async () => { var business = await Factory.CreateAsync(cancellationToken); - business.UserName = message.Item1.UserName; - business.Password = message.Item1.Password; - business.NickName = message.Item1.NickName; - business.Email = message.Item1.Email; - business.Phone = message.Item1.Phone; + business.UserName = message.UserName; + business.Password = message.Password; + business.NickName = message.NickName; + business.Email = message.Email; + business.Phone = message.Phone; + business.IsAdmin = message.IsAdmin; + business.Reserved = message.Reserved; business.MarkAsInsert(); await business.SaveAsync(false, cancellationToken); @@ -52,7 +54,11 @@ public Task HandleAsync(UserUpdateCommand message, MessageContext context, Cance business.Email = message.Item2.Email; business.NickName = message.Item2.NickName; + business.Phone = message.Item2.Phone; + business.IsAdmin = message.Item2.IsAdmin; + business.MarkAsUpdate(); + await business.SaveAsync(true, cancellationToken); }); } diff --git a/Source/Starfish.Service/Application/Implements/AdministratorApplicationService.cs b/Source/Starfish.Service/Application/Implements/AdministratorApplicationService.cs deleted file mode 100644 index 44afdc4..0000000 --- a/Source/Starfish.Service/Application/Implements/AdministratorApplicationService.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Nerosoft.Euonia.Application; -using Nerosoft.Starfish.Transit; -using Nerosoft.Starfish.UseCases; - -namespace Nerosoft.Starfish.Application; - -internal class AdministratorApplicationService : BaseApplicationService, IAdministratorApplicationService -{ - public Task> QueryAsync(AdministratorCriteria criteria, int skip, int count, CancellationToken cancellationToken = default) - { - var input = new GenericQueryInput(criteria, skip, count); - var useCase = LazyServiceProvider.GetRequiredService(); - return useCase.ExecuteAsync(input, cancellationToken).ContinueWith(task => - { - task.WaitAndUnwrapException(cancellationToken); - return task.Result.Result; - }, cancellationToken); - } - - public Task CountAsync(AdministratorCriteria criteria, CancellationToken cancellationToken = default) - { - var input = new AdministratorCountInput(criteria); - var useCase = LazyServiceProvider.GetRequiredService(); - return useCase.ExecuteAsync(input, cancellationToken).ContinueWith(task => - { - task.WaitAndUnwrapException(cancellationToken); - return task.Result.Result; - }, cancellationToken); - } - - public Task AssignAsync(AdministratorAssignDto data, CancellationToken cancellationToken = default) - { - var input = new AdministratorAssignInput(data); - var useCase = LazyServiceProvider.GetRequiredService(); - return useCase.ExecuteAsync(input, cancellationToken) - .ContinueWith(task => task.WaitAndUnwrapException(cancellationToken), cancellationToken); - } - - public Task DeleteAsync(string userId, CancellationToken cancellationToken = default) - { - var input = new AdministratorDeleteInput(userId); - var useCase = LazyServiceProvider.GetRequiredService(); - return useCase.ExecuteAsync(input, cancellationToken) - .ContinueWith(task => task.WaitAndUnwrapException(cancellationToken), cancellationToken); - } -} \ No newline at end of file diff --git a/Source/Starfish.Service/Application/Implements/UserApplicationService.cs b/Source/Starfish.Service/Application/Implements/UserApplicationService.cs index 6ccf283..0f2afc7 100644 --- a/Source/Starfish.Service/Application/Implements/UserApplicationService.cs +++ b/Source/Starfish.Service/Application/Implements/UserApplicationService.cs @@ -72,4 +72,11 @@ public Task ResetPasswordAsync(string id, string password, CancellationToken can var input = new ResetPasswordInput(id, password); return useCase.ExecuteAsync(input, cancellationToken); } + + public Task InitializeAsync(CancellationToken cancellationToken = default) + { + var useCase = LazyServiceProvider.GetService(); + return useCase.ExecuteAsync(cancellationToken); + } + } \ No newline at end of file diff --git a/Source/Starfish.Service/Application/Mappings/IdentityMappingProfile.cs b/Source/Starfish.Service/Application/Mappings/IdentityMappingProfile.cs index e5a9b76..cc9fb35 100644 --- a/Source/Starfish.Service/Application/Mappings/IdentityMappingProfile.cs +++ b/Source/Starfish.Service/Application/Mappings/IdentityMappingProfile.cs @@ -27,9 +27,6 @@ public IdentityMappingProfile() .ForMember(dest => dest.NickName, options => options.MapFrom(src => src.User.NickName)) .ForMember(dest => dest.Email, options => options.MapFrom(src => src.User.Email)) .ForMember(dest => dest.Phone, options => options.MapFrom(src => src.User.Phone)); - - CreateMap(); - CreateMap(); } private static string Mask(string source) diff --git a/Source/Starfish.Service/Application/Services/UserInitializeService.cs b/Source/Starfish.Service/Application/Services/UserInitializeService.cs new file mode 100644 index 0000000..4fff946 --- /dev/null +++ b/Source/Starfish.Service/Application/Services/UserInitializeService.cs @@ -0,0 +1,28 @@ +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace Nerosoft.Starfish.Application; + +internal class UserInitializeService : BackgroundService +{ + private readonly IUserApplicationService _service; + private readonly ILogger _logger; + + public UserInitializeService(IUserApplicationService service, ILoggerFactory logger) + { + _service = service; + _logger = logger.CreateLogger(); + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + try + { + await _service.InitializeAsync(stoppingToken); + } + catch (Exception exception) + { + _logger.LogError(exception, exception.Message); + } + } +} diff --git a/Source/Starfish.Service/Domain/Aggregates/Administrator.cs b/Source/Starfish.Service/Domain/Aggregates/Administrator.cs deleted file mode 100644 index 8bcf181..0000000 --- a/Source/Starfish.Service/Domain/Aggregates/Administrator.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Nerosoft.Euonia.Domain; - -namespace Nerosoft.Starfish.Domain; - -public class Administrator : Aggregate -{ - public string UserId { get; set; } - - public User User { get; set; } - - public string Roles { get; set; } -} \ No newline at end of file diff --git a/Source/Starfish.Service/Domain/Aggregates/User.cs b/Source/Starfish.Service/Domain/Aggregates/User.cs index cac5abe..04141ab 100644 --- a/Source/Starfish.Service/Domain/Aggregates/User.cs +++ b/Source/Starfish.Service/Domain/Aggregates/User.cs @@ -16,7 +16,7 @@ public sealed class User : Aggregate, IHasCreateTime, IHasUpdateTime, IT private User() { } - + /// /// 初始化用户聚合根 /// @@ -77,6 +77,11 @@ private User(string userName, string passwordHash, string passwordSalt) /// 预留账号不允许删除、设置角色等 public bool Reserved { get; set; } + /// + /// 是否是管理员 + /// + public bool IsAdmin { get; set; } + /// /// 来源 /// @@ -155,6 +160,21 @@ internal void SetNickName(string nickName) NickName = nickName; } + internal void SetIsAdmin(bool isAdmin) + { + if (Reserved) + { + return; + } + + if (isAdmin == IsAdmin) + { + return; + } + + IsAdmin = isAdmin; + } + /// /// 增加授权失败次数 /// diff --git a/Source/Starfish.Service/Domain/Business/AdministratorGeneralBusiness.cs b/Source/Starfish.Service/Domain/Business/AdministratorGeneralBusiness.cs deleted file mode 100644 index 8b8909f..0000000 --- a/Source/Starfish.Service/Domain/Business/AdministratorGeneralBusiness.cs +++ /dev/null @@ -1,125 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Nerosoft.Euonia.Business; -using Nerosoft.Starfish.Service; - -// ReSharper disable MemberCanBePrivate.Global - -namespace Nerosoft.Starfish.Domain; - -internal sealed class AdministratorGeneralBusiness : EditableObjectBase -{ - [Inject] - public IUserRepository UserRepository { get; set; } - - [Inject] - public IAdministratorRepository AdministratorRepository { get; set; } - - public Administrator Aggregate { get; private set; } - - public static readonly PropertyInfo UserIdProperty = RegisterProperty(p => p.UserId); - - public string UserId - { - get => GetProperty(UserIdProperty); - set => SetProperty(UserIdProperty, value); - } - - public static readonly PropertyInfo> RolesProperty = RegisterProperty>(p => p.Roles, []); - - public HashSet Roles - { - get => GetProperty(RolesProperty); - set => SetProperty(RolesProperty, value); - } - - protected override void AddRules() - { - Rules.AddRule(new UserCheckRule()); - } - - public void SetRoles(IEnumerable roles) - { - if (Roles.SetEquals(roles)) - { - return; - } - - Roles.Clear(); - if (roles.Any()) - { - foreach (var role in roles) - { - Roles.Add(role); - } - } - - ChangedProperties.Add(RolesProperty); - } - - [FactoryFetch] - internal async Task FetchAsync(string userId, CancellationToken cancellationToken = default) - { - var aggregate = await AdministratorRepository.GetAsync(t => t.UserId == userId, query => query.AsTracking(), cancellationToken); - - if (aggregate != null) - { - using (BypassRuleChecks) - { - UserId = aggregate.UserId; - Roles = [..aggregate.Roles.Split(",")]; - } - - Aggregate = aggregate; - } - } - - [FactoryInsert] - protected override async Task InsertAsync(CancellationToken cancellationToken = default) - { - Aggregate = new Administrator - { - UserId = UserId, - Roles = Roles.JoinAsString(",") - }; - - await AdministratorRepository.InsertAsync(Aggregate, true, cancellationToken); - } - - [FactoryUpdate] - protected override async Task UpdateAsync(CancellationToken cancellationToken = default) - { - if (ChangedProperties.Contains(RolesProperty)) - { - Aggregate.Roles = Roles.JoinAsString(","); - } - - await AdministratorRepository.UpdateAsync(Aggregate, true, cancellationToken); - } - - [FactoryDelete] - protected override async Task DeleteAsync(CancellationToken cancellationToken = default) - { - if (Aggregate == null) - { - throw new NotFoundException(); - } - - await AdministratorRepository.DeleteAsync(Aggregate, true, cancellationToken); - } - - public class UserCheckRule : RuleBase - { - public override async Task ExecuteAsync(IRuleContext context, CancellationToken cancellationToken = default) - { - var target = (AdministratorGeneralBusiness)context.Target; - if (target.ChangedProperties.Contains(UserIdProperty)) - { - var exists = await target.UserRepository.AnyAsync(t => t.Id == target.UserId, query => query.AsNoTracking(), cancellationToken); - if (exists) - { - context.AddErrorResult(string.Format(Resources.IDS_ERROR_USER_NOT_EXISTS, target.UserId)); - } - } - } - } -} \ No newline at end of file diff --git a/Source/Starfish.Service/Domain/Business/UserGeneralBusiness.cs b/Source/Starfish.Service/Domain/Business/UserGeneralBusiness.cs index f9264e6..44ed584 100644 --- a/Source/Starfish.Service/Domain/Business/UserGeneralBusiness.cs +++ b/Source/Starfish.Service/Domain/Business/UserGeneralBusiness.cs @@ -1,5 +1,6 @@ using System.Text.RegularExpressions; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; using Nerosoft.Euonia.Business; using Nerosoft.Euonia.Domain; using Nerosoft.Starfish.Service; @@ -28,6 +29,8 @@ public UserGeneralBusiness(IServiceProvider provider) public static readonly PropertyInfo NickNameProperty = RegisterProperty(p => p.NickName); public static readonly PropertyInfo EmailProperty = RegisterProperty(p => p.Email); public static readonly PropertyInfo PhoneProperty = RegisterProperty(p => p.Phone); + public static readonly PropertyInfo IsAdminProperty = RegisterProperty(p => p.IsAdmin); + public static readonly PropertyInfo ReservedProperty = RegisterProperty(p => p.Reserved); public string Id { @@ -65,9 +68,21 @@ public string Phone set => SetProperty(PhoneProperty, value); } + public bool IsAdmin + { + get => GetProperty(IsAdminProperty); + set => SetProperty(IsAdminProperty, value); + } + + public bool Reserved + { + get => GetProperty(ReservedProperty); + set => SetProperty(ReservedProperty, value); + } + protected override void AddRules() { - Rules.AddRule(new DuplicateUserNameCheckRule()); + Rules.AddRule(_provider.GetServiceOrCreateInstance()); Rules.AddRule(new DuplicateEmailCheckRule()); Rules.AddRule(new DuplicatePhoneCheckRule()); Rules.AddRule(new PasswordStrengthRule()); @@ -111,6 +126,8 @@ protected override Task InsertAsync(CancellationToken cancellationToken = defaul } user.SetNickName(NickName ?? UserName); + user.SetIsAdmin(IsAdmin); + user.Reserved = Reserved; return Repository.InsertAsync(user, true, cancellationToken) .ContinueWith(task => @@ -123,6 +140,11 @@ protected override Task InsertAsync(CancellationToken cancellationToken = defaul [FactoryUpdate] protected override Task UpdateAsync(CancellationToken cancellationToken = default) { + if (!HasChangedProperties) + { + return Task.CompletedTask; + } + if (ChangedProperties.Contains(EmailProperty)) { Aggregate.SetEmail(Email); @@ -143,6 +165,11 @@ protected override Task UpdateAsync(CancellationToken cancellationToken = defaul Aggregate.ChangePassword(Password); } + if (ChangedProperties.Contains(IsAdminProperty)) + { + Aggregate.SetIsAdmin(IsAdmin); + } + return _repository.UpdateAsync(Aggregate, true, cancellationToken); } @@ -157,8 +184,15 @@ protected override Task DeleteAsync(CancellationToken cancellationToken = defaul return _repository.DeleteAsync(Aggregate, true, cancellationToken); } - public class DuplicateUserNameCheckRule : RuleBase + public class UserNameAvailabilityCheckRule : RuleBase { + private readonly IConfiguration _configuration; + + public UserNameAvailabilityCheckRule(IConfiguration configuration) + { + _configuration = configuration; + } + public override async Task ExecuteAsync(IRuleContext context, CancellationToken cancellationToken = default) { var target = (UserGeneralBusiness)context.Target; @@ -167,6 +201,16 @@ public override async Task ExecuteAsync(IRuleContext context, CancellationToken return; } + if (!target.Reserved) + { + var reserved = _configuration.GetValue>("ReservedUsernames"); + if (reserved.Contains(target.UserName, StringComparison.OrdinalIgnoreCase)) + { + context.AddErrorResult(string.Format(Resources.IDS_ERROR_USER_USERNAME_UNAVAILABLE, target.UserName)); + return; + } + } + var repository = target.Repository; var exists = await repository.CheckUserNameExistsAsync(target.UserName, cancellationToken); if (exists) diff --git a/Source/Starfish.Service/Domain/Repositories/IAdministratorRepository.cs b/Source/Starfish.Service/Domain/Repositories/IAdministratorRepository.cs deleted file mode 100644 index 791776b..0000000 --- a/Source/Starfish.Service/Domain/Repositories/IAdministratorRepository.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Nerosoft.Starfish.Repository; -using Nerosoft.Starfish.Service; - -namespace Nerosoft.Starfish.Domain; - -internal interface IAdministratorRepository : IBaseRepository -{ - Task GetByUserIdAsync(string userId, CancellationToken cancellationToken = default); -} \ No newline at end of file diff --git a/Source/Starfish.Service/Repository/Contexts/AbstractDatabaseModelBuilder.cs b/Source/Starfish.Service/Repository/Contexts/AbstractDatabaseModelBuilder.cs index 3e8c7dd..4f1b827 100644 --- a/Source/Starfish.Service/Repository/Contexts/AbstractDatabaseModelBuilder.cs +++ b/Source/Starfish.Service/Repository/Contexts/AbstractDatabaseModelBuilder.cs @@ -8,7 +8,6 @@ internal abstract class AbstractDatabaseModelBuilder : IModelBuilder public virtual void Configure(ModelBuilder modelBuilder) { ConfigureUser(modelBuilder); - ConfigureAdministrator(modelBuilder); ConfigureTeam(modelBuilder); ConfigureTeamMember(modelBuilder); ConfigureConfiguration(modelBuilder); @@ -20,9 +19,7 @@ public virtual void Configure(ModelBuilder modelBuilder) } protected abstract ModelBuilder ConfigureUser(ModelBuilder modelBuilder); - - protected abstract ModelBuilder ConfigureAdministrator(ModelBuilder modelBuilder); - + protected abstract ModelBuilder ConfigureTeam(ModelBuilder modelBuilder); protected abstract ModelBuilder ConfigureTeamMember(ModelBuilder modelBuilder); diff --git a/Source/Starfish.Service/Repository/Contexts/RelationalDatabaseModelBuilder.cs b/Source/Starfish.Service/Repository/Contexts/RelationalDatabaseModelBuilder.cs index c81a44d..7b7a124 100644 --- a/Source/Starfish.Service/Repository/Contexts/RelationalDatabaseModelBuilder.cs +++ b/Source/Starfish.Service/Repository/Contexts/RelationalDatabaseModelBuilder.cs @@ -31,28 +31,7 @@ protected override ModelBuilder ConfigureUser(ModelBuilder modelBuilder) .HasValueGenerator(); }); } - - protected override ModelBuilder ConfigureAdministrator(ModelBuilder modelBuilder) - { - return modelBuilder.Entity(entity => - { - entity.ToTable("administrator"); - - entity.HasKey(t => t.Id); - - entity.HasIndex(t => t.UserId).HasDatabaseName("IDX_ADMIN_USER_ID") - .IsUnique(); - - entity.Property(t => t.Id) - .IsRequired() - .HasValueGenerator(); - - entity.HasOne(t => t.User) - .WithMany() - .HasForeignKey(t => t.UserId); - }); - } - + protected override ModelBuilder ConfigureTeam(ModelBuilder modelBuilder) { return modelBuilder.Entity(entity => diff --git a/Source/Starfish.Service/Repository/Repositories/AdministratorRepository.cs b/Source/Starfish.Service/Repository/Repositories/AdministratorRepository.cs deleted file mode 100644 index acb15ef..0000000 --- a/Source/Starfish.Service/Repository/Repositories/AdministratorRepository.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Nerosoft.Euonia.Repository; -using Nerosoft.Starfish.Domain; -using Nerosoft.Starfish.Service; - -namespace Nerosoft.Starfish.Repository; - -internal sealed class AdministratorRepository : BaseRepository, IAdministratorRepository -{ - public AdministratorRepository(IContextProvider provider) - : base(provider) - { - } - - public Task GetByUserIdAsync(string userId, CancellationToken cancellationToken = default) - { - return Context.Set().FirstOrDefaultAsync(t => t.UserId == userId, cancellationToken); - } -} diff --git a/Source/Starfish.Service/Repository/Specifications/AdministratorSpecification.cs b/Source/Starfish.Service/Repository/Specifications/AdministratorSpecification.cs deleted file mode 100644 index 43e49ae..0000000 --- a/Source/Starfish.Service/Repository/Specifications/AdministratorSpecification.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Nerosoft.Euonia.Linq; -using Nerosoft.Starfish.Domain; - -namespace Nerosoft.Starfish.Repository; - -internal static class AdministratorSpecification -{ - public static Specification UserNameContains(string userName) - { - userName = userName.Normalize(TextCaseType.Lower); - return new DirectSpecification(t => t.User.UserName.Contains(userName)); - } - - public static Specification NickNameContains(string nickName) - { - nickName = nickName.Normalize(TextCaseType.Lower); - return new DirectSpecification(t => t.User.NickName.ToLower().Contains(nickName)); - } - - public static Specification EmailContains(string email) - { - email = email.Normalize(TextCaseType.Lower); - return new DirectSpecification(t => t.User.Email.Contains(email)); - } - - public static Specification PhoneContains(string email) - { - email = email.Normalize(TextCaseType.Lower); - return new DirectSpecification(t => t.User.Phone.Contains(email)); - } - - public static Specification Matches(string keyword) - { - if (string.IsNullOrEmpty(keyword)) - { - return new TrueSpecification(); - } - - keyword = keyword.Normalize(TextCaseType.Lower); - - ISpecification[] specifications = - [ - UserNameContains(keyword), - NickNameContains(keyword), - EmailContains(keyword), - PhoneContains(keyword) - ]; - - return new CompositeSpecification(PredicateOperator.OrElse, specifications); - } -} \ No newline at end of file diff --git a/Source/Starfish.Service/Seedwork/ServiceProviderExtensions.cs b/Source/Starfish.Service/Seedwork/ServiceProviderExtensions.cs new file mode 100644 index 0000000..d95b199 --- /dev/null +++ b/Source/Starfish.Service/Seedwork/ServiceProviderExtensions.cs @@ -0,0 +1,9 @@ +namespace Nerosoft.Starfish.Service; + +internal static class ServiceProviderExtensions +{ + public static T GetServiceOrCreateInstance(this IServiceProvider provider) + { + return ActivatorUtilities.GetServiceOrCreateInstance(provider); + } +} diff --git a/Source/Starfish.Service/UseCases/Admins/AdministratorAssignUseCase.cs b/Source/Starfish.Service/UseCases/Admins/AdministratorAssignUseCase.cs deleted file mode 100644 index ed6efc1..0000000 --- a/Source/Starfish.Service/UseCases/Admins/AdministratorAssignUseCase.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Nerosoft.Euonia.Application; -using Nerosoft.Euonia.Bus; -using Nerosoft.Euonia.Claims; -using Nerosoft.Euonia.Mapping; -using Nerosoft.Starfish.Application; -using Nerosoft.Starfish.Transit; - -namespace Nerosoft.Starfish.UseCases; - -internal interface IAdministratorAssignUseCase : INonOutputUseCase; - -internal record AdministratorAssignInput(AdministratorAssignDto Data); - -internal class AdministratorAssignUseCase : IAdministratorAssignUseCase -{ - private readonly IBus _bus; - private readonly UserPrincipal _user; - - public AdministratorAssignUseCase(IBus bus, UserPrincipal user) - { - _bus = bus; - _user = user; - } - - public Task ExecuteAsync(AdministratorAssignInput input, CancellationToken cancellationToken = default) - { - _user.EnsureInRoles(["SA"]); - - if (string.Equals(_user.UserId, input.Data.UserId)) - { - throw new InvalidOperationException(); - } - - var command = TypeAdapter.ProjectedAs(input.Data); - return _bus.SendAsync(command, cancellationToken); - } -} \ No newline at end of file diff --git a/Source/Starfish.Service/UseCases/Admins/AdministratorCountUseCase.cs b/Source/Starfish.Service/UseCases/Admins/AdministratorCountUseCase.cs deleted file mode 100644 index 4cb8b2c..0000000 --- a/Source/Starfish.Service/UseCases/Admins/AdministratorCountUseCase.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Security.Authentication; -using Microsoft.EntityFrameworkCore; -using Nerosoft.Euonia.Application; -using Nerosoft.Euonia.Claims; -using Nerosoft.Starfish.Domain; -using Nerosoft.Starfish.Repository; -using Nerosoft.Starfish.Transit; - -namespace Nerosoft.Starfish.UseCases; - -internal interface IAdministratorCountUseCase : IUseCase; - -internal record AdministratorCountInput(AdministratorCriteria Criteria); - -internal record AdministratorCountOutput(int Result); - -internal class AdministratorCountUseCase : IAdministratorCountUseCase -{ - private readonly IAdministratorRepository _repository; - private readonly UserPrincipal _user; - - public AdministratorCountUseCase(IAdministratorRepository repository, UserPrincipal user) - { - _repository = repository; - _user = user; - } - - public Task ExecuteAsync(AdministratorCountInput input, CancellationToken cancellationToken = default) - { - if (_user.IsAuthenticated) - { - throw new AuthenticationException(Resources.IDS_MESSAGE_LOGS_AUTH_FAILED); - } - - if (!_user.IsInRoles(["SA"])) - { - throw new UnauthorizedAccessException(Resources.IDS_ERROR_COMMON_UNAUTHORIZED_ACCESS); - } - - var predicate = AdministratorSpecification.Matches(input.Criteria.Keyword).Satisfy(); - - return _repository.CountAsync(predicate, query => query.AsNoTracking().Include(t => t.User), cancellationToken) - .ContinueWith(task => - { - task.WaitAndUnwrapException(cancellationToken); - return new AdministratorCountOutput(task.Result); - }, cancellationToken); - } -} \ No newline at end of file diff --git a/Source/Starfish.Service/UseCases/Admins/AdministratorDeleteUseCase.cs b/Source/Starfish.Service/UseCases/Admins/AdministratorDeleteUseCase.cs deleted file mode 100644 index c278b4c..0000000 --- a/Source/Starfish.Service/UseCases/Admins/AdministratorDeleteUseCase.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Nerosoft.Euonia.Application; -using Nerosoft.Euonia.Bus; -using Nerosoft.Euonia.Claims; -using Nerosoft.Starfish.Application; - -namespace Nerosoft.Starfish.UseCases; - -internal interface IAdministratorDeleteUseCase : INonOutputUseCase; - -internal record AdministratorDeleteInput(string UserId) : IUseCaseInput; - -internal class AdministratorDeleteUseCase : IAdministratorDeleteUseCase -{ - private readonly IBus _bus; - private readonly UserPrincipal _user; - - public AdministratorDeleteUseCase(IBus bus, UserPrincipal user) - { - _bus = bus; - _user = user; - } - - public Task ExecuteAsync(AdministratorDeleteInput input, CancellationToken cancellationToken = default) - { - _user.EnsureInRoles(["SA"]); - - if (string.Equals(_user.UserId, input.UserId)) - { - throw new InvalidOperationException(); - } - - var command = new AdministratorDeleteCommand(input.UserId); - - return _bus.SendAsync(command, cancellationToken); - } -} \ No newline at end of file diff --git a/Source/Starfish.Service/UseCases/Admins/AdministratorQueryUseCase.cs b/Source/Starfish.Service/UseCases/Admins/AdministratorQueryUseCase.cs deleted file mode 100644 index 4167d73..0000000 --- a/Source/Starfish.Service/UseCases/Admins/AdministratorQueryUseCase.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Security.Authentication; -using Microsoft.EntityFrameworkCore; -using Nerosoft.Euonia.Application; -using Nerosoft.Euonia.Claims; -using Nerosoft.Euonia.Mapping; -using Nerosoft.Starfish.Domain; -using Nerosoft.Starfish.Repository; -using Nerosoft.Starfish.Transit; - -namespace Nerosoft.Starfish.UseCases; - -internal interface IAdministratorQueryUseCase : IUseCase, AdministratorQueryOutput>; - -internal record AdministratorQueryOutput(List Result); - -internal class AdministratorQueryUseCase : IAdministratorQueryUseCase -{ - private readonly IAdministratorRepository _repository; - private readonly UserPrincipal _user; - - public AdministratorQueryUseCase(IAdministratorRepository repository, UserPrincipal user) - { - _repository = repository; - _user = user; - } - - public Task ExecuteAsync(GenericQueryInput input, CancellationToken cancellationToken = default) - { - if (_user.IsAuthenticated) - { - throw new AuthenticationException(Resources.IDS_MESSAGE_LOGS_AUTH_FAILED); - } - - if (!_user.IsInRoles(["SA"])) - { - throw new UnauthorizedAccessException(Resources.IDS_ERROR_COMMON_UNAUTHORIZED_ACCESS); - } - - var predicate = AdministratorSpecification.Matches(input.Criteria.Keyword).Satisfy(); - - return _repository.FindAsync(predicate, query => query.AsNoTracking().Include(t => t.User), input.Skip, input.Count, cancellationToken) - .ContinueWith(task => - { - task.WaitAndUnwrapException(cancellationToken); - var result = TypeAdapter.ProjectedAs>(task.Result); - return new AdministratorQueryOutput(result); - }, cancellationToken); - } -} \ No newline at end of file diff --git a/Source/Starfish.Service/UseCases/Identity/GrantWithPasswordUseCase.cs b/Source/Starfish.Service/UseCases/Identity/GrantWithPasswordUseCase.cs index 4abf7ba..ae383bb 100644 --- a/Source/Starfish.Service/UseCases/Identity/GrantWithPasswordUseCase.cs +++ b/Source/Starfish.Service/UseCases/Identity/GrantWithPasswordUseCase.cs @@ -41,9 +41,6 @@ public GrantWithPasswordUseCase(IServiceProvider provider) private IUserRepository _userRepository; private IUserRepository UserRepository => _userRepository ??= _provider.GetService(); - private IAdministratorRepository _adminRespository; - private IAdministratorRepository AdminRepository => _adminRespository ??= _provider.GetService(); - private IdentityCommonComponent _component; private IdentityCommonComponent Component => _component ??= _provider.GetService(); @@ -79,9 +76,8 @@ public async Task ExecuteAsync(GrantWithPassword throw new AuthenticationException(Resources.IDS_ERROR_USER_LOCKOUT); } - var administrator = await AdminRepository.GetByUserIdAsync(user.Id, cancellationToken); - var roles = administrator?.Roles?.Split(","); - + string[] roles = user.IsAdmin ? ["SA"] : []; + var (accessToken, refreshToken, issuesAt, expiresAt) = Component.GenerateAccessToken(user.Id, user.UserName, roles); @events.Add(new UserAuthSucceedEvent { diff --git a/Source/Starfish.Service/UseCases/Identity/GrantWithRefreshTokenUseCase.cs b/Source/Starfish.Service/UseCases/Identity/GrantWithRefreshTokenUseCase.cs index c415c38..18448e0 100644 --- a/Source/Starfish.Service/UseCases/Identity/GrantWithRefreshTokenUseCase.cs +++ b/Source/Starfish.Service/UseCases/Identity/GrantWithRefreshTokenUseCase.cs @@ -43,9 +43,6 @@ public GrantWithRefreshTokenUseCase(IServiceProvider provider) private IUserRepository UserRepository => _provider.GetService(); private ITokenRepository TokenRepository => _provider.GetService(); - private IAdministratorRepository _adminRespository; - private IAdministratorRepository AdminRepository => _adminRespository ??= _provider.GetService(); - private IdentityCommonComponent _component; private IdentityCommonComponent Component => _component ??= _provider.GetService(); @@ -88,10 +85,9 @@ public async Task ExecuteAsync(GrantWithRefr { throw new AuthenticationException(Resources.IDS_ERROR_USER_LOCKOUT); } - - var administrator = await AdminRepository.GetByUserIdAsync(user.Id, cancellationToken); - var roles = administrator?.Roles?.Split(","); - + + string[] roles = user.IsAdmin ? ["SA"] : []; + var (accessToken, refreshToken, issuesAt, expiresAt) = Component.GenerateAccessToken(user.Id, user.UserName, roles); @events.Add(new UserAuthSucceedEvent { diff --git a/Source/Starfish.Service/UseCases/Identity/UserCreateUseCase.cs b/Source/Starfish.Service/UseCases/Identity/UserCreateUseCase.cs index 07657dd..7b1772c 100644 --- a/Source/Starfish.Service/UseCases/Identity/UserCreateUseCase.cs +++ b/Source/Starfish.Service/UseCases/Identity/UserCreateUseCase.cs @@ -1,5 +1,6 @@ using Nerosoft.Euonia.Application; using Nerosoft.Euonia.Bus; +using Nerosoft.Euonia.Mapping; using Nerosoft.Starfish.Application; using Nerosoft.Starfish.Transit; @@ -22,7 +23,7 @@ public UserCreateUseCase(IBus bus) public Task ExecuteAsync(UserCreateInput input, CancellationToken cancellationToken = default) { - var command = new UserCreateCommand(input.Data); + var command = TypeAdapter.ProjectedAs(input.Data); return _bus.SendAsync(command, cancellationToken) .ContinueWith(task => new UserCreateOutput(task.Result), cancellationToken); } diff --git a/Source/Starfish.Service/UseCases/Identity/UserInitializeUseCase.cs b/Source/Starfish.Service/UseCases/Identity/UserInitializeUseCase.cs new file mode 100644 index 0000000..bf41a8f --- /dev/null +++ b/Source/Starfish.Service/UseCases/Identity/UserInitializeUseCase.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.Configuration; +using Nerosoft.Euonia.Application; +using Nerosoft.Euonia.Bus; +using Nerosoft.Starfish.Application; +using Nerosoft.Starfish.Domain; + +namespace Nerosoft.Starfish.UseCases; + +internal interface IUserInitializeUseCase : IParameterlessUseCase; + +internal class UserInitializeUseCase : IUserInitializeUseCase +{ + private readonly IBus _bus; + private readonly IUserRepository _repository; + private readonly IConfiguration _configuration; + + public UserInitializeUseCase(IBus bus, IUserRepository repository, IConfiguration configuration) + { + _bus = bus; + _repository = repository; + _configuration = configuration; + } + + public async Task ExecuteAsync(CancellationToken cancellationToken = default) + { + var username = _configuration["InitializeUser:UserName"]; + + if (string.IsNullOrWhiteSpace(username)) + { + return; + } + + var exists = await _repository.CheckUserNameExistsAsync(username, cancellationToken); + if (exists) + { + return; + } + + var command = new UserCreateCommand + { + UserName = _configuration["InitializeUser:UserName"], + Password = _configuration["InitializeUser:Password"], + IsAdmin = true, + Reserved = true + }; + await _bus.SendAsync(command, cancellationToken).ContinueWith(task => task.WaitAndUnwrapException()); + } +} \ No newline at end of file diff --git a/Source/Starfish.Transit/Identity/AdministratorCriteria.cs b/Source/Starfish.Transit/Identity/AdministratorCriteria.cs deleted file mode 100644 index 917e576..0000000 --- a/Source/Starfish.Transit/Identity/AdministratorCriteria.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Nerosoft.Starfish.Transit; - -/// -/// 管理员搜索条件 -/// -public class AdministratorCriteria -{ - /// - /// 关键字 - /// - /// - /// 搜索用户名、昵称、邮箱、电话号码 - /// - public string Keyword { get; set; } -} \ No newline at end of file diff --git a/Source/Starfish.Transit/Identity/AdministratorItemDto.cs b/Source/Starfish.Transit/Identity/AdministratorItemDto.cs deleted file mode 100644 index b7b52f1..0000000 --- a/Source/Starfish.Transit/Identity/AdministratorItemDto.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace Nerosoft.Starfish.Transit; - -/// -/// 管理员列表项数据传输对象 -/// -public sealed class AdministratorItemDto -{ - /// - /// 用户Id - /// - public string UserId { get; set; } - - /// - /// 用户名 - /// - public string UserName { get; set; } - - /// - /// 昵称 - /// - public string NickName { get; set; } - - /// - /// 邮箱 - /// - public string Email { get; set; } - - /// - /// 电话号码 - /// - public string Phone { get; set; } - - /// - /// 角色 - /// - public List Roles { get; set; } -} \ No newline at end of file diff --git a/Source/Starfish.Transit/Identity/UserCreateDto.cs b/Source/Starfish.Transit/Identity/UserCreateDto.cs index d998735..561c9bc 100644 --- a/Source/Starfish.Transit/Identity/UserCreateDto.cs +++ b/Source/Starfish.Transit/Identity/UserCreateDto.cs @@ -24,9 +24,14 @@ public class UserCreateDto /// 电话 /// public string Phone { get; set; } - + /// /// 昵称 /// public string NickName { get; set; } + + /// + /// 是否是管理员 + /// + public bool IsAdmin { get; set; } } \ No newline at end of file diff --git a/Source/Starfish.Transit/Identity/UserDetailDto.cs b/Source/Starfish.Transit/Identity/UserDetailDto.cs index 6cf9728..556e676 100644 --- a/Source/Starfish.Transit/Identity/UserDetailDto.cs +++ b/Source/Starfish.Transit/Identity/UserDetailDto.cs @@ -30,6 +30,11 @@ public class UserDetailDto /// public string NickName { get; set; } + /// + /// 是否管理员 + /// + public bool IsAdmin { get; set; } + /// /// 创建时间 /// diff --git a/Source/Starfish.Transit/Identity/UserItemDto.cs b/Source/Starfish.Transit/Identity/UserItemDto.cs index 90019a3..031947c 100644 --- a/Source/Starfish.Transit/Identity/UserItemDto.cs +++ b/Source/Starfish.Transit/Identity/UserItemDto.cs @@ -29,4 +29,9 @@ public class UserItemDto /// 昵称 /// public string NickName { get; set; } + + /// + /// 是否管理员 + /// + public bool IsAdmin { get; set; } } \ No newline at end of file diff --git a/Source/Starfish.Transit/Identity/UserUpdateDto.cs b/Source/Starfish.Transit/Identity/UserUpdateDto.cs index c6e2c9e..34fa3ac 100644 --- a/Source/Starfish.Transit/Identity/UserUpdateDto.cs +++ b/Source/Starfish.Transit/Identity/UserUpdateDto.cs @@ -10,8 +10,18 @@ public class UserUpdateDto /// public string Email { get; set; } + /// + /// 电话号码 + /// + public string Phone { get; set; } + /// /// 昵称 /// public string NickName { get; set; } + + /// + /// 是否是管理员 + /// + public bool IsAdmin { get; set; } } diff --git a/Source/Starfish.Transit/Misc/ConnectionInfoDto.cs b/Source/Starfish.Transit/Misc/ConnectionInfoDto.cs new file mode 100644 index 0000000..799eb27 --- /dev/null +++ b/Source/Starfish.Transit/Misc/ConnectionInfoDto.cs @@ -0,0 +1,32 @@ +namespace Nerosoft.Starfish.Transit; + +/// +/// 连接信息传输对象 +/// +public class ConnectionInfoDto +{ + /// + /// 配置Id + /// + public string ConfigurationId { get; set; } + + /// + /// 配置名称 + /// + public string ConfigurationName { get; set; } + + /// + /// 连接Id + /// + public string ConnectionId { get; set; } + + /// + /// 连接类型 + /// + public string ConnectionType { get; set; } + + /// + /// 连接时间 + /// + public DateTime ConnectedTime { get; set; } +} \ No newline at end of file diff --git a/Source/Starfish.Transit/Identity/AdministratorAssignDto.cs b/Source/Starfish.Transit/Team/TeamMemberAppendDto.cs similarity index 62% rename from Source/Starfish.Transit/Identity/AdministratorAssignDto.cs rename to Source/Starfish.Transit/Team/TeamMemberAppendDto.cs index c8ef616..76301b8 100644 --- a/Source/Starfish.Transit/Identity/AdministratorAssignDto.cs +++ b/Source/Starfish.Transit/Team/TeamMemberAppendDto.cs @@ -1,9 +1,9 @@ namespace Nerosoft.Starfish.Transit; /// -/// 管理员编辑数据传输对象 +/// 添加团队成员请求Dto /// -public class AdministratorAssignDto +public class TeamMemberAppendDto { /// /// 用户Id @@ -13,5 +13,5 @@ public class AdministratorAssignDto /// /// 角色 /// - public List Roles { get; set; } -} + public string Role { get; set; } +} \ No newline at end of file diff --git a/Source/Starfish.Webapi/Controllers/AdministratorController.cs b/Source/Starfish.Webapi/Controllers/AdministratorController.cs deleted file mode 100644 index d7aa7a9..0000000 --- a/Source/Starfish.Webapi/Controllers/AdministratorController.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Nerosoft.Starfish.Application; -using Nerosoft.Starfish.Transit; - -namespace Nerosoft.Starfish.Webapi.Controllers; - -/// -/// 管理员管理Controller -/// -[Route("api/[controller]")] -[ApiController, ApiExplorerSettings(GroupName = "identity")] -[Authorize] -public class AdministratorController : ControllerBase -{ - private readonly IAdministratorApplicationService _service; - - /// - /// 构造函数 - /// - /// - public AdministratorController(IAdministratorApplicationService service) - { - _service = service; - } - - /// - /// 查询管理员列表 - /// - /// - /// - /// - /// - [HttpGet] - [Produces(typeof(List))] - public async Task QueryAsync([FromQuery] AdministratorCriteria criteria, int skip = Constants.Query.Skip, int count = Constants.Query.Count) - { - var result = await _service.QueryAsync(criteria, skip, count, HttpContext.RequestAborted); - return Ok(result); - } - - /// - /// 查询管理员数量 - /// - /// - /// - [HttpGet("count")] - [Produces(typeof(int))] - public async Task CountAsync([FromQuery] AdministratorCriteria criteria) - { - var result = await _service.CountAsync(criteria, HttpContext.RequestAborted); - return Ok(result); - } - - /// - /// 创建管理员 - /// - /// - /// - [HttpPost] - public async Task AssignAsync([FromBody] AdministratorAssignDto data) - { - await _service.AssignAsync(data, HttpContext.RequestAborted); - return Ok(); - } - - /// - /// 删除管理员 - /// - /// - /// - [HttpDelete("{userId}")] - public async Task DeleteAsync(string userId) - { - await _service.DeleteAsync(userId, HttpContext.RequestAborted); - return Ok(); - } -} \ No newline at end of file diff --git a/Source/Starfish.Webapi/appsettings.json b/Source/Starfish.Webapi/appsettings.json index 71e5de8..85142d8 100644 --- a/Source/Starfish.Webapi/appsettings.json +++ b/Source/Starfish.Webapi/appsettings.json @@ -27,6 +27,16 @@ "TopicName": "nerosoft.starfish.topic" } }, + "InitializeUser": { + "UserName": "admin", + "Password": "Starfish.8888" + }, + "ReservedUsernames": [ + "starfish", + "admin", + "administrator", + "root" + ], "FeatureManagement": { "UserRegistration": true }, diff --git a/Source/Starfish.Webapp/Pages/User/Edit.razor b/Source/Starfish.Webapp/Pages/User/Edit.razor index d85d55d..d659621 100644 --- a/Source/Starfish.Webapp/Pages/User/Edit.razor +++ b/Source/Starfish.Webapp/Pages/User/Edit.razor @@ -4,7 +4,7 @@ - + @Dialog.Instance.Parameters.Title @@ -16,25 +16,32 @@ + ReadOnly="@(!string.IsNullOrEmpty(Content))" /> @if (string.IsNullOrEmpty(Content)) { + TextFieldType="TextFieldType.Password" /> + TextFieldType="TextFieldType.Password" /> } + @bind-Value="NickName" /> + TextFieldType="TextFieldType.Email" /> + + + + @@ -63,6 +70,10 @@ private string Email { get; set; } + private string Phone { get; set; } + + private bool IsAdmin { get; set; } + protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); @@ -77,10 +88,12 @@ if (!string.IsNullOrEmpty(Content)) { var request = new UserUpdateDto - { - NickName = NickName, - Email = Email - }; + { + NickName = NickName, + Email = Email, + Phone = Phone, + IsAdmin = IsAdmin + }; await Api.UpdateAsync(Content, request) .EnsureSuccess(); @@ -93,12 +106,14 @@ } var request = new UserCreateDto - { - UserName = UserName, - Password = Password, - NickName = NickName, - Email = Email - }; + { + UserName = UserName, + Password = Password, + NickName = NickName, + Email = Email, + Phone = Phone, + IsAdmin = IsAdmin + }; await Api.CreateAsync(request) .EnsureSuccess(); @@ -140,6 +155,8 @@ UserName = result.UserName; NickName = result.NickName; Email = result.Email; + Phone = result.Phone; + IsAdmin = result.IsAdmin; }); } diff --git a/Source/Starfish.Webapp/Pages/User/Index.razor b/Source/Starfish.Webapp/Pages/User/Index.razor index 882e060..86ba9d9 100644 --- a/Source/Starfish.Webapp/Pages/User/Index.razor +++ b/Source/Starfish.Webapp/Pages/User/Index.razor @@ -15,31 +15,32 @@ + GridTemplateColumns="0.5fr 0.5fr 1fr 1fr 0.4fr 0.2fr"> @(context.UserName) - - - + + + + - - + + - + @@ -59,10 +60,10 @@ { List items = null; var tasks = new List - { + { Api.SearchAsync(Criteria, request.StartIndex, Pagination.ItemsPerPage, request.CancellationToken) .EnsureSuccess(result => items = result, request.CancellationToken) - }; + }; if (request.StartIndex == 0) { diff --git a/Source/Starfish.Webapp/Properties/Resources.resx b/Source/Starfish.Webapp/Properties/Resources.resx index 249e0c5..9e01898 100644 --- a/Source/Starfish.Webapp/Properties/Resources.resx +++ b/Source/Starfish.Webapp/Properties/Resources.resx @@ -570,6 +570,9 @@ Email + + Administrator + Nick name @@ -588,12 +591,18 @@ Email + + Administrator + Nick name Password + + Phone number + User name diff --git a/Source/Starfish.Webapp/Properties/Resources.zh-Hans.resx b/Source/Starfish.Webapp/Properties/Resources.zh-Hans.resx index 67f30c1..299150b 100644 --- a/Source/Starfish.Webapp/Properties/Resources.zh-Hans.resx +++ b/Source/Starfish.Webapp/Properties/Resources.zh-Hans.resx @@ -570,6 +570,9 @@ 邮箱 + + 管理员 + 昵称 @@ -588,12 +591,18 @@ 邮箱 + + 管理员 + 昵称 密码 + + 手机号 + 用户名 diff --git a/Source/Starfish.Webapp/Properties/Resources.zh-Hant.resx b/Source/Starfish.Webapp/Properties/Resources.zh-Hant.resx index 34cd414..734f742 100644 --- a/Source/Starfish.Webapp/Properties/Resources.zh-Hant.resx +++ b/Source/Starfish.Webapp/Properties/Resources.zh-Hant.resx @@ -345,12 +345,6 @@ 配置 - - 配置Id - - - 配置名稱 - 連接時間 @@ -576,6 +570,9 @@ 電子郵件 + + 管理員 + 昵稱 @@ -594,12 +591,18 @@ 電子郵件 + + 管理員 + 昵稱 密碼 + + 手機號 + 用戶名 diff --git a/Source/Starfish.Webapp/Rest/Defines/IAdministratorApi.cs b/Source/Starfish.Webapp/Rest/Defines/IAdministratorApi.cs deleted file mode 100644 index 5efa708..0000000 --- a/Source/Starfish.Webapp/Rest/Defines/IAdministratorApi.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Nerosoft.Starfish.Transit; -using Refit; - -namespace Nerosoft.Starfish.Webapp.Rest; - -internal interface IAdministratorApi -{ - [Get("/api/administrator")] - Task>> QueryAsync([Query] AdministratorCriteria criteria, int skip = Constants.Query.Skip, int count = Constants.Query.Count, CancellationToken cancellationToken = default); - - [Post("/api/administrator")] - Task AssignAsync([Body] AdministratorAssignDto data, CancellationToken cancellationToken = default); - - [Get("/api/administrator/count")] - Task> CountAsync([Query] AdministratorCriteria criteria, CancellationToken cancellationToken = default); - - [Delete("/api/administrator/{userId}")] - Task DeleteAsync(string userId, CancellationToken cancellationToken = default); -} \ No newline at end of file diff --git a/Source/Starfish.Webapp/Rest/ServiceCollectionExtensions.cs b/Source/Starfish.Webapp/Rest/ServiceCollectionExtensions.cs index a519c44..e4dfbd9 100644 --- a/Source/Starfish.Webapp/Rest/ServiceCollectionExtensions.cs +++ b/Source/Starfish.Webapp/Rest/ServiceCollectionExtensions.cs @@ -39,7 +39,6 @@ public static IServiceCollection AddHttpClientApi(this IServiceCollection servic .AddTransient(provider => provider.GetRestService(HTTP_CLIENT_NAME)) .AddTransient(provider => provider.GetRestService(HTTP_CLIENT_NAME)) .AddTransient(provider => provider.GetRestService(HTTP_CLIENT_NAME)) - .AddTransient(provider => provider.GetRestService(HTTP_CLIENT_NAME)) .AddTransient(provider => provider.GetRestService(HTTP_CLIENT_NAME)) .AddTransient(provider => provider.GetRestService(HTTP_CLIENT_NAME));