Стартовый набор: шаблоны логик, работа с пользователями, база даннных

This commit is contained in:
kotcheshir73 2021-03-26 20:09:52 +04:00
parent 4acf81d087
commit 08f50f6e11
80 changed files with 5696 additions and 46 deletions

View File

@ -0,0 +1,36 @@
using System;
namespace CommonTools.Attributes
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ViewModelPropertyAttribute : Attribute
{
/// <summary>
/// Название на форме
/// </summary>
public string DisplayName { get; set; }
/// <summary>
/// Скрывать или нет
/// </summary>
public bool IsHide { get; set; }
/// <summary>
/// Ширина колонки
/// </summary>
public int ColumnWidth { get; set; }
/// <summary>
/// Конструктор
/// </summary>
/// <param name="displayName">Название на форме</param>
/// <param name="isHide">Скрывать или нет</param>
/// <param name="columnWidth">Ширина колонки</param>
public ViewModelPropertyAttribute(string displayName, int columnWidth, bool isHide = false)
{
DisplayName = displayName;
ColumnWidth = columnWidth;
IsHide = isHide;
}
}
}

View File

@ -25,7 +25,7 @@ namespace CommonTools.OperationResultModels
public List<(string Title, string Message)> Errors { get; private set; }
/// <summary>
/// Какой-то объект, получаемый по результатам операции (например, id)
/// Объект, получаемый по результатам операции
/// </summary>
public object Result { get; private set; }
@ -38,42 +38,4 @@ namespace CommonTools.OperationResultModels
StatusCode = ResultServiceStatusCode.Success;
}
}
/// <summary>
/// Результат любой операции
/// </summary>
/// <typeparam name="T"></typeparam>
public class OperationResultModel<T>
where T : ElementViewModel
{
/// <summary>
/// Успешность операции
/// </summary>
public bool IsSucceeded { get; private set; }
/// <summary>
/// Статус операции
/// </summary>
public ResultServiceStatusCode StatusCode { get; private set; }
/// <summary>
/// Спсиок ошибок
/// </summary>
public List<KeyValuePair<string, string>> Errors { get; private set; }
/// <summary>
/// Какой-то объект, получаемый по результатам операции (например, id)
/// </summary>
public T Result { get; private set; }
/// <summary>
/// Конструктор по умолчанию
/// </summary>
public OperationResultModel()
{
Errors = new List<KeyValuePair<string, string>>();
IsSucceeded = true;
StatusCode = 0;
}
}
}

View File

@ -1,4 +1,5 @@
using System;
using CommonTools.Attributes;
using System;
namespace CommonTools.ViewModels
{
@ -7,6 +8,7 @@ namespace CommonTools.ViewModels
/// </summary>
public class ElementViewModel
{
[ViewModelProperty("Идентификатор", 1, true)]
public Guid Id { get; set; }
}
}

View File

@ -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<Access> Accesses { set; get; }
public virtual DbSet<EnviromentSetting> EnviromentSettings { set; get; }
public virtual DbSet<Role> Roles { set; get; }
public virtual DbSet<User> Users { set; get; }
public virtual DbSet<UserRole> UserRoles { set; get; }
}
}

View File

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Security\SecurityBusinessLogic\SecurityBusinessLogic.csproj" />
<ProjectReference Include="..\ModelTools\ModelTools.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,13 @@
namespace DatabaseCore
{
/// <summary>
/// Работа с БД
/// </summary>
public static class DatabaseManager
{
/// <summary>
/// Получение объекта от класса DbContext
/// </summary>
public static DatabaseContext GetContext => new();
}
}

View File

@ -0,0 +1,211 @@
// <auto-generated />
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<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<int>("AccessType")
.HasColumnType("int");
b.Property<DateTime>("DateCreate")
.HasColumnType("datetime2");
b.Property<DateTime?>("DateDelete")
.HasColumnType("datetime2");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("Operation")
.HasColumnType("int");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("Accesses");
});
modelBuilder.Entity("DatabaseCore.Models.Security.EnviromentSetting", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("Key")
.HasColumnType("nvarchar(max)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("EnviromentSettings");
});
modelBuilder.Entity("DatabaseCore.Models.Security.Role", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("DateCreate")
.HasColumnType("datetime2");
b.Property<DateTime?>("DateDelete")
.HasColumnType("datetime2");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("RoleName")
.HasColumnType("nvarchar(max)");
b.Property<int>("RolePriority")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Roles");
});
modelBuilder.Entity("DatabaseCore.Models.Security.User", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<byte[]>("Avatar")
.HasColumnType("varbinary(max)");
b.Property<int>("CountAttempt")
.HasColumnType("int");
b.Property<DateTime?>("DateBanned")
.HasColumnType("datetime2");
b.Property<DateTime>("DateCreate")
.HasColumnType("datetime2");
b.Property<DateTime?>("DateDelete")
.HasColumnType("datetime2");
b.Property<DateTime?>("DateLastVisit")
.HasColumnType("datetime2");
b.Property<DateTime?>("DateLocked")
.HasColumnType("datetime2");
b.Property<Guid?>("EmployeeId")
.HasColumnType("uniqueidentifier");
b.Property<bool>("IsBanned")
.HasColumnType("bit");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<Guid?>("LecturerId")
.HasColumnType("uniqueidentifier");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("StudentId")
.HasColumnType("uniqueidentifier");
b.Property<string>("UserName")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("DatabaseCore.Models.Security.UserRole", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("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
}
}
}

