From ee9163fa8e2aa3e87f8be8d0e1534f26ddcde4cc Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Thu, 15 Jan 2015 12:42:36 -0500 Subject: [PATCH] 2.5.2: Reorganize upgrade path so that 2.5.2 contains the show art schema changes * Also bump the system_version number to 2.5.2. This will be deprecated sooner or later... --- airtime_mvc/application/configs/constants.php | 1 + .../controllers/UpgradeController.php | 78 +++++ .../upgrade_sql/airtime_2.5.3/upgrade.sql | 6 + .../upgrade_sql/airtime_2.5.5/upgrade.sql | 5 + airtime_mvc/application/upgrade/Upgrades.php | 292 ++++++++++++++++++ airtime_mvc/build/sql/defaultdata.sql | 3 + 6 files changed, 385 insertions(+) create mode 100644 airtime_mvc/application/controllers/UpgradeController.php create mode 100644 airtime_mvc/application/controllers/upgrade_sql/airtime_2.5.3/upgrade.sql create mode 100644 airtime_mvc/application/controllers/upgrade_sql/airtime_2.5.5/upgrade.sql create mode 100644 airtime_mvc/application/upgrade/Upgrades.php diff --git a/airtime_mvc/application/configs/constants.php b/airtime_mvc/application/configs/constants.php index 7b27bc891..45bdbd123 100644 --- a/airtime_mvc/application/configs/constants.php +++ b/airtime_mvc/application/configs/constants.php @@ -19,6 +19,7 @@ define('LICENSE_URL' , 'http://www.gnu.org/licenses/agpl-3.0-standalone.h define('AIRTIME_COPYRIGHT_DATE' , '2010-2012'); define('AIRTIME_REST_VERSION' , '1.1'); define('AIRTIME_API_VERSION' , '1.1'); +define('AIRTIME_CODE_VERSION' , '2.5.2'); // Metadata Keys for files define('MDATA_KEY_FILEPATH' , 'filepath'); diff --git a/airtime_mvc/application/controllers/UpgradeController.php b/airtime_mvc/application/controllers/UpgradeController.php new file mode 100644 index 000000000..2691f270f --- /dev/null +++ b/airtime_mvc/application/controllers/UpgradeController.php @@ -0,0 +1,78 @@ +view->layout()->disableLayout(); + $this->_helper->viewRenderer->setNoRender(true); + + if (!$this->verifyAuth()) { + return; + } + + $upgraders = array(); + array_push($upgraders, new AirtimeUpgrader252()); + /* These upgrades do not apply to open source Airtime yet. + array_push($upgraders, new AirtimeUpgrader253()); + array_push($upgraders, new AirtimeUpgrader254()); + */ + $didWePerformAnUpgrade = false; + try + { + for ($i = 0; $i < count($upgraders); $i++) + { + $upgrader = $upgraders[$i]; + if ($upgrader->checkIfUpgradeSupported()) + { + // pass __DIR__ to the upgrades, since __DIR__ returns parent dir of file, not executor + $upgrader->upgrade(__DIR__); //This will throw an exception if the upgrade fails. + $didWePerformAnUpgrade = true; + $this->getResponse() + ->setHttpResponseCode(200) + ->appendBody("Upgrade to Airtime " . $upgrader->getNewVersion() . " OK
"); + $i = 0; //Start over, in case the upgrade handlers are not in ascending order. + } + } + + if (!$didWePerformAnUpgrade) + { + $this->getResponse() + ->setHttpResponseCode(200) + ->appendBody("No upgrade was performed. The current Airtime version is " . AirtimeUpgrader::getCurrentVersion() . ".
"); + } + } + catch (Exception $e) + { + $this->getResponse() + ->setHttpResponseCode(400) + ->appendBody($e->getMessage()); + } + } + + private function verifyAuth() + { + //The API key is passed in via HTTP "basic authentication": + //http://en.wikipedia.org/wiki/Basic_access_authentication + + $CC_CONFIG = Config::getConfig(); + + //Decode the API key that was passed to us in the HTTP request. + $authHeader = $this->getRequest()->getHeader("Authorization"); + + $encodedRequestApiKey = substr($authHeader, strlen("Basic ")); + $encodedStoredApiKey = base64_encode($CC_CONFIG["apiKey"][0] . ":"); + + if ($encodedRequestApiKey !== $encodedStoredApiKey) + { + $this->getResponse() + ->setHttpResponseCode(401) + ->appendBody("Error: Incorrect API key.
"); + return false; + } + return true; + } + +} diff --git a/airtime_mvc/application/controllers/upgrade_sql/airtime_2.5.3/upgrade.sql b/airtime_mvc/application/controllers/upgrade_sql/airtime_2.5.3/upgrade.sql new file mode 100644 index 000000000..6c7980983 --- /dev/null +++ b/airtime_mvc/application/controllers/upgrade_sql/airtime_2.5.3/upgrade.sql @@ -0,0 +1,6 @@ +DELETE FROM cc_pref WHERE keystr = 'system_version'; +INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '2.5.3'); + +ALTER TABLE cc_files DROP COLUMN state; +ALTER TABLE cc_files ADD import_status integer default 1; -- Default is "pending" +UPDATE cc_files SET import_status=0; -- Existing files are already "imported" diff --git a/airtime_mvc/application/controllers/upgrade_sql/airtime_2.5.5/upgrade.sql b/airtime_mvc/application/controllers/upgrade_sql/airtime_2.5.5/upgrade.sql new file mode 100644 index 000000000..191eb2084 --- /dev/null +++ b/airtime_mvc/application/controllers/upgrade_sql/airtime_2.5.5/upgrade.sql @@ -0,0 +1,5 @@ +DELETE FROM cc_pref WHERE keystr = 'system_version'; +INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '2.5.5'); + +ALTER TABLE cc_show ADD COLUMN image_path varchar(255) DEFAULT ''; +ALTER TABLE cc_show_instances ADD COLUMN description varchar(255) DEFAULT ''; diff --git a/airtime_mvc/application/upgrade/Upgrades.php b/airtime_mvc/application/upgrade/Upgrades.php new file mode 100644 index 000000000..f95216bd0 --- /dev/null +++ b/airtime_mvc/application/upgrade/Upgrades.php @@ -0,0 +1,292 @@ +filterByKeystr('system_version') + ->findOne(); + $airtime_version = $pref->getValStr(); + return $airtime_version; + } + + /** + * This function checks to see if this class can perform an upgrade of your version of Airtime + * @return boolean True if we can upgrade your version of Airtime. + */ + public function checkIfUpgradeSupported() + { + if (!in_array(AirtimeUpgrader::getCurrentVersion(), $this->getSupportedVersions())) { + return false; + } + return true; + } + + protected function toggleMaintenanceScreen($toggle) + { + if ($toggle) + { + //Disable Airtime UI + //create a temporary maintenance notification file + //when this file is on the server, zend framework redirects all + //requests to the maintenance page and sets a 503 response code + $this->maintenanceFile = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."maintenance.txt" : "/tmp/maintenance.txt"; + $file = fopen($this->maintenanceFile, 'w'); + fclose($file); + } else { + //delete maintenance.txt to give users access back to Airtime + if ($this->maintenanceFile) { + unlink($this->maintenanceFile); + } + } + } + + /** Implement this for each new version of Airtime */ + abstract public function upgrade(); +} + +/** This upgrade adds schema changes to accommodate show artwork and show instance descriptions */ +class AirtimeUpgrader252 extends AirtimeUpgrader { + protected function getSupportedVersions() { + return array ( + '2.5.1' + ); + } + + public function getNewVersion() { + return '2.5.2'; + } + + public function upgrade($dir = __DIR__) { + Cache::clear(); + assert($this->checkIfUpgradeSupported()); + + $newVersion = $this->getNewVersion(); + + try { + $this->toggleMaintenanceScreen(true); + Cache::clear(); + + // Begin upgrade + $airtimeConf = isset($_SERVER['AIRTIME_CONF']) ? $_SERVER['AIRTIME_CONF'] : "/etc/airtime/airtime.conf"; + $values = parse_ini_file($airtimeConf, true); + + $username = $values['database']['dbuser']; + $password = $values['database']['dbpass']; + $host = $values['database']['host']; + $database = $values['database']['dbname']; + + passthru("export PGPASSWORD=$password && psql -h $host -U $username -q -f $dir/upgrade_sql/airtime_" + .$this->getNewVersion()."/upgrade.sql $database 2>&1 | grep -v \"will create implicit index\""); + + Application_Model_Preference::SetAirtimeVersion($newVersion); + Cache::clear(); + + $this->toggleMaintenanceScreen(false); + + return true; + } catch(Exception $e) { + $this->toggleMaintenanceScreen(false); + throw $e; + } + } +} + +class AirtimeUpgrader253 extends AirtimeUpgrader +{ + protected function getSupportedVersions() + { + return array('2.5.2'); + } + public function getNewVersion() + { + return '2.5.3'; + } + + public function upgrade($dir = __DIR__) + { + Cache::clear(); + assert($this->checkIfUpgradeSupported()); + + $con = Propel::getConnection(); + $con->beginTransaction(); + try { + + $this->toggleMaintenanceScreen(true); + Cache::clear(); + + //Begin upgrade + + //Update disk_usage value in cc_pref + $musicDir = CcMusicDirsQuery::create() + ->filterByType('stor') + ->filterByExists(true) + ->findOne(); + $storPath = $musicDir->getDirectory(); + + //Update disk_usage value in cc_pref + $storDir = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."srv/airtime/stor" : "/srv/airtime/stor"; + $diskUsage = shell_exec("du -sb $storDir | awk '{print $1}'"); + + Application_Model_Preference::setDiskUsage($diskUsage); + + //clear out the cache + Cache::clear(); + + $con->commit(); + + //update system_version in cc_pref and change some columns in cc_files + $airtimeConf = isset($_SERVER['AIRTIME_CONF']) ? $_SERVER['AIRTIME_CONF'] : "/etc/airtime/airtime.conf"; + $values = parse_ini_file($airtimeConf, true); + + $username = $values['database']['dbuser']; + $password = $values['database']['dbpass']; + $host = $values['database']['host']; + $database = $values['database']['dbname']; + + passthru("export PGPASSWORD=$password && psql -h $host -U $username -q -f $dir/upgrade_sql/airtime_".$this->getNewVersion()."/upgrade.sql $database 2>&1 | grep -v \"will create implicit index\""); + + Application_Model_Preference::SetAirtimeVersion($this->getNewVersion()); + //clear out the cache + Cache::clear(); + + $this->toggleMaintenanceScreen(false); + + } catch (Exception $e) { + $con->rollback(); + $this->toggleMaintenanceScreen(false); + } + } +} + +class AirtimeUpgrader254 extends AirtimeUpgrader +{ + protected function getSupportedVersions() + { + return array('2.5.3'); + } + public function getNewVersion() + { + return '2.5.4'; + } + + public function upgrade() + { + Cache::clear(); + + assert($this->checkIfUpgradeSupported()); + + $newVersion = $this->getNewVersion(); + + $con = Propel::getConnection(); + //$con->beginTransaction(); + try { + $this->toggleMaintenanceScreen(true); + Cache::clear(); + + //Begin upgrade + + //First, ensure there are no superadmins already. + $numberOfSuperAdmins = CcSubjsQuery::create() + ->filterByDbType(UTYPE_SUPERADMIN) + ->filterByDbLogin("sourcefabric_admin", Criteria::NOT_EQUAL) //Ignore sourcefabric_admin users + ->count(); + + //Only create a super admin if there isn't one already. + if ($numberOfSuperAdmins == 0) + { + //Find the "admin" user and promote them to superadmin. + $adminUser = CcSubjsQuery::create() + ->filterByDbLogin('admin') + ->findOne(); + if (!$adminUser) + { + //TODO: Otherwise get the user with the lowest ID that is of type administrator: + // + $adminUser = CcSubjsQuery::create() + ->filterByDbType(UTYPE_ADMIN) + ->orderByDbId(Criteria::ASC) + ->findOne(); + + if (!$adminUser) { + throw new Exception("Failed to find any users of type 'admin' ('A')."); + } + } + + $adminUser = new Application_Model_User($adminUser->getDbId()); + $adminUser->setType(UTYPE_SUPERADMIN); + $adminUser->save(); + Logging::info($_SERVER['HTTP_HOST'] . ': ' . $newVersion . " Upgrade: Promoted user " . $adminUser->getLogin() . " to be a Super Admin."); + + //Also try to promote the sourcefabric_admin user + $sofabAdminUser = CcSubjsQuery::create() + ->filterByDbLogin('sourcefabric_admin') + ->findOne(); + if ($sofabAdminUser) { + $sofabAdminUser = new Application_Model_User($sofabAdminUser->getDbId()); + $sofabAdminUser->setType(UTYPE_SUPERADMIN); + $sofabAdminUser->save(); + Logging::info($_SERVER['HTTP_HOST'] . ': ' . $newVersion . " Upgrade: Promoted user " . $sofabAdminUser->getLogin() . " to be a Super Admin."); + } + } + + //$con->commit(); + Application_Model_Preference::SetAirtimeVersion($newVersion); + Cache::clear(); + + $this->toggleMaintenanceScreen(false); + + return true; + + } catch(Exception $e) { + //$con->rollback(); + $this->toggleMaintenanceScreen(false); + throw $e; + } + } +} + +/* We are skipping 2.5.5 because it used to be the Show Artwork. + * + * DO NOT USE schema version 2.5.5! + */ + + +/** This is a stub. Please implement this 2.5.6 upgrader for the next schema change that we need. + * (It's setup to upgrade from 2.5.4 and 2.5.5 - this is a must due to the 2.5.5 schema being phase out. Long story... + * + */ +class AirtimeUpgrader256 extends AirtimeUpgrader { + protected function getSupportedVersions() { + return array ( + '2.5.4', '2.5.5' + ); + } + + public function getNewVersion() { + return '2.5.6'; + } + + public function upgrade($dir = __DIR__) { + Cache::clear(); + assert($this->checkIfUpgradeSupported()); + + $newVersion = $this->getNewVersion(); + + try { + //TODO: Implement this + return true; + } catch(Exception $e) { + $this->toggleMaintenanceScreen(false); + throw $e; + } + } +} diff --git a/airtime_mvc/build/sql/defaultdata.sql b/airtime_mvc/build/sql/defaultdata.sql index af82be2b8..94e478fcb 100644 --- a/airtime_mvc/build/sql/defaultdata.sql +++ b/airtime_mvc/build/sql/defaultdata.sql @@ -1,3 +1,6 @@ +-- Schema version +INSERT INTO cc_pref("keystr", "valstr") VALUES('system_version', '2.5.2'); + INSERT INTO cc_subjs ("login", "type", "pass") VALUES ('admin', 'A', md5('admin')); -- added in 2.3 INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('off_air_meta', 'Airtime - offline', 'string');