From ed0d95b77469db4591c63f3a93dc7df40cc0e68e Mon Sep 17 00:00:00 2001 From: nuxsmin Date: Mon, 26 Feb 2018 14:07:14 +0100 Subject: [PATCH] * [ADD] Improved tracking handling. * [MOD] Improved login process workflow. --- INSTALL | 1 - .../web/Controllers/LoginController.php | 29 +- .../web/Controllers/Traits/JsonTrait.php | 16 +- lib/SP/DataModel/TrackData.php | 5 +- lib/SP/Repositories/Track/TrackRepository.php | 164 +++++++++++ lib/SP/Repositories/Track/TrackRequest.php | 53 ++++ lib/SP/Services/Auth/LoginResponse.php | 47 ++++ lib/SP/Services/Auth/LoginService.php | 259 +++++++++++------- lib/SP/Services/Track/TrackService.php | 113 ++++++++ public/js/app-actions.js | 4 +- public/js/app-actions.min.js | 6 +- public/js/app-main.min.js | 2 +- public/js/app-triggers.min.js | 2 +- 13 files changed, 581 insertions(+), 120 deletions(-) create mode 100644 lib/SP/Repositories/Track/TrackRepository.php create mode 100644 lib/SP/Repositories/Track/TrackRequest.php create mode 100644 lib/SP/Services/Auth/LoginResponse.php create mode 100644 lib/SP/Services/Track/TrackService.php diff --git a/INSTALL b/INSTALL index 689bad7f..e18c481d 100644 --- a/INSTALL +++ b/INSTALL @@ -40,4 +40,3 @@ Telepítés és gyakran feltett kérdésekre https://doc.syspass.org Installation et Foire aux questions du https://doc.syspass.org --- - diff --git a/app/modules/web/Controllers/LoginController.php b/app/modules/web/Controllers/LoginController.php index fe9cd034..0e7edd03 100644 --- a/app/modules/web/Controllers/LoginController.php +++ b/app/modules/web/Controllers/LoginController.php @@ -29,10 +29,11 @@ use SP\Core\Events\EventMessage; use SP\Core\SessionFactory; use SP\Core\SessionUtil; use SP\Html\Html; +use SP\Http\Request; use SP\Http\Response; use SP\Modules\Web\Controllers\Helpers\LayoutHelper; +use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Services\Auth\LoginService; -use SP\Util\Json; /** * Class LoginController @@ -41,17 +42,37 @@ use SP\Util\Json; */ class LoginController extends ControllerBase { + use JsonTrait; + /** * Login action * - * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface */ public function loginAction() { - $loginService = $this->dic->get(LoginService::class); - Json::returnJson($loginService->doLogin()); + try { + $loginService = $this->dic->get(LoginService::class); + $loginResponmse = $loginService->doLogin(); + + $forward = Request::getRequestHeaders('X-Forwarded-For'); + + if ($forward) { + $this->eventDispatcher->notifyEvent('login.info', + new Event($this, EventMessage::factory() + ->addDetail('X-Forwarded-For', $this->configData->isDemoEnabled() ? '***' : $forward)) + ); + } + + $this->returnJsonResponseData(['url' => $loginResponmse->getRedirect()]); + } catch (\Exception $e) { + processException($e); + + $this->eventDispatcher->notifyEvent('exception', new Event($e)); + + $this->returnJsonResponse($e->getCode(), $e->getMessage()); + } } /** diff --git a/app/modules/web/Controllers/Traits/JsonTrait.php b/app/modules/web/Controllers/Traits/JsonTrait.php index 8246358a..be249b5d 100644 --- a/app/modules/web/Controllers/Traits/JsonTrait.php +++ b/app/modules/web/Controllers/Traits/JsonTrait.php @@ -38,9 +38,9 @@ trait JsonTrait /** * Returns JSON response * - * @param int $status Status code - * @param string $description Untranslated description string - * @param array|null $messages Untranslated massages array of strings + * @param int $status Status code + * @param string $description Untranslated description string + * @param array|null $messages Untranslated massages array of strings */ protected function returnJsonResponse($status, $description, array $messages = null) { @@ -59,10 +59,10 @@ trait JsonTrait * Returns JSON response * * @param mixed $data - * @param int $status Status code - * @param null $description Untranslated description string + * @param int $status Status code + * @param null $description Untranslated description string */ - protected function returnJsonResponseData($data, $status = 0, $description = null) + protected function returnJsonResponseData($data, $status = JsonResponse::JSON_SUCCESS, $description = null) { $jsonResponse = new JsonResponse(); $jsonResponse->setStatus($status); @@ -80,7 +80,7 @@ trait JsonTrait * Returns JSON response * * @param \Exception $exception - * @param int $status Status code + * @param int $status Status code */ protected function returnJsonResponseException(\Exception $exception, $status = JsonResponse::JSON_ERROR) { @@ -88,7 +88,7 @@ trait JsonTrait $jsonResponse->setStatus($status); $jsonResponse->setDescription($exception->getMessage()); - if ($exception instanceof SPException && $exception->getHint() !== null ) { + if ($exception instanceof SPException && $exception->getHint() !== null) { $jsonResponse->setMessages([$exception->getHint()]); } diff --git a/lib/SP/DataModel/TrackData.php b/lib/SP/DataModel/TrackData.php index e4329e47..79170206 100644 --- a/lib/SP/DataModel/TrackData.php +++ b/lib/SP/DataModel/TrackData.php @@ -25,7 +25,6 @@ namespace SP\DataModel; use SP\Core\Exceptions\InvalidArgumentException; -use SP\Core\Exceptions\SPException; /** * Class TrackData @@ -152,9 +151,9 @@ class TrackData extends DataModelBase } elseif (strlen($ip) > 4) { $this->ipv6 = $ip; } elseif ($ip === false) { - debugLog(sprintf('%s : %s', __('IP inválida', true), $track_ip)); + debugLog(sprintf('%s : %s', __('IP inválida'), $track_ip)); - throw new InvalidArgumentException(SPException::ERROR, __('IP inválida'), $track_ip); + throw new InvalidArgumentException(__u('IP inválida'), InvalidArgumentException::ERROR, $track_ip); } } diff --git a/lib/SP/Repositories/Track/TrackRepository.php b/lib/SP/Repositories/Track/TrackRepository.php new file mode 100644 index 00000000..b60fd5d0 --- /dev/null +++ b/lib/SP/Repositories/Track/TrackRepository.php @@ -0,0 +1,164 @@ +setQuery($query); + $queryData->addParam($trackRequest->userId); + $queryData->addParam($trackRequest->source); + $queryData->addParam($trackRequest->getIpv4()); + $queryData->addParam($trackRequest->getIpv6()); + $queryData->setOnErrorMessage(__u('Error al crear track')); + + DbWrapper::getQuery($queryData, $this->db); + + return $this->db->getLastId(); + } + + /** + * @param $id int|array + * @return mixed + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\ConstraintException + */ + public function delete($id) + { + $queryData = new QueryData(); + $queryData->setQuery('DELETE FROM Track WHERE id = ? LIMIT 1'); + $queryData->addParam($id); + $queryData->setOnErrorMessage(__u('Error al eliminar track')); + + DbWrapper::getQuery($queryData, $this->db); + + return $this->db->getNumRows(); + } + + /** + * @param TrackData $itemData + * @return bool + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function update(TrackData $itemData) + { + $query = /** @lang SQL */ + 'UPDATE Track SET + track_userId = ?, + source = ?, + time = UNIX_TIMESTAMP(), + ipv4 = ?, + ipv6 = ? + WHERE id = ? LIMIT 1'; + + $queryData = new QueryData(); + $queryData->setQuery($query); + $queryData->addParam($itemData->getUserId()); + $queryData->addParam($itemData->getSource()); + $queryData->addParam($itemData->getTrackIpv4Bin()); + $queryData->addParam($itemData->getTrackIpv6Bin()); + $queryData->addParam($itemData->getId()); + $queryData->setOnErrorMessage(__u('Error al actualizar track')); + + return DbWrapper::getQuery($queryData, $this->db); + } + + /** + * @param $id int + * @return TrackData + */ + public function getById($id) + { + $query = /** @lang SQL */ + 'SELECT id, + userId, + source, + time, + ipv4, + ipv6 + FROM Track + WHERE id = ? LIMIT 1'; + + $queryData = new QueryData(); + $queryData->setQuery($query); + $queryData->addParam($id); + $queryData->setMapClassName(TrackData::class); + $queryData->setOnErrorMessage(__u('Error al obtener track')); + + return DbWrapper::getResults($queryData, $this->db); + } + + /** + * @return TrackData[] + */ + public function getAll() + { + $query = /** @lang SQL */ + 'SELECT id, + userId, + source, + time, + ipv4, + ipv6 FROM Track'; + + $queryData = new QueryData(); + $queryData->setQuery($query); + $queryData->setMapClassName(TrackData::class); + $queryData->setOnErrorMessage(__u('Error al obtener tracks')); + + return DbWrapper::getResultsArray($queryData); + } + + /** + * Devuelve los tracks de un cliente desde un tiempo y origen determinados + * + * @param TrackRequest $trackRequest + * @return array + */ + public function getTracksForClientFromTime(TrackRequest $trackRequest) + { + $query = /** @lang SQL */ + 'SELECT id, userId + FROM Track + WHERE `time` >= ? + AND (ipv4 = ? OR ipv6 = ?) + AND `source` = ?'; + + $queryData = new QueryData(); + $queryData->setQuery($query); + $queryData->addParam($trackRequest->time); + $queryData->addParam($trackRequest->getIpv4()); + $queryData->addParam($trackRequest->getIpv6()); + $queryData->addParam($trackRequest->source); + $queryData->setMapClassName(TrackData::class); + $queryData->setOnErrorMessage(__u('Error al obtener tracks')); + + return DbWrapper::getResultsArray($queryData, $this->db); + } +} \ No newline at end of file diff --git a/lib/SP/Repositories/Track/TrackRequest.php b/lib/SP/Repositories/Track/TrackRequest.php new file mode 100644 index 00000000..56fa0c4b --- /dev/null +++ b/lib/SP/Repositories/Track/TrackRequest.php @@ -0,0 +1,53 @@ +ipv4 = $ip; + } elseif (strlen($ip) > 4) { + $this->ipv6 = $ip; + } elseif ($ip === false) { + debugLog(sprintf('%s : %s', __('IP inválida'), $address)); + + throw new InvalidArgumentException(__u('IP inválida'), InvalidArgumentException::ERROR, $address); + } + } + + /** + * @return string + */ + public function getIpv6() + { + return $this->ipv6; + } + + /** + * @return string + */ + public function getIpv4() + { + return $this->ipv4; + } +} \ No newline at end of file diff --git a/lib/SP/Services/Auth/LoginResponse.php b/lib/SP/Services/Auth/LoginResponse.php new file mode 100644 index 00000000..c37c9c5c --- /dev/null +++ b/lib/SP/Services/Auth/LoginResponse.php @@ -0,0 +1,47 @@ +status = $status; + $this->redirect = $redirect; + } + + /** + * @return int + */ + public function getStatus() + { + return $this->status; + } + + /** + * @return string + */ + public function getRedirect() + { + return $this->redirect; + } +} \ No newline at end of file diff --git a/lib/SP/Services/Auth/LoginService.php b/lib/SP/Services/Auth/LoginService.php index 3f9bb0af..1b731a3b 100644 --- a/lib/SP/Services/Auth/LoginService.php +++ b/lib/SP/Services/Auth/LoginService.php @@ -27,34 +27,31 @@ namespace SP\Services\Auth; defined('APP_ROOT') || die(); use Defuse\Crypto\Exception\CryptoException; -use SP\Bootstrap; use SP\Config\ConfigData; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; use SP\Core\Exceptions\SPException; use SP\Core\Language; use SP\Core\UI\Theme; -use SP\DataModel\TrackData; use SP\DataModel\UserLoginData; use SP\DataModel\UserPreferencesData; -use SP\Http\JsonResponse; use SP\Http\Request; -use SP\Mgmt\Tracks\Track; use SP\Providers\Auth\Auth; use SP\Providers\Auth\AuthResult; use SP\Providers\Auth\AuthUtil; use SP\Providers\Auth\Browser\BrowserAuthData; use SP\Providers\Auth\Database\DatabaseAuthData; use SP\Providers\Auth\Ldap\LdapAuthData; +use SP\Repositories\Track\TrackRequest; use SP\Services\Crypt\TemporaryMasterPassService; use SP\Services\Service; +use SP\Services\Track\TrackService; use SP\Services\User\UserLoginRequest; use SP\Services\User\UserPassService; use SP\Services\User\UserService; use SP\Services\UserPassRecover\UserPassRecoverService; use SP\Services\UserProfile\UserProfileService; use SP\Util\HttpUtil; -use SP\Util\Json; use SP\Util\Util; /** @@ -72,17 +69,10 @@ class LoginService extends Service const STATUS_USER_DISABLED = 3; const STATUS_NEED_OLD_PASS = 5; const STATUS_MAX_ATTEMPTS_EXCEEDED = 6; + const STATUS_PASS_RESET = 7; + const STATUS_PASS = 0; + const STATUS_NONE = 100; - /** - * Tiempo para contador de intentos - */ - const TIME_TRACKING = 600; - const TIME_TRACKING_MAX_ATTEMPTS = 5; - - /** - * @var JsonResponse - */ - protected $jsonResponse; /** * @var UserLoginData */ @@ -103,10 +93,19 @@ class LoginService extends Service * @var Language */ protected $language; + /** + * @var TrackService + */ + protected $trackService; + /** + * @var TrackRequest + */ + protected $trackRequest; /** * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface + * @throws \SP\Core\Exceptions\InvalidArgumentException */ public function initialize() { @@ -114,132 +113,125 @@ class LoginService extends Service $this->theme = $this->dic->get(Theme::class); $this->userService = $this->dic->get(UserService::class); $this->language = $this->dic->get(Language::class); + $this->trackService = $this->dic->get(TrackService::class); - $this->jsonResponse = new JsonResponse(); $this->userLoginData = new UserLoginData(); + $this->trackRequest = TrackService::getTrackRequest('login'); } /** * Ejecutar las acciones de login * - * @return JsonResponse + * @return LoginResponse + * @throws AuthException + * @throws SPException * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException */ public function doLogin() { $this->userLoginData->setLoginUser(Request::analyze('user')); $this->userLoginData->setLoginPass(Request::analyzeEncrypted('pass')); - try { - // FIXME: add service -// $this->checkTracking(); + $this->trackRequest->userId = $this->userLoginData->getLoginUser(); - $auth = new Auth($this->userLoginData, $this->configData); + $this->checkTracking(); - if (($result = $auth->doAuth()) !== false) { - // Ejecutar la acción asociada al tipo de autentificación + $auth = new Auth($this->userLoginData, $this->configData); + if (($result = $auth->doAuth()) !== false) { + // Ejecutar la acción asociada al tipo de autentificación + foreach ($result as $authResult) { /** @var AuthResult $authResult */ - foreach ($result as $authResult) { - if ($authResult->isAuthGranted() === true - && $this->{$authResult->getAuth()}($authResult->getData()) === true) { - break; - } + if ($authResult->isAuthGranted() === true + && $this->{$authResult->getAuth()}($authResult->getData()) === true) { + break; } - } else { - $this->addTracking(); - - throw new AuthException(__u('Login incorrecto'), AuthException::INFO, null, self::STATUS_INVALID_LOGIN); } + } else { + $this->addTracking(); - $this->checkUser(); - $this->loadMasterPass(); - $this->setUserSession(); - $this->loadUserPreferences(); - $this->cleanUserData(); - } catch (SPException $e) { - processException($e); - - $this->eventDispatcher->notifyEvent('exception', new Event($e)); - - $this->jsonResponse->setDescription($e->getMessage()); - $this->jsonResponse->setStatus($e->getCode()); - - Json::returnJson($this->jsonResponse); - } - - $forward = Request::getRequestHeaders('X-Forwarded-For'); - - if ($forward) { - $this->eventDispatcher->notifyEvent('login.info', - new Event($this, EventMessage::factory() - ->addDetail('X-Forwarded-For', $this->configData->isDemoEnabled() ? '***' : $forward)) + throw new AuthException( + __u('Login incorrecto'), + AuthException::INFO, + __FUNCTION__, + self::STATUS_INVALID_LOGIN ); } -// $data = ['url' => 'index.php' . Request::importUrlParamsToGet()]; - $data = ['url' => 'index.php?r=index']; - $this->jsonResponse->setStatus(JsonResponse::JSON_SUCCESS); - $this->jsonResponse->setData($data); + if (($loginResponse = $this->checkUser())->getStatus() !== self::STATUS_NONE) { + return $loginResponse; + } - return $this->jsonResponse; + $this->loadMasterPass(); + $this->setUserSession(); + $this->loadUserPreferences(); + $this->cleanUserData(); + + return new LoginResponse(self::STATUS_PASS, 'index.php?r=index'); } /** * Comprobar los intentos de login * - * @throws \SP\Services\Auth\AuthException + * @throws AuthException + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface */ private function checkTracking() { try { - $TrackData = new TrackData(); - $TrackData->setSource('Login'); - $TrackData->setTrackIp(HttpUtil::getClientAddress()); - - $attempts = count(Track::getItem($TrackData)->getTracksForClientFromTime(time() - self::TIME_TRACKING)); - } catch (SPException $e) { + $attempts = count($this->trackService->getTracksForClientFromTime($this->trackRequest)); + } catch (\Exception $e) { processException($e); throw new AuthException(__u('Error interno'), AuthException::ERROR, null, Service::STATUS_INTERNAL_ERROR); } - if ($attempts >= self::TIME_TRACKING_MAX_ATTEMPTS) { + if ($attempts >= TrackService::TIME_TRACKING_MAX_ATTEMPTS) { $this->addTracking(); $this->eventDispatcher->notifyEvent('login.track.delay', new Event($this, EventMessage::factory() - ->addDescription(sprintf(__('Intentos excedidos (%d/%d)'), $attempts, self::TIME_TRACKING_MAX_ATTEMPTS)) + ->addDescription(sprintf(__('Intentos excedidos (%d/%d)'), $attempts, TrackService::TIME_TRACKING_MAX_ATTEMPTS)) ->addDetail(__u('Segundos'), 0.3 * $attempts)) ); - sleep(0.3 * $attempts); + sleep(TrackService::TIME_SLEEP * $attempts); - throw new AuthException(__u('Intentos excedidos'), AuthException::INFO, null, self::STATUS_MAX_ATTEMPTS_EXCEEDED); + throw new AuthException( + __u('Intentos excedidos'), + AuthException::INFO, + null, + self::STATUS_MAX_ATTEMPTS_EXCEEDED + ); } } /** * Añadir un seguimiento * - * @throws \SP\Services\Auth\AuthException + * @throws AuthException */ private function addTracking() { try { - $TrackData = new TrackData(); - $TrackData->setSource('Login'); - $TrackData->setTrackIp(HttpUtil::getClientAddress()); - - Track::getItem($TrackData)->add(); + $this->trackService->add($this->trackRequest); $this->eventDispatcher->notifyEvent('login.track.add', - new Event($this, EventMessage::factory()->addDescription(HttpUtil::getClientAddress(true))) + new Event($this, EventMessage::factory() + ->addDescription(HttpUtil::getClientAddress(true))) + ); + } catch (\Exception $e) { + throw new AuthException( + __u('Error interno'), + AuthException::ERROR, + null, + Service::STATUS_INTERNAL_ERROR ); - } catch (SPException $e) { - throw new AuthException(__u('Error interno'), AuthException::ERROR, null, Service::STATUS_INTERNAL_ERROR); } } @@ -252,6 +244,7 @@ class LoginService extends Service * @throws \Psr\Container\NotFoundExceptionInterface * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException + * @return LoginResponse */ protected function checkUser() { @@ -268,7 +261,12 @@ class LoginService extends Service $this->addTracking(); - throw new AuthException(__u('Usuario deshabilitado'), AuthException::INFO, null, self::STATUS_USER_DISABLED); + throw new AuthException( + __u('Usuario deshabilitado'), + AuthException::INFO, + null, + self::STATUS_USER_DISABLED + ); } // Comprobar si se ha forzado un cambio de clave @@ -283,11 +281,10 @@ class LoginService extends Service $this->dic->get(UserPassRecoverService::class)->add($userLoginResponse->getId(), $hash); - $this->jsonResponse->setData(['url' => Bootstrap::$WEBURI . '/index.php?u=userPassReset/change/' . $hash]); - $this->jsonResponse->setStatus(0); - - Json::returnJson($this->jsonResponse); + return new LoginResponse(self::STATUS_PASS_RESET, 'index.php?r=userPassReset/change/' . $hash); } + + return new LoginResponse(self::STATUS_NONE); } /** @@ -323,7 +320,12 @@ class LoginService extends Service $this->addTracking(); - throw new AuthException(__u('Clave maestra incorrecta'), AuthException::INFO, null, self::STATUS_INVALID_MASTER_PASS); + throw new AuthException( + __u('Clave maestra incorrecta'), + AuthException::INFO, + null, + self::STATUS_INVALID_MASTER_PASS + ); } $this->eventDispatcher->notifyEvent('login.masterPass', @@ -337,7 +339,12 @@ class LoginService extends Service $this->addTracking(); - throw new AuthException(__u('Clave maestra incorrecta'), AuthException::INFO, null, self::STATUS_INVALID_MASTER_PASS); + throw new AuthException( + __u('Clave maestra incorrecta'), + AuthException::INFO, + null, + self::STATUS_INVALID_MASTER_PASS + ); } $this->eventDispatcher->notifyEvent('login.masterPass', @@ -346,21 +353,37 @@ class LoginService extends Service } else { switch ($userPassService->loadUserMPass($this->userLoginData)->getStatus()) { case UserPassService::MPASS_CHECKOLD: - throw new AuthException(__u('Es necesaria su clave anterior'), AuthException::INFO, null, self::STATUS_NEED_OLD_PASS); + throw new AuthException( + __u('Es necesaria su clave anterior'), + AuthException::INFO, + null, + self::STATUS_NEED_OLD_PASS + ); break; case UserPassService::MPASS_NOTSET: case UserPassService::MPASS_CHANGED: case UserPassService::MPASS_WRONG: $this->addTracking(); - throw new AuthException(__u('La clave maestra no ha sido guardada o es incorrecta'), AuthException::INFO, null, self::STATUS_INVALID_MASTER_PASS); + throw new AuthException( + __u('La clave maestra no ha sido guardada o es incorrecta'), + AuthException::INFO, + null, + self::STATUS_INVALID_MASTER_PASS + ); break; } } } catch (CryptoException $e) { $this->eventDispatcher->notifyEvent('exception', new Event($e)); - throw new AuthException(__u('Error interno'), AuthException::ERROR, $e->getMessage(), Service::STATUS_INTERNAL_ERROR); + throw new AuthException( + __u('Error interno'), + AuthException::ERROR, + $e->getMessage(), + Service::STATUS_INTERNAL_ERROR, + $e + ); } } @@ -437,7 +460,12 @@ class LoginService extends Service $this->eventDispatcher->notifyEvent('login.auth.ldap', new Event($this, $eventMessage)); - throw new AuthException(__u('Login incorrecto'), AuthException::INFO, null, self::STATUS_INVALID_LOGIN); + throw new AuthException( + __u('Login incorrecto'), + AuthException::INFO, + __FUNCTION__, + self::STATUS_INVALID_LOGIN + ); } if ($authData->getStatusCode() === 701) { @@ -445,7 +473,12 @@ class LoginService extends Service $this->eventDispatcher->notifyEvent('login.auth.ldap', new Event($this, $eventMessage)); - throw new AuthException(__u('Cuenta expirada'), AuthException::INFO, null, self::STATUS_USER_DISABLED); + throw new AuthException( + __u('Cuenta expirada'), + AuthException::INFO, + __FUNCTION__, + self::STATUS_USER_DISABLED + ); } if ($authData->getStatusCode() === 702) { @@ -453,7 +486,12 @@ class LoginService extends Service $this->eventDispatcher->notifyEvent('login.auth.ldap', new Event($this, $eventMessage)); - throw new AuthException(__u('El usuario no tiene grupos asociados'), AuthException::INFO, null, self::STATUS_USER_DISABLED); + throw new AuthException( + __u('El usuario no tiene grupos asociados'), + AuthException::INFO, + __FUNCTION__, + self::STATUS_USER_DISABLED + ); } if ($authData->isAuthGranted() === false) { @@ -464,7 +502,12 @@ class LoginService extends Service $this->eventDispatcher->notifyEvent('login.auth.ldap', new Event($this, $eventMessage)); - throw new AuthException(__u('Error interno'), AuthException::INFO, null, Service::STATUS_INTERNAL_ERROR); + throw new AuthException( + __u('Error interno'), + AuthException::INFO, + __FUNCTION__, + Service::STATUS_INTERNAL_ERROR + ); } $this->eventDispatcher->notifyEvent('login.auth.ldap', @@ -492,7 +535,13 @@ class LoginService extends Service $this->userService->createOnLogin($userLoginRequest); } } catch (\Exception $e) { - throw new AuthException(__u('Error interno'), AuthException::ERROR, null, Service::STATUS_INTERNAL_ERROR, $e); + throw new AuthException( + __u('Error interno'), + AuthException::ERROR, + __FUNCTION__, + Service::STATUS_INTERNAL_ERROR, + $e + ); } return true; @@ -524,7 +573,12 @@ class LoginService extends Service $this->eventDispatcher->notifyEvent('login.auth.database', new Event($this, $eventMessage)); - throw new AuthException(__u('Login incorrecto'), AuthException::INFO, null, self::STATUS_INVALID_LOGIN); + throw new AuthException( + __u('Login incorrecto'), + AuthException::INFO, + __FUNCTION__, + self::STATUS_INVALID_LOGIN + ); } if ($authData->getAuthenticated() === 1) { @@ -560,7 +614,12 @@ class LoginService extends Service $this->eventDispatcher->notifyEvent('login.auth.browser', new Event($this, $eventMessage)); - throw new AuthException(__u('Login incorrecto'), AuthException::INFO, null, self::STATUS_INVALID_LOGIN); + throw new AuthException( + __u('Login incorrecto'), + AuthException::INFO, + __FUNCTION__, + self::STATUS_INVALID_LOGIN + ); } if ($authData->getAuthenticated() === 1 && $this->configData->isAuthBasicAutoLoginEnabled()) { @@ -579,7 +638,13 @@ class LoginService extends Service return true; } catch (\Exception $e) { - throw new AuthException(__u('Error interno'), AuthException::ERROR, null, Service::STATUS_INTERNAL_ERROR, $e); + throw new AuthException( + __u('Error interno'), + AuthException::ERROR, + __FUNCTION__, + Service::STATUS_INTERNAL_ERROR, + $e + ); } } diff --git a/lib/SP/Services/Track/TrackService.php b/lib/SP/Services/Track/TrackService.php new file mode 100644 index 00000000..a48c3f06 --- /dev/null +++ b/lib/SP/Services/Track/TrackService.php @@ -0,0 +1,113 @@ +trackRepository->add($trackRequest); + } + + /** + * @param $id int|array + * @return mixed + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\ConstraintException + */ + public function delete($id) + { + return $this->trackRepository->delete($id); + } + + /** + * @param TrackData $itemData + * @return bool + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function update(TrackData $itemData) + { + return $this->trackRepository->update($itemData); + } + + /** + * @param $id int + * @return TrackData + */ + public function getById($id) + { + return $this->trackRepository->getById($id); + } + + /** + * @return TrackData[] + */ + public function getAll() + { + return $this->trackRepository->getAll(); + } + + /** + * Devuelve los tracks de un cliente desde un tiempo y origen determinados + * + * @param TrackRequest $trackRequest + * @return array + */ + public function getTracksForClientFromTime(TrackRequest $trackRequest) + { + return $this->trackRepository->getTracksForClientFromTime($trackRequest); + } + + /** + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface + */ + public function initialize() + { + $this->trackRepository = $this->dic->get(TrackRepository::class); + } + + /** + * @param $source + * @return TrackRequest + * @throws \SP\Core\Exceptions\InvalidArgumentException + */ + public static function getTrackRequest($source) + { + $trackRequest = new TrackRequest(); + $trackRequest->time = time() - self::TIME_TRACKING; + $trackRequest->setTrackIp(HttpUtil::getClientAddress()); + $trackRequest->source = $source; + + return $trackRequest; + } +} \ No newline at end of file diff --git a/public/js/app-actions.js b/public/js/app-actions.js index e607cc33..f6553150 100644 --- a/public/js/app-actions.js +++ b/public/js/app-actions.js @@ -1559,7 +1559,7 @@ sysPass.Actions = function (Common) { const grid = { search: function ($obj) { - log.info("appMgmt:search"); + log.info("grid:search"); const $target = $($obj.data("target")); const opts = Common.appRequests().getRequestOpts(); @@ -1589,7 +1589,7 @@ sysPass.Actions = function (Common) { if (typeof callback === "function") { callback($form); } else { - grid.search($obj); + grid.search($form); } }, delete: function ($obj, onAccept) { diff --git a/public/js/app-actions.min.js b/public/js/app-actions.min.js index e2373264..abd0851d 100644 --- a/public/js/app-actions.min.js +++ b/public/js/app-actions.min.js @@ -1,5 +1,5 @@ var $jscomp={scope:{},findInternal:function(c,e,l){c instanceof String&&(c=String(c));for(var f=c.length,g=0;g";mdlDialog().show({text:b,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43],onClick:function(b){b=c.appRequests().getRequestOpts();b.url=f.appMgmt.save;b.data={actionId:a.data("action-id"),sk:c.sk.get(),isAjax:1,ldap_loginattribute:$("#ldap_loginattribute").val(),ldap_nameattribute:$("#ldap_nameattribute").val(),ldap_ads:$("#ldap_ads").prop("checked")}; -c.appRequests().getActionCall(b,function(a){c.msg.out(a)})}}})}},m={search:function(a){e.info("appMgmt:search");var b=$(a.data("target")),d=c.appRequests().getRequestOpts();d.url=f.entrypoint+"?r="+a.data("action-route");d.method="get";d.data=a.serialize();c.appRequests().getActionCall(d,function(a){0===a.status?b.html(a.data.html):b.html(c.msg.html.error(a.description));c.sk.set(a.csrf)})},nav:function(a,b){e.info("grid:nav");var d=$("#"+a.data("action-form"));d.find("[name='start']").val(a.data("start")); -d.find("[name='count']").val(a.data("count"));d.find("[name='sk']").val(c.sk.get());"function"===typeof b?b(d):m.search(a)},"delete":function(a,b){var d='