View File

@ -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<Guid>(type: "uniqueidentifier", nullable: false),
Key = table.Column<string>(type: "nvarchar(max)", nullable: true),
Value = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_EnviromentSettings", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Roles",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
RoleName = table.Column<string>(type: "nvarchar(max)", nullable: true),
RolePriority = table.Column<int>(type: "int", nullable: false),
DateCreate = table.Column<DateTime>(type: "datetime2", nullable: false),
DateDelete = table.Column<DateTime>(type: "datetime2", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Roles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
UserName = table.Column<string>(type: "nvarchar(max)", nullable: true),
PasswordHash = table.Column<string>(type: "nvarchar(max)", nullable: true),
StudentId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LecturerId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
EmployeeId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Avatar = table.Column<byte[]>(type: "varbinary(max)", nullable: true),
DateLastVisit = table.Column<DateTime>(type: "datetime2", nullable: true),
IsBanned = table.Column<bool>(type: "bit", nullable: false),
DateBanned = table.Column<DateTime>(type: "datetime2", nullable: true),
CountAttempt = table.Column<int>(type: "int", nullable: false),
DateLocked = table.Column<DateTime>(type: "datetime2", nullable: true),
DateCreate = table.Column<DateTime>(type: "datetime2", nullable: false),
DateDelete = table.Column<DateTime>(type: "datetime2", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Accesses",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
RoleId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Operation = table.Column<int>(type: "int", nullable: false),
AccessType = table.Column<int>(type: "int", nullable: false),
DateCreate = table.Column<DateTime>(type: "datetime2", nullable: false),
DateDelete = table.Column<DateTime>(type: "datetime2", nullable: true),
IsDeleted = table.Column<bool>(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<Guid>(type: "uniqueidentifier", nullable: false),
RoleId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
UserId = table.Column<Guid>(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");
}
}
}

View File

@ -0,0 +1,209 @@
// <auto-generated />
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<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<int>("AccessType")
.HasColumnType("int");
b.Property<DateTime>("DateCreate")
.HasColumnType("datetime2");
b.Property<DateTime?>("DateDelete")
.HasColumnType("datetime2");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("Operation")
.HasColumnType("int");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("Accesses");
});
modelBuilder.Entity("DatabaseCore.Models.Security.EnviromentSetting", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("Key")
.HasColumnType("nvarchar(max)");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("EnviromentSettings");
});
modelBuilder.Entity("DatabaseCore.Models.Security.Role", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("DateCreate")
.HasColumnType("datetime2");
b.Property<DateTime?>("DateDelete")
.HasColumnType("datetime2");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("RoleName")
.HasColumnType("nvarchar(max)");
b.Property<int>("RolePriority")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Roles");
});
modelBuilder.Entity("DatabaseCore.Models.Security.User", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<byte[]>("Avatar")
.HasColumnType("varbinary(max)");
b.Property<int>("CountAttempt")
.HasColumnType("int");
b.Property<DateTime?>("DateBanned")
.HasColumnType("datetime2");
b.Property<DateTime>("DateCreate")
.HasColumnType("datetime2");
b.Property<DateTime?>("DateDelete")
.HasColumnType("datetime2");
b.Property<DateTime?>("DateLastVisit")
.HasColumnType("datetime2");
b.Property<DateTime?>("DateLocked")
.HasColumnType("datetime2");
b.Property<Guid?>("EmployeeId")
.HasColumnType("uniqueidentifier");
b.Property<bool>("IsBanned")
.HasColumnType("bit");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<Guid?>("LecturerId")
.HasColumnType("uniqueidentifier");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("StudentId")
.HasColumnType("uniqueidentifier");
b.Property<string>("UserName")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("DatabaseCore.Models.Security.UserRole", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("RoleId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("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
}
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Runtime.Serialization;
namespace DatabaseCore.Models
{
/// <summary>
/// Базовый набор для сущности
/// </summary>
[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;
}
}
}

View File

@ -0,0 +1,24 @@
using ModelTools.Attributes;
using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.Serialization;
namespace DatabaseCore.Models
{
/// <summary>
/// Тип Id для всеъ сущностей
/// </summary>
[DataContract]
public class IdEntity
{
[DataMember]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[MapConfiguration("Id")]
public Guid Id { get; set; }
public IdEntity() : base()
{
Id = Guid.NewGuid();
}
}
}

View File

@ -0,0 +1,38 @@
using ModelTools.Attributes;
using ModelTools.Enums;
using System;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
namespace DatabaseCore.Models.Security
{
/// <summary>
/// Класс, описывающий возможные действия для роли
/// </summary>
[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; }
//-------------------------------------------------------------------------
}
}

View File

@ -0,0 +1,21 @@
using ModelTools.Attributes;
using System.Runtime.Serialization;
namespace DatabaseCore.Models.Security
{
/// <summary>
/// Класс, описывающий общие настройки системы
/// </summary>
[DataContract]
[EntityDescription("EnviromentSetting", "Общие настройки системы")]
public class EnviromentSetting : IdEntity
{
[DataMember]
[MapConfiguration("Key")]
public string Key { get; set; }
[DataMember]
[MapConfiguration("Value")]
public string Value { get; set; }
}
}

View File

