<?php // Some helper functions dealing with users/repos/bugs/etc. include_once('totp.inc.php'); /* * Creating a user */ $_user_id = time() . '-' . rg_id(8); $_testns = 'main'; function rg_test_create_user($db, &$rg_ui) { global $_testns; global $_user_id; if (!isset($_user_id)) $_user_id = time() . '-' . rg_id(8); if (!is_array($rg_ui)) $rg_ui = array(); $username = $_testns . '-user-' . $_user_id . '<xss>e'; $new = array(); $new['uid'] = 0; $new['organization'] = 0; $new['username'] = $username; $new['realname'] = 'realname-' . $_user_id . '<xss>'; $new['email'] = 'email-' . $_user_id . '@embedromix.ro'; $new['is_admin'] = 0; $new['rights'] = 'C'; $new['session_time'] = 3600; $new['confirm_token'] = ''; $new['confirmed'] = 0; $new['plan_id'] = 0; $new['pass'] = 'pass-' . $_user_id . ':'; $new['pass2'] = 'pass-' . $_user_id . ':'; $new['disk_used_mb'] = 0; $new['git_mb'] = 0; $new['artifacts_mb'] = 0; $new['last_ip'] = '?'; $_user_id++; // Delete old user $sql = 'DELETE FROM users WHERE username = @@username@@'; $res = rg_sql_query_params($db, $sql, $new); if ($res === FALSE) { rg_log("Cannot delete old user: " . rg_sql_error()); exit(1); } rg_sql_free_result($res); rg_cache_unset('username_to_uid::' . $username, RG_SOCKET_NO_WAIT); $rg_ui = array_merge($new, $rg_ui); $r = rg_user_edit($db, $rg_ui); if ($r === FALSE) { rg_log("Cannot create user (" . rg_user_error() . ")!"); exit(1); } $rg_ui['uid'] = $r; // delete associated bugs $sql = "SELECT * FROM repos WHERE uid = " . $rg_ui['uid']; $res = rg_sql_query($db, $sql); while (($row = rg_sql_fetch_array($res))) { $_t = array('bug_labels', 'bug_notes', 'bug_search', 'bugs', 'merge_requests', 'watch_bug', 'watch_repo'); foreach ($_t as $_table) { $sql = "DELETE FROM $_table WHERE repo_id = " . $row['repo_id']; $res2 = rg_sql_query($db, $sql); rg_sql_free_result($res2); } $sql = "DELETE FROM rights WHERE type = 'repo' AND obj_id = " . $row['repo_id']; $res2 = rg_sql_query($db, $sql); rg_sql_free_result($res2); } rg_sql_free_result($res); // delete associated repos $sql = "DELETE FROM repos WHERE uid = " . $rg_ui['uid']; $res = rg_sql_query($db, $sql); rg_sql_free_result($res); // Delete associated keys $sql = "DELETE FROM keys WHERE uid = " . $rg_ui['uid']; $res = rg_sql_query($db, $sql); rg_sql_free_result($res); // Delete given rights $sql = "DELETE FROM rights WHERE uid = " . $rg_ui['uid']; $res = rg_sql_query($db, $sql); rg_sql_free_result($res); // Delete login tokens $sql = "DELETE FROM login_tokens WHERE uid = " . $rg_ui['uid']; $res = rg_sql_query($db, $sql); rg_sql_free_result($res); // Delete login tokens ips $sql = "DELETE FROM login_tokens_ip WHERE uid = " . $rg_ui['uid']; $res = rg_sql_query($db, $sql); rg_sql_free_result($res); } /* * Creating a repo helper; see rg_test_create_repo() */ $_repo_id = 1; function rg_test_create_repo_no_dir($db, $rg_ui, &$extra) { global $_testns; global $_repo_id; if (!is_array($extra)) $extra = array(); $repo_id = isset($extra['repo_id']) ? $extra['repo_id'] : 0; rg_log('Creating a repo with id ' . $repo_id); $new = array(); $new['master'] = 0; if (isset($extra['name'])) $new['name'] = $extra['name']; else $new['name'] = $_testns . '-repo-' . $_repo_id . '<xss>' . rand(); $new['max_commit_size'] = 0; $new['description'] = 'desc line1\ndesc line2' . '<xss>'; $new['git_dir_done'] = 0; $new['public'] = 1; $new['license'] = 'GPL <xss>'; $new['template'] = 'template here <xss>'; $_repo_id++; rg_log("Deleting repo " . $repo_id . "/" . $new['name']); $sql = 'DELETE FROM repos WHERE repo_id = ' . $repo_id . ' OR name = @@name@@'; $res = rg_sql_query_params($db, $sql, $new); if ($res === FALSE) { rg_log("Cannot delete old repo: " . rg_sql_error()); exit(1); } rg_sql_free_result($res); $extra = array_merge($new, $extra); $extra['repo_id'] = 0; $r = rg_repo_edit($db, $rg_ui, $extra); if ($r === FALSE) { rg_log("Cannot insert a repo (" . rg_repo_error() . ")!"); exit(1); } rg_repo_cosmetic($db, $extra); rg_log_ml('extra: ' . print_r($extra, TRUE)); if ($repo_id > 0) { $sql = "UPDATE repos SET repo_id = $repo_id" . " WHERE repo_id = " . $extra['repo_id']; $res = rg_sql_query($db, $sql); rg_sql_free_result($res); $new['repo_id'] = $repo_id; // TODO: this is strange rg_cache_unset('repo_by_name::' . $rg_ui['uid'], RG_SOCKET_NO_WAIT); } } /* * Creating a repo helper * You can enforce a repo-name/repo-id by setting extra['name/repo_id']. */ function rg_test_create_repo($db, $rg_ui, &$extra) { rg_test_create_repo_no_dir($db, $rg_ui, $extra); $key = 'repo_by_id' . '::' . $extra['repo_id']; rg_log('Waiting for the repo git dir to be created (key [' . $key . '])...'); $tries = 50; while ($tries > 0) { $tries--; rg_cache_core_unset($key); $r = rg_cache_get($key); if ($r === FALSE) { sleep(1); continue; } //rg_log_ml('DEBUG: r: ' . print_r($r, TRUE)); if ($r['git_dir_done'] == 1) break; sleep(1); } if ($tries === 0) { rg_log('Seems that the git folder was not created!'); exit(1); } } /* * Creating a ssh key helper */ function rg_test_create_key($db, $rg_ui) { rg_log("Creating a key"); // spaces are on purpose, to test that we remove them correctly $skey = 'ssh-rsa AAAAB3Nz aC1yc2EAAAADA QABAAABAQDgy8QSbr13izfGxO0sqOsxu4faw6hF1LLrlcBobT5zzO4wzbokjliRiZ9sfA0zd0WEfdQJ6W01hVNf9QpJlUiGM4OyXBKOc8JLfCyjtcfRcC48hPQ22IY9TtfrxGK38IgwdS7+Ophjs8u0RlqHd8eMtYWcmxlHwdIEb6+IZ6kyA2srmFGN6DQCnOvyYSd+iZ8u4DQBEuWxzsKvrat9gR5H6KNTYisSB9rjLKQd4rFbu6Tl217wJY1LWjH7hlFPxioMCg0Fzv6AkQXWnAr1GrCVgIQDC5dEVUrw2NSVElEC+eaG6OZnkq7CP0B8pSj3BV2TNhSgnQb9Ojo9xNHc2Pwx aaa@aaa.aaa'; $r = rg_keys_add($db, $rg_ui, $skey); if ($r === FALSE) { rg_log("Cannot add a key (" . rg_keys_error() . ")!"); exit(1); } return $r; } /* * Helper to add some rights */ function rg_test_create_rights($db, $rg_ui, $ri, &$extra) { if (!is_array($extra)) $extra = array(); $a = array(); $a['right_id'] = 0; $a['who'] = 90; $a['obj_id'] = $ri['repo_id']; $a['uid'] = $rg_ui['uid']; $a['rights'] = "abc"; $a['misc'] = "misc1/@USER@/"; $a['ip'] = "1.1.1.1 2.2.2.2 10.0.0.0/8"; $a['prio'] = 13; $a['description'] = "desc1"; $r = rg_rights_set($db, "type1", $a); if ($r !== TRUE) { rg_log("Seems I cannot set rights 1 (" . rg_rights_error() . ")"); exit(1); } return $r; } /* * Helper to add a bug */ function rg_test_create_bug($db, $rg_ui, $ri, &$extra) { if (!is_array($extra)) $extra = array(); $a = array(); $a['bug_id'] = 0; $a['itime'] = time() - 600; $a['utime'] = time() - 300; $a['uid'] = 30; $a['ip'] = '1.1.1.1 <xss>'; $a['title'] = 'a nice title <xss>'; $a['body'] = 'a nice body <xss>'; $a['assigned_uid'] = 0; $a['deleted'] = 0; $a['deleted_who'] = 0; $a['state'] = 1; $r = rg_bug_edit($db, $rg_ui, $ri, $a); if ($r === FALSE) { rg_log('Seems I cannot add bug: ' . rg_bug_error() . ")"); exit(1); } return $r; } /* * Helper for creating and uploading a ssh key * Returns the key. */ function rg_test_upload_ssh_key($db, $rg_ui, $key_suffix, &$key_name) { global $test_url; $key_name = $rg_ui['uid'] . $key_suffix; putenv('RG_SSH_KEY=' . $key_name); // we must regenerate the key because else we will not be the correct user rg_log_enter("Generating a SSH key [$key_name]"); if (file_exists('keys/' . $key_name)) unlink('keys/' . $key_name); if (file_exists('keys/' . $key_name . '.pub')) unlink('keys/' . $key_name . '.pub'); $r = rg_exec("ssh-keygen -t rsa -N '' -b 4096 -C \"Key for RocketGit\"" . " -f keys/" . escapeshellarg($key_name) . " </dev/null", '', FALSE, FALSE, FALSE); if ($r['ok'] != 1) { rg_log('Cannot generate key: ' . $r['stderr']); exit(1); } if (!file_exists("keys/" . $key_name . ".pub")) { rg_log("Could not find the ssh key!"); exit(1); } $key = file_get_contents("keys/" . $key_name . ".pub"); rg_log("Loading ssh key form..."); $data = array(); $headers = array(); $r = do_req($test_url . "/op/settings/keys?t=load_key_form", $data, $headers); if ($r === FALSE) { rg_log("Cannot load form!"); exit(1); } if (empty($r['tokens']['keys'])) { rg_log_ml('r: ' . print_r($r, TRUE)); rg_log('token not found!'); exit(1); } rg_log("Uploading the key..."); $data = array('add' => 1, 'token' => $r['tokens']['keys'], 'key' => $key); $headers = array(); $r = do_req($test_url . '/op/settings/keys?t=upload_ssh_key', $data, $headers); if ($r === FALSE) { rg_log_ml('r: ' . print_r($r, TRUE)); rg_log_ml("Cannot upload key!"); exit(1); } $akp = rg_state_get($db, 'AuthorizedKeysCommand'); if ($akp == 0) { rg_log("Waiting for key to be added to the authorized_keys file"); while (1) { $c = file_get_contents("/home/rocketgit/.ssh/authorized_keys"); if (strstr($c, $key)) break; sleep(1); } } rg_log("Uploading done"); rg_log_exit(); return $key; } /* * Helper for generating scratch codes * Returns the scratch codes. */ function rg_test_sc_generate($db, $rg_ui) { global $test_url; rg_log("Loading generate scratch codes form..."); $data = array(); $headers = array(); $r = do_req($test_url . "/op/settings/totp/sc", $data, $headers); if ($r === FALSE) { rg_log("Cannot load form!"); exit(1); } if (empty($r['tokens']['sc'])) { rg_log_ml('r: ' . print_r($r, TRUE)); rg_log('token not found!'); exit(1); } rg_log("Generating scratch codes..."); $data = array('generate' => 1, 'token' => $r['tokens']['sc']); $headers = array(); $r = do_req($test_url . '/op/settings/totp/sc', $data, $headers); if ($r === FALSE) { rg_log_ml('r: ' . print_r($r, TRUE)); rg_log_ml('Cannot generate scratch codes!'); exit(1); } rg_log("Generation done"); $t = explode('<div class="secret_token">', $r['body']); $t = explode('</div>', $t[1]); $t = explode("\n", $t[0]); $sc = explode(' ', trim($t[1])); rg_log_ml('DEBUG: sc: ' . print_r($sc, TRUE)); return $sc; } /* * Helper for adding a webhook */ function rg_test_wh_add_edit($db, $rg_ui, $htype, $hsubtype, $extra) { global $test_url; rg_log_enter('Loading webhook add form...'); $headers = array(); if (!isset($extra['wh::id'])) $extra['wh::id'] = 0; if ($extra['wh::id'] == 0) $url = 'add/' . $htype . '/' . $hsubtype; else $url = 'edit/' . $extra['wh::id']; $r = do_req($test_url . "/op/settings/wh/" . $url, $data, $headers); if ($r === FALSE) { rg_log("Cannot load form!"); exit(1); } if (empty($r['tokens']['wh_add'])) { rg_log_ml('r: ' . print_r($r, TRUE)); rg_log_ml('Token not found!'); exit(1); } rg_log("Adding webhook..."); $data = array('doit' => 1, 'token' => $r['tokens']['wh_add']); $data = array_merge($data, $extra); $headers = array(); $r = do_req($test_url . '/op/settings/wh/' . $url, $data, $headers); if ($r === FALSE) { rg_log_ml('r: ' . print_r($r, TRUE)); rg_log_ml('Cannot add webhook!'); exit(1); } if (!strstr($r['body'], 'success')) { rg_log_ml('r[body]: ' . print_r($r['body'], TRUE)); rg_log('Cannot add webhook (no \'with success\' message)!'); exit(1); } rg_log_exit(); } /* * Check if a merge request hit the database * Returns the row or exits */ function rg_test_mr_info($db, $repo_id, $nr) { rg_log_enter('Check if the merge request ' . $nr . ' is in database...'); $tries = 10; while ($tries > 0) { $params = array('nr' => $nr); $sql = 'SELECT * FROM merge_requests' . ' WHERE repo_id = ' . $repo_id . ' AND id = @@nr@@'; $res = rg_sql_query_params($db, $sql, $params); $rows = rg_sql_num_rows($res); if ($rows > 0) $row = rg_sql_fetch_array($res); rg_sql_free_result($res); if ($rows > 0) break; sleep(1); $tries--; } if ($rows == 0) { rg_log('Seems the merge request did not hit the database!'); exit(1); } rg_log_exit(); return $row; } /* * Run ssh command, using a generated key */ function test_ssh($uid, $extra) { global $rg_ssh_host, $rg_ssh_port; $kn = getenv('RG_SSH_KEY'); $cmd = 'ssh -v' . ' -i keys/' . $kn . ' -p ' . $rg_ssh_port . ' -o ControlMaster=no' . ' -o ControlPath=' . __DIR__ . '/jars/ssh-' . $uid . ' rocketgit@' . $rg_ssh_host; return rg_exec($cmd . ' ' . $extra, '', FALSE, FALSE, FALSE); } /* * Wait for a value in cache */ function test_wait_cache($key) { for ($i = 0; $i < 50; $i++) { rg_cache_core_unset($key); $r = rg_cache_get($key); if ($r !== FALSE) break; sleep(1); } if ($r === FALSE) { rg_log('Could not obtain a value from cache for key [' . $key . ']!'); exit(1); } return $r; }