From b86172c1f0b3b7ba0ea54bff0718364f38257fbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20Marcos?= Date: Mon, 11 Jun 2018 16:05:35 +0200 Subject: [PATCH 1/6] Update README.md --- README.md | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4676d2bd58..a62e7a483b 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,52 @@ - Virtualization (OpenVZ) - Administrator, reseller and client login - Configuration mirroring and clusters -- Open Source software (BSD license) \ No newline at end of file +- Open Source software (BSD license) +- +# ISPConfig-vcs + +Easy version control system integration in ISPConfig 3. + +This is a very early version, so only git repositories can be created for the moment. + + +## What is this for? +This plugin integrates Git repositories for the ISPConfig Sites. + +You have the option to 'git clone' a repository on the %document_root%/web folder of the websites. +The first time you add the repo it tries to 'git clone'-it creating a temporal folder in /tmp/web_git/[web_git_id]/. +After the clone, it changes permissions to every file with the user and group of the website. Then it moves all the content to the %document_root%/web folder. + +Every time you change the values of a repository (via ISPConfig form) it checks if there is a git repository created in the folder. +If not, it tries to clone it. If yes, performs a 'git pull' and changes and chowns all the web folder. + +'git pull' log is stored and can be viewed inside a Git repository register. + + +## Requirements +* ISPConfig 3 +* Admin user +* git +* Git repository url (HTTP/HTTPS) + + +## Instalation + +I recommend you test this plugin in a non-production enviroment. + +``` +#Get sources +git clone http://git.funcli.net:3000/funcli/ISPConfig-vcs.git /tmp/vcs +cd /tmp/vcs + +#Import database table +mysql -uroot -p dbispconfig < database.sql + +#Add files to ISPConfig +cp -r interface /usr/local/ispconfig/ +cp -r server /usr/local/ispconfig/ + +#Enable module and plugin +ln -s /usr/local/ispconfig/server/mods-available/vcs_module.inc.php /usr/local/ispconfig/server/mods-enabled/vcs_module.inc.php +ln -s /usr/local/ispconfig/server/plugins-available/vcs_plugin.inc.php /usr/local/ispconfig/server/plugins-enabled/vcs_plugin.inc.php +``` \ No newline at end of file -- GitLab From 4d7b4dbb1701b1bd8fe06035d226d537f556e3ba Mon Sep 17 00:00:00 2001 From: jadsolucions Date: Mon, 11 Jun 2018 16:07:17 +0200 Subject: [PATCH 2/6] Add new files. --- interface/web/vcs/form/web_git.tform.php | 179 +++++++++ interface/web/vcs/index.php | 16 + interface/web/vcs/lib/admin.conf.php | 7 + interface/web/vcs/lib/lang/en_web_git.lng | 11 + .../web/vcs/lib/lang/en_web_git_list.lng | 7 + interface/web/vcs/lib/module.conf.php | 75 ++++ interface/web/vcs/list/web_git.list.php | 102 +++++ interface/web/vcs/templates/web_git_edit.htm | 38 ++ interface/web/vcs/templates/web_git_list.htm | 59 +++ interface/web/vcs/templates/web_git_log.htm | 3 + interface/web/vcs/web_git_del.php | 48 +++ interface/web/vcs/web_git_edit.php | 56 +++ interface/web/vcs/web_git_list.php | 50 +++ interface/web/vcs/web_git_update.php | 87 +++++ server/mods-available/vcs_module.inc.php | 96 +++++ server/plugins-available/vcs_plugin.inc.php | 369 ++++++++++++++++++ 16 files changed, 1203 insertions(+) create mode 100644 interface/web/vcs/form/web_git.tform.php create mode 100644 interface/web/vcs/index.php create mode 100644 interface/web/vcs/lib/admin.conf.php create mode 100644 interface/web/vcs/lib/lang/en_web_git.lng create mode 100644 interface/web/vcs/lib/lang/en_web_git_list.lng create mode 100644 interface/web/vcs/lib/module.conf.php create mode 100644 interface/web/vcs/list/web_git.list.php create mode 100644 interface/web/vcs/templates/web_git_edit.htm create mode 100644 interface/web/vcs/templates/web_git_list.htm create mode 100644 interface/web/vcs/templates/web_git_log.htm create mode 100644 interface/web/vcs/web_git_del.php create mode 100644 interface/web/vcs/web_git_edit.php create mode 100644 interface/web/vcs/web_git_list.php create mode 100644 interface/web/vcs/web_git_update.php create mode 100644 server/mods-available/vcs_module.inc.php create mode 100644 server/plugins-available/vcs_plugin.inc.php diff --git a/interface/web/vcs/form/web_git.tform.php b/interface/web/vcs/form/web_git.tform.php new file mode 100644 index 0000000000..e52efe9a06 --- /dev/null +++ b/interface/web/vcs/form/web_git.tform.php @@ -0,0 +1,179 @@ + 0 id must match with id of current user +$form["auth_preset"]["groupid"] = 0; // 0 = default groupid of the user, > 0 id must match with groupid of current user +$form["auth_preset"]["perm_user"] = 'riud'; //r = read, i = insert, u = update, d = delete +$form["auth_preset"]["perm_group"] = 'riud'; //r = read, i = insert, u = update, d = delete +$form["auth_preset"]["perm_other"] = ''; //r = read, i = insert, u = update, d = delete + + +//* Maybe we're writing in a response to another message +$sm_default_recipient_id = ''; +$sm_default_subject = ''; +if(isset($_GET['reply'])) +{ + $sm_msg_id = preg_replace("/[^0-9]/", "", $_GET['reply']); + $res = $app->db->queryOneRecord("SELECT sender_id, subject FROM support_message WHERE support_message_id=?", $sm_msg_id); + if($res['sender_id']) + { + $sm_default_recipient_id = $res['sender_id']; + $sm_default_subject = (preg_match("/^Re:/", $res['subject'])?"":"Re: ") . $res['subject']; + } +} + +$authsql = $app->tform->getAuthSQL('r', 'client'); + +//* Begin of the form definition of the first tab. The name of the tab is called "message". We refer +//* to this name in the $form["tab_default"] setting above. +$form["tabs"]['info'] = array ( + 'title' => "Website", // Title of the Tab + 'width' => 100, // Tab width + 'template' => "templates/web_git_edit.htm", // Template file name + 'fields' => array ( + //################################# + // Begin Datatable fields + //################################# + + //Website + 'parent_domain_id' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'SELECT', + 'default' => '', + 'datasource' => array ( 'type' => 'SQL', + 'querystring' => "SELECT web_domain.domain_id, CONCAT(web_domain.domain, ' :: ', server.server_name) AS parent_domain FROM web_domain, server WHERE web_domain.type = 'vhost' AND web_domain.server_id = server.server_id AND {AUTHSQL::web_domain} ORDER BY web_domain.domain", + 'keyfield'=> 'domain_id', + 'valuefield'=> 'parent_domain' + ), + 'value' => '' + ), + 'url' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'NOTEMPTY', + 'errmsg'=> 'subject_is_empty'), + ), + 'filters' => array( + 0 => array( 'event' => 'SAVE', + 'type' => 'STRIPTAGS'), + 1 => array( 'event' => 'SAVE', + 'type' => 'STRIPNL') + ), + 'default' => $sm_default_subject, + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), + 'username' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'default' => '', + 'value' => '', + 'separator' => '', + 'width' => '30', + 'maxlength' => '255', + 'rows' => '', + 'cols' => '', + 'searchable' => 2 + ), + 'password' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'default' => '', + 'value' => '', + 'separator' => '', + 'width' => '30', + 'maxlength' => '255', + 'rows' => '', + 'cols' => '', + 'searchable' => 0 + ), + /*'password' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'PASSWORD', + 'encryption'=> 'CRYPT', + 'default' => '', + 'value' => '', + 'separator' => '', + 'width' => '30', + 'maxlength' => '255', + 'rows' => '', + 'cols' => '' + ),*/ + 'tstamp' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'TEXT', + 'default' => time(), + 'value' => '', + 'width' => '30', + 'maxlength' => '30' + ), + //################################# + // ENDE Datatable fields + //################################# + ) +); + + + +?> \ No newline at end of file diff --git a/interface/web/vcs/index.php b/interface/web/vcs/index.php new file mode 100644 index 0000000000..93204bc525 --- /dev/null +++ b/interface/web/vcs/index.php @@ -0,0 +1,16 @@ + + + +ISPConfig Help + + + +
+

 