@ -0,0 +1,33 @@
using ModelTools.Attributes;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.Serialization;
namespace DatabaseCore.Models.Security
{
/// <summary>
/// Класс, описывающий роль в системе
/// </summary>
[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> Access { get; set; }
[ForeignKey("RoleId")]
public virtual List<UserRole> UserRoles { get; set; }
}
}

View File

@ -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
{
/// <summary>
/// Класс, описывающий пользователя системы
/// </summary>
[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<UserRole> UserRoles { get; set; }
}
}

View File

@ -0,0 +1,30 @@
using ModelTools.Attributes;
using System;
using System.Runtime.Serialization;
namespace DatabaseCore.Models.Security
{
/// <summary>
/// Связка пользователь - роль
/// </summary>
[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; }
//-------------------------------------------------------------------------
}
}

View File

@ -0,0 +1,57 @@
using Microsoft.EntityFrameworkCore;
namespace DatabaseCore.Scripts
{
/// <summary>
/// Скрипты для миграции данных по безопасности
/// </summary>
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";
/// <summary>
/// Перенос данных по безопасности
/// </summary>
/// <param name="context"></param>
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);
}
}
}

View File

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

View File

@ -0,0 +1,39 @@
using System;
namespace ModelTools.Attributes
{
/// <summary>
/// Описание зависимости сущности от другой сущности (требуется для сохранения и загрузки данных)
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class EntityDependencyAttribute : Attribute
{
/// <summary>
/// Название класса от котрого зависит этот класс
/// </summary>
public string ClassName { get; set; }
/// <summary>
/// Название поле в этом классе, которое ссылает на другой класс (идентификатор)
/// </summary>
public string ColumnName { get; set; }
/// <summary>
/// Описание зависимости
/// </summary>
public string Description { get; set; }
/// <summary>
/// Описание зависимости сущности от другой сущности (требуется для сохранения и загрузки данных)
/// </summary>
/// <param name="className">Название класса от котрого зависит этот класс</param>
/// <param name="columnName">Название поле в этом классе, которое ссылает на другой класс (идентификатор)</param>
/// <param name="description">Описание зависимости</param>
public EntityDependencyAttribute(string className, string columnName, string description)
{
ClassName = className;
ColumnName = columnName;
Description = description;
}
}
}

View File

@ -0,0 +1,32 @@
using System;
namespace ModelTools.Attributes
{
/// <summary>
/// Описание класса из базы данных, его назначение
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class EntityDescriptionAttribute : Attribute
{
/// <summary>
/// Название сущности, которую описывает класс
/// </summary>
public string EntityName { get; set; }
/// <summary>
/// Описание назначения сущности
/// </summary>
public string Description { get; set; }
/// <summary>
/// Описание класса из базы данных, его назначение
/// </summary>
/// <param name="entityName">Название сущности, которую описывает класс</param>
/// <param name="description">Описание назначения сущности</param>
public EntityDescriptionAttribute(string entityName, string description)
{
EntityName = entityName;
Description = description;
}
}
}

View File

@ -0,0 +1,32 @@
using System;
namespace ModelTools.Attributes
{
/// <summary>
/// Настройка для полей сущности правил маппинга
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class MapConfigurationAttribute : Attribute
{
/// <summary>
/// Название свойства с класса, из которого извлекаем данные
/// </summary>
public string PropertyNameFromModel { get; set; }
/// <summary>
/// Сложное свойство (свойствое в другом классе-свойстве)
/// </summary>
public bool IsDifficle { get; set; }
/// <summary>
/// Настройка для полей сущности правил маппинга
/// </summary>
/// <param name="propertyNameFromMModel">Название свойства с класса, из которого извлекаем данные</param>
/// <param name="isDifficle">Сложное свойство (свойствое в другом классе-свойстве)</param>
public MapConfigurationAttribute(string propertyNameFromMModel, bool isDifficle = false)
{
PropertyNameFromModel = propertyNameFromMModel;
IsDifficle = isDifficle;
}
}
}

View File

@ -0,0 +1,68 @@
using System;
namespace ModelTools.Attributes
{
/// <summary>
/// Настройка отображения элемента в контролах
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ViewModelPropertyAttribute : Attribute
{
/// <summary>
/// Используется при выводе списка
/// </summary>
public bool UseOnList { get; set; }
/// <summary>
/// Используется при выводе элемента
/// </summary>
public bool UseOnElement { get; set; }
/// <summary>
/// Название на форме
/// </summary>
public string DisplayName { get; set; }
/// <summary>
/// Скрывать или нет при выводе списка
/// </summary>
public bool IsHide { get; set; }
/// <summary>
/// Ширина колонки
/// </summary>
public int? ColumnWidth { get; set; }
/// <summary>
/// Настройка отображения элемента в контролах
/// </summary>
/// <param name="displayName">Название на форме</param>
/// <param name="useOnList">Используется при выводе списка</param>
/// <param name="useOnElement">Используется при выводе элемента</param>
/// <param name="isHide">Скрывать или нет</param>
public ViewModelPropertyAttribute(string displayName, bool useOnList, bool useOnElement, bool isHide = false)
{
DisplayName = displayName;
UseOnList = useOnList;
UseOnElement = useOnElement;
ColumnWidth = null;
IsHide = isHide;
}
/// <summary>
/// Конструктор
/// </summary>
/// <param name="displayName">Название на форме</param>
/// <param name="useOnList">Используется при выводе списка</param>
/// <param name="useOnElement">Используется при выводе элемента</param>
/// <param name="columnWidth">Ширина колонки</param>
public ViewModelPropertyAttribute(string displayName, bool useOnList, bool useOnElement, int columnWidth)
{
DisplayName = displayName;
UseOnList = useOnList;
UseOnElement = useOnElement;
ColumnWidth = columnWidth;
IsHide = false;
}
}
}

