feat: remove php web installer

This commit is contained in:
jo 2022-04-29 14:43:45 +02:00 committed by Kyle Robbertze
parent eb8e7b3415
commit 0d16960887
15 changed files with 7 additions and 1063 deletions

View File

@ -4,7 +4,6 @@
define('ROOT_PATH', dirname(__DIR__, 2));
define('LIB_PATH', ROOT_PATH . '/library');
define('BUILD_PATH', ROOT_PATH . '/build');
define('SETUP_PATH', BUILD_PATH . '/airtime-setup');
define('APPLICATION_PATH', ROOT_PATH . '/application');
define('CONFIG_PATH', APPLICATION_PATH . '/configs');
define('VENDOR_PATH', ROOT_PATH . '/vendor');
@ -24,10 +23,6 @@ define('LIBRETIME_CONFIG_DIR', getenv('LIBRETIME_CONFIG_DIR') ?: '/etc/libretime
define('LIBRETIME_CONF_DIR', LIBRETIME_CONFIG_DIR); // Deprecated
define('LIBRETIME_CONFIG_FILEPATH', getenv('LIBRETIME_CONFIG_FILEPATH') ?: LIBRETIME_CONFIG_DIR . '/config.yml');
// Installer
define('INSTALLER_CONFIG_FILEPATH', LIBRETIME_CONFIG_DIR . '/airtime.temp.conf');
define('INSTALLER_DEFAULT_STORAGE_PATH', '/srv/airtime/stor');
// Legacy constants
define('PRODUCT_NAME', 'LibreTime');
define('PRODUCT_SITE_URL', 'http://libretime.org');

View File

@ -1,49 +0,0 @@
<?php
$tempConfigPath = INSTALLER_CONFIG_FILEPATH;
if (file_exists($tempConfigPath)) {
$airtimeConfig = parse_ini_file($tempConfigPath, true);
$db = $airtimeConfig['database'];
}
?>
<form action="#" role="form" id="dbSettingsForm">
<h3 class="form-title">Database Settings</h3>
<span id="helpBlock" class="help-block help-message"></span>
<p>
Enter your Airtime database settings here. Empty or non-existent databases will be created and populated
if the given user has administrative permissions in postgres.
</p>
<div class="form-group">
<label class="control-label" for="dbUser">Username</label>
<input required class="form-control" type="text" name="dbUser" id="dbUser" placeholder="Username" value="<?php echo isset($db) ? $db['user'] : 'airtime'; ?>" />
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
</div>
<div class="form-group">
<label class="control-label" for="dbPass">Password</label>
<input required class="form-control" type="password" name="dbPass" id="dbPass" placeholder="Password" value="<?php echo isset($db) ? $db['password'] : 'airtime'; ?>" />
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
</div>
<div class="form-group">
<label class="control-label" for="dbName">Name</label>
<input required class="form-control" type="text" name="dbName" id="dbName" placeholder="Name" value="<?php echo isset($db) ? $db['name'] : 'airtime'; ?>" />
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
</div>
<div class="form-group">
<label class="control-label" for="dbHost">Host</label>
<input required class="form-control" type="text" name="dbHost" id="dbHost" placeholder="Host" value="<?php echo isset($db) ? $db['host'] : 'localhost'; ?>" />
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
</div>
<input class="form-control" type="hidden" name="dbErr" id="dbErr" aria-describedby="helpBlock" />
<div>
<p style="text-align:right">
This may take up to 30 seconds to complete!
</p>
<input type="submit" formtarget="dbSettingsForm" class="btn btn-primary btn-next" value="Next &#10097;" />
</div>
</form>
<script>
$("#dbSettingsForm").submit(function(e) {
submitForm(e, "DatabaseSetup");
});
</script>

View File

@ -1,32 +0,0 @@
<?php
?>
<form action="#" role="form" id="finishSettingsForm">
<h3 class="form-title">Manual Step: Start Libretime Services</h3>
<span id="helpBlock" class="help-block help-message"></span>
<p>
Looks like you're almost done! As a final step, please run the following commands from the terminal:
</p>
<pre style="text-align: left">sudo systemctl start libretime-analyzer
sudo systemctl start libretime-api
sudo systemctl start libretime-celery
sudo systemctl start libretime-liquidsoap
sudo systemctl start libretime-playout</pre>
<p>
Click "Done!" to bring up the Libretime configuration checklist; if your configuration is all green,
you're ready to get started with your personal Libretime station!
</p>
<p>
If you need to re-run the web installer, just remove <code><?php echo LIBRETIME_CONFIG_FILEPATH; ?></code>.
</p>
<div>
<input type="submit" formtarget="finishSettingsForm" class="btn btn-primary btn-next" value="Done!" />
</div>
</form>
<script>
$("#finishSettingsForm").submit(function(e) {
e.preventDefault();
window.location.assign("/?config");
});
</script>

View File

@ -1,43 +0,0 @@
<?php
?>
<form action="#" role="form" id="generalSettingsForm">
<h3 class="form-title">General Settings</h3>
<span id="helpBlock" class="help-block help-message"></span>
<div id="generalFormBody">
<div class="form-group">
<label class="control-label" for="publicUrl">Public URL</label>
<input required class="form-control" type="text" name="publicUrl" id="publicUrl" placeholder="https://example.com/" />
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
</div>
<input class="form-control" type="hidden" name="generalErr" id="generalErr" aria-describedby="helpBlock" />
<hr />
<p>
The CORS URL can be setup during install if you are accessing your LibreTime instance behind a Proxy.
This is common with docker setups. If you have a reverse proxy setup enter the URL below, otherwise you
can safely ignore this. Please enter one URL per line. Include the entire URL such as http://example.com
If you are reinstalling LibreTime on an existing setup you can ignore this as well,
the settings in your existing database will be retained unless you enter new values below.
</p>
<div class="form-group">
<label class="control-label" for="corsUrl">CORS URLs</label>
<textarea name="corsUrl" class="form-control" id="corsUrl" rows="4" cols="50"></textarea>
</div>
</div>
<div>
<input type="submit" formtarget="generalSettingsForm" class="btn btn-primary btn-next" value="Next &#10097;" />
<input type="button" class="btn btn-primary btn-back" value="&#10096; Back" />
</div>
</form>
<script>
$("#publicUrl").val(function() {
return window.location.href;
});
$("#corsUrl").text(function() {
return window.location.origin;
});
$("#generalSettingsForm").submit(function(e) {
submitForm(e, "GeneralSetup");
});
</script>

View File

@ -1,30 +0,0 @@
<?php
?>
<form action="#" role="form" id="mediaSettingsForm">
<h3 class="form-title">Media Settings</h3>
<span id="helpBlock" class="help-block help-message"></span>
<p>
Here you can set the default media storage directory for Airtime. If left blank, we'll create a new
directory located at <code><?php echo INSTALLER_DEFAULT_STORAGE_PATH; ?></code> for you.
</p>
<div class="form-group">
<label class="control-label" for="mediaFolder">Media folder</label>
<input class="form-control" type="text" name="mediaFolder" id="mediaFolder" placeholder="/path/to/my/music/directory/" />
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
<span id="mediaHelpBlock" class="help-block">
Note that you need to enter the <strong>fully qualified</strong> path name!
</span>
</div>
<input class="form-control" type="hidden" name="mediaErr" id="mediaErr" aria-describedby="helpBlock"/>
<div>
<input type="submit" formtarget="mediaSettingsForm" class="btn btn-primary btn-next" value="Next &#10097;"/>
<input type="button" class="btn btn-primary btn-back" value="&#10096; Back"/>
</div>
</form>
<script>
$("#mediaSettingsForm").submit(function(e) {
submitForm(e, "MediaSetup");
});
</script>

View File

@ -1,77 +0,0 @@
<?php
$tempConfigPath = INSTALLER_CONFIG_FILEPATH;
if (file_exists($tempConfigPath)) {
$airtimeConfig = parse_ini_file($tempConfigPath, true);
$rmq = $airtimeConfig['rabbitmq'];
}
?>
<form action="#" role="form" id="rmqSettingsForm">
<h3 class="form-title">RabbitMQ Settings</h3>
<span id="helpBlock" class="help-block help-message"></span>
<p>
RabbitMQ is an AMQP-based messaging system used by Libretime. You should only edit these settings
if you have changed the defaults since running the installer, or if you've opted to install RabbitMQ manually.
</p>
<p>
In either case, we recommend that you change at least the default password provided -
you can do this by running the following line from the command line:<br/>
<code>sudo rabbitmqctl change_password &lt;username&gt; &lt;newpassword&gt;</code><br/>
<strong>Notice:</strong> using special characters such as ! in your rabbitmq password will cause LibreTime to fail
to load properly after setup. Please use alphanumerical characters only.
</p>
<div id="rmqSlideToggle">
<span><strong>Advanced </strong></span><span id="advCaret" class="caret"></span><hr/>
</div>
<div id="rmqFormBody">
<div class="form-group">
<label class="control-label" for="rmqUser">Username</label>
<input required class="form-control" type="text" name="rmqUser" id="rmqUser" placeholder="Username"
value="<?php echo isset($rmq) ? $rmq['user'] : 'airtime'; ?>" />
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
</div>
<div class="form-group">
<label class="control-label" for="rmqPass">Password</label>
<input class="form-control" type="password" name="rmqPass" id="rmqPass" placeholder="Password"
value="<?php echo isset($rmq) ? $rmq['password'] : 'airtime'; ?>" />
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
<span id="rmqHelpBlock" class="help-block">
You probably want to change this!
</span>
</div>
<div class="form-group">
<label class="control-label" for="rmqHost">Host</label>
<input required class="form-control" type="text" name="rmqHost" id="rmqHost" placeholder="Host"
value="<?php echo isset($rmq) ? $rmq['host'] : '127.0.0.1'; ?>" />
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
</div>
<div class="form-group">
<label class="control-label" for="rmqPort">Port</label>
<input required class="form-control" type="text" name="rmqPort" id="rmqPort" placeholder="Port"
value="<?php echo isset($rmq) ? $rmq['port'] : '5672'; ?>" />
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
</div>
<div class="form-group">
<label class="control-label" for="rmqVHost">Virtual Host</label>
<input required class="form-control" type="text" name="rmqVHost" id="rmqVHost" placeholder="VHost"
value="<?php echo isset($rmq) ? $rmq['vhost'] : '/airtime'; ?>" />
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
</div>
<input class="form-control" type="hidden" name="rmqErr" id="rmqErr" aria-describedby="helpBlock"/>
</div>
<div>
<input type="submit" formtarget="rmqSettingsForm" class="btn btn-primary btn-next" value="Next &#10097;"/>
<input type="button" class="btn btn-primary btn-back" value="&#10096; Back"/>
</div>
</form>
<script>
$("#rmqSlideToggle").click(function() {
$("#rmqFormBody").slideToggle(500);
$("#advCaret").toggleClass("caret-up");
});
$("#rmqSettingsForm").submit(function(e) {
submitForm(e, "RabbitMQSetup");
});
</script>

View File

@ -1,60 +0,0 @@
<?php
require_once dirname(__DIR__, 2) . '/application/preload.php';
?>
<html>
<head>
<script type="text/javascript" src="js/libs/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="js/libs/jquery-ui-1.8.24.min.js"></script>
<script type="text/javascript" src="js/setup/setup-config.js"></script>
<link rel="stylesheet" type="text/css" href="css/bootstrap-3.3.1.min.css" />
<link rel="stylesheet" type="text/css" href="css/setup/setup-config.css" />
</head>
<body>
<div class="header">
<h3 class="logo">
<img src="css/images/libretime_logo_jp.png" id="LibreTimeLogo" /><br/>
<strong>Setup</strong>
</h3>
<strong>Step <span id="stepCount">1</span> of 5</strong>
</div>
<div class="viewport">
<div class="form-slider">
<div id="databaseSettings" class="form-wrapper">
<?php
require_once SETUP_PATH . '/forms/database-settings.php';
?>
</div>
<div id="rabbitmqSettings" class="form-wrapper">
<?php
require_once SETUP_PATH . '/forms/rabbitmq-settings.php';
?>
</div>
<div id="generalSettings" class="form-wrapper">
<?php
require_once SETUP_PATH . '/forms/general-settings.php';
?>
</div>
<div id="mediaSettings" class="form-wrapper">
<?php
require_once SETUP_PATH . '/forms/media-settings.php';
?>
</div>
<div id="finishSettings" class="form-wrapper">
<?php
require_once SETUP_PATH . '/forms/finish-settings.php';
?>
</div>
</div>
</div>
<script>
$(".btn-skip").click(nextSlide);
$(".btn-back").click(prevSlide);
</script>
</body>
</html>

View File

@ -2,6 +2,11 @@
require_once dirname(__DIR__) . '/application/preload.php';
// Early exit if a configuration file does not exists!
if (!file_exists(LIBRETIME_CONFIG_FILEPATH)) {
exit("could not find a configuration file at '{$LIBRETIME_CONFIG_FILEPATH}', please make sure it is properly set!");
}
$configRun = false;
$extensions = get_loaded_extensions();
$airtimeSetup = false;
@ -40,7 +45,7 @@ if (!class_exists('Propel')) {
exit('Error: Propel not found. Did you install Airtime\'s third-party dependencies with composer? (Check the README.)');
}
require_once SETUP_PATH . '/load.php';
require_once APPLICATION_PATH . '/check.php';
// This allows us to pass ?config as a parameter to any page
// and get to the config checklist.
@ -48,13 +53,4 @@ if (array_key_exists('config', $_GET)) {
showConfigCheckPage();
}
// If a configuration file exists, forward to our boot script
if (file_exists(LIBRETIME_CONFIG_FILEPATH)) {
require_once APPLICATION_PATH . '/airtime-boot.php';
}
// Otherwise, we'll need to run our configuration setup
else {
$airtimeSetup = true;
require_once SETUP_PATH . '/setup-config.php';
}
require_once APPLICATION_PATH . '/airtime-boot.php';

View File

@ -1,6 +0,0 @@
<?php
/* The purpose of this file is get PHP to clear its cache regarding the
* filesystem layout. See this ticket http://dev.sourcefabric.org/browse/CC-3320 */
clearstatcache(true);

View File

@ -1,293 +0,0 @@
<?php
/**
* User: sourcefabric
* Date: 02/12/14
* Class DatabaseSetup
* Wrapper class for validating and installing the Airtime database during the installation process.
*/
class DatabaseSetup extends Setup
{
// config file section header
protected static $_section = '[database]';
// Constant form field names for passing errors back to the front-end
public const DB_USER = 'dbUser';
public const DB_PASS = 'dbPass';
public const DB_NAME = 'dbName';
public const DB_HOST = 'dbHost';
// Array of key->value pairs for the config file
protected static $_properties;
/**
* @var PDO
*/
public static $dbh;
public function __construct($settings)
{
static::$_properties = [
'host' => $settings[self::DB_HOST],
'name' => $settings[self::DB_NAME],
'user' => $settings[self::DB_USER],
'password' => $settings[self::DB_PASS],
];
}
private function setNewDatabaseConnection($dbName)
{
self::$dbh = new PDO('pgsql:host=' . self::$_properties['host'] . ';dbname=' . $dbName . ';port=5432'
. ';user=' . self::$_properties['user'] . ';password=' . self::$_properties['password']);
$err = self::$dbh->errorInfo();
if ($err[1] != null) {
throw new PDOException();
}
}
/**
* Runs various database checks against the given settings. If a database with the given name already exists,
* we attempt to install the Airtime schema. If not, we first check if the user can create databases, then try
* to create the database. If we encounter errors, the offending fields are returned in an array to the browser.
*
* @throws AirtimeDatabaseException
*
* @return array associative array containing a display message and fields with errors
*/
public function runSetup()
{
$this->writeToTemp();
try {
$this->setNewDatabaseConnection('postgres');
if ($this->checkDatabaseExists()) {
$this->installDatabaseTables();
} else {
$this->checkUserCanCreateDb();
$this->createDatabase();
$this->installDatabaseTables();
}
} catch (PDOException $e) {
throw new AirtimeDatabaseException(
"Couldn't establish a connection to the database! " .
'Please check your credentials and try again. '
. 'PDO Exception: ' . $e->getMessage(),
[self::DB_NAME, self::DB_USER, self::DB_PASS]
);
}
self::$dbh = null;
return [
'message' => 'Airtime database was created successfully!',
'errors' => [],
];
}
private function installDatabaseTables()
{
$this->checkDatabaseEncoding();
$this->setNewDatabaseConnection(self::$_properties['name']);
$this->checkSchemaExists();
$this->createDatabaseTables();
$this->updateIcecastPassword();
$this->updateDjangoTables();
}
/**
* Check if the database settings and credentials given are valid.
*
* @return bool true if the database given exists and the user is valid and can access it
*/
private function checkDatabaseExists()
{
$statement = self::$dbh->prepare('SELECT datname FROM pg_database WHERE datname = :dbname');
$statement->execute([':dbname' => self::$_properties['name']]);
$result = $statement->fetch();
return isset($result[0]);
}
/**
* Check if the database schema has already been set up.
*
* @throws AirtimeDatabaseException
*/
private function checkSchemaExists()
{
$statement = self::$dbh->prepare("SELECT EXISTS (SELECT relname FROM pg_class WHERE relname='cc_files')");
$statement->execute();
$result = $statement->fetch();
if (isset($result[0]) && $result[0] == 't') {
throw new AirtimeDatabaseException('Airtime is already installed in this database!', []);
}
}
/**
* Check if the given user has access on the given host to create a new database.
*
* @throws AirtimeDatabaseException
*/
private function checkUserCanCreateDb()
{
$statement = self::$dbh->prepare("SELECT 1 FROM pg_roles WHERE rolname=:dbuser AND rolcreatedb='t'");
$statement->execute([':dbuser' => self::$_properties['user']]);
$result = $statement->fetch();
if (!isset($result[0])) {
throw new AirtimeDatabaseException(
'No database ' . self::$_properties['name'] . " exists; user '"
. self::$_properties['user'] . "' does not have permission to "
. 'create databases on ' . self::$_properties['host'],
[self::DB_NAME, self::DB_USER, self::DB_PASS]
);
}
}
/**
* Creates the Airtime database using the given credentials.
*
* @throws AirtimeDatabaseException
*/
private function createDatabase()
{
$statement = self::$dbh->prepare('CREATE DATABASE ' . pg_escape_string(self::$_properties['name'])
. " WITH ENCODING 'UNICODE' TEMPLATE template0"
. ' OWNER ' . pg_escape_string(self::$_properties['user']));
if (!$statement->execute()) {
throw new AirtimeDatabaseException(
'There was an error creating the database!',
[self::DB_NAME]
);
}
}
/**
* Creates the Airtime database schema using the given credentials.
*
* @throws AirtimeDatabaseException
*/
private function createDatabaseTables()
{
$sqlDir = dirname(ROOT_PATH) . '/api/libretime_api/legacy/migrations/sql/';
$files = ['schema.sql', 'data.sql'];
foreach ($files as $file) {
try {
$sql = file_get_contents($sqlDir . $file);
self::$dbh->exec($sql);
} catch (PDOException $e) {
echo $e->getMessage();
throw new AirtimeDatabaseException(
'There was an error setting up the Airtime schema!: ' . $e->getMessage(),
[self::DB_NAME]
);
}
}
}
/**
* Checks whether the newly-created database's encoding was properly set to UTF8.
*
* @throws AirtimeDatabaseException
*/
private function checkDatabaseEncoding()
{
$statement = self::$dbh->prepare('SELECT pg_encoding_to_char(encoding) '
. 'FROM pg_database WHERE datname = :dbname');
$statement->execute([':dbname' => self::$_properties['name']]);
$encoding = $statement->fetch();
if (!($encoding && $encoding[0] == 'UTF8')) {
throw new AirtimeDatabaseException(
'The database was installed with an incorrect encoding type!',
[self::DB_NAME]
);
}
}
/**
* Updates the icecast password in the database based upon the temp file created during install.
*
* @throws AirtimeDatabaseException
*/
private function updateIcecastPassword()
{
if (!file_exists(LIBRETIME_CONF_DIR . '/icecast_pass')) {
throw new AirtimeDatabaseException('The Icecast Password file was not accessible', []);
}
$icecast_pass_txt = file(LIBRETIME_CONF_DIR . '/icecast_pass');
$icecast_pass = $icecast_pass_txt[0];
$icecast_pass = str_replace(PHP_EOL, '', $icecast_pass);
$statement = self::$dbh->prepare("UPDATE cc_stream_setting SET value = :icecastpass WHERE keyname = 's1_pass'");
$statement->bindValue(':icecastpass', $icecast_pass, PDO::PARAM_STR);
try {
$statement->execute();
} catch (PDOException $ex) {
echo 'Error!: ' . $ex->getMessage() . '<br />';
}
$statement = self::$dbh->prepare("UPDATE cc_stream_setting SET value = :icecastpass WHERE keyname = 's1_admin_pass'");
$statement->bindValue(':icecastpass', $icecast_pass, PDO::PARAM_STR);
try {
$statement->execute();
} catch (PDOException $ex) {
echo 'Error!: ' . $ex->getMessage() . '<br />';
}
$statement = self::$dbh->prepare("UPDATE cc_stream_setting SET value = :icecastpass WHERE keyname = 's2_pass'");
$statement->bindValue(':icecastpass', $icecast_pass, PDO::PARAM_STR);
try {
$statement->execute();
} catch (PDOException $ex) {
echo 'Error!: ' . $ex->getMessage() . '<br />';
}
$statement = self::$dbh->prepare("UPDATE cc_stream_setting SET value = :icecastpass WHERE keyname = 's2_admin_pass'");
$statement->bindValue(':icecastpass', $icecast_pass, PDO::PARAM_STR);
try {
$statement->execute();
} catch (PDOException $ex) {
echo 'Error!: ' . $ex->getMessage() . '<br />';
}
$statement = self::$dbh->prepare("UPDATE cc_stream_setting SET value = :icecastpass WHERE keyname = 's3_pass'");
$statement->bindValue(':icecastpass', $icecast_pass, PDO::PARAM_STR);
try {
$statement->execute();
} catch (PDOException $ex) {
echo 'Error!: ' . $ex->getMessage() . '<br />';
}
$statement = self::$dbh->prepare("UPDATE cc_stream_setting SET value = :icecastpass WHERE keyname = 's3_admin_pass'");
$statement->bindValue(':icecastpass', $icecast_pass, PDO::PARAM_STR);
try {
$statement->execute();
} catch (PDOException $ex) {
echo 'Error!: ' . $ex->getMessage() . '<br />';
}
$statement = self::$dbh->prepare("UPDATE cc_stream_setting SET value = :icecastpass WHERE keyname = 's1_admin_pass'");
$statement->bindValue(':icecastpass', $icecast_pass, PDO::PARAM_STR);
try {
$statement->execute();
} catch (PDOException $ex) {
echo 'Error!: ' . $ex->getMessage() . '<br />';
}
$statement = self::$dbh->prepare("INSERT INTO cc_pref (keystr, valstr) VALUES ('default_icecast_password', :icecastpass )");
$statement->bindValue(':icecastpass', $icecast_pass, PDO::PARAM_STR);
try {
$statement->execute();
} catch (PDOException $ex) {
echo 'Error!: ' . $ex->getMessage() . '<br />';
}
}
/**
* Updates the Django related tables for the API.
*/
private function updateDjangoTables()
{
shell_exec('DJANGO_SETTINGS_MODULE=libretime_api.settings.testing LIBRETIME_CONFIG_FILEPATH=' . INSTALLER_CONFIG_FILEPATH . ' libretime-api migrate');
}
}

View File

@ -1,90 +0,0 @@
<?php
/**
* User: sourcefabric
* Date: 08/12/14.
*
* Class GeneralSetup
*
* Wrapper class for validating and setting up general settings during the installation process
*/
class GeneralSetup extends Setup
{
// config file section header
protected static $_section = '[general]';
// Array of key->value pairs for the config file
protected static $_properties;
// Constant form field names for passing errors back to the front-end
public const PUBLIC_URL = 'publicUrl';
public const CORS_URL = 'corsUrl';
public static $cors_url;
// Message and error fields to return to the front-end
public static $message;
public static $errors = [];
public function __construct($settings)
{
self::$_properties = [
'api_key' => $this->generateRandomString(),
'public_url' => $settings[self::PUBLIC_URL],
'cors_url' => $settings[self::CORS_URL],
];
self::$cors_url = $settings[self::CORS_URL];
}
/**
* @return array associative array containing a display message and fields with errors
*/
public function runSetup()
{
// TODO Do we need to validate these settings?
if (count(self::$errors) <= 0) {
$this->writeToTemp();
}
if (strlen(self::$cors_url) == 0) {
} else {
$this->setupCorsUrl();
}
return [
'message' => self::$message,
'errors' => self::$errors,
];
}
/**
* If the user entered a CORS Url then add it to the system preferences
* TODO Make sure we check for existing CORS URLs and display them on initial form.
*/
public function setupCorsUrl()
{
try {
$_SERVER['LIBRETIME_CONFIG_FILEPATH'] = INSTALLER_CONFIG_FILEPATH;
Propel::init(PROPEL_CONFIG_FILEPATH);
$con = Propel::getConnection();
} catch (Exception $e) {
self::$message = "Failed to insert Cors URL; database isn't configured properly!";
self::$errors[] = self::CORS_URL;
return;
}
$this->runCorsUrlQuery($con);
}
public function runCorsUrlQuery($con)
{
try {
Application_Model_Preference::SetAllowedCorsUrls(self::$cors_url);
Propel::close();
} catch (Exception $e) {
self::$message = 'Failed to insert ' . self::$cors_url . ' into cc_pref' . $e;
self::$errors[] = self::CORS_URL;
}
}
}

View File

@ -1,136 +0,0 @@
<?php
/**
* Author: sourcefabric
* Date: 08/12/14.
*
* Class MediaSetup
*
* Wrapper class for validating and setting up media folder during the installation process
*/
class MediaSetup extends Setup
{
public const MEDIA_FOLDER = 'mediaFolder';
public static $path;
public static $message;
public static $errors = [];
public function __construct($settings)
{
self::$path = $settings[self::MEDIA_FOLDER];
}
/**
* @return array associative array containing a display message and fields with errors
*/
public function runSetup()
{
// If the path passed in is empty, set it to the default
if (strlen(self::$path) == 0) {
self::$path = INSTALLER_DEFAULT_STORAGE_PATH;
if (!file_exists(INSTALLER_DEFAULT_STORAGE_PATH)) {
mkdir(INSTALLER_DEFAULT_STORAGE_PATH, 0755, true);
}
}
// Append a trailing / if they didn't
if (!(substr(self::$path, -1) == '/')) {
self::$path .= '/';
}
if (file_exists(self::$path)) {
$this->setupMusicDirectory();
} else {
self::$message = 'Invalid path!';
self::$errors[] = self::MEDIA_FOLDER;
}
// Finalize and move installer config file to libretime config file
if (file_exists(LIBRETIME_CONFIG_DIR)) {
if (!$this->moveAirtimeConfig()) {
self::$message = 'Error moving or deleting the installer config!';
self::$errors[] = 'ERR';
}
/*
* If we're upgrading from an old Airtime instance (pre-2.5.2) we rename their old
* config.yml to config.yml.tmp during the setup process. Now that we're done,
* we can rename it to config.yml.bak to avoid confusion.
*/
$fileName = LIBRETIME_CONFIG_FILEPATH;
$tmpFile = $fileName . '.tmp';
$bakFile = $fileName . '.bak';
if (file_exists($tmpFile)) {
rename($tmpFile, $bakFile);
}
} else {
self::$message = "Failed to move config.yml; /etc/libretime doesn't exist!";
self::$errors[] = 'ERR';
}
return [
'message' => self::$message,
'errors' => self::$errors,
];
}
/**
* Moves /tmp/airtime.temp.conf to /etc/libretime/config.yml and then removes it to complete setup.
*
* @return bool false if either of the copy or removal operations fail
*/
public function moveAirtimeConfig()
{
return copy(INSTALLER_CONFIG_FILEPATH, LIBRETIME_CONFIG_FILEPATH)
&& unlink(INSTALLER_CONFIG_FILEPATH);
}
/**
* Add the given directory to cc_music_dirs
* TODO Should we check for an existing entry in cc_music_dirs?
*/
public function setupMusicDirectory()
{
try {
$_SERVER['LIBRETIME_CONFIG_FILEPATH'] = INSTALLER_CONFIG_FILEPATH;
Propel::init(PROPEL_CONFIG_FILEPATH);
$con = Propel::getConnection();
} catch (Exception $e) {
self::$message = "Failed to insert media folder; database isn't configured properly!";
self::$errors[] = self::MEDIA_FOLDER;
return;
}
$this->runMusicDirsQuery($con);
}
public function runMusicDirsQuery($con)
{
try {
if ($this->checkMusicDirectoryExists($con)) {
$dir = CcMusicDirsQuery::create()->findPk(1, $con);
} else {
$dir = new CcMusicDirs();
}
$dir->setDirectory(self::$path)
->setType('stor')
->save();
self::$message = 'Successfully set up media folder!';
Propel::close();
unset($_SERVER['AIRTIME_CONF']);
} catch (Exception $e) {
self::$message = 'Failed to insert ' . self::$path . ' into cc_music_dirs';
self::$errors[] = self::MEDIA_FOLDER;
}
}
public function checkMusicDirectoryExists($con)
{
$entry = CcMusicDirsQuery::create()->findPk(1, $con);
return isset($entry) && $entry;
}
}

View File

@ -1,88 +0,0 @@
<?php
/**
* User: sourcefabric
* Date: 02/12/14.
*
* Class RabbitMQSetup
*
* Wrapper class for validating and setting up RabbitMQ during the installation process
*/
class RabbitMQSetup extends Setup
{
// config.yml section header
protected static $_section = '[rabbitmq]';
// Array of key->value pairs for config.yml
protected static $_properties;
// Constant form field names for passing errors back to the front-end
public const RMQ_USER = 'rmqUser';
public const RMQ_PASS = 'rmqPass';
public const RMQ_PORT = 'rmqPort';
public const RMQ_HOST = 'rmqHost';
public const RMQ_VHOST = 'rmqVHost';
// Message and error fields to return to the front-end
public static $message;
public static $errors = [];
public function __construct($settings)
{
static::$_properties = [
'host' => $settings[self::RMQ_HOST],
'port' => $settings[self::RMQ_PORT],
'user' => $settings[self::RMQ_USER],
'password' => $settings[self::RMQ_PASS],
'vhost' => $settings[self::RMQ_VHOST],
];
}
/**
* @return array associative array containing a display message and fields with errors
*/
public function runSetup()
{
try {
if ($this->checkRMQConnection()) {
self::$message = 'Connection successful!';
} else {
$this->identifyRMQConnectionError();
}
} catch (Exception $e) {
$this->identifyRMQConnectionError();
}
return [
'message' => self::$message,
'errors' => self::$errors,
];
}
public function checkRMQConnection()
{
$conn = new \PhpAmqpLib\Connection\AMQPStreamConnection(
self::$_properties['host'],
self::$_properties['port'],
self::$_properties['user'],
self::$_properties['password'],
self::$_properties['vhost']
);
$this->writeToTemp();
return isset($conn);
}
public function identifyRMQConnectionError()
{
// It's impossible to identify errors coming out of amqp.inc without a major
// rewrite, so for now just tell the user ALL THE THINGS went wrong
self::$message = _("Couldn't connect to RabbitMQ server! Please check if the server "
. 'is running and your credentials are correct.');
self::$errors[] = self::RMQ_USER;
self::$errors[] = self::RMQ_PASS;
self::$errors[] = self::RMQ_HOST;
self::$errors[] = self::RMQ_PORT;
self::$errors[] = self::RMQ_VHOST;
}
}

View File

@ -1,143 +0,0 @@
<?php
require_once dirname(__DIR__, 2) . '/application/preload.php';
/**
* Class Setup.
*
* @author sourcefabric
*
* Abstract superclass for the setup and installation process
*/
abstract class Setup
{
protected static $_section;
/**
* Array of key->value pairs for config.yml.
*
* @var array
*/
protected static $_properties;
abstract public function __construct($settings);
abstract public function runSetup();
/**
* Write new property values to a given section in airtime.temp.conf.
*/
protected function writeToTemp()
{
if (!file_exists(INSTALLER_CONFIG_FILEPATH)) {
copy(SAMPLE_CONFIG_FILEPATH, INSTALLER_CONFIG_FILEPATH);
}
// Logging::info(CONFIG_TEMP_FILEPATH);
$this->_write(INSTALLER_CONFIG_FILEPATH);
}
protected function _write($filePath)
{
$file = file($filePath);
$fileOutput = '';
$inSection = false;
foreach ($file as $line) {
if (strpos($line, static::$_section) !== false) {
$inSection = true;
} elseif (strpos($line, '[') !== false) {
$inSection = false;
}
if (substr(trim($line), 0, 1) == '#') {
/* Workaround to strip comments from config.yml.
* We need to do this because python's ConfigObj and PHP
* have different (and equally strict) rules about comment
* characters in configuration files.
*/
} elseif ($inSection) {
$key = trim(@substr($line, 0, strpos($line, '=')));
$fileOutput .= $key && isset(static::$_properties[$key]) ?
$key . ' = ' . static::$_properties[$key] . "\n" : $line;
} else {
$fileOutput .= $line;
}
}
file_put_contents($filePath, $fileOutput);
}
/**
* Generates a random string.
*
* @param int $p_len
* length of the output string
* @param string $p_chars
* characters to use in the output string
*
* @return string the generated random string
*/
protected function generateRandomString($p_len = 20, $p_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
{
$string = '';
for ($i = 0; $i < $p_len; ++$i) {
$pos = random_int(0, strlen($p_chars) - 1);
$string .= $p_chars[$pos];
}
return $string;
}
}
/**
* Class AirtimeDatabaseException.
*
* @author sourcefabric
*
* Exception class for database setup errors
*/
class AirtimeDatabaseException extends Exception
{
protected $message = 'Unknown Airtime database exception';
protected $errors = [];
public function __construct($message = null, $errors = [], $code = 0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
$this->errors = $errors;
}
public function getErrorFields()
{
return $this->errors;
}
}
// Import Setup subclasses
require_once 'database-setup.php';
require_once 'rabbitmq-setup.php';
require_once 'general-setup.php';
require_once 'media-setup.php';
// If config.yml exists, we shouldn't be here
if (!file_exists('/etc/libretime/config.yml')) {
if (isset($_GET['obj']) && $objType = $_GET['obj']) {
$obj = new $objType($_POST);
if ($obj instanceof Setup) {
try {
$response = $obj->runSetup();
} catch (AirtimeDatabaseException $e) {
$response = [
'message' => $e->getMessage(),
'errors' => $e->getErrorFields(),
];
}
echo json_encode($response);
}
}
}