+

 

+

 

+

 

+

 

+
+ + \ No newline at end of file diff --git a/interface/web/vcs/lib/admin.conf.php b/interface/web/vcs/lib/admin.conf.php new file mode 100644 index 0000000000..b081da9fe5 --- /dev/null +++ b/interface/web/vcs/lib/admin.conf.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/interface/web/vcs/lib/lang/en_web_git.lng b/interface/web/vcs/lib/lang/en_web_git.lng new file mode 100644 index 0000000000..688c3c7ef7 --- /dev/null +++ b/interface/web/vcs/lib/lang/en_web_git.lng @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/interface/web/vcs/lib/lang/en_web_git_list.lng b/interface/web/vcs/lib/lang/en_web_git_list.lng new file mode 100644 index 0000000000..9e6f98dd7b --- /dev/null +++ b/interface/web/vcs/lib/lang/en_web_git_list.lng @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/interface/web/vcs/lib/module.conf.php b/interface/web/vcs/lib/module.conf.php new file mode 100644 index 0000000000..ba575aae9b --- /dev/null +++ b/interface/web/vcs/lib/module.conf.php @@ -0,0 +1,75 @@ + 'View repositories', + 'target' => 'content', + 'link' => 'vcs/web_git_list.php' + ); + +// Add a menu item with the label 'View messages' +$items[] = array( 'title' => 'Add repository', + 'target' => 'content', + 'link' => 'vcs/web_git_edit.php' + ); + +// Append the menu $items defined above to a menu section labeled 'Support' +$module['nav'][] = array( 'title' => 'Git', + 'open' => 1, + 'items' => $items + ); + +?> \ No newline at end of file diff --git a/interface/web/vcs/list/web_git.list.php b/interface/web/vcs/list/web_git.list.php new file mode 100644 index 0000000000..e2fb0d925f --- /dev/null +++ b/interface/web/vcs/list/web_git.list.php @@ -0,0 +1,102 @@ + "parent_domain_id", + 'datatype' => "VARCHAR", + 'filters' => array( 0 => array( 'event' => 'SHOW', + 'type' => 'IDNTOUTF8') + ), + 'formtype' => "SELECT", + 'op' => "=", + 'prefix' => "", + 'suffix' => "", + 'datasource' => array ( 'type' => 'SQL', + 'querystring' => "SELECT domain_id,domain FROM web_domain WHERE type = 'vhost' AND {AUTHSQL} ORDER BY domain", + 'keyfield'=> 'domain_id', + 'valuefield'=> 'domain' + ), + 'width' => "", + 'value' => ""); + +$liste['item'][] = array( 'field' => 'url', + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'op' => 'like', + 'prefix' => '%', + 'suffix' => '%', + 'width' => '', + 'value' => ''); + +$liste['item'][] = array( 'field' => 'tstamp', + 'datatype' => 'DATETIMETSTAMP', + 'formtype' => 'TEXT', + 'op' => '=', + 'prefix' => '', + 'suffix' => '', + 'width' => '', + 'value' => ''); + + +?> \ No newline at end of file diff --git a/interface/web/vcs/templates/web_git_edit.htm b/interface/web/vcs/templates/web_git_edit.htm new file mode 100644 index 0000000000..4c0f33900a --- /dev/null +++ b/interface/web/vcs/templates/web_git_edit.htm @@ -0,0 +1,38 @@ + +

+ + + {tmpl_var name='parent_domain_id_txt'} +
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+ +
+
+
+ + + + + +
+ + +
diff --git a/interface/web/vcs/templates/web_git_list.htm b/interface/web/vcs/templates/web_git_list.htm new file mode 100644 index 0000000000..095c02df73 --- /dev/null +++ b/interface/web/vcs/templates/web_git_list.htm @@ -0,0 +1,59 @@ + +

+ + +

{tmpl_var name="toolsarea_head_txt"}