View File

@ -0,0 +1,20 @@
using System;
namespace ModelTools.BindingModels
{
/// <summary>
/// Информация для доступа к выполнению операций
/// </summary>
public class AccessBindingModel
{
/// <summary>
/// Пропускать проверку (работает только для получения данных)
/// </summary>
public bool SkipCheck { get; set; }
/// <summary>
/// Идентификатор пользователя, который запрашивает выполнение операции
/// </summary>
public Guid? UserId { get; set; }
}
}

View File

@ -0,0 +1,30 @@
using System;
namespace ModelTools.BindingModels
{
/// <summary>
/// Получение записи
/// </summary>
public class GetBindingModel : AccessBindingModel
{
/// <summary>
/// Идентификатор получаемой записи (для одной записи)
/// </summary>
public Guid? Id { get; set; }
/// <summary>
/// Номер страницы, которую получаем (для списка)
/// </summary>
public int? PageNumber { get; set; }
/// <summary>
/// Количество записей возвращаемых (для списка)
/// </summary>
public int? PageSize { get; set; }
/// <summary>
/// Иной признак, по которму отбираем записи (для списка)
/// </summary>
public string PageName { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using System;
namespace ModelTools.BindingModels
{
/// <summary>
/// Сохранение записи по идентификатору
/// </summary>
public class SetBindingModel : AccessBindingModel
{
/// <summary>
/// Идентификатор записи
/// </summary>
public Guid Id { get; set; }
}
}

View File

@ -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
{
/// <summary>
/// Базовый класс для логики сущности
/// </summary>
/// <typeparam name="G"></typeparam>
/// <typeparam name="S"></typeparam>
/// <typeparam name="L"></typeparam>
/// <typeparam name="E"></typeparam>
public abstract class BusinessLogicCore<G, S, L, E>
where G : GetBindingModel
where S : SetBindingModel
where L : ListViewModel<E>
where E : ElementViewModel
{
/// <summary>
/// Перечень ошибок при выполнении операции
/// </summary>
public List<(string Title, string Message)> Errors { get; protected set; }
protected IEntityService<G, S> Service { get; set; }
protected ISecurityManager Security { get; set; }
protected readonly AccessOperation _serviceOperation;
protected readonly string _entity;
public BusinessLogicCore(IEntityService<G, S> service, string entity, AccessOperation serviceOperation)
{
Service = service;
Errors = new List<(string Title, string Message)>();
Security = UnityContainerConfigurator.Resolve<ISecurityManager>();
_entity = entity;
_serviceOperation = serviceOperation;
}
/// <summary>
/// Проверка доступности операции для пользователя
/// </summary>
/// <param name="model"></param>
/// <param name="type"></param>
/// <returns></returns>
protected bool NoAccess(AccessBindingModel model, AccessType type)
{
if (Security.CheckAccess(model, _serviceOperation, type, _entity))
{
return false;
}
Errors.Add(("Ошибка безопасности", Security.ErrorMessage));
return true;
}
/// <summary>
/// Получение списка записей
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Получение записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Создание записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Изменение записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Удаление записи
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Получить список элементов
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
protected abstract L ConvertToL(OperationResultModel model);
/// <summary>
/// Получить элемент
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
protected abstract E ConvertToE(OperationResultModel model);
}
}

View File

@ -0,0 +1,100 @@
using ModelTools.Attributes;
using System;
using System.Reflection;
namespace ModelTools.BusinessLogics
{
/// <summary>
/// Маппер сущностей
/// </summary>
public class Mapper
{
/// <summary>
/// Преобразование из одного класса в другой
/// </summary>
/// <typeparam name="From"></typeparam>
/// <typeparam name="To"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static To MapToClass<From, To>(From obj) where To : class => FillObject(obj, (To)Activator.CreateInstance(typeof(To)));
/// <summary>
/// Преобразование из одного класса в другой
/// </summary>
/// <typeparam name="From"></typeparam>
/// <typeparam name="To"></typeparam>
/// <param name="obj"></param>
/// <param name="newObject"></param>
/// <returns></returns>
public static To MapToClass<From, To>(From obj, To newObject) where To : class => FillObject(obj, newObject);
/// <summary>
/// Заполнение объекта
/// </summary>
/// <typeparam name="From"></typeparam>
/// <typeparam name="To"></typeparam>
/// <param name="obj"></param>
/// <param name="newObject"></param>
/// <returns></returns>
private static To FillObject<From, To>(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<MapConfigurationAttribute>();
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;
}
}
}

View File

@ -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
{
/// <summary>
/// Загрузчик данных
/// </summary>
public static class ServiceProviderLoader
{
private static readonly string _configFileName = "DepartmentPortal.config";
private static readonly string _pathToLoaderExt = "..\\..\\..\\..\\Extensions\\";
/// <summary>
/// Получение данных с файла настроек
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Загрузка всех классов-реализаций ILoaderExtensions
/// </summary>
/// <returns></returns>
public static List<ILoaderExtensions> GetLoaderExtensions()
{
var list = new List<ILoaderExtensions>();
if(Directory.Exists(_pathToLoaderExt))
{
var files = Directory.GetFiles(_pathToLoaderExt, "*.dll", SearchOption.AllDirectories);
var loadedFiles = new List<string>();
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;
}
/// <summary>
/// Получение имени файла
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
private static string GetFile(string fileName) => Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), fileName);
}
}

View File

@ -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;
}
}
/// <summary>
/// Инициализация сервисов
/// </summary>
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<T, U>() where U : T => Container.RegisterType<T, U>(new HierarchicalLifetimeManager());
public static void PublishService<T>() => Container.RegisterType<T>(new HierarchicalLifetimeManager());
public static T Resolve<T>() => Container.Resolve<T>();
}
}

