Install.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. <?php
  2. Lib::loadClass('RouteBase');
  3. Lib::loadClass('UI');
  4. //TODO install nie kopiuje aktualnej /config/.config_base_structure.php @2017-09-24 bindera - sprawdzone na medicalu
  5. class Route_Install extends RouteBase {
  6. public function handleAuth() {
  7. if (!User::logged()) {
  8. throw new HttpException('Unauthorized', 401);
  9. }
  10. if (!User::isAdmin()) {
  11. throw new HttpException('Unauthorized - only for administrators', 401);
  12. }
  13. }
  14. public function defaultAction() {
  15. UI::gora();
  16. UI::menu();
  17. $this->menu();
  18. UI::setTitleJsTag("Install");
  19. UI::dol();
  20. }
  21. public function menu() {
  22. $serversList = $this->fetchActiveLicences();
  23. ?>
  24. <div class="jumbotron">
  25. <div class="container">
  26. <form class="form-inline" method="GET">
  27. <input type="hidden" name="_route" value="Install" />
  28. <input type="hidden" name="_task" value="createApp" />
  29. <label>Przygotuj kod źródłowy do aktualizacji na serwerze klienta:</label>
  30. <select id="servers_list" class="form-control" name="licence_id">
  31. <?php foreach ($serversList as $srv) : ?>
  32. <option value="<?php echo $srv->ID; ?>">[<?php echo $srv->ID; ?>] <?php echo $srv->domain; ?></option>
  33. <?php endforeach; ?>
  34. </select>
  35. <button type="submit" id="fldSbmtBtn" class="btn btn-primary" autocomplete="off">
  36. Generuj
  37. </button>
  38. <div id="servers_list_react"></div>
  39. </form>
  40. </div>
  41. </div>
  42. <script type="text/javascript">
  43. jQuery(document).ready(function () {
  44. jQuery('#fldSbmtBtn').on('click', function () {
  45. jQuery(this).text(jQuery(this).text() + '...').attr('disabled', 'disabled');
  46. jQuery(this).parent().submit();
  47. })
  48. });
  49. </script>
  50. <?php
  51. echo UI::h('script', ['src'=>"static/vendor.js", 'type'=>"text/javascript"]);
  52. // echo UI::h('script', ['src'=>"https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.js", 'type'=>"text/javascript"]);
  53. // echo UI::h('script', ['src'=>"https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.js", 'type'=>"text/javascript"]);
  54. // echo UI::h('script', ['src'=>"https://cdnjs.cloudflare.com/ajax/libs/react-bootstrap-typeahead/0.10.4/react-bootstrap-typeahead.js", 'type'=>"text/javascript"]);
  55. $jsonServersList = array_values(array_map(
  56. function ($srv) {
  57. return [
  58. 'id' => $srv->ID,
  59. 'label' => "{$srv->domain} [{$srv->ID}]"
  60. ];
  61. },
  62. $serversList
  63. ));
  64. echo UI::h('script', ['type'=>"text/javascript"], "
  65. (function(global){
  66. if (!global.p5VendorJs) { console.warn('Brak p5VendorJs'); return; }
  67. if (!global.p5VendorJs.React) { console.warn('Brak p5VendorJs.React'); return; }
  68. if (!global.p5VendorJs.ReactDOM) { console.warn('Brak p5VendorJs.ReactDOM'); return; }
  69. if (!global.p5VendorJs.Typeahead) { console.warn('Brak p5VendorJs.Typeahead'); return; }
  70. const React = global.p5VendorJs.React;
  71. const ReactDOM = global.p5VendorJs.ReactDOM;
  72. const Typeahead = global.p5VendorJs.Typeahead;
  73. var options = ".json_encode($jsonServersList).";
  74. var selected = [];
  75. var onInputChange = function (query) {
  76. // console.log('onInputChange:: query', query);
  77. }
  78. var onChange = function (value) {
  79. // console.log('onChange:: value', value);
  80. if (value.length > 0) {
  81. var id = value[0]['id'];
  82. if (id > 0) {
  83. document.getElementById('servers_list').value = id;
  84. }
  85. }
  86. }
  87. ReactDOM.render(
  88. React.createElement(Typeahead, {
  89. options: options,
  90. emptyLabel: 'Brak danych',
  91. placeholder: 'Wybierz serwer',
  92. selected: selected,
  93. // onInputChange: onInputChange,
  94. onChange: onChange,
  95. }, null),
  96. document.getElementById('servers_list_react')
  97. );
  98. })(window);
  99. ");
  100. }
  101. public function createAppAction() {
  102. session_write_close();
  103. $args = array();
  104. $args['licence_id'] = V::get('licence_id', 0, $_REQUEST, 'int');
  105. UI::gora();
  106. UI::menu();
  107. UI::setTitleJsTag("Install");
  108. //$this->menu($args['licence_id']);// TODO: GO BACK BTN
  109. try {
  110. $appLicenceInfo = $this->getAppLicenceInfo($args['licence_id']);
  111. $this->validateAppLicenceInfo($appLicenceInfo);
  112. } catch (Exception $e) {
  113. $this->_endWithException($e);
  114. }
  115. // $this->generateApp($appLicenceInfo->installPath, $appLicenceInfo->domains);
  116. //DBG::_(true, true, "appLicenceInfo", $appLicenceInfo, __CLASS__, __FUNCTION__, __LINE__);
  117. if ('_generateEncryptedSource' === V::get('_postTask', '', $_POST)) {
  118. echo '<div class="container">';
  119. echo '<h4>' . "Generowanie..." . '</h4>';
  120. echo '<div style="border:1px solid silver; max-height:400px; overflow-y:scroll">';
  121. try {
  122. $this->validateAppLicenceInfo($appLicenceInfo);
  123. $this->generateApp($appLicenceInfo->installPath, $appLicenceInfo->domains);
  124. } catch (Exception $e) {
  125. echo '</div></div>';// .container/ scroll
  126. $this->_endWithException($e);
  127. }
  128. echo '</div>';// .container
  129. UI::alert('success', "<strong>Gotowe</strong> Aplikacja znajduje się w katalogu {$appLicenceInfo->installFolderName}");
  130. $appLicenceInfo = $this->getAppLicenceInfo($args['licence_id']);
  131. }
  132. if ('newGenerateApp' === V::get('_postTask', '', $_POST)) {
  133. $this->newGenerateApp($appLicenceInfo);
  134. }
  135. if ('updateAndSendToRemoteTestDir' === V::get('_postTask', '', $_POST)) {
  136. echo '<details><summary style="cursor:pointer">aktualizuj werjsę, szyfruj i wyślij do testowego katalogu na serwerze</summary>';
  137. try {
  138. $idLicence = V::get('licence_id', 0, $_POST, 'int');
  139. $appLicenceInfo = $this->getAppLicenceInfo($idLicence);
  140. $this->validateAppLicenceInfo($appLicenceInfo);
  141. $this->gitResetHard($appLicenceInfo->installPath, $appLicenceInfo->projects);
  142. flush();
  143. $this->_encodeSource($appLicenceInfo->installPath, $appLicenceInfo->domains);
  144. flush();
  145. $this->_sendToRemoteTestDir($appLicenceInfo);
  146. } catch (Exception $e) {
  147. DBG::log($e);
  148. UI::alert('danger', $e->getMessage());
  149. }
  150. echo '</details>';
  151. $testDirUrl = "https://{$appLicenceInfo->mainServer}/se.encrypted.upgrade/";
  152. UI::alert('info', UI::h('p', [], [
  153. "testowy katalog zaktualizowany - ",
  154. UI::h('a', [ 'href' => $testDirUrl, 'target' => "_blank" ], $testDirUrl),
  155. ]));
  156. flush();
  157. }
  158. // echo UI::hButtonPost("TODO: Generuj z p5.git", [
  159. // 'class' => "btn btn-md btn-primary",
  160. // 'data' => [
  161. // '_postTask' => "newGenerateApp",
  162. // 'licence_id' => $appLicenceInfo->ID,
  163. // ],
  164. // ]);
  165. echo UI::h('div', [ 'class' => "jumbotron" ], [
  166. UI::h('div', [ 'class' => "container" ], [
  167. UI::h('h3', [], "Generowanie aplikacji dla licencji {$appLicenceInfo->ID}"),
  168. UI::h('p', [], "Licencja dla domen: " . implode(', ', $appLicenceInfo->domains)),
  169. UI::h('p', [], "Katalog z zakodowanymi plikami: {$appLicenceInfo->installFolderName}"),
  170. UI::hButtonPost("Generuj", [
  171. 'class' => "btn btn-primary",
  172. 'data' => [
  173. '_postTask' => '_generateEncryptedSource',
  174. 'licence_id' => $appLicenceInfo->ID,
  175. ]
  176. ]),
  177. (!$appLicenceInfo->installFolderGitExists)
  178. ? UI::h('div', [ 'class' => "alert alert-info" ], "Katalog nie istnieje - wygeneruj aplikację")
  179. : UI::h('div', [ 'class' => "alert alert-info", 'style' => "margin-top:10px" ], [
  180. UI::h('p', [], "Katalog istnieje i zawiera już repozytorium git: "),
  181. UI::h('p', [], [
  182. UI::hButtonPost("aktualizuj werjsę, szyfruj i wyślij do testowego katalogu na serwerze", [
  183. 'class' => "btn btn-xs btn-primary",
  184. 'data' => [
  185. '_postTask' => "updateAndSendToRemoteTestDir",
  186. 'licence_id' => $appLicenceInfo->ID,
  187. ],
  188. ]),
  189. ]),
  190. UI::h('p', [ 'style' => "margin-left:20px" ], [
  191. UI::h('a', [
  192. 'href' => "index.php?_route=Install&_task=gitResetHard&licence_id={$appLicenceInfo->ID}",
  193. 'target' => "_blank",
  194. 'class' => "btn btn-xs btn-default"
  195. ], "aktualizuj werjsę</a> (git reset --hard, git pull, set SE/VERSION - tak samo co 'rm -rf; git clone', ale szybciej)"),
  196. ]),
  197. UI::h('p', [ 'style' => "margin-left:20px" ], [
  198. UI::h('a', [
  199. 'href' => "index.php?_route=Install&_task=encodeSource&licence_id={$appLicenceInfo->ID}",
  200. 'target' => "_blank",
  201. 'class' => "btn btn-xs btn-default"
  202. ], "encode files"),
  203. ]),
  204. UI::h('p', [ 'style' => "margin-left:20px" ], [
  205. UI::h('a', [
  206. 'href' => "index.php?_route=Install&_task=sendToRemoteTestDir&licence_id={$appLicenceInfo->ID}",
  207. 'target' => "_blank",
  208. 'class' => "btn btn-xs btn-default"
  209. ], "send encoded files to remote server test folder (generates ssh key if not set)"),
  210. ]),
  211. UI::h('p', [ 'style' => "margin-top:30px" ], [
  212. "Test online: ",
  213. UI::h('a', [
  214. 'target' => "_blank",
  215. 'href' => "https://{$appLicenceInfo->mainServer}/se.encrypted.upgrade/"
  216. ], "https://{$appLicenceInfo->mainServer}/se.encrypted.upgrade/"),
  217. ]),
  218. "<br> - ",
  219. UI::h('a', [
  220. 'href' => "index.php?_route=Install&_task=upgradeRemoteFromTestDir&licence_id={$appLicenceInfo->ID}",
  221. 'onclick' => "return confirm('Uruchomić aktualizację SE na https://{$appLicenceInfo->mainServer}/SE/?')",
  222. 'target' => "_blank",
  223. 'class' => "btn btn-xs btn-warning"
  224. ], "UPGRADE Production folder from uploaded dir: ~/se.encrypted.upgrade/"),
  225. ]),
  226. ]),
  227. ]);
  228. ?>
  229. <script type="text/javascript">
  230. jQuery(document).ready(function () {
  231. jQuery('#fldSbmtBtn').on('click', function () {
  232. jQuery(this).text(jQuery(this).text() + '...').attr('disabled', 'disabled');
  233. jQuery(this).parent().submit();
  234. })
  235. });
  236. </script>
  237. <?php
  238. UI::dol();
  239. }
  240. public function gitResetHardAction() {
  241. session_write_close();
  242. $args = array();
  243. $args['licence_id'] = V::get('licence_id', 0, $_REQUEST, 'int');
  244. UI::gora();
  245. UI::menu();
  246. //$this->menu($args['licence_id']);// TODO: GO BACK BTN
  247. try {
  248. $appLicenceInfo = $this->getAppLicenceInfo($args['licence_id']);
  249. $this->validateAppLicenceInfo($appLicenceInfo);
  250. UI::startContainer();
  251. $this->gitResetHard($appLicenceInfo->installPath, $appLicenceInfo->projects);
  252. UI::endContainer();
  253. } catch (Exception $e) {
  254. $this->_endWithException($e);
  255. }
  256. UI::dol();
  257. }
  258. public function gitResetHard($installPath, $projects = []) {
  259. if (empty($installPath)) throw new Exception("Install path not found");
  260. $cmds = array();
  261. $cmds[] = "git reset --hard";
  262. $cmds[] = "git pull";
  263. $cmds[] = "echo `git show-ref --head|head -1|head -c 8` > SE/VERSION ";
  264. $hasError = false;
  265. foreach ($cmds as $cmd) {
  266. $out = ''; $ret = '';
  267. exec("cd {$installPath} && {$cmd}", $out, $ret);
  268. if (0 !== $ret) $hasError = true;
  269. DBG::nicePrint($out, "cmd: `{$cmd}` (return:{$ret})");
  270. }
  271. foreach ($projects as $projectName) {
  272. $cmd = "ls -l SE/projects/{$projectName} | wc -l";
  273. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  274. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  275. if (!empty($out) && '0' !== trim($out[0])) {
  276. // $cmd = "git submodule update SE/projects/{$projectName}";
  277. $cmd = "cd SE/projects/{$projectName} && git reset --hard"; // revert encode source - checkout to last commit (need update)
  278. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  279. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  280. }
  281. $cmd = "git submodule update --init SE/projects/{$projectName}"; // checkout to current commit
  282. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  283. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  284. }
  285. if (!$hasError) {
  286. UI::alert('success', "OK");
  287. } else {
  288. UI::alert('danger', "errors");
  289. }
  290. }
  291. public function encodeSourceAction() {
  292. session_write_close();
  293. $args = array();
  294. $args['licence_id'] = V::get('licence_id', 0, $_REQUEST, 'int');
  295. UI::gora();
  296. UI::menu();
  297. //$this->menu($args['licence_id']);// TODO: GO BACK BTN
  298. try {
  299. $appLicenceInfo = $this->getAppLicenceInfo($args['licence_id']);
  300. $this->validateAppLicenceInfo($appLicenceInfo);
  301. $this->_encodeSource($appLicenceInfo->installPath, $appLicenceInfo->domains);
  302. } catch (Exception $e) {
  303. $this->_endWithException($e);
  304. }
  305. UI::dol();
  306. }
  307. public function _encodeSource($installPath, $domains) {
  308. UI::startContainer();
  309. $this->encodeSourceFiles($installPath, $domains, $dbg = true);
  310. // try {
  311. // $this->encodeSourceFiles($appLicenceInfo->installPath, $appLicenceInfo->domains, $dbg = false);
  312. // UI::alert('success', "OK");
  313. // } catch (Exception $e) {
  314. // UI::alert('danger', $e->getMessage());
  315. // }
  316. UI::endContainer();
  317. }
  318. // @usage: Router::getRoute('Install')->encodeSourceFiles($installPath = '/path_to_git_repo', $domains = [ 'domain.com', 'localhost' ], $dbg = false);
  319. public function encodeSourceFiles($installPath, $domains, $dbg = false) {
  320. if (empty($installPath)) throw new Exception("Install path not found");
  321. if (empty($domains)) throw new Exception("Domains not found");
  322. $phpVersionsForSgencoder = '--phpversion 5.5 --phpversion 5.6';// encode for PHP 5.x (currently supported PHP 5.0-5.6)
  323. if ('1' == V::get('DBG_ENCODER_HELP', '', $_REQUEST)) {// encoder help
  324. $cmd = "cd {$installPath}/SE && /Applications/SourceGuardian.app/Contents/MacOS/sgencoder --help ";
  325. $out = ''; $ret = '';
  326. exec($cmd, $out, $ret);
  327. DBG::nicePrint($out, "cmd: `{$cmd}` (return:{$ret})");
  328. exit;
  329. }
  330. $domainEncodePhpFiles = [
  331. 'ant.php',
  332. 'api.php',
  333. 'budynki.php',
  334. 'index-ajax.php',
  335. 'index.php',
  336. 'procesy5.php',
  337. 'session-expire.php',
  338. 'test-sync.php',
  339. 'wfs-data.php',
  340. 'wfs-qgis.php',
  341. 'wfs.php',
  342. ];
  343. $cmd = "find . -name '*.php' ";
  344. $out = ''; $ret = '';
  345. exec("cd {$installPath}/SE && {$cmd}", $out, $ret);
  346. if ($dbg) DBG::nicePrint($out, "cmd: `{$cmd}` (return:{$ret})");
  347. else DBG::log($out, 'array', "cmd: `{$cmd}` (return:{$ret})");
  348. if (0 !== $ret) throw new Exception("Error at find php files");
  349. if (empty($out)) throw new Exception("No php files found");
  350. $allPhpFiles = array_map(function ($phpFilePath) {
  351. return ('./' == substr($phpFilePath, 0, 2))? substr($phpFilePath, 2) : $phpFilePath;
  352. }, $out);
  353. $freeEncodePhpFiles = array_filter($allPhpFiles, function ($phpFilePath) use ($domainEncodePhpFiles) {
  354. if ('se-lib/Vendor/' === substr($phpFilePath, 0, strlen('se-lib/Vendor/'))) return false; // SKIP se-lib/Vendor/*
  355. if ('.ini.php' === substr($phpFilePath, -1 * strlen('.ini.php'))) return false; // SKIP *.ini.php
  356. return (!in_array($phpFilePath, $domainEncodePhpFiles));
  357. });
  358. DBG::log($freeEncodePhpFiles, 'array', "\$freeEncodePhpFiles");
  359. if (empty($freeEncodePhpFiles)) throw new Exception("No php files to encode");
  360. $cmdTempl = "cd {$installPath}/SE && /Applications/SourceGuardian.app/Contents/MacOS/sgencoder {$phpVersionsForSgencoder} -b- ";
  361. $cmdDomainEncodeDomainsTempl = " --domain " . implode(" --domain ", array_merge($domains, ['localhost']));
  362. $cmdDomainEncodeFilesTempl = " " . implode(" ", $domainEncodePhpFiles);
  363. $cmdFreeEncodeFilesTempl = " " . implode(" ", $freeEncodePhpFiles);
  364. $cmds = [
  365. $cmdTempl . $cmdDomainEncodeDomainsTempl . $cmdDomainEncodeFilesTempl,
  366. $cmdTempl . $cmdFreeEncodeFilesTempl,
  367. ];
  368. $returnValues = [];
  369. foreach ($cmds as $cmd) {
  370. $out = ''; $ret = '';
  371. exec($cmd, $out, $ret);
  372. $encoderSummaryLine = end($out);
  373. $returnValues[] = $encoderSummaryLine;
  374. if ($dbg) {
  375. DBG::nicePrint([$cmd], "cmd");
  376. DBG::nicePrint($out, "return: '{$ret}'");
  377. // DBG::nicePrint([$encoderSummaryLine], "cmd last line");
  378. }
  379. else DBG::log([$cmd, $out], 'array', "cmd return:'{$ret}'");
  380. // if (0 !== $ret) throw new Exception("Error at encode files");
  381. if (empty($out)) throw new Exception("No output for encode files command");
  382. }
  383. $statusInfo = array_reduce($returnValues, function ($ret, $encoderSummaryLine) {
  384. DBG::log([$ret, $encoderSummaryLine], 'array', "DBG reduce [\$ret, \$encoderSummaryLine]");
  385. $matches = [];
  386. preg_match_all('/(\d+) files, (\d+) processed, (\d+) errors/', $encoderSummaryLine, $matches, PREG_SET_ORDER, 0);
  387. return [
  388. 'files' => $ret['files'] + (int)$matches[0][1],
  389. 'processed' => $ret['processed'] + (int)$matches[0][2],
  390. 'errors' => $ret['errors'] + (int)$matches[0][3],
  391. ];
  392. }, [
  393. 'files' => 0,
  394. 'processed' => 0,
  395. 'errors' => 0,
  396. ]);
  397. if ($statusInfo['errors'] === 0 && $statusInfo['files'] > 0) {
  398. if ($dbg) UI::alert('success', "{$statusInfo['files']} files, {$statusInfo['processed']} processed, {$statusInfo['errors']} errors");
  399. } else {
  400. if ($dbg) UI::alert('danger', "{$statusInfo['files']} files, {$statusInfo['processed']} processed, {$statusInfo['errors']} errors");
  401. else throw new Exception("{$statusInfo['files']} files, {$statusInfo['processed']} processed, {$statusInfo['errors']} errors");
  402. }
  403. }
  404. public function getAppLicenceInfo($idLicence) {
  405. $idLicence = intval($idLicence);
  406. if (empty($idLicence)) throw new Exception("Nie wybrano serwera/licencji.");
  407. //DBG::_(true, true, 'idLicence', $idLicence, __CLASS__, __FUNCTION__, __LINE__);
  408. $appLicenceInfo = (object)$this->fetchAppLicenceInfo($idLicence);
  409. $appLicenceInfo->domains = $this->fetchDomainsByLicenceId($idLicence);
  410. $installRootPath = '/Library/Server/Web/Data/Sites/Default/PLIKI/SES_PROCESY5_A';
  411. $appLicenceInfo->installFolderName = "{$idLicence}_upgrade_SE_source_encrypted";
  412. $appLicenceInfo->installPath = "{$installRootPath}/{$appLicenceInfo->installFolderName}";
  413. //DBG::_(true, true, 'appLicenceInfo', $appLicenceInfo, __CLASS__, __FUNCTION__, __LINE__);
  414. if (empty($appLicenceInfo->domains)) throw new Exception("Domains not found."); // TODO: mv to validate
  415. $appLicenceInfo->installFolderExists = file_exists("{$appLicenceInfo->installPath}/SE");
  416. $appLicenceInfo->installFolderGitExists = file_exists("{$appLicenceInfo->installPath}/.git");
  417. $appLicenceInfo->projects = []; // TODO: get from db
  418. if (79 == $idLicence) { // bravecom.procesy5.pl
  419. $appLicenceInfo->projects = [ 'bravecare' ];
  420. } else if (80 == $idLicence) { // bravecom.yellowgroup.pl
  421. $appLicenceInfo->projects = [ 'bocian' ];
  422. }
  423. return $appLicenceInfo;
  424. }
  425. public function validateAppLicenceInfo($appLicenceInfo) {
  426. if (empty($appLicenceInfo->ID)) throw new Exception("Nie wybrano serwera/licencji.");
  427. if (empty($appLicenceInfo->domains)) throw new Exception("Domains not found");
  428. if (empty($appLicenceInfo->installPath)) throw new Exception("Install path not found");
  429. }
  430. public function generateApp($installPath, $domains, $projects = []) {
  431. $cmds = array();
  432. $cmds[] = "if [ -d {$installPath} ] ; then rm -rf '{$installPath}'; fi";
  433. $cmds[] = "mkdir {$installPath}";
  434. $cmds[] = "cd {$installPath} && git clone --depth 1 ssh://git@biuro.biall-net.pl:2222/plabudda/se.git .";
  435. $cmds[] = "cd {$installPath} && echo `git show-ref --head|head -1|head -c 8` > SE/VERSION ";
  436. foreach ($cmds as $cmd) {
  437. V::exec($cmd, $out, $ret);
  438. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  439. }
  440. foreach ($projects as $projectName) {
  441. $cmd = "ls -l SE/projects/{$projectName} | wc -l";
  442. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  443. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  444. if (!empty($out) && '0' !== trim($out[0])) {
  445. // $cmd = "git submodule update SE/projects/{$projectName}";
  446. $cmd = "cd SE/projects/{$projectName} && git reset --hard"; // revert encode source - checkout to last commit (need update)
  447. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  448. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  449. }
  450. $cmd = "git submodule update --init SE/projects/{$projectName}"; // checkout to current commit
  451. V::exec("cd {$installPath} && {$cmd}", $out, $ret);
  452. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  453. }
  454. $this->_encodeSource($installPath, $domains);
  455. // 1763: $exec='cd '.$installer_dir.' && /Applications/SourceGuardian.app/Contents/MacOS/sgencoder -b-
  456. // '.INSTALL_SES_PROCESY_A::get_same_domains_for_install($h->SERVER_ADDRESS_SHORT).'
  457. // -r *.php
  458. // -x superedit-DB_PROCEDURES_CREATE.php
  459. // -x INI.php
  460. // -x .config_base_structure.php
  461. // ';
  462. //
  463. // INSTALL_SES_PROCESY_A::get_same_domains_for_install($h->SERVER_ADDRESS_SHORT):
  464. // $res2=DB::query("select SERVER_ADDRESS_SHORT from SES_PROCESY5_A where SERVER_ADDRESS_IP='".$h->SERVER_ADDRESS_IP."'");
  465. // while($h2=DB::fetch($res2)) {
  466. // $domain[]=' --domain '.$h2->SERVER_ADDRESS_SHORT;
  467. // ssh server@biuro.galeriaprzymorze.eu: PHP 5.5.20
  468. // ssh server@biuro.biall-net.pl
  469. // cd /Users/plabudda/procesy5-install-galeriaprzymorze.eu/
  470. // sudo chown -R server:admin SE/
  471. // /Applications/SourceGuardian.app/Contents/MacOS/sgencoder --phpversion 5.5 -b- --domain galeriaprzymorze.eu -r SE/*.php SE/se-lib/*.php SE/se-lib/*/*.php SE/se-lib/*/*/*.php SE/procesy/*.php SE/odt2xhtml/*.php -x superedit-DB_PROCEDURES_CREATE.php -x INI.php -x .config_base_structure.php
  472. }
  473. public function fetchActiveLicences() {
  474. $activeLic = array();
  475. $sql = "
  476. select l.`ID`
  477. , l.`SERVER_ADDRESS`
  478. , l.`SERVER_ADDRESS_SHORT` as domain -- domain for sgencoder
  479. , l.`SERVER_ADDRESS_IP`
  480. from `SES_PROCESY5_A` l
  481. where 1=1
  482. -- TODO: and l.`A_STATUS` in('NORMAL','WAITING')
  483. order by l.`ID` DESC
  484. ";
  485. $rows = DB::getPDO()->fetchAll($sql);
  486. foreach ($rows as $row) {
  487. $r = (object)$row;
  488. $activeLic[$r->ID] = $r;
  489. }
  490. return $activeLic;
  491. }
  492. public function fetchDomainsByLicenceId($licenceId) {
  493. $domains = array();
  494. $sql = "
  495. select g.`SERVER_ADDRESS_SHORT`, g.`SERVER_ADDRESS`
  496. from `SES_PROCESY5_A` g
  497. where g.`SERVER_ADDRESS_IP`=(select l.`SERVER_ADDRESS_IP`
  498. from `SES_PROCESY5_A` l
  499. where l.`ID`='{$licenceId}'
  500. -- TODO: and l.`A_STATUS` in('NORMAL','WAITING')
  501. )
  502. -- TODO: and g.`A_STATUS` in('NORMAL','WAITING')
  503. ";
  504. $rows = DB::getPDO()->fetchAll($sql);
  505. foreach ($rows as $row) {
  506. $r = (object)$row;
  507. $domains[] = $r->SERVER_ADDRESS_SHORT;
  508. if ($r->SERVER_ADDRESS != $r->SERVER_ADDRESS_SHORT) {
  509. $domains[] = $r->SERVER_ADDRESS;
  510. }
  511. }
  512. return $domains;
  513. }
  514. public function fetchMainServerByLicenceId($licenceId) {
  515. return DB::getPDO()->fetchValue("
  516. select g.`SERVER_ADDRESS`
  517. from `SES_PROCESY5_A` g
  518. where g.`ID`='{$licenceId}'
  519. -- TODO: and g.`A_STATUS` in('NORMAL','WAITING')
  520. ");
  521. }
  522. public function fetchAppLicenceInfo($licenceId) {
  523. $licenceInfo = null;
  524. $sql = "
  525. select g.ID
  526. , g.SERVER_ADDRESS as mainServer
  527. , g.ADMIN_USERNAME as rootLogin
  528. , g.ADMIN_USERNAME_PASSWD as rootPassword
  529. , g.SSH_PORT as sshPort
  530. from SES_PROCESY5_A g
  531. where g.`ID`=:id_licence
  532. -- TODO: and g.A_STATUS in('NORMAL','WAITING')
  533. ";
  534. $all = DB::getPDO()->fetchAll($sql, [ ':id_licence' => $licenceId ]);
  535. if (empty($all)) throw new Exception("Brak licencji o nr '{$licenceId}'");
  536. $licenceInfo = reset($all);
  537. if (!$licenceInfo['sshPort']) $licenceInfo['sshPort'] = 22;
  538. return $licenceInfo;
  539. }
  540. public function _endWithException($e) {
  541. echo UI::h('div', ['class'=>"container"], [
  542. UI::h('div', ['class' => "alert alert-danger"], "#" . $e->getLine() . ": " . $e->getMessage()),
  543. UI::h('p', [], [
  544. "Wróć do ",
  545. UI::h('a', ['href'=>"index.php?_route=Install"], "menu")
  546. ])
  547. ]);
  548. UI::dol();
  549. exit;
  550. }
  551. public function sendToRemoteTestDirAction() {
  552. session_write_close();
  553. $args = array();
  554. $args['licence_id'] = V::get('licence_id', 0, $_REQUEST, 'int');
  555. UI::gora();
  556. //UI::menu();
  557. //$this->menu($args['licence_id']);// TODO: GO BACK BTN
  558. try {
  559. $appLicenceInfo = $this->getAppLicenceInfo($args['licence_id']);
  560. $this->validateAppLicenceInfo($appLicenceInfo);
  561. // TODO: if (59 ) => baratosz.sledz - na lokalnym kompie
  562. // bn:~/$ scp -r SE server@192.168.61.153:~/se.encrypted.upgrade
  563. // remote SE.git = '/Users/bartoszsledz/Desktop/production-se'
  564. // remote:~/$ mv SE ~/SE.bup.2017-07-03
  565. // remote:~/$ mv ~/se.encrypted.upgrade/SE SE
  566. // remote:~/$ cp -r ~/SE.bup.2017-07-03/config SE/
  567. // remote:~/$ sudo chown -R bartoszsledz:staff SE/
  568. $this->_sendToRemoteTestDir($appLicenceInfo);
  569. echo "Test online: ";
  570. echo UI::h('a', ['target'=>"_blank", 'href'=>"https://{$appLicenceInfo->mainServer}/se.encrypted.upgrade/"], "https://{$appLicenceInfo->mainServer}/se.encrypted.upgrade/");
  571. } catch (Exception $e) {
  572. $this->_endWithException($e);
  573. }
  574. UI::dol();
  575. }
  576. public function _fetchRemoteHomeDir($appLicenceInfo) {
  577. $this->_assertRsaKeyExists($appLicenceInfo);
  578. $sshHostUsr = "{$appLicenceInfo->rootLogin}@{$appLicenceInfo->mainServer}";
  579. $sshArgs = (22 != $appLicenceInfo->sshPort)? "-p {$appLicenceInfo->sshPort}" : '';
  580. $rsyncSshPort = (22 != $appLicenceInfo->sshPort)? "-e 'ssh -p {$appLicenceInfo->sshPort}'" : '';
  581. if (V::get('DBG_REMOTE', '', $_GET)) {// DBG
  582. $cmd = "echo ~";
  583. V::exec("ssh {$sshArgs} {$sshHostUsr} '{$cmd}'", $out, $ret);
  584. DBG::log([ 'cmd-remote' => $cmd, 'output' => $out ], 'array', "return: {$ret}");
  585. V::execRemote($appLicenceInfo->mainServer, $appLicenceInfo->rootLogin, $appLicenceInfo->rootPassword, $cmd, $out, $ret, $appLicenceInfo->sshPort);
  586. DBG::log([ 'cmd-remote' => $cmd, 'output' => $out ], 'array', "return: {$ret}");
  587. V::execRootRemote($appLicenceInfo->mainServer, $appLicenceInfo->rootLogin, $appLicenceInfo->rootPassword, $cmd, $out, $ret, $appLicenceInfo->sshPort);
  588. DBG::log([ 'cmd-remote' => $cmd, 'output' => $out ], 'array', "return: {$ret}");
  589. }
  590. $cmd = "echo ~";
  591. V::exec("ssh {$sshArgs} {$sshHostUsr} '{$cmd}'", $out, $ret);
  592. DBG::log([ 'cmd-remote' => $cmd, 'output' => $out ], 'array', "return: {$ret}");
  593. if (empty($out) || empty($out[0])) throw new Exception("Cannot fetch remote home dir");
  594. return $out[0];
  595. }
  596. public function _sendToRemoteTestDir($appLicenceInfo) {
  597. $cmd = ''; $out = ''; $ret = '';
  598. $dryRunOnly = (V::get('dry-run', '', $_REQUEST)) ? "--dry-run" : "";
  599. $this->_assertRsaKeyExists($appLicenceInfo);
  600. $sshHostUsr = "{$appLicenceInfo->rootLogin}@{$appLicenceInfo->mainServer}";
  601. $sshArgs = (22 != $appLicenceInfo->sshPort)? "-p {$appLicenceInfo->sshPort}" : '';
  602. $rsyncSshPort = (22 != $appLicenceInfo->sshPort)? "-e 'ssh -p {$appLicenceInfo->sshPort}'" : '';
  603. // $appLicenceInfo->sshPort
  604. /* rsync options:
  605. -a, --archive archive mode; same as -rlptgoD (no -H)
  606. -u, --update skip files that are newer on the receiver
  607. -t, --times preserve times
  608. --delete delete extraneous files from dest dirs
  609. */
  610. $remoteDir = $this->_fetchRemoteHomeDir($appLicenceInfo);
  611. DBG::log($remoteDir, 'array', "remote home dir:");
  612. $cmd = "
  613. ssh {$sshArgs} {$sshHostUsr} '[ ! -d ~/se.encrypted.upgrade ] && mkdir ~/se.encrypted.upgrade || echo 1';
  614. ssh {$sshArgs} {$sshHostUsr} 'rm -rf ~/se.encrypted.upgrade/SE';
  615. ssh {$sshArgs} {$sshHostUsr} 'cp -r /Library/Server/Web/Data/Sites/Default/SE ~/se.encrypted.upgrade/SE';
  616. ssh {$sshArgs} {$sshHostUsr} 'rm -rf ~/se.encrypted.upgrade/SE/config';
  617. rsync --archive --times --delete --compress --one-file-system --omit-dir-times --no-g --no-perms {$dryRunOnly} \
  618. --verbose {$rsyncSshPort} \
  619. --exclude='stuff' \
  620. --exclude='stuff/**' \
  621. --exclude='schema/default_db.instance.xml' \
  622. --exclude='schema/default_db_xml_cache.public' \
  623. --exclude='schema/default_db.instance.xml/**' \
  624. --exclude='schema/default_db_xml_cache.public/**' \
  625. '{$appLicenceInfo->installPath}/SE/' {$sshHostUsr}:~/se.encrypted.upgrade/SE/;
  626. ssh {$sshArgs} {$sshHostUsr} 'cp -r /Library/Server/Web/Data/Sites/Default/SE/config ~/se.encrypted.upgrade/SE/';
  627. ssh {$sshArgs} {$sshHostUsr} 'rm /Library/Server/Web/Data/Sites/Default/se.encrypted.upgrade'
  628. ssh {$sshArgs} {$sshHostUsr} 'ln -s ~/se.encrypted.upgrade/SE /Library/Server/Web/Data/Sites/Default/se.encrypted.upgrade'
  629. ";
  630. V::exec($cmd, $out, $ret);
  631. DBG::log([ 'cmd-remote' => $cmd, 'output' => $out ], 'array', "return: {$ret}");
  632. if (0 !== $ret) throw new Exception("Cannot run remote command using rsa key! #{$ret}");
  633. }
  634. public function upgradeRemoteFromTestDirAction() {
  635. session_write_close();
  636. $args = array();
  637. $args['licence_id'] = V::get('licence_id', 0, $_REQUEST, 'int');
  638. UI::gora();
  639. //UI::menu();
  640. //$this->menu($args['licence_id']);// TODO: GO BACK BTN
  641. try {
  642. $appLicenceInfo = $this->getAppLicenceInfo($args['licence_id']);
  643. $this->validateAppLicenceInfo($appLicenceInfo);
  644. $this->_upgradeRemoteFromTestDir($appLicenceInfo);
  645. echo "Test online: ";
  646. echo UI::h('a', ['target'=>"_blank", 'href'=>"https://{$appLicenceInfo->mainServer}/SE/"], "https://{$appLicenceInfo->mainServer}/SE/");
  647. } catch (Exception $e) {
  648. $this->_endWithException($e);
  649. }
  650. UI::dol();
  651. }
  652. public function _upgradeRemoteFromTestDir($appLicenceInfo) {
  653. $cmd = ''; $out = ''; $ret = '';
  654. $this->_assertRsaKeyExists($appLicenceInfo);
  655. $dateStr = date("Y-m-d_H-i-s");
  656. // $remoteHomeDir = "/Users/{$appLicenceInfo->rootLogin}";// BUG: alias like in ams - login = prezes is alias for arkadiuszbinder
  657. $remoteHomeDir = $this->_fetchRemoteHomeDir($appLicenceInfo);
  658. $cmd = "
  659. rm -rf /Library/Server/Web/Data/Sites/Default/SE.test 2>&1
  660. cp -r {$remoteHomeDir}/se.encrypted.upgrade/SE /Library/Server/Web/Data/Sites/Default/SE.test 2>&1
  661. [ ! -d {$remoteHomeDir}/bup.se.upgrade ] && mkdir {$remoteHomeDir}/bup.se.upgrade || echo 1
  662. [ ! -d {$remoteHomeDir}/bup.se.upgrade ] && exit 1
  663. [ ! -d {$remoteHomeDir}/bup.se.upgrade-testttttt ] && exit 1
  664. [ ! -f /Library/Server/Web/Data/Sites/Default/SE.test/VERSION ] && echo \"Error: plik VERSION nie istnieje\" || echo \"check VERSION OK\"
  665. [ ! -f /Library/Server/Web/Data/Sites/Default/SE.test/VERSION ] && exit 1
  666. [ ! -f /Library/Server/Web/Data/Sites/Default/SE.test/index.php ] && echo \"Error: plik index.php nie istnieje\" || echo \"check index.php OK\"
  667. [ ! -f /Library/Server/Web/Data/Sites/Default/SE.test/index.php ] && exit 1
  668. [ ! -d /Library/Server/Web/Data/Sites/Default/SE.test/se-lib ] && echo \"Error: plik se-lib nie istnieje\" || echo \"check se-lib OK\"
  669. [ ! -d /Library/Server/Web/Data/Sites/Default/SE.test/se-lib ] && exit 1
  670. exit 0
  671. ";
  672. V::execRootRemote($appLicenceInfo->mainServer, $appLicenceInfo->rootLogin, $appLicenceInfo->rootPassword, $cmd, $out, $ret, $appLicenceInfo->sshPort);
  673. $cmd = "
  674. mv /Library/Server/Web/Data/Sites/Default/SE {$remoteHomeDir}/bup.se.upgrade/bup.{$dateStr} 2>&1
  675. mv /Library/Server/Web/Data/Sites/Default/SE.test /Library/Server/Web/Data/Sites/Default/SE 2>&1
  676. exit 0
  677. ";
  678. V::execRootRemote($appLicenceInfo->mainServer, $appLicenceInfo->rootLogin, $appLicenceInfo->rootPassword, $cmd, $out, $ret, $appLicenceInfo->sshPort);
  679. DBG::_(true, true, "cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  680. if (0 !== $ret) throw new Exception("Cannot run remote command as root! #{$ret}");
  681. // TODO: SE/bash_install_check.php requires $domain!
  682. // $cmd = "/usr/bin/php /Library/Server/Web/Data/Sites/Default/SE/bash_install_check.php {$domain}";
  683. // V::execRootRemote($appLicenceInfo->mainServer, $appLicenceInfo->rootLogin, $appLicenceInfo->rootPassword, $cmd, $out, $ret, $appLicenceInfo->sshPort);
  684. // DBG::_(true, true, "cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  685. // if (0 !== $ret) throw new Exception("Cannot run remote command as root! #{$ret}");
  686. }
  687. public function _assertRsaKeyExists($appLicenceInfo) {
  688. $cmd = ''; $out = ''; $ret = '';
  689. $cmd = "echo ~ && pwd";// /Library/WebServer
  690. $cmd = "ls -1 ~/.ssh/";
  691. //$cmd = "rm /tmp/id_rsa";
  692. //$cmd = "rm /tmp/id_rsa.pub";
  693. //$cmd = "ssh-keygen -t rsa -N '' -C '_www@biuro.biall-net.pl' -f /tmp/id_rsa";
  694. //$cmd = "ssh-keygen -t rsa -N '' -C '_www@biuro.biall-net.pl' -f /tmp/id_rsa";
  695. V::exec($cmd, $out, $ret);
  696. DBG::_(true, true, "cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  697. if (0 !== $ret) {// no ~/.ssh directory
  698. $rsaKeyPath = "~/.ssh";
  699. $cmds = array();
  700. $cmds[] = "mkdir {$rsaKeyPath}";
  701. $cmds[] = "ssh-keygen -t rsa -N '' -C '_www@biuro.biall-net.pl' -f {$rsaKeyPath}/id_rsa 2>&1";
  702. $cmds[] = "ls -1 $rsaKeyPath";
  703. foreach ($cmds as $cmd) {
  704. V::exec($cmd, $out, $ret);
  705. DBG::_(true, true, "cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  706. if (0 !== $ret) throw new Exception("Error '{$ret}' cmd({$cmd}): " . implode("\n", $out));
  707. }
  708. }
  709. $cmd = "cat ~/.ssh/id_rsa.pub";
  710. V::exec($cmd, $out, $ret);
  711. DBG::_(true, true, "cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  712. if (0 !== $ret || empty($out) || empty($out[0])) throw new Exception("Cannot read rsa public key");
  713. $rsaPubKey = $out[0];
  714. $cmd = 'ls -1a';
  715. $cmd = "
  716. [ ! -d ~/.ssh ] && mkdir ~/.ssh;
  717. [ ! -d ~/.ssh ] && echo 'ERROR ~/.ssh not exists and cannot be created';
  718. [ ! -f ~/.ssh/authorized_keys ] && echo '{$rsaPubKey}' > ~/.ssh/authorized_keys;
  719. [ ! -f ~/.ssh/authorized_keys ] && echo 'ERROR ~/.ssh/authorized_keys not exists and cannot be created';
  720. cat ~/.ssh/authorized_keys| grep '{$rsaPubKey}' && echo 'OK' || echo '{$rsaPubKey}' >> ~/.ssh/authorized_keys;
  721. chmod 600 ~/.ssh/authorized_keys;
  722. ";
  723. V::execRemote($appLicenceInfo->mainServer, $appLicenceInfo->rootLogin, $appLicenceInfo->rootPassword, $cmd, $out, $ret, $appLicenceInfo->sshPort);
  724. DBG::_(true, true, "remote cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  725. //$cmd = "ssh server@{$appLicenceInfo->mainServer} 'ls -1 .ssh/'";
  726. //$cmd = "ssh -i ~/.ssh/id_rsa server@{$appLicenceInfo->mainServer} 'ls -1'";
  727. $sshPort = (22 != $appLicenceInfo->sshPort)? "-p {$appLicenceInfo->sshPort}" : '';
  728. $cmd = "ssh {$sshPort} {$appLicenceInfo->rootLogin}@{$appLicenceInfo->mainServer} 'ls -1'";
  729. V::exec($cmd, $out, $ret);
  730. DBG::_(true, true, "cmd: {$cmd} (return: {$ret})", $out, __CLASS__, __FUNCTION__, __LINE__);
  731. if (0 !== $ret) throw new Exception("Cannot run remote command using rsa key! #{$ret}");
  732. }
  733. public function newGenerateApp($appLicenceInfo) {
  734. if (empty($appLicenceInfo->ID)) throw new Exception("Nie wybrano serwera/licencji.");
  735. if (empty($appLicenceInfo->domains)) throw new Exception("Domains not found");
  736. $installPath = $appLicenceInfo->installPath;
  737. if (empty($installPath)) throw new Exception("Install path not found");
  738. $installPath .= '-p5';
  739. $cmds = array();
  740. $cmds[] = "if [ -d {$installPath} ] ; then rm -rf '{$installPath}'; fi";
  741. $cmds[] = "mkdir {$installPath}";
  742. $cmds[] = "cd {$installPath} && git clone --depth 1 ssh://git@biuro.biall-net.pl:2222/p5/p5.git .";
  743. $cmds[] = "cd {$installPath} && echo `git show-ref --head|head -1|head -c 8` > SE/VERSION ";
  744. // TODO: fetch from DB
  745. {
  746. foreach ($appLicenceInfo->projects as $projectName) {
  747. $cmds[] = "cd {$installPath} && git submodule update --init SE/projects/{$projectName}";
  748. }
  749. }
  750. foreach ($cmds as $cmd) {
  751. $out = ''; $ret = '';
  752. exec($cmd, $out, $ret);
  753. DBG::nicePrint([ 'cmd' => $cmd, 'output' => $out ], "return: {$ret}");
  754. }
  755. // $this->_encodeSource($appLicenceInfo->installPath, $appLicenceInfo->domains);
  756. }
  757. }