installer.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <?php
  2. abstract class BaseSetup {
  3. public function getConfig($section=null) {
  4. return (!empty($section))? $this->config[$section] : $this->config;
  5. }
  6. public function getOptions() {
  7. return $this->getConfig('form');
  8. }
  9. public function withDatabase() {
  10. return ($this->getConfig('database') === true);
  11. }
  12. }
  13. class WordpressSetup extends BaseSetup {
  14. protected $config = [
  15. 'form' => [
  16. 'protocol' => [
  17. 'type' => 'select',
  18. 'options' => ['http','ion','https'],
  19. 'value' => 'ion',
  20. ],
  21. 'subdir' => ['type'=>'text', 'value'=>'/'],
  22. 'site_name' => ['type'=>'text', 'value'=>'Wordpress Blog'],
  23. 'site_description' => ['value'=>'Another wordpresss site'],
  24. 'wordpress_account_username' => ['value'=>'wpadmin'],
  25. 'wordpress_account_password' => 'password',
  26. ],
  27. 'database' => true,
  28. 'url' => 'https://wordpress.org/wordpress-5.2.2.tar.gz'
  29. ];
  30. }
  31. class HestiaApp {
  32. public function run($cmd, $args, &$return_code=null) {
  33. $cli_script = HESTIA_CMD . '/' . basename($cmd);
  34. $cli_arguments = '';
  35. if (!empty($args) && is_array($args)) {
  36. foreach ($args as $arg) {
  37. $cli_arguments .= escapeshellarg($arg) . ' ';
  38. }
  39. } else {
  40. $cli_arguments = escapeshellarg($args);
  41. }
  42. exec ($cli_script . ' ' . $cli_arguments, $output, $return_code);
  43. $result['code'] = $return_code;
  44. $result['raw'] = $output;
  45. $result['text'] = implode( PHP_EOL, $result['raw']);
  46. $result['json'] = json_decode($result['text'], true);
  47. return (object)$result;
  48. }
  49. public function realuser() {
  50. // Logged in user
  51. return $_SESSION['user'];
  52. }
  53. public function user() {
  54. // Effective user
  55. if ($this->realuser() == 'admin' && !empty($_SESSION['look'])) {
  56. return $_SESSION['look'];
  57. }
  58. return $this->realuser();
  59. }
  60. public function userOwnsDomain($domain) {
  61. $status = null;
  62. $this->run('v-list-web-domain', [$this->user(), $domain, 'json'], $status);
  63. return ($status === 0);
  64. }
  65. public function databaseAdd($dbname,$dbuser,$dbpass) {
  66. $v_password = tempnam("/tmp","vst");
  67. $fp = fopen($v_password, "w");
  68. fwrite($fp, $dbpass."\n");
  69. fclose($fp);
  70. $this->run('v-add-database', [$this->user(), $dbname, $dbuser, $v_password], $status);
  71. unlink($v_password);
  72. return ($status === 0);
  73. }
  74. }
  75. class AppInstaller {
  76. private $domain;
  77. private $appsetup;
  78. private $appcontext;
  79. private $formNamespace = 'webapp';
  80. private $errors;
  81. private $database_config = [
  82. 'database_name' => 'text',
  83. 'database_user' => 'text',
  84. 'database_password' => 'password',
  85. ];
  86. public function __construct($app, $domain, $context) {
  87. $this->domain = $domain;
  88. $this->appcontext = $context;
  89. if (!$this->appcontext->userOwnsDomain($domain)) {
  90. throw new Exception("User does not have access to domain [$domain]");
  91. }
  92. $appclass = ucfirst($app).'Setup';
  93. if (class_exists($appclass)) {
  94. $this->appsetup = new $appclass();
  95. }
  96. if (!$this->appsetup) {
  97. throw new Exception( "Application [".ucfirst($app)."] does not have a installer" );
  98. }
  99. }
  100. public function getStatus() {
  101. return $this->errors;
  102. }
  103. public function formNs() {
  104. return $this->formNamespace;
  105. }
  106. public function getOptions() {
  107. if(!$this->appsetup) return;
  108. $options = $this->appsetup->getOptions();
  109. if ($this->appsetup->withDatabase()) {
  110. $options = array_merge($options, $this->database_config);
  111. }
  112. return $options;
  113. }
  114. public function filterOptions($options)
  115. {
  116. $filteredoptions = [];
  117. array_walk($options, function($value, $key) use(&$filteredoptions) {
  118. if (strpos($key, $this->formNs().'_')===0) {
  119. $option = str_replace($this->formNs().'_','',$key);
  120. $filteredoptions[$option] = $value;
  121. }
  122. });
  123. return $filteredoptions;
  124. }
  125. public function execute($options) {
  126. if (!$this->appsetup) return;
  127. $options = $this->filterOptions($options);
  128. $random_num = random_int(10000, 99999);
  129. if ($this->appsetup->withDatabase()) {
  130. if(empty($options['database_name'])) {
  131. $options['database_name'] = $random_num;
  132. }
  133. if(empty($options['database_user'])) {
  134. $options['database_user'] = $random_num;
  135. }
  136. if(empty($options['database_password'])) {
  137. $options['database_password'] = bin2hex(random_bytes(10));
  138. }
  139. if(!$this->appcontext->databaseAdd($options['database_name'], $options['database_user'], $options['database_password'])){
  140. $this->errors[] = "Error adding database";
  141. return false;
  142. }
  143. }
  144. }
  145. }