View File

@ -0,0 +1,100 @@
namespace ModelTools.Enums
{
/// <summary>
/// Операции в системе
/// </summary>
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
}
}

View File

@ -0,0 +1,34 @@
namespace ModelTools.Enums
{
/// <summary>
/// Тип операции
/// </summary>
public enum AccessType : int
{
/// <summary>
/// Простой просомтр
/// </summary>
SimpleView = 0,
/// <summary>
/// Полный просомтр
/// </summary>
FullView = 1,
/// <summary>
/// Добавление/Изменение
/// </summary>
Change = 2,
/// <summary>
/// Удаление
/// </summary>
Delete = 4,
// TODO убрать
/// <summary>
/// Доступ к админке
/// </summary>
Administrator = 8
}
}

View File

@ -0,0 +1,38 @@
namespace ModelTools.Enums
{
/// <summary>
/// Статус результата операции
/// </summary>
public enum ResultServiceStatusCode
{
/// <summary>
/// Успешно
/// </summary>
Success = 200,
/// <summary>
/// Ошибка общая
/// </summary>
Error = 400,
/// <summary>
/// Элемент уже сущствует
/// </summary>
ExsistItem = 401,
/// <summary>
/// Запись удалена
/// </summary>
WasDelete = 402,
/// <summary>
/// Не найдено
/// </summary>
NotFound = 404,
/// <summary>
/// Не найден файл
/// </summary>
FileNotFound = 405
}
}

View File

@ -0,0 +1,28 @@
using System.IO;
namespace ModelTools.Extensions
{
public static class StringExtension
{
/// <summary>
/// Проверка, что строка пустая
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static bool IsEmpty(this string str) => string.IsNullOrEmpty(str);
/// <summary>
/// Проверка, что строка не пустая
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static bool IsNotEmpty(this string str) => !string.IsNullOrEmpty(str);
/// <summary>
/// Получение имени файла по полному пути
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string GetFileName(this string str) => (new FileInfo(str)).Name;
}
}

View File

@ -0,0 +1,41 @@
using ModelTools.BindingModels;
using ModelTools.OperationResultModels;
namespace ModelTools.Interfaces
{
/// <summary>
/// Описание логики для хранилища сущности
/// </summary>
public interface IEntityService<G, S>
where G : GetBindingModel
where S : SetBindingModel
{
/// <summary>
/// Получение списка сущностей
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
OperationResultModel Read(G model);
/// <summary>
/// Создание новой сущности
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
OperationResultModel Create(S model);
/// <summary>
/// Изменение сущности
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
OperationResultModel Update(S model);
/// <summary>
/// Удаление сущности
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
OperationResultModel Delete(G model);
}
}

View File

@ -0,0 +1,13 @@
namespace ModelTools.Interfaces
{
/// <summary>
/// Интерфейс для регистрации зависомстей в модулях
/// </summary>
public interface ILoaderExtensions
{
/// <summary>
/// Регистрация сервисов
/// </summary>
public void RegisterServices();
}
}

View File

@ -0,0 +1,23 @@
using ModelTools.BindingModels;
using ModelTools.Enums;
namespace ModelTools.Interfaces
{
public interface ISecurityManager
{
/// <summary>
/// Сообщение с причиной не получения доступа
/// </summary>
string ErrorMessage { get; set; }
/// <summary>
/// Авторизация пользователя к операции
/// </summary>
/// <param name="model">Данные по пользователю</param>
/// <param name="operation">Операция, которую хотят выполнить</param>
/// <param name="type">Тип операции</param>
/// <param name="entity">Для какой сущности</param>
/// <returns></returns>
bool CheckAccess(AccessBindingModel model, AccessOperation operation, AccessType type, string entity);
}
}

