From f8d15a2281dde13d60979e88bad06f12665a3199 Mon Sep 17 00:00:00 2001 From: Denis Flaven Date: Fri, 27 Mar 2009 15:14:45 +0000 Subject: [PATCH] - First implementation of an automated setup SVN:code[13] --- setup/index.php | 420 ++++++++++++++++++++++++++++++++++ setup/setuppage.class.inc.php | 149 ++++++++++++ 2 files changed, 569 insertions(+) create mode 100644 setup/index.php create mode 100644 setup/setuppage.class.inc.php diff --git a/setup/index.php b/setup/index.php new file mode 100644 index 0000000000..b301d5c9cc --- /dev/null +++ b/setup/index.php @@ -0,0 +1,420 @@ +no_cache(); + +/** + * Helper function to check if the current version of PHP + * is compatible with the application + * @return boolean true if this is Ok, false otherwise + */ +function CheckPHPVersion(nice_web_page $oP) +{ + if (version_compare(phpversion(), PHP_MIN_VERSION, '>=')) + { + $oP->ok("The current PHP Version (".phpversion().") is greater than the minimum required version (".PHP_MIN_VERSION.")"); + } + else + { + $oP->error("Error: The current PHP Version (".phpversion().") is lower than the minimum required version (".PHP_MIN_VERSION.")"); + return false; + } + if (extension_loaded('mysql')) + { + $oP->ok("The required extension 'mysql' is present."); + } + else + { + $oP->error("Error: missing required extension 'mysql'."); + return false; + } + return true; +} + +/** + * Helper function check the connection to the database and (if connected) to enumerate + * the existing databases + * @return Array The list of databases found in the server + */ +function CheckServerConnection(nice_web_page $oP, $sDBServer, $sDBUser, $sDBPwd) +{ + $aResult = array(); + try + { + $oDBSource = new CMDBSource; + $oDBSource->Init($sDBServer, $sDBUser, $sDBPwd); + $oP->ok("Connection to '$sDBServer' as '$sDBUser' successful."); + $sDBVersion = $oDBSource->GetDBVersion(); + if (version_compare($sDBVersion, MYSQL_MIN_VERSION, '>=')) + { + $oP->ok("Current MySQL version ($sDBVersion), greater than minimum required version (".MYSQL_MIN_VERSION.")"); + } + else + { + $oP->error("Error: Current MySQL version is ($sDBVersion), minimum required version (".MYSQL_MIN_VERSION.")"); + return false; + } + $aResult = $oDBSource->ListDB(); + } + catch(Exception $e) + { + $oP->error("Error: Connection to '$sDBServer' as '$sDBUser' failed."); + $oP->p($e->GetHtmlDesc()); + $aResult = false; + } + return $aResult; +} + +/** + * Helper function to create the database structure + * @return boolean true on success, false otherwise + */ +function CreateDatabaseStructure(nice_web_page $oP, Config $oConfig, $sDBName, $sDBPrefix) +{ + $oP->info("Creating the structure in '$sDBName' (prefix = '$sDBPrefix')."); + require_once('../core/coreexception.class.inc.php'); + require_once('../core/attributedef.class.inc.php'); + require_once('../core/filterdef.class.inc.php'); + require_once('../core/stimulus.class.inc.php'); + require_once('../core/MyHelpers.class.inc.php'); + require_once('../core/expression.class.inc.php'); + require_once('../core/cmdbsource.class.inc.php'); + require_once('../core/sqlquery.class.inc.php'); + require_once('../core/dbobject.class.php'); + require_once('../core/dbobjectsearch.class.php'); + require_once('../core/dbobjectset.class.php'); + require_once('../core/userrights.class.inc.php'); + MetaModel::Startup(TMP_CONFIG_FILE, true); // allow missing DB + //MetaModel::CheckDefinitions(); + if (!MetaModel::DBExists()) + { + MetaModel::DBCreate(); + $oP->ok("Database structure created in '$sDBName' (prefix = '$sDBPrefix')."); + } + else + { + $oP->error("Error: database '$sDBName' (prefix = '$sDBPrefix') already exists."); + return false; + } + return true; +} + +/** + * Helper function to create and administrator account for iTop + * @return boolean true on success, false otherwise + */ +function CreateAdminAccount(nice_web_page $oP, Config $oConfig, $sAdminUser, $sAdminPwd) +{ + require_once('../core/coreexception.class.inc.php'); + require_once('../core/attributedef.class.inc.php'); + require_once('../core/filterdef.class.inc.php'); + require_once('../core/stimulus.class.inc.php'); + require_once('../core/MyHelpers.class.inc.php'); + require_once('../core/expression.class.inc.php'); + require_once('../core/cmdbsource.class.inc.php'); + require_once('../core/sqlquery.class.inc.php'); + require_once('../core/dbobject.class.php'); + require_once('../core/dbobjectsearch.class.php'); + require_once('../core/dbobjectset.class.php'); + require_once('../core/userrights.class.inc.php'); + MetaModel::Startup(TMP_CONFIG_FILE, true); // allow missing DB + if (UserRights::CreateAdministrator($sAdminUser, $sAdminPwd)) + { + $oP->ok("Administrator account '$sAdminUser' created."); + return true; + } + else + { + $oP->error("Failed to create the administrator account '$sAdminUser'."); + return false; + } +} + +/** + * Helper function to load some sample data into the database + */ +function LoadSampleData(nice_web_page $oP) +{ + // TO BE IMPLEMENTED + $oP->ok("Sample data loaded into the database."); + return true; +} + +/** + * Display the form for the first step of the configuration wizard + * which consists in the database server selection + */ +function DisplayStep1(nice_web_page $oP) +{ + $sNextOperation = 'step2'; + $oP->add("

iTop configuration wizard

\n"); + $oP->add("

Checking prerequisites

\n"); + if (CheckPHPVersion($oP)) + { + $oP->add("

Step 1: Configuration of the database connection

\n"); + $oP->add("
\n"); + // Form goes here + $oP->add("
Database connection\n"); + $aForm = array(); + $aForm[] = array('label' => 'Server name:', 'input' => "", + 'help' => 'E.g. "localhost", "dbserver.mycompany.com" or "192.142.10.23".'); + $aForm[] = array('label' => 'User name:', 'input' => ""); + $aForm[] = array('label' => 'Password:', 'input' => ""); + $oP->form($aForm); + $oP->add("
\n"); + $oP->add("\n"); + $oP->add("\n"); + $oP->add("
\n"); + } +} + +/** + * Display the form for the second step of the configuration wizard + * which consists in + * 1) Validating the parameters by connecting to the database server + * 2) Prompting to select an existing database or to create a new one + */ +function DisplayStep2(nice_web_page $oP, Config $oConfig, $sDBServer, $sDBUser, $sDBPwd) +{ + $sNextOperation = 'step3'; + $oP->add("

iTop configuration wizard

\n"); + $oP->add("

Step 2: Database selection

\n"); + $oP->add("
\n"); + $aDatabases = CheckServerConnection($oP, $sDBServer, $sDBUser, $sDBPwd); + if ($aDatabases === false) + { + // Connection failed, invalid credentials ? Go back + $oP->add("\n"); + } + else + { + // Connection is Ok, save it and continue the setup wizard + $oConfig->SetDBHost($sDBServer); + $oConfig->SetDBUser($sDBUser); + $oConfig->SetDBPwd($sDBPwd); + $oConfig->WriteToFile(); + + $oP->add("
Specify a database\n"); + $aForm = array(); + foreach($aDatabases as $sDBName) + { + $aForm[] = array('label' => " $sDBName"); + } + $aForm[] = array('label' => " create a new database: "); + $oP->form($aForm); + + $oP->add("
\n"); + $aForm = array(); + $aForm[] = array('label' => "Add a prefix to all the tables: "); + $oP->form($aForm); + + $oP->add("\n"); + $oP->add("\n"); + $oP->add("    \n"); + $oP->add("\n"); + } + $oP->add("
\n"); +} + +/** + * Display the form for the third step of the configuration wizard + * which consists in + * 1) Validating the parameters by connecting to the database server & selecting the database + * 2) Creating the database structure + * 3) Prompting for the admin account to be created + */ +function DisplayStep3(nice_web_page $oP, Config $oConfig, $sDBName, $sDBPrefix) +{ + $sNextOperation = 'step4'; + $oP->add("

iTop configuration wizard

\n"); + $oP->add("

Creation of the database structure

\n"); + $oP->add("
\n"); + $oConfig->SetDBName($sDBName); + $oConfig->SetDBSubname($sDBPrefix); + $oConfig->WriteToFile(TMP_CONFIG_FILE); + if (CreateDatabaseStructure($oP, $oConfig, $sDBName, $sDBPrefix)) + { + $oP->add("

Step 3: Definition of the administrator account

\n"); + // Database created, continue with admin creation + $oP->add("
Administrator account\n"); + $aForm = array(); + $aForm[] = array('label' => "Login:", 'input' => ""); + $aForm[] = array('label' => "Password:", 'input' => ""); + $aForm[] = array('label' => "Retype password:", 'input' => ""); + $oP->form($aForm); + $oP->add("
\n"); + $oP->add("\n"); + $oP->add("\n"); + $oP->add("    \n"); + $oP->add("\n"); + } + else + { + $oP->add("\n"); + } + // Form goes here + $oP->add("
\n"); +} + +/** + * Display the form for the fourth step of the configuration wizard + * which consists in + * 1) Creating the admin user account + * 2) Prompting to load some sample data + */ +function DisplayStep4(nice_web_page $oP, Config $oConfig, $sAdminUser, $sAdminPwd) +{ + $sNextOperation = 'step5'; + $oP->add("

iTop configuration wizard

\n"); + $oP->add("

Creation of the administrator account

\n"); + + $oP->add("
\n"); + if (CreateAdminAccount($oP, $oConfig, $sAdminUser, $sAdminPwd)) + { + $oP->add("

Step 4: Loading of sample data

\n"); + $oP->p("
Do you want to load sample data into the database ? \n"); + $oP->p(" Yes, for testing purposes, populate the database with sample data.\n"); + $oP->p(" No, this is a production system, I will load real data myself.\n"); + $oP->p("
\n"); + $oP->add("\n"); // To be compatible with login page + $oP->add("\n"); // To be compatible with login page + $oP->add("\n"); + $oP->add("\n"); + $oP->add("    \n"); + $oP->add("\n"); + } + else + { + // Creation failed + $oP->add("\n"); + } + // Form goes here + $oP->add("
\n"); +} +/** + * Display the form for the fifth (and final) step of the configuration wizard + * which consists in + * 1) Creating the final configuration file + * 2) Prompting the user to make the file read-only + */ +function DisplayStep5(nice_web_page $oP, Config $oConfig, $sAuthUser, $sAuthPwd, $bLoadSampleData) +{ + try + { + session_start(); + + // Write the final configuration file + $oConfig->WriteToFile(FINAL_CONFIG_FILE); + + // Start the application + require_once('../application/application.inc.php'); + require_once('../application/startup.inc.php'); + if (UserRights::Login($sAuthUser, $sAuthPwd)) + { + $_SESSION['auth_user'] = $sAuthUser; + $_SESSION['auth_pwd'] = $sAuthPwd; + // remove the tmp config file + @unlink(TMP_CONFIG_FILE); + // try to make the final config file read-only + @chmod(FINAL_CONFIG_FILE, "a-w"); + + $oP->add("

iTop configuration wizard

\n"); + $oP->add("

Configuration completed

\n"); + $oP->add("
\n"); + if ($bLoadSampleData) + { + LoadSampleData($oP); + } + // Form goes here + $oP->add("\n"); + $oP->add("    \n"); + $oP->add("\n"); + $oP->add("
\n"); + } + else + { + $oP->add("

iTop configuration wizard

\n"); + $oP->add("

Step 5: Configuration completed

\n"); + + @unlink(FINAL_CONFIG_FILE); // remove the aborted config + $oP->error("Error: Failed to login for user: '$sAuthUser'\n"); + + $oP->add("
\n"); + $oP->add("\n"); + $oP->add("    \n"); + $oP->add("
\n"); + } + } + catch(Exception $e) + { + $oP->error("Error: unable to create the configuration file."); + $oP->p($e->getHtmlDesc()); + $oP->p("Did you forget to remove the previous (read-only) configuration file ?"); + } +} +/** + * Main program + */ +try +{ + $oConfig = new Config(TMP_CONFIG_FILE); +} +catch(Exception $e) +{ + // We'll end here when the tmp config file does not exist. It's normal + $oConfig = new Config(TMP_CONFIG_FILE, false /* Don't try to load it */); +} +switch($sOperation) +{ + case 'step1': + DisplayStep1($oP); + break; + + case 'step2': + $sDBServer = Utils::ReadParam('db_server'); + $sDBUser = Utils::ReadParam('db_user'); + $sDBPwd = Utils::ReadParam('db_pwd'); + DisplayStep2($oP, $oConfig, $sDBServer, $sDBUser, $sDBPwd); + break; + + case 'step3': + $sDBName = Utils::ReadParam('db_name'); + if (empty($sDBName)) + { + $sDBName = Utils::ReadParam('new_db_name'); + } + $sDBPrefix = Utils::ReadParam('db_prefix'); + DisplayStep3($oP, $oConfig, $sDBName, $sDBPrefix); + break; + + case 'step4': + $sAdminUser = Utils::ReadParam('auth_user'); + $sAdminPwd = Utils::ReadParam('auth_pwd'); + DisplayStep4($oP, $oConfig, $sAdminUser, $sAdminPwd); + break; + + case 'step5': + $bLoadSampleData = (Utils::ReadParam('sample_data', 'no') == 'yes'); + $sAdminUser = Utils::ReadParam('auth_user'); + $sAdminPwd = Utils::ReadParam('auth_pwd'); + DisplayStep5($oP, $oConfig, $sAdminUser, $sAdminPwd, $bLoadSampleData); + break; + + default: + $oP->error("Error: unsupported operation '$sOperation'"); + +} +$oP->output(); +?> diff --git a/setup/setuppage.class.inc.php b/setup/setuppage.class.inc.php new file mode 100644 index 0000000000..28579298a8 --- /dev/null +++ b/setup/setuppage.class.inc.php @@ -0,0 +1,149 @@ +add_style(" +body { + background-color: #eee; + margin: 0; + padding: 0; + font-size: 10pt; +} +#setup { + width: 600px; + margin-left: auto; + margin-right: auto; + margin-top: 50px; + padding: 20px; + background-color: #fff; + border: 1px solid #000; +} +.center { + text-align: center; +} + +h1 { + color: #83b217; + font-size: 16pt; +} +h2 { + color: #000; + font-size: 14pt; +} +.v-spacer { + padding-top: 1em; +} +button { + margin-top: 1em; + padding-left: 1em; + padding-right: 1em; +} +p.info { + padding-left: 50px; + background: url(../images/info-mid.png) no-repeat top left; + height: 48px; + line-height: 48px; +} +p.ok { + padding-left: 50px; + background: url(../images/clean-mid.png) no-repeat top left; + height: 48px; + line-height: 48px; +} +p.warning { + padding-left: 50px; + background: url(../images/messagebox_warning-mid.png) no-repeat top left; + height: 48px; + line-height: 48px; +} +p.error { + padding-left: 50px; + background: url(../images/stop-mid.png) no-repeat top left; + height: 48px; + line-height: 48px; +} +td.label { + text-align: left; +} +td.input { + text-align: left; +} +table.formTable { + border: 0; + cellpadding: 2px; + cellspacing: 0; +} +.wizlabel, .wizinput { + color: #000; + font-size: 10pt; +} +.wizhelp { + color: #333; + font-size: 8pt; +} + "); + } + public function info($sText) + { + $this->add("

$sText

\n"); + } + + public function ok($sText) + { + $this->add("

$sText

\n"); + } + + public function warning($sText) + { + $this->add("

$sText

\n"); + } + + public function error($sText) + { + $this->add("

$sText

\n"); + } + + public function form($aData) + { + $this->add("\n"); + foreach($aData as $aRow) + { + $this->add("\n"); + if (isset($aRow['label']) && isset($aRow['label']) && isset($aRow['help'])) + { + $this->add("\n"); + $this->add("\n"); + $this->add("\n"); + } + else if (isset($aRow['label']) && isset($aRow['help'])) + { + $this->add("\n"); + $this->add("\n"); + } + else if (isset($aRow['label']) && isset($aRow['input'])) + { + $this->add("\n"); + $this->add("\n"); + } + else if (isset($aRow['label'])) + { + $this->add("\n"); + } + $this->add("\n"); + } + $this->add("
{$aRow['label']}{$aRow['input']}{$aRow['help']}{$aRow['label']}{$aRow['help']}{$aRow['label']}{$aRow['input']}{$aRow['label']}
\n"); + } + + public function output() + { + $this->s_content = "
{$this->s_content}\n
\n"; + return parent::output(); + } +} // End of class +?>