From 08f50f6e115a9ebf02f810a092aa56b40988b5f3 Mon Sep 17 00:00:00 2001 From: kotcheshir73 Date: Fri, 26 Mar 2021 20:09:52 +0400 Subject: [PATCH] =?UTF-8?q?=D0=A1=D1=82=D0=B0=D1=80=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=D1=8B=D0=B9=20=D0=BD=D0=B0=D0=B1=D0=BE=D1=80:=20=D1=88=D0=B0?= =?UTF-8?q?=D0=B1=D0=BB=D0=BE=D0=BD=D1=8B=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA?= =?UTF-8?q?,=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20=D1=81=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D1=8F=D0=BC=D0=B8,=20=D0=B1=D0=B0=D0=B7=D0=B0=20=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D0=BD=D1=8B=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Attributes/ViewModelPropertyAttribute.cs | 36 + .../OperationResultModel.cs | 40 +- .../ViewModels/ElementViewModel.cs | 4 +- .../Common/DatabaseCore/DatabaseContext.cs | 33 + .../Common/DatabaseCore/DatabaseCore.csproj | 21 + .../Common/DatabaseCore/DatabaseManager.cs | 13 + ...210326072923_AddSecurityModels.Designer.cs | 211 ++ .../20210326072923_AddSecurityModels.cs | 146 ++ .../DatabaseContextModelSnapshot.cs | 209 ++ .../Common/DatabaseCore/Models/BaseEntity.cs | 28 + .../Common/DatabaseCore/Models/IdEntity.cs | 24 + .../DatabaseCore/Models/Security/Access.cs | 38 + .../Models/Security/EnviromentSetting.cs | 21 + .../DatabaseCore/Models/Security/Role.cs | 33 + .../DatabaseCore/Models/Security/User.cs | 63 + .../DatabaseCore/Models/Security/UserRole.cs | 30 + .../Scripts/SecureMigrationScript.cs | 57 + .../Common/DatabaseCore/SecurityManager.cs | 64 + .../Attributes/EntityDependencyAttribute.cs | 39 + .../Attributes/EntityDescriptionAttribute.cs | 32 + .../Attributes/MapConfigurationAttribute.cs | 32 + .../Attributes/ViewModelPropertyAttribute.cs | 68 + .../BindingModels/AccessBindingModel.cs | 20 + .../BindingModels/GetBindingModel.cs | 30 + .../BindingModels/SetBindingModel.cs | 15 + .../BusinessLogics/BusinessLogicCore.cs | 226 +++ .../ModelTools/BusinessLogics/Mapper.cs | 100 + .../BusinessLogics/ServiceProviderLoader.cs | 79 + .../UnityContainerConfigurator.cs | 43 + .../ModelTools/Enums/AccessOperation.cs | 100 + .../Common/ModelTools/Enums/AccessType.cs | 34 + .../Enums/ResultServiceStatusCode.cs | 38 + .../ModelTools/Extensions/StringExtension.cs | 28 + .../ModelTools/Interfaces/IEntityService.cs | 41 + .../Interfaces/ILoaderExtensions.cs | 13 + .../ModelTools/Interfaces/ISecurityManager.cs | 23 + .../Common/ModelTools/ModelTools.csproj | 11 + .../OperationResultModel.cs | 114 ++ .../ModelTools/ViewModels/ElementViewModel.cs | 15 + .../ModelTools/ViewModels/ListViewModel.cs | 16 + DepartmentPortal/DepartmentPortal.sln | 41 +- .../DepartmentPortal.config | 4 + .../DepartmentPortalDesctop.csproj | 27 + .../FormEnter.Designer.cs | 119 ++ .../DepartmentPortalDesctop/FormEnter.cs | 32 + .../DepartmentPortalDesctop/FormEnter.resx | 60 + .../FormMain.Designer.cs | 125 ++ .../DepartmentPortalDesctop/FormMain.cs | 22 + .../DepartmentPortalDesctop/FormMain.resx | 60 + .../DepartmentPortalDesctop/Program.cs | 33 + .../Extensions/net5.0/DatabaseCore.dll | Bin 0 -> 47616 bytes .../Extensions/net5.0/ModelTools.dll | Bin 0 -> 19968 bytes .../net5.0/SecurityBusinessLogic.dll | Bin 0 -> 19968 bytes .../net5.0/SecurityImplementation.deps.json | 1782 +++++++++++++++++ .../net5.0/SecurityImplementation.dll | Bin 0 -> 22016 bytes .../net5.0/ref/SecurityImplementation.dll | Bin 0 -> 7168 bytes .../BindingModels/AccessBindingModels.cs | 28 + .../EnviromentSettingBindingModels.cs | 25 + .../BindingModels/RoleBindingModels.cs | 22 + .../BindingModels/UserBindingModels.cs | 49 + .../BusinessLogics/AccessBusinessLogic.cs | 21 + .../EnviromentSettingBusinessLogic.cs | 22 + .../BusinessLogics/RoleBusinessLogic.cs | 21 + .../BusinessLogics/UserBusinessLogic.cs | 21 + .../BusinessLogics/UserManager.cs | 223 +++ .../Interfaces/IAccessService.cs | 10 + .../Interfaces/IEnviromentSettingService.cs | 10 + .../Interfaces/IRoleService.cs | 10 + .../Interfaces/IUserService.cs | 10 + .../SecurityBusinessLogic.csproj | 15 + .../ViewModels/AccessViewModels.cs | 42 + .../ViewModels/EnviromentSettingViewModels.cs | 26 + .../ViewModels/RoleViewModels.cs | 26 + .../ViewModels/UserViewModels.cs | 62 + .../Implementations/AccessService.cs | 131 ++ .../EnviromentSettingService.cs | 114 ++ .../Implementations/RoleService.cs | 150 ++ .../Implementations/UserService.cs | 171 ++ .../SecurityImplementation.csproj | 16 + .../SecurityLoaderExtensions.cs | 24 + 80 files changed, 5696 insertions(+), 46 deletions(-) create mode 100644 DepartmentPortal/Common/CommonTools/Attributes/ViewModelPropertyAttribute.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/DatabaseContext.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/DatabaseCore.csproj create mode 100644 DepartmentPortal/Common/DatabaseCore/DatabaseManager.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/Migrations/20210326072923_AddSecurityModels.Designer.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/Migrations/20210326072923_AddSecurityModels.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/Migrations/DatabaseContextModelSnapshot.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/Models/BaseEntity.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/Models/IdEntity.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/Models/Security/Access.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/Models/Security/EnviromentSetting.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/Models/Security/Role.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/Models/Security/User.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/Models/Security/UserRole.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/Scripts/SecureMigrationScript.cs create mode 100644 DepartmentPortal/Common/DatabaseCore/SecurityManager.cs create mode 100644 DepartmentPortal/Common/ModelTools/Attributes/EntityDependencyAttribute.cs create mode 100644 DepartmentPortal/Common/ModelTools/Attributes/EntityDescriptionAttribute.cs create mode 100644 DepartmentPortal/Common/ModelTools/Attributes/MapConfigurationAttribute.cs create mode 100644 DepartmentPortal/Common/ModelTools/Attributes/ViewModelPropertyAttribute.cs create mode 100644 DepartmentPortal/Common/ModelTools/BindingModels/AccessBindingModel.cs create mode 100644 DepartmentPortal/Common/ModelTools/BindingModels/GetBindingModel.cs create mode 100644 DepartmentPortal/Common/ModelTools/BindingModels/SetBindingModel.cs create mode 100644 DepartmentPortal/Common/ModelTools/BusinessLogics/BusinessLogicCore.cs create mode 100644 DepartmentPortal/Common/ModelTools/BusinessLogics/Mapper.cs create mode 100644 DepartmentPortal/Common/ModelTools/BusinessLogics/ServiceProviderLoader.cs create mode 100644 DepartmentPortal/Common/ModelTools/BusinessLogics/UnityContainerConfigurator.cs create mode 100644 DepartmentPortal/Common/ModelTools/Enums/AccessOperation.cs create mode 100644 DepartmentPortal/Common/ModelTools/Enums/AccessType.cs create mode 100644 DepartmentPortal/Common/ModelTools/Enums/ResultServiceStatusCode.cs create mode 100644 DepartmentPortal/Common/ModelTools/Extensions/StringExtension.cs create mode 100644 DepartmentPortal/Common/ModelTools/Interfaces/IEntityService.cs create mode 100644 DepartmentPortal/Common/ModelTools/Interfaces/ILoaderExtensions.cs create mode 100644 DepartmentPortal/Common/ModelTools/Interfaces/ISecurityManager.cs create mode 100644 DepartmentPortal/Common/ModelTools/ModelTools.csproj create mode 100644 DepartmentPortal/Common/ModelTools/OperationResultModels/OperationResultModel.cs create mode 100644 DepartmentPortal/Common/ModelTools/ViewModels/ElementViewModel.cs create mode 100644 DepartmentPortal/Common/ModelTools/ViewModels/ListViewModel.cs create mode 100644 DepartmentPortal/DepartmentPortalDesctop/DepartmentPortal.config create mode 100644 DepartmentPortal/DepartmentPortalDesctop/DepartmentPortalDesctop.csproj create mode 100644 DepartmentPortal/DepartmentPortalDesctop/FormEnter.Designer.cs create mode 100644 DepartmentPortal/DepartmentPortalDesctop/FormEnter.cs create mode 100644 DepartmentPortal/DepartmentPortalDesctop/FormEnter.resx create mode 100644 DepartmentPortal/DepartmentPortalDesctop/FormMain.Designer.cs create mode 100644 DepartmentPortal/DepartmentPortalDesctop/FormMain.cs create mode 100644 DepartmentPortal/DepartmentPortalDesctop/FormMain.resx create mode 100644 DepartmentPortal/DepartmentPortalDesctop/Program.cs create mode 100644 DepartmentPortal/Extensions/net5.0/DatabaseCore.dll create mode 100644 DepartmentPortal/Extensions/net5.0/ModelTools.dll create mode 100644 DepartmentPortal/Extensions/net5.0/SecurityBusinessLogic.dll create mode 100644 DepartmentPortal/Extensions/net5.0/SecurityImplementation.deps.json create mode 100644 DepartmentPortal/Extensions/net5.0/SecurityImplementation.dll create mode 100644 DepartmentPortal/Extensions/net5.0/ref/SecurityImplementation.dll create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/AccessBindingModels.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/EnviromentSettingBindingModels.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/RoleBindingModels.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/UserBindingModels.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/AccessBusinessLogic.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/EnviromentSettingBusinessLogic.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/RoleBusinessLogic.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/UserBusinessLogic.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/UserManager.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IAccessService.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IEnviromentSettingService.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IRoleService.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IUserService.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/SecurityBusinessLogic.csproj create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/AccessViewModels.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/EnviromentSettingViewModels.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/RoleViewModels.cs create mode 100644 DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/UserViewModels.cs create mode 100644 DepartmentPortal/Security/SecurityImplementation/Implementations/AccessService.cs create mode 100644 DepartmentPortal/Security/SecurityImplementation/Implementations/EnviromentSettingService.cs create mode 100644 DepartmentPortal/Security/SecurityImplementation/Implementations/RoleService.cs create mode 100644 DepartmentPortal/Security/SecurityImplementation/Implementations/UserService.cs create mode 100644 DepartmentPortal/Security/SecurityImplementation/SecurityImplementation.csproj create mode 100644 DepartmentPortal/Security/SecurityImplementation/SecurityLoaderExtensions.cs diff --git a/DepartmentPortal/Common/CommonTools/Attributes/ViewModelPropertyAttribute.cs b/DepartmentPortal/Common/CommonTools/Attributes/ViewModelPropertyAttribute.cs new file mode 100644 index 0000000..3e2ea0c --- /dev/null +++ b/DepartmentPortal/Common/CommonTools/Attributes/ViewModelPropertyAttribute.cs @@ -0,0 +1,36 @@ +using System; + +namespace CommonTools.Attributes +{ + [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] + public class ViewModelPropertyAttribute : Attribute + { + /// + /// Название на форме + /// + public string DisplayName { get; set; } + + /// + /// Скрывать или нет + /// + public bool IsHide { get; set; } + + /// + /// Ширина колонки + /// + public int ColumnWidth { get; set; } + + /// + /// Конструктор + /// + /// Название на форме + /// Скрывать или нет + /// Ширина колонки + public ViewModelPropertyAttribute(string displayName, int columnWidth, bool isHide = false) + { + DisplayName = displayName; + ColumnWidth = columnWidth; + IsHide = isHide; + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/CommonTools/OperationResultModels/OperationResultModel.cs b/DepartmentPortal/Common/CommonTools/OperationResultModels/OperationResultModel.cs index 93d1616..ab9056b 100644 --- a/DepartmentPortal/Common/CommonTools/OperationResultModels/OperationResultModel.cs +++ b/DepartmentPortal/Common/CommonTools/OperationResultModels/OperationResultModel.cs @@ -25,7 +25,7 @@ namespace CommonTools.OperationResultModels public List<(string Title, string Message)> Errors { get; private set; } /// - /// Какой-то объект, получаемый по результатам операции (например, id) + /// Объект, получаемый по результатам операции /// public object Result { get; private set; } @@ -38,42 +38,4 @@ namespace CommonTools.OperationResultModels StatusCode = ResultServiceStatusCode.Success; } } - - /// - /// Результат любой операции - /// - /// - public class OperationResultModel - where T : ElementViewModel - { - /// - /// Успешность операции - /// - public bool IsSucceeded { get; private set; } - - /// - /// Статус операции - /// - public ResultServiceStatusCode StatusCode { get; private set; } - - /// - /// Спсиок ошибок - /// - public List> Errors { get; private set; } - - /// - /// Какой-то объект, получаемый по результатам операции (например, id) - /// - public T Result { get; private set; } - - /// - /// Конструктор по умолчанию - /// - public OperationResultModel() - { - Errors = new List>(); - IsSucceeded = true; - StatusCode = 0; - } - } } \ No newline at end of file diff --git a/DepartmentPortal/Common/CommonTools/ViewModels/ElementViewModel.cs b/DepartmentPortal/Common/CommonTools/ViewModels/ElementViewModel.cs index 1106ed9..1479933 100644 --- a/DepartmentPortal/Common/CommonTools/ViewModels/ElementViewModel.cs +++ b/DepartmentPortal/Common/CommonTools/ViewModels/ElementViewModel.cs @@ -1,4 +1,5 @@ -using System; +using CommonTools.Attributes; +using System; namespace CommonTools.ViewModels { @@ -7,6 +8,7 @@ namespace CommonTools.ViewModels /// public class ElementViewModel { + [ViewModelProperty("Идентификатор", 1, true)] public Guid Id { get; set; } } } \ No newline at end of file diff --git a/DepartmentPortal/Common/DatabaseCore/DatabaseContext.cs b/DepartmentPortal/Common/DatabaseCore/DatabaseContext.cs new file mode 100644 index 0000000..7ef1c95 --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/DatabaseContext.cs @@ -0,0 +1,33 @@ +using DatabaseCore.Models.Security; +using Microsoft.EntityFrameworkCore; + +namespace DatabaseCore +{ + public class DatabaseContext : DbContext + { + public DatabaseContext() : base() { } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (optionsBuilder.IsConfigured == false) + { +#if RELEASE + var connectionString = ModelTools.ServiceProvider.ServiceProviderLoader.GetConfigData("connectionString"); + optionsBuilder.UseSqlServer(connectionString); +#endif + +#if DEBUG + optionsBuilder.UseSqlServer(@"Data Source=CHESHIR\SQLEXPRESS;Initial Catalog=DepartmentDatabasePortal;persist security info=True;user id=admin;password=cheshirSA123;MultipleActiveResultSets=True;"); +#endif + } + base.OnConfiguring(optionsBuilder); + } + + + public virtual DbSet Accesses { set; get; } + public virtual DbSet EnviromentSettings { set; get; } + public virtual DbSet Roles { set; get; } + public virtual DbSet Users { set; get; } + public virtual DbSet UserRoles { set; get; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/DatabaseCore/DatabaseCore.csproj b/DepartmentPortal/Common/DatabaseCore/DatabaseCore.csproj new file mode 100644 index 0000000..b5aca4a --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/DatabaseCore.csproj @@ -0,0 +1,21 @@ + + + + net5.0 + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/DepartmentPortal/Common/DatabaseCore/DatabaseManager.cs b/DepartmentPortal/Common/DatabaseCore/DatabaseManager.cs new file mode 100644 index 0000000..6bdd322 --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/DatabaseManager.cs @@ -0,0 +1,13 @@ +namespace DatabaseCore +{ + /// + /// Работа с БД + /// + public static class DatabaseManager + { + /// + /// Получение объекта от класса DbContext + /// + public static DatabaseContext GetContext => new(); + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/DatabaseCore/Migrations/20210326072923_AddSecurityModels.Designer.cs b/DepartmentPortal/Common/DatabaseCore/Migrations/20210326072923_AddSecurityModels.Designer.cs new file mode 100644 index 0000000..e9c7b52 --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/Migrations/20210326072923_AddSecurityModels.Designer.cs @@ -0,0 +1,211 @@ +// +using System; +using DatabaseCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace DatabaseCore.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20210326072923_AddSecurityModels")] + partial class AddSecurityModels + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.4") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("DatabaseCore.Models.Security.Access", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AccessType") + .HasColumnType("int"); + + b.Property("DateCreate") + .HasColumnType("datetime2"); + + b.Property("DateDelete") + .HasColumnType("datetime2"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Operation") + .HasColumnType("int"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("Accesses"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.EnviromentSetting", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Key") + .HasColumnType("nvarchar(max)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("EnviromentSettings"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.Role", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("DateCreate") + .HasColumnType("datetime2"); + + b.Property("DateDelete") + .HasColumnType("datetime2"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("RoleName") + .HasColumnType("nvarchar(max)"); + + b.Property("RolePriority") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.User", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Avatar") + .HasColumnType("varbinary(max)"); + + b.Property("CountAttempt") + .HasColumnType("int"); + + b.Property("DateBanned") + .HasColumnType("datetime2"); + + b.Property("DateCreate") + .HasColumnType("datetime2"); + + b.Property("DateDelete") + .HasColumnType("datetime2"); + + b.Property("DateLastVisit") + .HasColumnType("datetime2"); + + b.Property("DateLocked") + .HasColumnType("datetime2"); + + b.Property("EmployeeId") + .HasColumnType("uniqueidentifier"); + + b.Property("IsBanned") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("LecturerId") + .HasColumnType("uniqueidentifier"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("StudentId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.UserRole", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.Access", b => + { + b.HasOne("DatabaseCore.Models.Security.Role", "Role") + .WithMany("Access") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.UserRole", b => + { + b.HasOne("DatabaseCore.Models.Security.Role", "Role") + .WithMany("UserRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DatabaseCore.Models.Security.User", "User") + .WithMany("UserRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.Role", b => + { + b.Navigation("Access"); + + b.Navigation("UserRoles"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.User", b => + { + b.Navigation("UserRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/DepartmentPortal/Common/DatabaseCore/Migrations/20210326072923_AddSecurityModels.cs b/DepartmentPortal/Common/DatabaseCore/Migrations/20210326072923_AddSecurityModels.cs new file mode 100644 index 0000000..04aafc8 --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/Migrations/20210326072923_AddSecurityModels.cs @@ -0,0 +1,146 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace DatabaseCore.Migrations +{ + public partial class AddSecurityModels : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "EnviromentSettings", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Key = table.Column(type: "nvarchar(max)", nullable: true), + Value = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EnviromentSettings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Roles", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + RoleName = table.Column(type: "nvarchar(max)", nullable: true), + RolePriority = table.Column(type: "int", nullable: false), + DateCreate = table.Column(type: "datetime2", nullable: false), + DateDelete = table.Column(type: "datetime2", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Roles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + UserName = table.Column(type: "nvarchar(max)", nullable: true), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + StudentId = table.Column(type: "uniqueidentifier", nullable: true), + LecturerId = table.Column(type: "uniqueidentifier", nullable: true), + EmployeeId = table.Column(type: "uniqueidentifier", nullable: true), + Avatar = table.Column(type: "varbinary(max)", nullable: true), + DateLastVisit = table.Column(type: "datetime2", nullable: true), + IsBanned = table.Column(type: "bit", nullable: false), + DateBanned = table.Column(type: "datetime2", nullable: true), + CountAttempt = table.Column(type: "int", nullable: false), + DateLocked = table.Column(type: "datetime2", nullable: true), + DateCreate = table.Column(type: "datetime2", nullable: false), + DateDelete = table.Column(type: "datetime2", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Accesses", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + RoleId = table.Column(type: "uniqueidentifier", nullable: false), + Operation = table.Column(type: "int", nullable: false), + AccessType = table.Column(type: "int", nullable: false), + DateCreate = table.Column(type: "datetime2", nullable: false), + DateDelete = table.Column(type: "datetime2", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Accesses", x => x.Id); + table.ForeignKey( + name: "FK_Accesses_Roles_RoleId", + column: x => x.RoleId, + principalTable: "Roles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserRoles", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + RoleId = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "uniqueidentifier", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserRoles", x => x.Id); + table.ForeignKey( + name: "FK_UserRoles_Roles_RoleId", + column: x => x.RoleId, + principalTable: "Roles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_UserRoles_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Accesses_RoleId", + table: "Accesses", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_UserRoles_RoleId", + table: "UserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_UserRoles_UserId", + table: "UserRoles", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Accesses"); + + migrationBuilder.DropTable( + name: "EnviromentSettings"); + + migrationBuilder.DropTable( + name: "UserRoles"); + + migrationBuilder.DropTable( + name: "Roles"); + + migrationBuilder.DropTable( + name: "Users"); + } + } +} diff --git a/DepartmentPortal/Common/DatabaseCore/Migrations/DatabaseContextModelSnapshot.cs b/DepartmentPortal/Common/DatabaseCore/Migrations/DatabaseContextModelSnapshot.cs new file mode 100644 index 0000000..fe854ca --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/Migrations/DatabaseContextModelSnapshot.cs @@ -0,0 +1,209 @@ +// +using System; +using DatabaseCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace DatabaseCore.Migrations +{ + [DbContext(typeof(DatabaseContext))] + partial class DatabaseContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.4") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("DatabaseCore.Models.Security.Access", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AccessType") + .HasColumnType("int"); + + b.Property("DateCreate") + .HasColumnType("datetime2"); + + b.Property("DateDelete") + .HasColumnType("datetime2"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Operation") + .HasColumnType("int"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("Accesses"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.EnviromentSetting", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Key") + .HasColumnType("nvarchar(max)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("EnviromentSettings"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.Role", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("DateCreate") + .HasColumnType("datetime2"); + + b.Property("DateDelete") + .HasColumnType("datetime2"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("RoleName") + .HasColumnType("nvarchar(max)"); + + b.Property("RolePriority") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.User", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Avatar") + .HasColumnType("varbinary(max)"); + + b.Property("CountAttempt") + .HasColumnType("int"); + + b.Property("DateBanned") + .HasColumnType("datetime2"); + + b.Property("DateCreate") + .HasColumnType("datetime2"); + + b.Property("DateDelete") + .HasColumnType("datetime2"); + + b.Property("DateLastVisit") + .HasColumnType("datetime2"); + + b.Property("DateLocked") + .HasColumnType("datetime2"); + + b.Property("EmployeeId") + .HasColumnType("uniqueidentifier"); + + b.Property("IsBanned") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("LecturerId") + .HasColumnType("uniqueidentifier"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("StudentId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.UserRole", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("UserId"); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.Access", b => + { + b.HasOne("DatabaseCore.Models.Security.Role", "Role") + .WithMany("Access") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.UserRole", b => + { + b.HasOne("DatabaseCore.Models.Security.Role", "Role") + .WithMany("UserRoles") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("DatabaseCore.Models.Security.User", "User") + .WithMany("UserRoles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.Role", b => + { + b.Navigation("Access"); + + b.Navigation("UserRoles"); + }); + + modelBuilder.Entity("DatabaseCore.Models.Security.User", b => + { + b.Navigation("UserRoles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/DepartmentPortal/Common/DatabaseCore/Models/BaseEntity.cs b/DepartmentPortal/Common/DatabaseCore/Models/BaseEntity.cs new file mode 100644 index 0000000..4819b48 --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/Models/BaseEntity.cs @@ -0,0 +1,28 @@ +using System; +using System.Runtime.Serialization; + +namespace DatabaseCore.Models +{ + /// + /// Базовый набор для сущности + /// + [DataContract] + public class BaseEntity : IdEntity + { + [DataMember] + public DateTime DateCreate { get; set; } + + [DataMember] + public DateTime? DateDelete { get; set; } + + [DataMember] + public bool IsDeleted { get; set; } + + public BaseEntity() : base() + { + DateCreate = DateTime.Now; + DateDelete = null; + IsDeleted = false; + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/DatabaseCore/Models/IdEntity.cs b/DepartmentPortal/Common/DatabaseCore/Models/IdEntity.cs new file mode 100644 index 0000000..eb15cd0 --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/Models/IdEntity.cs @@ -0,0 +1,24 @@ +using ModelTools.Attributes; +using System; +using System.ComponentModel.DataAnnotations.Schema; +using System.Runtime.Serialization; + +namespace DatabaseCore.Models +{ + /// + /// Тип Id для всеъ сущностей + /// + [DataContract] + public class IdEntity + { + [DataMember] + [DatabaseGenerated(DatabaseGeneratedOption.None)] + [MapConfiguration("Id")] + public Guid Id { get; set; } + + public IdEntity() : base() + { + Id = Guid.NewGuid(); + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/DatabaseCore/Models/Security/Access.cs b/DepartmentPortal/Common/DatabaseCore/Models/Security/Access.cs new file mode 100644 index 0000000..c4a0b5c --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/Models/Security/Access.cs @@ -0,0 +1,38 @@ +using ModelTools.Attributes; +using ModelTools.Enums; +using System; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; + +namespace DatabaseCore.Models.Security +{ + /// + /// Класс, описывающий возможные действия для роли + /// + [DataContract] + [EntityDescription("Access", "Доступные действия для ролей")] + [EntityDependency("Role", "RoleId", "Доступные дейсвтиия создаются под конкретную роль")] + public class Access : BaseEntity + { + [Required] + [DataMember] + [MapConfiguration("RoleId")] + public Guid RoleId { get; set; } + + [Required] + [DataMember] + [MapConfiguration("Operation")] + public AccessOperation Operation { get; set; } + + [Required] + [DataMember] + [MapConfiguration("AccessType")] + public AccessType AccessType { get; set; } + + //------------------------------------------------------------------------- + + public virtual Role Role { get; set; } + + //------------------------------------------------------------------------- + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/DatabaseCore/Models/Security/EnviromentSetting.cs b/DepartmentPortal/Common/DatabaseCore/Models/Security/EnviromentSetting.cs new file mode 100644 index 0000000..dfd0fb6 --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/Models/Security/EnviromentSetting.cs @@ -0,0 +1,21 @@ +using ModelTools.Attributes; +using System.Runtime.Serialization; + +namespace DatabaseCore.Models.Security +{ + /// + /// Класс, описывающий общие настройки системы + /// + [DataContract] + [EntityDescription("EnviromentSetting", "Общие настройки системы")] + public class EnviromentSetting : IdEntity + { + [DataMember] + [MapConfiguration("Key")] + public string Key { get; set; } + + [DataMember] + [MapConfiguration("Value")] + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/DatabaseCore/Models/Security/Role.cs b/DepartmentPortal/Common/DatabaseCore/Models/Security/Role.cs new file mode 100644 index 0000000..40f4cf2 --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/Models/Security/Role.cs @@ -0,0 +1,33 @@ +using ModelTools.Attributes; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Runtime.Serialization; + +namespace DatabaseCore.Models.Security +{ + /// + /// Класс, описывающий роль в системе + /// + [DataContract] + [EntityDescription("Role", "Роли в системе")] + public class Role : BaseEntity + { + [DataMember] + [MapConfiguration("RoleName")] + public string RoleName { get; set; } + + [DataMember] + [MapConfiguration("RolePriority")] + public int RolePriority { get; set; } + + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + + [ForeignKey("RoleId")] + public virtual List Access { get; set; } + + [ForeignKey("RoleId")] + public virtual List UserRoles { get; set; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/DatabaseCore/Models/Security/User.cs b/DepartmentPortal/Common/DatabaseCore/Models/Security/User.cs new file mode 100644 index 0000000..6e5aa34 --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/Models/Security/User.cs @@ -0,0 +1,63 @@ +using ModelTools.Attributes; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Runtime.Serialization; + +namespace DatabaseCore.Models.Security +{ + /// + /// Класс, описывающий пользователя системы + /// + [DataContract] + [EntityDescription("User", "Пользователи системы")] + public class User : BaseEntity + { + [DataMember] + [MapConfiguration("Login")] + public string UserName { get; set; } + + [DataMember] + [MapConfiguration("Password")] + public string PasswordHash { get; set; } + + [DataMember] + [MapConfiguration("StudentId")] + public Guid? StudentId { get; set; } + + [DataMember] + [MapConfiguration("LecturerId")] + public Guid? LecturerId { get; set; } + + [DataMember] + [MapConfiguration("EmployeeId")] + public Guid? EmployeeId { get; set; } + + [DataMember] + [MapConfiguration("Avatar")] + public byte[] Avatar { get; set; } + + [DataMember] + [MapConfiguration("DateLastVisit")] + public DateTime? DateLastVisit { get; set; } + + [DataMember] + [MapConfiguration("IsBanned")] + public bool IsBanned { get; set; } + + [DataMember] + [MapConfiguration("DateBanned")] + public DateTime? DateBanned { get; set; } + + [DataMember] + [MapConfiguration("CountAttempt")] + public int CountAttempt { get; set; } + + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + + [ForeignKey("UserId")] + public virtual List UserRoles { get; set; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/DatabaseCore/Models/Security/UserRole.cs b/DepartmentPortal/Common/DatabaseCore/Models/Security/UserRole.cs new file mode 100644 index 0000000..b2e3bfb --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/Models/Security/UserRole.cs @@ -0,0 +1,30 @@ +using ModelTools.Attributes; +using System; +using System.Runtime.Serialization; + +namespace DatabaseCore.Models.Security +{ + /// + /// Связка пользователь - роль + /// + [DataContract] + [EntityDescription("UserRole", "Связь пользователей системы с ролями, которые им назначены")] + [EntityDependency("Role", "RoleId", "К какой роли относится пользователь")] + [EntityDependency("User", "UserId", "К какой роли относится пользователь")] + public class UserRole : BaseEntity + { + [DataMember] + public Guid RoleId { get; set; } + + [DataMember] + public Guid UserId { get; set; } + + //------------------------------------------------------------------------- + + public virtual Role Role { get; set; } + + public virtual User User { get; set; } + + //------------------------------------------------------------------------- + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/DatabaseCore/Scripts/SecureMigrationScript.cs b/DepartmentPortal/Common/DatabaseCore/Scripts/SecureMigrationScript.cs new file mode 100644 index 0000000..be16bc8 --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/Scripts/SecureMigrationScript.cs @@ -0,0 +1,57 @@ +using Microsoft.EntityFrameworkCore; + +namespace DatabaseCore.Scripts +{ + /// + /// Скрипты для миграции данных по безопасности + /// + public static class SecureMigrationScript + { + private static readonly string clearMigration = +@"DELETE FROM DepartmentDatabasePortal.dbo.EnviromentSettings +GO +DELETE FROM DepartmentDatabasePortal.dbo.Accesses; +GO +DELETE FROM DepartmentDatabasePortal.dbo.UserRoles; +GO +DELETE FROM DepartmentDatabasePortal.dbo.Users; +GO +DELETE FROM DepartmentDatabasePortal.dbo.Roles; +GO"; + + private static readonly string roleMigration = +@"INSERT INTO DepartmentDatabasePortal.dbo.Roles(Id, RoleName, RolePriority, DateCreate, DateDelete, IsDeleted) +SELECT Id, RoleName, RolePriority, DateCreate, DateDelete, IsDeleted FROM DepartmentDatabaseContext.dbo.DepartmentRoles"; + + private static readonly string userMigration = +@"INSERT INTO DepartmentDatabasePortal.dbo.Users(Id, UserName, PasswordHash, StudentId, LecturerId, Avatar, DateLastVisit, IsBanned, DateBanned, CountAttempt, DateCreate, DateDelete, IsDeleted) +SELECT Id, UserName, PasswordHash, StudentId, LecturerId, Avatar, DateLastVisit, IsLocked, DateBanned, CountAttempt, DateCreate, DateDelete, IsDeleted FROM DepartmentDatabaseContext.dbo.DepartmentUsers"; + + private static readonly string userroleMigration = +@"INSERT INTO DepartmentDatabasePortal.dbo.UserRoles(Id, UserId, RoleId, DateCreate, DateDelete, IsDeleted) +SELECT Id, UserId, RoleId, DateCreate, DateDelete, IsDeleted FROM DepartmentDatabaseContext.dbo.DepartmentUserRoles"; + + private static readonly string accessMigration = +@"INSERT INTO DepartmentDatabasePortal.dbo.Accesses(Id, Operation, AccessType, RoleId, DateCreate, DateDelete, IsDeleted) +SELECT Id, Operation, AccessType, RoleId, DateCreate, DateDelete, IsDeleted FROM DepartmentDatabaseContext.dbo.DepartmentAccesses"; + + private static readonly string enviromentsettingMigration = +@"INSERT INTO DepartmentDatabasePortal.dbo.EnviromentSettings(Id, [Key], [Value]) +SELECT NEWID(), [Key], [Value] FROM DepartmentDatabaseContext.dbo.CurrentSettings"; + + /// + /// Перенос данных по безопасности + /// + /// + public static void RunScript(DbContext context) + { + context.Database.ExecuteSqlRaw(clearMigration, null); + + context.Database.ExecuteSqlRaw(roleMigration, null); + context.Database.ExecuteSqlRaw(userMigration, null); + context.Database.ExecuteSqlRaw(userroleMigration, null); + context.Database.ExecuteSqlRaw(accessMigration, null); + context.Database.ExecuteSqlRaw(enviromentsettingMigration, null); + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/DatabaseCore/SecurityManager.cs b/DepartmentPortal/Common/DatabaseCore/SecurityManager.cs new file mode 100644 index 0000000..2ed76c5 --- /dev/null +++ b/DepartmentPortal/Common/DatabaseCore/SecurityManager.cs @@ -0,0 +1,64 @@ +using DatabaseCore.Models.Security; +using ModelTools.BindingModels; +using ModelTools.Enums; +using ModelTools.Interfaces; +using SecurityBusinessLogic.BusinessLogics; +using System.Linq; + +namespace DatabaseCore +{ + public class SecurityManager : ISecurityManager + { + public string ErrorMessage { get; set; } + + public bool CheckAccess(AccessBindingModel model, AccessOperation operation, AccessType type, string entity) + { + using var context = DatabaseManager.GetContext; + Access access; + if (model != null) + { + // простой просмотр возможен + if (model.SkipCheck && type == AccessType.SimpleView) + { + return true; + } + // если не указан идентификатор пользователя, то смотрим, может он авторизован + if (!model.UserId.HasValue && UserManager.GetInstance.User != null) + { + model.UserId = UserManager.GetInstance.UserId; + } + + var roles = context.UserRoles.Where(x => x.UserId == model.UserId).Select(x => x.Role).OrderByDescending(x => x.RolePriority).ToList(); + if (roles == null) + { + ErrorMessage = $"Не верный пользователь"; + return false; + } + access = context.Accesses.FirstOrDefault(a => a.Operation == operation && roles.Contains(a.Role)); + } + else + { + access = context.Accesses.FirstOrDefault(a => a.Operation == operation && UserManager.GetInstance.Roles.Contains(a.RoleId)); + } + if (access != null) + { + if (access.AccessType >= type) return true; + } + switch (type) + { + case AccessType.FullView: + ErrorMessage = $"Нет доступа на чтение данных по сущности '{entity}'"; + return false; + case AccessType.Change: + ErrorMessage = $"Нет доступа на изменение данных по сущности '{entity}'"; + return false; + case AccessType.Delete: + ErrorMessage = $"Нет доступа на удаление данных по сущности '{entity}'"; + return false; + default: + ErrorMessage = $"Нет доступа по сущности '{entity}'"; + return false; + } + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/Attributes/EntityDependencyAttribute.cs b/DepartmentPortal/Common/ModelTools/Attributes/EntityDependencyAttribute.cs new file mode 100644 index 0000000..8640e72 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/Attributes/EntityDependencyAttribute.cs @@ -0,0 +1,39 @@ +using System; + +namespace ModelTools.Attributes +{ + /// + /// Описание зависимости сущности от другой сущности (требуется для сохранения и загрузки данных) + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public class EntityDependencyAttribute : Attribute + { + /// + /// Название класса от котрого зависит этот класс + /// + public string ClassName { get; set; } + + /// + /// Название поле в этом классе, которое ссылает на другой класс (идентификатор) + /// + public string ColumnName { get; set; } + + /// + /// Описание зависимости + /// + public string Description { get; set; } + + /// + /// Описание зависимости сущности от другой сущности (требуется для сохранения и загрузки данных) + /// + /// Название класса от котрого зависит этот класс + /// Название поле в этом классе, которое ссылает на другой класс (идентификатор) + /// Описание зависимости + public EntityDependencyAttribute(string className, string columnName, string description) + { + ClassName = className; + ColumnName = columnName; + Description = description; + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/Attributes/EntityDescriptionAttribute.cs b/DepartmentPortal/Common/ModelTools/Attributes/EntityDescriptionAttribute.cs new file mode 100644 index 0000000..22111b7 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/Attributes/EntityDescriptionAttribute.cs @@ -0,0 +1,32 @@ +using System; + +namespace ModelTools.Attributes +{ + /// + /// Описание класса из базы данных, его назначение + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public class EntityDescriptionAttribute : Attribute + { + /// + /// Название сущности, которую описывает класс + /// + public string EntityName { get; set; } + + /// + /// Описание назначения сущности + /// + public string Description { get; set; } + + /// + /// Описание класса из базы данных, его назначение + /// + /// Название сущности, которую описывает класс + /// Описание назначения сущности + public EntityDescriptionAttribute(string entityName, string description) + { + EntityName = entityName; + Description = description; + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/Attributes/MapConfigurationAttribute.cs b/DepartmentPortal/Common/ModelTools/Attributes/MapConfigurationAttribute.cs new file mode 100644 index 0000000..850fcd3 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/Attributes/MapConfigurationAttribute.cs @@ -0,0 +1,32 @@ +using System; + +namespace ModelTools.Attributes +{ + /// + /// Настройка для полей сущности правил маппинга + /// + [AttributeUsage(AttributeTargets.Property)] + public class MapConfigurationAttribute : Attribute + { + /// + /// Название свойства с класса, из которого извлекаем данные + /// + public string PropertyNameFromModel { get; set; } + + /// + /// Сложное свойство (свойствое в другом классе-свойстве) + /// + public bool IsDifficle { get; set; } + + /// + /// Настройка для полей сущности правил маппинга + /// + /// Название свойства с класса, из которого извлекаем данные + /// Сложное свойство (свойствое в другом классе-свойстве) + public MapConfigurationAttribute(string propertyNameFromMModel, bool isDifficle = false) + { + PropertyNameFromModel = propertyNameFromMModel; + IsDifficle = isDifficle; + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/Attributes/ViewModelPropertyAttribute.cs b/DepartmentPortal/Common/ModelTools/Attributes/ViewModelPropertyAttribute.cs new file mode 100644 index 0000000..a8358fb --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/Attributes/ViewModelPropertyAttribute.cs @@ -0,0 +1,68 @@ +using System; + +namespace ModelTools.Attributes +{ + /// + /// Настройка отображения элемента в контролах + /// + [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] + public class ViewModelPropertyAttribute : Attribute + { + /// + /// Используется при выводе списка + /// + public bool UseOnList { get; set; } + + /// + /// Используется при выводе элемента + /// + public bool UseOnElement { get; set; } + + /// + /// Название на форме + /// + public string DisplayName { get; set; } + + /// + /// Скрывать или нет при выводе списка + /// + public bool IsHide { get; set; } + + /// + /// Ширина колонки + /// + public int? ColumnWidth { get; set; } + + /// + /// Настройка отображения элемента в контролах + /// + /// Название на форме + /// Используется при выводе списка + /// Используется при выводе элемента + /// Скрывать или нет + public ViewModelPropertyAttribute(string displayName, bool useOnList, bool useOnElement, bool isHide = false) + { + DisplayName = displayName; + UseOnList = useOnList; + UseOnElement = useOnElement; + ColumnWidth = null; + IsHide = isHide; + } + + /// + /// Конструктор + /// + /// Название на форме + /// Используется при выводе списка + /// Используется при выводе элемента + /// Ширина колонки + public ViewModelPropertyAttribute(string displayName, bool useOnList, bool useOnElement, int columnWidth) + { + DisplayName = displayName; + UseOnList = useOnList; + UseOnElement = useOnElement; + ColumnWidth = columnWidth; + IsHide = false; + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/BindingModels/AccessBindingModel.cs b/DepartmentPortal/Common/ModelTools/BindingModels/AccessBindingModel.cs new file mode 100644 index 0000000..cda456c --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/BindingModels/AccessBindingModel.cs @@ -0,0 +1,20 @@ +using System; + +namespace ModelTools.BindingModels +{ + /// + /// Информация для доступа к выполнению операций + /// + public class AccessBindingModel + { + /// + /// Пропускать проверку (работает только для получения данных) + /// + public bool SkipCheck { get; set; } + + /// + /// Идентификатор пользователя, который запрашивает выполнение операции + /// + public Guid? UserId { get; set; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/BindingModels/GetBindingModel.cs b/DepartmentPortal/Common/ModelTools/BindingModels/GetBindingModel.cs new file mode 100644 index 0000000..c13aa05 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/BindingModels/GetBindingModel.cs @@ -0,0 +1,30 @@ +using System; + +namespace ModelTools.BindingModels +{ + /// + /// Получение записи + /// + public class GetBindingModel : AccessBindingModel + { + /// + /// Идентификатор получаемой записи (для одной записи) + /// + public Guid? Id { get; set; } + + /// + /// Номер страницы, которую получаем (для списка) + /// + public int? PageNumber { get; set; } + + /// + /// Количество записей возвращаемых (для списка) + /// + public int? PageSize { get; set; } + + /// + /// Иной признак, по которму отбираем записи (для списка) + /// + public string PageName { get; set; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/BindingModels/SetBindingModel.cs b/DepartmentPortal/Common/ModelTools/BindingModels/SetBindingModel.cs new file mode 100644 index 0000000..894357a --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/BindingModels/SetBindingModel.cs @@ -0,0 +1,15 @@ +using System; + +namespace ModelTools.BindingModels +{ + /// + /// Сохранение записи по идентификатору + /// + public class SetBindingModel : AccessBindingModel + { + /// + /// Идентификатор записи + /// + public Guid Id { get; set; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/BusinessLogics/BusinessLogicCore.cs b/DepartmentPortal/Common/ModelTools/BusinessLogics/BusinessLogicCore.cs new file mode 100644 index 0000000..f6adbd0 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/BusinessLogics/BusinessLogicCore.cs @@ -0,0 +1,226 @@ +using ModelTools.BindingModels; +using ModelTools.Enums; +using ModelTools.Interfaces; +using ModelTools.OperationResultModels; +using ModelTools.ViewModels; +using System; +using System.Collections.Generic; + +namespace ModelTools.BusinessLogics +{ + /// + /// Базовый класс для логики сущности + /// + /// + /// + /// + /// + public abstract class BusinessLogicCore + where G : GetBindingModel + where S : SetBindingModel + where L : ListViewModel + where E : ElementViewModel + { + /// + /// Перечень ошибок при выполнении операции + /// + public List<(string Title, string Message)> Errors { get; protected set; } + + protected IEntityService Service { get; set; } + + protected ISecurityManager Security { get; set; } + + protected readonly AccessOperation _serviceOperation; + + protected readonly string _entity; + + public BusinessLogicCore(IEntityService service, string entity, AccessOperation serviceOperation) + { + Service = service; + Errors = new List<(string Title, string Message)>(); + Security = UnityContainerConfigurator.Resolve(); + _entity = entity; + _serviceOperation = serviceOperation; + } + + /// + /// Проверка доступности операции для пользователя + /// + /// + /// + /// + protected bool NoAccess(AccessBindingModel model, AccessType type) + { + if (Security.CheckAccess(model, _serviceOperation, type, _entity)) + { + return false; + } + + Errors.Add(("Ошибка безопасности", Security.ErrorMessage)); + return true; + } + + /// + /// Получение списка записей + /// + /// + /// + public L GetList(G model) + { + Errors.Clear(); + try + { + if (NoAccess(model, AccessType.SimpleView) && NoAccess(model, AccessType.FullView)) + { + return null; + } + var result = Service.Read(model); + if (!result.IsSucceeded) + { + Errors.AddRange(Errors); + return null; + } + + return ConvertToL(result); + } + catch (Exception ex) + { + Errors.Add(("Ошибка получения", ex.Message)); + } + return null; + } + + /// + /// Получение записи + /// + /// + /// + public E GetElement(G model) + { + Errors.Clear(); + try + { + if (NoAccess(model, AccessType.SimpleView) && NoAccess(model, AccessType.FullView)) + { + return null; + } + var result = Service.Read(model); + if (!result.IsSucceeded) + { + Errors.AddRange(Errors); + return null; + } + return ConvertToE(result); + } + catch (Exception ex) + { + Errors.Add(("Ошибка получения", ex.Message)); + } + return null; + } + + /// + /// Создание записи + /// + /// + /// + public E Create(S model) + { + Errors.Clear(); + try + { + if (NoAccess(model, AccessType.Change)) + { + return null; + } + var result = Service.Create(model); + if (!result.IsSucceeded) + { + Errors.AddRange(Errors); + return null; + } + + return ConvertToE(result); + } + catch (Exception ex) + { + Errors.Add(("Ошибка создания", ex.Message)); + } + return null; + } + + /// + /// Изменение записи + /// + /// + /// + public E Update(S model) + { + Errors.Clear(); + try + { + if (NoAccess(model, AccessType.Change)) + { + return null; + } + var result = Service.Update(model); + if (!result.IsSucceeded) + { + Errors.AddRange(Errors); + return null; + } + + return ConvertToE(result); + } + catch (Exception ex) + { + Errors.Add(("Ошибка изменения", ex.Message)); + } + return null; + } + + /// + /// Удаление записи + /// + /// + /// + public bool Delete(G model) + { + Errors.Clear(); + try + { + if (NoAccess(model, AccessType.Delete)) + { + return false; + } + var result = Service.Delete(model); + if (!result.IsSucceeded) + { + Errors.AddRange(Errors); + return false; + } + + return true; + } + catch (Exception ex) + { + Errors.Add(("Ошибка удаления", ex.Message)); + } + return false; + } + + /// + /// Получить список элементов + /// + /// + /// + protected abstract L ConvertToL(OperationResultModel model); + + /// + /// Получить элемент + /// + /// + /// + protected abstract E ConvertToE(OperationResultModel model); + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/BusinessLogics/Mapper.cs b/DepartmentPortal/Common/ModelTools/BusinessLogics/Mapper.cs new file mode 100644 index 0000000..b576561 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/BusinessLogics/Mapper.cs @@ -0,0 +1,100 @@ +using ModelTools.Attributes; +using System; +using System.Reflection; + +namespace ModelTools.BusinessLogics +{ + /// + /// Маппер сущностей + /// + public class Mapper + { + /// + /// Преобразование из одного класса в другой + /// + /// + /// + /// + /// + public static To MapToClass(From obj) where To : class => FillObject(obj, (To)Activator.CreateInstance(typeof(To))); + + /// + /// Преобразование из одного класса в другой + /// + /// + /// + /// + /// + /// + public static To MapToClass(From obj, To newObject) where To : class => FillObject(obj, newObject); + + /// + /// Заполнение объекта + /// + /// + /// + /// + /// + /// + private static To FillObject(From obj, To newObject) + where To : class + { + if (obj == null) + { + return null; + } + + if (newObject == null) + { + return null; + } + var typeFrom = typeof(From); + var typeTo = typeof(To); + var properties = typeTo.GetProperties(); + foreach (var property in properties) + { + var customAttribute = property.GetCustomAttribute(); + if (customAttribute != null) + { + object value = obj; + if (customAttribute.IsDifficle) + { + var props = customAttribute.PropertyNameFromModel.Split('.'); + foreach (var prop in props) + { + var bindingProperty = value.GetType().GetProperty(prop); + if (bindingProperty != null) + { + value = bindingProperty.GetValue(obj); + if (value is null) + { + break; + } + } + else + { + value = null; + break; + } + } + } + else + { + var bindingProperty = typeFrom.GetProperty(customAttribute.PropertyNameFromModel); + if (bindingProperty != null) + { + value = bindingProperty.GetValue(obj); + } + } + if (value is null) + { + continue; + } + property.SetValue(newObject, value); + } + } + + return newObject; + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/BusinessLogics/ServiceProviderLoader.cs b/DepartmentPortal/Common/ModelTools/BusinessLogics/ServiceProviderLoader.cs new file mode 100644 index 0000000..9386353 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/BusinessLogics/ServiceProviderLoader.cs @@ -0,0 +1,79 @@ +using ModelTools.Extensions; +using ModelTools.Interfaces; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Xml.XPath; + +namespace ModelTools.BusinessLogics +{ + /// + /// Загрузчик данных + /// + public static class ServiceProviderLoader + { + private static readonly string _configFileName = "DepartmentPortal.config"; + + private static readonly string _pathToLoaderExt = "..\\..\\..\\..\\Extensions\\"; + + /// + /// Получение данных с файла настроек + /// + /// + /// + public static string GetConfigData(string key) + { + var fileName = GetFile(_configFileName); + if (!File.Exists(fileName)) + { + return string.Empty; + } + + var doc = new XPathDocument(fileName); + var nav = doc.CreateNavigator(); + var data = nav.SelectDescendants(key, "", false); + data.MoveNext(); + return data.Current.Value; + } + + /// + /// Загрузка всех классов-реализаций ILoaderExtensions + /// + /// + public static List GetLoaderExtensions() + { + var list = new List(); + if(Directory.Exists(_pathToLoaderExt)) + { + var files = Directory.GetFiles(_pathToLoaderExt, "*.dll", SearchOption.AllDirectories); + var loadedFiles = new List(); + foreach(var file in files.Distinct()) + { + if(loadedFiles.Contains(file.GetFileName())) + { + continue; + } + Assembly asm = Assembly.LoadFrom(file); + foreach (var t in asm.GetExportedTypes()) + { + if (t.IsClass && typeof(ILoaderExtensions).IsAssignableFrom(t)) + { + list.Add((ILoaderExtensions)Activator.CreateInstance(t)); + } + } + loadedFiles.Add(file.GetFileName()); + } + } + return list; + } + + /// + /// Получение имени файла + /// + /// + /// + private static string GetFile(string fileName) => Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), fileName); + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/BusinessLogics/UnityContainerConfigurator.cs b/DepartmentPortal/Common/ModelTools/BusinessLogics/UnityContainerConfigurator.cs new file mode 100644 index 0000000..4c03192 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/BusinessLogics/UnityContainerConfigurator.cs @@ -0,0 +1,43 @@ +using System; +using Unity; +using Unity.Lifetime; + +namespace ModelTools.BusinessLogics +{ + public class UnityContainerConfigurator + { + private static IUnityContainer _unityContainer; + + public static IUnityContainer Container + { + get + { + if (_unityContainer == null) _unityContainer = new UnityContainer(); + return _unityContainer; + } + } + + /// + /// Инициализация сервисов + /// + public static void InitServices() + { + var ext = ServiceProviderLoader.GetLoaderExtensions(); + if (ext.Count == 0) + { + throw new ArgumentNullException("Отсутствуют компоненты для загрузки зависимостей по модулям"); + } + // регистрируем в UnityContainaer зависимости + foreach (var e in ext) + { + e.RegisterServices(); + } + } + + public static void PublishService() where U : T => Container.RegisterType(new HierarchicalLifetimeManager()); + + public static void PublishService() => Container.RegisterType(new HierarchicalLifetimeManager()); + + public static T Resolve() => Container.Resolve(); + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/Enums/AccessOperation.cs b/DepartmentPortal/Common/ModelTools/Enums/AccessOperation.cs new file mode 100644 index 0000000..67a70f6 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/Enums/AccessOperation.cs @@ -0,0 +1,100 @@ +namespace ModelTools.Enums +{ + /// + /// Операции в системе + /// + public enum AccessOperation + { + #region Администрирование + Администрирование = 0, + + Роли = 1, + + Доступы = 2, + + Пользователи = 3, + + НастройкиСреды = 4, + #endregion + + #region База + Кафедра = 100, + + Аудитории = 101, + + Направления = 102, + + Преподаватели = 103, // + должности, звания + + Дисциплины = 104, // + Блоки дисциплин + + Группы = 105, // + + Студенты = 106, + + Приказы_студентов = 107, + #endregion + + // Меню Учебный процесс + Учебный_процесс = 150, + + Учебные_планы = 120, + + Виды_нагрузок = 121, + + Учебные_года = 122, + + Даты_семестра = 126, + + Контингент = 123, + + Нормы_времени = 124, + + Расчет_штатов = 125, + + Расчасовки = 127, + + Преподавательская_ставка = 128, + + Индивидуальный_план = 130, + + // Меню Расписание + Расписание = 200, + + Расписание_аудитории = 201, + + Расписание_группы = 202, + + Расписание_преподаватели = 203, + + Расписание_настройки = 204, + + Расписание_интервалы_пар = 205, + + Расписание_дисциплины = 206, + + // Меню Сервис + Сервис = 300, + + Генерация_билетов = 301, + + // Меню зав лаб + ЗавЛабораторией = 400, + + МатериальноТехническиеЦенности = 401, + + УстановленоеПО = 402, + + // Экзамены - составление билетов и проведение + СоставлениеЭкзаменов = 500, + + Ведомости = 501, + + ШаблоныБилетов = 502, + + // Web-портал + Новости = 600, + + Комментарии = 601 + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/Enums/AccessType.cs b/DepartmentPortal/Common/ModelTools/Enums/AccessType.cs new file mode 100644 index 0000000..d6f0f00 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/Enums/AccessType.cs @@ -0,0 +1,34 @@ +namespace ModelTools.Enums +{ + /// + /// Тип операции + /// + public enum AccessType : int + { + /// + /// Простой просомтр + /// + SimpleView = 0, + + /// + /// Полный просомтр + /// + FullView = 1, + + /// + /// Добавление/Изменение + /// + Change = 2, + + /// + /// Удаление + /// + Delete = 4, + + // TODO убрать + /// + /// Доступ к админке + /// + Administrator = 8 + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/Enums/ResultServiceStatusCode.cs b/DepartmentPortal/Common/ModelTools/Enums/ResultServiceStatusCode.cs new file mode 100644 index 0000000..d31bf2d --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/Enums/ResultServiceStatusCode.cs @@ -0,0 +1,38 @@ +namespace ModelTools.Enums +{ + /// + /// Статус результата операции + /// + public enum ResultServiceStatusCode + { + /// + /// Успешно + /// + Success = 200, + + /// + /// Ошибка общая + /// + Error = 400, + + /// + /// Элемент уже сущствует + /// + ExsistItem = 401, + + /// + /// Запись удалена + /// + WasDelete = 402, + + /// + /// Не найдено + /// + NotFound = 404, + + /// + /// Не найден файл + /// + FileNotFound = 405 + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/Extensions/StringExtension.cs b/DepartmentPortal/Common/ModelTools/Extensions/StringExtension.cs new file mode 100644 index 0000000..b656bfd --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/Extensions/StringExtension.cs @@ -0,0 +1,28 @@ +using System.IO; + +namespace ModelTools.Extensions +{ + public static class StringExtension + { + /// + /// Проверка, что строка пустая + /// + /// + /// + public static bool IsEmpty(this string str) => string.IsNullOrEmpty(str); + + /// + /// Проверка, что строка не пустая + /// + /// + /// + public static bool IsNotEmpty(this string str) => !string.IsNullOrEmpty(str); + + /// + /// Получение имени файла по полному пути + /// + /// + /// + public static string GetFileName(this string str) => (new FileInfo(str)).Name; + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/Interfaces/IEntityService.cs b/DepartmentPortal/Common/ModelTools/Interfaces/IEntityService.cs new file mode 100644 index 0000000..2ab6242 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/Interfaces/IEntityService.cs @@ -0,0 +1,41 @@ +using ModelTools.BindingModels; +using ModelTools.OperationResultModels; + +namespace ModelTools.Interfaces +{ + /// + /// Описание логики для хранилища сущности + /// + public interface IEntityService + where G : GetBindingModel + where S : SetBindingModel + { + /// + /// Получение списка сущностей + /// + /// + /// + OperationResultModel Read(G model); + + /// + /// Создание новой сущности + /// + /// + /// + OperationResultModel Create(S model); + + /// + /// Изменение сущности + /// + /// + /// + OperationResultModel Update(S model); + + /// + /// Удаление сущности + /// + /// + /// + OperationResultModel Delete(G model); + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/Interfaces/ILoaderExtensions.cs b/DepartmentPortal/Common/ModelTools/Interfaces/ILoaderExtensions.cs new file mode 100644 index 0000000..1316e47 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/Interfaces/ILoaderExtensions.cs @@ -0,0 +1,13 @@ +namespace ModelTools.Interfaces +{ + /// + /// Интерфейс для регистрации зависомстей в модулях + /// + public interface ILoaderExtensions + { + /// + /// Регистрация сервисов + /// + public void RegisterServices(); + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/Interfaces/ISecurityManager.cs b/DepartmentPortal/Common/ModelTools/Interfaces/ISecurityManager.cs new file mode 100644 index 0000000..78156d4 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/Interfaces/ISecurityManager.cs @@ -0,0 +1,23 @@ +using ModelTools.BindingModels; +using ModelTools.Enums; + +namespace ModelTools.Interfaces +{ + public interface ISecurityManager + { + /// + /// Сообщение с причиной не получения доступа + /// + string ErrorMessage { get; set; } + + /// + /// Авторизация пользователя к операции + /// + /// Данные по пользователю + /// Операция, которую хотят выполнить + /// Тип операции + /// Для какой сущности + /// + bool CheckAccess(AccessBindingModel model, AccessOperation operation, AccessType type, string entity); + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/ModelTools.csproj b/DepartmentPortal/Common/ModelTools/ModelTools.csproj new file mode 100644 index 0000000..dfb11d9 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/ModelTools.csproj @@ -0,0 +1,11 @@ + + + + net5.0 + + + + + + + diff --git a/DepartmentPortal/Common/ModelTools/OperationResultModels/OperationResultModel.cs b/DepartmentPortal/Common/ModelTools/OperationResultModels/OperationResultModel.cs new file mode 100644 index 0000000..9036f76 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/OperationResultModels/OperationResultModel.cs @@ -0,0 +1,114 @@ +using ModelTools.Enums; +using System; +using System.Collections.Generic; + +namespace ModelTools.OperationResultModels +{ + /// + /// Результат любой операции + /// + public class OperationResultModel + { + /// + /// Успешность операции (количество ошибок = 0) + /// + public bool IsSucceeded => Errors.Count == 0; + + /// + /// Статус операции + /// + public ResultServiceStatusCode StatusCode { get; set; } + + /// + /// Спсиок ошибок + /// + public List<(string Title, string Message)> Errors { get; private set; } + + /// + /// Объект, получаемый по результатам операции + /// + public object Result { get; private set; } + + /// + /// Конструктор по умолчанию + /// + public OperationResultModel() + { + Errors = new List<(string Title, string Message)>(); + StatusCode = ResultServiceStatusCode.Success; + } + + /// + /// Успешно + /// + /// + /// + public static OperationResultModel Success(object obj) + { + return new OperationResultModel + { + Result = obj, + Errors = new List<(string Title, string Message)>(), + StatusCode = ResultServiceStatusCode.Success + }; + } + + /// + /// Добавление простой ошибки + /// + /// + /// + /// + public static OperationResultModel Error(string key, string value) => Error(key, value, ResultServiceStatusCode.Error); + + /// + /// Добавление простой ошибки со сменой статуса + /// + /// + /// + /// + /// + public static OperationResultModel Error(string key, string error, ResultServiceStatusCode statusCode) + { + var model = new OperationResultModel(); + model.Errors.Add((key, error)); + model.StatusCode = statusCode; + return model; + } + + /// + /// Добавление ошибки + /// + /// + /// + public static OperationResultModel Error(Exception error) => Error(error, ResultServiceStatusCode.Error); + + /// + /// Добавление ошибки + /// + /// + /// + /// + public static OperationResultModel Error(Exception error, ResultServiceStatusCode statusCode) => Error("Ошибка", error, statusCode); + + /// + /// Добавление ошибки (включая вложеннные) + /// + /// + /// + /// + /// + public static OperationResultModel Error(string key, Exception error, ResultServiceStatusCode statusCode) + { + var model = new OperationResultModel(); + model.Errors.Add((key, error.Message)); + while (error.InnerException != null) + { + error = error.InnerException; + model.Errors.Add(("Inner error:", error.Message)); + } + model.StatusCode = statusCode; + return model; + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/ViewModels/ElementViewModel.cs b/DepartmentPortal/Common/ModelTools/ViewModels/ElementViewModel.cs new file mode 100644 index 0000000..dfe800e --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/ViewModels/ElementViewModel.cs @@ -0,0 +1,15 @@ +using ModelTools.Attributes; +using System; + +namespace ModelTools.ViewModels +{ + /// + /// Возвращаемая запись + /// + public class ElementViewModel + { + [ViewModelProperty("Идентификатор", useOnList: true, useOnElement: false, isHide: true)] + [MapConfiguration("Id")] + public Guid Id { get; set; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Common/ModelTools/ViewModels/ListViewModel.cs b/DepartmentPortal/Common/ModelTools/ViewModels/ListViewModel.cs new file mode 100644 index 0000000..f98f307 --- /dev/null +++ b/DepartmentPortal/Common/ModelTools/ViewModels/ListViewModel.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace ModelTools.ViewModels +{ + /// + /// Список возвращаемых значений + /// + /// + public class ListViewModel + where T : ElementViewModel + { + public int MaxCount { get; set; } + + public List List { get; set; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/DepartmentPortal.sln b/DepartmentPortal/DepartmentPortal.sln index 822b3d2..3c23c6f 100644 --- a/DepartmentPortal/DepartmentPortal.sln +++ b/DepartmentPortal/DepartmentPortal.sln @@ -5,7 +5,17 @@ VisualStudioVersion = 16.0.31112.23 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{6F154F8D-3437-45EE-9D89-02B96BDF3E8E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommonTools", "Common\CommonTools\CommonTools.csproj", "{9E533D43-452A-40D6-852B-01E8391BBFF9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DatabaseCore", "Common\DatabaseCore\DatabaseCore.csproj", "{D4DAAEDE-A550-42BB-A50C-AD8FCB23D00A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ModelTools", "Common\ModelTools\ModelTools.csproj", "{8BE3C29B-6E9F-4DFC-BAC3-14229D58616F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Security", "Security", "{7DA26C36-778E-4563-9AEC-966E26EA7B2A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SecurityBusinessLogic", "Security\SecurityBusinessLogic\SecurityBusinessLogic.csproj", "{D424B54F-AF26-4A39-8D2B-CF874F31DE42}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DepartmentPortalDesctop", "DepartmentPortalDesctop\DepartmentPortalDesctop.csproj", "{B6CE93CB-998F-4F2D-BE9E-6FDF37FDFD0E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SecurityImplementation", "Security\SecurityImplementation\SecurityImplementation.csproj", "{24D7BD00-EC45-4B98-92BB-C6FFB01F66ED}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -13,16 +23,35 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9E533D43-452A-40D6-852B-01E8391BBFF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9E533D43-452A-40D6-852B-01E8391BBFF9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9E533D43-452A-40D6-852B-01E8391BBFF9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9E533D43-452A-40D6-852B-01E8391BBFF9}.Release|Any CPU.Build.0 = Release|Any CPU + {D4DAAEDE-A550-42BB-A50C-AD8FCB23D00A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4DAAEDE-A550-42BB-A50C-AD8FCB23D00A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4DAAEDE-A550-42BB-A50C-AD8FCB23D00A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4DAAEDE-A550-42BB-A50C-AD8FCB23D00A}.Release|Any CPU.Build.0 = Release|Any CPU + {8BE3C29B-6E9F-4DFC-BAC3-14229D58616F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8BE3C29B-6E9F-4DFC-BAC3-14229D58616F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8BE3C29B-6E9F-4DFC-BAC3-14229D58616F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8BE3C29B-6E9F-4DFC-BAC3-14229D58616F}.Release|Any CPU.Build.0 = Release|Any CPU + {D424B54F-AF26-4A39-8D2B-CF874F31DE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D424B54F-AF26-4A39-8D2B-CF874F31DE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D424B54F-AF26-4A39-8D2B-CF874F31DE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D424B54F-AF26-4A39-8D2B-CF874F31DE42}.Release|Any CPU.Build.0 = Release|Any CPU + {B6CE93CB-998F-4F2D-BE9E-6FDF37FDFD0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6CE93CB-998F-4F2D-BE9E-6FDF37FDFD0E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6CE93CB-998F-4F2D-BE9E-6FDF37FDFD0E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6CE93CB-998F-4F2D-BE9E-6FDF37FDFD0E}.Release|Any CPU.Build.0 = Release|Any CPU + {24D7BD00-EC45-4B98-92BB-C6FFB01F66ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {24D7BD00-EC45-4B98-92BB-C6FFB01F66ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {24D7BD00-EC45-4B98-92BB-C6FFB01F66ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {24D7BD00-EC45-4B98-92BB-C6FFB01F66ED}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {9E533D43-452A-40D6-852B-01E8391BBFF9} = {6F154F8D-3437-45EE-9D89-02B96BDF3E8E} + {D4DAAEDE-A550-42BB-A50C-AD8FCB23D00A} = {6F154F8D-3437-45EE-9D89-02B96BDF3E8E} + {8BE3C29B-6E9F-4DFC-BAC3-14229D58616F} = {6F154F8D-3437-45EE-9D89-02B96BDF3E8E} + {D424B54F-AF26-4A39-8D2B-CF874F31DE42} = {7DA26C36-778E-4563-9AEC-966E26EA7B2A} + {24D7BD00-EC45-4B98-92BB-C6FFB01F66ED} = {7DA26C36-778E-4563-9AEC-966E26EA7B2A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {FBA0CB49-EF2D-4538-9D00-FCEDA24879A9} diff --git a/DepartmentPortal/DepartmentPortalDesctop/DepartmentPortal.config b/DepartmentPortal/DepartmentPortalDesctop/DepartmentPortal.config new file mode 100644 index 0000000..0151204 --- /dev/null +++ b/DepartmentPortal/DepartmentPortalDesctop/DepartmentPortal.config @@ -0,0 +1,4 @@ + + + Data Source=10.3.1.13\SQLEXPRESS;Initial Catalog=DepartmentDatabasePortal;persist security info=True;user id=sa;password=isadmin;MultipleActiveResultSets=True; + \ No newline at end of file diff --git a/DepartmentPortal/DepartmentPortalDesctop/DepartmentPortalDesctop.csproj b/DepartmentPortal/DepartmentPortalDesctop/DepartmentPortalDesctop.csproj new file mode 100644 index 0000000..9b4d650 --- /dev/null +++ b/DepartmentPortal/DepartmentPortalDesctop/DepartmentPortalDesctop.csproj @@ -0,0 +1,27 @@ + + + + WinExe + net5.0-windows + true + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + Always + + + + \ No newline at end of file diff --git a/DepartmentPortal/DepartmentPortalDesctop/FormEnter.Designer.cs b/DepartmentPortal/DepartmentPortalDesctop/FormEnter.Designer.cs new file mode 100644 index 0000000..3a59812 --- /dev/null +++ b/DepartmentPortal/DepartmentPortalDesctop/FormEnter.Designer.cs @@ -0,0 +1,119 @@ + +namespace DepartmentPortalDesctop +{ + partial class FormEnter + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.labelLogin = new System.Windows.Forms.Label(); + this.textBoxLogin = new System.Windows.Forms.TextBox(); + this.labelPassword = new System.Windows.Forms.Label(); + this.textBoxPassword = new System.Windows.Forms.TextBox(); + this.buttonEnter = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // labelLogin + // + this.labelLogin.AutoSize = true; + this.labelLogin.Location = new System.Drawing.Point(12, 9); + this.labelLogin.Name = "labelLogin"; + this.labelLogin.Size = new System.Drawing.Size(44, 15); + this.labelLogin.TabIndex = 0; + this.labelLogin.Text = "Логин:"; + // + // textBoxLogin + // + this.textBoxLogin.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxLogin.Location = new System.Drawing.Point(70, 6); + this.textBoxLogin.Name = "textBoxLogin"; + this.textBoxLogin.Size = new System.Drawing.Size(242, 23); + this.textBoxLogin.TabIndex = 1; + // + // labelPassword + // + this.labelPassword.AutoSize = true; + this.labelPassword.Location = new System.Drawing.Point(12, 49); + this.labelPassword.Name = "labelPassword"; + this.labelPassword.Size = new System.Drawing.Size(52, 15); + this.labelPassword.TabIndex = 2; + this.labelPassword.Text = "Пароль:"; + // + // textBoxPassword + // + this.textBoxPassword.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBoxPassword.Location = new System.Drawing.Point(70, 46); + this.textBoxPassword.Name = "textBoxPassword"; + this.textBoxPassword.Size = new System.Drawing.Size(242, 23); + this.textBoxPassword.TabIndex = 3; + this.textBoxPassword.UseSystemPasswordChar = true; + // + // buttonEnter + // + this.buttonEnter.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.buttonEnter.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonEnter.DialogResult = System.Windows.Forms.DialogResult.OK; + this.buttonEnter.Location = new System.Drawing.Point(88, 88); + this.buttonEnter.MinimumSize = new System.Drawing.Size(100, 30); + this.buttonEnter.Name = "buttonEnter"; + this.buttonEnter.Size = new System.Drawing.Size(167, 30); + this.buttonEnter.TabIndex = 4; + this.buttonEnter.Text = "Вход"; + this.buttonEnter.UseVisualStyleBackColor = true; + this.buttonEnter.Click += new System.EventHandler(this.ButtonEnter_Click); + // + // FormEnter + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(324, 131); + this.Controls.Add(this.buttonEnter); + this.Controls.Add(this.textBoxPassword); + this.Controls.Add(this.labelPassword); + this.Controls.Add(this.textBoxLogin); + this.Controls.Add(this.labelLogin); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "FormEnter"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Вход в систему"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label labelLogin; + private System.Windows.Forms.TextBox textBoxLogin; + private System.Windows.Forms.Label labelPassword; + private System.Windows.Forms.TextBox textBoxPassword; + private System.Windows.Forms.Button buttonEnter; + } +} \ No newline at end of file diff --git a/DepartmentPortal/DepartmentPortalDesctop/FormEnter.cs b/DepartmentPortal/DepartmentPortalDesctop/FormEnter.cs new file mode 100644 index 0000000..acfb1b8 --- /dev/null +++ b/DepartmentPortal/DepartmentPortalDesctop/FormEnter.cs @@ -0,0 +1,32 @@ +using SecurityBusinessLogic.BusinessLogics; +using System; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace DepartmentPortalDesctop +{ + /// + /// Форма входа в систему + /// + public partial class FormEnter : Form + { + public FormEnter() + { + InitializeComponent(); + } + + private void ButtonEnter_Click(object sender, EventArgs e) + { + try + { + Task.WaitAll(Task.Run(async () => await UserManager.GetInstance.LoginAsync(textBoxLogin.Text, textBoxPassword.Text))); + DialogResult = DialogResult.OK; + Close(); + } + catch (Exception ex) + { + //ErrorMessanger.PrintErrorMessage("При аутентфикации возникла ошибка: ", new List> { new KeyValuePair("Аутентфикация", ex.Message) }); + } + } + } +} diff --git a/DepartmentPortal/DepartmentPortalDesctop/FormEnter.resx b/DepartmentPortal/DepartmentPortalDesctop/FormEnter.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/DepartmentPortal/DepartmentPortalDesctop/FormEnter.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/DepartmentPortal/DepartmentPortalDesctop/FormMain.Designer.cs b/DepartmentPortal/DepartmentPortalDesctop/FormMain.Designer.cs new file mode 100644 index 0000000..39fe88e --- /dev/null +++ b/DepartmentPortal/DepartmentPortalDesctop/FormMain.Designer.cs @@ -0,0 +1,125 @@ + +namespace DepartmentPortalDesctop +{ + partial class FormMain + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.menuMain = new System.Windows.Forms.MenuStrip(); + this.panelControls = new System.Windows.Forms.Panel(); + this.listBoxControls = new System.Windows.Forms.ListBox(); + this.splitContainerMain = new System.Windows.Forms.SplitContainer(); + this.ButtonShowHideControlList = new System.Windows.Forms.Button(); + this.panelControls.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainerMain)).BeginInit(); + this.splitContainerMain.SuspendLayout(); + this.SuspendLayout(); + // + // menuMain + // + this.menuMain.Location = new System.Drawing.Point(0, 0); + this.menuMain.Name = "menuMain"; + this.menuMain.Size = new System.Drawing.Size(800, 24); + this.menuMain.TabIndex = 0; + this.menuMain.Text = "Главное меню"; + // + // panelControls + // + this.panelControls.Controls.Add(this.listBoxControls); + this.panelControls.Dock = System.Windows.Forms.DockStyle.Left; + this.panelControls.Location = new System.Drawing.Point(0, 24); + this.panelControls.Name = "panelControls"; + this.panelControls.Size = new System.Drawing.Size(191, 426); + this.panelControls.TabIndex = 1; + // + // listBoxControls + // + this.listBoxControls.Dock = System.Windows.Forms.DockStyle.Fill; + this.listBoxControls.FormattingEnabled = true; + this.listBoxControls.ItemHeight = 15; + this.listBoxControls.Location = new System.Drawing.Point(0, 0); + this.listBoxControls.Name = "listBoxControls"; + this.listBoxControls.Size = new System.Drawing.Size(191, 426); + this.listBoxControls.TabIndex = 0; + // + // splitContainerMain + // + this.splitContainerMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainerMain.Location = new System.Drawing.Point(216, 24); + this.splitContainerMain.Name = "splitContainerMain"; + this.splitContainerMain.Panel1MinSize = 100; + // + // splitContainerMain.Panel2 + // + this.splitContainerMain.Panel2.AutoScroll = true; + this.splitContainerMain.Size = new System.Drawing.Size(584, 426); + this.splitContainerMain.SplitterDistance = 295; + this.splitContainerMain.TabIndex = 2; + // + // ButtonShowHideControlList + // + this.ButtonShowHideControlList.Dock = System.Windows.Forms.DockStyle.Left; + this.ButtonShowHideControlList.Location = new System.Drawing.Point(191, 24); + this.ButtonShowHideControlList.Name = "ButtonShowHideControlList"; + this.ButtonShowHideControlList.Size = new System.Drawing.Size(25, 426); + this.ButtonShowHideControlList.TabIndex = 3; + this.ButtonShowHideControlList.Text = ">"; + this.ButtonShowHideControlList.UseVisualStyleBackColor = true; + this.ButtonShowHideControlList.Click += new System.EventHandler(this.ButtonShowHideControlList_Click); + // + // FormMain + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.splitContainerMain); + this.Controls.Add(this.ButtonShowHideControlList); + this.Controls.Add(this.panelControls); + this.Controls.Add(this.menuMain); + this.MainMenuStrip = this.menuMain; + this.Name = "FormMain"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Кафедральный портал"; + this.WindowState = System.Windows.Forms.FormWindowState.Maximized; + this.panelControls.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainerMain)).EndInit(); + this.splitContainerMain.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip menuMain; + private System.Windows.Forms.Panel panelControls; + private System.Windows.Forms.ListBox listBoxControls; + private System.Windows.Forms.SplitContainer splitContainerMain; + private System.Windows.Forms.Button ButtonShowHideControlList; + } +} + diff --git a/DepartmentPortal/DepartmentPortalDesctop/FormMain.cs b/DepartmentPortal/DepartmentPortalDesctop/FormMain.cs new file mode 100644 index 0000000..86a3111 --- /dev/null +++ b/DepartmentPortal/DepartmentPortalDesctop/FormMain.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace DepartmentPortalDesctop +{ + public partial class FormMain : Form + { + private Dictionary controls; + public FormMain() + { + InitializeComponent(); + controls = new Dictionary(); + } + + private void ButtonShowHideControlList_Click(object sender, EventArgs e) + { + ButtonShowHideControlList.Text = panelControls.Visible ? ">" : "<"; + panelControls.Visible = !panelControls.Visible; + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/DepartmentPortalDesctop/FormMain.resx b/DepartmentPortal/DepartmentPortalDesctop/FormMain.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/DepartmentPortal/DepartmentPortalDesctop/FormMain.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/DepartmentPortal/DepartmentPortalDesctop/Program.cs b/DepartmentPortal/DepartmentPortalDesctop/Program.cs new file mode 100644 index 0000000..2f29dcd --- /dev/null +++ b/DepartmentPortal/DepartmentPortalDesctop/Program.cs @@ -0,0 +1,33 @@ +using DatabaseCore; +using ModelTools.BusinessLogics; +using ModelTools.Interfaces; +using SecurityBusinessLogic.BusinessLogics; +using System; +using System.Windows.Forms; + +namespace DepartmentPortalDesctop +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + UnityContainerConfigurator.PublishService(); + UnityContainerConfigurator.InitServices(); + + Application.SetHighDpiMode(HighDpiMode.SystemAware); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + var form = new FormEnter(); + + if (form.ShowDialog() == DialogResult.OK && UserManager.GetInstance.IsAuth) + { + Application.Run(UnityContainerConfigurator.Resolve()); + } + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Extensions/net5.0/DatabaseCore.dll b/DepartmentPortal/Extensions/net5.0/DatabaseCore.dll new file mode 100644 index 0000000000000000000000000000000000000000..c57f744f73a30d891447af7d26760140ab0f91c2 GIT binary patch literal 47616 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 HHSm7{>rn&4 literal 0 HcmV?d00001 diff --git a/DepartmentPortal/Extensions/net5.0/ModelTools.dll b/DepartmentPortal/Extensions/net5.0/ModelTools.dll new file mode 100644 index 0000000000000000000000000000000000000000..f6de6c20f1109287069373739f0304b8f0f96776 GIT binary patch literal 19968 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 Y{uljhQUA{;M1& literal 0 HcmV?d00001 diff --git a/DepartmentPortal/Extensions/net5.0/SecurityBusinessLogic.dll b/DepartmentPortal/Extensions/net5.0/SecurityBusinessLogic.dll new file mode 100644 index 0000000000000000000000000000000000000000..522d2d8407c4dfa6dc1ee2e62af35cf62e210705 GIT binary patch literal 19968 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 literal 0 HcmV?d00001 diff --git a/DepartmentPortal/Extensions/net5.0/SecurityImplementation.deps.json b/DepartmentPortal/Extensions/net5.0/SecurityImplementation.deps.json new file mode 100644 index 0000000..d56a467 --- /dev/null +++ b/DepartmentPortal/Extensions/net5.0/SecurityImplementation.deps.json @@ -0,0 +1,1782 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v5.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v5.0": { + "SecurityImplementation/1.0.0": { + "dependencies": { + "DatabaseCore": "1.0.0", + "SecurityBusinessLogic": "1.0.0" + }, + "runtime": { + "SecurityImplementation.dll": {} + } + }, + "Microsoft.CSharp/4.5.0": {}, + "Microsoft.Data.SqlClient/2.0.1": { + "dependencies": { + "Microsoft.Data.SqlClient.SNI.runtime": "2.0.1", + "Microsoft.Identity.Client": "4.14.0", + "Microsoft.IdentityModel.JsonWebTokens": "5.6.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0", + "Microsoft.Win32.Registry": "4.7.0", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Diagnostics.DiagnosticSource": "5.0.1", + "System.Runtime.Caching": "4.7.0", + "System.Security.Principal.Windows": "4.7.0", + "System.Text.Encoding.CodePages": "4.7.0" + }, + "runtime": { + "lib/netcoreapp3.1/Microsoft.Data.SqlClient.dll": { + "assemblyVersion": "2.0.20168.4", + "fileVersion": "2.0.20168.4" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/netcoreapp3.1/Microsoft.Data.SqlClient.dll": { + "rid": "unix", + "assetType": "runtime", + "assemblyVersion": "2.0.20168.4", + "fileVersion": "2.0.20168.4" + }, + "runtimes/win/lib/netcoreapp3.1/Microsoft.Data.SqlClient.dll": { + "rid": "win", + "assetType": "runtime", + "assemblyVersion": "2.0.20168.4", + "fileVersion": "2.0.20168.4" + } + } + }, + "Microsoft.Data.SqlClient.SNI.runtime/2.0.1": { + "runtimeTargets": { + "runtimes/win-arm/native/Microsoft.Data.SqlClient.SNI.dll": { + "rid": "win-arm", + "assetType": "native", + "fileVersion": "2.0.1.0" + }, + "runtimes/win-arm/native/Microsoft.Data.SqlClient.SNI.pdb": { + "rid": "win-arm", + "assetType": "native", + "fileVersion": "0.0.0.0" + }, + "runtimes/win-arm64/native/Microsoft.Data.SqlClient.SNI.dll": { + "rid": "win-arm64", + "assetType": "native", + "fileVersion": "2.0.1.0" + }, + "runtimes/win-arm64/native/Microsoft.Data.SqlClient.SNI.pdb": { + "rid": "win-arm64", + "assetType": "native", + "fileVersion": "0.0.0.0" + }, + "runtimes/win-x64/native/Microsoft.Data.SqlClient.SNI.dll": { + "rid": "win-x64", + "assetType": "native", + "fileVersion": "2.0.1.0" + }, + "runtimes/win-x64/native/Microsoft.Data.SqlClient.SNI.pdb": { + "rid": "win-x64", + "assetType": "native", + "fileVersion": "0.0.0.0" + }, + "runtimes/win-x86/native/Microsoft.Data.SqlClient.SNI.dll": { + "rid": "win-x86", + "assetType": "native", + "fileVersion": "2.0.1.0" + }, + "runtimes/win-x86/native/Microsoft.Data.SqlClient.SNI.pdb": { + "rid": "win-x86", + "assetType": "native", + "fileVersion": "0.0.0.0" + } + } + }, + "Microsoft.EntityFrameworkCore/5.0.4": { + "dependencies": { + "Microsoft.EntityFrameworkCore.Abstractions": "5.0.4", + "Microsoft.EntityFrameworkCore.Analyzers": "5.0.4", + "Microsoft.Extensions.Caching.Memory": "5.0.0", + "Microsoft.Extensions.DependencyInjection": "5.0.1", + "Microsoft.Extensions.Logging": "5.0.0", + "System.Collections.Immutable": "5.0.0", + "System.ComponentModel.Annotations": "5.0.0", + "System.Diagnostics.DiagnosticSource": "5.0.1" + }, + "runtime": { + "lib/netstandard2.1/Microsoft.EntityFrameworkCore.dll": { + "assemblyVersion": "5.0.4.0", + "fileVersion": "5.0.421.11803" + } + } + }, + "Microsoft.EntityFrameworkCore.Abstractions/5.0.4": { + "runtime": { + "lib/netstandard2.1/Microsoft.EntityFrameworkCore.Abstractions.dll": { + "assemblyVersion": "5.0.4.0", + "fileVersion": "5.0.421.11803" + } + } + }, + "Microsoft.EntityFrameworkCore.Analyzers/5.0.4": {}, + "Microsoft.EntityFrameworkCore.Relational/5.0.4": { + "dependencies": { + "Microsoft.EntityFrameworkCore": "5.0.4", + "Microsoft.Extensions.Configuration.Abstractions": "5.0.0" + }, + "runtime": { + "lib/netstandard2.1/Microsoft.EntityFrameworkCore.Relational.dll": { + "assemblyVersion": "5.0.4.0", + "fileVersion": "5.0.421.11803" + } + } + }, + "Microsoft.EntityFrameworkCore.SqlServer/5.0.4": { + "dependencies": { + "Microsoft.Data.SqlClient": "2.0.1", + "Microsoft.EntityFrameworkCore.Relational": "5.0.4" + }, + "runtime": { + "lib/netstandard2.1/Microsoft.EntityFrameworkCore.SqlServer.dll": { + "assemblyVersion": "5.0.4.0", + "fileVersion": "5.0.421.11803" + } + } + }, + "Microsoft.Extensions.Caching.Abstractions/5.0.0": { + "dependencies": { + "Microsoft.Extensions.Primitives": "5.0.0" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll": { + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.20.51904" + } + } + }, + "Microsoft.Extensions.Caching.Memory/5.0.0": { + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "5.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0", + "Microsoft.Extensions.Logging.Abstractions": "5.0.0", + "Microsoft.Extensions.Options": "5.0.0", + "Microsoft.Extensions.Primitives": "5.0.0" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Caching.Memory.dll": { + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.20.51904" + } + } + }, + "Microsoft.Extensions.Configuration.Abstractions/5.0.0": { + "dependencies": { + "Microsoft.Extensions.Primitives": "5.0.0" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Abstractions.dll": { + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.20.51904" + } + } + }, + "Microsoft.Extensions.DependencyInjection/5.0.1": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0" + }, + "runtime": { + "lib/net5.0/Microsoft.Extensions.DependencyInjection.dll": { + "assemblyVersion": "5.0.0.1", + "fileVersion": "5.0.120.57516" + } + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": { + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.20.51904" + } + } + }, + "Microsoft.Extensions.Logging/5.0.0": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.1", + "Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0", + "Microsoft.Extensions.Logging.Abstractions": "5.0.0", + "Microsoft.Extensions.Options": "5.0.0" + }, + "runtime": { + "lib/netstandard2.1/Microsoft.Extensions.Logging.dll": { + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.20.51904" + } + } + }, + "Microsoft.Extensions.Logging.Abstractions/5.0.0": { + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.dll": { + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.20.51904" + } + } + }, + "Microsoft.Extensions.Options/5.0.0": { + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "5.0.0", + "Microsoft.Extensions.Primitives": "5.0.0" + }, + "runtime": { + "lib/net5.0/Microsoft.Extensions.Options.dll": { + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.20.51904" + } + } + }, + "Microsoft.Extensions.Primitives/5.0.0": { + "runtime": { + "lib/netcoreapp3.0/Microsoft.Extensions.Primitives.dll": { + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.20.51904" + } + } + }, + "Microsoft.Identity.Client/4.14.0": { + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "System.ComponentModel.TypeConverter": "4.3.0", + "System.Net.NameResolution": "4.3.0", + "System.Private.Uri": "4.3.2", + "System.Runtime.Serialization.Formatters": "4.3.0", + "System.Runtime.Serialization.Json": "4.3.0", + "System.Runtime.Serialization.Primitives": "4.3.0", + "System.Security.SecureString": "4.3.0", + "System.Xml.XDocument": "4.3.0" + }, + "runtime": { + "lib/netcoreapp2.1/Microsoft.Identity.Client.dll": { + "assemblyVersion": "4.14.0.0", + "fileVersion": "4.14.0.0" + } + } + }, + "Microsoft.IdentityModel.JsonWebTokens/5.6.0": { + "dependencies": { + "Microsoft.IdentityModel.Tokens": "5.6.0", + "Newtonsoft.Json": "10.0.1" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.JsonWebTokens.dll": { + "assemblyVersion": "5.6.0.0", + "fileVersion": "5.6.0.61018" + } + } + }, + "Microsoft.IdentityModel.Logging/5.6.0": { + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.Logging.dll": { + "assemblyVersion": "5.6.0.0", + "fileVersion": "5.6.0.61018" + } + } + }, + "Microsoft.IdentityModel.Protocols/5.6.0": { + "dependencies": { + "Microsoft.IdentityModel.Logging": "5.6.0", + "Microsoft.IdentityModel.Tokens": "5.6.0" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.dll": { + "assemblyVersion": "5.6.0.0", + "fileVersion": "5.6.0.61018" + } + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect/5.6.0": { + "dependencies": { + "Microsoft.IdentityModel.Protocols": "5.6.0", + "Newtonsoft.Json": "10.0.1", + "System.IdentityModel.Tokens.Jwt": "5.6.0" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll": { + "assemblyVersion": "5.6.0.0", + "fileVersion": "5.6.0.61018" + } + } + }, + "Microsoft.IdentityModel.Tokens/5.6.0": { + "dependencies": { + "Microsoft.IdentityModel.Logging": "5.6.0", + "Newtonsoft.Json": "10.0.1", + "System.Security.Cryptography.Cng": "4.5.0" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.dll": { + "assemblyVersion": "5.6.0.0", + "fileVersion": "5.6.0.61018" + } + } + }, + "Microsoft.NETCore.Platforms/3.1.0": {}, + "Microsoft.NETCore.Targets/1.1.3": {}, + "Microsoft.Win32.Registry/4.7.0": { + "dependencies": { + "System.Security.AccessControl": "4.7.0", + "System.Security.Principal.Windows": "4.7.0" + } + }, + "Microsoft.Win32.SystemEvents/4.7.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0" + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Win32.SystemEvents.dll": { + "assemblyVersion": "4.0.2.0", + "fileVersion": "4.700.19.56404" + } + }, + "runtimeTargets": { + "runtimes/win/lib/netcoreapp3.0/Microsoft.Win32.SystemEvents.dll": { + "rid": "win", + "assetType": "runtime", + "assemblyVersion": "4.0.2.0", + "fileVersion": "4.700.19.56404" + } + } + }, + "Newtonsoft.Json/10.0.1": { + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "System.Collections": "4.3.0", + "System.ComponentModel.TypeConverter": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Dynamic.Runtime": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Runtime.Serialization.Formatters": "4.3.0", + "System.Runtime.Serialization.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + }, + "runtime": { + "lib/netstandard1.3/Newtonsoft.Json.dll": { + "assemblyVersion": "10.0.0.0", + "fileVersion": "10.0.1.20720" + } + } + }, + "runtime.native.System/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3" + } + }, + "System.Collections/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable/5.0.0": {}, + "System.Collections.NonGeneric/4.3.0": { + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Collections.Specialized/4.3.0": { + "dependencies": { + "System.Collections.NonGeneric": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.ComponentModel/4.3.0": { + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.ComponentModel.Annotations/5.0.0": {}, + "System.ComponentModel.Primitives/4.3.0": { + "dependencies": { + "System.ComponentModel": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.ComponentModel.TypeConverter/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Collections.NonGeneric": "4.3.0", + "System.Collections.Specialized": "4.3.0", + "System.ComponentModel": "4.3.0", + "System.ComponentModel.Primitives": "4.3.0", + "System.Globalization": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Configuration.ConfigurationManager/4.7.0": { + "dependencies": { + "System.Security.Cryptography.ProtectedData": "4.7.0", + "System.Security.Permissions": "4.7.0" + }, + "runtime": { + "lib/netstandard2.0/System.Configuration.ConfigurationManager.dll": { + "assemblyVersion": "4.0.3.0", + "fileVersion": "4.700.19.56404" + } + } + }, + "System.Diagnostics.Debug/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource/5.0.1": { + "runtime": { + "lib/net5.0/System.Diagnostics.DiagnosticSource.dll": { + "assemblyVersion": "5.0.0.0", + "fileVersion": "5.0.220.61120" + } + } + }, + "System.Diagnostics.Tools/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.Tracing/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common/4.7.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.Win32.SystemEvents": "4.7.0" + }, + "runtime": { + "lib/netstandard2.0/System.Drawing.Common.dll": { + "assemblyVersion": "4.0.0.1", + "fileVersion": "4.6.26919.2" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/netcoreapp3.0/System.Drawing.Common.dll": { + "rid": "unix", + "assetType": "runtime", + "assemblyVersion": "4.0.2.0", + "fileVersion": "4.700.19.56404" + }, + "runtimes/win/lib/netcoreapp3.0/System.Drawing.Common.dll": { + "rid": "win", + "assetType": "runtime", + "assemblyVersion": "4.0.2.0", + "fileVersion": "4.700.19.56404" + } + } + }, + "System.Dynamic.Runtime/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Globalization/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IdentityModel.Tokens.Jwt/5.6.0": { + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "5.6.0", + "Microsoft.IdentityModel.Tokens": "5.6.0", + "Newtonsoft.Json": "10.0.1" + }, + "runtime": { + "lib/netstandard2.0/System.IdentityModel.Tokens.Jwt.dll": { + "assemblyVersion": "5.6.0.0", + "fileVersion": "5.6.0.61018" + } + } + }, + "System.IO/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives/4.3.0": { + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Linq/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Net.NameResolution/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Principal.Windows": "4.7.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Net.Primitives/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.ObjectModel/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Private.DataContractSerialization/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Serialization.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0", + "System.Xml.XmlDocument": "4.3.0", + "System.Xml.XmlSerializer": "4.3.0" + } + }, + "System.Private.Uri/4.3.2": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3" + } + }, + "System.Reflection/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit/4.3.0": { + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration/4.3.0": { + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight/4.3.0": { + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Primitives/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions/4.3.0": { + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3" + } + }, + "System.Runtime.Caching/4.7.0": { + "dependencies": { + "System.Configuration.ConfigurationManager": "4.7.0" + }, + "runtime": { + "lib/netstandard2.0/System.Runtime.Caching.dll": { + "assemblyVersion": "4.0.1.0", + "fileVersion": "4.700.19.56404" + } + }, + "runtimeTargets": { + "runtimes/win/lib/netstandard2.0/System.Runtime.Caching.dll": { + "rid": "win", + "assetType": "runtime", + "assemblyVersion": "4.0.1.0", + "fileVersion": "4.700.19.56404" + } + } + }, + "System.Runtime.CompilerServices.Unsafe/4.5.2": {}, + "System.Runtime.Extensions/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.Numerics/4.3.0": { + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Runtime.Serialization.Formatters/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Serialization.Primitives": "4.3.0" + } + }, + "System.Runtime.Serialization.Json/4.3.0": { + "dependencies": { + "System.IO": "4.3.0", + "System.Private.DataContractSerialization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Serialization.Primitives/4.3.0": { + "dependencies": { + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Security.AccessControl/4.7.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "System.Security.Principal.Windows": "4.7.0" + } + }, + "System.Security.Cryptography.Cng/4.5.0": {}, + "System.Security.Cryptography.Primitives/4.3.0": { + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.ProtectedData/4.7.0": { + "runtime": { + "lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll": { + "assemblyVersion": "4.0.5.0", + "fileVersion": "4.700.19.56404" + } + }, + "runtimeTargets": { + "runtimes/win/lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll": { + "rid": "win", + "assetType": "runtime", + "assemblyVersion": "4.0.5.0", + "fileVersion": "4.700.19.56404" + } + } + }, + "System.Security.Permissions/4.7.0": { + "dependencies": { + "System.Security.AccessControl": "4.7.0", + "System.Windows.Extensions": "4.7.0" + }, + "runtime": { + "lib/netcoreapp3.0/System.Security.Permissions.dll": { + "assemblyVersion": "4.0.3.0", + "fileVersion": "4.700.19.56404" + } + } + }, + "System.Security.Principal.Windows/4.7.0": {}, + "System.Security.SecureString/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Text.Encoding/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages/4.7.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0" + } + }, + "System.Text.Encoding.Extensions/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.RegularExpressions/4.3.0": { + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading/4.3.0": { + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Tasks/4.3.0": { + "dependencies": { + "Microsoft.NETCore.Platforms": "3.1.0", + "Microsoft.NETCore.Targets": "1.1.3", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Windows.Extensions/4.7.0": { + "dependencies": { + "System.Drawing.Common": "4.7.0" + }, + "runtime": { + "lib/netcoreapp3.0/System.Windows.Extensions.dll": { + "assemblyVersion": "4.0.1.0", + "fileVersion": "4.700.19.56404" + } + }, + "runtimeTargets": { + "runtimes/win/lib/netcoreapp3.0/System.Windows.Extensions.dll": { + "rid": "win", + "assetType": "runtime", + "assemblyVersion": "4.0.1.0", + "fileVersion": "4.700.19.56404" + } + } + }, + "System.Xml.ReaderWriter/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlDocument/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlSerializer/4.3.0": { + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "Unity/5.11.10": { + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "4.5.2" + }, + "runtime": { + "lib/netcoreapp3.0/Unity.Abstractions.dll": { + "assemblyVersion": "5.11.7.0", + "fileVersion": "5.11.7.0" + }, + "lib/netcoreapp3.0/Unity.Container.dll": { + "assemblyVersion": "5.11.11.0", + "fileVersion": "5.11.11.0" + } + } + }, + "DatabaseCore/1.0.0": { + "dependencies": { + "Microsoft.EntityFrameworkCore": "5.0.4", + "Microsoft.EntityFrameworkCore.SqlServer": "5.0.4", + "ModelTools": "1.0.0", + "SecurityBusinessLogic": "1.0.0" + }, + "runtime": { + "DatabaseCore.dll": {} + } + }, + "ModelTools/1.0.0": { + "dependencies": { + "Unity": "5.11.10" + }, + "runtime": { + "ModelTools.dll": {} + } + }, + "SecurityBusinessLogic/1.0.0": { + "dependencies": { + "ModelTools": "1.0.0" + }, + "runtime": { + "SecurityBusinessLogic.dll": {} + } + } + } + }, + "libraries": { + "SecurityImplementation/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "Microsoft.CSharp/4.5.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-kaj6Wb4qoMuH3HySFJhxwQfe8R/sJsNJnANrvv8WdFPMoNbKY5htfNscv+LHCu5ipz+49m2e+WQXpLXr9XYemQ==", + "path": "microsoft.csharp/4.5.0", + "hashPath": "microsoft.csharp.4.5.0.nupkg.sha512" + }, + "Microsoft.Data.SqlClient/2.0.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-cff+ug/XZnGmX6DFgLY92t7G9W3i8r23w5Qnuby41l9rS+X+f7Y51hV5glvIrmsu3tIcnxbR+Z4CQ2zGhksIJw==", + "path": "microsoft.data.sqlclient/2.0.1", + "hashPath": "microsoft.data.sqlclient.2.0.1.nupkg.sha512" + }, + "Microsoft.Data.SqlClient.SNI.runtime/2.0.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-MalWSIMdwLZoNXxjmFmeRrFgaUXbEADkYNGm6HM33pculFv8gKt53s1Frs+kTfVPWMYjocd4gqwz92KrkcLfXA==", + "path": "microsoft.data.sqlclient.sni.runtime/2.0.1", + "hashPath": "microsoft.data.sqlclient.sni.runtime.2.0.1.nupkg.sha512" + }, + "Microsoft.EntityFrameworkCore/5.0.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-upRpXluUeONMYO+O3RU8G+ZZcrnDrnNVWg4eJmSfertTdw7Hc5tgIeg/O8+oBKqf+OvBrQKW0U3PI9yoTsuPYg==", + "path": "microsoft.entityframeworkcore/5.0.4", + "hashPath": "microsoft.entityframeworkcore.5.0.4.nupkg.sha512" + }, + "Microsoft.EntityFrameworkCore.Abstractions/5.0.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-4y+y28SHjniLIqj7M7YNRO8khBnCBtkM6TJG8oX0wyEZuLum+3e9vqqna1naaV6Hi4BhXBHcD/sjhIfW1u0ZfQ==", + "path": "microsoft.entityframeworkcore.abstractions/5.0.4", + "hashPath": "microsoft.entityframeworkcore.abstractions.5.0.4.nupkg.sha512" + }, + "Microsoft.EntityFrameworkCore.Analyzers/5.0.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-z8OMwlXcUZJCArcDdhR0NRkmS0UyNg08l1LXPZCgYqjBeW8RvNXshH3H5ru/7IOVpyOfKrG5Q3nsgdD18OFG/g==", + "path": "microsoft.entityframeworkcore.analyzers/5.0.4", + "hashPath": "microsoft.entityframeworkcore.analyzers.5.0.4.nupkg.sha512" + }, + "Microsoft.EntityFrameworkCore.Relational/5.0.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-9Qa6SqX+hJZogo99bICsS6kgQ1C5RtEjPrsvQxjInVdY9QSWsXWIYfem0rv3wi+htwkJuMHVHGSaqG1oeAwe+w==", + "path": "microsoft.entityframeworkcore.relational/5.0.4", + "hashPath": "microsoft.entityframeworkcore.relational.5.0.4.nupkg.sha512" + }, + "Microsoft.EntityFrameworkCore.SqlServer/5.0.4": { + "type": "package", + "serviceable": true, + "sha512": "sha512-wFn6lYyezhTIWpEB85NYn0TmVs0GiTQBbgKxK4/BmeEXBoLdltOngosey1u9t1+c2xjxuis1V7fP3wcLVSf+jg==", + "path": "microsoft.entityframeworkcore.sqlserver/5.0.4", + "hashPath": "microsoft.entityframeworkcore.sqlserver.5.0.4.nupkg.sha512" + }, + "Microsoft.Extensions.Caching.Abstractions/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-bu8As90/SBAouMZ6fJ+qRNo1X+KgHGrVueFhhYi+E5WqEhcnp2HoWRFnMzXQ6g4RdZbvPowFerSbKNH4Dtg5yg==", + "path": "microsoft.extensions.caching.abstractions/5.0.0", + "hashPath": "microsoft.extensions.caching.abstractions.5.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Caching.Memory/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-/1qPCleFOkJe0O+xmFqCNLFYQZTJz965sVw8CUB/BQgsApBwzAUsL2BUkDvQW+geRUVTXUS9zLa0pBjC2VJ1gA==", + "path": "microsoft.extensions.caching.memory/5.0.0", + "hashPath": "microsoft.extensions.caching.memory.5.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Configuration.Abstractions/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ETjSBHMp3OAZ4HxGQYpwyGsD8Sw5FegQXphi0rpoGMT74S4+I2mm7XJEswwn59XAaKOzC15oDSOWEE8SzDCd6Q==", + "path": "microsoft.extensions.configuration.abstractions/5.0.0", + "hashPath": "microsoft.extensions.configuration.abstractions.5.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.DependencyInjection/5.0.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-//mDNrYeiJ0eh/awFhDFJQzkRVra/njU5Y4fyK7X29g5HScrzbUkKOKlyTtygthcGFt4zNC8G5CFCjb/oizomA==", + "path": "microsoft.extensions.dependencyinjection/5.0.1", + "hashPath": "microsoft.extensions.dependencyinjection.5.0.1.nupkg.sha512" + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ORj7Zh81gC69TyvmcUm9tSzytcy8AVousi+IVRAI8nLieQjOFryRusSFh7+aLk16FN9pQNqJAiMd7BTKINK0kA==", + "path": "microsoft.extensions.dependencyinjection.abstractions/5.0.0", + "hashPath": "microsoft.extensions.dependencyinjection.abstractions.5.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Logging/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-MgOwK6tPzB6YNH21wssJcw/2MKwee8b2gI7SllYfn6rvTpIrVvVS5HAjSU2vqSku1fwqRvWP0MdIi14qjd93Aw==", + "path": "microsoft.extensions.logging/5.0.0", + "hashPath": "microsoft.extensions.logging.5.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Logging.Abstractions/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-NxP6ahFcBnnSfwNBi2KH2Oz8Xl5Sm2krjId/jRR3I7teFphwiUoUeZPwTNA21EX+5PtjqmyAvKaOeBXcJjcH/w==", + "path": "microsoft.extensions.logging.abstractions/5.0.0", + "hashPath": "microsoft.extensions.logging.abstractions.5.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Options/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-CBvR92TCJ5uBIdd9/HzDSrxYak+0W/3+yxrNg8Qm6Bmrkh5L+nu6m3WeazQehcZ5q1/6dDA7J5YdQjim0165zg==", + "path": "microsoft.extensions.options/5.0.0", + "hashPath": "microsoft.extensions.options.5.0.0.nupkg.sha512" + }, + "Microsoft.Extensions.Primitives/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-cI/VWn9G1fghXrNDagX9nYaaB/nokkZn0HYAawGaELQrl8InSezfe9OnfPZLcJq3esXxygh3hkq2c3qoV3SDyQ==", + "path": "microsoft.extensions.primitives/5.0.0", + "hashPath": "microsoft.extensions.primitives.5.0.0.nupkg.sha512" + }, + "Microsoft.Identity.Client/4.14.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-Etqux6Zuuv1yEN4UwKbAn6EZv0Rooc+vM4N9z7gxmeT7dyoKlXIRN44DQPzD9LV1CW0KsTVqH+2B42p1NKqPlQ==", + "path": "microsoft.identity.client/4.14.0", + "hashPath": "microsoft.identity.client.4.14.0.nupkg.sha512" + }, + "Microsoft.IdentityModel.JsonWebTokens/5.6.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-0q0U1W+gX1jmfmv7uU7GXFGB518atmSwucxsVwPGpuaGS3jwd2tUi+Gau+ezxR6oAFEBFKG9lz/fxRZzGMeDXg==", + "path": "microsoft.identitymodel.jsonwebtokens/5.6.0", + "hashPath": "microsoft.identitymodel.jsonwebtokens.5.6.0.nupkg.sha512" + }, + "Microsoft.IdentityModel.Logging/5.6.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-zEDrfEVW5x5w2hbTV94WwAcWvtue5hNTXYqoPh3ypF6U8csm09JazEYy+VPp2RtczkyMfcsvWY9Fea17e+isYQ==", + "path": "microsoft.identitymodel.logging/5.6.0", + "hashPath": "microsoft.identitymodel.logging.5.6.0.nupkg.sha512" + }, + "Microsoft.IdentityModel.Protocols/5.6.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ei7YqYx0pIFL6JjK8ZnPK0MXZRWUNHtJPUl3KqSvj9+2f5CMa6GRSEC+BMDHr17tP6yujYUg0IQOcKzmC7qN5g==", + "path": "microsoft.identitymodel.protocols/5.6.0", + "hashPath": "microsoft.identitymodel.protocols.5.6.0.nupkg.sha512" + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect/5.6.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-yh3n+uXiwpBy/5+t67tYcmRxb9kwQdaKRyG/DNipRMF37bg5Jr0vENOo1BQz6OySMl5WIK544SzPjtr7/KkucA==", + "path": "microsoft.identitymodel.protocols.openidconnect/5.6.0", + "hashPath": "microsoft.identitymodel.protocols.openidconnect.5.6.0.nupkg.sha512" + }, + "Microsoft.IdentityModel.Tokens/5.6.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-C3OqR3QfBQ7wcC7yAsdMQqay87OsV6yWPYG/Ai3n7dvmWIGkouQhXoVxRP0xz3cAFL4hxZBXyw4aLTC421PaMg==", + "path": "microsoft.identitymodel.tokens/5.6.0", + "hashPath": "microsoft.identitymodel.tokens.5.6.0.nupkg.sha512" + }, + "Microsoft.NETCore.Platforms/3.1.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-z7aeg8oHln2CuNulfhiLYxCVMPEwBl3rzicjvIX+4sUuCwvXw5oXQEtbiU2c0z4qYL5L3Kmx0mMA/+t/SbY67w==", + "path": "microsoft.netcore.platforms/3.1.0", + "hashPath": "microsoft.netcore.platforms.3.1.0.nupkg.sha512" + }, + "Microsoft.NETCore.Targets/1.1.3": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3Wrmi0kJDzClwAC+iBdUBpEKmEle8FQNsCs77fkiOIw/9oYA07bL1EZNX0kQ2OMN3xpwvl0vAtOCYY3ndDNlhQ==", + "path": "microsoft.netcore.targets/1.1.3", + "hashPath": "microsoft.netcore.targets.1.1.3.nupkg.sha512" + }, + "Microsoft.Win32.Registry/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-KSrRMb5vNi0CWSGG1++id2ZOs/1QhRqROt+qgbEAdQuGjGrFcl4AOl4/exGPUYz2wUnU42nvJqon1T3U0kPXLA==", + "path": "microsoft.win32.registry/4.7.0", + "hashPath": "microsoft.win32.registry.4.7.0.nupkg.sha512" + }, + "Microsoft.Win32.SystemEvents/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-mtVirZr++rq+XCDITMUdnETD59XoeMxSpLRIII7JRI6Yj0LEDiO1pPn0ktlnIj12Ix8bfvQqQDMMIF9wC98oCA==", + "path": "microsoft.win32.systemevents/4.7.0", + "hashPath": "microsoft.win32.systemevents.4.7.0.nupkg.sha512" + }, + "Newtonsoft.Json/10.0.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ebWzW9j2nwxQeBo59As2TYn7nYr9BHicqqCwHOD1Vdo+50HBtLPuqdiCYJcLdTRknpYis/DSEOQz5KmZxwrIAg==", + "path": "newtonsoft.json/10.0.1", + "hashPath": "newtonsoft.json.10.0.1.nupkg.sha512" + }, + "runtime.native.System/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "path": "runtime.native.system/4.3.0", + "hashPath": "runtime.native.system.4.3.0.nupkg.sha512" + }, + "System.Collections/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "path": "system.collections/4.3.0", + "hashPath": "system.collections.4.3.0.nupkg.sha512" + }, + "System.Collections.Concurrent/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "path": "system.collections.concurrent/4.3.0", + "hashPath": "system.collections.concurrent.4.3.0.nupkg.sha512" + }, + "System.Collections.Immutable/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-FXkLXiK0sVVewcso0imKQoOxjoPAj42R8HtjjbSjVPAzwDfzoyoznWxgA3c38LDbN9SJux1xXoXYAhz98j7r2g==", + "path": "system.collections.immutable/5.0.0", + "hashPath": "system.collections.immutable.5.0.0.nupkg.sha512" + }, + "System.Collections.NonGeneric/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-prtjIEMhGUnQq6RnPEYLpFt8AtLbp9yq2zxOSrY7KJJZrw25Fi97IzBqY7iqssbM61Ek5b8f3MG/sG1N2sN5KA==", + "path": "system.collections.nongeneric/4.3.0", + "hashPath": "system.collections.nongeneric.4.3.0.nupkg.sha512" + }, + "System.Collections.Specialized/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-Epx8PoVZR0iuOnJJDzp7pWvdfMMOAvpUo95pC4ScH2mJuXkKA2Y4aR3cG9qt2klHgSons1WFh4kcGW7cSXvrxg==", + "path": "system.collections.specialized/4.3.0", + "hashPath": "system.collections.specialized.4.3.0.nupkg.sha512" + }, + "System.ComponentModel/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-VyGn1jGRZVfxnh8EdvDCi71v3bMXrsu8aYJOwoV7SNDLVhiEqwP86pPMyRGsDsxhXAm2b3o9OIqeETfN5qfezw==", + "path": "system.componentmodel/4.3.0", + "hashPath": "system.componentmodel.4.3.0.nupkg.sha512" + }, + "System.ComponentModel.Annotations/5.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-dMkqfy2el8A8/I76n2Hi1oBFEbG1SfxD2l5nhwXV3XjlnOmwxJlQbYpJH4W51odnU9sARCSAgv7S3CyAFMkpYg==", + "path": "system.componentmodel.annotations/5.0.0", + "hashPath": "system.componentmodel.annotations.5.0.0.nupkg.sha512" + }, + "System.ComponentModel.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-j8GUkCpM8V4d4vhLIIoBLGey2Z5bCkMVNjEZseyAlm4n5arcsJOeI3zkUP+zvZgzsbLTYh4lYeP/ZD/gdIAPrw==", + "path": "system.componentmodel.primitives/4.3.0", + "hashPath": "system.componentmodel.primitives.4.3.0.nupkg.sha512" + }, + "System.ComponentModel.TypeConverter/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-16pQ6P+EdhcXzPiEK4kbA953Fu0MNG2ovxTZU81/qsCd1zPRsKc3uif5NgvllCY598k6bI0KUyKW8fanlfaDQg==", + "path": "system.componentmodel.typeconverter/4.3.0", + "hashPath": "system.componentmodel.typeconverter.4.3.0.nupkg.sha512" + }, + "System.Configuration.ConfigurationManager/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-/anOTeSZCNNI2zDilogWrZ8pNqCmYbzGNexUnNhjW8k0sHqEZ2nHJBp147jBV3hGYswu5lINpNg1vxR7bnqvVA==", + "path": "system.configuration.configurationmanager/4.7.0", + "hashPath": "system.configuration.configurationmanager.4.7.0.nupkg.sha512" + }, + "System.Diagnostics.Debug/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "path": "system.diagnostics.debug/4.3.0", + "hashPath": "system.diagnostics.debug.4.3.0.nupkg.sha512" + }, + "System.Diagnostics.DiagnosticSource/5.0.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-uXQEYqav2V3zP6OwkOKtLv+qIi6z3m1hsGyKwXX7ZA7htT4shoVccGxnJ9kVRFPNAsi1ArZTq2oh7WOto6GbkQ==", + "path": "system.diagnostics.diagnosticsource/5.0.1", + "hashPath": "system.diagnostics.diagnosticsource.5.0.1.nupkg.sha512" + }, + "System.Diagnostics.Tools/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "path": "system.diagnostics.tools/4.3.0", + "hashPath": "system.diagnostics.tools.4.3.0.nupkg.sha512" + }, + "System.Diagnostics.Tracing/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "path": "system.diagnostics.tracing/4.3.0", + "hashPath": "system.diagnostics.tracing.4.3.0.nupkg.sha512" + }, + "System.Drawing.Common/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-v+XbyYHaZjDfn0ENmJEV1VYLgGgCTx1gnfOBcppowbpOAriglYgGCvFCPr2EEZyBvXlpxbEsTwkOlInl107ahA==", + "path": "system.drawing.common/4.7.0", + "hashPath": "system.drawing.common.4.7.0.nupkg.sha512" + }, + "System.Dynamic.Runtime/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-SNVi1E/vfWUAs/WYKhE9+qlS6KqK0YVhnlT0HQtr8pMIA8YX3lwy3uPMownDwdYISBdmAF/2holEIldVp85Wag==", + "path": "system.dynamic.runtime/4.3.0", + "hashPath": "system.dynamic.runtime.4.3.0.nupkg.sha512" + }, + "System.Globalization/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "path": "system.globalization/4.3.0", + "hashPath": "system.globalization.4.3.0.nupkg.sha512" + }, + "System.Globalization.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "path": "system.globalization.extensions/4.3.0", + "hashPath": "system.globalization.extensions.4.3.0.nupkg.sha512" + }, + "System.IdentityModel.Tokens.Jwt/5.6.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-KMvPpX4exs2fe7Upq5zHMSR4yupc+jy8WG8yjucZL0XvT+r/T0hRvLIe9fP/SeN8/UVxFYBRAkRI5k1zbRGqmA==", + "path": "system.identitymodel.tokens.jwt/5.6.0", + "hashPath": "system.identitymodel.tokens.jwt.5.6.0.nupkg.sha512" + }, + "System.IO/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "path": "system.io/4.3.0", + "hashPath": "system.io.4.3.0.nupkg.sha512" + }, + "System.IO.FileSystem/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "path": "system.io.filesystem/4.3.0", + "hashPath": "system.io.filesystem.4.3.0.nupkg.sha512" + }, + "System.IO.FileSystem.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "path": "system.io.filesystem.primitives/4.3.0", + "hashPath": "system.io.filesystem.primitives.4.3.0.nupkg.sha512" + }, + "System.Linq/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "path": "system.linq/4.3.0", + "hashPath": "system.linq.4.3.0.nupkg.sha512" + }, + "System.Linq.Expressions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "path": "system.linq.expressions/4.3.0", + "hashPath": "system.linq.expressions.4.3.0.nupkg.sha512" + }, + "System.Net.NameResolution/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", + "path": "system.net.nameresolution/4.3.0", + "hashPath": "system.net.nameresolution.4.3.0.nupkg.sha512" + }, + "System.Net.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "path": "system.net.primitives/4.3.0", + "hashPath": "system.net.primitives.4.3.0.nupkg.sha512" + }, + "System.ObjectModel/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "path": "system.objectmodel/4.3.0", + "hashPath": "system.objectmodel.4.3.0.nupkg.sha512" + }, + "System.Private.DataContractSerialization/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-yDaJ2x3mMmjdZEDB4IbezSnCsnjQ4BxinKhRAaP6kEgL6Bb6jANWphs5SzyD8imqeC/3FxgsuXT6ykkiH1uUmA==", + "path": "system.private.datacontractserialization/4.3.0", + "hashPath": "system.private.datacontractserialization.4.3.0.nupkg.sha512" + }, + "System.Private.Uri/4.3.2": { + "type": "package", + "serviceable": true, + "sha512": "sha512-o1+7RJnu3Ik3PazR7Z7tJhjPdE000Eq2KGLLWhqJJKXj04wrS8lwb1OFtDF9jzXXADhUuZNJZlPc98uwwqmpFA==", + "path": "system.private.uri/4.3.2", + "hashPath": "system.private.uri.4.3.2.nupkg.sha512" + }, + "System.Reflection/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "path": "system.reflection/4.3.0", + "hashPath": "system.reflection.4.3.0.nupkg.sha512" + }, + "System.Reflection.Emit/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "path": "system.reflection.emit/4.3.0", + "hashPath": "system.reflection.emit.4.3.0.nupkg.sha512" + }, + "System.Reflection.Emit.ILGeneration/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "path": "system.reflection.emit.ilgeneration/4.3.0", + "hashPath": "system.reflection.emit.ilgeneration.4.3.0.nupkg.sha512" + }, + "System.Reflection.Emit.Lightweight/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "path": "system.reflection.emit.lightweight/4.3.0", + "hashPath": "system.reflection.emit.lightweight.4.3.0.nupkg.sha512" + }, + "System.Reflection.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "path": "system.reflection.extensions/4.3.0", + "hashPath": "system.reflection.extensions.4.3.0.nupkg.sha512" + }, + "System.Reflection.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "path": "system.reflection.primitives/4.3.0", + "hashPath": "system.reflection.primitives.4.3.0.nupkg.sha512" + }, + "System.Reflection.TypeExtensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "path": "system.reflection.typeextensions/4.3.0", + "hashPath": "system.reflection.typeextensions.4.3.0.nupkg.sha512" + }, + "System.Resources.ResourceManager/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "path": "system.resources.resourcemanager/4.3.0", + "hashPath": "system.resources.resourcemanager.4.3.0.nupkg.sha512" + }, + "System.Runtime/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "path": "system.runtime/4.3.0", + "hashPath": "system.runtime.4.3.0.nupkg.sha512" + }, + "System.Runtime.Caching/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-NdvNRjTPxYvIEhXQszT9L9vJhdQoX6AQ0AlhjTU+5NqFQVuacJTfhPVAvtGWNA2OJCqRiR/okBcZgMwI6MqcZg==", + "path": "system.runtime.caching/4.7.0", + "hashPath": "system.runtime.caching.4.7.0.nupkg.sha512" + }, + "System.Runtime.CompilerServices.Unsafe/4.5.2": { + "type": "package", + "serviceable": true, + "sha512": "sha512-wprSFgext8cwqymChhrBLu62LMg/1u92bU+VOwyfBimSPVFXtsNqEWC92Pf9ofzJFlk4IHmJA75EDJn1b2goAQ==", + "path": "system.runtime.compilerservices.unsafe/4.5.2", + "hashPath": "system.runtime.compilerservices.unsafe.4.5.2.nupkg.sha512" + }, + "System.Runtime.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "path": "system.runtime.extensions/4.3.0", + "hashPath": "system.runtime.extensions.4.3.0.nupkg.sha512" + }, + "System.Runtime.Handles/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "path": "system.runtime.handles/4.3.0", + "hashPath": "system.runtime.handles.4.3.0.nupkg.sha512" + }, + "System.Runtime.InteropServices/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "path": "system.runtime.interopservices/4.3.0", + "hashPath": "system.runtime.interopservices.4.3.0.nupkg.sha512" + }, + "System.Runtime.Numerics/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "path": "system.runtime.numerics/4.3.0", + "hashPath": "system.runtime.numerics.4.3.0.nupkg.sha512" + }, + "System.Runtime.Serialization.Formatters/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-KT591AkTNFOTbhZlaeMVvfax3RqhH1EJlcwF50Wm7sfnBLuHiOeZRRKrr1ns3NESkM20KPZ5Ol/ueMq5vg4QoQ==", + "path": "system.runtime.serialization.formatters/4.3.0", + "hashPath": "system.runtime.serialization.formatters.4.3.0.nupkg.sha512" + }, + "System.Runtime.Serialization.Json/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-CpVfOH0M/uZ5PH+M9+Gu56K0j9lJw3M+PKRegTkcrY/stOIvRUeonggxNrfBYLA5WOHL2j15KNJuTuld3x4o9w==", + "path": "system.runtime.serialization.json/4.3.0", + "hashPath": "system.runtime.serialization.json.4.3.0.nupkg.sha512" + }, + "System.Runtime.Serialization.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-Wz+0KOukJGAlXjtKr+5Xpuxf8+c8739RI1C+A2BoQZT+wMCCoMDDdO8/4IRHfaVINqL78GO8dW8G2lW/e45Mcw==", + "path": "system.runtime.serialization.primitives/4.3.0", + "hashPath": "system.runtime.serialization.primitives.4.3.0.nupkg.sha512" + }, + "System.Security.AccessControl/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-JECvTt5aFF3WT3gHpfofL2MNNP6v84sxtXxpqhLBCcDRzqsPBmHhQ6shv4DwwN2tRlzsUxtb3G9M3763rbXKDg==", + "path": "system.security.accesscontrol/4.7.0", + "hashPath": "system.security.accesscontrol.4.7.0.nupkg.sha512" + }, + "System.Security.Cryptography.Cng/4.5.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-WG3r7EyjUe9CMPFSs6bty5doUqT+q9pbI80hlNzo2SkPkZ4VTuZkGWjpp77JB8+uaL4DFPRdBsAY+DX3dBK92A==", + "path": "system.security.cryptography.cng/4.5.0", + "hashPath": "system.security.cryptography.cng.4.5.0.nupkg.sha512" + }, + "System.Security.Cryptography.Primitives/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "path": "system.security.cryptography.primitives/4.3.0", + "hashPath": "system.security.cryptography.primitives.4.3.0.nupkg.sha512" + }, + "System.Security.Cryptography.ProtectedData/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ehYW0m9ptxpGWvE4zgqongBVWpSDU/JCFD4K7krxkQwSz/sFQjEXCUqpvencjy6DYDbn7Ig09R8GFffu8TtneQ==", + "path": "system.security.cryptography.protecteddata/4.7.0", + "hashPath": "system.security.cryptography.protecteddata.4.7.0.nupkg.sha512" + }, + "System.Security.Permissions/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-dkOV6YYVBnYRa15/yv004eCGRBVADXw8qRbbNiCn/XpdJSUXkkUeIvdvFHkvnko4CdKMqG8yRHC4ox83LSlMsQ==", + "path": "system.security.permissions/4.7.0", + "hashPath": "system.security.permissions.4.7.0.nupkg.sha512" + }, + "System.Security.Principal.Windows/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ojD0PX0XhneCsUbAZVKdb7h/70vyYMDYs85lwEI+LngEONe/17A0cFaRFqZU+sOEidcVswYWikYOQ9PPfjlbtQ==", + "path": "system.security.principal.windows/4.7.0", + "hashPath": "system.security.principal.windows.4.7.0.nupkg.sha512" + }, + "System.Security.SecureString/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-PnXp38O9q/2Oe4iZHMH60kinScv6QiiL2XH54Pj2t0Y6c2zKPEiAZsM/M3wBOHLNTBDFP0zfy13WN2M0qFz5jg==", + "path": "system.security.securestring/4.3.0", + "hashPath": "system.security.securestring.4.3.0.nupkg.sha512" + }, + "System.Text.Encoding/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "path": "system.text.encoding/4.3.0", + "hashPath": "system.text.encoding.4.3.0.nupkg.sha512" + }, + "System.Text.Encoding.CodePages/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-aeu4FlaUTemuT1qOd1MyU4T516QR4Fy+9yDbwWMPHOHy7U8FD6SgTzdZFO7gHcfAPHtECqInbwklVvUK4RHcNg==", + "path": "system.text.encoding.codepages/4.7.0", + "hashPath": "system.text.encoding.codepages.4.7.0.nupkg.sha512" + }, + "System.Text.Encoding.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "path": "system.text.encoding.extensions/4.3.0", + "hashPath": "system.text.encoding.extensions.4.3.0.nupkg.sha512" + }, + "System.Text.RegularExpressions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "path": "system.text.regularexpressions/4.3.0", + "hashPath": "system.text.regularexpressions.4.3.0.nupkg.sha512" + }, + "System.Threading/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "path": "system.threading/4.3.0", + "hashPath": "system.threading.4.3.0.nupkg.sha512" + }, + "System.Threading.Tasks/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "path": "system.threading.tasks/4.3.0", + "hashPath": "system.threading.tasks.4.3.0.nupkg.sha512" + }, + "System.Threading.Tasks.Extensions/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==", + "path": "system.threading.tasks.extensions/4.3.0", + "hashPath": "system.threading.tasks.extensions.4.3.0.nupkg.sha512" + }, + "System.Windows.Extensions/4.7.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-CeWTdRNfRaSh0pm2gDTJFwVaXfTq6Xwv/sA887iwPTneW7oMtMlpvDIO+U60+3GWTB7Aom6oQwv5VZVUhQRdPQ==", + "path": "system.windows.extensions/4.7.0", + "hashPath": "system.windows.extensions.4.7.0.nupkg.sha512" + }, + "System.Xml.ReaderWriter/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "path": "system.xml.readerwriter/4.3.0", + "hashPath": "system.xml.readerwriter.4.3.0.nupkg.sha512" + }, + "System.Xml.XDocument/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "path": "system.xml.xdocument/4.3.0", + "hashPath": "system.xml.xdocument.4.3.0.nupkg.sha512" + }, + "System.Xml.XmlDocument/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-lJ8AxvkX7GQxpC6GFCeBj8ThYVyQczx2+f/cWHJU8tjS7YfI6Cv6bon70jVEgs2CiFbmmM8b9j1oZVx0dSI2Ww==", + "path": "system.xml.xmldocument/4.3.0", + "hashPath": "system.xml.xmldocument.4.3.0.nupkg.sha512" + }, + "System.Xml.XmlSerializer/4.3.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-MYoTCP7EZ98RrANESW05J5ZwskKDoN0AuZ06ZflnowE50LTpbR5yRg3tHckTVm5j/m47stuGgCrCHWePyHS70Q==", + "path": "system.xml.xmlserializer/4.3.0", + "hashPath": "system.xml.xmlserializer.4.3.0.nupkg.sha512" + }, + "Unity/5.11.10": { + "type": "package", + "serviceable": true, + "sha512": "sha512-B4+Ps3oqI78hJ+dAFsJhPkJT6qycsNExgLbtw7CEHSzKc2ac3YyUR8SHQ+ZyTwld/y5IbDx/aNOHnKE9Em1zWA==", + "path": "unity/5.11.10", + "hashPath": "unity.5.11.10.nupkg.sha512" + }, + "DatabaseCore/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "ModelTools/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "SecurityBusinessLogic/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Extensions/net5.0/SecurityImplementation.dll b/DepartmentPortal/Extensions/net5.0/SecurityImplementation.dll new file mode 100644 index 0000000000000000000000000000000000000000..1af8b4b5c4945d83eb2cee8826f85e1a1b5e4a4e GIT binary patch literal 22016 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 literal 0 HcmV?d00001 diff --git a/DepartmentPortal/Extensions/net5.0/ref/SecurityImplementation.dll b/DepartmentPortal/Extensions/net5.0/ref/SecurityImplementation.dll new file mode 100644 index 0000000000000000000000000000000000000000..4beadf6d9ed946fbebd754a79e66d3e41170efa7 GIT binary patch literal 7168 zcmeHLTWl298UANycfB@vv6pM0NtT!tlC-Pk)|Qluuh6B&xL(@)=wo*!)s8Xu-DKAN*N^KvIK)mn}3Dk#HQR(;pGrOL( zAuW-Rs>o;cf9L#{`OZ22Idf)akDPdsbRvpF?%pMO3pJNs!B2+saHk)?nxyou+5|x7fwMcxfI%k%l%aF2YU@nbuqa~%6s6Xec zb3U{`qyaF<1xeJAlEvtAuIH9ulQ~SI!8uq5iIiS2oSgpnGd$Jhsof(3m-$>p;j<}52^#Mu`nZ!wW83N9+f*p;(gAu`}@g zRAW3QSQq@O;5NZu$BTLgmEv#fY5F6*jP?X^`}NrBc$(Vu)$tB`RR3~3N&ln|V1ETM zY4XJTzTit@nUeN9g1-^VC28LQ^2kp!U^e{gqI&#3g zmi8=-aysayc1KTQMFQ>n8!kk&o7ydMo4%XcZJNhwHLkk|O>b&95E*Y_Ni==8=sfPx z#&x&p2N*#^y9lkVsog+iD%66pv^RaX=mp$sjq7gHPpG4*U4*uxsog;2%1{efI-9;* z^fE1Ix9JL{o4$+CRyDO7i0o=%>0Z_-$milr@Hw#qhu*`&812Dc+XqQvmrX!Au%iq} z8kQ;~gS~M9XKgnyi8JH^&c&ysy&c$v>lyn53xeMeJT7Pmz6wlI4m;`Rz}56i;3j$> z*h7B{f_hBi z1qTF6f)@m@2)-+LT~OC0UT{EgEl$0yl&ARl;3LTky8#I~UFbi$%Pahm_xM+GVKN0m`B!OS(9KS9Y;2Sm4FhV5|HWdTgAQ{)3Iv zYHRGDR_oCkZw+L9OnG(74~EbGbXd&|T&UJ8#oJTja%BrH*?sqk2)#Khf~88#O}Ucq zxDETDX;f^-^UadiWN5ibas}I0?yQ0RPBNfz$FaPqbY9SfFO`law&lTB}MyO&!_ zOXHg~@JwL}gO+u~Fm0-OCCo?3?Ze)?Pl97{H%keZE&pQ%_}h{2?8l3JO9{T_vDi!O z9LE109Gk}fxcngemZ06ZA{>q>9OKl*p@{?mAq3F-qO z55MHZ!giw?L_-6sfv=c@Wa9q>1x}l0$&rvPc()-Mhu47BgWn(@aSpVgycz!mNHvVf zN0bSB~a)ufMk*bHb&=!>XJR2OC+-(3ZX<56;i zjXqn)GbwzHnG7Pv!}UC_TFbZ}lsAuqLu<}!61*;$7xJ(j@5lM3@M>*BJZI9ESR3QC zA~SoC{&Q5uwU*>#8&*)GVQ^N2kuz6AUU-HTI)&bdvXJMc|D&OuSB3j; z!Mcrt-@)kW$gv-p9bq>-*t+HMZj5j77QV$2U6S?a!y0(#sfyiXAq!dLy>(?4 ZuHp50$fY; + /// Получение информации по доступу + /// + public class AccessGetBindingModel : GetBindingModel + { + public Guid? RoleId { get; set; } + } + + /// + /// Сохранение информации по доступу + /// + public class AccessSetBindingModel : SetBindingModel + { + public Guid RoleId { get; set; } + + [Required(ErrorMessage = "required")] + public AccessOperation Operation { get; set; } + + public AccessType AccessType { get; set; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/EnviromentSettingBindingModels.cs b/DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/EnviromentSettingBindingModels.cs new file mode 100644 index 0000000..e672f6f --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/EnviromentSettingBindingModels.cs @@ -0,0 +1,25 @@ +using ModelTools.BindingModels; +using System.ComponentModel.DataAnnotations; + +namespace SecurityBusinessLogic.BindingModels +{ + /// + /// Получение общих настроек системы + /// + public class EnviromentSettingGetBindingModel : GetBindingModel + { + public string Key { get; set; } + } + + /// + /// Сохранение общих настроек системы + /// + public class EnviromentSettingSetBindingModel : SetBindingModel + { + [Required(ErrorMessage = "required")] + public string Key { get; set; } + + [Required(ErrorMessage = "required")] + public string Value { get; set; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/RoleBindingModels.cs b/DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/RoleBindingModels.cs new file mode 100644 index 0000000..2cbbc29 --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/RoleBindingModels.cs @@ -0,0 +1,22 @@ +using ModelTools.BindingModels; +using System.ComponentModel.DataAnnotations; + +namespace SecurityBusinessLogic.BindingModels +{ + /// + /// Получение роли + /// + public class RoleGetBindingModel : GetBindingModel { } + + /// + /// Сохранение роли + /// + public class RoleSetBindingModel : SetBindingModel + { + [Required(ErrorMessage = "required")] + public string RoleName { get; set; } + + [Required(ErrorMessage = "required")] + public int RolePriority { get; set; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/UserBindingModels.cs b/DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/UserBindingModels.cs new file mode 100644 index 0000000..daf0b13 --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/BindingModels/UserBindingModels.cs @@ -0,0 +1,49 @@ +using ModelTools.BindingModels; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace SecurityBusinessLogic.BindingModels +{ + /// + /// Получение пользователя + /// + public class UserGetBindingModel : GetBindingModel + { + public bool? IsBanned { get; set; } + + public string Login { get; set; } + + public string Password { get; set; } + + public List LecturerIds { get; set; } + } + + /// + /// Сохранение пользователя + /// + public class UserSetBindingModel : SetBindingModel + { + [Required(ErrorMessage = "required")] + public string Login { get; set; } + + [Required(ErrorMessage = "required")] + public string Password { get; set; } + + public Guid? StudentId { get; set; } + + public Guid? LecturerId { get; set; } + + public Guid? EmployeeId { get; set; } + + public byte[] Avatar { get; set; } + + public DateTime? DateLastVisit { get; set; } + + public bool IsBanned { get; set; } + + public DateTime? DateBanned { get; set; } + + public int CountAttempt { get; set; } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/AccessBusinessLogic.cs b/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/AccessBusinessLogic.cs new file mode 100644 index 0000000..0c7cfec --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/AccessBusinessLogic.cs @@ -0,0 +1,21 @@ +using ModelTools.BusinessLogics; +using ModelTools.Enums; +using ModelTools.OperationResultModels; +using SecurityBusinessLogic.BindingModels; +using SecurityBusinessLogic.Interfaces; +using SecurityBusinessLogic.ViewModels; + +namespace SecurityBusinessLogic.BusinessLogics +{ + /// + /// Логика работы с доступами + /// + public class AccessBusinessLogic : BusinessLogicCore + { + public AccessBusinessLogic(IAccessService service) : base(service, "Доступы", AccessOperation.Доступы) { } + + protected override AccessViewModel ConvertToE(OperationResultModel model) => model.Result as AccessViewModel; + + protected override AccessListViewModel ConvertToL(OperationResultModel model) => model.Result as AccessListViewModel; + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/EnviromentSettingBusinessLogic.cs b/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/EnviromentSettingBusinessLogic.cs new file mode 100644 index 0000000..7f54e26 --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/EnviromentSettingBusinessLogic.cs @@ -0,0 +1,22 @@ +using ModelTools.BusinessLogics; +using ModelTools.Enums; +using ModelTools.OperationResultModels; +using SecurityBusinessLogic.BindingModels; +using SecurityBusinessLogic.Interfaces; +using SecurityBusinessLogic.ViewModels; + +namespace SecurityBusinessLogic.BusinessLogics +{ + /// + /// Логика работы с общими настройками системы + /// + public class EnviromentSettingBusinessLogic : BusinessLogicCore + { + public EnviromentSettingBusinessLogic(IEnviromentSettingService service) : base(service, "Настройки Среды", AccessOperation.НастройкиСреды) { } + + protected override EnviromentSettingViewModel ConvertToE(OperationResultModel model) => model.Result as EnviromentSettingViewModel; + + protected override EnviromentSettingListViewModel ConvertToL(OperationResultModel model) => model.Result as EnviromentSettingListViewModel; + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/RoleBusinessLogic.cs b/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/RoleBusinessLogic.cs new file mode 100644 index 0000000..26a4e15 --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/RoleBusinessLogic.cs @@ -0,0 +1,21 @@ +using ModelTools.BusinessLogics; +using ModelTools.Enums; +using ModelTools.OperationResultModels; +using SecurityBusinessLogic.BindingModels; +using SecurityBusinessLogic.Interfaces; +using SecurityBusinessLogic.ViewModels; + +namespace SecurityBusinessLogic.BusinessLogics +{ + /// + /// Логика работы с ролями + /// + public class RoleBusinessLogic : BusinessLogicCore + { + public RoleBusinessLogic(IRoleService service) : base(service, "Роли", AccessOperation.Роли) { } + + protected override RoleViewModel ConvertToE(OperationResultModel model) => model.Result as RoleViewModel; + + protected override RoleListViewModel ConvertToL(OperationResultModel model) => model.Result as RoleListViewModel; + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/UserBusinessLogic.cs b/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/UserBusinessLogic.cs new file mode 100644 index 0000000..ff84eaf --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/UserBusinessLogic.cs @@ -0,0 +1,21 @@ +using ModelTools.BusinessLogics; +using ModelTools.Enums; +using ModelTools.OperationResultModels; +using SecurityBusinessLogic.BindingModels; +using SecurityBusinessLogic.Interfaces; +using SecurityBusinessLogic.ViewModels; + +namespace SecurityBusinessLogic.BusinessLogics +{ + /// + /// Логика работы с пользователями + /// + public class UserBusinessLogic : BusinessLogicCore + { + public UserBusinessLogic(IUserService service) : base(service, "Пользователи", AccessOperation.Пользователи) { } + + protected override UserViewModel ConvertToE(OperationResultModel model) => model.Result as UserViewModel; + + protected override UserListViewModel ConvertToL(OperationResultModel model) => model.Result as UserListViewModel; + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/UserManager.cs b/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/UserManager.cs new file mode 100644 index 0000000..491c729 --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/BusinessLogics/UserManager.cs @@ -0,0 +1,223 @@ +using ModelTools.BusinessLogics; +using SecurityBusinessLogic.BindingModels; +using SecurityBusinessLogic.ViewModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace SecurityBusinessLogic.BusinessLogics +{ + /// + /// Менеджер по работе с пользователем системы + /// + public class UserManager + { + private readonly int _countDayToBanned = 3; + + private readonly int _countMaxAttempt = 3; + + private readonly RoleBusinessLogic _roleBusinessLogic; + + private readonly UserBusinessLogic _userBusinessLogic; + + private static UserManager _userManager; + + private static readonly object _lockObject = new(); + + private UserManager() + { + _roleBusinessLogic = UnityContainerConfigurator.Resolve(); + _userBusinessLogic = UnityContainerConfigurator.Resolve(); + } + + public static UserManager GetInstance + { + get + { + if (_userManager == null) + { + lock (_lockObject) + { + _userManager = new UserManager(); + } + } + + return _userManager; + } + } + + /// + /// Аутентифицированный пользователь + /// + public UserViewModel User { get; private set; } + + /// + /// Список ролей аутентифицированного пользователь + /// + public List Roles { get; private set; } + + /// + /// Сообщение об ошибке + /// + public string ErrorMessage { get; private set; } + + /// + /// Идентификатор аутентифицированного пользователь + /// + public Guid? UserId => User?.Id; + + /// + /// Выполнена ли аутентификация + /// + public bool IsAuth => User != null; + + /// + /// Аутентификация пользователя + /// + /// + /// + /// + public async Task LoginAsync(string login, string password) + { + await Task.Run(() => + { + UserSetBindingModel model; + var passwordHash = GetPasswordHash(password); + var user = _userBusinessLogic.GetElement(new UserGetBindingModel + { + Login = login, + Password = passwordHash, + SkipCheck = true + }); + + if (user == null) + { + if(_userBusinessLogic.Errors.Count > 0) + { + throw new Exception(_userBusinessLogic.Errors[0].Message); + } + + user = _userBusinessLogic.GetElement(new UserGetBindingModel + { + Login = login, + IsBanned = true, + SkipCheck = true + }); + if (user != null) + { + user.CountAttempt++; + if (user.CountAttempt > _countMaxAttempt) + { + user.IsBanned = true; + user.DateBanned = DateTime.Now; + } + + model = GetSetBindingModel(user); + model.Password = passwordHash; + _userBusinessLogic.Update(model); + } + + if (_userBusinessLogic.Errors.Count > 0) + { + throw new Exception(_userBusinessLogic.Errors[0].Message); + } + + throw new Exception("Введен неверный логин/пароль"); + } + if (user.IsBanned) + { + if (user.DateBanned.Value.AddDays(_countDayToBanned) > DateTime.Now) + { + user.IsBanned = false; + } + else + { + throw new Exception("Пользователь заблокирован"); + } + } + + user.DateLastVisit = DateTime.Now; + user.CountAttempt = 0; + + model = GetSetBindingModel(user); + model.Password = passwordHash; + _userBusinessLogic.Update(model); + + User = user; + Roles = _roleBusinessLogic.GetList(new RoleGetBindingModel { UserId = User.Id }).List.Select(x => x.Id).ToList(); + }); + } + + /// + /// Выход из системы + /// + /// + public async Task LogoutAsync() + { + await Task.Run(() => + { + User = null; + Roles = null; + }); + } + + /// + /// Смена пароля + /// + /// + /// + /// + public void ChangePassword(string login, string oldPassword, string newPassword) + { + var user = _userBusinessLogic.GetElement(new UserGetBindingModel + { + Login = login, + Password = GetPasswordHash(oldPassword), + SkipCheck = true + }); + if (user == null) + { + throw new Exception("Введен неверный логин/пароль"); + } + if (user.IsBanned) + { + throw new Exception("Пользователь забаннен"); + } + var model = GetSetBindingModel(user); + model.Password = GetPasswordHash(newPassword); + _userBusinessLogic.Update(model); + } + + /// + /// Получение хеша пароля + /// + /// + /// + public static string GetPasswordHash(string password) => Encoding.ASCII.GetString((new MD5CryptoServiceProvider()).ComputeHash(Encoding.ASCII.GetBytes(password))); + + /// + /// Получение модели для сохранения из представления + /// + /// + /// + private static UserSetBindingModel GetSetBindingModel(UserViewModel model) + { + return new UserSetBindingModel + { + Id = model.Id, + Login = model.Login, + LecturerId = model.LecturerId, + StudentId = model.StudentId, + EmployeeId = model.EmployeeId, + Avatar = model.Avatar, + IsBanned = model.IsBanned, + DateBanned = model.DateBanned, + CountAttempt = model.CountAttempt, + DateLastVisit = model.DateLastVisit + }; + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IAccessService.cs b/DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IAccessService.cs new file mode 100644 index 0000000..9d25010 --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IAccessService.cs @@ -0,0 +1,10 @@ +using ModelTools.Interfaces; +using SecurityBusinessLogic.BindingModels; + +namespace SecurityBusinessLogic.Interfaces +{ + /// + /// Хранение доступов + /// + public interface IAccessService : IEntityService { } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IEnviromentSettingService.cs b/DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IEnviromentSettingService.cs new file mode 100644 index 0000000..1c4fea5 --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IEnviromentSettingService.cs @@ -0,0 +1,10 @@ +using ModelTools.Interfaces; +using SecurityBusinessLogic.BindingModels; + +namespace SecurityBusinessLogic.Interfaces +{ + /// + /// Хранение общих настроек системы + /// + public interface IEnviromentSettingService : IEntityService { } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IRoleService.cs b/DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IRoleService.cs new file mode 100644 index 0000000..e65ce8c --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IRoleService.cs @@ -0,0 +1,10 @@ +using ModelTools.Interfaces; +using SecurityBusinessLogic.BindingModels; + +namespace SecurityBusinessLogic.Interfaces +{ + /// + /// Хранение ролей + /// + public interface IRoleService : IEntityService { } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IUserService.cs b/DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IUserService.cs new file mode 100644 index 0000000..d62fdac --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/Interfaces/IUserService.cs @@ -0,0 +1,10 @@ +using ModelTools.Interfaces; +using SecurityBusinessLogic.BindingModels; + +namespace SecurityBusinessLogic.Interfaces +{ + /// + /// Хранение пользователей + /// + public interface IUserService : IEntityService { } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/SecurityBusinessLogic.csproj b/DepartmentPortal/Security/SecurityBusinessLogic/SecurityBusinessLogic.csproj new file mode 100644 index 0000000..eea8d8b --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/SecurityBusinessLogic.csproj @@ -0,0 +1,15 @@ + + + + net5.0 + + + + + + + + + + + diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/AccessViewModels.cs b/DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/AccessViewModels.cs new file mode 100644 index 0000000..3ae3438 --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/AccessViewModels.cs @@ -0,0 +1,42 @@ +using ModelTools.Attributes; +using ModelTools.Enums; +using ModelTools.ViewModels; +using System; + +namespace SecurityBusinessLogic.ViewModels +{ + /// + /// Список достпуов + /// + public class AccessListViewModel : ListViewModel { } + + /// + /// Элемент доступа + /// + public class AccessViewModel : ElementViewModel + { + [ViewModelProperty("Роль", false, true)] + [MapConfiguration("RoleId")] + public Guid RoleId { get; set; } + + [ViewModelProperty("Роль", true, false, 100)] + [MapConfiguration("Role.RoleName", true)] + public string RoleName { get; set; } + + [ViewModelProperty("Операция", false, true)] + [MapConfiguration("AccessOperation")] + public AccessOperation AccessOperation { get; set; } + + [ViewModelProperty("Операция", true, false)] + public string AccessOperationTitle => AccessOperation.ToString("G"); + + [ViewModelProperty("Тип", false, true)] + [MapConfiguration("AccessType")] + public AccessType AccessType { get; set; } + + [ViewModelProperty("Тип", true, false, 50)] + public string AccessTypeTitle => AccessType.ToString("G"); + + public override string ToString() => $"{RoleName}-{AccessOperationTitle}({AccessTypeTitle})"; + } +} diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/EnviromentSettingViewModels.cs b/DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/EnviromentSettingViewModels.cs new file mode 100644 index 0000000..20d6262 --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/EnviromentSettingViewModels.cs @@ -0,0 +1,26 @@ +using ModelTools.Attributes; +using ModelTools.ViewModels; + +namespace SecurityBusinessLogic.ViewModels +{ + /// + /// Список общих настроек системы + /// + public class EnviromentSettingListViewModel : ListViewModel { } + + /// + /// Элемент общих настроек системы + /// + public class EnviromentSettingViewModel : ElementViewModel + { + [ViewModelProperty("Ключ", true, true)] + [MapConfiguration("Key")] + public string Key { get; set; } + + [ViewModelProperty("Значение", true, true, 100)] + [MapConfiguration("Value")] + public int Value { get; set; } + + public override string ToString() => Key; + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/RoleViewModels.cs b/DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/RoleViewModels.cs new file mode 100644 index 0000000..e55dad6 --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/RoleViewModels.cs @@ -0,0 +1,26 @@ +using ModelTools.Attributes; +using ModelTools.ViewModels; + +namespace SecurityBusinessLogic.ViewModels +{ + /// + /// Список ролей + /// + public class RoleListViewModel : ListViewModel { } + + /// + /// Элемент ролей + /// + public class RoleViewModel : ElementViewModel + { + [ViewModelProperty("Название роли", true, true)] + [MapConfiguration("RoleName")] + public string RoleName { get; set; } + + [ViewModelProperty("Приоритет", true, true, 100)] + [MapConfiguration("RolePriority")] + public int RolePriority { get; set; } + + public override string ToString() => RoleName; + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/UserViewModels.cs b/DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/UserViewModels.cs new file mode 100644 index 0000000..56c8933 --- /dev/null +++ b/DepartmentPortal/Security/SecurityBusinessLogic/ViewModels/UserViewModels.cs @@ -0,0 +1,62 @@ +using ModelTools.Attributes; +using ModelTools.ViewModels; +using System; + +namespace SecurityBusinessLogic.ViewModels +{ + /// + /// Список пользователей + /// + public class UserListViewModel : ListViewModel { } + + /// + /// Элемент пользователей + /// + public class UserViewModel : ElementViewModel + { + [ViewModelProperty("Пользователь", true, true)] + [MapConfiguration("UserName")] + public string Login { get; set; } + + [ViewModelProperty("Студент", false, true)] + [MapConfiguration("StudentId")] + public Guid? StudentId { get; set; } + + [ViewModelProperty("Преподаватель", false, true)] + [MapConfiguration("LecturerId")] + public Guid? LecturerId { get; set; } + + [ViewModelProperty("Сотрудник", false, true)] + [MapConfiguration("EmployeeId")] + public Guid? EmployeeId { get; set; } + + [ViewModelProperty("Фото", false, true)] + [MapConfiguration("Avatar")] + public byte[] Avatar { get; set; } + + [ViewModelProperty("Посл. визит", true, false, 100)] + [MapConfiguration("DateLastVisit")] + public DateTime? DateLastVisit { get; set; } + + [ViewModelProperty("Блокировка", false, true)] + [MapConfiguration("IsBanned")] + public bool IsBanned { get; set; } + + [ViewModelProperty("Блокир.", true, false, 100)] + public string Banned => IsBanned ? "Да" : "Нет"; + + [ViewModelProperty("Дата Б.", false, true, 100)] + [MapConfiguration("DateBanned")] + public DateTime? DateBanned { get; set; } + + [ViewModelProperty("Дата Б.", true, false, 100)] + public string DateBannedTitle => DateBanned.HasValue ? DateBanned.Value.ToShortDateString() : string.Empty; + + [ViewModelProperty("Количество попыток входа", false, false)] + [MapConfiguration("CountAttempt")] + public int CountAttempt { get; set; } + + public override string ToString() => Login; + + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityImplementation/Implementations/AccessService.cs b/DepartmentPortal/Security/SecurityImplementation/Implementations/AccessService.cs new file mode 100644 index 0000000..27caa61 --- /dev/null +++ b/DepartmentPortal/Security/SecurityImplementation/Implementations/AccessService.cs @@ -0,0 +1,131 @@ +using DatabaseCore; +using DatabaseCore.Models.Security; +using Microsoft.EntityFrameworkCore; +using ModelTools.BusinessLogics; +using ModelTools.Enums; +using ModelTools.OperationResultModels; +using SecurityBusinessLogic.BindingModels; +using SecurityBusinessLogic.Interfaces; +using SecurityBusinessLogic.ViewModels; +using System; +using System.Linq; + +namespace SecurityImplementation.Implementations +{ + /// + /// Реализация IAccessService + /// + public class AccessService : IAccessService + { + public OperationResultModel Create(AccessSetBindingModel model) + { + using var context = DatabaseManager.GetContext; + + var exsistEntity = context.Accesses.FirstOrDefault(x => x.Operation == model.Operation && x.RoleId == model.RoleId && x.AccessType == model.AccessType); + if (exsistEntity == null) + { + var entity = Mapper.MapToClass(model); + context.Accesses.Add(entity); + context.SaveChanges(); + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + else + { + if (exsistEntity.IsDeleted) + { + exsistEntity.IsDeleted = false; + context.SaveChanges(); + return OperationResultModel.Success(Mapper.MapToClass(exsistEntity)); + } + else + { + return OperationResultModel.Error("Error:", "Элемент уже существует", ResultServiceStatusCode.ExsistItem); + } + } + } + + public OperationResultModel Delete(AccessGetBindingModel model) + { + using var context = DatabaseManager.GetContext; + + var entity = context.Accesses.FirstOrDefault(x => x.Id == model.Id); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + else if (entity.IsDeleted) + { + return OperationResultModel.Error("Error:", "Элемент был удален", ResultServiceStatusCode.WasDelete); + } + entity.IsDeleted = true; + entity.DateDelete = DateTime.Now; + + context.SaveChanges(); + + return OperationResultModel.Success(true); + } + + public OperationResultModel Read(AccessGetBindingModel model) + { + int countPages = 0; + using var context = DatabaseManager.GetContext; + + // для одной записи + if(model.Id.HasValue) + { + var entity = context.Accesses.FirstOrDefault(x => x.Id == model.Id.Value); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + + var query = context.Accesses.Where(x => !x.IsDeleted).AsQueryable(); + if (model.RoleId.HasValue) + { + query = query.Where(x => x.RoleId == model.RoleId); + } + + query = query.OrderBy(x => x.Role.RoleName).ThenBy(x => x.Operation).ThenBy(x => x.AccessType); + + if (model.PageNumber.HasValue && model.PageSize.HasValue) + { + countPages = (int)Math.Ceiling((double)query.Count() / model.PageSize.Value); + query = query + .Skip(model.PageSize.Value * model.PageNumber.Value) + .Take(model.PageSize.Value); + } + + query = query.Include(x => x.Role); + + var result = new AccessListViewModel + { + MaxCount = countPages, + List = query.Select(Mapper.MapToClass).ToList() + }; + + return OperationResultModel.Success(result); + } + + public OperationResultModel Update(AccessSetBindingModel model) + { + using var context = DatabaseManager.GetContext; + + var entity = context.Accesses.FirstOrDefault(x => x.Id == model.Id); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + else if (entity.IsDeleted) + { + return OperationResultModel.Error("Error:", "Элемент был удален", ResultServiceStatusCode.WasDelete); + } + entity = Mapper.MapToClass(model, entity); + + context.SaveChanges(); + + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityImplementation/Implementations/EnviromentSettingService.cs b/DepartmentPortal/Security/SecurityImplementation/Implementations/EnviromentSettingService.cs new file mode 100644 index 0000000..01ea3d0 --- /dev/null +++ b/DepartmentPortal/Security/SecurityImplementation/Implementations/EnviromentSettingService.cs @@ -0,0 +1,114 @@ +using DatabaseCore; +using DatabaseCore.Models.Security; +using ModelTools.BusinessLogics; +using ModelTools.Enums; +using ModelTools.Extensions; +using ModelTools.OperationResultModels; +using SecurityBusinessLogic.BindingModels; +using SecurityBusinessLogic.Interfaces; +using SecurityBusinessLogic.ViewModels; +using System; +using System.Linq; + +namespace SecurityImplementation.Implementations +{ + /// + /// Реализация IEnviromentSettingService + /// + public class EnviromentSettingService : IEnviromentSettingService + { + public OperationResultModel Create(EnviromentSettingSetBindingModel model) + { + using var context = DatabaseManager.GetContext; + + var exsistEntity = context.EnviromentSettings.FirstOrDefault(x => x.Key == model.Key); + if (exsistEntity == null) + { + var entity = Mapper.MapToClass(model); + context.EnviromentSettings.Add(entity); + context.SaveChanges(); + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + return OperationResultModel.Error("Error:", "Элемент уже существует", ResultServiceStatusCode.ExsistItem); + } + + public OperationResultModel Delete(EnviromentSettingGetBindingModel model) + { + using var context = DatabaseManager.GetContext; + + var entity = context.EnviromentSettings.FirstOrDefault(x => x.Id == model.Id); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + + context.EnviromentSettings.Remove(entity); + context.SaveChanges(); + + return OperationResultModel.Success(true); + } + + public OperationResultModel Read(EnviromentSettingGetBindingModel model) + { + int countPages = 0; + using var context = DatabaseManager.GetContext; + + // для одной записи + if (model.Id.HasValue) + { + var entity = context.EnviromentSettings.FirstOrDefault(x => x.Id == model.Id.Value); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + + if (model.Key.IsNotEmpty()) + { + var entity = context.EnviromentSettings.FirstOrDefault(x => x.Key == model.Key); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + + var query = context.EnviromentSettings.AsQueryable(); + + query = query.OrderBy(x => x.Key); + + if (model.PageNumber.HasValue && model.PageSize.HasValue) + { + countPages = (int)Math.Ceiling((double)query.Count() / model.PageSize.Value); + query = query + .Skip(model.PageSize.Value * model.PageNumber.Value) + .Take(model.PageSize.Value); + } + + var result = new EnviromentSettingListViewModel + { + MaxCount = countPages, + List = query.Select(Mapper.MapToClass).ToList() + }; + + return OperationResultModel.Success(result); + } + + public OperationResultModel Update(EnviromentSettingSetBindingModel model) + { + using var context = DatabaseManager.GetContext; + + var entity = context.EnviromentSettings.FirstOrDefault(x => x.Id == model.Id); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + entity = Mapper.MapToClass(model, entity); + + context.SaveChanges(); + + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityImplementation/Implementations/RoleService.cs b/DepartmentPortal/Security/SecurityImplementation/Implementations/RoleService.cs new file mode 100644 index 0000000..80b19b4 --- /dev/null +++ b/DepartmentPortal/Security/SecurityImplementation/Implementations/RoleService.cs @@ -0,0 +1,150 @@ +using DatabaseCore; +using DatabaseCore.Models.Security; +using ModelTools.BusinessLogics; +using ModelTools.Enums; +using ModelTools.OperationResultModels; +using SecurityBusinessLogic.BindingModels; +using SecurityBusinessLogic.Interfaces; +using SecurityBusinessLogic.ViewModels; +using System; +using System.Linq; + +namespace SecurityImplementation.Implementations +{ + /// + /// Реализация IRoleService + /// + public class RoleService : IRoleService + { + public OperationResultModel Create(RoleSetBindingModel model) + { + using var context = DatabaseManager.GetContext; + + var exsistEntity = context.Roles.FirstOrDefault(x => x.RoleName == model.RoleName); + if (exsistEntity == null) + { + var entity = Mapper.MapToClass(model); + context.Roles.Add(entity); + context.SaveChanges(); + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + else + { + if (exsistEntity.IsDeleted) + { + exsistEntity.IsDeleted = false; + context.SaveChanges(); + return OperationResultModel.Success(Mapper.MapToClass(exsistEntity)); + } + else + { + return OperationResultModel.Error("Error:", "Элемент уже существует", ResultServiceStatusCode.ExsistItem); + } + } + } + + public OperationResultModel Delete(RoleGetBindingModel model) + { + using var context = DatabaseManager.GetContext; + using var transaction = context.Database.BeginTransaction(); + try + { + var entity = context.Roles.FirstOrDefault(x => x.Id == model.Id); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + else if (entity.IsDeleted) + { + return OperationResultModel.Error("Error:", "Элемент был удален", ResultServiceStatusCode.WasDelete); + } + entity.IsDeleted = true; + entity.DateDelete = DateTime.Now; + + context.SaveChanges(); + + var access = context.Accesses.Where(x => x.RoleId == model.Id); + foreach(var ac in access) + { + ac.IsDeleted = true; + ac.DateDelete = DateTime.Now; + } + context.SaveChanges(); + + var users = context.UserRoles.Where(x => x.RoleId == model.Id); + foreach (var u in users) + { + u.IsDeleted = true; + u.DateDelete = DateTime.Now; + } + context.SaveChanges(); + + transaction.Commit(); + } + catch(Exception) + { + transaction.Rollback(); + throw; + } + + return OperationResultModel.Success(true); + } + + public OperationResultModel Read(RoleGetBindingModel model) + { + int countPages = 0; + using var context = DatabaseManager.GetContext; + + // для одной записи + if (model.Id.HasValue) + { + var entity = context.Roles.FirstOrDefault(x => x.Id == model.Id.Value); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + + var query = context.Roles.Where(x => !x.IsDeleted).AsQueryable(); + + query = query.OrderBy(x => x.RoleName); + + if (model.PageNumber.HasValue && model.PageSize.HasValue) + { + countPages = (int)Math.Ceiling((double)query.Count() / model.PageSize.Value); + query = query + .Skip(model.PageSize.Value * model.PageNumber.Value) + .Take(model.PageSize.Value); + } + + var result = new RoleListViewModel + { + MaxCount = countPages, + List = query.Select(Mapper.MapToClass).ToList() + }; + + return OperationResultModel.Success(result); + } + + public OperationResultModel Update(RoleSetBindingModel model) + { + using var context = DatabaseManager.GetContext; + + var entity = context.Roles.FirstOrDefault(x => x.Id == model.Id); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + else if (entity.IsDeleted) + { + return OperationResultModel.Error("Error:", "Элемент был удален", ResultServiceStatusCode.WasDelete); + } + entity = Mapper.MapToClass(model, entity); + + context.SaveChanges(); + + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityImplementation/Implementations/UserService.cs b/DepartmentPortal/Security/SecurityImplementation/Implementations/UserService.cs new file mode 100644 index 0000000..142698c --- /dev/null +++ b/DepartmentPortal/Security/SecurityImplementation/Implementations/UserService.cs @@ -0,0 +1,171 @@ +using DatabaseCore; +using DatabaseCore.Models.Security; +using ModelTools.BusinessLogics; +using ModelTools.Enums; +using ModelTools.Extensions; +using ModelTools.OperationResultModels; +using SecurityBusinessLogic.BindingModels; +using SecurityBusinessLogic.Interfaces; +using SecurityBusinessLogic.ViewModels; +using System; +using System.Linq; + +namespace SecurityImplementation.Implementations +{ + /// + /// Реализация IUserService + /// + public class UserService : IUserService + { + public OperationResultModel Create(UserSetBindingModel model) + { + using var context = DatabaseManager.GetContext; + + var exsistEntity = context.Users.FirstOrDefault(x => x.UserName == model.Login); + if (exsistEntity == null) + { + var entity = Mapper.MapToClass(model); + context.Users.Add(entity); + context.SaveChanges(); + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + else + { + if (exsistEntity.IsDeleted) + { + exsistEntity.IsDeleted = false; + context.SaveChanges(); + return OperationResultModel.Success(Mapper.MapToClass(exsistEntity)); + } + else + { + return OperationResultModel.Error("Error:", "Элемент уже существует", ResultServiceStatusCode.ExsistItem); + } + } + } + + public OperationResultModel Delete(UserGetBindingModel model) + { + using var context = DatabaseManager.GetContext; + using var transaction = context.Database.BeginTransaction(); + try + { + var entity = context.Users.FirstOrDefault(x => x.Id == model.Id); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + else if (entity.IsDeleted) + { + return OperationResultModel.Error("Error:", "Элемент был удален", ResultServiceStatusCode.WasDelete); + } + entity.IsDeleted = true; + entity.DateDelete = DateTime.Now; + + context.SaveChanges(); + + var users = context.UserRoles.Where(x => x.UserId == model.Id); + foreach (var u in users) + { + u.IsDeleted = true; + u.DateDelete = DateTime.Now; + } + context.SaveChanges(); + + transaction.Commit(); + } + catch (Exception) + { + transaction.Rollback(); + throw; + } + + return OperationResultModel.Success(true); + } + + public OperationResultModel Read(UserGetBindingModel model) + { + int countPages = 0; + using var context = DatabaseManager.GetContext; + + // для одной записи + if (model.Id.HasValue) + { + var entity = context.Users.FirstOrDefault(x => x.Id == model.Id.Value); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + + if (model.Login.IsNotEmpty() && model.Password.IsNotEmpty()) + { + var entity = context.Users.FirstOrDefault(x => x.UserName == model.Login && x.PasswordHash == model.Password); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + + if (model.Login.IsNotEmpty() && model.IsBanned.HasValue) + { + var entity = context.Users.FirstOrDefault(x => x.UserName == model.Login && x.IsBanned == model.IsBanned.Value); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + + var query = context.Users.Where(x => !x.IsDeleted).AsQueryable(); + if (model.IsBanned.HasValue) + { + query = query.Where(x => x.IsBanned == model.IsBanned.Value); + } + if (model.LecturerIds != null) + { + query = query.Where(x => x.LecturerId.HasValue && model.LecturerIds.Contains(x.LecturerId.Value)); + } + + query = query.OrderBy(x => x.UserName); + + if (model.PageNumber.HasValue && model.PageSize.HasValue) + { + countPages = (int)Math.Ceiling((double)query.Count() / model.PageSize.Value); + query = query + .Skip(model.PageSize.Value * model.PageNumber.Value) + .Take(model.PageSize.Value); + } + + var result = new UserListViewModel + { + MaxCount = countPages, + List = query.Select(Mapper.MapToClass).ToList() + }; + + return OperationResultModel.Success(result); + } + + public OperationResultModel Update(UserSetBindingModel model) + { + using var context = DatabaseManager.GetContext; + + var entity = context.Users.FirstOrDefault(x => x.Id == model.Id); + if (entity == null) + { + return OperationResultModel.Error("Error:", "Элемент не найден", ResultServiceStatusCode.NotFound); + } + else if (entity.IsDeleted) + { + return OperationResultModel.Error("Error:", "Элемент был удален", ResultServiceStatusCode.WasDelete); + } + entity = Mapper.MapToClass(model, entity); + + context.SaveChanges(); + + return OperationResultModel.Success(Mapper.MapToClass(entity)); + } + } +} \ No newline at end of file diff --git a/DepartmentPortal/Security/SecurityImplementation/SecurityImplementation.csproj b/DepartmentPortal/Security/SecurityImplementation/SecurityImplementation.csproj new file mode 100644 index 0000000..d808588 --- /dev/null +++ b/DepartmentPortal/Security/SecurityImplementation/SecurityImplementation.csproj @@ -0,0 +1,16 @@ + + + + net5.0 + + + + ..\..\Extensions\ + + + + + + + + diff --git a/DepartmentPortal/Security/SecurityImplementation/SecurityLoaderExtensions.cs b/DepartmentPortal/Security/SecurityImplementation/SecurityLoaderExtensions.cs new file mode 100644 index 0000000..b9767c4 --- /dev/null +++ b/DepartmentPortal/Security/SecurityImplementation/SecurityLoaderExtensions.cs @@ -0,0 +1,24 @@ +using ModelTools.BusinessLogics; +using ModelTools.Interfaces; +using SecurityBusinessLogic.BusinessLogics; +using SecurityBusinessLogic.Interfaces; +using SecurityImplementation.Implementations; + +namespace SecurityImplementation +{ + public class SecurityLoaderExtensions : ILoaderExtensions + { + public void RegisterServices() + { + UnityContainerConfigurator.PublishService(); + UnityContainerConfigurator.PublishService(); + UnityContainerConfigurator.PublishService(); + UnityContainerConfigurator.PublishService(); + + UnityContainerConfigurator.PublishService(); + UnityContainerConfigurator.PublishService(); + UnityContainerConfigurator.PublishService(); + UnityContainerConfigurator.PublishService(); + } + } +} \ No newline at end of file