diff --git a/.gitignore b/.gitignore
index 2aa48837..c735930b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,4 +56,7 @@ app/temp/*
app/modules/web/plugins/*
vendor/*
+.phpstorm.meta.php
+composer.phar
+
!.blank
\ No newline at end of file
diff --git a/app/modules/web/Controllers/AccountController.php b/app/modules/web/Controllers/AccountController.php
index ba191fc4..8481abcb 100644
--- a/app/modules/web/Controllers/AccountController.php
+++ b/app/modules/web/Controllers/AccountController.php
@@ -163,7 +163,7 @@ class AccountController extends ControllerBase implements CrudControllerInterfac
} catch (\Exception $e) {
processException($e);
- ErrorUtil::showExceptionInView($this->view, $e);
+ ErrorUtil::showExceptionInView($this->view, $e, 'account');
}
}
@@ -267,7 +267,7 @@ class AccountController extends ControllerBase implements CrudControllerInterfac
} catch (\Exception $e) {
processException($e);
- ErrorUtil::showExceptionInView($this->view, $e);
+ ErrorUtil::showExceptionInView($this->view, $e, 'account');
}
}
@@ -310,7 +310,7 @@ class AccountController extends ControllerBase implements CrudControllerInterfac
} catch (\Exception $e) {
processException($e);
- ErrorUtil::showExceptionInView($this->view, $e);
+ ErrorUtil::showExceptionInView($this->view, $e, 'account');
}
}
@@ -356,7 +356,7 @@ class AccountController extends ControllerBase implements CrudControllerInterfac
} catch (\Exception $e) {
processException($e);
- ErrorUtil::showExceptionInView($this->view, $e);
+ ErrorUtil::showExceptionInView($this->view, $e, 'account');
}
}
@@ -398,7 +398,7 @@ class AccountController extends ControllerBase implements CrudControllerInterfac
} catch (\Exception $e) {
processException($e);
- ErrorUtil::showExceptionInView($this->view, $e);
+ ErrorUtil::showExceptionInView($this->view, $e, 'account');
}
}
@@ -442,7 +442,7 @@ class AccountController extends ControllerBase implements CrudControllerInterfac
} catch (\Exception $e) {
processException($e);
- ErrorUtil::showExceptionInView($this->view, $e);
+ ErrorUtil::showExceptionInView($this->view, $e, 'account-editpass');
}
}
@@ -484,7 +484,7 @@ class AccountController extends ControllerBase implements CrudControllerInterfac
} catch (\Exception $e) {
processException($e);
- ErrorUtil::showExceptionInView($this->view, $e);
+ ErrorUtil::showExceptionInView($this->view, $e, 'account-history');
}
}
@@ -515,7 +515,7 @@ class AccountController extends ControllerBase implements CrudControllerInterfac
} catch (\Exception $e) {
processException($e);
- ErrorUtil::showExceptionInView($this->view, $e);
+ ErrorUtil::showExceptionInView($this->view, $e, 'account-request');
}
}
diff --git a/app/modules/web/Controllers/ConfigEncryptionController.php b/app/modules/web/Controllers/ConfigEncryptionController.php
index ef0c36e3..2075bac0 100644
--- a/app/modules/web/Controllers/ConfigEncryptionController.php
+++ b/app/modules/web/Controllers/ConfigEncryptionController.php
@@ -68,6 +68,7 @@ class ConfigEncryptionController extends SimpleControllerBase
$newMasterPassR = Request::analyzeEncrypted('newMasterPwdR');
$confirmPassChange = Request::analyzeBool('confirmPassChange', false);
$noAccountPassChange = Request::analyzeBool('chkNoAccountChange', false);
+ $taskId = Request::analyzeString('taskId');
if (!$mastePassService->checkUserUpdateMPass($this->session->getUserData()->getLastUpdateMPass())) {
$this->returnJsonResponse(JsonResponse::JSON_SUCCESS_STICKY, __u('Clave maestra actualizada'), [__u('Reinicie la sesión para cambiarla')]);
@@ -102,11 +103,13 @@ class ConfigEncryptionController extends SimpleControllerBase
if (!$noAccountPassChange) {
Util::lockApp($this->session->getUserData()->getId(), 'masterpass');
+ $task = $taskId !== null ? TaskFactory::create(__FUNCTION__, $taskId) : null;
+
$request = new UpdateMasterPassRequest(
$currentMasterPass,
$newMasterPass,
$configService->getByParam('masterPwd'),
- TaskFactory::create(__FUNCTION__, 'masterpass')
+ $task
);
try {
@@ -126,7 +129,9 @@ class ConfigEncryptionController extends SimpleControllerBase
} finally {
Util::unlockApp();
- TaskFactory::end($request->getTask()->getTaskId());
+ if ($task) {
+ TaskFactory::end($task->getTaskId());
+ }
}
} else {
try {
diff --git a/app/modules/web/Controllers/ConfigManagerController.php b/app/modules/web/Controllers/ConfigManagerController.php
index 7d65032e..208c58c7 100644
--- a/app/modules/web/Controllers/ConfigManagerController.php
+++ b/app/modules/web/Controllers/ConfigManagerController.php
@@ -221,9 +221,12 @@ class ConfigManagerController extends ControllerBase
$template->setBase('config');
$template->addTemplate('encryption');
- $template->assign('mailSecurity', ['SSL', 'TLS']);
- $template->assign('numAccounts', $this->dic->get(AccountService::class)->getTotalNumAccounts()->num);
- $template->assign('taskId', Task::genTaskId('masterpass'));
+ $numAccounts = $this->dic->get(AccountService::class)->getTotalNumAccounts()->num;
+ $template->assign('numAccounts', $numAccounts);
+
+ if ($numAccounts > 500) {
+ $template->assign('taskId', Task::genTaskId('masterpass'));
+ }
$configService = $this->dic->get(ConfigService::class);
diff --git a/app/modules/web/Controllers/Helpers/Account/AccountActionsHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountActionsHelper.php
index a3cd2fdd..29e34527 100644
--- a/app/modules/web/Controllers/Helpers/Account/AccountActionsHelper.php
+++ b/app/modules/web/Controllers/Helpers/Account/AccountActionsHelper.php
@@ -105,8 +105,9 @@ class AccountActionsHelper extends HelperBase
&& $accountAcl->isShowViewPass()
) {
$action = $accountActionsDto->getPublicLinkId() ? $this->getPublicLinkRefreshAction() : $this->getPublicLinkAction();
+ $itemId = $accountActionsDto->getPublicLinkId() ?: $accountActionsDto->getAccountId();
- $actionsEnabled[] = $action->addData('item-id', $accountActionsDto->getPublicLinkId());
+ $actionsEnabled[] = $action->addData('item-id', $itemId);
}
if ($accountAcl->isShowViewPass()) {
diff --git a/app/modules/web/Controllers/Helpers/Account/AccountHelper.php b/app/modules/web/Controllers/Helpers/Account/AccountHelper.php
index d94f4978..93927354 100644
--- a/app/modules/web/Controllers/Helpers/Account/AccountHelper.php
+++ b/app/modules/web/Controllers/Helpers/Account/AccountHelper.php
@@ -177,7 +177,7 @@ class AccountHelper extends HelperBase
}
if (!$this->dic->get(MasterPassService::class)->checkUserUpdateMPass($this->session->getUserData()->getLastUpdateMPass())) {
- throw new UpdatedMasterPassException(UnauthorizedPageException::INFO);
+ throw new UpdatedMasterPassException(UpdatedMasterPassException::INFO);
}
}
diff --git a/app/modules/web/Controllers/TaskController.php b/app/modules/web/Controllers/TaskController.php
new file mode 100644
index 00000000..7da8b8d5
--- /dev/null
+++ b/app/modules/web/Controllers/TaskController.php
@@ -0,0 +1,92 @@
+.
+ */
+
+namespace SP\Modules\Web\Controllers;
+
+use DI\Container;
+use Klein\Klein;
+use SP\Core\Session\Session;
+use SP\Core\Task;
+use SP\Core\TaskFactory;
+use SP\Services\ServiceException;
+use SP\Services\Task\TaskService;
+
+/**
+ * Class TaskController
+ *
+ * @package SP\Modules\Web\Controllers
+ */
+class TaskController
+{
+ /**
+ * @var Container
+ */
+ private $container;
+
+ /**
+ * TaskController constructor.
+ *
+ * @param Container $container
+ * @throws \Psr\Container\ContainerExceptionInterface
+ * @throws \Psr\Container\NotFoundExceptionInterface
+ */
+ public function __construct(Container $container)
+ {
+ $this->container = $container;
+ }
+
+ /**
+ * @param string $taskId
+ * @throws \Psr\Container\ContainerExceptionInterface
+ * @throws \Psr\Container\NotFoundExceptionInterface
+ */
+ public function runTaskAction($taskId)
+ {
+ Session::close();
+
+ $router = $this->container->get(Klein::class);
+ $router->response()->header('Content-Type', 'text/event-stream');
+ $router->response()->header('Cache-Control', 'no-store, no-cache');
+ $router->response()->header('Access-Control-Allow-Origin', '*');
+ $router->response()->send(true);
+
+ try {
+ $this->container->get(TaskService::class)->run($taskId);
+ } catch (ServiceException $e) {
+ processException($e);
+ }
+ }
+
+ /**
+ * @param $taskId
+ */
+ public function testTaskAction($taskId)
+ {
+ $task = TaskFactory::create($taskId, Task::genTaskId($taskId));
+
+ TaskFactory::update($task->getTaskId(), TaskFactory::createMessage($task->getTaskId(), 'Prueba Tarea'));
+
+ echo $task->getTaskId();
+ }
+}
\ No newline at end of file
diff --git a/app/modules/web/themes/material-blue/views/config/encryption.inc b/app/modules/web/themes/material-blue/views/config/encryption.inc
index 0733c228..6532ac74 100644
--- a/app/modules/web/themes/material-blue/views/config/encryption.inc
+++ b/app/modules/web/themes/material-blue/views/config/encryption.inc
@@ -114,8 +114,7 @@
- = 500): ?>
-
+
diff --git a/lib/SP/Core/Task.php b/lib/SP/Core/Task.php
index d4308ba2..a81b2fe8 100644
--- a/lib/SP/Core/Task.php
+++ b/lib/SP/Core/Task.php
@@ -2,8 +2,8 @@
/**
* sysPass
*
- * @author nuxsmin
- * @link https://syspass.org
+ * @author nuxsmin
+ * @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -25,6 +25,7 @@
namespace SP\Core;
use SP\Core\Messages\TaskMessage;
+use SP\Core\Session\Session;
use SP\Util\Util;
/**
@@ -130,7 +131,7 @@ class Task
*/
public static function genTaskId($name)
{
- return uniqid($name, true);
+ return uniqid($name);
}
/**
@@ -295,7 +296,7 @@ class Task
file_put_contents($this->fileTask, serialize($this));
if ($lockSession === true) {
- session_write_close();
+ Session::close();
}
return $this;
diff --git a/lib/SP/Core/TaskFactory.php b/lib/SP/Core/TaskFactory.php
index 4437dc6b..9b63b67d 100644
--- a/lib/SP/Core/TaskFactory.php
+++ b/lib/SP/Core/TaskFactory.php
@@ -41,13 +41,13 @@ class TaskFactory
/**
* Crear una tarea para la actualización de estado de la actualización
*
- * @param $name
- * @param $id
+ * @param string $name
+ * @param string $id
* @return Task
*/
public static function create($name, $id)
{
- return self::add((new Task($name, $id))->register(false));
+ return self::add((new Task($name, $id))->register());
}
/**
diff --git a/lib/SP/Http/Request.php b/lib/SP/Http/Request.php
index 83573851..0eee33e6 100644
--- a/lib/SP/Http/Request.php
+++ b/lib/SP/Http/Request.php
@@ -114,7 +114,7 @@ class Request
{
$encryptedData = self::analyzeString($param);
- if ($encryptedData === '') {
+ if ($encryptedData === null) {
return '';
}
@@ -142,7 +142,7 @@ class Request
public static function analyzeString($param, $default = null)
{
if (!isset($_REQUEST[$param])) {
- return (string)$default;
+ return $default;
}
return filter_var($_REQUEST[$param], FILTER_SANITIZE_STRING);
@@ -156,7 +156,7 @@ class Request
public static function analyzeEmail($param, $default = null)
{
if (!isset($_REQUEST[$param])) {
- return (string)$default;
+ return $default;
}
return filter_var($_REQUEST[$param], FILTER_SANITIZE_EMAIL);
diff --git a/lib/SP/Repositories/Account/AccountHistoryRepository.php b/lib/SP/Repositories/Account/AccountHistoryRepository.php
index 0bb45f55..be48e39c 100644
--- a/lib/SP/Repositories/Account/AccountHistoryRepository.php
+++ b/lib/SP/Repositories/Account/AccountHistoryRepository.php
@@ -66,13 +66,13 @@ class AccountHistoryRepository extends Repository implements RepositoryItemInter
WHERE AH.accountId = ?
ORDER BY AH.id DESC';
- $Data = new QueryData();
- $Data->setQuery($query);
- $Data->addParam($id);
+ $queryData = new QueryData();
+ $queryData->setQuery($query);
+ $queryData->addParam($id);
$items = [];
- foreach (DbWrapper::getResultsArray($Data, $this->db) as $history) {
+ foreach (DbWrapper::getResultsArray($queryData, $this->db) as $history) {
// Comprobamos si la entrada en el historial es la primera (no tiene editor ni fecha de edición)
if (empty($history->dateEdit) || $history->dateEdit === '0000-00-00 00:00:00') {
$date = $history->dateAdd . ' - ' . $history->userAdd;
@@ -130,7 +130,7 @@ class AccountHistoryRepository extends Repository implements RepositoryItemInter
*/
public function create($itemData)
{
- $Data = new QueryData();
+ $queryData = new QueryData();
$query = /** @lang SQL */
'INSERT INTO AccountHistory
(accountId,
@@ -178,14 +178,14 @@ class AccountHistoryRepository extends Repository implements RepositoryItemInter
isPrivateGroup,
?,?,? FROM Account WHERE id = ?';
- $Data->setQuery($query);
- $Data->addParam($itemData['isModify']);
- $Data->addParam($itemData['isDelete']);
- $Data->addParam($itemData['masterPassHash']);
- $Data->addParam($itemData['id']);
- $Data->setOnErrorMessage(__u('Error al actualizar el historial'));
+ $queryData->setQuery($query);
+ $queryData->addParam($itemData['isModify']);
+ $queryData->addParam($itemData['isDelete']);
+ $queryData->addParam($itemData['masterPassHash']);
+ $queryData->addParam($itemData['id']);
+ $queryData->setOnErrorMessage(__u('Error al actualizar el historial'));
- return DbWrapper::getQuery($Data, $this->db);
+ return DbWrapper::getQuery($queryData, $this->db);
}
/**
@@ -211,14 +211,14 @@ class AccountHistoryRepository extends Repository implements RepositoryItemInter
$query = /** @lang SQL */
'DELETE FROM AccountHistory WHERE id = ? LIMIT 1';
- $Data = new QueryData();
- $Data->setQuery($query);
- $Data->addParam($id);
- $Data->setOnErrorMessage(__u('Error al eliminar la cuenta'));
+ $queryData = new QueryData();
+ $queryData->setQuery($query);
+ $queryData->addParam($id);
+ $queryData->setOnErrorMessage(__u('Error al eliminar la cuenta'));
- DbWrapper::getQuery($Data, $this->db);
+ DbWrapper::getQuery($queryData, $this->db);
- return $Data->getQueryNumRows() === 1;
+ return $queryData->getQueryNumRows() === 1;
}
/**
@@ -278,12 +278,12 @@ class AccountHistoryRepository extends Repository implements RepositoryItemInter
LEFT JOIN User U2 ON AH.userEditId = U2.id
WHERE AH.id = ? LIMIT 1';
- $Data = new QueryData();
- $Data->setQuery($query);
- $Data->setMapClassName(AccountHistoryData::class);
- $Data->addParam($id);
+ $queryData = new QueryData();
+ $queryData->setQuery($query);
+ $queryData->setMapClassName(AccountHistoryData::class);
+ $queryData->addParam($id);
- $queryRes = DbWrapper::getResults($Data, $this->db);
+ $queryRes = DbWrapper::getResults($queryData, $this->db);
if ($queryRes === false) {
throw new SPException(__u('No se pudieron obtener los datos de la cuenta'), SPException::CRITICAL);
@@ -310,12 +310,12 @@ class AccountHistoryRepository extends Repository implements RepositoryItemInter
LEFT JOIN User U2 ON AH.userEditId = U2.id
ORDER BY AH.id DESC';
- $Data = new QueryData();
- $Data->setQuery($query);
+ $queryData = new QueryData();
+ $queryData->setQuery($query);
$items = [];
- foreach (DbWrapper::getResultsArray($Data, $this->db) as $history) {
+ foreach (DbWrapper::getResultsArray($queryData, $this->db) as $history) {
// Comprobamos si la entrada en el historial es la primera (no tiene editor ni fecha de edición)
if (empty($history->dateEdit) || $history->dateEdit === '0000-00-00 00:00:00') {
$date = $history->dateAdd . ' - ' . $history->userAdd;
@@ -432,7 +432,7 @@ class AccountHistoryRepository extends Repository implements RepositoryItemInter
$queryData = new QueryData();
$queryData->setQuery($query);
- return DbWrapper::getResultsArray($queryData);
+ return DbWrapper::getResultsArray($queryData, $this->db);
}
/**
diff --git a/lib/SP/Services/Account/AccountCryptService.php b/lib/SP/Services/Account/AccountCryptService.php
index 846ed048..a748888b 100644
--- a/lib/SP/Services/Account/AccountCryptService.php
+++ b/lib/SP/Services/Account/AccountCryptService.php
@@ -88,9 +88,11 @@ class AccountCryptService extends Service
throw new ServiceException(__u('Error al obtener las claves de las cuentas'), ServiceException::ERROR);
}
- $taskId = $this->request->getTask()->getTaskId();
+ if ($this->request->useTask()) {
+ $taskId = $this->request->getTask()->getTaskId();
- TaskFactory::update($taskId, TaskFactory::createMessage($taskId, __('Actualizar Clave Maestra')));
+ TaskFactory::update($taskId, TaskFactory::createMessage($taskId, __('Actualizar Clave Maestra')));
+ }
$counter = 0;
$startTime = time();
@@ -107,14 +109,25 @@ class AccountCryptService extends Service
if ($counter % 100 === 0) {
$eta = Util::getETA($startTime, $counter, $numAccounts);
- $taskMessage = TaskFactory::createMessage($taskId, __('Actualizar Clave Maestra'))
- ->setMessage(sprintf(__('Cuentas actualizadas: %d /%d'), $counter, $numAccounts))
- ->setProgress(round(($counter * 100) / $numAccounts, 2))
- ->setTime(sprintf('ETA: %ds (%.2f/s)', $eta[0], $eta[1]));
+ if (isset($taskId)) {
+ $taskMessage = TaskFactory::createMessage($taskId, __('Actualizar Clave Maestra'))
+ ->setMessage(sprintf(__('Cuentas actualizadas: %d / %d'), $counter, $numAccounts))
+ ->setProgress(round(($counter * 100) / $numAccounts, 2))
+ ->setTime(sprintf('ETA: %ds (%.2f/s)', $eta[0], $eta[1]));
- TaskFactory::update($taskId, $taskMessage);
- debugLog($taskMessage->composeText());
+ TaskFactory::update($taskId, $taskMessage);
+
+ debugLog($taskMessage->composeText());
+ } else {
+ debugLog(
+ sprintf(__('Cuentas actualizadas: %d / %d - %d%% - ETA: %ds (%.2f/s)'),
+ $counter,
+ $numAccounts,
+ round(($counter * 100) / $numAccounts, 2),
+ $eta[0], $eta[1])
+ );
+ }
}
$accountRequest = new AccountPasswordRequest();
@@ -161,9 +174,11 @@ class AccountCryptService extends Service
new Event($this, EventMessage::factory()->addDescription(__u('Actualizar Clave Maestra')))
);
- $taskId = $this->request->getTask();
+ if ($this->request->useTask()) {
+ $taskId = $this->request->getTask();
- TaskFactory::update($taskId, TaskFactory::createMessage($taskId, __u('Actualizar Clave Maestra')));
+ TaskFactory::update($taskId, TaskFactory::createMessage($taskId, __u('Actualizar Clave Maestra')));
+ }
$eventMessage = $this->processAccounts($this->accountService->getAccountsPassData(), function ($request) {
$this->accountService->updatePasswordMasterPass($request);
@@ -204,7 +219,11 @@ class AccountCryptService extends Service
$configData = $this->config->getConfigData();
$currentMasterPassHash = $this->request->getCurrentHash();
- $taskId = $this->request->getTask()->getTaskId();
+
+ if ($this->request->useTask()) {
+ $taskId = $this->request->getTask()->getTaskId();
+ }
+
$eventMessage = EventMessage::factory();
foreach ($accounts as $account) {
@@ -217,14 +236,24 @@ class AccountCryptService extends Service
if ($counter % 100 === 0) {
$eta = Util::getETA($startTime, $counter, $numAccounts);
- $taskMessage = TaskFactory::createMessage($taskId, __('Actualizar Clave Maestra'))
- ->setMessage(sprintf(__('Cuentas actualizadas: %d /%d'), $counter, $numAccounts))
- ->setProgress(round(($counter * 100) / $numAccounts, 2))
- ->setTime(sprintf('ETA: %ds (%.2f/s)', $eta[0], $eta[1]));
+ if (isset($taskId)) {
+ $taskMessage = TaskFactory::createMessage($taskId, __('Actualizar Clave Maestra'))
+ ->setMessage(sprintf(__('Cuentas actualizadas: %d / %d'), $counter, $numAccounts))
+ ->setProgress(round(($counter * 100) / $numAccounts, 2))
+ ->setTime(sprintf('ETA: %ds (%.2f/s)', $eta[0], $eta[1]));
- TaskFactory::update($taskId, $taskMessage);
+ TaskFactory::update($taskId, $taskMessage);
- debugLog($taskMessage->composeText());
+ debugLog($taskMessage->composeText());
+ } else {
+ debugLog(
+ sprintf(__('Cuentas actualizadas: %d / %d - %d%% - ETA: %ds (%.2f/s)'),
+ $counter,
+ $numAccounts,
+ round(($counter * 100) / $numAccounts, 2),
+ $eta[0], $eta[1])
+ );
+ }
}
if (isset($account->mPassHash) && $account->mPassHash !== $currentMasterPassHash) {
@@ -285,7 +314,9 @@ class AccountCryptService extends Service
$taskId = $this->request->getTask();
- TaskFactory::update($taskId, TaskFactory::createMessage($taskId, __u('Actualizar Clave Maestra (H)')));
+ if ($this->request->useTask()) {
+ TaskFactory::update($taskId, TaskFactory::createMessage($taskId, __u('Actualizar Clave Maestra (H)')));
+ }
$eventMessage = $this->processAccounts($this->accountHistoryService->getAccountsPassData(), function ($request) {
/** @var AccountPasswordRequest $request */
diff --git a/lib/SP/Services/Crypt/MasterPassService.php b/lib/SP/Services/Crypt/MasterPassService.php
index 757f01b2..1fd1d6df 100644
--- a/lib/SP/Services/Crypt/MasterPassService.php
+++ b/lib/SP/Services/Crypt/MasterPassService.php
@@ -2,8 +2,8 @@
/**
* sysPass
*
- * @author nuxsmin
- * @link https://syspass.org
+ * @author nuxsmin
+ * @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -25,7 +25,8 @@
namespace SP\Services\Crypt;
use SP\Core\Crypt\Hash;
-use SP\Core\Exceptions\SPException;
+use SP\Core\Events\Event;
+use SP\Core\Events\EventMessage;
use SP\Services\Account\AccountCryptService;
use SP\Services\Config\ConfigService;
use SP\Services\CustomField\CustomFieldCryptService;
@@ -79,32 +80,38 @@ class MasterPassService extends Service
/**
* @param UpdateMasterPassRequest $request
- * @throws SPException
- * @throws ServiceException
+ * @throws \Exception
*/
public function changeMasterPassword(UpdateMasterPassRequest $request)
{
$db = $this->dic->get(Database::class);
- if (!DbWrapper::beginTransaction($db)) {
- throw new ServiceException(__u('No es posible iniciar una transacción'), ServiceException::ERROR);
- }
-
try {
+ if (!DbWrapper::beginTransaction($db)) {
+ throw new ServiceException(__u('No es posible iniciar una transacción'), ServiceException::ERROR);
+ }
+
$this->accountCryptService->updateMasterPassword($request);
$this->accountCryptService->updateHistoryMasterPassword($request);
$this->customFieldCryptService->updateMasterPassword($request);
- } catch (ServiceException $e) {
- DbWrapper::rollbackTransaction($db);
+
+ if (!DbWrapper::endTransaction($db)) {
+ throw new ServiceException(__u('No es posible finalizar una transacción'), ServiceException::ERROR);
+ }
+ } catch (\Exception $e) {
+ if (DbWrapper::rollbackTransaction($db)) {
+ $this->eventDispatcher->notifyEvent('update.masterPassword.rollback',
+ new Event($this, EventMessage::factory()
+ ->addDescription(__u('Rollback')))
+ );
+
+ debugLog('Rollback');
+ }
throw $e;
}
-
- if (!DbWrapper::endTransaction($db)) {
- throw new ServiceException(__u('No es posible finalizar una transacción'), ServiceException::ERROR);
- }
}
/**
diff --git a/lib/SP/Services/Crypt/UpdateMasterPassRequest.php b/lib/SP/Services/Crypt/UpdateMasterPassRequest.php
index 643627cb..d38708ba 100644
--- a/lib/SP/Services/Crypt/UpdateMasterPassRequest.php
+++ b/lib/SP/Services/Crypt/UpdateMasterPassRequest.php
@@ -2,8 +2,8 @@
/**
* sysPass
*
- * @author nuxsmin
- * @link https://syspass.org
+ * @author nuxsmin
+ * @link https://syspass.org
* @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
@@ -64,7 +64,7 @@ class UpdateMasterPassRequest
* @param string $currentHash
* @param Task $task
*/
- public function __construct($currentMasterPass, $newMasterPass, $currentHash, Task $task)
+ public function __construct($currentMasterPass, $newMasterPass, $currentHash, Task $task = null)
{
$this->currentMasterPass = $currentMasterPass;
$this->newMasterPass = $newMasterPass;
@@ -97,6 +97,14 @@ class UpdateMasterPassRequest
return $this->task;
}
+ /**
+ * @return bool
+ */
+ public function useTask()
+ {
+ return $this->task !== null;
+ }
+
/**
* @return string
*/
diff --git a/lib/SP/Services/CustomField/CustomFieldCryptService.php b/lib/SP/Services/CustomField/CustomFieldCryptService.php
index 8796b489..2989539e 100644
--- a/lib/SP/Services/CustomField/CustomFieldCryptService.php
+++ b/lib/SP/Services/CustomField/CustomFieldCryptService.php
@@ -82,23 +82,33 @@ class CustomFieldCryptService extends Service
/**
* @param callable $decryptor
- * @throws ServiceException
*/
protected function processUpdateMasterPassword(callable $decryptor)
{
$customFields = $this->customFieldService->getAll();
if (count($customFields) === 0) {
- throw new ServiceException(__u('No hay datos de campos personalizados'), ServiceException::INFO);
+ $this->eventDispatcher->notifyEvent('update.masterPassword.customFields',
+ new Event($this, EventMessage::factory()
+ ->addDescription(__u('Actualizar Clave Maestra'))
+ ->addDescription(__u('No hay datos de campos personalizados')))
+ );
+ return;
}
$this->eventDispatcher->notifyEvent('update.masterPassword.customFields.start',
- new Event($this, EventMessage::factory()->addDescription(__u('Actualizar Clave Maestra')))
+ new Event($this, EventMessage::factory()
+ ->addDescription(__u('Actualizar Clave Maestra'))
+ ->addDescription(__u('Actualizando datos encriptados')))
);
- $taskId = $this->request->getTask()->getTaskId();
+ if ($this->request->useTask()) {
+ $taskId = $this->request->getTask()->getTaskId();
- TaskFactory::update($taskId, TaskFactory::createMessage($taskId, __('Actualizar Clave Maestra'))->setMessage(__u('Actualizando datos encriptados')));
+ TaskFactory::update($taskId,
+ TaskFactory::createMessage($taskId, __('Actualizar Clave Maestra'))
+ ->setMessage(__('Actualizando datos encriptados')));
+ }
$errors = [];
$success = [];
@@ -144,8 +154,6 @@ class CustomFieldCryptService extends Service
Crypt::unlockSecuredKey($customFieldData->getKey(), $this->request->getCurrentMasterPass()),
$this->request->getCurrentMasterPass());
});
- } catch (ServiceException $e) {
- throw $e;
} catch (\Exception $e) {
$this->eventDispatcher->notifyEvent('exception', new Event($e));
diff --git a/lib/SP/Services/Task/TaskService.php b/lib/SP/Services/Task/TaskService.php
new file mode 100644
index 00000000..d50e896f
--- /dev/null
+++ b/lib/SP/Services/Task/TaskService.php
@@ -0,0 +1,217 @@
+.
+ */
+
+namespace SP\Services\Task;
+
+use SP\Core\Task;
+use SP\Core\TaskFactory;
+use SP\Services\Service;
+use SP\Services\ServiceException;
+use SP\Util\Util;
+
+/**
+ * Class TaskService
+ *
+ * @package SP\Services
+ */
+class TaskService extends Service
+{
+ /**
+ * Tiempo de espera en cada intento de inicialización
+ */
+ const STARTUP_WAIT_TIME = 5;
+ /**
+ * Intentos de inicialización
+ */
+ const STARTUP_WAIT_COUNT = 30;
+
+ /**
+ * @var Task Instancia de la tarea
+ */
+ protected $task;
+ /**
+ * @var string Archivo de bloqueo
+ */
+ protected $lockFile;
+ /**
+ * @var string Directorio de las tareas
+ */
+ protected $dir;
+ /**
+ * @var string ID de la tarea
+ */
+ protected $taskId;
+ /**
+ * @var string Archivo de la tarea
+ */
+ protected $taskFile;
+
+ /**
+ * Realizar acción
+ *
+ * @param string $taskId
+ * @throws ServiceException
+ */
+ public function run($taskId)
+ {
+ $this->taskId = $taskId;
+ $this->dir = Util::getTempDir();
+
+ if ($this->dir === false || !$this->getLock()) {
+ throw new ServiceException(__('No es posible crear archivo de bloqueo'));
+ }
+
+ $this->taskFile = $this->dir . DIRECTORY_SEPARATOR . $this->taskId . '.task';
+
+ $count = 0;
+
+ while (!$this->checkTaskRegistered() || !$this->checkTaskFile()) {
+ if ($count >= self::STARTUP_WAIT_COUNT || !file_exists($this->lockFile)) {
+ debugLog('Aborting ...');
+
+ die(1);
+ } else {
+ debugLog(sprintf('Waiting for task "%s" (%ds) ...', $taskId, (self::STARTUP_WAIT_COUNT - $count) * self::STARTUP_WAIT_TIME));
+
+ $count++;
+ sleep(self::STARTUP_WAIT_TIME);
+ }
+ }
+
+ $this->readTaskStatus();
+
+ die(0);
+ }
+
+ /**
+ * Obtener un bloqueo para la ejecución de la tarea
+ *
+ * @return bool
+ */
+ private function getLock()
+ {
+ $this->lockFile = $this->dir . DIRECTORY_SEPARATOR . $this->taskId . '.lock';
+
+ if (file_exists($this->lockFile)) {
+ $timeout = self::STARTUP_WAIT_COUNT * self::STARTUP_WAIT_TIME;
+
+ if (filemtime($this->lockFile) + $timeout < time()) {
+ unlink($this->lockFile);
+
+ return $this->updateLock();
+ }
+
+ return false;
+ }
+
+ return $this->updateLock();
+ }
+
+ /**
+ * Actualizar el tiempo del archivo de bloqueo
+ */
+ protected function updateLock()
+ {
+ return file_put_contents($this->lockFile, time()) !== false;
+ }
+
+ /**
+ * Comprueba si una tarea ha sido registrada en la sesión
+ *
+ * @return bool
+ */
+ protected function checkTaskRegistered()
+ {
+ if (is_object($this->task)) {
+ debugLog('Task detected: ' . $this->task->getTaskId());
+
+ return true;
+ }
+
+ if (file_exists($this->taskFile)) {
+ $task = file_get_contents($this->taskFile);
+
+ if ($task !== false) {
+ $this->task = unserialize($task);
+ }
+
+ return is_object($this->task);
+ }
+
+ return false;
+ }
+
+ /**
+ * Comprobar si el archivo de salida de la tarea existe
+ */
+ protected function checkTaskFile()
+ {
+ return file_exists($this->task->getFileOut());
+ }
+
+ /**
+ * Leer el estado de una tarea y enviarlo
+ */
+ protected function readTaskStatus()
+ {
+ debugLog('Tracking task: ' . $this->task->getTaskId());
+
+ $id = 0;
+ $failCount = 0;
+ $file = $this->task->getFileOut();
+ $interval = $this->task->getInterval();
+
+ $taskMessage = TaskFactory::createMessage($this->task->getTaskId(), __('Esperando actualización de progreso ...'));
+
+ while ($failCount <= self::STARTUP_WAIT_COUNT && file_exists($this->taskFile)) {
+ $content = file_get_contents($file);
+
+ if (!empty($content)) {
+ $this->sendMessage($id, $content);
+ $id++;
+ } else {
+ debugLog($taskMessage->composeJson());
+
+ $this->sendMessage($id, $taskMessage->composeJson());
+ $failCount++;
+ }
+
+ sleep($interval);
+ }
+ }
+
+ /**
+ * Enviar un mensaje
+ *
+ * @param $id
+ * @param $message
+ */
+ protected function sendMessage($id, $message)
+ {
+ echo 'id: ', $id, PHP_EOL, 'data: ', $message, PHP_EOL, PHP_EOL;
+
+ ob_flush();
+ flush();
+ }
+}
\ No newline at end of file
diff --git a/lib/SP/Util/Util.php b/lib/SP/Util/Util.php
index 56e5c8e8..2ef0853b 100644
--- a/lib/SP/Util/Util.php
+++ b/lib/SP/Util/Util.php
@@ -327,7 +327,7 @@ class Util
public static function getTempDir()
{
$sysTmp = sys_get_temp_dir();
- $appTmp = Init::$SERVERROOT . DIRECTORY_SEPARATOR . 'tmp';
+ $appTmp = APP_PATH . DIRECTORY_SEPARATOR . 'temp';
$file = 'syspass.test';
$checkDir = function ($dir) use ($file) {
diff --git a/public/js/app-actions.js b/public/js/app-actions.js
index 84d635f5..1ed26111 100644
--- a/public/js/app-actions.js
+++ b/public/js/app-actions.js
@@ -657,31 +657,17 @@ sysPass.Actions = function (Common) {
positive: {
title: Common.config().LANG[43],
onClick: function (e) {
- const $useTask = $obj.find("input[name='useTask']");
- const $taskStatus = $("#taskStatus");
+ let taskRunner;
+ const taskId = $obj.find("input[name='taskId']").val();
- $taskStatus.empty().html(Common.config().LANG[62]);
-
- if ($useTask.length > 0 && $useTask.val() == 1) {
- const optsTask = Common.appRequests().getRequestOpts();
- optsTask.url = ajaxUrl.entrypoint;
- optsTask.data = {
- source: $obj.find("input[name='lock']").val(),
- taskId: $obj.find("input[name='taskId']").val()
- };
-
- const task = Common.appRequests().getActionEvent(optsTask, function (result) {
- let text = result.task + " - " + result.message + " - " + result.time + " - " + result.progress + "%";
- text += " '+b.config().LANG[3]+"
" + Common.config().LANG[62];
-
- $taskStatus.empty().html(text);
- });
+ if (taskId) {
+ taskRunner = task(taskId);
}
const opts = Common.appRequests().getRequestOpts();
opts.url = ajaxUrl.entrypoint;
opts.method = "get";
- opts.useFullLoading = true;
+ opts.useFullLoading = !!taskId;
opts.data = $obj.serialize();
Common.appRequests().getActionCall(opts, function (json) {
@@ -690,8 +676,8 @@ sysPass.Actions = function (Common) {
if (json.status !== 0) {
$obj.find(":input[name=h]").val("");
} else {
- if (task !== undefined) {
- task.close();
+ if (taskRunner !== undefined) {
+ taskRunner.close();
}
setTimeout(function () {
@@ -781,30 +767,16 @@ sysPass.Actions = function (Common) {
positive: {
title: Common.config().LANG[43],
onClick: function (e) {
- const $useTask = $obj.find("input[name='useTask']");
- const $taskStatus = $("#taskStatus");
+ let taskRunner;
+ const taskId = $obj.find("input[name='taskId']").val();
- $taskStatus.empty().html(Common.config().LANG[62]);
-
- if ($useTask.length > 0 && $useTask.val() == 1) {
- const optsTask = Common.appRequests().getRequestOpts();
- optsTask.url = ajaxUrl.entrypoint;
- optsTask.data = {
- source: $obj.find("input[name='lock']").val(),
- taskId: $obj.find("input[name='taskId']").val()
- };
-
- const task = Common.appRequests().getActionEvent(optsTask, function (result) {
- let text = result.task + " - " + result.message + " - " + result.time + " - " + result.progress + "%";
- text += "
" + Common.config().LANG[62];
-
- $taskStatus.empty().html(text);
- });
+ if (taskId) {
+ taskRunner = task(taskId);
}
const opts = Common.appRequests().getRequestOpts();
opts.url = ajaxUrl.entrypoint;
- opts.useFullLoading = true;
+ opts.useFullLoading = !!taskId;
opts.data = $obj.serialize();
Common.appRequests().getActionCall(opts, function (json) {
@@ -812,8 +784,8 @@ sysPass.Actions = function (Common) {
$obj.find(":input[type=password]").val("");
- if (task !== undefined) {
- task.close();
+ if (taskRunner !== undefined) {
+ taskRunner.close();
}
});
}
@@ -956,14 +928,13 @@ sysPass.Actions = function (Common) {
const itemId = $obj.data("item-id");
const opts = Common.appRequests().getRequestOpts();
- opts.url = ajaxUrl.entrypoint;
- opts.data = {
- r: $obj.data("action-route"),
- accountId: itemId,
- notify: notify,
- sk: Common.sk.get(),
- isAjax: 1
- };
+
+ if (itemId) {
+ opts.url = ajaxUrl.entrypoint + "?r=" + $obj.data("action-route") + "/" + itemId + "/" + notify;
+ } else {
+ opts.url = ajaxUrl.entrypoint + "?r=" + $obj.data("action-route");
+ opts.data = $obj.serialize();
+ }
Common.appRequests().getActionCall(opts, function (json) {
Common.msg.out(json);
@@ -1544,6 +1515,23 @@ sysPass.Actions = function (Common) {
}
};
+ const task = function (taskId) {
+ const $taskStatus = $("#taskStatus");
+
+ $taskStatus.empty().html(Common.config().LANG[62]);
+
+ const opts = Common.appRequests().getRequestOpts();
+ opts.method = "get";
+ opts.url = ajaxUrl.entrypoint + "?r=task/runTask/" + taskId;
+
+ return Common.appRequests().getActionEvent(opts, function (result) {
+ let text = result.task + " - " + result.message + " - " + result.time + " - " + result.progress + "%";
+ text += "
" + Common.config().LANG[62];
+
+ $taskStatus.empty().html(text);
+ });
+ };
+
return {
doAction: doAction,
appMgmt: appMgmt,
diff --git a/public/js/app-actions.min.js b/public/js/app-actions.min.js
index abc593b4..94a5281d 100644
--- a/public/js/app-actions.min.js
+++ b/public/js/app-actions.min.js
@@ -1,8 +1,8 @@
var $jscomp={scope:{},findInternal:function(b,e,l){b instanceof String&&(b=String(b));for(var f=b.length,h=0;h
'+b.config().LANG[59]+"
'+b.config().LANG[48]+"
'+b.config().LANG[20]+"
'+b.config().LANG[58]+"
'+b.config().LANG[57]+ -"
'+b.config().LANG[48]+"
'+b.config().LANG[20]+"
'+b.config().LANG[58]+"
'+b.config().LANG[57]+"