private eAuthResult CreateUserContext(int IdUser, string user, string password, out IUserContext userContext, out string resultReason) { var authorizationAttemptsExceeded = false; var id = 0; userContext = null; resultReason = null; Modules.Auth.ModuleConfiguration authConfig = null; using (var db = new CoreDB.CoreContext()) using (var scope = db.CreateScope(TransactionScopeOption.RequiresNew)) { var returnNewFailedResultWithAuthAttempt = new Func <string, string>(message => { RegisterLogHistoryEvent(id, EventType.Error, EventCodeAuthError, "Ошибка авторизации", message); if (id > 0) { db.ExecuteQuery( $"UPDATE users SET AuthorizationAttempts = (AuthorizationAttempts + 1){(authorizationAttemptsExceeded ? ", BlockedUntil=@BlockedUntil, BlockedReason=@BlockedReason" : "")} WHERE id=@IdUser", new { IdUser = id, BlockedUntil = DateTime.Now.Timestamp() + authConfig.AuthorizationAttemptsBlock, BlockedReason = authConfig.AuthorizationAttemptsBlockMessage, } ); } return(message + (authorizationAttemptsExceeded ? " " + authConfig.AuthorizationAttemptsMessage : "")); }); try { authConfig = AppCore.Get <Modules.Auth.ModuleAuth>()?.GetConfiguration <Modules.Auth.ModuleConfiguration>(); var checkCredentialsResult = CheckCredentials(IdUser, user, password, db, out var res); if (!checkCredentialsResult.IsSuccess) { resultReason = returnNewFailedResultWithAuthAttempt(checkCredentialsResult.Message); return(checkCredentialsResult.AuthResult); } id = res.IdUser; var attempts = authConfig.AuthorizationAttempts; authorizationAttemptsExceeded = attempts > 0 && (res.AuthorizationAttempts + 1) >= attempts; AppCore.Get <UsersManager>().getUsers(new Dictionary <int, CoreDB.User>() { { id, res } }); var context = new UserContext(res, true); ((IComponentStartable)context).Start(AppCore); var permissionsResult = AppCore.GetUserContextManager().GetPermissions(context.IdUser); if (!permissionsResult.IsSuccess) { resultReason = returnNewFailedResultWithAuthAttempt(permissionsResult.Message); return(eAuthResult.UnknownError); } context.ApplyPermissions(permissionsResult.Result); RegisterLogHistoryEvent(id, EventType.Info, EventCodeAuthSuccess, "Успешный вход"); res.AuthorizationAttempts = 0; db.SaveChanges(); userContext = context; var checkStateResult = CheckUserState(res, res.Comment); if (checkStateResult.IsSuccess) { return(eAuthResult.Success); } else { resultReason = returnNewFailedResultWithAuthAttempt(checkStateResult.Message); return(checkStateResult.AuthResult); } } catch (Exception ex) { this.RegisterEvent(EventType.CriticalError, "Неизвестная ошибка во время получения контекста пользователя.", $"IdUser={IdUser}, Login='******'.", null, ex); userContext = null; resultReason = "Неизвестная ошибка во время получения контекста пользователя."; return(eAuthResult.UnknownError); } finally { scope.Complete(); } } }
private ExecutionAuthResult CheckCredentials(int idUser, string login, string password, CoreDB.CoreContext db, out CoreDB.User outData) { outData = null; if (idUser == (int.MaxValue - 1)) { return(new ExecutionAuthResult(eAuthResult.NothingFound, $"Пользователь '{login}' не найден в базе данных.")); } try { if (idUser <= 0 && string.IsNullOrEmpty(login)) { return(new ExecutionAuthResult(eAuthResult.WrongAuthData, "Не указаны реквизиты для авторизации!")); } List <CoreDB.User> query = null; bool directAuthorize = false; // Если в $user передан id и $password не передан вообще. if (idUser > 0) { query = db.Users.Where(x => x.IdUser == idUser).ToList(); directAuthorize = true; } // Если Email if (query == null && login.isEmail()) { switch (AppCore.WebConfig.userAuthorizeAllowed) { case eUserAuthorizeAllowed.Nothing: return(new ExecutionAuthResult(eAuthResult.AuthDisabled, "Авторизация запрещена.")); case eUserAuthorizeAllowed.OnlyPhone: return(new ExecutionAuthResult(eAuthResult.AuthMethodNotAllowed, "Авторизация возможна только по номеру телефона.")); case eUserAuthorizeAllowed.EmailAndPhone: case eUserAuthorizeAllowed.OnlyEmail: query = (from p in db.Users where p.email.ToLower() == login.ToLower() select p).ToList(); break; } } // Если номер телефона if (query == null) { var phone = PhoneBuilder.ParseString(login); if (phone.IsCorrect) { switch (AppCore.WebConfig.userAuthorizeAllowed) { case eUserAuthorizeAllowed.Nothing: return(new ExecutionAuthResult(eAuthResult.AuthDisabled, "Авторизация запрещена.")); case eUserAuthorizeAllowed.OnlyEmail: return(new ExecutionAuthResult(eAuthResult.AuthMethodNotAllowed, "Авторизация возможна только через электронную почту.")); case eUserAuthorizeAllowed.EmailAndPhone: case eUserAuthorizeAllowed.OnlyPhone: query = (from p in db.Users where p.phone.ToLower() == phone.ParsedPhoneNumber.ToLower() select p).ToList(); break; } } else { if (!login.isEmail()) { return(new ExecutionAuthResult(eAuthResult.WrongAuthData, "Переданные данные не являются ни номером телефона, ни адресом электронной почты.")); } } } if (query == null) { return(new ExecutionAuthResult(eAuthResult.UnknownError, "Что-то пошло не так во время авторизации.")); } if (query.Count == 1) { var res = query.First(); if (directAuthorize || res.password == UsersExtensions.hashPassword(password)) { outData = res; return(new ExecutionAuthResult(eAuthResult.Success)); } else { return(new ExecutionAuthResult(eAuthResult.WrongPassword, "Неверный пароль.")); } } else if (query.Count > 1) { AppCore.Get <MessagingManager>().RegisterEvent(EventType.CriticalError, "Одинаковые реквизиты входа!", $"Найдено несколько пользователей с логином '{login}'"); return(new ExecutionAuthResult(eAuthResult.MultipleFound, "Найдено несколько пользователей с логином '" + login + "'. Обратитесь к администратору для решения проблемы.")); } else { return(new ExecutionAuthResult(eAuthResult.NothingFound, $"Пользователь '{login}' не найден в базе данных.")); } } catch (Exception ex) { this.RegisterEvent(EventType.Error, "Ошибка во время поиска и проверки пользователя", $"IdUser={idUser}, Login='******'.", null, ex); return(new ExecutionAuthResult(eAuthResult.UnknownError, "Неизвестная ошибка во время проверки авторизации.")); } }