View File

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Unity" Version="5.11.10" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,114 @@
using ModelTools.Enums;
using System;
using System.Collections.Generic;
namespace ModelTools.OperationResultModels
{
/// <summary>
/// Результат любой операции
/// </summary>
public class OperationResultModel
{
/// <summary>
/// Успешность операции (количество ошибок = 0)
/// </summary>
public bool IsSucceeded => Errors.Count == 0;
/// <summary>
/// Статус операции
/// </summary>
public ResultServiceStatusCode StatusCode { get; set; }
/// <summary>
/// Спсиок ошибок
/// </summary>
public List<(string Title, string Message)> Errors { get; private set; }
/// <summary>
/// Объект, получаемый по результатам операции
/// </summary>
public object Result { get; private set; }
/// <summary>
/// Конструктор по умолчанию
/// </summary>
public OperationResultModel()
{
Errors = new List<(string Title, string Message)>();
StatusCode = ResultServiceStatusCode.Success;
}
/// <summary>
/// Успешно
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static OperationResultModel Success(object obj)
{
return new OperationResultModel
{
Result = obj,
Errors = new List<(string Title, string Message)>(),
StatusCode = ResultServiceStatusCode.Success
};
}
/// <summary>
/// Добавление простой ошибки
/// </summary>
/// <param name="model"></param>
/// <param name="key"></param>
/// <param name="value"></param>
public static OperationResultModel Error(string key, string value) => Error(key, value, ResultServiceStatusCode.Error);
/// <summary>
/// Добавление простой ошибки со сменой статуса
/// </summary>
/// <param name="model"></param>
/// <param name="key"></param>
/// <param name="error"></param>
/// <param name="statusCode"></param>
public static OperationResultModel Error(string key, string error, ResultServiceStatusCode statusCode)
{
var model = new OperationResultModel();
model.Errors.Add((key, error));
model.StatusCode = statusCode;
return model;
}
/// <summary>
/// Добавление ошибки
/// </summary>
/// <param name="model"></param>
/// <param name="error"></param>
public static OperationResultModel Error(Exception error) => Error(error, ResultServiceStatusCode.Error);
/// <summary>
/// Добавление ошибки
/// </summary>
/// <param name="model"></param>
/// <param name="error"></param>
/// <param name="statusCode"></param>
public static OperationResultModel Error(Exception error, ResultServiceStatusCode statusCode) => Error("Ошибка", error, statusCode);
/// <summary>
/// Добавление ошибки (включая вложеннные)
/// </summary>
/// <param name="model"></param>
/// <param name="key"></param>
/// <param name="error"></param>
/// <param name="statusCode"></param>
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;
}
}
}

View File

@ -0,0 +1,15 @@
using ModelTools.Attributes;
using System;
namespace ModelTools.ViewModels
{
/// <summary>
/// Возвращаемая запись
/// </summary>
public class ElementViewModel
{
[ViewModelProperty("Идентификатор", useOnList: true, useOnElement: false, isHide: true)]
[MapConfiguration("Id")]
public Guid Id { get; set; }
}
}

View File

@ -0,0 +1,16 @@
using System.Collections.Generic;
namespace ModelTools.ViewModels
{
/// <summary>
/// Список возвращаемых значений
/// </summary>
/// <typeparam name="T"></typeparam>
public class ListViewModel<T>
where T : ElementViewModel
{
public int MaxCount { get; set; }
public List<T> List { get; set; }
}
}

View File

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

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionString>Data Source=10.3.1.13\SQLEXPRESS;Initial Catalog=DepartmentDatabasePortal;persist security info=True;user id=sa;password=isadmin;MultipleActiveResultSets=True;</connectionString>
</configuration>

View File

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\DatabaseCore\DatabaseCore.csproj" />
<ProjectReference Include="..\Security\SecurityBusinessLogic\SecurityBusinessLogic.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="DepartmentPortal.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -0,0 +1,119 @@

namespace DepartmentPortalDesctop
{
partial class FormEnter
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -0,0 +1,32 @@
using SecurityBusinessLogic.BusinessLogics;
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DepartmentPortalDesctop
{
/// <summary>
/// Форма входа в систему
/// </summary>
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<KeyValuePair<string, string>> { new KeyValuePair<string, string>("Аутентфикация", ex.Message) });
}
}
}
}

View File

@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,125 @@

namespace DepartmentPortalDesctop
{
partial class FormMain
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace DepartmentPortalDesctop
{
public partial class FormMain : Form
{
private Dictionary<Guid, Control> controls;
public FormMain()
{
InitializeComponent();
controls = new Dictionary<Guid, Control>();
}
private void ButtonShowHideControlList_Click(object sender, EventArgs e)
{
ButtonShowHideControlList.Text = panelControls.Visible ? ">" : "<";
panelControls.Visible = !panelControls.Visible;
}
}
}

View File

@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -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
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
UnityContainerConfigurator.PublishService<ISecurityManager, SecurityManager>();
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<FormMain>());
}
}
}
}

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
using ModelTools.BindingModels;
using ModelTools.Enums;
using System;
using System.ComponentModel.DataAnnotations;
namespace SecurityBusinessLogic.BindingModels
{
/// <summary>
/// Получение информации по доступу
/// </summary>
public class AccessGetBindingModel : GetBindingModel
{
public Guid? RoleId { get; set; }
}
/// <summary>
/// Сохранение информации по доступу
/// </summary>
public class AccessSetBindingModel : SetBindingModel
{
public Guid RoleId { get; set; }
[Required(ErrorMessage = "required")]
public AccessOperation Operation { get; set; }
public AccessType AccessType { get; set; }
}
}

View File

