From f24af19b79c71865113ae2959af7d20aa52fca18 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Thu, 28 Apr 2011 12:39:59 -0700 Subject: [PATCH] First version of installer for domain-based status networks New installer class for domain-based status networks. (XXX: this should probably be generalized for all multi-home systems). New script to run that installer. --- .../DomainStatusNetworkPlugin.php | 27 +- .../domainstatusnetworkinstaller.php | 276 ++++++++++++++++++ .../scripts/installforemail.php | 56 ++++ 3 files changed, 353 insertions(+), 6 deletions(-) create mode 100644 plugins/DomainStatusNetwork/domainstatusnetworkinstaller.php create mode 100644 plugins/DomainStatusNetwork/scripts/installforemail.php diff --git a/plugins/DomainStatusNetwork/DomainStatusNetworkPlugin.php b/plugins/DomainStatusNetwork/DomainStatusNetworkPlugin.php index 024afd4c29..aa7929ef02 100644 --- a/plugins/DomainStatusNetwork/DomainStatusNetworkPlugin.php +++ b/plugins/DomainStatusNetwork/DomainStatusNetworkPlugin.php @@ -74,22 +74,37 @@ class DomainStatusNetworkPlugin extends Plugin return; } - $sn = Status_network::staticGet('nickname', $nickname); - - if (empty($sn)) { - $this->log(LOG_ERR, "No site for nickname $nickname"); - return; + try { + $sn = Status_network::staticGet('nickname', $nickname); + } catch (Exception $e) { + $this->log(LOG_ERR, $e->getMessage()); } $tags = $sn->getTags(); foreach ($tags as $tag) { if (strncmp($tag, 'domain=', 7) == 0) { - common_config_append('email', 'whitelist', substr($tag, 7)); + $domain = substr($tag, 7); + $this->log("Setting email domain to {$domain}"); + common_config_append('email', 'whitelist', $domain); } } } + function onAutoload($cls) + { + $dir = dirname(__FILE__); + + switch ($cls) + { + case 'DomainStatusNetworkInstaller': + include_once $dir . '/' . strtolower($cls) . '.php'; + return false; + default: + return true; + } + } + static function toDomain($raw) { $parts = explode('@', $raw); diff --git a/plugins/DomainStatusNetwork/domainstatusnetworkinstaller.php b/plugins/DomainStatusNetwork/domainstatusnetworkinstaller.php new file mode 100644 index 0000000000..891fdd9817 --- /dev/null +++ b/plugins/DomainStatusNetwork/domainstatusnetworkinstaller.php @@ -0,0 +1,276 @@ +. + * + * @category DomainStatusNetwork + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +/** + * Installer class for domain-based multi-homing systems + * + * @category DomainStatusNetwork + * @package StatusNet + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ + +class DomainStatusNetworkInstaller extends Installer +{ + protected $domain = null; + protected $rootname = null; + protected $sitedb = null; + protected $rootpass = null; + protected $nickname = null; + protected $sn = null; + protected $verbose = false; + + function __construct($domain) + { + $this->domain = $domain; + } + + /** + * Go for it! + * @return boolean success + */ + function main() + { + // We don't check prereqs. Check 'em before setting up a + // multi-home system, kthxbi + if ($this->prepare()) { + return $this->handle(); + } else { + $this->showHelp(); + return false; + } + } + + /** + * Get our input parameters... + * @return boolean success + */ + function prepare() + { + $config = $this->getConfig(); + + $this->nickname = DomainStatusNetworkPlugin::nicknameForDomain($this->domain); + + // XXX make this configurable + + $this->sitename = sprintf('The %s Status Network', $this->domain); + + $this->server = $this->nickname.'.'.$config['WILDCARD']; + $this->path = null; + $this->fancy = true; + + $this->host = $config['DBHOSTNAME']; + $this->database = $this->nickname.$config['DBBASE']; + $this->dbtype = 'mysql'; // XXX: support others... someday + $this->username = $this->nickname.$config['USERBASE']; + + $pwgen = $config['PWDGEN']; + + $password = `$pwgen`; + + $this->password = trim($password); + + // For setting up the database + + $this->rootname = $config['ADMIN']; + $this->rootpass = $config['ADMINPASS']; + $this->sitehost = $config['DBHOST']; + $this->sitedb = $config['SITEDB']; + + // Explicitly empty + + $this->adminNick = null; + $this->adminPass = null; + $this->adminEmail = null; + $this->adminUpdates = null; + + /** Should we skip writing the configuration file? */ + $this->skipConfig = true; + + if (!$this->validateDb()) { + return false; + } + + return true; + } + + function handle() + { + return $this->doInstall(); + } + + function setupDatabase() + { + $this->createDatabase(); + parent::setupDatabase(); + $this->createDirectories(); + $this->saveStatusNetwork(); + $this->checkSchema(); + } + + function saveStatusNetwork() + { + Status_network::setupDB($this->sitehost, + $this->rootname, + $this->rootpass, + $this->sitedb, array()); + + $sn = new Status_network(); + + $sn->nickname = $this->nickname; + $sn->dbhost = $this->host; + $sn->dbuser = $this->username; + $sn->dbpass = $this->password; + $sn->dbname = $this->database; + + $result = $sn->insert(); + + if (!$result) { + throw new ServerException("Couldn't create status_network: " . print_r($sn, true)); + } + + $sn->setTags(array('domain='.$this->domain)); + + $this->sn = $sn; + + } + + function checkSchema() + { + $config = $this->getConfig(); + + Status_network::$wildcard = $config['WILDCARD']; + + StatusNet::switchSite($this->nickname); + + Event::handle('CheckSchema'); + } + + function getStatusNetwork() + { + return $this->sn; + } + + function createDirectories() + { + $config = $this->getConfig(); + + foreach (array('AVATARBASE', 'BACKGROUNDBASE', 'FILEBASE') as $key) { + $base = $config[$key]; + mkdir($base.'/'.$this->nickname, 0777, true); + } + } + + function createDatabase() + { + // Create the New DB + $res = mysql_connect($this->host, $this->rootname, $this->rootpass); + if (!$res) { + throw new ServerException("Can't connect to {$this->host} as {$this->rootname}"); + } + + mysql_query("CREATE DATABASE ". mysql_real_escape_string($this->database), $res); + + $return = mysql_select_db($this->database, $res); + + if (!$return) { + throw new ServerException("Unable to connect to {$this->database} on {$this->host}"); + } + + foreach (array('localhost', '%') as $src) { + mysql_query("GRANT ALL ON " . + mysql_real_escape_string($this->database).".* TO '" . + $this->username . "'@'".$src."' ". + "IDENTIFIED BY '".$this->password."'", $res); + } + + mysql_close($res); + } + + function getConfig() + { + static $config; + + $cfg_file = "/etc/statusnet/setup.cfg"; + + if (empty($config)) { + $result = parse_ini_file($cfg_file); + + $config = array(); + foreach ($result as $key => $value) { + $key = str_replace('export ', '', $key); + $config[$key] = $value; + } + } + + return $config; + } + + function showHelp() + { + } + + function warning($message, $submessage='') + { + print $this->html2text($message) . "\n"; + if ($submessage != '') { + print " " . $this->html2text($submessage) . "\n"; + } + print "\n"; + } + + function updateStatus($status, $error=false) + { + if ($this->verbose || $error) { + if ($error) { + print "ERROR: "; + } + print $this->html2text($status); + print "\n"; + } + } + + private function html2text($html) + { + // break out any links for text legibility + $breakout = preg_replace('/+]\bhref="(.*)"[^>]*>(.*)<\/a>/', + '\2 <\1>', + $html); + return html_entity_decode(strip_tags($breakout), ENT_QUOTES, 'UTF-8'); + } +} diff --git a/plugins/DomainStatusNetwork/scripts/installforemail.php b/plugins/DomainStatusNetwork/scripts/installforemail.php new file mode 100644 index 0000000000..5eb5388885 --- /dev/null +++ b/plugins/DomainStatusNetwork/scripts/installforemail.php @@ -0,0 +1,56 @@ +#!/usr/bin/env php +. + */ + +define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..')); + +$helptext = << + +END_OF_INSTALLFOREMAIL_HELP; + +require_once INSTALLDIR.'/scripts/commandline.inc'; + +$email = $args[0]; + +$domain = DomainStatusNetworkPlugin::toDomain($email); + +$sn = DomainStatusNetworkPlugin::siteForDomain($domain); + +if (empty($sn)) { + $installer = new DomainStatusNetworkInstaller($domain); + // Do the thing + $installer->main(); + + $sn = $installer->getStatusNetwork(); + + $config = $installer->getConfig(); + + Status_network::$wildcard = $config['WILDCARD']; +} + +StatusNet::switchSite($sn->nickname); + +$confirm = EmailRegistrationPlugin::registerEmail($email); + +$confirmUrl = common_local_url('register', array('code' => $confirm->code)); + +print $confirmUrl."\n";