'+c.config().LANG[12]+"

",e=a.data("selection"),f=[];if(e&&($(e).find(".is-selected").each(function(){f.push($(this).data("item-id"))}),0===f.length))return;mdlDialog().show({text:d,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43], +c.appRequests().getActionCall(b,function(a){c.msg.out(a)})}}})}},m={search:function(a){e.info("grid:search");var b=$(a.data("target")),d=c.appRequests().getRequestOpts();d.url=f.entrypoint+"?r="+a.data("action-route");d.method="get";d.data=a.serialize();c.appRequests().getActionCall(d,function(a){0===a.status?b.html(a.data.html):b.html(c.msg.html.error(a.description));c.sk.set(a.csrf)})},nav:function(a,b){e.info("grid:nav");var d=$("#"+a.data("action-form"));d.find("[name='start']").val(a.data("start")); +d.find("[name='count']").val(a.data("count"));d.find("[name='sk']").val(c.sk.get());"function"===typeof b?b(d):m.search(d)},"delete":function(a,b){var d='

'+c.config().LANG[12]+"

",e=a.data("selection"),f=[];if(e&&($(e).find(".is-selected").each(function(){f.push($(this).data("item-id"))}),0===f.length))return;mdlDialog().show({text:d,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43], onClick:function(a){a.preventDefault();"function"===typeof b&&b(f)}}})}};return{doAction:function(a,b){var d={r:a.r+(void 0!==a.itemId?"/"+a.itemId:""),isAjax:1},e=c.appRequests().getRequestOpts();e.url=f.doAction;e.method="get";e.type="html";e.addHistory=!0;e.data=d;c.appRequests().getActionCall(e,function(a){var d=$("#content");d.empty().html(a);a=c.triggers().views;a.common(d);if(void 0!==b&&"function"===typeof a[b])a[b]();d=$(".mdl-layout__content");0";mdlDialog().show({text:b,negative:{title:c.config().LANG[44],onClick:function(a){a.preventDefault();c.msg.error(c.config().LANG[44])}},positive:{title:c.config().LANG[43],onClick:function(b){b=c.appRequests().getRequestOpts();b.url=f.entrypoint;b.method="get";b.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:c.sk.get()};c.appRequests().getActionCall(b,function(a){c.msg.out(a);0===a.status&&p.listFiles($("#list-account-files"))})}}})}}, diff --git a/public/js/app-main.min.js b/public/js/app-main.min.js index 6e7442a6..ec47692a 100644 --- a/public/js/app-main.min.js +++ b/public/js/app-main.min.js @@ -1,5 +1,5 @@ var $jscomp={scope:{},findInternal:function(b,l,h){b instanceof String&&(b=String(b));for(var m=b.length,n=0;n