@ -0,0 +1,25 @@
using ModelTools.BindingModels;
using System.ComponentModel.DataAnnotations;
namespace SecurityBusinessLogic.BindingModels
{
/// <summary>
/// Получение общих настроек системы
/// </summary>
public class EnviromentSettingGetBindingModel : GetBindingModel
{
public string Key { get; set; }
}
/// <summary>
/// Сохранение общих настроек системы
/// </summary>
public class EnviromentSettingSetBindingModel : SetBindingModel
{
[Required(ErrorMessage = "required")]
public string Key { get; set; }
[Required(ErrorMessage = "required")]
public string Value { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using ModelTools.BindingModels;
using System.ComponentModel.DataAnnotations;
namespace SecurityBusinessLogic.BindingModels
{
/// <summary>
/// Получение роли
/// </summary>
public class RoleGetBindingModel : GetBindingModel { }
/// <summary>
/// Сохранение роли
/// </summary>
public class RoleSetBindingModel : SetBindingModel
{
[Required(ErrorMessage = "required")]
public string RoleName { get; set; }
[Required(ErrorMessage = "required")]
public int RolePriority { get; set; }
}
}

View File

@ -0,0 +1,49 @@
using ModelTools.BindingModels;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace SecurityBusinessLogic.BindingModels
{
/// <summary>
/// Получение пользователя
/// </summary>
public class UserGetBindingModel : GetBindingModel
{
public bool? IsBanned { get; set; }
public string Login { get; set; }
public string Password { get; set; }
public List<Guid> LecturerIds { get; set; }
}
/// <summary>
/// Сохранение пользователя
/// </summary>
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; }
}
}

View File

@ -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
{
/// <summary>
/// Логика работы с доступами
/// </summary>
public class AccessBusinessLogic : BusinessLogicCore<AccessGetBindingModel, AccessSetBindingModel, AccessListViewModel, AccessViewModel>
{
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;
}
}

View File

@ -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
{
/// <summary>
/// Логика работы с общими настройками системы
/// </summary>
public class EnviromentSettingBusinessLogic : BusinessLogicCore<EnviromentSettingGetBindingModel, EnviromentSettingSetBindingModel,
EnviromentSettingListViewModel, EnviromentSettingViewModel>
{
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;
}
}

View File

@ -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
{
/// <summary>
/// Логика работы с ролями
/// </summary>
public class RoleBusinessLogic : BusinessLogicCore<RoleGetBindingModel, RoleSetBindingModel, RoleListViewModel, RoleViewModel>
{
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;
}
}

View File

@ -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
{
/// <summary>
/// Логика работы с пользователями
/// </summary>
public class UserBusinessLogic : BusinessLogicCore<UserGetBindingModel, UserSetBindingModel, UserListViewModel, UserViewModel>
{
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;
}
}

View File

@ -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
{
/// <summary>
/// Менеджер по работе с пользователем системы
/// </summary>
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<RoleBusinessLogic>();
_userBusinessLogic = UnityContainerConfigurator.Resolve<UserBusinessLogic>();
}
public static UserManager GetInstance
{
get
{
if (_userManager == null)
{
lock (_lockObject)
{
_userManager = new UserManager();
}
}
return _userManager;
}
}
/// <summary>
/// Аутентифицированный пользователь
/// </summary>
public UserViewModel User { get; private set; }
/// <summary>
/// Список ролей аутентифицированного пользователь
/// </summary>
public List<Guid> Roles { get; private set; }
/// <summary>
/// Сообщение об ошибке
/// </summary>
public string ErrorMessage { get; private set; }
/// <summary>
/// Идентификатор аутентифицированного пользователь
/// </summary>
public Guid? UserId => User?.Id;
/// <summary>
/// Выполнена ли аутентификация
/// </summary>
public bool IsAuth => User != null;
/// <summary>
/// Аутентификация пользователя
/// </summary>
/// <param name="login"></param>
/// <param name="password"></param>
/// <returns></returns>
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();
});
}
/// <summary>
/// Выход из системы
/// </summary>
/// <returns></returns>
public async Task LogoutAsync()
{
await Task.Run(() =>
{
User = null;
Roles = null;
});
}
/// <summary>
/// Смена пароля
/// </summary>
/// <param name="login"></param>
/// <param name="oldPassword"></param>
/// <param name="newPassword"></param>
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);
}
/// <summary>
/// Получение хеша пароля
/// </summary>
/// <param name="password"></param>
/// <returns></returns>
public static string GetPasswordHash(string password) => Encoding.ASCII.GetString((new MD5CryptoServiceProvider()).ComputeHash(Encoding.ASCII.GetBytes(password)));
/// <summary>
/// Получение модели для сохранения из представления
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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
};
}
}
}

View File

@ -0,0 +1,10 @@
using ModelTools.Interfaces;
using SecurityBusinessLogic.BindingModels;
namespace SecurityBusinessLogic.Interfaces
{
/// <summary>
/// Хранение доступов
/// </summary>
public interface IAccessService : IEntityService<AccessGetBindingModel, AccessSetBindingModel> { }
}

View File

@ -0,0 +1,10 @@
using ModelTools.Interfaces;
using SecurityBusinessLogic.BindingModels;
namespace SecurityBusinessLogic.Interfaces
{
/// <summary>
/// Хранение общих настроек системы
/// </summary>
public interface IEnviromentSettingService : IEntityService<EnviromentSettingGetBindingModel, EnviromentSettingSetBindingModel> { }
}

View File

@ -0,0 +1,10 @@
using ModelTools.Interfaces;
using SecurityBusinessLogic.BindingModels;
namespace SecurityBusinessLogic.Interfaces
{
/// <summary>
/// Хранение ролей
/// </summary>
public interface IRoleService : IEntityService<RoleGetBindingModel, RoleSetBindingModel> { }
}

View File

