diff --git a/.gitignore b/.gitignore index 52fa9d98..2aa48837 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,6 @@ res/ tools/ app/temp/* app/modules/web/plugins/* -vendor/ +vendor/* !.blank \ No newline at end of file diff --git a/app/modules/web/Controllers/AccountController.php b/app/modules/web/Controllers/AccountController.php index a7d4b776..d27cb054 100644 --- a/app/modules/web/Controllers/AccountController.php +++ b/app/modules/web/Controllers/AccountController.php @@ -159,7 +159,7 @@ class AccountController extends ControllerBase implements CrudControllerInterfac public function viewLinkAction($hash) { $layoutHelper = new LayoutHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - $layoutHelper->getPublicLayout('account-link', 'account'); + $layoutHelper->getPublicLayout(['name' => 'account-link', 'base' => 'account'], 'account'); try { $publicLinkService = new PublicLinkService(); diff --git a/app/modules/web/Controllers/BootstrapController.php b/app/modules/web/Controllers/BootstrapController.php index be782042..f0390109 100644 --- a/app/modules/web/Controllers/BootstrapController.php +++ b/app/modules/web/Controllers/BootstrapController.php @@ -26,7 +26,6 @@ namespace SP\Modules\Web\Controllers; use SP\Bootstrap; use SP\Core\CryptPKI; -use SP\Core\Plugin\PluginUtil; use SP\Http\Cookies; use SP\Http\Response; use SP\Providers\Auth\Browser\Browser; @@ -43,6 +42,7 @@ class BootstrapController extends SimpleControllerBase * * @throws \SP\Core\Exceptions\FileNotFoundException * @throws \SP\Core\Exceptions\SPException + * @throws \SP\Core\Dic\ContainerException */ public function getEnvironmentAction() { @@ -59,7 +59,8 @@ class BootstrapController extends SimpleControllerBase 'timezone' => date_default_timezone_get(), 'debug' => DEBUG || $configData->isDebug(), 'cookies_enabled' => Cookies::checkCookies(), - 'plugins' => PluginUtil::getEnabledPlugins(), +// 'plugins' => PluginUtil::getEnabledPlugins(), + 'plugins' => [], 'loggedin' => $this->session->isLoggedIn(), 'authbasic_autologin' => Browser::getServerAuthUser() && $configData->isAuthBasicAutoLoginEnabled(), 'pk' => $this->session->getPublicKey() ?: (new CryptPKI())->getPublicKey() diff --git a/app/modules/web/Controllers/Helpers/LayoutHelper.php b/app/modules/web/Controllers/Helpers/LayoutHelper.php index 3dcac9fd..19221d18 100644 --- a/app/modules/web/Controllers/Helpers/LayoutHelper.php +++ b/app/modules/web/Controllers/Helpers/LayoutHelper.php @@ -61,20 +61,24 @@ class LayoutHelper extends HelperBase /** * Sets a full layout page * - * @param Acl $acl * @param string $page Page/view name + * @param Acl $acl * @return LayoutHelper */ - public function getFullLayout(Acl $acl, $page = '') + public function getFullLayout($page, Acl $acl = null) { + $this->view->addTemplate('main', '_layouts'); + $this->setPage($page); $this->initBody(); - $this->getSessionBar(); - $this->getMenu($acl); - $this->view->addPartial('body-content'); - $this->view->addPartial('body-footer'); - $this->view->addPartial('body-end'); + if ($this->loggedIn) { + $this->getSessionBar(); + } + + if ($acl !== null) { + $this->getMenu($acl); + } return $this; } @@ -96,10 +100,6 @@ class LayoutHelper extends HelperBase { $this->view->assign('startTime', microtime()); - $this->view->addPartial('header'); - $this->view->addPartial('body-start'); - - $this->view->assign('useLayout', true); $this->view->assign('isInstalled', $this->configData->isInstalled()); $this->view->assign('sk', SessionUtil::getSessionKey(true, $this->configData)); $this->view->assign('appInfo', Util::getAppInfo()); @@ -210,8 +210,6 @@ class LayoutHelper extends HelperBase */ public function getSessionBar() { - $this->view->addPartial('sessionbar'); - $userType = null; $userData = $this->session->getUserData(); @@ -239,8 +237,6 @@ class LayoutHelper extends HelperBase */ public function getMenu(Acl $acl) { - $this->view->addPartial('body-header-menu'); - $icons = $this->theme->getIcons(); $actionSearch = new DataGridAction(); @@ -324,6 +320,8 @@ class LayoutHelper extends HelperBase $this->view->append('actions', $actionEventlog); } + + $this->view->assign('useMenu', true); } /** @@ -335,23 +333,39 @@ class LayoutHelper extends HelperBase */ public function getPublicLayout($template, $page = '') { + $this->view->addTemplate('main', '_layouts'); + $this->view->addContentTemplate($template); + $this->view->assign('useFixedHeader'); + $this->setPage($page); $this->initBody(); - $this->view->addPartial('body-header'); - $this->view->addTemplate($template); - $this->view->addPartial('body-footer'); - $this->view->addPartial('body-end'); - return $this; } /** - * @param bool $loggedIn + * Sets a custom layout page + * + * @param string $template + * @param string $page Page/view name + * @return LayoutHelper */ - protected function setLoggedIn($loggedIn) + public function getCustomLayout($template, $page = '') { - $this->loggedIn = (bool)$loggedIn; + $this->view->addTemplate('main', '_layouts'); + $this->view->addContentTemplate($template); + + $this->setPage($page); + $this->initBody(); + + return $this; + } + + protected function initialize() + { + $this->loggedIn = $this->session->isLoggedIn(); + $this->view->assign('loggedIn', $this->loggedIn); } + } \ No newline at end of file diff --git a/app/modules/web/Controllers/IndexController.php b/app/modules/web/Controllers/IndexController.php index 69a7379a..0b602de3 100644 --- a/app/modules/web/Controllers/IndexController.php +++ b/app/modules/web/Controllers/IndexController.php @@ -47,7 +47,7 @@ class IndexController extends ControllerBase Response::redirect('index.php?r=login'); } else { $LayoutHelper = new LayoutHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - $LayoutHelper->getFullLayout($this->acl, 'main'); + $LayoutHelper->getFullLayout('main', $this->acl); $this->view(); } diff --git a/app/modules/web/Controllers/InstallController.php b/app/modules/web/Controllers/InstallController.php new file mode 100644 index 00000000..7406bb4b --- /dev/null +++ b/app/modules/web/Controllers/InstallController.php @@ -0,0 +1,128 @@ +. + */ + +namespace SP\Modules\Web\Controllers; + +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; +use SP\Controller\ControllerBase; +use SP\Core\Exceptions\SPException; +use SP\Core\Install\Installer; +use SP\Core\Language; +use SP\DataModel\InstallData; +use SP\Http\Request; +use SP\Modules\Web\Controllers\Helpers\LayoutHelper; +use SP\Modules\Web\Controllers\Traits\JsonTrait; +use SP\Util\Checks; + +/** + * Class InstallController + * + * @package SP\Modules\Web\Controllers + */ +class InstallController extends ControllerBase +{ + use JsonTrait; + + /** + * @throws \SP\Core\Dic\ContainerException + */ + public function indexAction() + { + $layoutHelper = new LayoutHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $layoutHelper->getPublicLayout('index', 'install'); + + $errors = []; + + if (!Checks::checkPhpVersion()) { + $errors[] = [ + 'type' => SPException::CRITICAL, + 'description' => __('Versión de PHP requerida >= ') . ' 5.6.0 <= 7.0', + 'hint' => __('Actualice la versión de PHP para que la aplicación funcione correctamente') + ]; + } + + $modules = Checks::checkModules(); + + if (count($modules) > 0) { + foreach ($modules as $module) { + $error[] = [ + 'type' => SPException::WARNING, + 'description' => sprintf('%s (%s)', __('Módulo no disponible'), $module), + 'hint' => __('Sin este módulo la aplicación puede no funcionar correctamente.') + ]; + } + } + + if (@file_exists(__FILE__ . "\0Nullbyte")) { + $errors[] = [ + 'type' => SPException::WARNING, + 'description' => __('La version de PHP es vulnerable al ataque NULL Byte (CVE-2006-7243)'), + 'hint' => __('Actualice la versión de PHP para usar sysPass de forma segura')]; + } + + if (!Checks::secureRNGIsAvailable()) { + $errors[] = [ + 'type' => SPException::WARNING, + 'description' => __('No se encuentra el generador de números aleatorios.'), + 'hint' => __('Sin esta función un atacante puede utilizar su cuenta al resetear la clave')]; + } + + $this->view->assign('errors', $errors); + $this->view->assign('langsAvailable', Language::getAvailableLanguages()); + $this->view->assign('langBrowser', Language::$globalLang); + + $this->view(); + } + + /** + * Performs sysPass installation + * + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function installAction() + { + $installData = new InstallData(); + $installData->setSiteLang(Request::analyze('sitelang', 'en_US')); + $installData->setAdminLogin(Request::analyze('adminlogin', 'admin')); + $installData->setAdminPass(Request::analyzeEncrypted('adminpass')); + $installData->setMasterPassword(Request::analyzeEncrypted('masterpassword')); + $installData->setDbAdminUser(Request::analyze('dbuser', 'root')); + $installData->setDbAdminPass(Request::analyzeEncrypted('dbpass')); + $installData->setDbName(Request::analyze('dbname', 'syspass')); + $installData->setDbHost(Request::analyze('dbhost', 'localhost')); + $installData->setHostingMode(Request::analyze('hostingmode', false)); + + try { + Installer::run($installData); + + $this->returnJsonResponse(0, __('Instalación finalizada')); + } catch (SPException $e) { + $this->returnJsonResponse(1, $e->getMessage(), [$e->getHint()]); + } catch (\Exception $e) { + $this->returnJsonResponse(1, $e->getMessage()); + } + } +} \ No newline at end of file diff --git a/app/modules/web/Controllers/LoginController.php b/app/modules/web/Controllers/LoginController.php index 0ccb439d..01bacb30 100644 --- a/app/modules/web/Controllers/LoginController.php +++ b/app/modules/web/Controllers/LoginController.php @@ -29,7 +29,6 @@ use SP\Core\SessionFactory; use SP\Core\SessionUtil; use SP\Html\Html; use SP\Http\Response; -use SP\Log\Log; use SP\Modules\Web\Controllers\Helpers\LayoutHelper; use SP\Services\Auth\LoginService; use SP\Util\Json; @@ -47,36 +46,39 @@ class LoginController extends ControllerBase * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface + * @throws \ReflectionException */ public function loginAction() { - $LoginService = new LoginService($this->config, $this->session, $this->theme, $this->eventDispatcher); - Json::returnJson($LoginService->doLogin()); + $loginService = new LoginService($this->config, $this->session, $this->theme, $this->eventDispatcher); + Json::returnJson($loginService->doLogin()); } /** * Logout action + * + * @throws \SP\Core\Dic\ContainerException */ public function logoutAction() { if ($this->session->isLoggedIn()) { - $inactiveTime = abs(round((time() - SessionFactory::getLastActivity()) / 60, 2)); - $totalTime = abs(round((time() - SessionFactory::getStartActivity()) / 60, 2)); +// $inactiveTime = abs(round((time() - SessionFactory::getLastActivity()) / 60, 2)); +// $totalTime = abs(round((time() - SessionFactory::getStartActivity()) / 60, 2)); - $Log = new Log(); - $LogMessage = $Log->getLogMessage(); - $LogMessage->setAction(__u('Finalizar sesión')); - $LogMessage->addDetails(__u('Usuario'), SessionFactory::getUserData()->getLogin()); - $LogMessage->addDetails(__u('Tiempo inactivo'), $inactiveTime . ' min.'); - $LogMessage->addDetails(__u('Tiempo total'), $totalTime . ' min.'); - $Log->writeLog(); +// $Log = new Log(); +// $LogMessage = $Log->getLogMessage(); +// $LogMessage->setAction(__u('Finalizar sesión')); +// $LogMessage->addDetails(__u('Usuario'), SessionFactory::getUserData()->getLogin()); +// $LogMessage->addDetails(__u('Tiempo inactivo'), $inactiveTime . ' min.'); +// $LogMessage->addDetails(__u('Tiempo total'), $totalTime . ' min.'); +// $Log->writeLog(); SessionUtil::cleanSession(); SessionFactory::setLoggedOut(true); - $LayoutHelper = new LayoutHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - $LayoutHelper->setPage('logout'); - $LayoutHelper->initBody(); + $layoutHelper = new LayoutHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $layoutHelper->setPage('logout'); + $layoutHelper->initBody(); $this->view->addTemplate('logout'); @@ -90,12 +92,13 @@ class LoginController extends ControllerBase /** * Index action + * + * @throws \SP\Core\Dic\ContainerException */ public function indexAction() { - $LayoutHelper = new LayoutHelper($this->view, $this->config, $this->session, $this->eventDispatcher); - $LayoutHelper->setPage('login'); - $LayoutHelper->initBody(); + $layoutHelper = new LayoutHelper($this->view, $this->config, $this->session, $this->eventDispatcher); + $layoutHelper->getCustomLayout('index', 'login'); if (SessionFactory::getLoggedOut() === true) { SessionFactory::setLoggedOut(); @@ -105,12 +108,6 @@ class LoginController extends ControllerBase $this->view->assign('loggedOut', 0); } - $this->view->addTemplate('login'); - - $this->view->addPartial('body-footer'); - $this->view->addPartial('body-end'); - - $this->view->assign('useLayout', false); $this->view->assign('mailEnabled', $this->configData->isMailEnabled()); $this->view->assign('updated', SessionFactory::getAppUpdated()); diff --git a/app/modules/web/themes/material-blue/views/_layouts/main.inc b/app/modules/web/themes/material-blue/views/_layouts/main.inc new file mode 100644 index 00000000..5c7154a1 --- /dev/null +++ b/app/modules/web/themes/material-blue/views/_layouts/main.inc @@ -0,0 +1,55 @@ + + + + + <?php echo $appInfo['appname'], ' :: ', $appInfo['appdesc']; ?> + + + + + + + + +
+ + +
+
+
+
+ +
+ includePartial('fixed-header'); + elseif ($this->hashContentTemplates()): + foreach ($this->getContentTemplates() as $template): + include $template; + endforeach; + endif; + ?> +
+ + includePartial('footer'); ?> +
+ + + + + + + + + + diff --git a/app/modules/web/themes/material-blue/views/_partials/fixed-header.inc b/app/modules/web/themes/material-blue/views/_partials/fixed-header.inc new file mode 100644 index 00000000..9cfd2b6c --- /dev/null +++ b/app/modules/web/themes/material-blue/views/_partials/fixed-header.inc @@ -0,0 +1,180 @@ +
+
+
+ + + + + + + +
+ + + +
+
+ + +
+ + +
+ + +
+ hashContentTemplates()): + foreach ($this->getContentTemplates() as $template): + include $template; + endforeach; + else: ?> +
+ +
+
diff --git a/app/modules/web/themes/material-blue/views/_partials/footer.inc b/app/modules/web/themes/material-blue/views/_partials/footer.inc new file mode 100644 index 00000000..7db3aa8f --- /dev/null +++ b/app/modules/web/themes/material-blue/views/_partials/footer.inc @@ -0,0 +1,63 @@ + diff --git a/app/modules/web/themes/material-blue/views/install/index.inc b/app/modules/web/themes/material-blue/views/install/index.inc new file mode 100644 index 00000000..058cb130 --- /dev/null +++ b/app/modules/web/themes/material-blue/views/install/index.inc @@ -0,0 +1,173 @@ + +
+
+

+
+ + includePartial('error-list'); ?> + +
+ + + +
+ + +
+ + +
+ +
+ getIconHelp()->getIcon(); ?> +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+ +
+ + +
+
+ +
+ + + + + +
+ + +
+ +
+ getIconHelp()->getIcon(); ?> +
+
+ +
+ +
+ + +
+ +
+ + +
+ +
+ getIconHelp()->getIcon(); ?> +
+
+ +
+ +
+ + +
+ +
+ getIconHelp()->getIcon(); ?> +
+
+ +
+
+ +
+ + +
+ + +
+ +
+ + +
+ +
+
+
+ +
+ +
+
+
diff --git a/app/modules/web/themes/material-blue/views/login/login.inc b/app/modules/web/themes/material-blue/views/login/index.inc similarity index 97% rename from app/modules/web/themes/material-blue/views/login/login.inc rename to app/modules/web/themes/material-blue/views/login/index.inc index b5c3462d..c0e2377c 100644 --- a/app/modules/web/themes/material-blue/views/login/login.inc +++ b/app/modules/web/themes/material-blue/views/login/index.inc @@ -1,7 +1,9 @@
-
+
perm_identity diff --git a/app/modules/web/themes/material-blue/views/main/install.inc b/app/modules/web/themes/material-blue/views/main/install.inc deleted file mode 100644 index bfd1c4f2..00000000 --- a/app/modules/web/themes/material-blue/views/main/install.inc +++ /dev/null @@ -1,173 +0,0 @@ - -
-
-
-

