User Detail ve Work Hour tanımlaması

This commit is contained in:
Sedat Öztürk 2026-04-26 22:05:19 +03:00
parent 5dbd8a0f3f
commit c4671f7051
18 changed files with 258 additions and 50 deletions

View file

@ -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; }
}

View file

@ -39,6 +39,8 @@ public class UserInfoViewModel: ExtensibleObject
public AssignedBranchViewModel[] Branches { get; set; } public AssignedBranchViewModel[] Branches { get; set; }
public AssignedClaimViewModel[] Claims { get; set; } public AssignedClaimViewModel[] Claims { get; set; }
public AssignedWorkHourViewModel[] WorkHours { get; set; }
public bool LockUser { get; set; } public bool LockUser { get; set; }
@ -51,5 +53,5 @@ public class UserInfoViewModel: ExtensibleObject
public string RocketUsername { get; set; } public string RocketUsername { get; set; }
public DateTimeOffset? CreationTime { get; set; } public DateTimeOffset? CreationTime { get; set; }
public DateTimeOffset? LastModificationTime { get; set; } public DateTimeOffset? LastModificationTime { get; set; }
public string WorkHour { get; set; }
} }

View file

@ -26,6 +26,7 @@ public class PlatformIdentityAppService : ApplicationService
public IRepository<IdentityClaimType, Guid> claimTypesRepository { get; } public IRepository<IdentityClaimType, Guid> claimTypesRepository { get; }
public IGuidGenerator guidGenerator { get; } public IGuidGenerator guidGenerator { get; }
public IdentityUserManager UserManager { get; set; } public IdentityUserManager UserManager { get; set; }
public IRepository<WorkHour, Guid> workHourRepository { get; }
public PlatformIdentityAppService( public PlatformIdentityAppService(
IIdentityUserAppService identityUserAppService, IIdentityUserAppService identityUserAppService,
@ -34,11 +35,13 @@ public class PlatformIdentityAppService : ApplicationService
IRepository<Branch, Guid> branchRepository, IRepository<Branch, Guid> branchRepository,
IRepository<BranchUsers, Guid> branchUsersRepository, IRepository<BranchUsers, Guid> branchUsersRepository,
IRepository<IdentityClaimType, Guid> claimTypesRepository, IRepository<IdentityClaimType, Guid> claimTypesRepository,
IRepository<WorkHour, Guid> workHourRepository,
IGuidGenerator guidGenerator IGuidGenerator guidGenerator
) )
{ {
this.IdentityUserAppService = identityUserAppService; this.IdentityUserAppService = identityUserAppService;
this.identityUserRepository = identityUserRepository; this.identityUserRepository = identityUserRepository;
this.workHourRepository = workHourRepository;
this.permissionRepository = permissionRepository; this.permissionRepository = permissionRepository;
this.branchRepository = branchRepository; this.branchRepository = branchRepository;
this.branchUsersRepository = branchUsersRepository; this.branchUsersRepository = branchUsersRepository;
@ -89,6 +92,14 @@ public class PlatformIdentityAppService : ApplicationService
}; };
}).ToArray(); }).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() return new UserInfoViewModel()
{ {
Id = user.Id, Id = user.Id,
@ -98,6 +109,7 @@ public class PlatformIdentityAppService : ApplicationService
Roles = roles, Roles = roles,
Branches = branches, Branches = branches,
Claims = claims, Claims = claims,
WorkHours = workHours,
Email = user.Email, Email = user.Email,
PhoneNumber = user.PhoneNumber, PhoneNumber = user.PhoneNumber,
IsActive = user.IsActive, IsActive = user.IsActive,
@ -116,6 +128,7 @@ public class PlatformIdentityAppService : ApplicationService
AccessFailedCount = user.AccessFailedCount, AccessFailedCount = user.AccessFailedCount,
ShouldChangePasswordOnNextLogin = user.ShouldChangePasswordOnNextLogin, ShouldChangePasswordOnNextLogin = user.ShouldChangePasswordOnNextLogin,
RocketUsername = user.GetRocketUsername(), RocketUsername = user.GetRocketUsername(),
WorkHour = user.GetWorkHour(),
CreationTime = user.CreationTime, CreationTime = user.CreationTime,
LastModificationTime = user.LastModificationTime, LastModificationTime = user.LastModificationTime,
}; };
@ -142,7 +155,7 @@ public class PlatformIdentityAppService : ApplicationService
//LoginEndDate //LoginEndDate
user.SetLoginEndDate(UserInfo.LoginEndDate); user.SetLoginEndDate(UserInfo.LoginEndDate);
user.SetWorkHour(UserInfo.WorkHour);
user.SetIsActive(UserInfo.IsActive); user.SetIsActive(UserInfo.IsActive);
user.SetEmailConfirmed(UserInfo.EmailConfirmed); user.SetEmailConfirmed(UserInfo.EmailConfirmed);
@ -169,6 +182,7 @@ public class PlatformIdentityAppService : ApplicationService
user.SetPhoneNumber(UserInfo.PhoneNumber, user.PhoneNumberConfirmed); user.SetPhoneNumber(UserInfo.PhoneNumber, user.PhoneNumberConfirmed);
user.SetLastPasswordChangeTime(UserInfo.LastPasswordChangeTime); user.SetLastPasswordChangeTime(UserInfo.LastPasswordChangeTime);
user.SetRocketUsername(UserInfo.RocketUsername); user.SetRocketUsername(UserInfo.RocketUsername);
user.SetWorkHour(UserInfo.WorkHour);
await UserManager.UpdateAsync(user); await UserManager.UpdateAsync(user);

