mirror of
https://github.com/nuxsmin/sysPass.git
synced 2026-03-03 07:04:07 +01:00
* [ADD] Improved tracking handling.
* [MOD] Improved login process workflow.
This commit is contained in:
1
INSTALL
1
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
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()]);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
164
lib/SP/Repositories/Track/TrackRepository.php
Normal file
164
lib/SP/Repositories/Track/TrackRepository.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace SP\Repositories\Track;
|
||||
|
||||
use SP\DataModel\TrackData;
|
||||
use SP\Repositories\Repository;
|
||||
use SP\Storage\DbWrapper;
|
||||
use SP\Storage\QueryData;
|
||||
|
||||
/**
|
||||
* Class TrackRepository
|
||||
* @package SP\Repositories\Track
|
||||
*/
|
||||
class TrackRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* @param TrackRequest $trackRequest
|
||||
* @return mixed
|
||||
* @throws \SP\Core\Exceptions\ConstraintException
|
||||
* @throws \SP\Core\Exceptions\QueryException
|
||||
*/
|
||||
public function add(TrackRequest $trackRequest)
|
||||
{
|
||||
$query = /** @lang SQL */
|
||||
'INSERT INTO Track SET
|
||||
userId = ?,
|
||||
source = ?,
|
||||
time = UNIX_TIMESTAMP(),
|
||||
ipv4 = ?,
|
||||
ipv6 = ?';
|
||||
|
||||
$queryData = new QueryData();
|
||||
$queryData->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);
|
||||
}
|
||||
}
|
||||
53
lib/SP/Repositories/Track/TrackRequest.php
Normal file
53
lib/SP/Repositories/Track/TrackRequest.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace SP\Repositories\Track;
|
||||
|
||||
use SP\Core\Exceptions\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Class TrackRequest
|
||||
* @package SP\Repositories\Track
|
||||
*/
|
||||
class TrackRequest
|
||||
{
|
||||
public $time;
|
||||
public $source;
|
||||
public $userId;
|
||||
protected $ipv6;
|
||||
protected $ipv4;
|
||||
|
||||
/**
|
||||
* @param string $address
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function setTrackIp($address)
|
||||
{
|
||||
$ip = @inet_pton($address);
|
||||
|
||||
if (strlen($ip) === 4) {
|
||||
$this->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;
|
||||
}
|
||||
}
|
||||
47
lib/SP/Services/Auth/LoginResponse.php
Normal file
47
lib/SP/Services/Auth/LoginResponse.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace SP\Services\Auth;
|
||||
|
||||
/**
|
||||
* Class LoginResponse
|
||||
*
|
||||
* @package SP\Services\Auth
|
||||
*/
|
||||
class LoginResponse
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $status;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $redirect;
|
||||
|
||||
/**
|
||||
* LoginResponse constructor.
|
||||
* @param int $status
|
||||
* @param string $redirect
|
||||
*/
|
||||
public function __construct($status, $redirect = null)
|
||||
{
|
||||
$this->status = $status;
|
||||
$this->redirect = $redirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getStatus()
|
||||
{
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRedirect()
|
||||
{
|
||||
return $this->redirect;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
113
lib/SP/Services/Track/TrackService.php
Normal file
113
lib/SP/Services/Track/TrackService.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace SP\Services\Track;
|
||||
|
||||
use SP\DataModel\TrackData;
|
||||
use SP\Repositories\Track\TrackRepository;
|
||||
use SP\Repositories\Track\TrackRequest;
|
||||
use SP\Services\Service;
|
||||
use SP\Util\HttpUtil;
|
||||
|
||||
/**
|
||||
* Class TrackService
|
||||
* @package SP\Services
|
||||
*/
|
||||
class TrackService extends Service
|
||||
{
|
||||
/**
|
||||
* Tiempo para contador de intentos
|
||||
*/
|
||||
const TIME_TRACKING = 600;
|
||||
const TIME_TRACKING_MAX_ATTEMPTS = 5;
|
||||
const TIME_SLEEP = 0.3;
|
||||
|
||||
/**
|
||||
* @var TrackRepository
|
||||
*/
|
||||
protected $trackRepository;
|
||||
|
||||
/**
|
||||
* @param TrackRequest $trackRequest
|
||||
* @return mixed
|
||||
* @throws \SP\Core\Exceptions\ConstraintException
|
||||
* @throws \SP\Core\Exceptions\QueryException
|
||||
*/
|
||||
public function add(TrackRequest $trackRequest)
|
||||
{
|
||||
return $this->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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
6
public/js/app-actions.min.js
vendored
6
public/js/app-actions.min.js
vendored
@@ -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<f;g++){var n=c[g];if(e.call(l,n,g,c))return{i:g,v:n}}return{i:-1,v:void 0}}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(c,e,l){if(l.get||l.set)throw new TypeError("ES3 does not support getters and setters.");c!=Array.prototype&&c!=Object.prototype&&(c[e]=l.value)};
|
||||
$jscomp.getGlobal=function(c){return"undefined"!=typeof window&&window===c?c:"undefined"!=typeof global?global:c};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(c,e,l,f){if(e){l=$jscomp.global;c=c.split(".");for(f=0;f<c.length-1;f++){var g=c[f];g in l||(l[g]={});l=l[g]}c=c[c.length-1];f=l[c];e=e(f);e!=f&&null!=e&&$jscomp.defineProperty(l,c,{configurable:!0,writable:!0,value:e})}};
|
||||
$jscomp.getGlobal=function(c){return"undefined"!=typeof window&&window===c?c:"undefined"!=typeof global&&null!=global?global:c};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(c,e,l,f){if(e){l=$jscomp.global;c=c.split(".");for(f=0;f<c.length-1;f++){var g=c[f];g in l||(l[g]={});l=l[g]}c=c[c.length-1];f=l[c];e=e(f);e!=f&&null!=e&&$jscomp.defineProperty(l,c,{configurable:!0,writable:!0,value:e})}};
|
||||
$jscomp.polyfill("Array.prototype.find",function(c){return c?c:function(c,l){return $jscomp.findInternal(this,c,l).v}},"es6-impl","es3");
|
||||
sysPass.Actions=function(c){var e=c.log,l=0,f={entrypoint:"/index.php",doAction:"/index.php",updateItems:"/index.php",user:{savePreferences:"/ajax/ajax_userPrefsSave.php",password:"/ajax/ajax_usrpass.php",passreset:"/ajax/ajax_passReset.php"},main:{login:"/index.php?r=login/login",install:"/ajax/ajax_install.php",upgrade:"/ajax/ajax_upgrade.php",getUpdates:"/index.php?r=index/checkUpdates",task:"/ajax/ajax_task.php"},checks:"/ajax/ajax_checkConnection.php",config:{save:"/ajax/ajax_configSave.php",
|
||||
"export":"/ajax/ajax_configSave.php","import":"/ajax/ajax_configSave.php"},file:"/ajax/ajax_filesMgmt.php",link:"/index.php",plugin:"/ajax/ajax_itemSave.php",account:{save:"/index.php",saveFavorite:"/ajax/ajax_itemSave.php",request:"/ajax/ajax_itemSave.php",getFiles:"/index.php",search:"/index.php?r=account/search"},appMgmt:{show:"/index.php",save:"/index.php",search:"/index.php"},eventlog:"/ajax/ajax_eventlog.php",wiki:{show:"/ajax/ajax_wiki.php"},notice:{show:"/ajax/ajax_noticeShow.php",search:"/ajax/ajax_noticeSearch.php"}};
|
||||
@@ -24,8 +24,8 @@ h={state:{tab:{index:0,refresh:!0,route:""},itemId:0,update:function(a){var c=$(
|
||||
c.appRequests().getActionCall(b,function(b){if(0!==b.status)c.msg.out(b);else{var d=a.data("item-dst");n(b.data.html,{open:function(){d&&(h.state.tab.refresh=!1)},close:function(){d&&r.update(a)}})}})},"delete":function(a){e.info("appMgmt:delete");h.state.update(a);m["delete"](a,function(b){var d=a.data("item-id"),e=c.appRequests().getRequestOpts();e.url=f.entrypoint;e.method="get";e.data={r:a.data("action-route")+(d?"/"+d:""),items:b,sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(e,function(a){c.msg.out(a);
|
||||
g({r:h.state.tab.route,tabIndex:h.state.tab.index})})})},save:function(a){e.info("appMgmt:save");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint+"?r="+a.data("route");b.data=a.serialize();c.appRequests().getActionCall(b,function(a){c.msg.out(a);0===a.status&&(!0===h.state.tab.refresh&&g({r:h.state.tab.route,tabIndex:h.state.tab.index}),$.magnificPopup.close())})},search:function(a){e.info("appMgmt:search");m.search(a)},nav:function(a){e.info("appMgmt:nav");m.nav(a)},ldapSync:function(a){e.info("appMgmt:ldapSync");
|
||||
var b='<div id="alert"><p id="alert-text">'+c.config().LANG[57]+"</p></div>";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='<div id="alert"><p id="alert-text">'+c.config().LANG[12]+"</p></div>",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='<div id="alert"><p id="alert-text">'+c.config().LANG[12]+"</p></div>",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<d.scrollTop()&&d.animate({scrollTop:0},1E3)})},
|
||||
appMgmt:u,account:p,file:{view:function(a){e.info("file:view");var 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(b){if(1===b.status)return c.msg.out(b);v(a,b.data.html)})},download:function(a){e.info("file:download");a={r:a.data("action-route")+"/"+a.data("item-id"),sk:c.sk.get()};$.fileDownload(f.entrypoint,{httpMethod:"GET",data:a})},"delete":function(a){e.info("file:delete");
|
||||
var b='<div id="alert"><p id="alert-text">'+c.config().LANG[15]+"</p></div>";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"))})}}})}},
|
||||
|
||||
2
public/js/app-main.min.js
vendored
2
public/js/app-main.min.js
vendored
@@ -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<m;n++){var w=b[n];if(l.call(h,w,n,b))return{i:n,v:w}}return{i:-1,v:void 0}}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(b,l,h){if(h.get||h.set)throw new TypeError("ES3 does not support getters and setters.");b!=Array.prototype&&b!=Object.prototype&&(b[l]=h.value)};
|
||||
$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(b,l,h,m){if(l){h=$jscomp.global;b=b.split(".");for(m=0;m<b.length-1;m++){var n=b[m];n in h||(h[n]={});h=h[n]}b=b[b.length-1];m=h[b];l=l(m);l!=m&&null!=l&&$jscomp.defineProperty(h,b,{configurable:!0,writable:!0,value:l})}};
|
||||
$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global&&null!=global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(b,l,h,m){if(l){h=$jscomp.global;b=b.split(".");for(m=0;m<b.length-1;m++){var n=b[m];n in h||(h[n]={});h=h[n]}b=b[b.length-1];m=h[b];l=l(m);l!=m&&null!=l&&$jscomp.defineProperty(h,b,{configurable:!0,writable:!0,value:l})}};
|
||||
$jscomp.polyfill("Array.prototype.find",function(b){return b?b:function(b,h){return $jscomp.findInternal(this,b,h).v}},"es6-impl","es3");$jscomp.SYMBOL_PREFIX="jscomp_symbol_";$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(b){return $jscomp.SYMBOL_PREFIX+(b||"")+$jscomp.symbolCounter_++};
|
||||
$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var b=$jscomp.global.Symbol.iterator;b||(b=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[b]&&$jscomp.defineProperty(Array.prototype,b,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(b){var l=0;return $jscomp.iteratorPrototype(function(){return l<b.length?{done:!1,value:b[l++]}:{done:!0}})};
|
||||
$jscomp.iteratorPrototype=function(b){$jscomp.initSymbolIterator();b={next:b};b[$jscomp.global.Symbol.iterator]=function(){return this};return b};$jscomp.array=$jscomp.array||{};$jscomp.iteratorFromArray=function(b,l){$jscomp.initSymbolIterator();b instanceof String&&(b+="");var h=0,m={next:function(){if(h<b.length){var n=h++;return{value:l(n,b[n]),done:!1}}m.next=function(){return{done:!0,value:void 0}};return m.next()}};m[Symbol.iterator]=function(){return m};return m};
|
||||
|
||||
2
public/js/app-triggers.min.js
vendored
2
public/js/app-triggers.min.js
vendored
@@ -1,5 +1,5 @@
|
||||
var $jscomp={scope:{},findInternal:function(b,d,f){b instanceof String&&(b=String(b));for(var a=b.length,c=0;c<a;c++){var e=b[c];if(d.call(f,e,c,b))return{i:c,v:e}}return{i:-1,v:void 0}}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(b,d,f){if(f.get||f.set)throw new TypeError("ES3 does not support getters and setters.");b!=Array.prototype&&b!=Object.prototype&&(b[d]=f.value)};
|
||||
$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(b,d,f,a){if(d){f=$jscomp.global;b=b.split(".");for(a=0;a<b.length-1;a++){var c=b[a];c in f||(f[c]={});f=f[c]}b=b[b.length-1];a=f[b];d=d(a);d!=a&&null!=d&&$jscomp.defineProperty(f,b,{configurable:!0,writable:!0,value:d})}};
|
||||
$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global&&null!=global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(b,d,f,a){if(d){f=$jscomp.global;b=b.split(".");for(a=0;a<b.length-1;a++){var c=b[a];c in f||(f[c]={});f=f[c]}b=b[b.length-1];a=f[b];d=d(a);d!=a&&null!=d&&$jscomp.defineProperty(f,b,{configurable:!0,writable:!0,value:d})}};
|
||||
$jscomp.polyfill("Array.prototype.find",function(b){return b?b:function(b,f){return $jscomp.findInternal(this,b,f).v}},"es6-impl","es3");
|
||||
sysPass.Triggers=function(b){var d=b.log,f=function(a){var c={valueField:"id",labelField:"name",searchField:["name"]};a.find(".select-box").each(function(a){var d=$(this);c.plugins=d.hasClass("select-box-deselect")?{clear_selection:{title:b.config().LANG[51]}}:{};if(d.data("onchange")){var e=d.data("onchange").split("/");c.onChange=function(a){if(0<a)if(2===e.length)sysPassApp.actions()[e[0]][e[1]](d);else sysPassApp.actions()[e[0]](d)}}d.selectize(c)});a.find("#allowed_exts").selectize({create:function(a){return{value:a.toUpperCase(),
|
||||
text:a.toUpperCase()}},createFilter:/^[a-z0-9]{1,4}$/i,plugins:["remove_button"]});a.find("#wikifilter").selectize({create:!0,createFilter:/^[a-z0-9:._-]+$/i,plugins:["remove_button"]})};return{views:{main:function(){d.info("views:main");clipboard.isSupported()||b.msg.info(b.config().LANG[65]);$(".btn-menu").click(function(){var a=$(this);"1"===a.attr("data-history-reset")&&b.appRequests().history.reset();b.appActions().doAction({r:a.data("route")},a.data("view"))});$("#btnLogout").click(function(a){b.appActions().main.logout()});
|
||||
|
||||
Reference in New Issue
Block a user