-
- - includeTemplate('error-list'); ?> - - - - - -
- - -
- - -
- -
- getIconHelp()->getIcon(); ?> -
-
- -
- -
- - -
-
- -
- -
- - -
- -
- - -
-
- -
- - - - - -
- - -
- -
- getIconHelp()->getIcon(); ?> -
-
- -
- -
- - -
- -
- - -
- -
- getIconHelp()->getIcon(); ?> -
-
- -
- -
- - -
- -
- getIconHelp()->getIcon(); ?> -
-
- -
-
- -
- - -
- - -
- -
- - -
- -
-
-
- -
- -
- -
-
\ No newline at end of file diff --git a/lib/Definitions.php b/lib/Definitions.php index bcf8f179..ed1639f6 100644 --- a/lib/Definitions.php +++ b/lib/Definitions.php @@ -24,7 +24,6 @@ use function DI\get; use function DI\object; -use Interop\Container\ContainerInterface; return [ \Klein\Klein::class => object(\Klein\Klein::class), @@ -33,13 +32,15 @@ return [ ->constructor(object(\SP\Storage\XmlHandler::class) ->constructor(CONFIG_FILE)), \SP\Core\Language::class => object(\SP\Core\Language::class), - \SP\Config\ConfigData::class => function (ContainerInterface $c) { - $config = $c->get(\SP\Config\Config::class); - + \SP\Config\ConfigData::class => function (\SP\Config\Config $config) { return $config->getConfigData(); }, + \SP\Storage\DatabaseConnectionData::class => function (\SP\Config\ConfigData $configData) { + return \SP\Storage\DatabaseConnectionData::getFromConfig($configData); + }, \SP\Storage\Database::class => object(\SP\Storage\Database::class) - ->constructor(object(\SP\Storage\MySQLHandler::class)), + ->constructor(object(\SP\Storage\MySQLHandler::class) + ->constructor(get(\SP\Storage\DatabaseConnectionData::class))), \SP\Core\Acl\Actions::class => object(\SP\Core\Acl\Actions::class) ->constructor(object(\SP\Storage\FileCache::class), object(\SP\Storage\XmlHandler::class) ->constructor(ACTIONS_FILE)), diff --git a/lib/SP/Bootstrap.php b/lib/SP/Bootstrap.php index b4368939..94c84bcb 100644 --- a/lib/SP/Bootstrap.php +++ b/lib/SP/Bootstrap.php @@ -74,6 +74,11 @@ class Bootstrap { use InjectableTrait; + /** + * Partial initialized controllers + */ + const PARTIAL_INIT = ['resource', 'install', 'bootstrap']; + /** * @var string The installation path on the server (e.g. /srv/www/syspass) */ @@ -223,7 +228,7 @@ class Bootstrap throw new RuntimeException("Oops, it looks like this content doesn't exist...\n"); } - $self->initialize(); + $self->initialize(in_array($controller, self::PARTIAL_INIT, true)); debugLog('Routing call: ' . $controllerClass . '::' . $method . '::' . print_r($params, true)); @@ -251,12 +256,16 @@ class Bootstrap /** * Inicializar la aplicación * + * @param bool $isPartial Do not perform a full initialization + * @throws ConfigException + * @throws InitializationException * @throws SPException * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface */ - protected function initialize() + protected function initialize($isPartial = false) { - debugLog('Initializing ...'); + debugLog('Initializing...'); self::$checkPhpVersion = Checks::checkPhpVersion(); @@ -277,7 +286,7 @@ class Bootstrap if (!self::$checkPhpVersion) { throw new InitializationException( - __u('Versión de PHP requerida >= ') . ' 5.6.0 <= 7.0', + sprintf(__u('Versión de PHP requerida >= %s <= %s'), '5.6', '7.0'), SPException::ERROR, __u('Actualice la versión de PHP para que la aplicación funcione correctamente') ); @@ -315,43 +324,39 @@ class Bootstrap // Comprobar si es necesario cambiar a HTTPS HttpUtil::checkHttps(); - // Comprobar si es necesario inicialización - if ((defined('IS_INSTALLER') || defined('IS_UPGRADE')) - && Checks::isAjax($this->router) - ) { - return; - } + if ($isPartial === false) { - // Comprobar si está instalado - $this->checkInstalled(); + // Comprobar si está instalado + $this->checkInstalled(); - // Comprobar si el modo mantenimiento está activado - $this->checkMaintenanceMode(); + // Comprobar si el modo mantenimiento está activado + $this->checkMaintenanceMode(); - // Comprobar si la Base de datos existe - DBUtil::checkDatabaseExist(self::$container->get(Database::class), $this->configData->getDbName()); + // Comprobar si la Base de datos existe + DBUtil::checkDatabaseExist(self::$container->get(Database::class)->getDbHandler(), $this->configData->getDbName()); - // Comprobar si es necesario actualizar componentes + // Comprobar si es necesario actualizar componentes // $this->checkUpgrade(); - // Inicializar la sesión - $this->initUserSession(); + // Inicializar la sesión + $this->initUserSession(); - // Cargar los plugins - PluginUtil::loadPlugins(); + // Cargar los plugins + PluginUtil::loadPlugins(); - // Comprobar acciones en URL + // Comprobar acciones en URL // $this->checkPreLoginActions(); - if ($this->session->isLoggedIn() && $this->session->getAuthCompleted() === true) { - $browser = new Browser(); + if ($this->session->isLoggedIn() && $this->session->getAuthCompleted() === true) { + $browser = new Browser(); - // Comprobar si se ha identificado mediante el servidor web y el usuario coincide - if ($browser->checkServerAuthUser($this->session->getUserData()->getLogin()) === false - && $browser->checkServerAuthUser($this->session->getUserData()->getSsoLogin()) === false - ) { - throw new InitializationException('Logout'); + // Comprobar si se ha identificado mediante el servidor web y el usuario coincide + if ($browser->checkServerAuthUser($this->session->getUserData()->getLogin()) === false + && $browser->checkServerAuthUser($this->session->getUserData()->getSsoLogin()) === false + ) { + throw new InitializationException('Logout'); // $this->goLogout(); + } } } } @@ -524,7 +529,11 @@ class Bootstrap private function checkInstalled() { // Redirigir al instalador si no está instalada - if (!$this->configData->isInstalled()) { + if (!$this->configData->isInstalled() + && $this->router->request()->param('r') !== 'install/index' + ) { + $this->router->response()->redirect('index.php?r=install/index')->send(); + throw new InitializationException('Not installed'); // if (self::$SUBURI !== '/index.php') { @@ -664,8 +673,8 @@ class Bootstrap * Devuelve un error utilizando la plantilla de error o en formato JSON * * @param string $message con la descripción del error - * @param string $hint opcional, con una ayuda sobre el error - * @param bool $headers + * @param string $hint opcional, con una ayuda sobre el error + * @param bool $headers */ public static function initError($message, $hint = '', $headers = false) { @@ -728,11 +737,11 @@ class Bootstrap } /** - * @param Config $config - * @param Upgrade $upgrade - * @param Session $session - * @param Theme $theme - * @param Klein $router + * @param Config $config + * @param Upgrade $upgrade + * @param Session $session + * @param Theme $theme + * @param Klein $router * @param Language $language */ public function inject(Config $config, diff --git a/lib/SP/Config/ConfigData.php b/lib/SP/Config/ConfigData.php index a3ee7890..66fb662e 100644 --- a/lib/SP/Config/ConfigData.php +++ b/lib/SP/Config/ConfigData.php @@ -36,7 +36,7 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $upgradeKey = ''; + private $upgradeKey; /** * @var bool */ @@ -44,31 +44,31 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $dokuwikiUrl = ''; + private $dokuwikiUrl; /** * @var string */ - private $dokuwikiUrlBase = ''; + private $dokuwikiUrlBase; /** * @var string */ - private $dokuwikiUser = ''; + private $dokuwikiUser; /** * @var string */ - private $dokuwikiPass = ''; + private $dokuwikiPass; /** * @var string */ - private $dokuwikiNamespace = ''; + private $dokuwikiNamespace; /** * @var int */ - private $ldapDefaultGroup = 0; + private $ldapDefaultGroup; /** * @var int */ - private $ldapDefaultProfile = 0; + private $ldapDefaultProfile; /** * @var bool */ @@ -76,7 +76,7 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $proxyServer = ''; + private $proxyServer; /** * @var int */ @@ -84,11 +84,11 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $proxyUser = ''; + private $proxyUser; /** * @var string */ - private $proxyPass = ''; + private $proxyPass; /** * @var int */ @@ -120,11 +120,11 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $configHash = ''; + private $configHash; /** * @var string */ - private $dbHost = ''; + private $dbHost; /** * @var string */ @@ -132,15 +132,15 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $dbName = ''; + private $dbName; /** * @var string */ - private $dbPass = ''; + private $dbPass; /** * @var string */ - private $dbUser = ''; + private $dbUser; /** * @var int */ @@ -176,19 +176,19 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $ldapBase = ''; + private $ldapBase; /** * @var string */ - private $ldapBindUser = ''; + private $ldapBindUser; /** * @var string */ - private $ldapBindPass = ''; + private $ldapBindPass; /** * @var string */ - private $ldapProxyUser = ''; + private $ldapProxyUser; /** * @var bool */ @@ -200,15 +200,15 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $ldapGroup = ''; + private $ldapGroup; /** * @var string */ - private $ldapServer = ''; + private $ldapServer; /** * @var string */ - private $ldapUserattr = ''; + private $ldapUserattr; /** * @var bool */ @@ -224,11 +224,11 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $mailFrom = ''; + private $mailFrom ; /** * @var string */ - private $mailPass = ''; + private $mailPass; /** * @var int */ @@ -240,15 +240,15 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $mailSecurity = ''; + private $mailSecurity; /** * @var string */ - private $mailServer = ''; + private $mailServer; /** * @var string */ - private $mailUser = ''; + private $mailUser; /** * @var bool */ @@ -256,7 +256,7 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $passwordSalt = ''; + private $passwordSalt; /** * @var bool */ @@ -268,7 +268,7 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $siteLang = ''; + private $siteLang; /** * @var string */ @@ -276,7 +276,7 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $configVersion = ''; + private $configVersion; /** * @var bool */ @@ -288,11 +288,11 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $wikiPageurl = ''; + private $wikiPageurl; /** * @var string */ - private $wikiSearchurl = ''; + private $wikiSearchurl; /** * @var int */ @@ -304,11 +304,11 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $backup_hash = ''; + private $backup_hash; /** * @var string */ - private $export_hash = ''; + private $export_hash; /** * @var bool */ @@ -324,7 +324,7 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $syslogServer = ''; + private $syslogServer; /** * @var int */ @@ -336,7 +336,7 @@ class ConfigData implements JsonSerializable /** * @var string */ - private $configSaver = ''; + private $configSaver; /** * @var bool */ @@ -360,11 +360,11 @@ class ConfigData implements JsonSerializable /** * @var int */ - private $ssoDefaultGroup = 0; + private $ssoDefaultGroup; /** * @var int */ - private $ssoDefaultProfile = 0; + private $ssoDefaultProfile; /** * @return boolean diff --git a/lib/SP/Controller/ControllerBase.php b/lib/SP/Controller/ControllerBase.php index 239819cf..6eadd863 100644 --- a/lib/SP/Controller/ControllerBase.php +++ b/lib/SP/Controller/ControllerBase.php @@ -40,7 +40,6 @@ use SP\DataModel\ProfileData; use SP\Http\JsonResponse; use SP\Mvc\View\Template; use SP\Services\User\UserLoginResponse; -use SP\Storage\Database; use SP\Util\Checks; use SP\Util\Json; use SP\Util\Util; @@ -87,8 +86,6 @@ abstract class ControllerBase protected $config; /** @var Session */ protected $session; - /** @var Database */ - protected $db; /** @var Theme */ protected $theme; /** @var \SP\Core\Acl\Acl */ @@ -103,6 +100,7 @@ abstract class ControllerBase * * @param $actionName * @throws \SP\Core\Dic\ContainerException + * @throws \ReflectionException */ public function __construct($actionName) { @@ -135,9 +133,6 @@ abstract class ControllerBase $this->view->assign('timeStart', $_SERVER['REQUEST_TIME_FLOAT']); $this->view->assign('icons', $this->icons); $this->view->assign('SessionUserData', $this->userData); - -// $this->view->assign('actionId', Request::analyze('actionId', 0)); -// $this->view->assign('id', Request::analyze('itemId', 0)); $this->view->assign('queryTimeStart', microtime()); $this->view->assign('userId', $this->userData->getId()); $this->view->assign('userGroupId', $this->userData->getUserGroupId()); @@ -150,18 +145,16 @@ abstract class ControllerBase /** * @param Config $config * @param Session $session - * @param Database $db * @param Theme $theme * @param EventDispatcher $ev * @param Acl $acl * @param Klein $router */ - public function inject(Config $config, Session $session, Database $db, Theme $theme, EventDispatcher $ev, Acl $acl, Klein $router) + public function inject(Config $config, Session $session, Theme $theme, EventDispatcher $ev, Acl $acl, Klein $router) { $this->config = $config; $this->configData = $config->getConfigData(); $this->session = $session; - $this->db = $db; $this->theme = $theme; $this->eventDispatcher = $ev; $this->acl = $acl; diff --git a/lib/SP/Core/Crypt/Crypt.php b/lib/SP/Core/Crypt/Crypt.php index 9d26e399..f42846b8 100644 --- a/lib/SP/Core/Crypt/Crypt.php +++ b/lib/SP/Core/Crypt/Crypt.php @@ -50,7 +50,7 @@ class Crypt try { if ($securedKey instanceof Key) { $key = $securedKey; - } elseif (!empty($password)) { + } elseif (null !== $password) { $key = self::unlockSecuredKey($securedKey, $password, false); } else { $key = Key::loadFromAsciiSafeString($securedKey); @@ -100,7 +100,7 @@ class Crypt try { if ($securedKey instanceof Key) { $key = $securedKey; - } elseif (!empty($password) && $securedKey instanceof KeyProtectedByPassword) { + } elseif (null !== $password && $securedKey instanceof KeyProtectedByPassword) { $key = self::unlockSecuredKey($securedKey, $password); } else { $key = Key::loadFromAsciiSafeString($securedKey); @@ -120,7 +120,7 @@ class Crypt * * @param string $password * @param bool $useAscii - * @return string|Key + * @return string|KeyProtectedByPassword * @throws CryptoException */ public static function makeSecuredKey($password, $useAscii = true) diff --git a/lib/SP/Core/Install/DatabaseSetupInterface.php b/lib/SP/Core/Install/DatabaseSetupInterface.php new file mode 100644 index 00000000..aa40ef9d --- /dev/null +++ b/lib/SP/Core/Install/DatabaseSetupInterface.php @@ -0,0 +1,79 @@ +. + */ + +namespace SP\Core\Install; + +/** + * Interface DatabaseInterface + * + * @package SP\Core\Install + */ +interface DatabaseSetupInterface +{ + /** + * Conectar con la BBDD + * + * Comprobar si la conexión con la base de datos para sysPass es posible con + * los datos facilitados. + */ + public function connectDatabase(); + + /** + * @return mixed + */ + public function setupDbUser(); + + /** + * Crear el usuario para conectar con la base de datos. + * Esta función crea el usuario para conectar con la base de datos. + */ + public function createDBUser(); + + /** + * Crear la base de datos + */ + public function createDatabase(); + + /** + * @return mixed + */ + public function checkDatabaseExist(); + + /** + * Deshacer la instalación en caso de fallo. + * Esta función elimina la base de datos y el usuario de sysPass + */ + public function rollback(); + + /** + * Crear la estructura de la base de datos. + * Esta función crea la estructura de la base de datos a partir del archivo dbsctructure.sql. + */ + public function createDBStructure(); + + /** + * Comprobar la conexión a la BBDD + */ + public function checkConnection(); +} \ No newline at end of file diff --git a/lib/SP/Core/Install/Installer.php b/lib/SP/Core/Install/Installer.php new file mode 100644 index 00000000..7900643f --- /dev/null +++ b/lib/SP/Core/Install/Installer.php @@ -0,0 +1,389 @@ +. + */ + +namespace SP\Core\Install; + +use SP\Config\Config; +use SP\Config\ConfigData; +use SP\Core\Crypt\Hash; +use SP\Core\Dic; +use SP\Core\Exceptions\InvalidArgumentException; +use SP\Core\Exceptions\SPException; +use SP\Core\Traits\InjectableTrait; +use SP\DataModel\InstallData; +use SP\DataModel\UserData; +use SP\DataModel\UserGroupData; +use SP\DataModel\UserProfileData; +use SP\Services\Config\ConfigService; +use SP\Services\User\UserService; +use SP\Services\UserGroup\UserGroupService; +use SP\Services\UserProfile\UserProfileService; +use SP\Storage\DatabaseConnectionData; +use SP\Util\Util; + +defined('APP_ROOT') || die(); + +/** + * Esta clase es la encargada de instalar sysPass. + */ +class Installer +{ + use InjectableTrait; + + /** + * Versión y número de compilación de sysPass + */ + const VERSION = [2, 2, 0]; + const BUILD = 17050101; + /** + * @var Config + */ + protected $config; + /** + * @var ConfigService + */ + protected $configService; + /** + * @var UserService + */ + protected $userService; + /** + * @var UserGroupService + */ + protected $userGroupService; + /** + * @var UserProfileService + */ + protected $userProfileService; + /** + * @var DatabaseSetupInterface + */ + protected $dbs; + /** + * @var DatabaseConnectionData $databaseConnectionData + */ + protected $databaseConnectionData; + /** + * @var InstallData + */ + private $installData; + /** + * @var ConfigData + */ + private $configData; + + /** + * Installer constructor. + * + * @param InstallData $installData + * @throws Dic\ContainerException + * @throws \ReflectionException + */ + public function __construct(InstallData $installData) + { + $this->injectDependencies(); + + $this->installData = $installData; + } + + /** + * @param InstallData $installData + * @return static + * @throws Dic\ContainerException + * @throws InvalidArgumentException + * @throws SPException + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface + * @throws \ReflectionException + */ + public static function run(InstallData $installData) + { + $installer = new static($installData); + $installer->checkData(); + $installer->install(); + + return $installer; + } + + /** + * @throws InvalidArgumentException + */ + public function checkData() + { + if (!$this->installData->getAdminLogin()) { + throw new InvalidArgumentException( + __u('Indicar nombre de usuario admin'), + SPException::ERROR, + __u('Usuario admin para acceso a la aplicación')); + } + + if (!$this->installData->getAdminPass()) { + throw new InvalidArgumentException( + __u('Indicar la clave de admin'), + SPException::ERROR, + __u('Clave del usuario admin de la aplicación')); + } + + if (!$this->installData->getMasterPassword()) { + throw new InvalidArgumentException( + __u('Indicar la clave maestra'), + SPException::ERROR, + __u('Clave maestra para encriptar las claves')); + } + + if (strlen($this->installData->getMasterPassword()) < 11) { + throw new InvalidArgumentException( + __u('Clave maestra muy corta'), + SPException::CRITICAL, + __u('La longitud de la clave maestra ha de ser mayor de 11 caracteres')); + } + + if (!$this->installData->getDbAdminUser()) { + throw new InvalidArgumentException( + __u('Indicar el usuario de la BBDD'), + SPException::CRITICAL, + __u('Usuario con permisos de administrador de la Base de Datos')); + } + + if (!$this->installData->getDbAdminPass()) { + throw new InvalidArgumentException( + __u('Indicar la clave de la BBDD'), + SPException::ERROR, + __u('Clave del usuario administrador de la Base de Datos')); + } + + if (!$this->installData->getDbName()) { + throw new InvalidArgumentException( + __u('Indicar el nombre de la BBDD'), + SPException::ERROR, + __u('Nombre para la BBDD de la aplicación pej. syspass')); + } + + if (substr_count($this->installData->getDbName(), '.') >= 1) { + throw new InvalidArgumentException( + __u('El nombre de la BBDD no puede contener "."'), + SPException::CRITICAL, + __u('Elimine los puntos del nombre de la Base de Datos')); + } + + if (!$this->installData->getDbHost()) { + throw new InvalidArgumentException( + __u('Indicar el servidor de la BBDD'), + SPException::ERROR, + __u('Servidor donde se instalará la Base de Datos')); + } + } + + /** + * Iniciar instalación. + * + * @throws SPException + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface + * @throws \ReflectionException + */ + public function install() + { + $this->setupDbHost(); + $this->setupConfig(); + $this->setupDb(); + + $this->setupDBConnectionData(); + $this->saveMasterPassword(); + $this->createAdminAccount(); + + $this->configService->create(new \SP\DataModel\ConfigData('version', Util::getVersionStringNormalized())); + + $this->configData->setInstalled(true); + $this->config->saveConfig($this->configData, false); + } + + /** + * Setup database connection data + */ + private function setupDbHost() + { + if (preg_match('/^(?:(?P.*):(?P\d{1,5}))|^(?:unix:(?P.*))/', $this->installData->getDbHost(), $match)) { + if (!empty($match['socket'])) { + $this->installData->setDbSocket($match['socket']); + } else { + $this->installData->setDbHost($match['host']); + $this->installData->setDbPort($match['port']); + } + } else { + $this->installData->setDbPort(3306); + } + + if (strpos('localhost', $this->installData->getDbHost()) === false + && strpos('127.0.0.1', $this->installData->getDbHost()) === false + ) { + $this->installData->setDbAuthHost($_SERVER['SERVER_ADDR']); + $this->installData->setDbAuthHostDns(gethostbyaddr($_SERVER['SERVER_ADDR'])); + } else { + $this->installData->setDbAuthHost('localhost'); + } + } + + /** + * Setup sysPass config data + * + * @throws \Defuse\Crypto\Exception\EnvironmentIsBrokenException + */ + private function setupConfig() + { + // Generate a random salt that is used to salt the local user passwords + $this->configData->setPasswordSalt(Util::generateRandomBytes(30)); + $this->configData->setConfigVersion(Util::getVersionStringNormalized()); + + // Set DB connection info + $this->configData->setDbHost($this->installData->getDbHost()); + $this->configData->setDbSocket($this->installData->getDbSocket()); + $this->configData->setDbPort($this->installData->getDbPort()); + $this->configData->setDbName($this->installData->getDbName()); + + // Set site config + $this->configData->setSiteLang($this->installData->getSiteLang()); + } + + /** + * Setup database connection for sysPass + */ + private function setupDBConnectionData() + { + // FIXME: ugly!! + $this->databaseConnectionData->refreshFromConfig($this->configData); + } + + /** + * @throws Dic\ContainerException + * @throws SPException + * @throws \ReflectionException + */ + private function setupDb() + { + $this->dbs = new MySQL($this->installData); + + // Si no es modo hosting se crea un hash para la clave y un usuario con prefijo "sp_" para la DB + if ($this->installData->isHostingMode()) { + // Guardar el usuario/clave de conexión a la BD + $this->configData->setDbUser($this->installData->getDbAdminUser()); + $this->configData->setDbPass($this->installData->getDbAdminPass()); + } else { + $this->dbs->setupDbUser(); + } + + $this->dbs->createDatabase(); + $this->dbs->createDBStructure(); + $this->dbs->checkConnection(); + } + + /** + * Saves the master password metadata + * + * @throws SPException + */ + private function saveMasterPassword() + { + try { + $this->configService->create(new \SP\DataModel\ConfigData('masterPwd', Hash::hashKey($this->installData->getMasterPassword()))); + $this->configService->create(new \SP\DataModel\ConfigData('lastupdatempass', time())); + } catch (\Exception $e) { + $this->dbs->rollback(); + + throw new SPException( + $e->getMessage(), + SPException::CRITICAL, + __u('Informe al desarrollador') + ); + } + } + + /** + * Crear el usuario admin de sysPass. + * Esta función crea el grupo, perfil y usuario 'admin' para utilizar sysPass. + * + * @throws SPException + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface + */ + private function createAdminAccount() + { + try { + $userGroupData = new UserGroupData(); + $userGroupData->setName('Admins'); + $userGroupData->setDescription('sysPass Admins'); + + $userProfileData = new UserProfileData(); + $userProfileData->setName('Admin'); + + // Datos del usuario + $userData = new UserData(); + $userData->setUserGroupId($this->userGroupService->create($userGroupData)); + $userData->setUserProfileId($this->userProfileService->create($userProfileData)); + $userData->setLogin($this->installData->getAdminLogin()); + $userData->setPass(Hash::hashKey($this->installData->getAdminPass())); + $userData->setName('sysPass Admin'); + $userData->setIsAdminApp(1); + + $this->userService->createWithMasterPass($userData, $this->installData->getMasterPassword()); + +// __u('Error al actualizar la clave maestra del usuario "admin"'), + } catch (\Exception $e) { + $this->dbs->rollback(); + + throw new SPException( + $e->getMessage(), + SPException::CRITICAL, + __u('Informe al desarrollador') + ); + } + } + + /** + * @param Config $config + * @param ConfigService $configService + * @param UserService $userService + * @param UserGroupService $userGroupService + * @param UserProfileService $userProfileService + * @param DatabaseConnectionData $databaseConnectionData + */ + public function inject(Config $config, + ConfigService $configService, + UserService $userService, + UserGroupService $userGroupService, + UserProfileService $userProfileService, + DatabaseConnectionData $databaseConnectionData) + { + $this->config = $config; + $this->configData = $config->getConfigData(); + $this->configService = $configService; + $this->userService = $userService; + $this->userGroupService = $userGroupService; + $this->userProfileService = $userProfileService; + $this->databaseConnectionData = $databaseConnectionData; + } +} \ No newline at end of file diff --git a/lib/SP/Core/Install/MySQL.php b/lib/SP/Core/Install/MySQL.php new file mode 100644 index 00000000..2b19cf19 --- /dev/null +++ b/lib/SP/Core/Install/MySQL.php @@ -0,0 +1,347 @@ +. + */ + +namespace SP\Core\Install; + +use PDOException; +use SP\Config\Config; +use SP\Config\ConfigData; +use SP\Core\Exceptions\SPException; +use SP\Core\Traits\InjectableTrait; +use SP\DataModel\InstallData; +use SP\Storage\DatabaseConnectionData; +use SP\Storage\DBUtil; +use SP\Storage\MySQLHandler; +use SP\Util\Util; + +/** + * Class MySQL + * + * @package SP\Core\Install + */ +class MySQL implements DatabaseSetupInterface +{ + use InjectableTrait; + + /** + * @var InstallData + */ + protected $installData; + /** + * @var MySQLHandler + */ + protected $dbs; + /** + * @var ConfigData + */ + protected $configData; + + /** + * MySQL constructor. + * + * @param InstallData $installData + * @throws SPException + * @throws \ReflectionException + * @throws \SP\Core\Dic\ContainerException + */ + public function __construct(InstallData $installData) + { + $this->injectDependencies(); + + $this->installData = $installData; + + $this->connectDatabase(); + } + + /** + * Conectar con la BBDD + * + * Comprobar si la conexión con la base de datos para sysPass es posible con + * los datos facilitados. + * + * @throws SPException + */ + public function connectDatabase() + { + try { + $dbc = (new DatabaseConnectionData()) + ->setDbHost($this->installData->getDbHost()) + ->setDbPort($this->installData->getDbPort()) + ->setDbSocket($this->installData->getDbSocket()) + ->setDbUser($this->installData->getDbAdminUser()) + ->setDbPass($this->installData->getDbAdminPass()); + + $this->dbs = new MySQLHandler($dbc); + $this->dbs->getConnectionSimple(); + } catch (SPException $e) { + throw new SPException( + __u('No es posible conectar con la BD'), + SPException::CRITICAL, + __('Compruebe los datos de conexión') . '
' . $e->getHint() + ); + } + } + + /** + * @param Config $config + */ + public function inject(Config $config) + { + $this->configData = $config->getConfigData(); + } + + /** + * @throws SPException + */ + public function setupDbUser() + { + $this->installData->setDbPass(Util::randomPassword()); + $this->installData->setDbUser(substr(uniqid('sp_'), 0, 16)); + + // Comprobar si el usuario sumistrado existe + $query = /** @lang SQL */ + 'SELECT COUNT(*) FROM mysql.user WHERE user = ? AND `host` = ?'; + + try { + $sth = $this->dbs->getConnectionSimple()->prepare($query); + $sth->execute([$this->installData->getDbUser(), $this->installData->getDbAuthHost()]); + + // Si no existe el usuario, se intenta crear + if ((int)$sth->fetchColumn() === 0 + // Se comprueba si el nuevo usuario es distinto del creado en otra instalación + && $this->installData->getDbUser() !== $this->configData->getDbUser() + ) { + $this->createDBUser(); + } + } catch (PDOException $e) { + throw new SPException( + sprintf(__('No es posible comprobar el usuario de sysPass (%s)'), $this->installData->getAdminLogin()), + SPException::CRITICAL, + __u('Compruebe los permisos del usuario de conexión a la BD') + ); + } + + // Guardar el nuevo usuario/clave de conexión a la BD + $this->configData->setDbUser($this->installData->getDbUser()); + $this->configData->setDbPass($this->installData->getDbPass()); + } + + /** + * Crear el usuario para conectar con la base de datos. + * Esta función crea el usuario para conectar con la base de datos. + * + * @throws SPException + */ + public function createDBUser() + { + if ($this->installData->isHostingMode()) { + return; + } + + $query = /** @lang SQL */ + 'CREATE USER `' . $this->installData->getDbUser() . '`@`' . $this->installData->getDbAuthHost() . '` IDENTIFIED BY \'' . $this->installData->getDbPass() . '\''; + + $queryDns = /** @lang SQL */ + 'CREATE USER `' . $this->installData->getDbUser() . '`@`' . $this->installData->getDbAuthHostDns() . '` IDENTIFIED BY \'' . $this->installData->getDbPass() . '\''; + + try { + $dbc = $this->dbs->getConnectionSimple(); + + $dbc->exec($query); + $dbc->exec($queryDns); + $dbc->exec('FLUSH PRIVILEGES'); + } catch (PDOException $e) { + throw new SPException( + sprintf(__u('Error al crear el usuario de conexión a MySQL \'%s\''), $this->installData->getDbUser()), + SPException::CRITICAL, $e->getMessage() + ); + } + } + + /** + * Crear la base de datos + * + * @throws SPException + */ + public function createDatabase() + { + $checkDatabase = $this->checkDatabaseExist(); + + if ($checkDatabase && !$this->installData->isHostingMode()) { + throw new SPException( + __u('La BBDD ya existe'), + SPException::ERROR, + __u('Indique una nueva Base de Datos o elimine la existente') + ); + } + + if (!$checkDatabase && $this->installData->isHostingMode()) { + throw new SPException( + __u('La BBDD no existe'), + SPException::ERROR, + __u('Es necesario crearla y asignar los permisos necesarios') + ); + } + + if (!$this->installData->isHostingMode()) { + + try { + $dbc = $this->dbs->getConnectionSimple(); + + $dbc->exec(/** @lang SQL */ + 'CREATE SCHEMA `' . $this->installData->getDbName() . '` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci'); + } catch (PDOException $e) { + throw new SPException( + sprintf(__('Error al crear la BBDD (\'%s\')'), $e->getMessage()), + SPException::CRITICAL, + __u('Verifique los permisos del usuario de la Base de Datos')); + } + + $query = /** @lang SQL */ + 'GRANT ALL PRIVILEGES ON `' . $this->installData->getDbName() . '`.* + TO `' . $this->installData->getDbUser() . '`@`' . $this->installData->getDbAuthHost() . '`'; + + $queryDns = /** @lang SQL */ + 'GRANT ALL PRIVILEGES ON `' . $this->installData->getDbName() . '`.* + TO `' . $this->installData->getDbUser() . '`@`' . $this->installData->getDbAuthHostDns() . '`'; + + try { + $dbc->exec($query); + $dbc->exec($queryDns); + $dbc->exec('FLUSH PRIVILEGES'); + } catch (PDOException $e) { + $this->rollback(); + + throw new SPException( + sprintf(__('Error al establecer permisos de la BBDD (\'%s\')'), $e->getMessage()), + SPException::CRITICAL, + __u('Verifique los permisos del usuario de la Base de Datos') + ); + } + } + } + + /** + * @return bool + * @throws SPException + */ + public function checkDatabaseExist() + { + $query = /** @lang SQL */ + 'SELECT COUNT(*) FROM information_schema.schemata WHERE `schema_name` = ? LIMIT 1'; + + $sth = $this->dbs->getConnectionSimple()->prepare($query); + $sth->execute([$this->installData->getDbName()]); + + return ((int)$sth->fetchColumn() > 0); + } + + /** + * @throws SPException + */ + public function rollback() + { + $dbc = $this->dbs->getConnectionSimple(); + + $dbc->exec('DROP DATABASE IF EXISTS `' . $this->installData->getDbName() . '`'); + $dbc->exec('DROP USER `' . $this->installData->getDbUser() . '`@`' . $this->installData->getDbAuthHost() . '`'); + $dbc->exec('DROP USER `' . $this->installData->getDbUser() . '`@`' . $this->installData->getDbAuthHostDns() . '`'); +// $this->DB->exec('DROP USER `' . $this->InstallData->getDbUser() . '`@`%`'); + + debugLog('Rollback'); + } + + /** + * @throws SPException + */ + public function createDBStructure() + { + $fileName = SQL_PATH . DIRECTORY_SEPARATOR . 'dbstructure.sql'; + + if (!file_exists($fileName)) { + throw new SPException( + __u('El archivo de estructura de la BBDD no existe'), + SPException::CRITICAL, + __u('No es posible crear la BBDD de la aplicación. Descárguela de nuevo.') + ); + } + + try { + $dbc = $this->dbs->getConnectionSimple(); + + // Usar la base de datos de sysPass + $dbc->exec('USE `' . $this->installData->getDbName() . '`'); + } catch (PDOException $e) { + throw new SPException( + sprintf(__('Error al seleccionar la BBDD') . ' \'%s\' (%s)', $this->installData->getDbName(), $e->getMessage()), + SPException::CRITICAL, + __u('No es posible usar la Base de Datos para crear la estructura. Compruebe los permisos y que no exista.') + ); + } + + // Leemos el archivo SQL para crear las tablas de la BBDD + $handle = fopen($fileName, 'rb'); + + if ($handle) { + while (!feof($handle)) { + $buffer = stream_get_line($handle, 1000000, ";\n"); + + if (strlen(trim($buffer)) > 0 && strpos($buffer, '--') !== 0) { + try { + $query = str_replace("\n", '', $buffer); + $dbc->query($query); + } catch (PDOException $e) { + $this->rollback(); + + debugLog($e->getMessage()); + + throw new SPException( + sprintf(__('Error al crear la BBDD (\'%s\')'), $e->getMessage()), + SPException::CRITICAL, + __u('Error al crear la estructura de la Base de Datos.') + ); + } + } + } + } + } + + /** + * Comprobar la conexión a la BBDD + * + * @throws SPException + */ + public function checkConnection() + { + if (!DBUtil::checkDatabaseExist($this->dbs, $this->installData->getDbName())) { + $this->rollback(); + + throw new SPException( + __u('Error al comprobar la base de datos'), + SPException::CRITICAL, + __u('Intente de nuevo la instalación') + ); + } + } +} \ No newline at end of file diff --git a/lib/SP/Core/Installer.php b/lib/SP/Core/Installer.php deleted file mode 100644 index 9604a65e..00000000 --- a/lib/SP/Core/Installer.php +++ /dev/null @@ -1,505 +0,0 @@ -. - */ - -namespace SP\Core; - -use PDO; -use PDOException; -use SP\Config\Config; -use SP\Config\ConfigData; -use SP\Config\ConfigDB; -use SP\Core\Crypt\Hash; -use SP\Core\Exceptions\InvalidArgumentException; -use SP\Core\Exceptions\SPException; -use SP\Core\Traits\InjectableTrait; -use SP\DataModel\InstallData; -use SP\DataModel\ProfileData; -use SP\DataModel\UserGroupData; -use SP\DataModel\UserLoginData; -use SP\Mgmt\Groups\Group; -use SP\Mgmt\Profiles\Profile; -use SP\Mgmt\Users\User; -use SP\Mgmt\Users\UserPass; -use SP\Storage\DBUtil; -use SP\Util\Util; - -defined('APP_ROOT') || die(); - -/** - * Esta clase es la encargada de instalar sysPass. - */ -class Installer -{ - use InjectableTrait; - - /** - * Versión y número de compilación de sysPass - */ - const VERSION = [2, 2, 0]; - const BUILD = 17050101; - /** - * @var Config - */ - protected $Config; - /** - * @var PDO Instancia de conexión a la BD - */ - private $DB; - /** - * @var InstallData - */ - private $InstallData; - /** - * @var ConfigData - */ - private $ConfigData; - - /** - * Installer constructor. - * - * @param InstallData $InstallData - */ - public function __construct(InstallData $InstallData) - { - $this->injectDependencies(); - - $this->InstallData = $InstallData; - } - - /** - * Iniciar instalación. - * - * @return bool - * @throws SPException - */ - public function install() - { - $this->checkData(); - - // Generate a random salt that is used to salt the local user passwords - $this->ConfigData->setPasswordSalt(Util::generateRandomBytes(30)); - $this->ConfigData->setConfigVersion(Util::getVersionStringNormalized()); - - if (preg_match('/unix:(.*)/', $this->InstallData->getDbHost(), $match)) { - $this->InstallData->setDbSocket($match[1]); - } elseif (preg_match('/(.*):(\d{1,5})/', $this->InstallData->getDbHost(), $match)) { - $this->InstallData->setDbHost($match[1]); - $this->InstallData->setDbPort($match[2]); - } else { - $this->InstallData->setDbPort(3306); - } - - if (!preg_match('/(localhost|127.0.0.1)/', $this->InstallData->getDbHost())) { - $this->InstallData->setDbAuthHost($_SERVER['SERVER_ADDR']); - $this->InstallData->setDbAuthHostDns(gethostbyaddr($_SERVER['SERVER_ADDR'])); - } else { - $this->InstallData->setDbAuthHost('localhost'); - } - - // Set DB connection info - $this->ConfigData->setDbHost($this->InstallData->getDbHost()); - $this->ConfigData->setDbSocket($this->InstallData->getDbSocket()); - $this->ConfigData->setDbPort($this->InstallData->getDbPort()); - $this->ConfigData->setDbName($this->InstallData->getDbName()); - - // Set site config - $this->ConfigData->setSiteLang($this->InstallData->getSiteLang()); - - $this->connectDatabase(); - $this->setupMySQLDatabase(); - $this->checkConnection(); - $this->createAdminAccount(); - - ConfigDB::setValue('version', Util::getVersionStringNormalized()); - - $this->ConfigData->setInstalled(true); - $this->Config->saveConfig($this->ConfigData); - - return true; - } - - /** - * @throws InvalidArgumentException - */ - public function checkData() - { - if (!$this->InstallData->getAdminLogin()) { - throw new InvalidArgumentException( - SPException::CRITICAL, - __('Indicar nombre de usuario admin', false), - __('Usuario admin para acceso a la aplicación', false)); - } - - if (!$this->InstallData->getAdminPass()) { - throw new InvalidArgumentException( - SPException::CRITICAL, - __('Indicar la clave de admin', false), - __('Clave del usuario admin de la aplicación', false)); - } - - if (!$this->InstallData->getMasterPassword()) { - throw new InvalidArgumentException( - SPException::CRITICAL, - __('Indicar la clave maestra', false), - __('Clave maestra para encriptar las claves', false)); - } - - if (strlen($this->InstallData->getMasterPassword()) < 11) { - throw new InvalidArgumentException( - SPException::CRITICAL, - __('Clave maestra muy corta', false), - __('La longitud de la clave maestra ha de ser mayor de 11 caracteres', false)); - } - - if (!$this->InstallData->getDbAdminUser()) { - throw new InvalidArgumentException( - SPException::CRITICAL, - __('Indicar el usuario de la BBDD', false), - __('Usuario con permisos de administrador de la Base de Datos', false)); - } - - if (!$this->InstallData->getDbAdminPass()) { - throw new InvalidArgumentException( - SPException::CRITICAL, - __('Indicar la clave de la BBDD'), - __('Clave del usuario administrador de la Base de Datos')); - } - - if (!$this->InstallData->getDbName()) { - throw new InvalidArgumentException( - SPException::CRITICAL, - __('Indicar el nombre de la BBDD', false), - __('Nombre para la BBDD de la aplicación pej. syspass', false)); - } - - if (substr_count($this->InstallData->getDbName(), '.') >= 1) { - throw new InvalidArgumentException( - SPException::CRITICAL, - __('El nombre de la BBDD no puede contener "."', false), - __('Elimine los puntos del nombre de la Base de Datos', false)); - } - - if (!$this->InstallData->getDbHost()) { - throw new InvalidArgumentException( - SPException::CRITICAL, - __('Indicar el servidor de la BBDD', false), - __('Servidor donde se instalará la Base de Datos', false)); - } - } - - /** - * Conectar con la BBDD. - * Comprobar si la conexión con la base de datos para sysPass es posible con - * los datos facilitados. - * - * @throws SPException - */ - private function connectDatabase() - { - try { - if (null !== $this->InstallData->getDbSocket()) { - $dsn = 'mysql:unix_socket=' . $this->InstallData->getDbSocket() . ';charset=utf8'; - } else { - $dsn = 'mysql:host=' . $this->InstallData->getDbHost() . ';dbport=' . $this->InstallData->getDbPort() . ';charset=utf8'; - } - $this->DB = new PDO($dsn, $this->InstallData->getDbAdminUser(), $this->InstallData->getDbAdminPass()); - $this->DB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - } catch (PDOException $e) { - throw new SPException(__('No es posible conectar con la BD', false), SPException::CRITICAL, __('Compruebe los datos de conexión') . '
' . $e->getMessage()); - } - } - - /** - * Configurar la base de datos. - * Esta función crea la base de datos y el usuario necesario para sysPass. - * - * @throws SPException - */ - private function setupMySQLDatabase() - { - // Si no es modo hosting se crea un hash para la clave y un usuario con prefijo "sp_" para la DB - if (!$this->InstallData->isHostingMode()) { - $this->InstallData->setDbPass(Util::randomPassword()); - $this->InstallData->setDbUser(substr('sp_' . $this->InstallData->getAdminLogin(), 0, 16)); - - // Comprobar si el usuario sumistrado existe - $query = /** @lang SQL */ - 'SELECT COUNT(*) FROM mysql.user WHERE user = ? AND host = ?'; - - try { - $sth = $this->DB->prepare($query); - $sth->execute([$this->InstallData->getDbUser(), $this->InstallData->getDbAuthHost()]); - - // Si no existe el usuario, se intenta crear - if ((int)$sth->fetchColumn() === 0 - // Se comprueba si el nuevo usuario es distinto del creado en otra instalación - && $this->InstallData->getDbUser() != $this->ConfigData->getDbUser() - ) { - $this->createDBUser(); - } - } catch (PDOException $e) { - throw new SPException(sprintf(__('No es posible comprobar el usuario de sysPass') . ' (%s)', $this->InstallData->getAdminLogin()), SPException::CRITICAL, __('Compruebe los permisos del usuario de conexión a la BD', false)); - } - - // Guardar el nuevo usuario/clave de conexión a la BD - $this->ConfigData->setDbUser($this->InstallData->getDbUser()); - $this->ConfigData->setDbPass($this->InstallData->getDbPass()); - } else { - // Guardar el usuario/clave de conexión a la BD - $this->ConfigData->setDbUser($this->InstallData->getDbAdminUser()); - $this->ConfigData->setDbPass($this->InstallData->getDbAdminPass()); - } - - try { - $this->createMySQLDatabase(); - $this->createDBStructure(); - } catch (SPException $e) { - throw $e; - } - } - - /** - * Crear el usuario para conectar con la base de datos. - * Esta función crea el usuario para conectar con la base de datos. - * Si se marca en modo hosting, no se crea el usuario. - * - * @throws SPException - */ - private function createDBUser() - { - if ($this->InstallData->isHostingMode()) { - return; - } - - $query = /** @lang SQL */ - 'CREATE USER `' . $this->InstallData->getDbUser() . '`@`' . $this->InstallData->getDbAuthHost() . '` IDENTIFIED BY \'' . $this->InstallData->getDbPass() . '\''; - - $queryDns = /** @lang SQL */ - 'CREATE USER `' . $this->InstallData->getDbUser() . '`@`' . $this->InstallData->getDbAuthHostDns() . '` IDENTIFIED BY \'' . $this->InstallData->getDbPass() . '\''; - - try { - $this->DB->exec($query); - $this->DB->exec($queryDns); - $this->DB->exec('FLUSH PRIVILEGES'); - } catch (PDOException $e) { - throw new SPException( - sprintf(__('Error al crear el usuario de conexión a MySQL \'%s\'', false), $this->InstallData->getDbUser()), SPException::CRITICAL, $e->getMessage()); - } - } - - /** - * Crear la base de datos en MySQL. - * - * @throws SPException - */ - private function createMySQLDatabase() - { - $checkDatabase = $this->checkDatabaseExist(); - - if ($checkDatabase && !$this->InstallData->isHostingMode()) { - throw new SPException(__('La BBDD ya existe', false), SPException::CRITICAL, __('Indique una nueva Base de Datos o elimine la existente', false)); - } elseif (!$checkDatabase && $this->InstallData->isHostingMode()) { - throw new SPException(__('La BBDD no existe', false), SPException::CRITICAL, __('Es necesario crearla y asignar los permisos necesarios', false)); - } - - if (!$this->InstallData->isHostingMode()) { - - try { - $this->DB->exec(/** @lang SQL */ - 'CREATE SCHEMA `' . $this->InstallData->getDbName() . '` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci'); - } catch (PDOException $e) { - throw new SPException(sprintf(__('Error al crear la BBDD') . ' (%s)', $e->getMessage()), SPException::CRITICAL, __('Verifique los permisos del usuario de la Base de Datos', false)); - } - - $query = /** @lang SQL */ - 'GRANT ALL PRIVILEGES ON `' . $this->InstallData->getDbName() . '`.* - TO `' . $this->InstallData->getDbUser() . '`@`' . $this->InstallData->getDbAuthHost() . '`'; - - $queryDns = /** @lang SQL */ - 'GRANT ALL PRIVILEGES ON `' . $this->InstallData->getDbName() . '`.* - TO `' . $this->InstallData->getDbUser() . '`@`' . $this->InstallData->getDbAuthHostDns() . '`'; - - try { - $this->DB->exec($query); - $this->DB->exec($queryDns); - $this->DB->exec('FLUSH PRIVILEGES'); - } catch (PDOException $e) { - $this->rollback(); - - throw new SPException(sprintf(__('Error al establecer permisos de la BBDD (\'%s\')'), $e->getMessage()), SPException::CRITICAL, __('Verifique los permisos del usuario de la Base de Datos', false)); - } - } - } - - /** - * Comprobar si la base de datos indicada existe. - * - * @return bool - */ - private function checkDatabaseExist() - { - $query = /** @lang SQL */ - 'SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name = ? LIMIT 1'; - - $sth = $this->DB->prepare($query); - $sth->execute([$this->InstallData->getDbName()]); - - return ((int)$sth->fetchColumn() > 0); - } - - /** - * Deshacer la instalación en caso de fallo. - * Esta función elimina la base de datos y el usuario de sysPass - */ - private function rollback() - { - try { - $this->DB->exec('DROP DATABASE IF EXISTS `' . $this->InstallData->getDbName() . '`'); - $this->DB->exec('DROP USER `' . $this->InstallData->getDbUser() . '`@`' . $this->InstallData->getDbAuthHost() . '`'); - $this->DB->exec('DROP USER `' . $this->InstallData->getDbUser() . '`@`' . $this->InstallData->getDbAuthHostDns() . '`'); -// $this->DB->exec('DROP USER `' . $this->InstallData->getDbUser() . '`@`%`'); - - debugLog('Rollback'); - - return true; - } catch (PDOException $e) { - debugLog($e->getMessage()); - - return false; - } - } - - /** - * Crear la estructura de la base de datos. - * Esta función crea la estructura de la base de datos a partir del archivo dbsctructure.sql. - * - * @throws SPException - */ - private function createDBStructure() - { - $fileName = SQL_PATH . DIRECTORY_SEPARATOR . 'dbstructure.sql'; - - if (!file_exists($fileName)) { - throw new SPException(__('El archivo de estructura de la BBDD no existe', false), SPException::CRITICAL, __('No es posible crear la BBDD de la aplicación. Descárguela de nuevo.', false)); - } - - try { - // Usar la base de datos de sysPass - $this->DB->exec('USE `' . $this->InstallData->getDbName() . '`'); - } catch (PDOException $e) { - throw new SPException(sprintf(__('Error al seleccionar la BBDD') . ' \'%s\' (%s)', $this->InstallData->getDbName(), $e->getMessage()), SPException::CRITICAL, __('No es posible usar la Base de Datos para crear la estructura. Compruebe los permisos y que no exista.', false)); - } - - // Leemos el archivo SQL para crear las tablas de la BBDD - $handle = fopen($fileName, 'rb'); - - if ($handle) { - while (!feof($handle)) { - $buffer = stream_get_line($handle, 1000000, ";\n"); - if (strlen(trim($buffer)) > 0) { - try { - $query = str_replace("\n", '', $buffer); - $this->DB->query($query); - } catch (PDOException $e) { - $this->rollback(); - - throw new SPException(sprintf(__('Error al crear la BBDD') . ' (%s)', $e->getMessage()), SPException::CRITICAL, __('Error al crear la estructura de la Base de Datos.', false)); - } - } - } - } - } - - /** - * Comprobar la conexión a la BBDD - * - * @throws \SP\Core\Exceptions\SPException - */ - protected function checkConnection() - { - if (!DBUtil::checkDatabaseExist()) { - $this->rollback(); - - throw new SPException(__('Error al comprobar la base de datos', false), SPException::CRITICAL, __('Intente de nuevo la instalación', false)); - } - } - - /** - * Crear el usuario admin de sysPass. - * Esta función crea el grupo, perfil y usuario 'admin' para utilizar sysPass. - * - * @throws SPException - * @throws \SP\Core\Exceptions\InvalidClassException - */ - private function createAdminAccount() - { - try { - $GroupData = new UserGroupData(); - $GroupData->setName('Admins'); - $GroupData->setDescription('sysPass Admins'); - - Group::getItem($GroupData)->add(); - - $ProfileData = new ProfileData(); - $ProfileData->setName('Admin'); - - Profile::getItem($ProfileData)->add(); - - // Datos del usuario - $UserData = new UserLoginData(); - $UserData->setUserGroupId($GroupData->getId()); - $UserData->setUserProfileId($ProfileData->getId()); - $UserData->setLogin($this->InstallData->getAdminLogin()); - $UserData->setLogin($this->InstallData->getAdminLogin()); - $UserData->setPass($this->InstallData->getAdminPass()); - $UserData->setLoginPass($this->InstallData->getAdminPass()); - $UserData->setName('Admin'); - $UserData->setIsAdminApp(1); - - User::getItem($UserData)->add(); - - // Guardar el hash de la clave maestra - ConfigDB::setCacheConfigValue('masterPwd', Hash::hashKey($this->InstallData->getMasterPassword())); - ConfigDB::setCacheConfigValue('lastupdatempass', time()); - ConfigDB::writeConfig(true); - - if (!UserPass::updateUserMPass($this->InstallData->getMasterPassword(), $UserData)) { - throw new SPException(__('Error al actualizar la clave maestra del usuario "admin"', false), SPException::CRITICAL); - } - } catch (\Exception $e) { - $this->rollback(); - throw new SPException($e->getMessage(), SPException::CRITICAL, __('Informe al desarrollador', false)); - } - } - - /** - * @param Config $config - */ - public function inject(Config $config) - { - $this->Config = $config; - $this->ConfigData = $config->getConfigData(); - } -} \ No newline at end of file diff --git a/lib/SP/Core/Upgrade/User.php b/lib/SP/Core/Upgrade/User.php index e98e86ff..509a83d8 100644 --- a/lib/SP/Core/Upgrade/User.php +++ b/lib/SP/Core/Upgrade/User.php @@ -29,7 +29,6 @@ use SP\Core\Exceptions\SPException; use SP\Core\OldCrypt; use SP\Core\TaskFactory; use SP\DataModel\UserLoginData; -use SP\Mgmt\Users\UserPass; use SP\Services\User\UserPassService; use SP\Storage\DbWrapper; use SP\Storage\QueryData; @@ -176,7 +175,7 @@ class User $mKey = OldCrypt::getDecrypt($userLoginData->getUserLoginResponse()->getMPass(), $userLoginData->getUserLoginResponse()->getMKey(), $key); try { - return $mKey && $userPassService->updateMasterPass($mKey, $userLoginData); + return $mKey && $userPassService->updateMasterPassOnLogin($mKey, $userLoginData); } catch (SPException $e) { } catch (CryptoException $e) { } diff --git a/lib/SP/Log/ActionLog.php b/lib/SP/Log/ActionLog.php index 8f265eba..f2509a6b 100644 --- a/lib/SP/Log/ActionLog.php +++ b/lib/SP/Log/ActionLog.php @@ -30,6 +30,7 @@ use SP\Core\Language; use SP\Core\Messages\LogMessage; use SP\Core\Session\Session; use SP\Core\Traits\InjectableTrait; +use SP\Storage\Database; /** * Clase abstracta ActionLog para la gestión de mensajes de eventos @@ -70,6 +71,10 @@ abstract class ActionLog extends LogLevel protected $language; /** @var \SP\Core\Session\Session */ protected $session; + /** + * @var Database + */ + protected $db; /** @@ -91,13 +96,15 @@ abstract class ActionLog extends LogLevel * @param Config $config * @param Language $language * @param Session $session + * @param Database $database */ - public function inject(Config $config, Language $language, Session $session) + public function inject(Config $config, Language $language, Session $session, Database $database) { $this->config = $config; $this->configData = $config->getConfigData(); $this->language = $language; $this->session = $session; + $this->db = $database; } /** diff --git a/lib/SP/Log/Log.php b/lib/SP/Log/Log.php index 5c58d957..9922546d 100644 --- a/lib/SP/Log/Log.php +++ b/lib/SP/Log/Log.php @@ -24,14 +24,10 @@ namespace SP\Log; -use SP\Core\DiFactory; use SP\Core\Exceptions\SPException; -use SP\Core\Language; use SP\Core\Messages\LogMessage; -use SP\Core\SessionFactory; use SP\Storage\DbWrapper; use SP\Storage\QueryData; -use SP\Util\Checks; use SP\Util\HttpUtil; use SP\Util\Util; @@ -84,7 +80,6 @@ class Log extends ActionLog * @return bool con el resultado * @throws \SP\Core\Exceptions\QueryException * @throws \SP\Core\Exceptions\ConstraintException - * @throws \phpmailer\phpmailerException * @throws \SP\Core\Exceptions\SPException */ public static function clearEvents() @@ -105,8 +100,7 @@ class Log extends ActionLog * @param string $description La descripción de la acción realizada * @param string $level * @return Log - * @throws \phpmailer\phpmailerException - * @throws \SP\Core\Exceptions\SPException + * @throws \PHPMailer\PHPMailer\Exception */ public static function writeNewLogAndEmail($action, $description = null, $level = Log::INFO) { @@ -123,6 +117,7 @@ class Log extends ActionLog * @param string $description La descripción de la acción realizada * @param string $level * @return Log + * @throws \SP\Core\Dic\ContainerException */ public static function writeNewLog($action, $description = null, $level = Log::INFO) { @@ -145,9 +140,8 @@ class Log extends ActionLog */ public function writeLog($resetDescription = false, $resetDetails = false) { - if ((defined('IS_INSTALLER') && IS_INSTALLER === 1) - || self::$logDbEnabled === 0 - || DiFactory::getDBStorage()->getDbStatus() === 1 + if (self::$logDbEnabled === 0 + || $this->db->getDbHandler()->getDbStatus() === 1 ) { debugLog('Action: ' . $this->LogMessage->getAction(true) . ' -- Description: ' . $this->LogMessage->getDescription(true) . ' -- Details: ' . $this->LogMessage->getDetails(true)); diff --git a/lib/SP/Mvc/View/Template.php b/lib/SP/Mvc/View/Template.php index 673f009f..6728e8d6 100644 --- a/lib/SP/Mvc/View/Template.php +++ b/lib/SP/Mvc/View/Template.php @@ -66,6 +66,10 @@ class Template * @var string Directorio base para los archivos de plantillas */ private $base; + /** + * @var array + */ + private $contentTemplates = []; /** * @param null $file Archivo de plantilla a añadir @@ -146,7 +150,7 @@ class Template } /** - * Añadir un nuevo archivo de plantilla al array de plantillas de la clase. + * Añadir un nuevo archivo de plantilla al array de plantillas * * @param string $file Con el nombre del archivo * @param string $name Nombre de la plantilla @@ -168,6 +172,36 @@ class Template } } + /** + * Añadir una nueva plantilla al array de plantillas de la clase + * + * @param string $name Con el nombre del archivo de plantilla + * @param string $base Directorio base para la plantilla + * @return bool + */ + public function addContentTemplate($name, $base = null) + { + try { + $template = $this->checkTemplate($name, $base); + $this->setContentTemplate($template, $name); + } catch (FileNotFoundException $e) { + return ''; + } + + return $template; + } + + /** + * Añadir un nuevo archivo de plantilla al array de plantillas de contenido + * + * @param string $file Con el nombre del archivo + * @param string $name Nombre de la plantilla + */ + private function setContentTemplate($file, $name) + { + $this->contentTemplates[$name] = $file; + } + /** * Removes a template from the stack * @@ -416,4 +450,20 @@ class Template { debugLog($this->vars); } + + /** + * @return array + */ + public function getContentTemplates() + { + return $this->contentTemplates; + } + + /** + * @return bool + */ + public function hashContentTemplates() + { + return count($this->contentTemplates) > 0; + } } \ No newline at end of file diff --git a/lib/SP/Providers/Auth/Browser/Browser.php b/lib/SP/Providers/Auth/Browser/Browser.php index f7a4d349..02a06f20 100644 --- a/lib/SP/Providers/Auth/Browser/Browser.php +++ b/lib/SP/Providers/Auth/Browser/Browser.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link http://syspass.org + * @author nuxsmin + * @link http://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -24,11 +24,11 @@ namespace SP\Providers\Auth\Browser; -use SP\Providers\Auth\AuthInterface; use SP\Config\Config; use SP\Config\ConfigData; use SP\Core\Traits\InjectableTrait; use SP\DataModel\UserLoginData; +use SP\Providers\Auth\AuthInterface; /** * Class Browser @@ -119,7 +119,7 @@ class Browser implements AuthInterface $authUser = self::getServerAuthUser(); - return $authUser === null ?: $authUser === $login; + return $authUser !== null && $authUser === $login ?: true; } /** diff --git a/lib/SP/Repositories/Category/CategoryRepository.php b/lib/SP/Repositories/Category/CategoryRepository.php index 86c478af..872f1957 100644 --- a/lib/SP/Repositories/Category/CategoryRepository.php +++ b/lib/SP/Repositories/Category/CategoryRepository.php @@ -50,7 +50,6 @@ class CategoryRepository extends Repository implements RepositoryItemInterface * @throws SPException * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException - * @throws \SP\Core\Dic\ContainerException */ public function create($itemData) { @@ -65,7 +64,7 @@ class CategoryRepository extends Repository implements RepositoryItemInterface $Data->setQuery($query); $Data->addParam($itemData->getName()); $Data->addParam($itemData->getDescription()); - $Data->addParam($this->makeItemHash($itemData->getName())); + $Data->addParam($this->makeItemHash($itemData->getName(), $this->db->getDbHandler())); $Data->setOnErrorMessage(__u('Error al crear la categoría')); DbWrapper::getQuery($Data, $this->db); @@ -80,7 +79,6 @@ class CategoryRepository extends Repository implements RepositoryItemInterface * @return bool * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException - * @throws \SP\Core\Dic\ContainerException */ public function checkDuplicatedOnAdd($itemData) { @@ -89,7 +87,7 @@ class CategoryRepository extends Repository implements RepositoryItemInterface $Data = new QueryData(); $Data->setQuery($query); - $Data->addParam($this->makeItemHash($itemData->getName())); + $Data->addParam($this->makeItemHash($itemData->getName(), $this->db->getDbHandler())); $Data->addParam($itemData->getName()); DbWrapper::getQuery($Data, $this->db); @@ -105,7 +103,6 @@ class CategoryRepository extends Repository implements RepositoryItemInterface * @throws SPException * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException - * @throws \SP\Core\Dic\ContainerException */ public function update($itemData) { @@ -124,7 +121,7 @@ class CategoryRepository extends Repository implements RepositoryItemInterface $Data->setQuery($query); $Data->addParam($itemData->getName()); $Data->addParam($itemData->getDescription()); - $Data->addParam($this->makeItemHash($itemData->getName())); + $Data->addParam($this->makeItemHash($itemData->getName(), $this->db->getDbHandler())); $Data->addParam($itemData->getId()); $Data->setOnErrorMessage(__u('Error al actualizar la categoría')); @@ -140,7 +137,6 @@ class CategoryRepository extends Repository implements RepositoryItemInterface * @return bool * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException - * @throws \SP\Core\Dic\ContainerException */ public function checkDuplicatedOnUpdate($itemData) { @@ -149,7 +145,7 @@ class CategoryRepository extends Repository implements RepositoryItemInterface $Data = new QueryData(); $Data->setQuery($query); - $Data->addParam($this->makeItemHash($itemData->getName())); + $Data->addParam($this->makeItemHash($itemData->getName(), $this->db->getDbHandler())); $Data->addParam($itemData->getName()); $Data->addParam($itemData->getId()); diff --git a/lib/SP/Repositories/Client/ClientRepository.php b/lib/SP/Repositories/Client/ClientRepository.php index b2b821d7..0ccba4ee 100644 --- a/lib/SP/Repositories/Client/ClientRepository.php +++ b/lib/SP/Repositories/Client/ClientRepository.php @@ -69,7 +69,7 @@ class ClientRepository extends Repository implements RepositoryItemInterface $Data->addParam($itemData->getName()); $Data->addParam($itemData->getDescription()); $Data->addParam($itemData->getIsGlobal()); - $Data->addParam($this->makeItemHash($itemData->getName())); + $Data->addParam($this->makeItemHash($itemData->getName(), $this->db->getDbHandler())); $Data->setOnErrorMessage(__u('Error al crear el cliente')); DbWrapper::getQuery($Data, $this->db); @@ -92,7 +92,7 @@ class ClientRepository extends Repository implements RepositoryItemInterface $Data = new QueryData(); $Data->setQuery($query); - $Data->addParam($this->makeItemHash($itemData->getName())); + $Data->addParam($this->makeItemHash($itemData->getName(), $this->db->getDbHandler())); DbWrapper::getQuery($Data, $this->db); @@ -127,7 +127,7 @@ class ClientRepository extends Repository implements RepositoryItemInterface $Data->addParam($itemData->getName()); $Data->addParam($itemData->getDescription()); $Data->addParam($itemData->getIsGlobal()); - $Data->addParam($this->makeItemHash($itemData->getName())); + $Data->addParam($this->makeItemHash($itemData->getName(), $this->db->getDbHandler())); $Data->addParam($itemData->getId()); $Data->setOnErrorMessage(__u('Error al actualizar el cliente')); @@ -151,7 +151,7 @@ class ClientRepository extends Repository implements RepositoryItemInterface $Data = new QueryData(); $Data->setQuery($query); - $Data->addParam($this->makeItemHash($itemData->getName())); + $Data->addParam($this->makeItemHash($itemData->getName(), $this->db->getDbHandler())); $Data->addParam($itemData->getId()); DbWrapper::getQuery($Data, $this->db); diff --git a/lib/SP/Repositories/RepositoryItemTrait.php b/lib/SP/Repositories/RepositoryItemTrait.php index 46da5066..6eb3962d 100644 --- a/lib/SP/Repositories/RepositoryItemTrait.php +++ b/lib/SP/Repositories/RepositoryItemTrait.php @@ -2,8 +2,8 @@ /** * sysPass * - * @author nuxsmin - * @link http://syspass.org + * @author nuxsmin + * @link http://syspass.org * @copyright 2012-2018, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. @@ -26,6 +26,7 @@ namespace SP\Repositories; use SP\Core\Exceptions\SPException; use SP\DataModel\DataModelInterface; +use SP\Storage\DBStorageInterface; use SP\Storage\DBUtil; /** @@ -64,14 +65,15 @@ trait RepositoryItemTrait * Esta función crear un hash para detectar nombres de elementos duplicados mediante * la eliminación de carácteres especiales y capitalización * - * @param $name + * @param string $name + * @param DBStorageInterface $DBStorage * @return string con el hash generado */ - protected function makeItemHash($name) + protected function makeItemHash($name, DBStorageInterface $DBStorage) { $charsSrc = ['.', ' ', '_', ', ', '-', ';', '\'', '"', ':', '(', ')', '|', '/']; - return md5(strtolower(str_replace($charsSrc, '', DBUtil::escape($name)))); + return md5(strtolower(str_replace($charsSrc, '', DBUtil::escape($name, $DBStorage)))); } /** diff --git a/lib/SP/Repositories/User/UserRepository.php b/lib/SP/Repositories/User/UserRepository.php index 730cc468..5dc923b1 100644 --- a/lib/SP/Repositories/User/UserRepository.php +++ b/lib/SP/Repositories/User/UserRepository.php @@ -439,7 +439,7 @@ class UserRepository extends Repository implements RepositoryItemInterface * Creates an item * * @param UserData $itemData - * @return mixed + * @return int * @throws SPException */ public function create($itemData) @@ -457,8 +457,9 @@ class UserRepository extends Repository implements RepositoryItemInterface notes = ?, userGroupId = ?, userProfileId = ?, - mPass = \'\', - mKey = \'\', + mPass = ?, + mKey = ?, + lastUpdateMPass = ?, isAdminApp = ?, isAdminAcc = ?, isDisabled = ?, @@ -476,6 +477,9 @@ class UserRepository extends Repository implements RepositoryItemInterface $Data->addParam($itemData->getNotes()); $Data->addParam($itemData->getUserGroupId()); $Data->addParam($itemData->getUserProfileId()); + $Data->addParam($itemData->getMPass()); + $Data->addParam($itemData->getMKey()); + $Data->addParam($itemData->getLastUpdateMPass()); $Data->addParam($itemData->isIsAdminApp()); $Data->addParam($itemData->isIsAdminAcc()); $Data->addParam($itemData->isIsDisabled()); diff --git a/lib/SP/Services/Auth/LoginService.php b/lib/SP/Services/Auth/LoginService.php index ecf9f152..7d333760 100644 --- a/lib/SP/Services/Auth/LoginService.php +++ b/lib/SP/Services/Auth/LoginService.php @@ -322,7 +322,7 @@ class LoginService $masterPass = $temporaryMasterPass->getUsingKey($masterPass); } - if ($userPassService->updateMasterPass($masterPass, $this->userLoginData)->getStatus() !== UserPassService::MPASS_OK) { + if ($userPassService->updateMasterPassOnLogin($masterPass, $this->userLoginData)->getStatus() !== UserPassService::MPASS_OK) { $this->LogMessage->addDescription(__u('Clave maestra incorrecta')); $this->addTracking(); @@ -523,22 +523,22 @@ class LoginService /** * Comprobar si el cliente ha enviado las variables de autentificación * - * @param BrowserAuthData $AuthData + * @param BrowserAuthData $authData * @return mixed * @throws AuthException */ - protected function authBrowser(BrowserAuthData $AuthData) + protected function authBrowser(BrowserAuthData $authData) { // Comprobar si concide el login con la autentificación del servidor web - if ($AuthData->getAuthenticated() === 0) { - if ($AuthData->isAuthGranted() === false) { + if ($authData->getAuthenticated() === 0) { + if ($authData->isAuthGranted() === false) { return false; } $this->LogMessage->addDescription(__u('Login incorrecto')); $this->LogMessage->addDetails(__u('Tipo'), __FUNCTION__); $this->LogMessage->addDetails(__u('Usuario'), $this->userLoginData->getLoginUser()); - $this->LogMessage->addDetails(__u('Autentificación'), sprintf('%s (%s)', AuthUtil::getServerAuthType(), $AuthData->getName())); + $this->LogMessage->addDetails(__u('Autentificación'), sprintf('%s (%s)', AuthUtil::getServerAuthType(), $authData->getName())); $this->addTracking(); @@ -547,17 +547,14 @@ class LoginService $this->LogMessage->addDetails(__u('Tipo'), __FUNCTION__); - if ($this->configData->isAuthBasicAutoLoginEnabled()) { + if ($authData->getAuthenticated() === 1 && $this->configData->isAuthBasicAutoLoginEnabled()) { try { $userLoginRequest = new UserLoginRequest(); $userLoginRequest->setLogin($this->userLoginData->getLoginUser()); $userLoginRequest->setPassword($this->userLoginData->getLoginPass()); // Verificamos si el usuario existe en la BBDD - if ($this->userService->checkExistsByLogin($this->userLoginData->getLoginUser())) { - // Actualizamos el usuario de SSO en la BBDD - $this->userService->updateOnLogin($userLoginRequest); - } else { + if (!$this->userService->checkExistsByLogin($this->userLoginData->getLoginUser())) { // Creamos el usuario de SSO en la BBDD $this->userService->createOnLogin($userLoginRequest); } @@ -566,7 +563,7 @@ class LoginService } $this->LogMessage->addDetails(__u('Usuario'), $this->userLoginData->getLoginUser()); - $this->LogMessage->addDetails(__u('Autentificación'), sprintf('%s (%s)', AuthUtil::getServerAuthType(), $AuthData->getName())); + $this->LogMessage->addDetails(__u('Autentificación'), sprintf('%s (%s)', AuthUtil::getServerAuthType(), $authData->getName())); return true; } diff --git a/lib/SP/Services/Config/ConfigService.php b/lib/SP/Services/Config/ConfigService.php index 3ff4935e..28e8a396 100644 --- a/lib/SP/Services/Config/ConfigService.php +++ b/lib/SP/Services/Config/ConfigService.php @@ -51,6 +51,7 @@ class ConfigService * ConfigService constructor. * * @throws \SP\Core\Dic\ContainerException + * @throws \ReflectionException */ public function __construct() { @@ -75,7 +76,11 @@ class ConfigService $query = $this->configRepository->getByParam($param); if (empty($query)) { - throw new ParameterNotFoundException(SPException::ERROR, sprintf(__('Parámetro no encontrado (%s)'), $param)); + throw new ParameterNotFoundException( + sprintf(__('Parámetro no encontrado (%s)'), + SPException::ERROR, + $param) + ); } return $query->value; } @@ -103,11 +108,11 @@ class ConfigService } catch (ConstraintException $e) { debugLog($e, true); - throw new ServiceException($e->getType(), $e->getMessage(), $e->getHint(), $e->getCode()); + throw new ServiceException($e->getMessage(), $e->getType(), $e->getHint(), $e->getCode()); } catch (QueryException $e) { debugLog($e, true); - throw new ServiceException($e->getType(), $e->getMessage(), $e->getHint(), $e->getCode()); + throw new ServiceException($e->getMessage(), $e->getType(), $e->getHint(), $e->getCode()); } } } diff --git a/lib/SP/Services/User/UserPassService.php b/lib/SP/Services/User/UserPassService.php index 770131f2..1c4c85d0 100644 --- a/lib/SP/Services/User/UserPassService.php +++ b/lib/SP/Services/User/UserPassService.php @@ -76,6 +76,7 @@ class UserPassService * UserPassService constructor. * * @throws \SP\Core\Dic\ContainerException + * @throws \ReflectionException */ public function __construct() { @@ -98,19 +99,19 @@ class UserPassService * Actualizar la clave maestra con la clave anterior del usuario * * @param string $oldUserPass - * @param UserLoginData $UserData $UserData + * @param UserLoginData $userLoginData $UserData * @return UserPassResponse * @throws SPException * @throws \Defuse\Crypto\Exception\CryptoException * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface */ - public function updateMasterPassFromOldPass($oldUserPass, UserLoginData $UserData) + public function updateMasterPassFromOldPass($oldUserPass, UserLoginData $userLoginData) { - $response = $this->loadUserMPass($UserData, $oldUserPass); + $response = $this->loadUserMPass($userLoginData, $oldUserPass); if ($response->getStatus() === self::MPASS_OK) { - return $this->updateMasterPass($response->getClearMasterPass(), $UserData); + return $this->updateMasterPassOnLogin($response->getClearMasterPass(), $userLoginData); } return new UserPassResponse(self::MPASS_WRONG); @@ -151,16 +152,17 @@ class UserPassService } try { - $securedKey = Crypt::unlockSecuredKey($userLoginResponse->getMKey(), $this->getKey($userLoginData, $key)); - $cryptMPass = Crypt::decrypt($userLoginResponse->getMPass(), $securedKey, $this->getKey($userLoginData, $key)); + $key = self::makeKeyForUser($userLoginData->getLoginUser(), $key ?: $userLoginData->getLoginPass(), $this->configData); + $securedKey = Crypt::unlockSecuredKey($userLoginResponse->getMKey(), $key); + $clearMPass = Crypt::decrypt($userLoginResponse->getMPass(), $securedKey, $key); // Comprobamos el hash de la clave del usuario con la guardada - if (Hash::checkHashKey($cryptMPass, $configHashMPass)) { - CryptSession::saveSessionKey($cryptMPass); + if (Hash::checkHashKey($clearMPass, $configHashMPass)) { + CryptSession::saveSessionKey($clearMPass); - $response = new UserPassResponse(self::MPASS_OK, $cryptMPass); - $response->setCryptMasterPass($cryptMPass); - $response->setCryptSecuredKey($securedKey); + $response = new UserPassResponse(self::MPASS_OK, $clearMPass); + $response->setCryptMasterPass($userLoginResponse->getMPass()); + $response->setCryptSecuredKey($userLoginResponse->getMKey()); return $response; } @@ -174,21 +176,18 @@ class UserPassService /** * Obtener una clave de cifrado basada en la clave del usuario y un salt. * - * @param UserLoginData $userLoginData - * @param string $key Clave de cifrado + * @param string $userLogin + * @param string $userPass + * @param ConfigData $configData * @return string con la clave de cifrado - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface */ - private function getKey(UserLoginData $userLoginData, $key = null) + public static function makeKeyForUser($userLogin, $userPass, ConfigData $configData) { - $pass = $key === null ? $userLoginData->getLoginPass() : $key; - - return $pass . $userLoginData->getLoginUser() . $this->configData->getPasswordSalt(); + return $userPass . $userLogin . $configData->getPasswordSalt(); } /** - * Actualizar la clave maestra del usuario en la BBDD. + * Actualizar la clave maestra del usuario al realizar login * * @param string $userMPass con la clave maestra * @param UserLoginData $userLoginData $userLoginData @@ -199,7 +198,7 @@ class UserPassService * @throws \Psr\Container\NotFoundExceptionInterface * @throws \SP\Core\Exceptions\SPException */ - public function updateMasterPass($userMPass, UserLoginData $userLoginData) + public function updateMasterPassOnLogin($userMPass, UserLoginData $userLoginData) { $userData = $userLoginData->getUserLoginResponse(); $configHashMPass = $this->configService->getByParam('masterPwd'); @@ -217,32 +216,49 @@ class UserPassService if (Hash::checkHashKey($userMPass, $configHashMPass) || CryptUpgrade::migrateHash($userMPass) ) { - $securedKey = Crypt::makeSecuredKey($this->getKey($userLoginData)); - $cryptMPass = Crypt::encrypt($userMPass, $securedKey, $this->getKey($userLoginData)); + $response = $this->createMasterPass($userMPass, $userLoginData->getLoginUser(), $userLoginData->getLoginPass()); - if (!empty($cryptMPass)) { - if (strlen($securedKey) > 1000 || strlen($cryptMPass) > 1000) { - throw new SPException(__u('Error interno'), SPException::ERROR, '', Service::STATUS_INTERNAL_ERROR); - } + $this->userRepository->updateMasterPassById($userData->getId(), $response->getCryptMasterPass(), $response->getCryptSecuredKey()); - $this->userRepository->updateMasterPassById($userData->getId(), $cryptMPass, $securedKey); + CryptSession::saveSessionKey($userMPass); - CryptSession::saveSessionKey($userMPass); - -// $userData->setMPass($cryptMPass); -// $userData->setMKey($securedKey); - - $response = new UserPassResponse(self::MPASS_OK, $userMPass); - $response->setCryptMasterPass($cryptMPass); - $response->setCryptSecuredKey($securedKey); - - return $response; - } + return $response; } return new UserPassResponse(self::MPASS_WRONG); } + /** + * Actualizar la clave maestra del usuario en la BBDD. + * + * @param string $masterPass + * @param string $userLogin + * @param string $userPass + * @return UserPassResponse + * @throws CryptoException + * @throws SPException + */ + public function createMasterPass($masterPass, $userLogin, $userPass) + { + $key = self::makeKeyForUser($userLogin, $userPass, $this->configData); + $securedKey = Crypt::makeSecuredKey($key); + $cryptMPass = Crypt::encrypt($masterPass, $securedKey, $key); + + if (strlen($securedKey) > 1000 || strlen($cryptMPass) > 1000) { + throw new SPException( + __u('Error interno'), + SPException::ERROR, + '', + Service::STATUS_INTERNAL_ERROR); + } + + $response = new UserPassResponse(self::MPASS_OK, $masterPass); + $response->setCryptMasterPass($cryptMPass); + $response->setCryptSecuredKey($securedKey); + + return $response; + } + /** * @param int $id * @param string $userPass diff --git a/lib/SP/Services/User/UserService.php b/lib/SP/Services/User/UserService.php index ea87290f..94a9045c 100644 --- a/lib/SP/Services/User/UserService.php +++ b/lib/SP/Services/User/UserService.php @@ -48,6 +48,10 @@ class UserService * @var UserRepository */ protected $userRepository; + /** + * @var UserPassService + */ + protected $userPassService; /** * UserService constructor. @@ -61,11 +65,13 @@ class UserService } /** - * @param UserRepository $userRepository + * @param UserRepository $userRepository + * @param UserPassService $userPassService */ - public function inject(UserRepository $userRepository) + public function inject(UserRepository $userRepository, UserPassService $userPassService) { $this->userRepository = $userRepository; + $this->userPassService = $userPassService; } /** @@ -192,7 +198,7 @@ class UserService * Creates an item * * @param UserData $itemData - * @return mixed + * @return int * @throws SPException */ public function create($itemData) @@ -200,6 +206,25 @@ class UserService return $this->userRepository->create($itemData); } + /** + * Creates an item + * + * @param UserData $itemData + * @param null $masterPass + * @return int + * @throws SPException + * @throws \Defuse\Crypto\Exception\CryptoException + */ + public function createWithMasterPass($itemData, $masterPass) + { + $response = $this->userPassService->createMasterPass($masterPass, $itemData->getLogin(), $itemData->getPass()); + $itemData->setMPass($response->getCryptMasterPass()); + $itemData->setMKey($response->getCryptSecuredKey()); + $itemData->setLastUpdateMPass(time()); + + return $this->userRepository->create($itemData); + } + /** * Searches for items by a given filter * diff --git a/lib/SP/Services/UserGroup/UserGroupService.php b/lib/SP/Services/UserGroup/UserGroupService.php index 0dee73ee..86c049b2 100644 --- a/lib/SP/Services/UserGroup/UserGroupService.php +++ b/lib/SP/Services/UserGroup/UserGroupService.php @@ -99,7 +99,7 @@ class UserGroupService /** * @param $itemData - * @return mixed + * @return int * @throws SPException */ public function create($itemData) diff --git a/lib/SP/Services/UserProfile/UserProfileService.php b/lib/SP/Services/UserProfile/UserProfileService.php index dd21ebba..d38cabef 100644 --- a/lib/SP/Services/UserProfile/UserProfileService.php +++ b/lib/SP/Services/UserProfile/UserProfileService.php @@ -99,7 +99,7 @@ class UserProfileService /** * @param $itemData - * @return mixed + * @return int * @throws SPException */ public function create($itemData) diff --git a/lib/SP/Storage/DBStorageInterface.php b/lib/SP/Storage/DBStorageInterface.php index abe9ff4f..bb730f4b 100644 --- a/lib/SP/Storage/DBStorageInterface.php +++ b/lib/SP/Storage/DBStorageInterface.php @@ -24,6 +24,8 @@ namespace SP\Storage; +use SP\Core\Exceptions\SPException; + /** * Interface DBStorageInterface * @@ -35,15 +37,17 @@ interface DBStorageInterface * Obtener una conexión PDO * * @return \PDO + * @throws SPException */ public function getConnection(); /** - * Establecer datos de conexión + * Obtener una conexión PDO sin seleccionar la BD * - * @return void + * @return \PDO + * @throws SPException */ - public function setConnectionData(); + public function getConnectionSimple(); /** * Devolcer el estado de la BD @@ -51,4 +55,9 @@ interface DBStorageInterface * @return int */ public function getDbStatus(); + + /** + * @return mixed + */ + public function getConnectionUri(); } \ No newline at end of file diff --git a/lib/SP/Storage/DBUtil.php b/lib/SP/Storage/DBUtil.php index 84f00fab..9eb6740f 100644 --- a/lib/SP/Storage/DBUtil.php +++ b/lib/SP/Storage/DBUtil.php @@ -26,7 +26,6 @@ namespace SP\Storage; use RuntimeException; -use SP\Core\DiFactory; use SP\Core\Exceptions\SPException; /** @@ -72,31 +71,33 @@ class DBUtil /** * Escapar una cadena de texto con funciones de mysqli. * - * @param $str string con la cadena a escapar + * @param string $str string con la cadena a escapar + * @param DBStorageInterface $DBStorage * @return string con la cadena escapada */ - public static function escape($str) + public static function escape($str, DBStorageInterface $DBStorage) { try { - $db = DiFactory::getDBStorage()->getConnection(); - - return $db->quote(trim($str)); + return $DBStorage->getConnection()->quote(trim($str)); } catch (SPException $e) { - return $str; + debugLog($e->getMessage()); } + + return $str; } /** * Obtener la información del servidor de base de datos * + * @param DBStorageInterface $DBStorage * @return array */ - public static function getDBinfo() + public static function getDBinfo(DBStorageInterface $DBStorage) { - $dbinfo = array(); + $dbinfo = []; try { - $db = DiFactory::getDBStorage()->getConnection(); + $db = $DBStorage->getConnection(); $attributes = [ 'SERVER_VERSION', @@ -109,7 +110,7 @@ class DBUtil $dbinfo[$val] = $db->getAttribute(constant('PDO::ATTR_' . $val)); } } catch (\Exception $e) { - return $dbinfo; + debugLog($e->getMessage()); } return $dbinfo; @@ -118,20 +119,20 @@ class DBUtil /** * Comprobar que la base de datos existe. * - * @param DatabaseInterface $database - * @param string $dbName + * @param DBStorageInterface $DBStorage + * @param string $dbName * @return bool */ - public static function checkDatabaseExist(DatabaseInterface $database, $dbName) + public static function checkDatabaseExist(DBStorageInterface $DBStorage, $dbName) { try { $query = /** @lang SQL */ 'SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = \'' . $dbName . '\' - AND table_name IN (\'Client\', \'Category\', \'Account\', \'User\', \'Config\', \'EventLog\')'; + AND `table_name` IN (\'Client\', \'Category\', \'Account\', \'User\', \'Config\', \'EventLog\')'; - return (int)$database->getDbHandler()->getConnection()->query($query)->fetchColumn() === 6; + return (int)$DBStorage->getConnection()->query($query)->fetchColumn() === 6; } catch (\Exception $e) { debugLog($e->getMessage()); debugLog($e->getCode()); diff --git a/lib/SP/Storage/DatabaseConnectionData.php b/lib/SP/Storage/DatabaseConnectionData.php new file mode 100644 index 00000000..563fe100 --- /dev/null +++ b/lib/SP/Storage/DatabaseConnectionData.php @@ -0,0 +1,197 @@ +. + */ + +namespace SP\Storage; + +use SP\Config\ConfigData; + +/** + * Class DatabaseConnectionData + * + * @package SP\Storage + */ +class DatabaseConnectionData +{ + /** + * @var string + */ + private $dbHost; + /** + * @var string + */ + private $dbSocket; + /** + * @var int + */ + private $dbPort; + /** + * @var string + */ + private $dbName; + /** + * @var string + */ + private $dbUser; + /** + * @var string + */ + private $dbPass; + + /** + * @param ConfigData $configData + * @return mixed + */ + public static function getFromConfig(ConfigData $configData) + { + return (new static()) + ->setDbHost($configData->getDbHost()) + ->setDbName($configData->getDbName()) + ->setDbUser($configData->getDbUser()) + ->setDbPass($configData->getDbPass()) + ->setDbPort($configData->getDbPort()) + ->setDbSocket($configData->getDbSocket()); + } + + /** + * @param ConfigData $configData + * @return DatabaseConnectionData + */ + public function refreshFromConfig(ConfigData $configData) + { + return $this->setDbHost($configData->getDbHost()) + ->setDbName($configData->getDbName()) + ->setDbUser($configData->getDbUser()) + ->setDbPass($configData->getDbPass()) + ->setDbPort($configData->getDbPort()) + ->setDbSocket($configData->getDbSocket()); + } + + /** + * @return string + */ + public function getDbHost() + { + return $this->dbHost; + } + + /** + * @param string $dbHost + * @return DatabaseConnectionData + */ + public function setDbHost($dbHost) + { + $this->dbHost = $dbHost; + return $this; + } + + /** + * @return string + */ + public function getDbSocket() + { + return $this->dbSocket; + } + + /** + * @param string $dbSocket + * @return DatabaseConnectionData + */ + public function setDbSocket($dbSocket) + { + $this->dbSocket = $dbSocket; + return $this; + } + + /** + * @return int + */ + public function getDbPort() + { + return $this->dbPort; + } + + /** + * @param int $dbPort + * @return DatabaseConnectionData + */ + public function setDbPort($dbPort) + { + $this->dbPort = $dbPort; + return $this; + } + + /** + * @return string + */ + public function getDbName() + { + return $this->dbName; + } + + /** + * @param string $dbName + * @return DatabaseConnectionData + */ + public function setDbName($dbName) + { + $this->dbName = $dbName; + return $this; + } + + /** + * @return string + */ + public function getDbUser() + { + return $this->dbUser; + } + + /** + * @param string $dbUser + * @return DatabaseConnectionData + */ + public function setDbUser($dbUser) + { + $this->dbUser = $dbUser; + return $this; + } + + /** + * @return string + */ + public function getDbPass() + { + return $this->dbPass; + } + + /** + * @param string $dbPass + * @return DatabaseConnectionData + */ + public function setDbPass($dbPass) + { + $this->dbPass = $dbPass; + return $this; + } +} \ No newline at end of file diff --git a/lib/SP/Storage/DbWrapper.php b/lib/SP/Storage/DbWrapper.php index 8acebfee..a75c14f3 100644 --- a/lib/SP/Storage/DbWrapper.php +++ b/lib/SP/Storage/DbWrapper.php @@ -29,9 +29,6 @@ use SP\Bootstrap; use SP\Core\Exceptions\ConstraintException; use SP\Core\Exceptions\QueryException; use SP\Core\Exceptions\SPException; -use SP\Core\Messages\LogMessage; -use SP\Log\Log; -use SP\Util\Util; defined('APP_ROOT') || die(); @@ -137,27 +134,26 @@ class DbWrapper * @param string $query La consulta que genera el error * @param \Exception $e * @param string $queryFunction - * @throws \SP\Core\Dic\ContainerException */ private static function logDBException($query, \Exception $e, $queryFunction) { - $caller = Util::traceLastCall($queryFunction); +// $caller = Util::traceLastCall($queryFunction); +// +// $LogMessage = new LogMessage(); +// $LogMessage->setAction($caller); +// $LogMessage->addDescription(__u('Error en la consulta')); +// $LogMessage->addDescription(sprintf('%s (%s)', $e->getMessage(), $e->getCode())); +// $LogMessage->addDetails('SQL', DBUtil::escape($query)); - $LogMessage = new LogMessage(); - $LogMessage->setAction($caller); - $LogMessage->addDescription(__u('Error en la consulta')); - $LogMessage->addDescription(sprintf('%s (%s)', $e->getMessage(), $e->getCode())); - $LogMessage->addDetails('SQL', DBUtil::escape($query)); - - debugLog($LogMessage->getDescription(true), true); - debugLog($LogMessage->getDetails()); + debugLog(sprintf('%s (%s)', $e->getMessage(), $e->getCode()), true); + debugLog($query); // Solo registrar eventos de ls BD si no son consultas del registro de eventos - if ($caller !== 'writeLog') { - $Log = new Log($LogMessage); - $Log->setLogLevel(Log::ERROR); - $Log->writeLog(); - } +// if ($caller !== 'writeLog') { +// $Log = new Log($LogMessage); +// $Log->setLogLevel(Log::ERROR); +// $Log->writeLog(); +// } } /** diff --git a/lib/SP/Storage/MySQLHandler.php b/lib/SP/Storage/MySQLHandler.php index 10fc30c4..6a140f26 100644 --- a/lib/SP/Storage/MySQLHandler.php +++ b/lib/SP/Storage/MySQLHandler.php @@ -25,11 +25,7 @@ namespace SP\Storage; use PDO; -use SP\Config\Config; -use SP\Config\ConfigData; use SP\Core\Exceptions\SPException; -use SP\Core\Init; -use SP\Core\Traits\InjectableTrait; defined('APP_ROOT') || die(); @@ -40,71 +36,29 @@ defined('APP_ROOT') || die(); */ class MySQLHandler implements DBStorageInterface { - use InjectableTrait; - const STATUS_OK = 0; const STATUS_KO = 1; - /** - * @var ConfigData - */ - protected $ConfigData; - /** - * @var Config - */ - protected $Config; /** * @var PDO */ private $db; - /** - * @var string - */ - private $dbHost = ''; - /** - * @var string - */ - private $dbSocket; - /** - * @var int - */ - private $dbPort = 0; - /** - * @var string - */ - private $dbName = ''; - /** - * @var string - */ - private $dbUser = ''; - /** - * @var string - */ - private $dbPass = ''; /** * @var int */ private $dbStatus = self::STATUS_KO; + /** + * @var DatabaseConnectionData + */ + private $connectionData; /** * MySQLHandler constructor. + * + * @param DatabaseConnectionData $connectionData */ - public function __construct() + public function __construct(DatabaseConnectionData $connectionData) { - $this->injectDependencies(); - $this->setConnectionData(); - } - - /** - * Establecer datos de conexión - */ - public function setConnectionData() - { - $this->dbHost = $this->ConfigData->getDbHost(); - $this->dbSocket = $this->ConfigData->getDbSocket(); - $this->dbUser = $this->ConfigData->getDbUser(); - $this->dbPass = $this->ConfigData->getDbPass(); - $this->dbName = $this->ConfigData->getDbName(); - $this->dbPort = $this->ConfigData->getDbPort(); + $this->connectionData = $connectionData; } /** @@ -125,45 +79,41 @@ class MySQLHandler implements DBStorageInterface * * @throws \SP\Core\Exceptions\SPException * @return PDO - * @throws \SP\Core\Exceptions\FileNotFoundException */ - public function getConnection() { if (!$this->db) { - $isInstalled = $this->ConfigData->isInstalled(); - - if (empty($this->dbHost) || empty($this->dbUser) || empty($this->dbPass) || empty($this->dbName)) { - if ($isInstalled) { - Init::initError(__('No es posible conectar con la BD'), __('Compruebe los datos de conexión')); - } else { - throw new SPException(__('No es posible conectar con la BD', false), SPException::CRITICAL, __('Compruebe los datos de conexión', false)); - } + if (null === $this->connectionData->getDbUser() + || null === $this->connectionData->getDbPass() + || null === $this->connectionData->getDbName() + || (null === $this->connectionData->getDbHost() && null === $this->connectionData->getDbSocket()) + ) { + throw new SPException( + __u('No es posible conectar con la BD'), + SPException::CRITICAL, + __u('Compruebe los datos de conexión')); } try { $opts = [PDO::ATTR_EMULATE_PREPARES => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]; - if (empty($this->dbSocket)) { - $dsn = 'mysql:host=' . $this->dbHost . ';port=' . $this->dbPort . ';dbname=' . $this->dbName . ';charset=utf8'; - } else { - $dsn = 'mysql:unix_socket=' . $this->dbSocket . ';dbname=' . $this->dbName . ';charset=utf8'; - } - - $this->db = new PDO($dsn, $this->dbUser, $this->dbPass, $opts); + $this->db = new PDO($this->getConnectionUri(), $this->connectionData->getDbUser(), $this->connectionData->getDbPass(), $opts); $this->dbStatus = self::STATUS_OK; } catch (\Exception $e) { - if ($isInstalled) { - if ($e->getCode() === 1049) { - $this->ConfigData->setInstalled(false); - $this->Config->saveConfig($this->ConfigData); - } - Init::initError( - __('No es posible conectar con la BD'), - 'Error ' . $e->getCode() . ': ' . $e->getMessage()); - } else { - throw new SPException($e->getMessage(), SPException::CRITICAL, $e->getCode()); - } +// if ($isInstalled) { +// if ($e->getCode() === 1049) { +// $this->ConfigData->setInstalled(false); +// $this->Config->saveConfig($this->ConfigData); +// } +// } + + throw new SPException( + __u('No es posible conectar con la BD'), + SPException::CRITICAL, + sprintf('Error %s: %s', $e->getCode(), $e->getMessage()), + $e->getCode(), + $e + ); } } @@ -171,11 +121,66 @@ class MySQLHandler implements DBStorageInterface } /** - * @param Config $config + * @return string */ - public function inject(Config $config) + public function getConnectionUri() { - $this->Config = $config; - $this->ConfigData = $config->getConfigData(); + if ('' === $this->connectionData->getDbSocket()) { + $dsn = 'mysql:host=' . $this->connectionData->getDbHost(); + + if (null !== $this->connectionData->getDbPort()) { + $dsn .= ';port=' . $this->connectionData->getDbPort(); + } + + if (null !== $this->connectionData->getDbName()) { + $dsn .= ';dbname=' . $this->connectionData->getDbName(); + } + + + return $dsn . ';charset=utf8'; + } + + $dsn = 'mysql:unix_socket=' . $this->connectionData->getDbSocket(); + + if ('' !== $this->connectionData->getDbName()) { + $dsn .= ';dbname=' . $this->connectionData->getDbName(); + } + + return $dsn . ';charset=utf8'; + } + + /** + * Obtener una conexión PDO sin seleccionar la BD + * + * @return \PDO + * @throws SPException + */ + public function getConnectionSimple() + { + if (!$this->db) { + if (null === $this->connectionData->getDbHost() && null === $this->connectionData->getDbSocket()) { + throw new SPException( + __u('No es posible conectar con la BD'), + SPException::CRITICAL, + __u('Compruebe los datos de conexión')); + } + + try { + $opts = [PDO::ATTR_EMULATE_PREPARES => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]; + + $this->db = new PDO($this->getConnectionUri(), $this->connectionData->getDbUser(), $this->connectionData->getDbPass(), $opts); + $this->dbStatus = self::STATUS_OK; + } catch (\Exception $e) { + throw new SPException( + __u('No es posible conectar con la BD'), + SPException::CRITICAL, + sprintf('Error %s: %s', $e->getCode(), $e->getMessage()), + $e->getCode(), + $e + ); + } + } + + return $this->db; } } \ No newline at end of file diff --git a/lib/SP/Util/Util.php b/lib/SP/Util/Util.php index 4e64cd14..67d97a4a 100644 --- a/lib/SP/Util/Util.php +++ b/lib/SP/Util/Util.php @@ -32,7 +32,7 @@ use SP\Config\ConfigData; use SP\Config\ConfigDB; use SP\Core\Exceptions\SPException; use SP\Core\Init; -use SP\Core\Installer; +use SP\Core\Install\Installer; use SP\Core\Session\Session; use SP\Core\SessionFactory; use SP\Html\Html; diff --git a/public/js/app-actions.js b/public/js/app-actions.js index d4dcd721..5767b6a1 100644 --- a/public/js/app-actions.js +++ b/public/js/app-actions.js @@ -23,8 +23,8 @@ sysPass.Actions = function (Common) { /** - * Objeto con acciones para las cuentas - */ + * Objeto con acciones para las cuentas + */ const account = { view: function ($obj) { log.info("account:show"); @@ -638,13 +638,13 @@ sysPass.Actions = function (Common) { login: function ($obj) { log.info("main:login"); - var opts = Common.appRequests().getRequestOpts(); - opts.url = ajaxUrl.main.login; + const opts = Common.appRequests().getRequestOpts(); + opts.url = ajaxUrl.entrypoint + "?r=" + $obj.data("route"); opts.method = "get"; opts.data = $obj.serialize(); Common.appRequests().getActionCall(opts, function (json) { - var $extra = $(".extra-hidden"); + const $extra = $(".extra-hidden"); switch (json.status) { case 0: @@ -687,16 +687,16 @@ sysPass.Actions = function (Common) { install: function ($obj) { log.info("main:install"); - var opts = Common.appRequests().getRequestOpts(); - opts.url = ajaxUrl.main.install; + const opts = Common.appRequests().getRequestOpts(); + opts.url = ajaxUrl.entrypoint + "?r=" + $obj.data("route"); opts.data = $obj.serialize(); Common.appRequests().getActionCall(opts, function (json) { Common.msg.out(json); - if (json.status == 0) { + if (json.status === 0) { setTimeout(function () { - Common.redirect("index.php"); + Common.redirect("index.php?r=login/index"); }, 1000); } }); diff --git a/public/js/app-actions.min.js b/public/js/app-actions.min.js index 69142e59..40565c1b 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,k,e){c instanceof String&&(c=String(c));for(var l=c.length,f=0;f
";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.account.save;b.data={r:"account/saveDelete/"+a.data("item-id"),sk:c.sk.get()};c.appRequests().getActionCall(b,function(a){c.msg.out(a);k.search()})}}})},viewPass:function(a){e.info("account:showpass");var b=a.data("parent-id")||0,b=0=== @@ -16,15 +16,15 @@ saveFavorite:"/ajax/ajax_itemSave.php",request:"/ajax/ajax_itemSave.php",getFile 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'+b+"
"),g=d.find("img");if(0===g.length)return p(b);g.hide();$.magnificPopup.open({items:{src:d,type:"inline"},callbacks:{open:function(){var a=this;g.on("click",function(){a.close()});setTimeout(function(){var a=c.resizeImage(g);d.css({backgroundColor:"#fff",width:a.width,height:"auto"});g.show("slow")},500)}}})},r={get:function(a){e.info("items:get");var b=a[0].selectize;b.clearOptions();b.load(function(d){var g=c.appRequests().getRequestOpts(); g.url=f.updateItems;g.method="get";g.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:a.data("sk")};c.appRequests().getActionCall(g,function(g){d(g.data);b.setValue(a.data("selected-id"),!0);c.appTriggers().updateFormHash()})})},update:function(a){e.info("items:update");var b=$("#"+a.data("item-dst"))[0].selectize;b.clearOptions();b.load(function(b){var d=c.appRequests().getRequestOpts();d.url=f.updateItems;d.method="get";d.data={r:a.data("item-route"),sk:c.sk.get()};c.appRequests().getActionCall(d, -function(a){b(a)})})}},t={logout:function(){c.redirect("index.php?r=login/logout")},login:function(a){e.info("main:login");var b=c.appRequests().getRequestOpts();b.url=f.main.login;b.method="get";b.data=a.serialize();c.appRequests().getActionCall(b,function(b){var d=$(".extra-hidden");switch(b.status){case 0:c.redirect(b.data.url);break;case 2:c.msg.out(b);a.find("input[type='text'],input[type='password']").val("");a.find("input:first").focus();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=a.find("input[name='useTask']");var d=$("#taskStatus");d.empty().html(c.config().LANG[62]);if(0
",d=a.data("selection"),g=[];if(d&&($(d).find(".is-selected").each(function(){var a=$(this);g.push(a.data("item-id"))}),0===g.length))return;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.preventDefault();b=c.appRequests().getRequestOpts();b.url=f.appMgmt.save;b.method="get";b.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(b,function(a){c.msg.out(a);n({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.appMgmt.save+"?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&&n({r:h.state.tab.route,tabIndex:h.state.tab.index}),$.magnificPopup.close())})},search:function(a){e.info("appMgmt:search");var b=$(a.data("target")),d=c.appRequests().getRequestOpts();d.url=f.appMgmt.search+"?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)); +function(a){b(a)})})}},t={logout:function(){c.redirect("index.php?r=login/logout")},login:function(a){e.info("main:login");var b=c.appRequests().getRequestOpts();b.url=f.entrypoint+"?r="+a.data("route");b.method="get";b.data=a.serialize();c.appRequests().getActionCall(b,function(b){var d=$(".extra-hidden");switch(b.status){case 0:c.redirect(b.data.url);break;case 2:c.msg.out(b);a.find("input[type='text'],input[type='password']").val("");a.find("input:first").focus();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=a.find("input[name='useTask']");var d=$("#taskStatus");d.empty().html(c.config().LANG[62]); +if(0",d=a.data("selection"),g=[];if(d&&($(d).find(".is-selected").each(function(){var a=$(this);g.push(a.data("item-id"))}),0===g.length))return;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.preventDefault();b=c.appRequests().getRequestOpts();b.url=f.appMgmt.save;b.method="get";b.data={r:a.data("action-route")+"/"+a.data("item-id"),sk:c.sk.get(),isAjax:1};c.appRequests().getActionCall(b,function(a){c.msg.out(a);n({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.appMgmt.save+ +"?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&&n({r:h.state.tab.route,tabIndex:h.state.tab.index}),$.magnificPopup.close())})},search:function(a){e.info("appMgmt:search");var b=$(a.data("target")),d=c.appRequests().getRequestOpts();d.url=f.appMgmt.search+"?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){e.info("appMgmt:nav");var b=$("#"+a.data("action-form"));b.find("[name='start']").val(a.data("start"));b.find("[name='count']").val(a.data("count"));b.find("[name='sk']").val(c.sk.get());h.search(b)},ldapSync:function(a){e.info("appMgmt:ldapSync");var b='

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

";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)})}}})}};return{doAction:m,appMgmt:h,account:k,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);u(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='

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

";mdlDialog().show({text:b,negative:{title:c.config().LANG[44], diff --git a/schemas/30018010101.sql b/schemas/30018010101.sql index 267ff22b..94c8783b 100644 --- a/schemas/30018010101.sql +++ b/schemas/30018010101.sql @@ -262,9 +262,9 @@ ALTER TABLE usrData ALTER TABLE usrData CHANGE user_pass pass VARBINARY(1000) NOT NULL; ALTER TABLE usrData - CHANGE user_mPass mPass VARBINARY(1000); + CHANGE user_mPass mPass VARBINARY(1000) DEFAULT NULL; ALTER TABLE usrData - CHANGE user_mKey mKey VARBINARY(1000) NOT NULL; + CHANGE user_mKey mKey VARBINARY(1000) DEFAULT NULL; ALTER TABLE usrData CHANGE user_email email VARCHAR(80); ALTER TABLE usrData diff --git a/schemas/dbstructure.sql b/schemas/dbstructure.sql index 29ebb7fd..284ce08a 100644 --- a/schemas/dbstructure.sql +++ b/schemas/dbstructure.sql @@ -1,9 +1,3 @@ --- MySQL dump 10.13 Distrib 5.5.58, for debian-linux-gnu (x86_64) --- --- Host: 172.18.0.2 Database: syspass --- ------------------------------------------------------ --- Server version 5.5.53-0+deb8u1 - /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; @@ -15,10 +9,6 @@ /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; --- --- Table structure for table `Account` --- - DROP TABLE IF EXISTS `Account`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -34,15 +24,15 @@ CREATE TABLE `Account` ( `url` varchar(255) DEFAULT NULL, `pass` varbinary(1000) NOT NULL, `key` varbinary(1000) NOT NULL, - `notes` text, - `countView` int(10) unsigned NOT NULL DEFAULT '0', - `countDecrypt` int(10) unsigned NOT NULL DEFAULT '0', + `notes` text DEFAULT NULL, + `countView` int(10) unsigned NOT NULL DEFAULT 0, + `countDecrypt` int(10) unsigned NOT NULL DEFAULT 0, `dateAdd` datetime NOT NULL, `dateEdit` datetime DEFAULT NULL, - `otherUserGroupEdit` tinyint(1) DEFAULT '0', - `otherUserEdit` tinyint(1) DEFAULT '0', - `isPrivate` tinyint(1) DEFAULT '0', - `isPrivateGroup` tinyint(1) DEFAULT '0', + `otherUserGroupEdit` tinyint(1) DEFAULT 0, + `otherUserEdit` tinyint(1) DEFAULT 0, + `isPrivate` tinyint(1) DEFAULT 0, + `isPrivateGroup` tinyint(1) DEFAULT 0, `passDate` int(11) unsigned DEFAULT NULL, `passDateChange` int(11) unsigned DEFAULT NULL, `parentId` mediumint(8) unsigned DEFAULT NULL, @@ -57,13 +47,9 @@ CREATE TABLE `Account` ( CONSTRAINT `fk_Account_userEditId` FOREIGN KEY (`userEditId`) REFERENCES `User` (`id`), CONSTRAINT `fk_Account_userGroupId` FOREIGN KEY (`userGroupId`) REFERENCES `UserGroup` (`id`), CONSTRAINT `fk_Account_userId` FOREIGN KEY (`userId`) REFERENCES `User` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `AccountFile` --- - DROP TABLE IF EXISTS `AccountFile`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -75,17 +61,13 @@ CREATE TABLE `AccountFile` ( `size` int(11) NOT NULL, `content` mediumblob NOT NULL, `extension` varchar(10) NOT NULL, - `thumb` mediumblob, + `thumb` mediumblob DEFAULT NULL, PRIMARY KEY (`id`), KEY `IDX_accountId` (`accountId`), CONSTRAINT `fk_AccountFile_accountId` FOREIGN KEY (`accountId`) REFERENCES `Account` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `AccountHistory` --- - DROP TABLE IF EXISTS `AccountHistory`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -103,20 +85,20 @@ CREATE TABLE `AccountHistory` ( `pass` varbinary(1000) NOT NULL, `key` varbinary(1000) NOT NULL, `notes` text NOT NULL, - `countView` int(10) unsigned NOT NULL DEFAULT '0', - `countDecrypt` int(10) unsigned NOT NULL DEFAULT '0', + `countView` int(10) unsigned NOT NULL DEFAULT 0, + `countDecrypt` int(10) unsigned NOT NULL DEFAULT 0, `dateAdd` datetime NOT NULL, `dateEdit` datetime DEFAULT NULL, - `isModify` tinyint(1) DEFAULT '0', - `isDeleted` tinyint(1) DEFAULT '0', + `isModify` tinyint(1) DEFAULT 0, + `isDeleted` tinyint(1) DEFAULT 0, `mPassHash` varbinary(255) NOT NULL, - `otherUserEdit` tinyint(1) DEFAULT '0', - `otherUserGroupEdit` tinyint(1) DEFAULT '0', + `otherUserEdit` tinyint(1) DEFAULT 0, + `otherUserGroupEdit` tinyint(1) DEFAULT 0, `passDate` int(10) unsigned DEFAULT NULL, `passDateChange` int(10) unsigned DEFAULT NULL, `parentId` mediumint(8) unsigned DEFAULT NULL, - `isPrivate` tinyint(1) DEFAULT '0', - `isPrivateGroup` tinyint(1) DEFAULT '0', + `isPrivate` tinyint(1) DEFAULT 0, + `isPrivateGroup` tinyint(1) DEFAULT 0, PRIMARY KEY (`id`), KEY `IDX_accountId` (`accountId`), KEY `fk_AccountHistory_userGroupId` (`userGroupId`), @@ -129,13 +111,9 @@ CREATE TABLE `AccountHistory` ( CONSTRAINT `fk_AccountHistory_userEditId` FOREIGN KEY (`userEditId`) REFERENCES `User` (`id`), CONSTRAINT `fk_AccountHistory_userGroupId` FOREIGN KEY (`userGroupId`) REFERENCES `UserGroup` (`id`), CONSTRAINT `fk_AccountHistory_userId` FOREIGN KEY (`userId`) REFERENCES `User` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `AccountToFavorite` --- - DROP TABLE IF EXISTS `AccountToFavorite`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -144,15 +122,11 @@ CREATE TABLE `AccountToFavorite` ( `userId` smallint(5) unsigned NOT NULL, KEY `search_idx` (`accountId`,`userId`), KEY `fk_AccountToFavorite_userId` (`userId`), - CONSTRAINT `fk_AccountToFavorite_userId` FOREIGN KEY (`userId`) REFERENCES `User` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `fk_AccountToFavorite_accountId` FOREIGN KEY (`accountId`) REFERENCES `Account` (`id`) ON DELETE CASCADE ON UPDATE CASCADE + CONSTRAINT `fk_AccountToFavorite_accountId` FOREIGN KEY (`accountId`) REFERENCES `Account` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `fk_AccountToFavorite_userId` FOREIGN KEY (`userId`) REFERENCES `User` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `AccountToGroup` --- - DROP TABLE IF EXISTS `AccountToGroup`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -161,15 +135,11 @@ CREATE TABLE `AccountToGroup` ( `userGroupId` smallint(5) unsigned NOT NULL, KEY `IDX_accountId` (`accountId`), KEY `fk_AccountToGroup_userGroupId` (`userGroupId`), - CONSTRAINT `fk_AccountToGroup_userGroupId` FOREIGN KEY (`userGroupId`) REFERENCES `UserGroup` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `fk_AccountToGroup_accountId` FOREIGN KEY (`accountId`) REFERENCES `Account` (`id`) ON DELETE CASCADE ON UPDATE CASCADE + CONSTRAINT `fk_AccountToGroup_accountId` FOREIGN KEY (`accountId`) REFERENCES `Account` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `fk_AccountToGroup_userGroupId` FOREIGN KEY (`userGroupId`) REFERENCES `UserGroup` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `AccountToTag` --- - DROP TABLE IF EXISTS `AccountToTag`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -178,15 +148,11 @@ CREATE TABLE `AccountToTag` ( `tagId` int(10) unsigned NOT NULL, KEY `fk_AccountToTag_accountId` (`accountId`), KEY `fk_AccountToTag_tagId` (`tagId`), - CONSTRAINT `fk_AccountToTag_tagId` FOREIGN KEY (`tagId`) REFERENCES `Tag` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `fk_AccountToTag_accountId` FOREIGN KEY (`accountId`) REFERENCES `Account` (`id`) ON DELETE CASCADE ON UPDATE CASCADE + CONSTRAINT `fk_AccountToTag_accountId` FOREIGN KEY (`accountId`) REFERENCES `Account` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `fk_AccountToTag_tagId` FOREIGN KEY (`tagId`) REFERENCES `Tag` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `AccountToUser` --- - DROP TABLE IF EXISTS `AccountToUser`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -195,15 +161,11 @@ CREATE TABLE `AccountToUser` ( `userId` smallint(5) unsigned NOT NULL, KEY `idx_account` (`accountId`), KEY `fk_AccountToUser_userId` (`userId`), - CONSTRAINT `fk_AccountToUser_userId` FOREIGN KEY (`userId`) REFERENCES `User` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `fk_AccountToUser_accountId` FOREIGN KEY (`accountId`) REFERENCES `Account` (`id`) ON DELETE CASCADE ON UPDATE CASCADE + CONSTRAINT `fk_AccountToUser_accountId` FOREIGN KEY (`accountId`) REFERENCES `Account` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `fk_AccountToUser_userId` FOREIGN KEY (`userId`) REFERENCES `User` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `Action` --- - DROP TABLE IF EXISTS `Action`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -216,10 +178,6 @@ CREATE TABLE `Action` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `AuthToken` --- - DROP TABLE IF EXISTS `AuthToken`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -238,13 +196,9 @@ CREATE TABLE `AuthToken` ( KEY `fk_AuthToken_actionId` (`actionId`), CONSTRAINT `fk_AuthToken_actionId` FOREIGN KEY (`actionId`) REFERENCES `Action` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `fk_AuthToken_userId` FOREIGN KEY (`userId`) REFERENCES `User` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `Category` --- - DROP TABLE IF EXISTS `Category`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -254,13 +208,9 @@ CREATE TABLE `Category` ( `hash` varbinary(40) NOT NULL, `description` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `Client` --- - DROP TABLE IF EXISTS `Client`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -269,16 +219,12 @@ CREATE TABLE `Client` ( `name` varchar(100) NOT NULL, `hash` varbinary(40) NOT NULL, `description` varchar(255) DEFAULT NULL, - `isGlobal` tinyint(1) DEFAULT '0', + `isGlobal` tinyint(1) DEFAULT 0, PRIMARY KEY (`id`), KEY `IDX_name` (`name`,`hash`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `Config` --- - DROP TABLE IF EXISTS `Config`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -289,10 +235,6 @@ CREATE TABLE `Config` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `CustomFieldData` --- - DROP TABLE IF EXISTS `CustomFieldData`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -301,7 +243,7 @@ CREATE TABLE `CustomFieldData` ( `moduleId` smallint(5) unsigned NOT NULL, `itemId` int(10) unsigned NOT NULL, `definitionId` int(10) unsigned NOT NULL, - `data` longblob, + `data` longblob DEFAULT NULL, `key` varbinary(1000) DEFAULT NULL, PRIMARY KEY (`id`), KEY `IDX_DEFID` (`definitionId`), @@ -310,13 +252,9 @@ CREATE TABLE `CustomFieldData` ( KEY `IDX_ITEM` (`itemId`), KEY `IDX_MODULE` (`moduleId`), CONSTRAINT `fk_CustomFieldData_definitionId` FOREIGN KEY (`definitionId`) REFERENCES `CustomFieldDefinition` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `CustomFieldDefinition` --- - DROP TABLE IF EXISTS `CustomFieldDefinition`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -324,7 +262,7 @@ CREATE TABLE `CustomFieldDefinition` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL, `moduleId` smallint(5) unsigned NOT NULL, - `field` blob, + `field` blob DEFAULT NULL, `required` tinyint(1) unsigned DEFAULT NULL, `help` varchar(255) DEFAULT NULL, `showInList` tinyint(1) unsigned DEFAULT NULL, @@ -332,13 +270,9 @@ CREATE TABLE `CustomFieldDefinition` ( PRIMARY KEY (`id`), KEY `fk_CustomFieldDefinition_typeId` (`typeId`), CONSTRAINT `fk_CustomFieldDefinition_typeId` FOREIGN KEY (`typeId`) REFERENCES `CustomFieldType` (`id`) ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `CustomFieldType` --- - DROP TABLE IF EXISTS `CustomFieldType`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -347,13 +281,9 @@ CREATE TABLE `CustomFieldType` ( `name` varchar(50) NOT NULL, `text` varchar(50) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `EventLog` --- - DROP TABLE IF EXISTS `EventLog`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -364,16 +294,12 @@ CREATE TABLE `EventLog` ( `userId` smallint(5) unsigned NOT NULL, `ipAddress` varchar(45) NOT NULL, `action` varchar(50) NOT NULL, - `description` text, + `description` text DEFAULT NULL, `level` varchar(20) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `Notice` --- - DROP TABLE IF EXISTS `Notice`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -383,10 +309,10 @@ CREATE TABLE `Notice` ( `component` varchar(100) NOT NULL, `description` varchar(500) NOT NULL, `date` int(10) unsigned NOT NULL, - `checked` tinyint(1) DEFAULT '0', + `checked` tinyint(1) DEFAULT 0, `userId` smallint(5) unsigned DEFAULT NULL, - `sticky` tinyint(1) DEFAULT '0', - `onlyAdmin` tinyint(1) DEFAULT '0', + `sticky` tinyint(1) DEFAULT 0, + `onlyAdmin` tinyint(1) DEFAULT 0, PRIMARY KEY (`id`), KEY `IDX_userId` (`userId`,`checked`,`date`), KEY `IDX_component` (`component`,`date`,`checked`,`userId`), @@ -394,10 +320,6 @@ CREATE TABLE `Notice` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `Plugin` --- - DROP TABLE IF EXISTS `Plugin`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -405,17 +327,13 @@ CREATE TABLE `Plugin` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL, `data` varbinary(5000) DEFAULT NULL, - `enabled` tinyint(1) NOT NULL DEFAULT '0', - `available` tinyint(1) DEFAULT '0', + `enabled` tinyint(1) NOT NULL DEFAULT 0, + `available` tinyint(1) DEFAULT 0, PRIMARY KEY (`id`), UNIQUE KEY `plugin_name_UNIQUE` (`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `PublicLink` --- - DROP TABLE IF EXISTS `PublicLink`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -423,16 +341,16 @@ CREATE TABLE `PublicLink` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `itemId` int(10) unsigned NOT NULL, `hash` varbinary(100) NOT NULL, - `data` longblob, + `data` longblob DEFAULT NULL, `userId` smallint(5) unsigned NOT NULL, `typeId` int(10) unsigned NOT NULL, `notify` tinyint(1) unsigned NOT NULL, `dateAdd` int(10) unsigned NOT NULL, `dateExpire` int(10) unsigned NOT NULL, - `countViews` smallint(5) unsigned DEFAULT '0', - `totalCountViews` smallint(5) unsigned DEFAULT '0', + `countViews` smallint(5) unsigned DEFAULT 0, + `totalCountViews` smallint(5) unsigned DEFAULT 0, `maxCountViews` smallint(5) unsigned NOT NULL, - `useInfo` blob, + `useInfo` blob DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `IDX_hash` (`hash`), UNIQUE KEY `unique_publicLink_hash` (`hash`), @@ -440,13 +358,9 @@ CREATE TABLE `PublicLink` ( KEY `IDX_itemId` (`itemId`), KEY `fk_PublicLink_userId` (`userId`), CONSTRAINT `fk_PublicLink_userId` FOREIGN KEY (`userId`) REFERENCES `User` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `Tag` --- - DROP TABLE IF EXISTS `Tag`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -457,13 +371,9 @@ CREATE TABLE `Tag` ( PRIMARY KEY (`id`), UNIQUE KEY `tag_hash_UNIQUE` (`hash`), KEY `IDX_name` (`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `Track` --- - DROP TABLE IF EXISTS `Track`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -477,13 +387,9 @@ CREATE TABLE `Track` ( PRIMARY KEY (`id`), KEY `IDX_userId` (`userId`), KEY `IDX_time-ip-source` (`time`,`ipv4`,`ipv6`,`source`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `User` --- - DROP TABLE IF EXISTS `User`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -495,37 +401,33 @@ CREATE TABLE `User` ( `ssoLogin` varchar(100) DEFAULT NULL, `pass` varbinary(1000) NOT NULL, `mPass` varbinary(1000) DEFAULT NULL, - `mKey` varbinary(1000) NOT NULL, + `mKey` varbinary(1000) DEFAULT NULL, `email` varchar(80) DEFAULT NULL, - `notes` text, - `loginCount` int(10) unsigned NOT NULL DEFAULT '0', + `notes` text DEFAULT NULL, + `loginCount` int(10) unsigned NOT NULL DEFAULT 0, `userProfileId` smallint(5) unsigned NOT NULL, `lastLogin` datetime DEFAULT NULL, `lastUpdate` datetime DEFAULT NULL, - `lastUpdateMPass` int(11) unsigned NOT NULL DEFAULT '0', - `isAdminApp` tinyint(1) DEFAULT '0', - `isAdminAcc` tinyint(1) DEFAULT '0', - `isLdap` tinyint(1) DEFAULT '0', - `isDisabled` tinyint(1) DEFAULT '0', + `lastUpdateMPass` int(11) unsigned NOT NULL DEFAULT 0, + `isAdminApp` tinyint(1) DEFAULT 0, + `isAdminAcc` tinyint(1) DEFAULT 0, + `isLdap` tinyint(1) DEFAULT 0, + `isDisabled` tinyint(1) DEFAULT 0, `hashSalt` varbinary(128) NOT NULL, - `isMigrate` tinyint(1) DEFAULT '0', - `isChangePass` tinyint(1) DEFAULT '0', - `isChangedPass` tinyint(1) DEFAULT '0', - `preferences` blob, + `isMigrate` tinyint(1) DEFAULT 0, + `isChangePass` tinyint(1) DEFAULT 0, + `isChangedPass` tinyint(1) DEFAULT 0, + `preferences` blob DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `IDX_login` (`login`,`ssoLogin`), KEY `IDX_pass` (`pass`(767)), KEY `fk_User_userGroupId` (`userGroupId`), KEY `fk_User_userProfileId` (`userProfileId`), - CONSTRAINT `fk_User_userProfileId` FOREIGN KEY (`userProfileId`) REFERENCES `UserProfile` (`id`), - CONSTRAINT `fk_User_userGroupId` FOREIGN KEY (`userGroupId`) REFERENCES `UserGroup` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; + CONSTRAINT `fk_User_userGroupId` FOREIGN KEY (`userGroupId`) REFERENCES `UserGroup` (`id`), + CONSTRAINT `fk_User_userProfileId` FOREIGN KEY (`userProfileId`) REFERENCES `UserProfile` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `UserGroup` --- - DROP TABLE IF EXISTS `UserGroup`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -534,13 +436,9 @@ CREATE TABLE `UserGroup` ( `name` varchar(50) NOT NULL, `description` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `UserPassRecover` --- - DROP TABLE IF EXISTS `UserPassRecover`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -549,17 +447,13 @@ CREATE TABLE `UserPassRecover` ( `userId` smallint(5) unsigned NOT NULL, `hash` varbinary(128) NOT NULL, `date` int(10) unsigned NOT NULL, - `used` tinyint(1) DEFAULT '0', + `used` tinyint(1) DEFAULT 0, PRIMARY KEY (`id`), KEY `IDX_userId` (`userId`,`date`), CONSTRAINT `fk_UserPassRecover_userId` FOREIGN KEY (`userId`) REFERENCES `User` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `UserProfile` --- - DROP TABLE IF EXISTS `UserProfile`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -568,13 +462,9 @@ CREATE TABLE `UserProfile` ( `name` varchar(45) NOT NULL, `profile` blob NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `UserToGroup` --- - DROP TABLE IF EXISTS `UserToGroup`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -588,10 +478,6 @@ CREATE TABLE `UserToGroup` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Temporary table structure for view `account_data_v` --- - DROP TABLE IF EXISTS `account_data_v`; /*!50001 DROP VIEW IF EXISTS `account_data_v`*/; SET @saved_cs_client = @@character_set_client; @@ -629,10 +515,6 @@ SET character_set_client = utf8; ) ENGINE=MyISAM */; SET character_set_client = @saved_cs_client; --- --- Temporary table structure for view `account_search_v` --- - DROP TABLE IF EXISTS `account_search_v`; /*!50001 DROP VIEW IF EXISTS `account_search_v`*/; SET @saved_cs_client = @@character_set_client; @@ -662,10 +544,6 @@ SET character_set_client = utf8; ) ENGINE=MyISAM */; SET character_set_client = @saved_cs_client; --- --- Final view structure for view `account_data_v` --- - /*!50001 DROP TABLE IF EXISTS `account_data_v`*/; /*!50001 DROP VIEW IF EXISTS `account_data_v`*/; /*!50001 SET @saved_cs_client = @@character_set_client */; @@ -675,16 +553,12 @@ SET character_set_client = @saved_cs_client; /*!50001 SET character_set_results = utf8 */; /*!50001 SET collation_connection = utf8_general_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ -/*!50013 DEFINER=`root`@`172.18.0.1` SQL SECURITY DEFINER */ -/*!50001 VIEW `account_data_v` AS select `Account`.`id` AS `id`,`Account`.`name` AS `name`,`Account`.`categoryId` AS `categoryId`,`Account`.`userId` AS `userId`,`Account`.`clientId` AS `clientId`,`Account`.`userGroupId` AS `userGroupId`,`Account`.`userEditId` AS `userEditId`,`Account`.`login` AS `login`,`Account`.`url` AS `url`,`Account`.`notes` AS `notes`,`Account`.`countView` AS `countView`,`Account`.`countDecrypt` AS `countDecrypt`,`Account`.`dateAdd` AS `dateAdd`,`Account`.`dateEdit` AS `dateEdit`,conv(`Account`.`otherUserEdit`,10,2) AS `otherUserEdit`,conv(`Account`.`otherUserGroupEdit`,10,2) AS `otherUserGroupEdit`,conv(`Account`.`isPrivate`,10,2) AS `isPrivate`,conv(`Account`.`isPrivateGroup`,10,2) AS `isPrivateGroup`,`Account`.`passDate` AS `passDate`,`Account`.`passDateChange` AS `passDateChange`,`Account`.`parentId` AS `parentId`,`Category`.`name` AS `categoryName`,`Client`.`name` AS `clientName`,`ug`.`name` AS `userGroupName`,`u1`.`name` AS `userName`,`u1`.`login` AS `userLogin`,`u2`.`name` AS `userEditName`,`u2`.`login` AS `userEditLogin`,`PublicLink`.`hash` AS `publicLinkHash` from ((((((`Account` left join `Category` on((`Account`.`categoryId` = `Category`.`id`))) join `UserGroup` `ug` on((`Account`.`userGroupId` = `ug`.`id`))) join `User` `u1` on((`Account`.`userId` = `u1`.`id`))) join `User` `u2` on((`Account`.`userEditId` = `u2`.`id`))) left join `Client` on((`Account`.`clientId` = `Client`.`id`))) left join `PublicLink` on((`Account`.`id` = `PublicLink`.`itemId`))) */; +/*!50013 SQL SECURITY DEFINER */ +/*!50001 VIEW `account_data_v` AS select `Account`.`id` AS `id`,`Account`.`name` AS `name`,`Account`.`categoryId` AS `categoryId`,`Account`.`userId` AS `userId`,`Account`.`clientId` AS `clientId`,`Account`.`userGroupId` AS `userGroupId`,`Account`.`userEditId` AS `userEditId`,`Account`.`login` AS `login`,`Account`.`url` AS `url`,`Account`.`notes` AS `notes`,`Account`.`countView` AS `countView`,`Account`.`countDecrypt` AS `countDecrypt`,`Account`.`dateAdd` AS `dateAdd`,`Account`.`dateEdit` AS `dateEdit`,conv(`Account`.`otherUserEdit`,10,2) AS `otherUserEdit`,conv(`Account`.`otherUserGroupEdit`,10,2) AS `otherUserGroupEdit`,conv(`Account`.`isPrivate`,10,2) AS `isPrivate`,conv(`Account`.`isPrivateGroup`,10,2) AS `isPrivateGroup`,`Account`.`passDate` AS `passDate`,`Account`.`passDateChange` AS `passDateChange`,`Account`.`parentId` AS `parentId`,`Category`.`name` AS `categoryName`,`Client`.`name` AS `clientName`,`ug`.`name` AS `userGroupName`,`u1`.`name` AS `userName`,`u1`.`login` AS `userLogin`,`u2`.`name` AS `userEditName`,`u2`.`login` AS `userEditLogin`,`PublicLink`.`hash` AS `publicLinkHash` from ((((((`Account` left join `Category` on(`Account`.`categoryId` = `Category`.`id`)) join `UserGroup` `ug` on(`Account`.`userGroupId` = `ug`.`id`)) join `User` `u1` on(`Account`.`userId` = `u1`.`id`)) join `User` `u2` on(`Account`.`userEditId` = `u2`.`id`)) left join `Client` on(`Account`.`clientId` = `Client`.`id`)) left join `PublicLink` on(`Account`.`id` = `PublicLink`.`itemId`)) */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; --- --- Final view structure for view `account_search_v` --- - /*!50001 DROP TABLE IF EXISTS `account_search_v`*/; /*!50001 DROP VIEW IF EXISTS `account_search_v`*/; /*!50001 SET @saved_cs_client = @@character_set_client */; @@ -694,8 +568,8 @@ SET character_set_client = @saved_cs_client; /*!50001 SET character_set_results = utf8 */; /*!50001 SET collation_connection = utf8_general_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ -/*!50013 DEFINER=`root`@`172.18.0.1` SQL SECURITY DEFINER */ -/*!50001 VIEW `account_search_v` AS select distinct `Account`.`id` AS `id`,`Account`.`clientId` AS `clientId`,`Account`.`categoryId` AS `categoryId`,`Account`.`name` AS `name`,`Account`.`login` AS `login`,`Account`.`url` AS `url`,`Account`.`notes` AS `notes`,`Account`.`userId` AS `userId`,`Account`.`userGroupId` AS `userGroupId`,`Account`.`otherUserEdit` AS `otherUserEdit`,`Account`.`otherUserGroupEdit` AS `otherUserGroupEdit`,`Account`.`isPrivate` AS `isPrivate`,`Account`.`isPrivateGroup` AS `isPrivateGroup`,`Account`.`passDate` AS `passDate`,`Account`.`passDateChange` AS `passDateChange`,`Account`.`parentId` AS `parentId`,`Account`.`countView` AS `countView`,`ug`.`name` AS `userGroupName`,`Category`.`name` AS `categoryName`,`Client`.`name` AS `customerName`,(select count(0) from `AccountFile` where (`AccountFile`.`accountId` = `Account`.`id`)) AS `num_files` from (((`Account` join `Category` on((`Account`.`categoryId` = `Category`.`id`))) join `UserGroup` `ug` on((`Account`.`userGroupId` = `ug`.`id`))) join `Client` on((`Client`.`id` = `Account`.`clientId`))) */; +/*!50013 SQL SECURITY DEFINER */ +/*!50001 VIEW `account_search_v` AS select distinct `Account`.`id` AS `id`,`Account`.`clientId` AS `clientId`,`Account`.`categoryId` AS `categoryId`,`Account`.`name` AS `name`,`Account`.`login` AS `login`,`Account`.`url` AS `url`,`Account`.`notes` AS `notes`,`Account`.`userId` AS `userId`,`Account`.`userGroupId` AS `userGroupId`,`Account`.`otherUserEdit` AS `otherUserEdit`,`Account`.`otherUserGroupEdit` AS `otherUserGroupEdit`,`Account`.`isPrivate` AS `isPrivate`,`Account`.`isPrivateGroup` AS `isPrivateGroup`,`Account`.`passDate` AS `passDate`,`Account`.`passDateChange` AS `passDateChange`,`Account`.`parentId` AS `parentId`,`Account`.`countView` AS `countView`,`ug`.`name` AS `userGroupName`,`Category`.`name` AS `categoryName`,`Client`.`name` AS `customerName`,(select count(0) from `AccountFile` where `AccountFile`.`accountId` = `Account`.`id`) AS `num_files` from (((`Account` join `Category` on(`Account`.`categoryId` = `Category`.`id`)) join `UserGroup` `ug` on(`Account`.`userGroupId` = `ug`.`id`)) join `Client` on(`Client`.`id` = `Account`.`clientId`)) */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -708,5 +582,3 @@ SET character_set_client = @saved_cs_client; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - --- Dump completed on 2018-01-01 13:45:54