diff --git a/api/src/Sozsoft.Platform.Application.Contracts/Identity/Dto/AssignedWorkHourViewModel.cs b/api/src/Sozsoft.Platform.Application.Contracts/Identity/Dto/AssignedWorkHourViewModel.cs new file mode 100644 index 0000000..cc20ca1 --- /dev/null +++ b/api/src/Sozsoft.Platform.Application.Contracts/Identity/Dto/AssignedWorkHourViewModel.cs @@ -0,0 +1,13 @@ +using System; + +namespace Sozsoft.Platform.Identity.Dto; + +public class AssignedWorkHourViewModel +{ + public Guid Id { get; set; } + + public string Name { get; set; } + + public bool IsAssigned { get; set; } +} + diff --git a/api/src/Sozsoft.Platform.Application.Contracts/Identity/Dto/UserInfoViewModel.cs b/api/src/Sozsoft.Platform.Application.Contracts/Identity/Dto/UserInfoViewModel.cs index f5673c0..1da4029 100644 --- a/api/src/Sozsoft.Platform.Application.Contracts/Identity/Dto/UserInfoViewModel.cs +++ b/api/src/Sozsoft.Platform.Application.Contracts/Identity/Dto/UserInfoViewModel.cs @@ -39,6 +39,8 @@ public class UserInfoViewModel: ExtensibleObject public AssignedBranchViewModel[] Branches { get; set; } public AssignedClaimViewModel[] Claims { get; set; } + + public AssignedWorkHourViewModel[] WorkHours { get; set; } public bool LockUser { get; set; } @@ -51,5 +53,5 @@ public class UserInfoViewModel: ExtensibleObject public string RocketUsername { get; set; } public DateTimeOffset? CreationTime { get; set; } public DateTimeOffset? LastModificationTime { get; set; } + public string WorkHour { get; set; } } - diff --git a/api/src/Sozsoft.Platform.Application/Identity/PlatformIdentityAppService.cs b/api/src/Sozsoft.Platform.Application/Identity/PlatformIdentityAppService.cs index b23c0c2..1a5c8f0 100644 --- a/api/src/Sozsoft.Platform.Application/Identity/PlatformIdentityAppService.cs +++ b/api/src/Sozsoft.Platform.Application/Identity/PlatformIdentityAppService.cs @@ -26,6 +26,7 @@ public class PlatformIdentityAppService : ApplicationService public IRepository claimTypesRepository { get; } public IGuidGenerator guidGenerator { get; } public IdentityUserManager UserManager { get; set; } + public IRepository workHourRepository { get; } public PlatformIdentityAppService( IIdentityUserAppService identityUserAppService, @@ -34,11 +35,13 @@ public class PlatformIdentityAppService : ApplicationService IRepository branchRepository, IRepository branchUsersRepository, IRepository claimTypesRepository, + IRepository workHourRepository, IGuidGenerator guidGenerator ) { this.IdentityUserAppService = identityUserAppService; this.identityUserRepository = identityUserRepository; + this.workHourRepository = workHourRepository; this.permissionRepository = permissionRepository; this.branchRepository = branchRepository; this.branchUsersRepository = branchUsersRepository; @@ -89,6 +92,14 @@ public class PlatformIdentityAppService : ApplicationService }; }).ToArray(); + var workHourList = await workHourRepository.GetListAsync(); + var workHours = workHourList.Select(workHour => new AssignedWorkHourViewModel + { + Id = workHour.Id, + Name = workHour.Name, + IsAssigned = workHourList.Contains(workHour) + }).ToArray(); + return new UserInfoViewModel() { Id = user.Id, @@ -98,6 +109,7 @@ public class PlatformIdentityAppService : ApplicationService Roles = roles, Branches = branches, Claims = claims, + WorkHours = workHours, Email = user.Email, PhoneNumber = user.PhoneNumber, IsActive = user.IsActive, @@ -116,6 +128,7 @@ public class PlatformIdentityAppService : ApplicationService AccessFailedCount = user.AccessFailedCount, ShouldChangePasswordOnNextLogin = user.ShouldChangePasswordOnNextLogin, RocketUsername = user.GetRocketUsername(), + WorkHour = user.GetWorkHour(), CreationTime = user.CreationTime, LastModificationTime = user.LastModificationTime, }; @@ -142,7 +155,7 @@ public class PlatformIdentityAppService : ApplicationService //LoginEndDate user.SetLoginEndDate(UserInfo.LoginEndDate); - + user.SetWorkHour(UserInfo.WorkHour); user.SetIsActive(UserInfo.IsActive); user.SetEmailConfirmed(UserInfo.EmailConfirmed); @@ -169,6 +182,7 @@ public class PlatformIdentityAppService : ApplicationService user.SetPhoneNumber(UserInfo.PhoneNumber, user.PhoneNumberConfirmed); user.SetLastPasswordChangeTime(UserInfo.LastPasswordChangeTime); user.SetRocketUsername(UserInfo.RocketUsername); + user.SetWorkHour(UserInfo.WorkHour); await UserManager.UpdateAsync(user); diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json index cdfb7c9..40debd4 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json @@ -2856,6 +2856,12 @@ "en": "Account Lockout Enabled", "tr": "Hesap Kilitlemesi Etkinleştirme" }, + { + "resourceName": "Platform", + "key": "Abp.Identity.User.LockoutManagement.WorkHour", + "en": "Work Hour", + "tr": "Çalışma Saati" + }, { "resourceName": "Platform", "key": "Abp.Identity.User.LockoutManagement.AccountLocked", @@ -12434,6 +12440,12 @@ } ], "LanguageFieldTitles": [ + { + "resourceName": "Platform", + "key": "App.Listform.ListformField.WorkHour", + "en": "Work Hour", + "tr": "Çalışma Saati" + }, { "resourceName": "Platform", "key": "App.Listform.ListformField.Abbreviation", @@ -13664,6 +13676,24 @@ "en": "Is Active", "tr": "Aktif" }, + { + "resourceName": "Platform", + "key": "App.Listform.ListformField.IsVerified", + "en": "Is Verified", + "tr": "Doğrulandı" + }, + { + "resourceName": "Platform", + "key": "App.Listform.ListformField.EmailConfirmed", + "en": "Email Confirmed", + "tr": "E-posta Doğrulandı" + }, + { + "resourceName": "Platform", + "key": "App.Listform.ListformField.TwoFactorEnabled", + "en": "Two Factor Enabled", + "tr": "İki Faktörlü Doğrulama Etkin" + }, { "resourceName": "Platform", "key": "App.Listform.ListformField.IsAnonymous", diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Administration.cs b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Administration.cs index f06b24f..9e08558 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Administration.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Administration.cs @@ -790,15 +790,16 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep PermissionJson = DefaultPermissionJson(PlatformConsts.IdentityPermissions.Users.Create, listFormName, PlatformConsts.IdentityPermissions.Users.Update, PlatformConsts.IdentityPermissions.Users.Delete, PlatformConsts.IdentityPermissions.Users.Export, PlatformConsts.IdentityPermissions.Users.Import, PlatformConsts.IdentityPermissions.Users.Note), DeleteCommand = $"UPDATE \"AbpUsers\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\"=@Id", DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(), - EditingOptionJson = DefaultEditingOptionJson(listFormName, 500, 550, true, true, true, true, false), + EditingOptionJson = DefaultEditingOptionJson(listFormName, 500, 600, true, true, true, true, false), EditingFormJson = JsonSerializer.Serialize(new List() { new () { Order=1,ColCount=1,ColSpan=1,ItemType="group",Items=[ new EditingFormItemDto { Order=1, DataField="Email", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order=2, DataField="Name", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order=3, DataField="Surname", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order=4, DataField="PhoneNumber", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, - new EditingFormItemDto { Order=5, DataField="Password", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, - new EditingFormItemDto { Order=6, DataField="IsActive", ColSpan=1, EditorType2=EditorTypes.dxCheckBox }, + new EditingFormItemDto { Order=5, DataField="WorkHour", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxSelectBox }, + new EditingFormItemDto { Order=6, DataField="Password", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=7, DataField="IsActive", ColSpan=1, EditorType2=EditorTypes.dxCheckBox }, ]} }), InsertServiceAddress = "list-form-dynamic-api/user-insert", @@ -822,7 +823,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep }, }), FormFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] { - new FieldsDefaultValue() { FieldName = "IsActive", FieldDbType = DbType.Boolean, Value = "true", CustomValueType = FieldCustomValueTypeEnum.Value } + new() { FieldName = "IsActive", FieldDbType = DbType.Boolean, Value = "true", CustomValueType = FieldCustomValueTypeEnum.Value } }), WidgetsJson = JsonSerializer.Serialize(new List { @@ -904,7 +905,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep SourceDbType = DbType.String, FieldName = "Email", CaptionName = "Abp.Account.EmailAddress", - Width = 300, + Width = 250, ListOrderNo = 2, Visible = true, IsActive = true, @@ -924,7 +925,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep SourceDbType = DbType.String, FieldName = "Name", CaptionName = "App.Listform.ListformField.Name", - Width = 150, + Width = 125, ListOrderNo = 3, Visible = true, IsActive = true, @@ -944,7 +945,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep SourceDbType = DbType.String, FieldName = "Surname", CaptionName = "App.Listform.ListformField.Surname", - Width = 150, + Width = 125, ListOrderNo = 4, Visible = true, IsActive = true, @@ -976,6 +977,27 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep PivotSettingsJson = DefaultPivotSettingsJson }, new ListFormField + { + ListFormCode = listForm.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.String, + FieldName = "WorkHour", + CaptionName = "App.Listform.ListformField.WorkHour", + Width = 150, + ListOrderNo = 6, + LookupJson = LookupQueryValues.DefaultLookupQueryJson(nameof(TableNameEnum.WorkHour), "Name", "Name"), + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + ValidationRuleJson = DefaultValidationRuleRequiredJson, + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(PlatformConsts.IdentityPermissions.Users.Create, PlatformConsts.IdentityPermissions.Users.Default, PlatformConsts.IdentityPermissions.Users.Update, true, true, false), + PivotSettingsJson = DefaultPivotSettingsJson + }, + new ListFormField { ListFormCode = listForm.ListFormCode, RoleId = null, @@ -985,7 +1007,61 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep FieldName = "IsActive", CaptionName = "App.Listform.ListformField.IsActive", Width = 100, - ListOrderNo = 6, + ListOrderNo = 7, + Visible = true, + IsActive = true, + IsDeleted = false, + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(PlatformConsts.IdentityPermissions.Users.Create, PlatformConsts.IdentityPermissions.Users.Default, PlatformConsts.IdentityPermissions.Users.Update, true, true, false), + PivotSettingsJson = DefaultPivotSettingsJson + }, + new ListFormField + { + ListFormCode = listForm.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Boolean, + FieldName = "IsVerified", + CaptionName = "App.Listform.ListformField.IsVerified", + Width = 100, + ListOrderNo = 8, + Visible = true, + IsActive = true, + IsDeleted = false, + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(PlatformConsts.IdentityPermissions.Users.Create, PlatformConsts.IdentityPermissions.Users.Default, PlatformConsts.IdentityPermissions.Users.Update, true, true, false), + PivotSettingsJson = DefaultPivotSettingsJson + }, + new ListFormField + { + ListFormCode = listForm.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Boolean, + FieldName = "EmailConfirmed", + CaptionName = "App.Listform.ListformField.EmailConfirmed", + Width = 100, + ListOrderNo = 9, + Visible = true, + IsActive = true, + IsDeleted = false, + ColumnCustomizationJson = DefaultColumnCustomizationJson, + PermissionJson = DefaultFieldPermissionJson(PlatformConsts.IdentityPermissions.Users.Create, PlatformConsts.IdentityPermissions.Users.Default, PlatformConsts.IdentityPermissions.Users.Update, true, true, false), + PivotSettingsJson = DefaultPivotSettingsJson + }, + new ListFormField + { + ListFormCode = listForm.ListFormCode, + RoleId = null, + UserId = null, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Boolean, + FieldName = "TwoFactorEnabled", + CaptionName = "App.Listform.ListformField.TwoFactorEnabled", + Width = 100, + ListOrderNo = 10, Visible = true, IsActive = true, IsDeleted = false, @@ -1003,7 +1079,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep FieldName = "Password", CaptionName = "App.Listform.ListformField.Password", Width = 100, - ListOrderNo = 7, + ListOrderNo = 11, Visible = false, IsActive = false, IsDeleted = false, diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs index dfa913c..868eeac 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs @@ -3659,7 +3659,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency SourceDbType = DbType.String, FieldName = "Code", CaptionName = "App.Platform.Code", - Width = 300, + Width = 100, ListOrderNo = 2, Visible = true, IsActive = true, @@ -3679,7 +3679,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency SourceDbType = DbType.Int32, FieldName = "DataSourceType", CaptionName = "App.Listform.ListformField.DataSourceType", - Width = 300, + Width = 200, ListOrderNo = 3, Visible = true, IsActive = true, @@ -3704,7 +3704,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency SourceDbType = DbType.String, FieldName = "ConnectionString", CaptionName = "App.Listform.ListformField.ConnectionString", - Width = 250, + Width = 400, ListOrderNo = 5, Visible = true, IsActive = true, diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/PlatformIdentityDataSeeder.cs b/api/src/Sozsoft.Platform.DbMigrator/Seeds/PlatformIdentityDataSeeder.cs index d7c47d4..40956ff 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/PlatformIdentityDataSeeder.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/PlatformIdentityDataSeeder.cs @@ -84,6 +84,7 @@ public class PlatformIdentityDataSeeder : IdentityDataSeeder adminUser.SetIsVerified(true); adminUser.SetRocketUsername(PlatformConsts.AbpIdentity.User.AdminRocketUsernameDefaultValue); adminUser.SetPhoneNumber(PlatformConsts.AbpIdentity.User.AdminPhoneNumberDefaultValue, true); + adminUser.SetWorkHour(PlatformConsts.AbpIdentity.User.AdminWorkHourDefaultValue); (await UserManager.CreateAsync(adminUser, adminPassword, validatePassword: false)).CheckErrors(); result.CreatedAdminUser = true; diff --git a/api/src/Sozsoft.Platform.Domain.Shared/PlatformConsts.cs b/api/src/Sozsoft.Platform.Domain.Shared/PlatformConsts.cs index 39f35df..126d5ed 100644 --- a/api/src/Sozsoft.Platform.Domain.Shared/PlatformConsts.cs +++ b/api/src/Sozsoft.Platform.Domain.Shared/PlatformConsts.cs @@ -95,6 +95,7 @@ public static class PlatformConsts public const string RoleNames = "RoleNames"; public const string IsVerified = "IsVerified"; public const string RocketUsername = "RocketUsername"; + public const string WorkHour = "WorkHour"; public const string UserLockedOutMessage = GroupName + ".UserLockedOutMessage"; public const string InvalidUserNameOrPassword = GroupName + ".InvalidUserNameOrPassword"; @@ -117,6 +118,7 @@ public static class PlatformConsts public const string AdminPasswordDefaultValue = "1q2w3E*"; public const string AdminPhoneNumberDefaultValue = "05449476346"; public const string AdminRocketUsernameDefaultValue = "sedat.ozturk"; + public const string AdminWorkHourDefaultValue = "00:00-23:59"; } public static class OrganizationUnits diff --git a/api/src/Sozsoft.Platform.Domain.Shared/PlatformModuleExtensionConfigurator.cs b/api/src/Sozsoft.Platform.Domain.Shared/PlatformModuleExtensionConfigurator.cs index b26c055..2fe858f 100644 --- a/api/src/Sozsoft.Platform.Domain.Shared/PlatformModuleExtensionConfigurator.cs +++ b/api/src/Sozsoft.Platform.Domain.Shared/PlatformModuleExtensionConfigurator.cs @@ -75,6 +75,15 @@ public static class PlatformModuleExtensionConfigurator { property.DisplayName = new LocalizableString(typeof(PlatformResource), PlatformConsts.AbpIdentity.User.RocketUsername); }); + + user.AddOrUpdateProperty( + PlatformConsts.AbpIdentity.User.WorkHour, + property => + { + property.Attributes.Add(new RequiredAttribute()); + property.Attributes.Add(new DefaultValueAttribute(PlatformConsts.AbpIdentity.User.AdminWorkHourDefaultValue)); + property.DisplayName = new LocalizableString(typeof(PlatformResource), PlatformConsts.AbpIdentity.User.WorkHour); + }); }); }); diff --git a/api/src/Sozsoft.Platform.Domain/Extensions/AbpIdentityUserExtensions.cs b/api/src/Sozsoft.Platform.Domain/Extensions/AbpIdentityUserExtensions.cs index bf9bdc6..d8a6e3b 100644 --- a/api/src/Sozsoft.Platform.Domain/Extensions/AbpIdentityUserExtensions.cs +++ b/api/src/Sozsoft.Platform.Domain/Extensions/AbpIdentityUserExtensions.cs @@ -40,5 +40,15 @@ public static class AbpIdentityUserExtensions { return user.GetProperty(PlatformConsts.AbpIdentity.User.RocketUsername); } + + //Work Hour + public static void SetWorkHour(this IdentityUser user, string workHour) + { + user.SetProperty(PlatformConsts.AbpIdentity.User.WorkHour, workHour); + } + public static string GetWorkHour(this IdentityUser user) + { + return user.GetProperty(PlatformConsts.AbpIdentity.User.WorkHour); + } } diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformEfCoreEntityExtensionMappings.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformEfCoreEntityExtensionMappings.cs index fa8babf..ff41dc5 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformEfCoreEntityExtensionMappings.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformEfCoreEntityExtensionMappings.cs @@ -46,6 +46,15 @@ public static class PlatformEfCoreEntityExtensionMappings } ); + ObjectExtensionManager.Instance + .MapEfCoreProperty( + PlatformConsts.AbpIdentity.User.WorkHour, + (entityBuilder, propertyBuilder) => + { + propertyBuilder.HasDefaultValue(null); + } + ); + ObjectExtensionManager.Instance .MapEfCoreProperty( PlatformConsts.Tenants.IsActive, diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260425160411_Initial.Designer.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260426180109_Initial.Designer.cs similarity index 99% rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260425160411_Initial.Designer.cs rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260426180109_Initial.Designer.cs index 1f951b9..5d3cc36 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260425160411_Initial.Designer.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260426180109_Initial.Designer.cs @@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore; namespace Sozsoft.Platform.Migrations { [DbContext(typeof(PlatformDbContext))] - [Migration("20260425160411_Initial")] + [Migration("20260426180109_Initial")] partial class Initial { /// @@ -5303,6 +5303,9 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(256)") .HasColumnName("UserName"); + b.Property("WorkHour") + .HasColumnType("nvarchar(max)"); + b.HasKey("Id"); b.HasIndex("Email"); diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260425160411_Initial.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260426180109_Initial.cs similarity index 99% rename from api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260425160411_Initial.cs rename to api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260426180109_Initial.cs index 75e3194..a34be3f 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260425160411_Initial.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/20260426180109_Initial.cs @@ -419,6 +419,7 @@ namespace Sozsoft.Platform.Migrations IsVerified = table.Column(type: "bit", nullable: false, defaultValue: false), LoginEndDate = table.Column(type: "datetime2", nullable: true), RocketUsername = table.Column(type: "nvarchar(max)", nullable: true), + WorkHour = table.Column(type: "nvarchar(max)", nullable: true), ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), CreationTime = table.Column(type: "datetime2", nullable: false), diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs index dff100e..9a4635f 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs @@ -5300,6 +5300,9 @@ namespace Sozsoft.Platform.Migrations .HasColumnType("nvarchar(256)") .HasColumnName("UserName"); + b.Property("WorkHour") + .HasColumnType("nvarchar(max)"); + b.HasKey("Id"); b.HasIndex("Email"); diff --git a/api/src/Sozsoft.Platform.EntityFrameworkCore/Seeds/TenantIdentityDataSeeder.cs b/api/src/Sozsoft.Platform.EntityFrameworkCore/Seeds/TenantIdentityDataSeeder.cs index c8062c3..a886f20 100644 --- a/api/src/Sozsoft.Platform.EntityFrameworkCore/Seeds/TenantIdentityDataSeeder.cs +++ b/api/src/Sozsoft.Platform.EntityFrameworkCore/Seeds/TenantIdentityDataSeeder.cs @@ -84,7 +84,8 @@ public class TenantIdentityDataSeeder : IdentityDataSeeder adminUser.SetIsVerified(true); adminUser.SetRocketUsername(PlatformConsts.AbpIdentity.User.AdminRocketUsernameDefaultValue); adminUser.SetPhoneNumber(PlatformConsts.AbpIdentity.User.AdminPhoneNumberDefaultValue, true); - + adminUser.SetWorkHour(PlatformConsts.AbpIdentity.User.AdminWorkHourDefaultValue); + (await UserManager.CreateAsync(adminUser, adminPassword, validatePassword: false)).CheckErrors(); result.CreatedAdminUser = true; diff --git a/api/src/Sozsoft.Platform.HttpApi.Host/Identity/PlatformSignInManager.cs b/api/src/Sozsoft.Platform.HttpApi.Host/Identity/PlatformSignInManager.cs index 8b5c152..b42531f 100644 --- a/api/src/Sozsoft.Platform.HttpApi.Host/Identity/PlatformSignInManager.cs +++ b/api/src/Sozsoft.Platform.HttpApi.Host/Identity/PlatformSignInManager.cs @@ -94,7 +94,7 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager { return new PlatformSignInResult() { IsNotAllowed_TenantIsPassive = true }; } - if (!await CanSignInWorkHourAsync()) + if (!await CanSignInWorkHourAsync(user)) { return new PlatformSignInResult() { IsNotAllowed_WorkHour = true }; } @@ -119,9 +119,16 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager /// /// Used to prevent login outside of defined work hours. /// - private async Task CanSignInWorkHourAsync() + private async Task CanSignInWorkHourAsync(IdentityUser user) { - var workHours = await repositoryWorkHour.GetListAsync(); + var workHourName = user.GetWorkHour(); + + if (string.IsNullOrWhiteSpace(workHourName)) + { + return true; + } + + var workHours = await repositoryWorkHour.GetListAsync(a => a.Name == workHourName); if (workHours.IsNullOrEmpty()) { diff --git a/ui/src/proxy/admin/models.ts b/ui/src/proxy/admin/models.ts index fc4dab4..ece1fc9 100644 --- a/ui/src/proxy/admin/models.ts +++ b/ui/src/proxy/admin/models.ts @@ -124,6 +124,7 @@ export interface UserInfoViewModel extends ExtensibleObject { roles: AssignedRoleViewModel[] branches: AssignedRoleViewModel[] claims: AssignedClaimViewModel[] + workHours: AssignedWorkHourViewModel[] lockUser: boolean lastPasswordChangeTime?: Date | string @@ -134,6 +135,7 @@ export interface UserInfoViewModel extends ExtensibleObject { rocketUsername?: string creationTime: Date | string lastModificationTime: Date | string + workHour?: string } export interface AssignedRoleViewModel { @@ -146,18 +148,22 @@ export interface AssignedBranchViewModel { isAssigned: boolean } -export interface AssignedClaimViewModel -{ - id: string - claimType: string - claimValue: string - isAssigned: boolean +export interface AssignedClaimViewModel { + id: string + claimType: string + claimValue: string + isAssigned: boolean } -export interface UserClaimModel -{ - id?: string - userId?: string - claimType: string - claimValue: string +export interface AssignedWorkHourViewModel { + id: string + name?: string + isAssigned: boolean +} + +export interface UserClaimModel { + id?: string + userId?: string + claimType: string + claimValue: string } diff --git a/ui/src/views/admin/user-management/Details.tsx b/ui/src/views/admin/user-management/Details.tsx index 3655d69..9588661 100644 --- a/ui/src/views/admin/user-management/Details.tsx +++ b/ui/src/views/admin/user-management/Details.tsx @@ -143,8 +143,7 @@ function UserDetails() { setSubmitting(false) }} > - {({ touched, errors, resetForm, isSubmitting, values }) => { - const userRoleNames = values.userRoleNames + {({ isSubmitting, values }) => { const roles = values.roles const branches = values.branches @@ -252,11 +251,7 @@ function UserDetails() { '::Abp.Identity.User.UserInformation.ContactInformation', )} - + @@ -305,9 +302,7 @@ function UserDetails() { onChange={(date: any) => { form.setFieldValue( field.name, - date - ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') - : null, + date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null, ) }} /> @@ -385,8 +380,14 @@ function UserDetails() { setSubmitting(false) }} > - {({ touched, errors, resetForm, isSubmitting, values }) => { - const userRoleNames = values.userRoleNames + {({ isSubmitting, values }) => { + const workHours = values.workHours + + const workHourOptions: SelectBoxOption[] = workHours.map((workHour) => ({ + value: workHour.name, + label: workHour.name, + })) + return (
@@ -488,6 +489,30 @@ function UserDetails() { '::Abp.Identity.User.LockoutManagement.LoginAndLockoutSettings', )} + + + {({ field, form }: FieldProps) => ( +