@ -0,0 +1,10 @@
using ModelTools.Interfaces;
using SecurityBusinessLogic.BindingModels;
namespace SecurityBusinessLogic.Interfaces
{
/// <summary>
/// Хранение пользователей
/// </summary>
public interface IUserService : IEntityService<UserGetBindingModel, UserSetBindingModel> { }
}

View File

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\ModelTools\ModelTools.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Enums\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,42 @@
using ModelTools.Attributes;
using ModelTools.Enums;
using ModelTools.ViewModels;
using System;
namespace SecurityBusinessLogic.ViewModels
{
/// <summary>
/// Список достпуов
/// </summary>
public class AccessListViewModel : ListViewModel<AccessViewModel> { }
/// <summary>
/// Элемент доступа
/// </summary>
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})";
}
}

View File

@ -0,0 +1,26 @@
using ModelTools.Attributes;
using ModelTools.ViewModels;
namespace SecurityBusinessLogic.ViewModels
{
/// <summary>
/// Список общих настроек системы
/// </summary>
public class EnviromentSettingListViewModel : ListViewModel<EnviromentSettingViewModel> { }
/// <summary>
/// Элемент общих настроек системы
/// </summary>
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;
}
}

View File

@ -0,0 +1,26 @@
using ModelTools.Attributes;
using ModelTools.ViewModels;
namespace SecurityBusinessLogic.ViewModels
{
/// <summary>
/// Список ролей
/// </summary>
public class RoleListViewModel : ListViewModel<RoleViewModel> { }
/// <summary>
/// Элемент ролей
/// </summary>
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;
}
}

View File

@ -0,0 +1,62 @@
using ModelTools.Attributes;
using ModelTools.ViewModels;
using System;
namespace SecurityBusinessLogic.ViewModels
{
/// <summary>
/// Список пользователей
/// </summary>
public class UserListViewModel : ListViewModel<UserViewModel> { }
/// <summary>
/// Элемент пользователей
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Реализация IAccessService
/// </summary>
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<AccessSetBindingModel, Access>(model);
context.Accesses.Add(entity);
context.SaveChanges();
return OperationResultModel.Success(Mapper.MapToClass<Access, AccessViewModel>(entity));
}
else
{
if (exsistEntity.IsDeleted)
{
exsistEntity.IsDeleted = false;
context.SaveChanges();
return OperationResultModel.Success(Mapper.MapToClass<Access, AccessViewModel>(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<Access, AccessViewModel>(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<Access, AccessViewModel>).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<Access, AccessViewModel>(entity));
}
}
}

View File

@ -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
{
/// <summary>
/// Реализация IEnviromentSettingService
/// </summary>
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<EnviromentSettingSetBindingModel, EnviromentSetting>(model);
context.EnviromentSettings.Add(entity);
context.SaveChanges();
return OperationResultModel.Success(Mapper.MapToClass<EnviromentSetting, EnviromentSettingViewModel>(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<EnviromentSetting, EnviromentSettingViewModel>(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<EnviromentSetting, EnviromentSettingViewModel>(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<EnviromentSetting, EnviromentSettingViewModel>).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<EnviromentSetting, EnviromentSettingViewModel>(entity));
}
}
}

View File

@ -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
{
/// <summary>
/// Реализация IRoleService
/// </summary>
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<RoleSetBindingModel, Role>(model);
context.Roles.Add(entity);
context.SaveChanges();
return OperationResultModel.Success(Mapper.MapToClass<Role, RoleViewModel>(entity));
}
else
{
if (exsistEntity.IsDeleted)
{
exsistEntity.IsDeleted = false;
context.SaveChanges();
return OperationResultModel.Success(Mapper.MapToClass<Role, RoleViewModel>(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<Role, RoleViewModel>(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<Role, RoleViewModel>).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<RoleSetBindingModel, Role>(model, entity);
context.SaveChanges();
return OperationResultModel.Success(Mapper.MapToClass<Role, RoleViewModel>(entity));
}
}
}

View File

@ -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
{
/// <summary>
/// Реализация IUserService
/// </summary>
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<UserSetBindingModel, User>(model);
context.Users.Add(entity);
context.SaveChanges();
return OperationResultModel.Success(Mapper.MapToClass<User, UserViewModel>(entity));
}
else
{
if (exsistEntity.IsDeleted)
{
exsistEntity.IsDeleted = false;
context.SaveChanges();
return OperationResultModel.Success(Mapper.MapToClass<User, UserViewModel>(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<User, UserViewModel>(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<User, UserViewModel>(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<User, UserViewModel>(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<User, UserViewModel>).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<User, UserViewModel>(entity));
}
}
}

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>..\..\Extensions\</OutputPath>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\DatabaseCore\DatabaseCore.csproj" />
<ProjectReference Include="..\SecurityBusinessLogic\SecurityBusinessLogic.csproj" />
</ItemGroup>
</Project>

View File

@ -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<IAccessService, AccessService>();
UnityContainerConfigurator.PublishService<IEnviromentSettingService, EnviromentSettingService>();
UnityContainerConfigurator.PublishService<IRoleService, RoleService>();
UnityContainerConfigurator.PublishService<IUserService, UserService>();
UnityContainerConfigurator.PublishService<AccessBusinessLogic>();
UnityContainerConfigurator.PublishService<EnviromentSettingBusinessLogic>();
UnityContainerConfigurator.PublishService<RoleBusinessLogic>();
UnityContainerConfigurator.PublishService<UserBusinessLogic>();
}
}
}