View file

@ -2856,6 +2856,12 @@
"en": "Account Lockout Enabled", "en": "Account Lockout Enabled",
"tr": "Hesap Kilitlemesi Etkinleştirme" "tr": "Hesap Kilitlemesi Etkinleştirme"
}, },
{
"resourceName": "Platform",
"key": "Abp.Identity.User.LockoutManagement.WorkHour",
"en": "Work Hour",
"tr": "Çalışma Saati"
},
{ {
"resourceName": "Platform", "resourceName": "Platform",
"key": "Abp.Identity.User.LockoutManagement.AccountLocked", "key": "Abp.Identity.User.LockoutManagement.AccountLocked",
@ -12434,6 +12440,12 @@
} }
], ],
"LanguageFieldTitles": [ "LanguageFieldTitles": [
{
"resourceName": "Platform",
"key": "App.Listform.ListformField.WorkHour",
"en": "Work Hour",
"tr": "Çalışma Saati"
},
{ {
"resourceName": "Platform", "resourceName": "Platform",
"key": "App.Listform.ListformField.Abbreviation", "key": "App.Listform.ListformField.Abbreviation",
@ -13664,6 +13676,24 @@
"en": "Is Active", "en": "Is Active",
"tr": "Aktif" "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", "resourceName": "Platform",
"key": "App.Listform.ListformField.IsAnonymous", "key": "App.Listform.ListformField.IsAnonymous",

View file

@ -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), 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", DeleteCommand = $"UPDATE \"AbpUsers\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\"=@Id",
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(), 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<EditingFormDto>() { EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>() {
new () { Order=1,ColCount=1,ColSpan=1,ItemType="group",Items=[ 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=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=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=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=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=5, DataField="WorkHour", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxSelectBox },
new EditingFormItemDto { Order=6, DataField="IsActive", ColSpan=1, EditorType2=EditorTypes.dxCheckBox }, 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", InsertServiceAddress = "list-form-dynamic-api/user-insert",
@ -822,7 +823,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
}, },
}), }),
FormFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] { 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<WidgetEditDto> WidgetsJson = JsonSerializer.Serialize(new List<WidgetEditDto>
{ {
@ -904,7 +905,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
SourceDbType = DbType.String, SourceDbType = DbType.String,
FieldName = "Email", FieldName = "Email",
CaptionName = "Abp.Account.EmailAddress", CaptionName = "Abp.Account.EmailAddress",
Width = 300, Width = 250,
ListOrderNo = 2, ListOrderNo = 2,
Visible = true, Visible = true,
IsActive = true, IsActive = true,
@ -924,7 +925,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
SourceDbType = DbType.String, SourceDbType = DbType.String,
FieldName = "Name", FieldName = "Name",
CaptionName = "App.Listform.ListformField.Name", CaptionName = "App.Listform.ListformField.Name",
Width = 150, Width = 125,
ListOrderNo = 3, ListOrderNo = 3,
Visible = true, Visible = true,
IsActive = true, IsActive = true,
@ -944,7 +945,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
SourceDbType = DbType.String, SourceDbType = DbType.String,
FieldName = "Surname", FieldName = "Surname",
CaptionName = "App.Listform.ListformField.Surname", CaptionName = "App.Listform.ListformField.Surname",
Width = 150, Width = 125,
ListOrderNo = 4, ListOrderNo = 4,
Visible = true, Visible = true,
IsActive = true, IsActive = true,
@ -976,6 +977,27 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
PivotSettingsJson = DefaultPivotSettingsJson PivotSettingsJson = DefaultPivotSettingsJson
}, },
new ListFormField 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, ListFormCode = listForm.ListFormCode,
RoleId = null, RoleId = null,
@ -985,7 +1007,61 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
FieldName = "IsActive", FieldName = "IsActive",
CaptionName = "App.Listform.ListformField.IsActive", CaptionName = "App.Listform.ListformField.IsActive",
Width = 100, 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, Visible = true,
IsActive = true, IsActive = true,
IsDeleted = false, IsDeleted = false,
@ -1003,7 +1079,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
FieldName = "Password", FieldName = "Password",
CaptionName = "App.Listform.ListformField.Password", CaptionName = "App.Listform.ListformField.Password",
Width = 100, Width = 100,
ListOrderNo = 7, ListOrderNo = 11,
Visible = false, Visible = false,
IsActive = false, IsActive = false,
IsDeleted = false, IsDeleted = false,

View file

@ -3659,7 +3659,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
SourceDbType = DbType.String, SourceDbType = DbType.String,
FieldName = "Code", FieldName = "Code",
CaptionName = "App.Platform.Code", CaptionName = "App.Platform.Code",
Width = 300, Width = 100,
ListOrderNo = 2, ListOrderNo = 2,
Visible = true, Visible = true,
IsActive = true, IsActive = true,
@ -3679,7 +3679,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
SourceDbType = DbType.Int32, SourceDbType = DbType.Int32,
FieldName = "DataSourceType", FieldName = "DataSourceType",
CaptionName = "App.Listform.ListformField.DataSourceType", CaptionName = "App.Listform.ListformField.DataSourceType",
Width = 300, Width = 200,
ListOrderNo = 3, ListOrderNo = 3,
Visible = true, Visible = true,
IsActive = true, IsActive = true,
@ -3704,7 +3704,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
SourceDbType = DbType.String, SourceDbType = DbType.String,
FieldName = "ConnectionString", FieldName = "ConnectionString",
CaptionName = "App.Listform.ListformField.ConnectionString", CaptionName = "App.Listform.ListformField.ConnectionString",
Width = 250, Width = 400,
ListOrderNo = 5, ListOrderNo = 5,
Visible = true, Visible = true,
IsActive = true, IsActive = true,

View file

@ -84,6 +84,7 @@ public class PlatformIdentityDataSeeder : IdentityDataSeeder
adminUser.SetIsVerified(true); adminUser.SetIsVerified(true);
adminUser.SetRocketUsername(PlatformConsts.AbpIdentity.User.AdminRocketUsernameDefaultValue); adminUser.SetRocketUsername(PlatformConsts.AbpIdentity.User.AdminRocketUsernameDefaultValue);
adminUser.SetPhoneNumber(PlatformConsts.AbpIdentity.User.AdminPhoneNumberDefaultValue, true); adminUser.SetPhoneNumber(PlatformConsts.AbpIdentity.User.AdminPhoneNumberDefaultValue, true);
adminUser.SetWorkHour(PlatformConsts.AbpIdentity.User.AdminWorkHourDefaultValue);
(await UserManager.CreateAsync(adminUser, adminPassword, validatePassword: false)).CheckErrors(); (await UserManager.CreateAsync(adminUser, adminPassword, validatePassword: false)).CheckErrors();
result.CreatedAdminUser = true; result.CreatedAdminUser = true;

View file

@ -95,6 +95,7 @@ public static class PlatformConsts
public const string RoleNames = "RoleNames"; public const string RoleNames = "RoleNames";
public const string IsVerified = "IsVerified"; public const string IsVerified = "IsVerified";
public const string RocketUsername = "RocketUsername"; public const string RocketUsername = "RocketUsername";
public const string WorkHour = "WorkHour";
public const string UserLockedOutMessage = GroupName + ".UserLockedOutMessage"; public const string UserLockedOutMessage = GroupName + ".UserLockedOutMessage";
public const string InvalidUserNameOrPassword = GroupName + ".InvalidUserNameOrPassword"; public const string InvalidUserNameOrPassword = GroupName + ".InvalidUserNameOrPassword";
@ -117,6 +118,7 @@ public static class PlatformConsts
public const string AdminPasswordDefaultValue = "1q2w3E*"; public const string AdminPasswordDefaultValue = "1q2w3E*";
public const string AdminPhoneNumberDefaultValue = "05449476346"; public const string AdminPhoneNumberDefaultValue = "05449476346";
public const string AdminRocketUsernameDefaultValue = "sedat.ozturk"; public const string AdminRocketUsernameDefaultValue = "sedat.ozturk";
public const string AdminWorkHourDefaultValue = "00:00-23:59";
} }
public static class OrganizationUnits public static class OrganizationUnits