+ + + + + + +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{tmpl_var name='search_limit'}
{tmpl_var name="parent_domain_id"}{tmpl_var name="url"}{tmpl_var name="tstamp"} + + +
{tmpl_var name='globalsearch_noresults_text_txt'}
+
+ + diff --git a/interface/web/vcs/templates/web_git_log.htm b/interface/web/vcs/templates/web_git_log.htm new file mode 100644 index 0000000000..a9b6211dc5 --- /dev/null +++ b/interface/web/vcs/templates/web_git_log.htm @@ -0,0 +1,3 @@ +{tmpl_var name='log'} + + diff --git a/interface/web/vcs/web_git_del.php b/interface/web/vcs/web_git_del.php new file mode 100644 index 0000000000..92bbe15259 --- /dev/null +++ b/interface/web/vcs/web_git_del.php @@ -0,0 +1,48 @@ +auth->check_module_permissions('vcs'); + +//* Load the form +$app->uses('tform_actions'); +$app->tform_actions->onDelete(); + +?> \ No newline at end of file diff --git a/interface/web/vcs/web_git_edit.php b/interface/web/vcs/web_git_edit.php new file mode 100644 index 0000000000..28a69421b4 --- /dev/null +++ b/interface/web/vcs/web_git_edit.php @@ -0,0 +1,56 @@ +uses('tpl,tform,tform_actions'); +$app->load('tform_actions'); + +// Create a class page_action that extends the tform_actions base class +class page_action extends tform_actions { + + //Customisations for the page actions will be defined here + function onAfterInsert() + { + global $app, $conf; + // + } + + /* Get the log file */ + function onLoad() { + global $app, $conf; + + $this->id = $app->functions->intval($_REQUEST["id"]); + $filename = $this->id.".log"; + $log = "No data logged for this repository"; + + $array_logs = $app->db->queryAllArray("SELECT data FROM monitor_data WHERE type = ?", "log_web_git_" . $this->id); + if(count($array_logs) > 0) { + $log = ''; + foreach($array_logs as $datalog) { + $log .= unserialize($datalog).PHP_EOL; + } + } + + $app->tpl->setVar("log", nl2br($log)); + parent::onLoad(); + } +} + +// Create the new page object +$page = new page_action(); + +// Start the page rendering and action handling +$page->onLoad(); + +?> diff --git a/interface/web/vcs/web_git_list.php b/interface/web/vcs/web_git_list.php new file mode 100644 index 0000000000..a77c69778f --- /dev/null +++ b/interface/web/vcs/web_git_list.php @@ -0,0 +1,50 @@ +auth->check_module_permissions('vcs'); + +//* Loading the class +$app->uses('listform_actions'); + +//* Optional limit +$userid=$app->functions->intval($_SESSION['s']['user']['userid']); +$app->listform_actions->SQLExtWhere = "web_git.sys_userid = $userid"; + +//* Start the form rendering and action ahndling +$app->listform_actions->onLoad(); + +?> \ No newline at end of file diff --git a/interface/web/vcs/web_git_update.php b/interface/web/vcs/web_git_update.php new file mode 100644 index 0000000000..534bcc4a0d --- /dev/null +++ b/interface/web/vcs/web_git_update.php @@ -0,0 +1,87 @@ +functions->intval($_GET['id']); + +if($userid && $web_git_id) { + /* + * Get the data of the repository + */ + $dbgit = $app->db->queryOneRecord( + "SELECT * FROM web_git WHERE web_git_id = ?", $web_git_id); + + if($dbgit && $dbgit["sys_userid"] == $userid) { + $data = []; + $data['old'] = $data['new'] = $dbgit; + $insert_data = [ + "server_id" => 1, + "dbtable" => "web_git", + "dbidx" => "web_git_id:".$web_git_id, + "action" => 'p', + "tstamp" => time(), + "user" => "admin", + "data" => serialize($data), + "status" => "ok" + ]; + + $mysql_db_user_id = $app->db->insertFromArray('sys_datalog', $insert_data); + + /* Sending this headers prevents the page to load the new content */ + header('HTTP/1.1 500 Internal Server Error'); + } else { + echo "You don't have permission to perform that action."; + } +} else { + echo "You must be logued in and provide an id."; + die(); +} + +die(); +?> \ No newline at end of file diff --git a/server/mods-available/vcs_module.inc.php b/server/mods-available/vcs_module.inc.php new file mode 100644 index 0000000000..756dcb8730 --- /dev/null +++ b/server/mods-available/vcs_module.inc.php @@ -0,0 +1,96 @@ +plugins->announceEvents($this->module_name, $this->actions_available); + + /* + As we want to get notified of any changes on several database tables, + we register for them. + + The following function registers the function "functionname" + to be executed when a record for the table "dbtable" is + processed in the sys_datalog. "classname" is the name of the + class that contains the function functionname. + */ + + $app->modules->registerTableHook('web_git', $this->module_name, 'process'); + } + + /* + This function is called when a change in one of the registered tables is detected. + The function then raises the events for the plugins. + */ + + function process($tablename, $action, $data) { + global $app; + + switch ($tablename) { + case 'web_git': + if($action == 'i') $app->plugins->raiseEvent('web_git_insert', $data); + if($action == 'u') $app->plugins->raiseEvent('web_git_insert', $data); + if($action == 'p') $app->plugins->raiseEvent('web_git_update', $data); + //if($action == 'd') $app->plugins->raiseEvent('web_git_delete', $data); + break; + } // end switch + } // end function + + +} // end class + +?> \ No newline at end of file diff --git a/server/plugins-available/vcs_plugin.inc.php b/server/plugins-available/vcs_plugin.inc.php new file mode 100644 index 0000000000..ebf4c66009 --- /dev/null +++ b/server/plugins-available/vcs_plugin.inc.php @@ -0,0 +1,369 @@ +plugins->registerEvent('web_git_insert', $this->plugin_name, 'insert'); + $app->plugins->registerEvent('web_git_update', $this->plugin_name, 'update'); + //$app->plugins->registerEvent('git_delete', $this->plugin_name, 'delete'); + + } + + /* Pull request */ + function update($event_name, $data) { + global $app, $conf; + + $this->insert($event_name, $data); + } + + /* Check if clone the repo or make a pull */ + function insert($event_name, $data) { + global $app, $conf; + $this->action = 'insert'; + + //Website + $web_id = $data['new']['parent_domain_id']; + $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $web_id); + + //user:grup + $username = escapeshellcmd($website['system_user']); + $groupname = escapeshellcmd($website['system_group']); + + //document_root + $document_root = escapeshellcmd($website['document_root']); + + //Git URL + $git_url = escapeshellcmd($data['new']['url']); + //Git User + $git_user = escapeshellcmd($data['new']['username']); + //Git pass + $git_pass = escapeshellcmd($data['new']['password']); + + if($website) { + //Document root is a git folder? + $dr_isGit = $this->pathIsGit($document_root . '/web'); + if($dr_isGit) { + $this->pull_request($data['new'], $website); + } else { + $this->setup_git($data['new'], $website); + } + + } + + + } + + private function pull_request($data, $website) { + global $app, $conf; + + $curr_path = $this->_exec('pwd'); // Current path + + //document_root + $document_root = escapeshellcmd($website['document_root'])."/web"; + //cd to document_root path + chdir($document_root); + + $gitBinary = $this->_exec("which git"); + + $log = date('Y-m-d h:i:s') . " ==========================================================================".PHP_EOL; + $log .= $this->_exec($gitBinary . ' pull'); + $log .= PHP_EOL."===========================================================================================".PHP_EOL; + + /* the id of the server as int */ + $server_id = intval($conf['server_id']); + + /** The type of the data */ + $type = 'log_web_git_' . $data['web_git_id']; + + /* + * actually this info has no state. + * maybe someone knows better...???... + */ + $state = 'no_state'; + + /* + * Return the Result + */ + $res = array(); + $res['server_id'] = $server_id; + $res['type'] = $type; + $res['data'] = $log; + $res['state'] = $state; + + /* + * Insert the log into the database + */ + $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' . + 'VALUES (?, ?, UNIX_TIMESTAMP(), ?, ?)'; + $app->dbmaster->query($sql, $res['server_id'], $res['type'], serialize($res['data']), $res['state']); + + //Permissions + //user:grup + $username = escapeshellcmd($website['system_user']); + $groupname = escapeshellcmd($website['system_group']); + + //Change permsis + $this->_exec('chown -R ' . $username . ':' . $groupname . ' ' . $document_root); + + chdir($curr_path); + } + + /* Creates a new git repo */ + private function setup_git($data, $website) { + global $app, $conf; + + //Create temp folder for the initial checkout + $tmp_path = '/tmp/web_git'; + $this->_exec('mkdir -p ' . $tmp_path); + $tmp_path .= '/' . $website['domain_id']; + + //Construir URL git con user y pass + $url_parts = parse_url($data['url']); + + if($data['username'] != "") $url_parts['user'] = $data['username']; + if($data['password'] != "") $url_parts['pass'] = $data['password']; + + $git_url = http_build_url($url_parts); + + $gitBinary = $this->_exec("which git"); + if($gitBinary) { + //Clonar repo + $this->_exec($gitBinary . ' clone ' . $git_url . ' ' . $tmp_path); + + //user:grup + $username = escapeshellcmd($website['system_user']); + $groupname = escapeshellcmd($website['system_group']); + //document_root + $document_root = escapeshellcmd($website['document_root']); + + //Cambiar permsis + $this->_exec('chown -R ' . $username . ':' . $groupname . ' ' . $tmp_path); + + //mover .git a document_root + $this->_exec('mv ' . $tmp_path . '/*' . ' ' . $document_root . '/web/'); /* nano comment */ + $this->_exec('mv ' . $tmp_path . '/.*' . ' ' . $document_root . '/web/'); + + //Eliminar carpeta temporal + $this->_exec('rm -rf ' . $tmp_path); + } + } + + function pathIsGit($path) { + global $app, $conf; + $curr_path = $this->_exec('pwd'); // Current path + //cd to document_root path + chdir($path); + + $gitBinary = $this->_exec("which git"); + $check = ''; + if($gitBinary) { + $check = $this->_exec($gitBinary . ' rev-parse --is-inside-work-tree'); //Returns "true" if inside a git repo + } + + chdir($curr_path); //back to previous path + + $app->log($check, LOGLEVEL_DEBUG); + + if($check == "true") { + return true; + } else { + return false; + } + } + + private function _exec($command) { + global $app; + $app->log('exec: '. $command, LOGLEVEL_DEBUG); + $output = shell_exec($command); + return trim($output); + } + + +} // end class + + +/** + * URL constants as defined in the PHP Manual under "Constants usable with + * http_build_url()". + * + * @see http://us2.php.net/manual/en/http.constants.php#http.constants.url + */ +if (!defined('HTTP_URL_REPLACE')) { + define('HTTP_URL_REPLACE', 1); +} +if (!defined('HTTP_URL_JOIN_PATH')) { + define('HTTP_URL_JOIN_PATH', 2); +} +if (!defined('HTTP_URL_JOIN_QUERY')) { + define('HTTP_URL_JOIN_QUERY', 4); +} +if (!defined('HTTP_URL_STRIP_USER')) { + define('HTTP_URL_STRIP_USER', 8); +} +if (!defined('HTTP_URL_STRIP_PASS')) { + define('HTTP_URL_STRIP_PASS', 16); +} +if (!defined('HTTP_URL_STRIP_AUTH')) { + define('HTTP_URL_STRIP_AUTH', 32); +} +if (!defined('HTTP_URL_STRIP_PORT')) { + define('HTTP_URL_STRIP_PORT', 64); +} +if (!defined('HTTP_URL_STRIP_PATH')) { + define('HTTP_URL_STRIP_PATH', 128); +} +if (!defined('HTTP_URL_STRIP_QUERY')) { + define('HTTP_URL_STRIP_QUERY', 256); +} +if (!defined('HTTP_URL_STRIP_FRAGMENT')) { + define('HTTP_URL_STRIP_FRAGMENT', 512); +} +if (!defined('HTTP_URL_STRIP_ALL')) { + define('HTTP_URL_STRIP_ALL', 1024); +} +if (!function_exists('http_build_url')) { + /** + * Build a URL. + * + * The parts of the second URL will be merged into the first according to + * the flags argument. + * + * @param mixed $url (part(s) of) an URL in form of a string or + * associative array like parse_url() returns + * @param mixed $parts same as the first argument + * @param int $flags a bitmask of binary or'ed HTTP_URL constants; + * HTTP_URL_REPLACE is the default + * @param array $new_url if set, it will be filled with the parts of the + * composed url like parse_url() would return + * @return string + */ + function http_build_url($url, $parts = array(), $flags = HTTP_URL_REPLACE, &$new_url = array()) + { + is_array($url) || $url = parse_url($url); + is_array($parts) || $parts = parse_url($parts); + isset($url['query']) && is_string($url['query']) || $url['query'] = null; + isset($parts['query']) && is_string($parts['query']) || $parts['query'] = null; + $keys = array('user', 'pass', 'port', 'path', 'query', 'fragment'); + // HTTP_URL_STRIP_ALL and HTTP_URL_STRIP_AUTH cover several other flags. + if ($flags & HTTP_URL_STRIP_ALL) { + $flags |= HTTP_URL_STRIP_USER | HTTP_URL_STRIP_PASS + | HTTP_URL_STRIP_PORT | HTTP_URL_STRIP_PATH + | HTTP_URL_STRIP_QUERY | HTTP_URL_STRIP_FRAGMENT; + } elseif ($flags & HTTP_URL_STRIP_AUTH) { + $flags |= HTTP_URL_STRIP_USER | HTTP_URL_STRIP_PASS; + } + // Schema and host are alwasy replaced + foreach (array('scheme', 'host') as $part) { + if (isset($parts[$part])) { + $url[$part] = $parts[$part]; + } + } + if ($flags & HTTP_URL_REPLACE) { + foreach ($keys as $key) { + if (isset($parts[$key])) { + $url[$key] = $parts[$key]; + } + } + } else { + if (isset($parts['path']) && ($flags & HTTP_URL_JOIN_PATH)) { + if (isset($url['path']) && substr($parts['path'], 0, 1) !== '/') { + // Workaround for trailing slashes + $url['path'] .= 'a'; + $url['path'] = rtrim( + str_replace(basename($url['path']), '', $url['path']), + '/' + ) . '/' . ltrim($parts['path'], '/'); + } else { + $url['path'] = $parts['path']; + } + } + if (isset($parts['query']) && ($flags & HTTP_URL_JOIN_QUERY)) { + if (isset($url['query'])) { + parse_str($url['query'], $url_query); + parse_str($parts['query'], $parts_query); + $url['query'] = http_build_query( + array_replace_recursive( + $url_query, + $parts_query + ) + ); + } else { + $url['query'] = $parts['query']; + } + } + } + if (isset($url['path']) && $url['path'] !== '' && substr($url['path'], 0, 1) !== '/') { + $url['path'] = '/' . $url['path']; + } + foreach ($keys as $key) { + $strip = 'HTTP_URL_STRIP_' . strtoupper($key); + if ($flags & constant($strip)) { + unset($url[$key]); + } + } + $parsed_string = ''; + if (!empty($url['scheme'])) { + $parsed_string .= $url['scheme'] . '://'; + } + if (!empty($url['user'])) { + $parsed_string .= $url['user']; + if (isset($url['pass'])) { + $parsed_string .= ':' . $url['pass']; + } + $parsed_string .= '@'; + } + if (!empty($url['host'])) { + $parsed_string .= $url['host']; + } + if (!empty($url['port'])) { + $parsed_string .= ':' . $url['port']; + } + if (!empty($url['path'])) { + $parsed_string .= $url['path']; + } + if (!empty($url['query'])) { + $parsed_string .= '?' . $url['query']; + } + if (!empty($url['fragment'])) { + $parsed_string .= '#' . $url['fragment']; + } + $new_url = $url; + return $parsed_string; + } +} + +?> -- GitLab From 1e103b9db7c19fafcef6f8d83cbba70f0abd28f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20Marcos?= Date: Mon, 11 Jun 2018 16:30:30 +0200 Subject: [PATCH 3/6] Update installation info --- README.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index a62e7a483b..b0bef016eb 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ - Administrator, reseller and client login - Configuration mirroring and clusters - Open Source software (BSD license) -- + # ISPConfig-vcs Easy version control system integration in ISPConfig 3. @@ -36,21 +36,14 @@ If not, it tries to clone it. If yes, performs a 'git pull' and changes and chow * Git repository url (HTTP/HTTPS) -## Instalation +## Installation I recommend you test this plugin in a non-production enviroment. ``` -#Get sources -git clone http://git.funcli.net:3000/funcli/ISPConfig-vcs.git /tmp/vcs -cd /tmp/vcs - #Import database table mysql -uroot -p dbispconfig < database.sql -#Add files to ISPConfig -cp -r interface /usr/local/ispconfig/ -cp -r server /usr/local/ispconfig/ #Enable module and plugin ln -s /usr/local/ispconfig/server/mods-available/vcs_module.inc.php /usr/local/ispconfig/server/mods-enabled/vcs_module.inc.php -- GitLab From 8d9acff5f515ab20a74296f4164b6a7288f4de16 Mon Sep 17 00:00:00 2001 From: jadsolucions Date: Wed, 13 Jun 2018 12:29:09 +0200 Subject: [PATCH 4/6] Added delete events Tabs --- server/mods-available/vcs_module.inc.php | 6 +- server/plugins-available/vcs_plugin.inc.php | 264 +++++++++++--------- 2 files changed, 151 insertions(+), 119 deletions(-) diff --git a/server/mods-available/vcs_module.inc.php b/server/mods-available/vcs_module.inc.php index 756dcb8730..013490ad95 100644 --- a/server/mods-available/vcs_module.inc.php +++ b/server/mods-available/vcs_module.inc.php @@ -1,7 +1,7 @@ plugins->raiseEvent('web_git_insert', $data); if($action == 'u') $app->plugins->raiseEvent('web_git_insert', $data); if($action == 'p') $app->plugins->raiseEvent('web_git_update', $data); - //if($action == 'd') $app->plugins->raiseEvent('web_git_delete', $data); + if($action == 'd') $app->plugins->raiseEvent('web_git_delete', $data); break; } // end switch } // end function @@ -93,4 +93,4 @@ class vcs_module { } // end class -?> \ No newline at end of file +?> diff --git a/server/plugins-available/vcs_plugin.inc.php b/server/plugins-available/vcs_plugin.inc.php index ebf4c66009..6b35ce058a 100644 --- a/server/plugins-available/vcs_plugin.inc.php +++ b/server/plugins-available/vcs_plugin.inc.php @@ -39,15 +39,47 @@ class vcs_plugin { $app->plugins->registerEvent('web_git_insert', $this->plugin_name, 'insert'); $app->plugins->registerEvent('web_git_update', $this->plugin_name, 'update'); - //$app->plugins->registerEvent('git_delete', $this->plugin_name, 'delete'); + $app->plugins->registerEvent('web_git_delete', $this->plugin_name, 'delete'); + //When a web is deleted, check if it has a web_git associated + $app->plugins->registerEvent('web_domain_delete', $this->plugin_name, 'chekRemovedWeb'); + } + + function chekRemovedWeb($event_name, $data) { + global $app, $conf; + + $domain_id = $data['old']['domain_id']; + + if($domain_id) { + $array_logs = $app->db->query("DELETE FROM web_git WHERE parent_domain_id = ?", $domain_id); + } + } + + function delete($event_name, $data) { + global $app, $conf; + + //Website + $web_id = $data['old']['parent_domain_id']; + $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $web_id); + + //document_root + $document_root = escapeshellcmd($website['document_root']); + + if($website) { + //Document root is a git folder? + $path = $document_root . '/web'; + $dr_isGit = $this->pathIsGit($path); + if($dr_isGit) { + $this->_exec('rm -rf ' . $path . '/.git'); + } + } } /* Pull request */ function update($event_name, $data) { - global $app, $conf; + global $app, $conf; - $this->insert($event_name, $data); + $this->insert($event_name, $data); } /* Check if clone the repo or make a pull */ @@ -55,161 +87,161 @@ class vcs_plugin { global $app, $conf; $this->action = 'insert'; - //Website - $web_id = $data['new']['parent_domain_id']; - $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $web_id); + //Website + $web_id = $data['new']['parent_domain_id']; + $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $web_id); - //user:grup - $username = escapeshellcmd($website['system_user']); + //user:grup + $username = escapeshellcmd($website['system_user']); $groupname = escapeshellcmd($website['system_group']); - //document_root - $document_root = escapeshellcmd($website['document_root']); - - //Git URL - $git_url = escapeshellcmd($data['new']['url']); - //Git User - $git_user = escapeshellcmd($data['new']['username']); - //Git pass - $git_pass = escapeshellcmd($data['new']['password']); - - if($website) { - //Document root is a git folder? - $dr_isGit = $this->pathIsGit($document_root . '/web'); - if($dr_isGit) { - $this->pull_request($data['new'], $website); - } else { - $this->setup_git($data['new'], $website); - } + //document_root + $document_root = escapeshellcmd($website['document_root']); + + //Git URL + $git_url = escapeshellcmd($data['new']['url']); + //Git User + $git_user = escapeshellcmd($data['new']['username']); + //Git pass + $git_pass = escapeshellcmd($data['new']['password']); + + if($website) { + //Document root is a git folder? + $dr_isGit = $this->pathIsGit($document_root . '/web'); + if($dr_isGit) { + $this->pull_request($data['new'], $website); + } else { + $this->setup_git($data['new'], $website); + } - } + } } private function pull_request($data, $website) { - global $app, $conf; + global $app, $conf; - $curr_path = $this->_exec('pwd'); // Current path + $curr_path = $this->_exec('pwd'); // Current path - //document_root + //document_root $document_root = escapeshellcmd($website['document_root'])."/web"; //cd to document_root path chdir($document_root); - $gitBinary = $this->_exec("which git"); - - $log = date('Y-m-d h:i:s') . " ==========================================================================".PHP_EOL; - $log .= $this->_exec($gitBinary . ' pull'); - $log .= PHP_EOL."===========================================================================================".PHP_EOL; - - /* the id of the server as int */ - $server_id = intval($conf['server_id']); - - /** The type of the data */ - $type = 'log_web_git_' . $data['web_git_id']; - - /* - * actually this info has no state. - * maybe someone knows better...???... - */ - $state = 'no_state'; - - /* - * Return the Result - */ - $res = array(); - $res['server_id'] = $server_id; - $res['type'] = $type; - $res['data'] = $log; - $res['state'] = $state; - - /* - * Insert the log into the database - */ - $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' . - 'VALUES (?, ?, UNIX_TIMESTAMP(), ?, ?)'; - $app->dbmaster->query($sql, $res['server_id'], $res['type'], serialize($res['data']), $res['state']); - - //Permissions - //user:grup + $gitBinary = $this->_exec("which git"); + + $log = date('Y-m-d h:i:s') . " ==========================================================================".PHP_EOL; + $log .= $this->_exec($gitBinary . ' pull'); + $log .= PHP_EOL."===========================================================================================".PHP_EOL; + + /* the id of the server as int */ + $server_id = intval($conf['server_id']); + + /** The type of the data */ + $type = 'log_web_git_' . $data['web_git_id']; + + /* + * actually this info has no state. + * maybe someone knows better...???... + */ + $state = 'no_state'; + + /* + * Return the Result + */ + $res = array(); + $res['server_id'] = $server_id; + $res['type'] = $type; + $res['data'] = $log; + $res['state'] = $state; + + /* + * Insert the log into the database + */ + $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' . + 'VALUES (?, ?, UNIX_TIMESTAMP(), ?, ?)'; + $app->dbmaster->query($sql, $res['server_id'], $res['type'], serialize($res['data']), $res['state']); + + //Permissions + //user:grup $username = escapeshellcmd($website['system_user']); $groupname = escapeshellcmd($website['system_group']); - //Change permsis + //Change permsis $this->_exec('chown -R ' . $username . ':' . $groupname . ' ' . $document_root); - chdir($curr_path); + chdir($curr_path); } /* Creates a new git repo */ private function setup_git($data, $website) { - global $app, $conf; + global $app, $conf; - //Create temp folder for the initial checkout - $tmp_path = '/tmp/web_git'; - $this->_exec('mkdir -p ' . $tmp_path); - $tmp_path .= '/' . $website['domain_id']; + //Create temp folder for the initial checkout + $tmp_path = '/tmp/web_git'; + $this->_exec('mkdir -p ' . $tmp_path); + $tmp_path .= '/' . $website['domain_id']; - //Construir URL git con user y pass - $url_parts = parse_url($data['url']); + //Construir URL git con user y pass + $url_parts = parse_url($data['url']); - if($data['username'] != "") $url_parts['user'] = $data['username']; - if($data['password'] != "") $url_parts['pass'] = $data['password']; + if($data['username'] != "") $url_parts['user'] = $data['username']; + if($data['password'] != "") $url_parts['pass'] = $data['password']; - $git_url = http_build_url($url_parts); + $git_url = http_build_url($url_parts); - $gitBinary = $this->_exec("which git"); - if($gitBinary) { - //Clonar repo - $this->_exec($gitBinary . ' clone ' . $git_url . ' ' . $tmp_path); + $gitBinary = $this->_exec("which git"); + if($gitBinary) { + //Clonar repo + $this->_exec($gitBinary . ' clone ' . $git_url . ' ' . $tmp_path); - //user:grup - $username = escapeshellcmd($website['system_user']); - $groupname = escapeshellcmd($website['system_group']); - //document_root - $document_root = escapeshellcmd($website['document_root']); + //user:grup + $username = escapeshellcmd($website['system_user']); + $groupname = escapeshellcmd($website['system_group']); + //document_root + $document_root = escapeshellcmd($website['document_root']); - //Cambiar permsis - $this->_exec('chown -R ' . $username . ':' . $groupname . ' ' . $tmp_path); + //Cambiar permsis + $this->_exec('chown -R ' . $username . ':' . $groupname . ' ' . $tmp_path); - //mover .git a document_root - $this->_exec('mv ' . $tmp_path . '/*' . ' ' . $document_root . '/web/'); /* nano comment */ - $this->_exec('mv ' . $tmp_path . '/.*' . ' ' . $document_root . '/web/'); + //mover .git a document_root + $this->_exec('mv ' . $tmp_path . '/*' . ' ' . $document_root . '/web/'); /* nano comment */ + $this->_exec('mv ' . $tmp_path . '/.*' . ' ' . $document_root . '/web/'); - //Eliminar carpeta temporal - $this->_exec('rm -rf ' . $tmp_path); - } + //Eliminar carpeta temporal + $this->_exec('rm -rf ' . $tmp_path); + } } function pathIsGit($path) { - global $app, $conf; - $curr_path = $this->_exec('pwd'); // Current path - //cd to document_root path - chdir($path); - - $gitBinary = $this->_exec("which git"); - $check = ''; - if($gitBinary) { - $check = $this->_exec($gitBinary . ' rev-parse --is-inside-work-tree'); //Returns "true" if inside a git repo - } + global $app, $conf; + $curr_path = $this->_exec('pwd'); // Current path + //cd to document_root path + chdir($path); + + $gitBinary = $this->_exec("which git"); + $check = ''; + if($gitBinary) { + $check = $this->_exec($gitBinary . ' rev-parse --is-inside-work-tree'); //Returns "true" if inside a git repo + } - chdir($curr_path); //back to previous path + chdir($curr_path); //back to previous path - $app->log($check, LOGLEVEL_DEBUG); + $app->log($check, LOGLEVEL_DEBUG); - if($check == "true") { - return true; - } else { - return false; - } + if($check == "true") { + return true; + } else { + return false; + } } private function _exec($command) { - global $app; - $app->log('exec: '. $command, LOGLEVEL_DEBUG); - $output = shell_exec($command); - return trim($output); + global $app; + $app->log('exec: '. $command, LOGLEVEL_DEBUG); + $output = shell_exec($command); + return trim($output); } -- GitLab From 909a8da92c77635e8e18cd63c1d385afbf413248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93scar=20Marcos?= Date: Wed, 13 Jun 2018 12:51:29 +0200 Subject: [PATCH 5/6] Update README.md --- README.md | 43 +------------------------------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/README.md b/README.md index b0bef016eb..4676d2bd58 100644 --- a/README.md +++ b/README.md @@ -7,45 +7,4 @@ - Virtualization (OpenVZ) - Administrator, reseller and client login - Configuration mirroring and clusters -- Open Source software (BSD license) - -# ISPConfig-vcs - -Easy version control system integration in ISPConfig 3. - -This is a very early version, so only git repositories can be created for the moment. - - -## What is this for? -This plugin integrates Git repositories for the ISPConfig Sites. - -You have the option to 'git clone' a repository on the %document_root%/web folder of the websites. -The first time you add the repo it tries to 'git clone'-it creating a temporal folder in /tmp/web_git/[web_git_id]/. -After the clone, it changes permissions to every file with the user and group of the website. Then it moves all the content to the %document_root%/web folder. - -Every time you change the values of a repository (via ISPConfig form) it checks if there is a git repository created in the folder. -If not, it tries to clone it. If yes, performs a 'git pull' and changes and chowns all the web folder. - -'git pull' log is stored and can be viewed inside a Git repository register. - - -## Requirements -* ISPConfig 3 -* Admin user -* git -* Git repository url (HTTP/HTTPS) - - -## Installation - -I recommend you test this plugin in a non-production enviroment. - -``` -#Import database table -mysql -uroot -p dbispconfig < database.sql - - -#Enable module and plugin -ln -s /usr/local/ispconfig/server/mods-available/vcs_module.inc.php /usr/local/ispconfig/server/mods-enabled/vcs_module.inc.php -ln -s /usr/local/ispconfig/server/plugins-available/vcs_plugin.inc.php /usr/local/ispconfig/server/plugins-enabled/vcs_plugin.inc.php -``` \ No newline at end of file +- Open Source software (BSD license) \ No newline at end of file -- GitLab From 036185ad3c447dd38724db360c0aa74d5dfb6fdb Mon Sep 17 00:00:00 2001 From: Funcli Date: Sat, 13 Oct 2018 01:33:55 +0200 Subject: [PATCH 6/6] Now everything is executed by the user of the website. Created a more random temp path (where the first 'git clone' it's done). No chown needed anymore. A bit of refactoring. --- server/plugins-available/vcs_plugin.inc.php | 96 ++++++++++++--------- 1 file changed, 56 insertions(+), 40 deletions(-) diff --git a/server/plugins-available/vcs_plugin.inc.php b/server/plugins-available/vcs_plugin.inc.php index 6b35ce058a..646c3e07d6 100644 --- a/server/plugins-available/vcs_plugin.inc.php +++ b/server/plugins-available/vcs_plugin.inc.php @@ -11,6 +11,7 @@ class vcs_plugin { // private variables var $action = ''; + var $website; //* This function is called during ispconfig installation to determine // if a symlink shall be created for this plugin. @@ -25,6 +26,25 @@ class vcs_plugin { } + /** + * Returns the website record in the database by its ID. Saves the info in a variable like cache. + * + * @param $website_id ID of the record to fetch + * @return Array Datos de una website en la base de datos. + */ + private function getWebsiteById($web_id) { + global $app; + + if(isset($this->website) && $this->website) { + $website = $this->website; + } else { + $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $web_id); + $this->website = $website; + } + + return $website; + } + /* This function is called when the plugin is loaded @@ -60,15 +80,15 @@ class vcs_plugin { //Website $web_id = $data['old']['parent_domain_id']; - $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $web_id); + $website = $this->getWebsiteById($web_id); //document_root - $document_root = escapeshellcmd($website['document_root']); + $document_root = escapeshellcmd($website['document_root']); if($website) { //Document root is a git folder? $path = $document_root . '/web'; - $dr_isGit = $this->pathIsGit($path); + $dr_isGit = $this->pathIsGit($path); if($dr_isGit) { $this->_exec('rm -rf ' . $path . '/.git'); } @@ -89,7 +109,7 @@ class vcs_plugin { //Website $web_id = $data['new']['parent_domain_id']; - $website = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $web_id); + $website = $this->getWebsiteById($web_id); //user:grup $username = escapeshellcmd($website['system_user']); @@ -122,8 +142,6 @@ class vcs_plugin { private function pull_request($data, $website) { global $app, $conf; - $curr_path = $this->_exec('pwd'); // Current path - //document_root $document_root = escapeshellcmd($website['document_root'])."/web"; //cd to document_root path @@ -131,7 +149,7 @@ class vcs_plugin { $gitBinary = $this->_exec("which git"); - $log = date('Y-m-d h:i:s') . " ==========================================================================".PHP_EOL; + $log = date('Y-m-d h:i:s') . " ==========================================================================".PHP_EOL; $log .= $this->_exec($gitBinary . ' pull'); $log .= PHP_EOL."===========================================================================================".PHP_EOL; @@ -161,17 +179,7 @@ class vcs_plugin { */ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' . 'VALUES (?, ?, UNIX_TIMESTAMP(), ?, ?)'; - $app->dbmaster->query($sql, $res['server_id'], $res['type'], serialize($res['data']), $res['state']); - - //Permissions - //user:grup - $username = escapeshellcmd($website['system_user']); - $groupname = escapeshellcmd($website['system_group']); - - //Change permsis - $this->_exec('chown -R ' . $username . ':' . $groupname . ' ' . $document_root); - - chdir($curr_path); + $app->dbmaster->query($sql, $res['server_id'], $res['type'], serialize($res['data']), $res['state']); } /* Creates a new git repo */ @@ -179,11 +187,11 @@ class vcs_plugin { global $app, $conf; //Create temp folder for the initial checkout - $tmp_path = '/tmp/web_git'; - $this->_exec('mkdir -p ' . $tmp_path); - $tmp_path .= '/' . $website['domain_id']; + $milliseconds = round(microtime(true) * 1000); + $tmp_path = '/tmp/web_git'.$milliseconds; + $this->_exec('mkdir -p ' . $tmp_path); - //Construir URL git con user y pass + //Construir URL git con user y pass $url_parts = parse_url($data['url']); if($data['username'] != "") $url_parts['user'] = $data['username']; @@ -193,54 +201,62 @@ class vcs_plugin { $gitBinary = $this->_exec("which git"); if($gitBinary) { - //Clonar repo + //Clonar repo $this->_exec($gitBinary . ' clone ' . $git_url . ' ' . $tmp_path); - //user:grup - $username = escapeshellcmd($website['system_user']); - $groupname = escapeshellcmd($website['system_group']); //document_root - $document_root = escapeshellcmd($website['document_root']); + $document_root = escapeshellcmd($website['document_root']); - //Cambiar permsis - $this->_exec('chown -R ' . $username . ':' . $groupname . ' ' . $tmp_path); - - //mover .git a document_root + //mover .git a document_root $this->_exec('mv ' . $tmp_path . '/*' . ' ' . $document_root . '/web/'); /* nano comment */ $this->_exec('mv ' . $tmp_path . '/.*' . ' ' . $document_root . '/web/'); //Eliminar carpeta temporal - $this->_exec('rm -rf ' . $tmp_path); + $this->_exec('rm -rf ' . $tmp_path); } } function pathIsGit($path) { global $app, $conf; - $curr_path = $this->_exec('pwd'); // Current path + //cd to document_root path chdir($path); $gitBinary = $this->_exec("which git"); $check = ''; - if($gitBinary) { + if($gitBinary) { $check = $this->_exec($gitBinary . ' rev-parse --is-inside-work-tree'); //Returns "true" if inside a git repo } - chdir($curr_path); //back to previous path - - $app->log($check, LOGLEVEL_DEBUG); - if($check == "true") { + $app->log("Path is a git folder", LOGLEVEL_DEBUG); return true; } else { + $app->log("Path is NOT a git folder", LOGLEVEL_DEBUG); return false; } } private function _exec($command) { global $app; - $app->log('exec: '. $command, LOGLEVEL_DEBUG); - $output = shell_exec($command); + + $command_original = $command; + + if(isset($this->website['system_user']) && $this->website['system_user']) { + $user = escapeshellcmd($this->website['system_user']); + $command = "sudo -H -u ". $user ." bash -c '".$command."'"; + } else { + $user = "root"; + } + + $app->log('exec (as '.$user.'): '. $command_original, LOGLEVEL_DEBUG); + $output = shell_exec($command); + + /** + * + * usar exec en vez de shell_exec, devolver un array con 0 => status, 1 => $output + */ + return trim($output); } -- GitLab