using ModelTools.BusinessLogics; using SecurityBusinessLogic.BindingModels; using SecurityBusinessLogic.ViewModels; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace SecurityBusinessLogic.BusinessLogics { /// /// Менеджер по работе с пользователем системы /// public class UserManager { private readonly int _countDayToBanned = 3; private readonly int _countMaxAttempt = 3; private readonly RoleBusinessLogic _roleBusinessLogic; private readonly UserBusinessLogic _userBusinessLogic; private static UserManager _userManager; private static readonly object _lockObject = new(); private UserManager() { _roleBusinessLogic = UnityContainerConfigurator.Resolve(); _userBusinessLogic = UnityContainerConfigurator.Resolve(); } public static UserManager GetInstance { get { if (_userManager == null) { lock (_lockObject) { _userManager = new UserManager(); } } return _userManager; } } /// /// Аутентифицированный пользователь /// public UserViewModel User { get; private set; } /// /// Список ролей аутентифицированного пользователь /// public List Roles { get; private set; } /// /// Сообщение об ошибке /// public string ErrorMessage { get; private set; } /// /// Идентификатор аутентифицированного пользователь /// public Guid? UserId => User?.Id; /// /// Выполнена ли аутентификация /// public bool IsAuth => User != null; /// /// Аутентификация пользователя /// /// /// /// public async Task LoginAsync(string login, string password) { await Task.Run(() => { UserSetBindingModel model; var passwordHash = GetPasswordHash(password); var user = _userBusinessLogic.GetElement(new UserGetBindingModel { Login = login, Password = passwordHash, SkipCheck = true }); if (user == null) { if(_userBusinessLogic.Errors.Count > 0) { throw new Exception(_userBusinessLogic.Errors[0].Message); } user = _userBusinessLogic.GetElement(new UserGetBindingModel { Login = login, IsBanned = true, SkipCheck = true }); if (user != null) { user.CountAttempt++; if (user.CountAttempt > _countMaxAttempt) { user.IsBanned = true; user.DateBanned = DateTime.Now; } model = GetSetBindingModel(user); model.Password = passwordHash; _userBusinessLogic.Update(model); } if (_userBusinessLogic.Errors.Count > 0) { throw new Exception(_userBusinessLogic.Errors[0].Message); } throw new Exception("Введен неверный логин/пароль"); } if (user.IsBanned) { if (user.DateBanned.Value.AddDays(_countDayToBanned) > DateTime.Now) { user.IsBanned = false; } else { throw new Exception("Пользователь заблокирован"); } } user.DateLastVisit = DateTime.Now; user.CountAttempt = 0; model = GetSetBindingModel(user); model.Password = passwordHash; _userBusinessLogic.Update(model); User = user; Roles = _roleBusinessLogic.GetList(new RoleGetBindingModel { UserId = User.Id }).List.Select(x => x.Id).ToList(); }); } /// /// Выход из системы /// /// public async Task LogoutAsync() { await Task.Run(() => { User = null; Roles = null; }); } /// /// Смена пароля /// /// /// /// public void ChangePassword(string login, string oldPassword, string newPassword) { var user = _userBusinessLogic.GetElement(new UserGetBindingModel { Login = login, Password = GetPasswordHash(oldPassword), SkipCheck = true }); if (user == null) { throw new Exception("Введен неверный логин/пароль"); } if (user.IsBanned) { throw new Exception("Пользователь забаннен"); } var model = GetSetBindingModel(user); model.Password = GetPasswordHash(newPassword); _userBusinessLogic.Update(model); } /// /// Получение хеша пароля /// /// /// public static string GetPasswordHash(string password) => Encoding.ASCII.GetString((new MD5CryptoServiceProvider()).ComputeHash(Encoding.ASCII.GetBytes(password))); /// /// Получение модели для сохранения из представления /// /// /// private static UserSetBindingModel GetSetBindingModel(UserViewModel model) { return new UserSetBindingModel { Id = model.Id, Login = model.Login, LecturerId = model.LecturerId, StudentId = model.StudentId, EmployeeId = model.EmployeeId, Avatar = model.Avatar, IsBanned = model.IsBanned, DateBanned = model.DateBanned, CountAttempt = model.CountAttempt, DateLastVisit = model.DateLastVisit }; } } }