View file

@ -75,6 +75,15 @@ public static class PlatformModuleExtensionConfigurator
{ {
property.DisplayName = new LocalizableString(typeof(PlatformResource), PlatformConsts.AbpIdentity.User.RocketUsername); property.DisplayName = new LocalizableString(typeof(PlatformResource), PlatformConsts.AbpIdentity.User.RocketUsername);
}); });
user.AddOrUpdateProperty<string>(
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);
});
}); });
}); });

View file

@ -40,5 +40,15 @@ public static class AbpIdentityUserExtensions
{ {
return user.GetProperty<string>(PlatformConsts.AbpIdentity.User.RocketUsername); return user.GetProperty<string>(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<string>(PlatformConsts.AbpIdentity.User.WorkHour);
}
} }

View file

@ -46,6 +46,15 @@ public static class PlatformEfCoreEntityExtensionMappings
} }
); );
ObjectExtensionManager.Instance
.MapEfCoreProperty<IdentityUser, string>(
PlatformConsts.AbpIdentity.User.WorkHour,
(entityBuilder, propertyBuilder) =>
{
propertyBuilder.HasDefaultValue(null);
}
);
ObjectExtensionManager.Instance ObjectExtensionManager.Instance
.MapEfCoreProperty<Tenant, bool>( .MapEfCoreProperty<Tenant, bool>(
PlatformConsts.Tenants.IsActive, PlatformConsts.Tenants.IsActive,

View file

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace Sozsoft.Platform.Migrations namespace Sozsoft.Platform.Migrations
{ {
[DbContext(typeof(PlatformDbContext))] [DbContext(typeof(PlatformDbContext))]
[Migration("20260425160411_Initial")] [Migration("20260426180109_Initial")]
partial class Initial partial class Initial
{ {
/// <inheritdoc /> /// <inheritdoc />
@ -5303,6 +5303,9 @@ namespace Sozsoft.Platform.Migrations
.HasColumnType("nvarchar(256)") .HasColumnType("nvarchar(256)")
.HasColumnName("UserName"); .HasColumnName("UserName");
b.Property<string>("WorkHour")
.HasColumnType("nvarchar(max)");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("Email"); b.HasIndex("Email");

View file

@ -419,6 +419,7 @@ namespace Sozsoft.Platform.Migrations
IsVerified = table.Column<bool>(type: "bit", nullable: false, defaultValue: false), IsVerified = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
LoginEndDate = table.Column<DateTime>(type: "datetime2", nullable: true), LoginEndDate = table.Column<DateTime>(type: "datetime2", nullable: true),
RocketUsername = table.Column<string>(type: "nvarchar(max)", nullable: true), RocketUsername = table.Column<string>(type: "nvarchar(max)", nullable: true),
WorkHour = table.Column<string>(type: "nvarchar(max)", nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false), ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false), ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false), CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),

View file

@ -5300,6 +5300,9 @@ namespace Sozsoft.Platform.Migrations
.HasColumnType("nvarchar(256)") .HasColumnType("nvarchar(256)")
.HasColumnName("UserName"); .HasColumnName("UserName");
b.Property<string>("WorkHour")
.HasColumnType("nvarchar(max)");
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("Email"); b.HasIndex("Email");

View file

@ -84,7 +84,8 @@ public class TenantIdentityDataSeeder : IdentityDataSeeder
adminUser.SetIsVerified(true); adminUser.SetIsVerified(true);
adminUser.SetRocketUsername(PlatformConsts.AbpIdentity.User.AdminRocketUsernameDefaultValue); adminUser.SetRocketUsername(PlatformConsts.AbpIdentity.User.AdminRocketUsernameDefaultValue);
adminUser.SetPhoneNumber(PlatformConsts.AbpIdentity.User.AdminPhoneNumberDefaultValue, true); adminUser.SetPhoneNumber(PlatformConsts.AbpIdentity.User.AdminPhoneNumberDefaultValue, true);
adminUser.SetWorkHour(PlatformConsts.AbpIdentity.User.AdminWorkHourDefaultValue);
(await UserManager.CreateAsync(adminUser, adminPassword, validatePassword: false)).CheckErrors(); (await UserManager.CreateAsync(adminUser, adminPassword, validatePassword: false)).CheckErrors();
result.CreatedAdminUser = true; result.CreatedAdminUser = true;

View file

@ -94,7 +94,7 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
{ {
return new PlatformSignInResult() { IsNotAllowed_TenantIsPassive = true }; return new PlatformSignInResult() { IsNotAllowed_TenantIsPassive = true };
} }
if (!await CanSignInWorkHourAsync()) if (!await CanSignInWorkHourAsync(user))
{ {
return new PlatformSignInResult() { IsNotAllowed_WorkHour = true }; return new PlatformSignInResult() { IsNotAllowed_WorkHour = true };
} }
@ -119,9 +119,16 @@ public class PlatformSignInManager : AbpSignInManager, IPlatformSignInManager
/// <summary> /// <summary>
/// Used to prevent login outside of defined work hours. /// Used to prevent login outside of defined work hours.
/// </summary> /// </summary>
private async Task<bool> CanSignInWorkHourAsync() private async Task<bool> 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()) if (workHours.IsNullOrEmpty())
{ {

View file

@ -124,6 +124,7 @@ export interface UserInfoViewModel extends ExtensibleObject {
roles: AssignedRoleViewModel[] roles: AssignedRoleViewModel[]
branches: AssignedRoleViewModel[] branches: AssignedRoleViewModel[]
claims: AssignedClaimViewModel[] claims: AssignedClaimViewModel[]
workHours: AssignedWorkHourViewModel[]
lockUser: boolean lockUser: boolean
lastPasswordChangeTime?: Date | string lastPasswordChangeTime?: Date | string
@ -134,6 +135,7 @@ export interface UserInfoViewModel extends ExtensibleObject {
rocketUsername?: string rocketUsername?: string
creationTime: Date | string creationTime: Date | string
lastModificationTime: Date | string lastModificationTime: Date | string
workHour?: string
} }
export interface AssignedRoleViewModel { export interface AssignedRoleViewModel {
@ -146,18 +148,22 @@ export interface AssignedBranchViewModel {
isAssigned: boolean isAssigned: boolean
} }
export interface AssignedClaimViewModel export interface AssignedClaimViewModel {
{ id: string
id: string claimType: string
claimType: string claimValue: string
claimValue: string isAssigned: boolean
isAssigned: boolean
} }
export interface UserClaimModel export interface AssignedWorkHourViewModel {
{ id: string
id?: string name?: string
userId?: string isAssigned: boolean
claimType: string }
claimValue: string
export interface UserClaimModel {
id?: string
userId?: string
claimType: string
claimValue: string
} }

View file

@ -143,8 +143,7 @@ function UserDetails() {
setSubmitting(false) setSubmitting(false)
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => { {({ isSubmitting, values }) => {
const userRoleNames = values.userRoleNames
const roles = values.roles const roles = values.roles
const branches = values.branches const branches = values.branches
@ -252,11 +251,7 @@ function UserDetails() {
'::Abp.Identity.User.UserInformation.ContactInformation', '::Abp.Identity.User.UserInformation.ContactInformation',
)} )}
</h6> </h6>
<FormItem <FormItem label={translate('::Abp.Account.EmailAddress')}>
label={translate(
'::Abp.Account.EmailAddress',
)}
>
<Field <Field
type="text" type="text"
disabled disabled
@ -271,7 +266,9 @@ function UserDetails() {
<Field <Field
type="text" type="text"
name="phoneNumber" name="phoneNumber"
placeholder={translate('::Abp.Identity.User.UserInformation.PhoneNumber')} placeholder={translate(
'::Abp.Identity.User.UserInformation.PhoneNumber',
)}
component={Input} component={Input}
/> />
</FormItem> </FormItem>
@ -305,9 +302,7 @@ function UserDetails() {
onChange={(date: any) => { onChange={(date: any) => {
form.setFieldValue( form.setFieldValue(
field.name, field.name,
date date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null,
? dayjs(date).format('YYYY-MM-DDTHH:mm:ss')
: null,
) )
}} }}
/> />
@ -385,8 +380,14 @@ function UserDetails() {
setSubmitting(false) setSubmitting(false)
}} }}
> >
{({ touched, errors, resetForm, isSubmitting, values }) => { {({ isSubmitting, values }) => {
const userRoleNames = values.userRoleNames const workHours = values.workHours
const workHourOptions: SelectBoxOption[] = workHours.map((workHour) => ({
value: workHour.name,
label: workHour.name,
}))
return ( return (
<Form> <Form>
<div className="w-1/2"> <div className="w-1/2">
@ -488,6 +489,30 @@ function UserDetails() {
'::Abp.Identity.User.LockoutManagement.LoginAndLockoutSettings', '::Abp.Identity.User.LockoutManagement.LoginAndLockoutSettings',
)} )}
</h6> </h6>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate('::Abp.Identity.User.LockoutManagement.WorkHour')}
>
<Field type="text" name="workHour">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={workHourOptions}
isClearable={true}
value={workHourOptions.filter(
(option) => option.value === values.workHour,
)}
onChange={(option) =>
form.setFieldValue(field.name, option?.value)
}
/>
)}
</Field>
</FormItem>
<FormItem <FormItem
layout="horizontal" layout="horizontal"
labelClass="!justify-start" labelClass="!justify-start"
@ -508,9 +533,7 @@ function UserDetails() {
onChange={(date) => { onChange={(date) => {
form.setFieldValue( form.setFieldValue(
field.name, field.name,
date date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null,
? dayjs(date).format('YYYY-MM-DDTHH:mm:ss')
: null,
) )
}} }}
/> />
@ -572,9 +595,7 @@ function UserDetails() {
onChange={(date) => { onChange={(date) => {
form.setFieldValue( form.setFieldValue(
field.name, field.name,
date date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null,
? dayjs(date).format('YYYY-MM-DDTHH:mm:ss')
: null,
) )
}} }}
/> />