diff --git a/index.php b/index.php index bee6a6619..ffe4c8a58 100644 --- a/index.php +++ b/index.php @@ -160,6 +160,8 @@ (isset($rssPage) && $rssPage) || (isset($xmlPage) && $xmlPage); $isMigrationGateExcluded = + (isset($_GET['m']) && $_GET['m'] === 'install' && + isset($_GET['a']) && $_GET['a'] === 'maint') || (isset($_GET['m']) && ($_GET['m'] === 'login' || $_GET['m'] === 'logout')); if ($_SESSION['CATS']->isLoggedIn() && diff --git a/js/install.js b/js/install.js index 035e819de..622e75df6 100755 --- a/js/install.js +++ b/js/install.js @@ -29,6 +29,7 @@ var response; var maxSteps; var installMaintNextAction = "a=reindexResumes"; +var maintenanceOnly = false; function setActiveStep(step) @@ -120,13 +121,31 @@ function Installpage_maint() response = http.responseText; + if (maintenanceOnly && + (http.status < 200 || + http.status >= 300 || + AJAX_isPHPError(response) || + response.indexOf("-1") != -1 || + response.indexOf("Query Error") != -1 || + response.indexOf("Access denied.") != -1)) + { + document.getElementById("maintenanceProgress").style.display = "none"; + document.getElementById("maintenanceError").style.display = ""; + document.getElementById("startMaintenance").disabled = false; + return; + } + if (response.indexOf("setProgressUpdating") == -1) - { - if (http.status == 200) - { - Installpage_populate(installMaintNextAction); - installMaintNextAction = "a=reindexResumes"; - } + { + if (maintenanceOnly) + { + window.location = "index.php"; + } + else if (http.status == 200) + { + Installpage_populate(installMaintNextAction); + installMaintNextAction = "a=reindexResumes"; + } } else { diff --git a/lib/ModuleUtility.php b/lib/ModuleUtility.php index 8a2b70e01..3d638e036 100755 --- a/lib/ModuleUtility.php +++ b/lib/ModuleUtility.php @@ -35,6 +35,8 @@ * @package CATS * @subpackage Library */ +include_once(LEGACY_ROOT . '/lib/SchemaMigrationStatus.php'); + class ModuleUtility { /* Prevent this class from being instantiated. */ @@ -508,7 +510,11 @@ private static function processModuleSchema($moduleName, $schema) if ($moduleName === 'install' && ($currentVersion === NULL || $currentVersion === '')) { - /* A NULL install module version means the database came from cats_schema.sql and should not replay historical install migrations. */ + /* This explicit installer/maintenance finalization is only for + * snapshot databases whose schema already matches the bundled + * baseline. It must not run during normal requests and is not + * proof that an unknown historical database state is current. + */ $sql = sprintf( "UPDATE module_schema @@ -521,6 +527,7 @@ private static function processModuleSchema($moduleName, $schema) ); $db->query($sql); + SchemaMigrationStatus::clearCache(); return; } @@ -592,6 +599,11 @@ private static function processModuleSchema($moduleName, $schema) $rs = $db->query($sql); $currentVersion = $version; + + if ($moduleName === 'install') + { + SchemaMigrationStatus::clearCache(); + } } } } diff --git a/modules/install/CATSUI.php b/modules/install/CATSUI.php index a1fdd2380..c2e264d1d 100755 --- a/modules/install/CATSUI.php +++ b/modules/install/CATSUI.php @@ -41,6 +41,34 @@ public function __construct() public function handleRequest() { + if ($this->getAction() !== 'maint') + { + return; + } + + if (!isset($_SESSION['CATS']) || !$_SESSION['CATS']->isLoggedIn()) + { + CATSUtility::transferRelativeURI('m=login'); + die(); + } + + if ($_SESSION['CATS']->getAccessLevel(ACL::SECOBJ_ROOT) < ACCESS_LEVEL_SA) + { + header('HTTP/1.1 403 Forbidden'); + CommonErrors::fatal(COMMONERROR_PERMISSION, $this); + } + + if (!SchemaMigrationStatus::hasPendingInstallMigrations()) + { + CATSUtility::transferRelativeURI(''); + die(); + } + + $this->_template->assign( + 'csrfToken', + $_SESSION['CATS']->getCSRFToken() + ); + $this->_template->display('./modules/install/Maintenance.tpl'); } } diff --git a/modules/install/Maintenance.tpl b/modules/install/Maintenance.tpl new file mode 100644 index 000000000..e157b666f --- /dev/null +++ b/modules/install/Maintenance.tpl @@ -0,0 +1,45 @@ + + + + + OpenCATS - Database Maintenance + + + + + + + + +
+
+ +
+ +
+
+
+ Database Maintenance +

Database migrations are pending. OpenCATS should be updated before normal use continues.

+

+ + + + + +
+
+
+ + diff --git a/modules/install/ajax/maint.php b/modules/install/ajax/maint.php index 3a3fba924..374a4119e 100755 --- a/modules/install/ajax/maint.php +++ b/modules/install/ajax/maint.php @@ -29,27 +29,47 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - header('Content-Type: text/html; charset=UTF-8'); - - $actionURL = htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES, 'UTF-8'); - - echo '', - 'OpenCATS Maintenance', - '

This maintenance action must be triggered via POST.

', - '

This page starts maintenance mode and related installer tasks.

', - '
', - '', - '', - '
', - ''; + header('HTTP/1.1 405 Method Not Allowed'); + header('Allow: POST'); die(); } +$installerActive = !file_exists('INSTALL_BLOCK'); + +if (!$installerActive) +{ + /* Fresh installation uses the installer's existing access model. An + * installed system requires an authenticated site admin and CSRF token. + */ + include_once('./config.php'); + include_once(LEGACY_ROOT . '/constants.php'); + include_once(LEGACY_ROOT . '/lib/DatabaseConnection.php'); + include_once(LEGACY_ROOT . '/lib/Session.php'); + + @session_name(CATS_SESSION_NAME); + @session_start(); + + if (!isset($_SESSION['CATS']) || + !$_SESSION['CATS']->isLoggedIn() || + $_SESSION['CATS']->getAccessLevel(ACL::SECOBJ_ROOT) < ACCESS_LEVEL_SA || + !isset($_POST['csrfToken']) || + !$_SESSION['CATS']->isCSRFTokenValid($_POST['csrfToken'])) + { + header('HTTP/1.1 403 Forbidden'); + die('Access denied.'); + } +} + if (file_exists('./modules.cache')) { @unlink('./modules.cache'); } +if (isset($_SESSION['modules'])) +{ + unset($_SESSION['modules']); +} + $maintPage = true; include_once('index.php'); diff --git a/modules/login/PendingMigrations.tpl b/modules/login/PendingMigrations.tpl index 50fa74fc7..21f4bf04a 100644 --- a/modules/login/PendingMigrations.tpl +++ b/modules/login/PendingMigrations.tpl @@ -21,7 +21,7 @@ isAdministrator): ?>

Database migrations are pending. OpenCATS should be updated before normal use continues.

-

Open the Installation Wizard to complete the upgrade.

+

Start Maintenance

Database maintenance is required before OpenCATS can be used normally. Please contact your administrator.