List of commits:
Subject Hash Author Date (UTC)
Lots of changes b8164d9e1e263eb4db75e32430f0753b63d0028e Catalin(ux) M. BOIE 2020-06-04 07:14:35
Lots of small fixes and functional tests ad2c8f4ce214896cb5984031dbd916467878ccfd Catalin(ux) M. BOIE 2020-05-16 09:30:47
Lots of things, mostly worker fixes 8768227306ef89ecc51d392cf986e75a7044dde4 Catalin(ux) M. BOIE 2020-04-10 15:27:11
Added functional test for HTTP 304 code 93205ec14d1073c434360abf7ea525a75407b1ab Catalin(ux) M. BOIE 2020-04-02 14:05:49
Lots of changes all over the place 3ddbd9e686f514eed1e715d7702a910ca3f8b22c Catalin(ux) M. BOIE 2020-04-01 07:17:57
More tests updates d5d45ace725f6ab336998a328136a2f7f9474df1 Catalin(ux) M. BOIE 2020-04-01 05:30:54
Lots of tests updates 183c4af52e56ae4e4fd74a35e2b17ac79952aec6 Catalin(ux) M. BOIE 2020-03-20 16:10:33
Improved a little bit the mail reporting for admin 576f96d554b1e273391ac54404bf5f885325e5e8 Catalin(ux) M. BOIE 2020-03-03 19:25:17
Worker and builder big changes 90f596e4fd8fa291b1da831bce609b486c7a5875 Catalin(ux) M. BOIE 2020-01-06 13:31:20
Samples update (switch to systemd services for builder and worker) 8bfde1fb79778d024350bf5d75f076fb5e178512 Catalin(ux) M. BOIE 2020-01-06 12:50:21
builder: show queue in the web page 6cab7820b0bd2622afb77391a9e9515e0e837eef Catalin(ux) M. BOIE 2020-01-06 12:49:26
totp: Allow also years for 'val' command d666df0cec948f938469b9eb12a1b981cb41cfa1 Catalin(ux) M. BOIE 2020-01-04 14:39:33
worker: change git clone parameters because we could not clone 8eb2727ac17e12e148f39c72e1f4bd1e31319b33 Catalin(ux) M. BOIE 2019-12-19 03:34:26
Added a TODO for worker 492fb4546829f53adacd74c4647c3634f7c37065 Catalin(ux) M. BOIE 2019-12-18 22:23:12
worker improvements 4387b00291b5848aa08c303f9d62a126a6806a35 Catalin(ux) M. BOIE 2019-12-18 22:17:23
.spec: require tidy for building the tests c0deab2ce24388c91d2bc2e96338a260c9657dd6 Catalin(ux) M. BOIE 2019-12-18 22:15:29
nginx configuration update 015c9404229f2ff7fb91cc57ab21289f01878334 Catalin(ux) M. BOIE 2019-12-18 21:55:13
Added Business model to comparison c62d466580aca0ff3371f3ba369959c7ef7631d0 Catalin(ux) M. BOIE 2019-11-21 20:44:16
CSS small correction ded9ef6bce5bebfa815bc7ae5733bc8e0810af3b Catalin(ux) M. BOIE 2019-11-21 18:20:41
Added LDAP/qrencode to features/thanks pages d269d59787f61045f5831c6985899c28da08ebeb Catalin(ux) M. BOIE 2019-11-21 18:20:22
Commit b8164d9e1e263eb4db75e32430f0753b63d0028e - Lots of changes
Author: Catalin(ux) M. BOIE
Author date (UTC): 2020-06-04 07:14
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2020-06-04 07:14
Parent(s): ad2c8f4ce214896cb5984031dbd916467878ccfd
Signer:
Signing key:
Signing status: N
Tree: 5e908e2b79ba3c9f38704ccaff242170fecc803f
File Lines added Lines deleted
TODO 15 1
hooks/update 3 3
inc/admin.inc.php 120 1
inc/api.inc.php 27 12
inc/graph.inc.php 204 40
inc/init.inc.php 0 2
inc/mail.inc.php 4 1
inc/mr.inc.php 9 2
inc/repo.inc.php 49 23
inc/sql.inc.php 1 1
inc/ssh.inc.php 72 40
inc/stats.inc.php 110 2
inc/stats/stats.php 30 10
inc/struct.inc.php 96 37
inc/user.inc.php 30 23
inc/util.inc.php 16 1
inc/workers.inc.php 152 0
root/index.php 124 104
root/themes/default/admin/ldap/list/footer.html 1 0
root/themes/default/admin/ldap/list/header.html 3 0
root/themes/default/admin/plans/list/footer.html 1 0
root/themes/default/admin/plans/list/header.html 3 0
root/themes/default/builder/cmds/footer.html 1 0
root/themes/default/builder/cmds/header.html 3 0
root/themes/default/builder/queue/footer.html 1 0
root/themes/default/builder/queue/header.html 3 0
root/themes/default/doc/api.html 211 165
root/themes/default/hints/repo/clone_owner.html 0 2
root/themes/default/hints/repo/edit_repo_path_rights.html 4 0
root/themes/default/hints/repo/edit_repo_refs_rights.html 4 0
root/themes/default/main.css 10 2
root/themes/default/repo/bug/list/footer.html 1 0
root/themes/default/repo/bug/list/header.html 3 0
root/themes/default/repo/cl/list/footer.html 1 0
root/themes/default/repo/cl/list/header.html 3 0
root/themes/default/repo/fstat/footer.html 1 0
root/themes/default/repo/fstat/header.html 4 0
root/themes/default/repo/history/footer.html 1 0
root/themes/default/repo/history/header.html 4 0
root/themes/default/repo/list/footer.html 1 0
root/themes/default/repo/list/header.html 4 0
root/themes/default/repo/log/footer.html 1 0
root/themes/default/repo/log/header.html 3 0
root/themes/default/repo/mr/list/footer.html 1 0
root/themes/default/repo/mr/list/header.html 3 0
root/themes/default/repo/stats/authors/footer.html 1 0
root/themes/default/repo/stats/authors/header.html 4 0
root/themes/default/repo/tree/footer.html 1 0
root/themes/default/repo/tree/header.html 4 0
root/themes/default/stats/stats.html 2 0
root/themes/default/user/keys/list/footer.html 1 0
root/themes/default/user/keys/list/header.html 3 0
root/themes/default/user/repo/rights/list_repo/footer.html 1 0
root/themes/default/user/repo/rights/list_repo/header.html 4 0
root/themes/default/user/repo/rights/list_repo_path/footer.html 1 0
root/themes/default/user/repo/rights/list_repo_path/header.html 4 0
root/themes/default/user/repo/rights/list_repo_refs/footer.html 1 0
root/themes/default/user/repo/rights/list_repo_refs/header.html 4 0
root/themes/default/user/settings/apikeys/hints.html 1 1
root/themes/default/user/settings/apikeys/list/footer.html 1 0
root/themes/default/user/settings/apikeys/list/header.html 3 0
root/themes/default/user/settings/totp/list/footer.html 1 0
root/themes/default/user/settings/totp/list/header.html 4 0
root/themes/default/user/settings/totp/sc/list/footer.html 1 0
root/themes/default/user/settings/totp/sc/list/header.html 4 0
root/themes/default/user/settings/wh/list/footer.html 1 0
root/themes/default/user/settings/wh/list/header.html 4 0
root/themes/default/user/settings/wh/plugins_list/footer.html 1 0
root/themes/default/user/settings/wh/plugins_list/header.html 4 0
root/themes/default/user/settings/workers/list/footer.html 1 0
root/themes/default/user/settings/workers/list/header.html 7 4
root/themes/default/user/settings/workers/list/line.html 4 5
scripts/builder.TODO 1 1
scripts/builder.php 4 2
scripts/remote.php 74 34
scripts/worker.TODO 5 5
scripts/worker.php 7 2
tests/_run_tests.sh 1 1
tests/common.php 1 1
tests/http.inc.php 62 12
tests/http_304.php 1 11
tests/http_api.php 142 0
tools/rg_authorize 1 1
File TODO changed (mode: 100644) (index 492655b..8942b4d)
7 7 [ ] [ ]
8 8
9 9 == Now == == Now ==
10 [ ] worker: table looks bad with the graphics embedded!
11 Have a link? And show some small statistics (avg_load/jobs/usage for today)?
10 12 [ ] [ ]
11 13
12 14 == BEFORE NEXT RELEASE == == BEFORE NEXT RELEASE ==
13 [ ] We may need to replace core.quotePath=false with -z! '"' is still quoted!
15 [ ] Workers: we should tell the user if a worker is connected or not when
16 loading the "List" page.
17 [ ] When changing the e-mail address we must invalidate/resend the confirmation.
18 [ ] Should I use ak_update_use or 'conns' will be enough?
19 In 'conns' I do not store the id of the key, for example.
20 [ ] Add the number of bytes in/out in 'conns' table, also because of charging
21 for private repos (packages download).
22 [ ] wh: allow saving artifacts to samba/nfs/ceph/webdav etc.
23 [ ] wh: allow to simulate another project push (call again all train
24 of hooks for another project). Think about 2 dependent programs.
25 [ ] wh: time based triggers.
26 [ ] wh: API based triggers.
27 [ ] C security scanner: flawfinder
14 28 [ ] wh: we need a tag for URL to the application to complement ##commit_url##. [ ] wh: we need a tag for URL to the application to complement ##commit_url##.
15 29 [ ] wh: ##tag## - add one for the site URL. ##site##? [ ] wh: ##tag## - add one for the site URL. ##site##?
16 30 [ ] 2fa: warn user when she/he is short on scratch codes. [ ] 2fa: warn user when she/he is short on scratch codes.
File hooks/update changed (mode: 100755) (index 67697ad..4f71c9a)
... ... rg_prof_start("hook-update");
33 33
34 34 rg_log_set_file($rg_log_dir . "/hook_update.log"); rg_log_set_file($rg_log_dir . "/hook_update.log");
35 35
36 rg_sql_app("rg-hook-update");
37 $db = rg_sql_open($rg_sql);
38
39 36 $a = $rg; $a = $rg;
40 37 $a['login_uid'] = sprintf("%u", getenv("ROCKETGIT_LOGIN_UID")); $a['login_uid'] = sprintf("%u", getenv("ROCKETGIT_LOGIN_UID"));
41 38 $a['login_url'] = getenv('ROCKETGIT_LOGIN_URL'); $a['login_url'] = getenv('ROCKETGIT_LOGIN_URL');
 
... ... $a['log_sid'] = $rg_log_sid;
51 48 rg_log("Start a=" . rg_array2string($a)); rg_log("Start a=" . rg_array2string($a));
52 49 rg_log("_SERVER: " . rg_array2string($_SERVER)); rg_log("_SERVER: " . rg_array2string($_SERVER));
53 50
51 rg_sql_app('rg-hook-update-' . $a['log_sid']);
52 $db = rg_sql_open($rg_sql);
53
54 54 if ($a['login_uid'] > 0) { if ($a['login_uid'] > 0) {
55 55 $a['ui'] = rg_user_info($db, $a['login_uid'], '', ''); $a['ui'] = rg_user_info($db, $a['login_uid'], '', '');
56 56 if ($a['ui']['ok'] != 1) if ($a['ui']['ok'] != 1)
File inc/admin.inc.php changed (mode: 100644) (index dbc895b..f8eb44b)
1 1 <?php <?php
2 2 $INC = isset($INC) ? $INC : dirname(__FILE__); $INC = isset($INC) ? $INC : dirname(__FILE__);
3 3 require_once($INC . "/user.inc.php"); require_once($INC . "/user.inc.php");
4 require_once($INC . "/repo.inc.php");
4 5 require_once($INC . "/workers.inc.php"); require_once($INC . "/workers.inc.php");
5 6
6 7 /* /*
 
... ... function rg_init($db, $rg)
269 270 return $ret; return $ret;
270 271 } }
271 272
273 function rg_admin_report_order_desc($a, $b)
274 {
275 if ($a == $b)
276 return 0;
277
278 if ($a < $b)
279 return 1;
280
281 return -1;
282 }
283
284 /*
285 * Generate reports from 'conns' table
286 */
287 function rg_admin_report_conns($db, $from, $to)
288 {
289 $ret = array('ok' => 0);
290 while (1) {
291 // Yesterday
292 $yesterday_text = '';
293 $y_start = gmmktime(0, 0, 0, gmdate('m'), gmdate('d') - 1, gmdate('Y'));
294 $y_end = gmmktime(0, 0, 0, gmdate('m'), gmdate('d'), gmdate('Y')) - 1;
295 $sql = 'SELECT * FROM conns'
296 . ' WHERE itime >= ' . $y_start
297 . ' AND itime <= ' . $y_end;
298 $res = rg_sql_query($db, $sql);
299 if ($res === FALSE) {
300 $ret['errmsg'] = rg_sql_error();
301 break;
302 }
303
304 $list = array('type', 'uid', 'repo_id', 'url', 'cmd', 'referer', 'ip');
305 foreach ($list as $k)
306 $ret[$k] = array();
307 $ret['count'] = 0;
308 $ret['sum_elap'] = 0;
309 while (($row = rg_sql_fetch_array($res))) {
310 $ret['count']++;
311 $ret['sum_elap'] += $row['elap'];
312
313 foreach ($list as $k) {
314 $v = $row[$k];
315 if (strcmp($k, 'uid') == 0) {
316 if ($v == 0)
317 continue;
318 } else if (strcmp($k, 'repo_id') == 0) {
319 if ($v == 0)
320 continue;
321 $v = $row['uid'] . '/' . $row[$k];
322 }
323
324 if (!isset($ret[$k][$v]))
325 $ret[$k][$v] = 1;
326 else
327 $ret[$k][$v]++;
328 }
329 }
330 rg_sql_free_result($res);
331
332 if ($ret['count'] == 0) {
333 $ret['ok'] = 1;
334 break;
335 }
336
337 $ret['avg_elap'] = intval($ret['sum_elap'] / $ret['count']);
338 unset($ret['sum_elap']);
339
340 foreach ($list as $k) {
341 uasort($ret[$k], 'rg_admin_report_order_desc');
342
343 // We want statistics for all types
344 if (strcmp($k, 'type') == 0)
345 continue;
346
347 $ret[$k] = rg_array_top($ret[$k], 10);
348 }
349
350 $ret['ok'] = 1;
351 break;
352 }
353
354 return $ret;
355 }
356
272 357 /* /*
273 358 * Helper for rg_admin_report1 - suggestion report * Helper for rg_admin_report1 - suggestion report
274 359 */ */
 
... ... function rg_admin_report1($db, $rg)
351 436 'events' => 'events', 'events' => 'events',
352 437 'build_jobs' => 'build jobs', 'build_jobs' => 'build jobs',
353 438 'apikeys' => 'api keys', 'apikeys' => 'api keys',
354 'workers' => 'workers');
439 'workers' => 'workers',
440 'conns' => 'connection stats');
355 441 $total_yesterday_changes = 0; $total_yesterday_changes = 0;
356 442 $body .= "\n" . 'Yesterday' . "\t" . 'Total' . "\t" . 'Category' . "\n"; $body .= "\n" . 'Yesterday' . "\t" . 'Total' . "\t" . 'Category' . "\n";
357 443 foreach ($list as $table => $text) { foreach ($list as $table => $text) {
 
... ... function rg_admin_report1($db, $rg)
364 450 $res = rg_sql_query($db, $sql); $res = rg_sql_query($db, $sql);
365 451 if ($res === FALSE) { if ($res === FALSE) {
366 452 $yesterday = "ERR"; $yesterday = "ERR";
453 $g[$table]['yesterday'] = $yesterday;
367 454 } else { } else {
368 455 $row = rg_sql_fetch_array($res); $row = rg_sql_fetch_array($res);
369 456 $yesterday = $row['count']; $yesterday = $row['count'];
 
... ... function rg_admin_report1($db, $rg)
427 514 $sug = rg_admin_report1_suggestions($db, $y_start, $y_end); $sug = rg_admin_report1_suggestions($db, $y_start, $y_end);
428 515 $body .= "\n" . $sug; $body .= "\n" . $sug;
429 516
517 $body .= "\n\n";
518 $conns = rg_admin_report_conns($db, $y_start, $y_end);
519 if ($conns['ok'] != 1) {
520 $body .= 'Cannot generate conns report: ' . $conns['errmsg'] . '!' . "\n";
521 } else {
522 unset($conns['ok']);
523
524 $body .= 'Number of conns entries: ' . $conns['count'] . "\n";
525 unset($conns['count']);
526
527 $body .= 'Average elap: ' . $conns['avg_elap'] . 'ms' . "\n";
528 unset($conns['avg_elap']);
529
530 rg_log_ml('DEBUG: conns: ' . print_r($conns, TRUE));
531 foreach ($conns as $t => $i) {
532 $body .= 'Top for \'' . $t . '\':' . "\n";
533 foreach ($i as $k => $v) {
534 if (strcmp($t, 'repo_id') == 0) {
535 $q = explode('/', $k);
536 $k = rg_repo_nice($db, $q[1]) . ' (user ' . rg_user_nice($db, $q[0]) . ')';
537 } else if (strcmp($t, 'uid') == 0) {
538 $k = rg_user_nice($db, $k) . ' (' . $k . ')';
539 }
540
541 $k2 = !empty($k) ? $k : 'EMPTY';
542 $body .= ' ' . $v . ' ' . $k2 . "\n";
543 }
544 $body .= "\n";
545 }
546 }
547
430 548 $rg['ui']['ignore_confirmed'] = 1; $rg['ui']['ignore_confirmed'] = 1;
431 549 $rg['ui']['email'] = $rg_admin_email; $rg['ui']['email'] = $rg_admin_email;
432 550 $rg['mail'] = array(); $rg['mail'] = array();
 
... ... function rg_admin_report1($db, $rg)
436 554 . ' [' . $total_yesterday_changes . 'c]' . ' [' . $total_yesterday_changes . 'c]'
437 555 . ' (' . $site . ')'; . ' (' . $site . ')';
438 556 $rg['mail']['body'] = $body; $rg['mail']['body'] = $body;
557 $rg['ignore_debug'] = 1;
439 558 rg_mail_template("mail/admin/report1", $rg); rg_mail_template("mail/admin/report1", $rg);
440 559 } }
441 560
File inc/api.inc.php changed (mode: 100644) (index ee5a63b..60fac49)
... ... require_once($INC . "/watch.inc.php");
12 12 /* /*
13 13 * Main entry point * Main entry point
14 14 */ */
15 function rg_api($db, $a)
15 function rg_api($db, &$a, $json)
16 16 { {
17 17 rg_prof_start('api'); rg_prof_start('api');
18 rg_log_enter('api: a=' . rg_array2string($a));
18 rg_log_enter('api: json=' . rg_array2string($json));
19 19
20 $ret = array();
20 21 while (1) { while (1) {
21 $a['cui'] = rg_user_info($db, $a['connect_uid'], '', '');
22 if ($a['cui']['exists'] != 1) {
23 $ret = array('error' => 'internal error');
22 if (!isset($json['cmd'])) {
23 $ret['error'] = '\'cmd\' parameter not present';
24 24 break; break;
25 25 } }
26 26
27 if (strncmp($a['cmd'], 'user', 4) == 0) {
28 $ret = rg_user_api($db, $a);
27 $ret['cmd'] = $json['cmd'];
28
29 if (isset($json['opaque']))
30 $ret['opaque'] = $json['opaque'];
31
32 // Needed for logging
33 rg_stats_conns_set('cmd', $json['cmd']);
34
35 if (isset($json['user'])) {
36 $a['target_ui'] = rg_user_info($db, 0, $json['user'], '');
37 } else if (isset($json['uid'])) {
38 $a['target_ui'] = rg_user_info($db, $json['uid'], '', '');
39 } else {
40 $a['target_ui'] = $a['login_ui'];
41 }
42
43 rg_stats_conns_set('uid', $a['target_ui']['uid']);
44
45 if (strncmp($json['cmd'], 'user', 4) == 0) {
46 $ret = array_merge($ret, rg_user_api($db, $a, $json));
29 47 break; break;
30 48 } }
31 49
32 if (strncmp($a['cmd'], 'repo', 4) == 0) {
33 $ret = rg_repo_api($db, $a);
50 if (strncmp($json['cmd'], 'repo', 4) == 0) {
51 $ret = array_merge($ret, rg_repo_api($db, $a, $json));
34 52 break; break;
35 53 } }
36 54
 
... ... function rg_api($db, $a)
38 56 break; break;
39 57 } }
40 58
41 $ret = json_encode($ret, JSON_PRETTY_PRINT) . "\n";
42
43 59 rg_log_exit(); rg_log_exit();
44 60 rg_prof_end('api'); rg_prof_end('api');
45 61 return $ret; return $ret;
46 62 } }
47 63
48 ?>
File inc/graph.inc.php changed (mode: 100644) (index a6be63d..6911cc6)
1 1 <?php <?php
2 2
3 $rg_graph_error = '';
4
5 function rg_graph_set_error($str)
6 {
7 global $rg_graph_error;
8 $rg_graph_error = $str;
9 rg_log('graph_set_error: ' . $str);
10 }
11
12 function rg_graph_error()
13 {
14 global $rg_graph_error;
15 return $rg_graph_error;
16 }
17
3 18 /* /*
4 * Helper for rg_graph_data_query to position a value in the correct interval
19 * Helper TODO
5 20 */ */
6 function rg_graph_pos($db, $itime, $unit)
21 function rg_graph_unit2info($unit)
7 22 { {
8 //rg_log_enter('graph_pos itime=' . $itime . ' unit=' . $unit);
23 $ret = array();
9 24
10 $h = gmdate('H', $itime);
11 $i = gmdate('i', $itime);
25 switch ($unit) {
26 case 'minute':
27 $ret['time_format'] = 'H';
28 break;
29
30 case 'hour':
31 $ret['time_format'] = 'Y-m-d';
32 break;
33
34 case 'day':
35 $ret['time_format'] = 'Y-m';
36 break;
37
38 case 'month':
39 $ret['time_format'] = 'Y';
40 break;
41
42 case 'year':
43 $ret['time_format'] = 'Y';
44 break;
45
46 default:
47 $ret['time_format'] = 'Y-m-d';
48 break;
49 }
50
51 return $ret;
52 }
53
54 /*
55 * Helper for rg_graph_data_query to position a value in the correct interval
56 */
57 function rg_graph_pos($itime, $unit)
58 {
12 59 $y = gmdate('Y', $itime); $y = gmdate('Y', $itime);
13 60 $m = gmdate('m', $itime); $m = gmdate('m', $itime);
14 61 $d = gmdate('d', $itime); $d = gmdate('d', $itime);
62 $h = gmdate('H', $itime);
63 $i = gmdate('i', $itime);
15 64
16 65 switch ($unit) { switch ($unit) {
17 66 case 'minute': case 'minute':
18 $n = gmmktime($h, $i, 0, $m, $d, $y);
19 $f = gmmktime($h, $i + 1, 0, $m, $d, $y);
67 $pos = gmmktime($h, $i, 0, $m, $d, $y);
68 $next = gmmktime($h, $i + 1, 0, $m, $d, $y);
69 $mark = gmmktime($h, 0, 0, $m, $d, $y);
20 70 break; break;
21 71
22 72 case 'hour': case 'hour':
23 $n = gmmktime($h, 0, 0, $m, $d, $y);
24 $f = gmmktime($h + 1, 0, 0, $m, $d, $y);
73 $pos = gmmktime($h, 0, 0, $m, $d, $y);
74 $next = gmmktime($h + 1, 0, 0, $m, $d, $y);
75 $mark = gmmktime(0, 0, 0, $m, $d, $y);
25 76 break; break;
26 77
27 78 case 'day': case 'day':
28 $n = gmmktime(0, 0, 0, $m, $d, $y);
29 $f = gmmktime(0, 0, 0, $m, $d + 1, $y);
79 $pos = gmmktime(0, 0, 0, $m, $d, $y);
80 $next = gmmktime(0, 0, 0, $m, $d + 1, $y);
81 $mark = gmmktime(0, 0, 0, $m, 1, $y);
30 82 break; break;
31 83
32 84 case 'month': case 'month':
33 $n = gmmktime(0, 0, 0, $m, 0, $y);
34 $f = gmmktime(0, 0, 0, $m + 1, 0, $y);
85 $pos = gmmktime(0, 0, 0, $m, 0, $y);
86 $next = gmmktime(0, 0, 0, $m + 1, 0, $y);
87 $mark = gmmktime(0, 0, 0, 1, 1, $y);
35 88 break; break;
36 89
37 90 case 'year': case 'year':
38 $n = gmmktime(0, 0, 0, 0, 0, $y);
39 $f = gmmktime(0, 0, 0, 0, 0, $y + 1);
91 $pos = gmmktime(0, 0, 0, 0, 0, $y);
92 $next = gmmktime(0, 0, 0, 0, 0, $y + 1);
93 $mark = 0;
40 94 break; break;
41 95
42 96 default: default:
43 rg_user_set_error('invalid unit ' . $unit);
44 $n = FALSE;
97 rg_graph_set_error('invalid unit ' . $unit);
98 $pos = FALSE;
45 99 } }
46 100
47 //rg_log_exit();
48 return $n === FALSE ? FALSE : array('pos' => $n, 'next' => $f);
101 if ($pos === FALSE)
102 return FALSE;
103
104 $ret = array('pos' => $pos, 'next' => $next);
105
106 if ($mark == $pos)
107 $ret['mark'] = $pos;
108
109 return $ret;
49 110 } }
50 111
51 112 /* /*
52 113 * Loads data for graphs (helper) * Loads data for graphs (helper)
53 114 * TODO: what about DST? * TODO: what about DST?
54 115 * @mode - 'avg' if we need averages per bar, 'sum' for sum * @mode - 'avg' if we need averages per bar, 'sum' for sum
116 * @decode_func - optional, a function to decode the data loaded from the database
55 117 */ */
56 function rg_graph_query($db, $start, $end, $unit, $mode, $query, $params)
118 function rg_graph_query($db, $start, $end, $unit, $mode, $query, $params,
119 $decode_func)
57 120 { {
58 121 rg_log_enter('graph_query start=' . $start . ' end=' . $end rg_log_enter('graph_query start=' . $start . ' end=' . $end
59 122 . ' unit=' . $unit . ' mode=' . $mode . ' query=' . $query); . ' unit=' . $unit . ' mode=' . $mode . ' query=' . $query);
60 123
61 124 $ret = FALSE; $ret = FALSE;
125 $error = FALSE;
62 126 while (1) { while (1) {
63 127 $res = rg_sql_query_params($db, $query, $params); $res = rg_sql_query_params($db, $query, $params);
64 128 if ($res === FALSE) { if ($res === FALSE) {
 
... ... function rg_graph_query($db, $start, $end, $unit, $mode, $query, $params)
66 130 break; break;
67 131 } }
68 132
69 $ret = array('list' => array(), 'min' => -1, 'max' => 0);
133 $ret = array(
134 'list' => array(),
135 'markers' => array(),
136 'min' => 0,
137 'max' => 0,
138 'unit' => $unit
139 );
140
141 $x = rg_graph_pos(time(), $unit);
142 if ($x !== FALSE)
143 $ret['now_pos'] = $x['pos'];
144
70 145 $counts = array(); $counts = array();
71 146 while (($row = rg_sql_fetch_array($res))) { while (($row = rg_sql_fetch_array($res))) {
72 $p = rg_graph_pos($db, $row['itime'], $unit);
147 $p = rg_graph_pos($row['itime'], $unit);
73 148 if ($p === FALSE) if ($p === FALSE)
74 149 break; break;
75 150
151 if (!empty($decode_func)) {
152 $_x = $decode_func($row['value']);
153 if ($_x === FALSE) {
154 $error = TRUE;
155 break;
156 }
157
158 $row['value'] = $_x;
159 }
160
76 161 $pos = $p['pos']; $pos = $p['pos'];
77 162 if (!isset($ret['list'][$pos])) if (!isset($ret['list'][$pos]))
78 163 $ret['list'][$pos] = $row['value']; $ret['list'][$pos] = $row['value'];
 
... ... function rg_graph_query($db, $start, $end, $unit, $mode, $query, $params)
85 170 $counts[$pos]++; $counts[$pos]++;
86 171 } }
87 172 rg_sql_free_result($res); rg_sql_free_result($res);
173 if ($error)
174 break;
88 175
89 176 $pos = $start; $pos = $start;
90 177 while ($pos < $end) { while ($pos < $end) {
91 $p = rg_graph_pos($db, $pos, $unit);
178 $p = rg_graph_pos($pos, $unit);
92 179 if ($p === FALSE) { if ($p === FALSE) {
93 180 $ret = FALSE; $ret = FALSE;
94 181 break; break;
 
... ... function rg_graph_query($db, $start, $end, $unit, $mode, $query, $params)
97 184 $pos = $p['pos']; $pos = $p['pos'];
98 185 $next = $p['next']; $next = $p['next'];
99 186
187 if (isset($p['mark'])) {
188 $mark = $p['mark'];
189 $ret['markers'][$mark] = 1;
190 }
191
100 192 if (!isset($ret['list'][$pos])) { if (!isset($ret['list'][$pos])) {
101 193 $ret['list'][$pos] = 0; $ret['list'][$pos] = 0;
102 194 } else if (strcmp($mode, 'avg') == 0) { } else if (strcmp($mode, 'avg') == 0) {
103 195 $ret['list'][$pos] = intval($ret['list'][$pos] / $counts[$pos]); $ret['list'][$pos] = intval($ret['list'][$pos] / $counts[$pos]);
104 196 } }
105 197
106 if (($ret['min'] == -1) || ($ret['min'] > $ret['list'][$pos]))
198 if ($ret['min'] > $ret['list'][$pos])
107 199 $ret['min'] = $ret['list'][$pos]; $ret['min'] = $ret['list'][$pos];
108 200 if ($ret['max'] < $ret['list'][$pos]) if ($ret['max'] < $ret['list'][$pos])
109 201 $ret['max'] = $ret['list'][$pos]; $ret['max'] = $ret['list'][$pos];
110 202
203 $ret['last_data_pos'] = $pos;
111 204 $pos = $next; $pos = $next;
112 205 } }
206
207 // Insert a fake entry to be able to show last time marker
208 $ret['list'][$end + 1] = 0;
209
113 210 ksort($ret['list']); ksort($ret['list']);
114 211 break; break;
115 212 } }
116 213
214 // final marker
215 $p = rg_graph_pos($end + 1, $unit);
216 if (($p !== FALSE) && isset($p['mark'])) {
217 $mark = $p['mark'];
218 $ret['markers'][$mark] = 1;
219 }
220
117 221 rg_log_exit(); rg_log_exit();
118 222 return $ret; return $ret;
119 223 } }
120 224
121 225 /* /*
122 226 * Creates a SVG graph * Creates a SVG graph
227 * TODO: user should be able to overwrite styles! Now we overwrite it.
123 228 */ */
124 229 function rg_graph($a) function rg_graph($a)
125 230 { {
231 rg_log_ml('DEBUG: a[data]: ' . print_r($a['data'], TRUE));
126 232 if (!isset($a['scale_style'])) if (!isset($a['scale_style']))
127 233 $a['scale_style'] = 'font-size: 8pt'; $a['scale_style'] = 'font-size: 8pt';
128
234 if (!isset($a['now_style']))
235 $a['now_style'] = 'fill: #999';
236 if (!isset($a['time_marker_line_style']))
237 $a['time_marker_line_style'] = 'fill: #bbb';
238 if (!isset($a['time_marker_text_style']))
239 $a['time_marker_text_style'] = 'font-color: #000';
240 if (!isset($a['footer_style']))
241 $a['footer_style'] = '';
242
243 $now = time();
129 244 $data_start_x = 10; $data_start_x = 10;
130 245 $data_start_y = 40; $data_start_y = 40;
131 246
247 // TODO: devide by 1000, 1000^2 etc.
132 248 $len = max(4, strlen(sprintf("%s", $a['data']['max']))); $len = max(4, strlen(sprintf("%s", $a['data']['max'])));
133 249 $data_start_x += $len * 8 + 3; $data_start_x += $len * 8 + 3;
134 250
 
... ... function rg_graph($a)
137 253 rg_log('DEBUG: count=' . count($a['data']['list']) . ' len=' . $len); rg_log('DEBUG: count=' . count($a['data']['list']) . ' len=' . $len);
138 254 rg_log('DEBUG: a[w]=' . $a['w']); rg_log('DEBUG: a[w]=' . $a['w']);
139 255
256 $time_date_height = 25;
140 257 $w = $data_start_x + 2 + $a['w'] + 2 + 10; $w = $data_start_x + 2 + $a['w'] + 2 + 10;
141 $h = $data_start_y + 2 + $a['h'] + 1 + 2 + 20;
258 $h = $data_start_y + 2 + $a['h'] + 1 + 2 + $time_date_height + 20;
142 259 rg_log('DEBUG: w=' . $w); rg_log('DEBUG: w=' . $w);
143 260
144 261 $ret = '<svg width="' . $w . '" height="' . $h . '"' $ret = '<svg width="' . $w . '" height="' . $h . '"'
 
... ... function rg_graph($a)
160 277 . ' style="' . $a['subtitle_style'] . '">' . ' style="' . $a['subtitle_style'] . '">'
161 278 . $a['subtitle'] . '</text>' . "\n"; . $a['subtitle'] . '</text>' . "\n";
162 279
280 // Footer left
281 $a['footer_left_style'] = $a['footer_style'] . '; text-anchor: begin';
282 $t = '1 unit = 1 ' . $a['data']['unit'];
283 $ret .= '<text x="' . ($data_start_x + 2) . '"'
284 . ' y="' . ($data_start_y + 2 + $a['h'] + 3 + 12 + $time_date_height) . '"'
285 . ' style="' . $a['footer_left_style']
286 . '">' . $t . '</text>' . "\n";
287
163 288 // Footer right // Footer right
164 $a['footer_style'] .= '; text-anchor: end';
165 $t = 'Generated at ' . gmdate('Y-m-d H:i');
289 $a['footer_right_style'] = $a['footer_style'] . '; text-anchor: end';
290 $t = 'Generated at ' . gmdate('Y-m-d H:i') . ' UTC';
166 291 $ret .= '<text x="' . ($data_start_x + 2 + $a['w'] + 2) . '"' $ret .= '<text x="' . ($data_start_x + 2 + $a['w'] + 2) . '"'
167 . ' y="' . ($data_start_y + 2 + $a['h'] + 3 + 12) . '"'
168 . ' style="' . $a['footer_style']
292 . ' y="' . ($data_start_y + 2 + $a['h'] + 3 + 12 + $time_date_height) . '"'
293 . ' style="' . $a['footer_right_style']
169 294 . '">' . $t . '</text>' . "\n"; . '">' . $t . '</text>' . "\n";
170 295
171 296 // Left scale // Left scale
 
... ... function rg_graph($a)
187 312 . ' height="' . (2 + $a['h'] + 1 + 2) . '"' . ' height="' . (2 + $a['h'] + 1 + 2) . '"'
188 313 . ' style="' . $a['data_style'] . '" />' . "\n"; . ' style="' . $a['data_style'] . '" />' . "\n";
189 314
315 // Base black line
316 $ret .= '<rect'
317 . ' x="' . ($data_start_x + 2) . '"'
318 . ' y="' . ($data_start_y + 2 + $a['h']) . '"'
319 . ' width="' . $a['w'] . '"'
320 . ' height="1"'
321 . ' style="fill: #333"'
322 . '/>' . "\n";
323
324
190 325 if ($a['data']['max'] == 0) if ($a['data']['max'] == 0)
191 326 $factor = 1; $factor = 1;
192 327 else else
193 328 $factor = $a['h'] / $a['data']['max']; $factor = $a['h'] / $a['data']['max'];
329 $unit_info = rg_graph_unit2info($a['data']['unit']);
330 $time_format = $unit_info['time_format'];
194 331 $x = $data_start_x + 2; $x = $data_start_x + 2;
332 $y_base = $data_start_y + 2;
195 333 foreach ($a['data']['list'] as $pos => $v0) { foreach ($a['data']['list'] as $pos => $v0) {
196 $v = sprintf('%u', $v0 * $factor);
334 // Time markers
335 if (isset($a['data']['markers'][$pos])) {
336 $ret .= '<rect'
337 . ' x="' . $x . '"'
338 . ' y="' . $y_base . '"'
339 . ' width="' . $a['data_line_width'] . '"'
340 . ' height="' . $a['h'] . '"'
341 . ' style="' . $a['time_marker_line_style'] . '"'
342 . '/>' . "\n";
343
344 $_x = $x + 3; $_y = $y_base + $a['h'] + 7;
345 $ret .= '<text x="' . $_x . '"'
346 . ' y="' . $_y . '"'
347 . ' style="' . $a['time_marker_text_style'] . '; text-anchor: end; font-size: 4pt" transform="rotate(-45,' . $_x . ',' . $_y . ')">'
348 . gmdate($time_format, $pos) . '</text>' . "\n";
349 }
197 350
198 $y = $data_start_y + 2 + $a['h'] - $v;
351 // 'now' marker
352 if ($pos == $a['data']['now_pos']) {
353 $ret .= '<rect'
354 . ' x="' . $x . '"'
355 . ' y="' . $y_base . '"'
356 . ' width="' . $a['data_line_width'] . '"'
357 . ' height="' . $a['h'] . '"'
358 . ' style="' . $a['now_style'] . '"'
359 . '/>' . "\n";
360
361 $ret .= '<text x="' . $x . '"'
362 . ' y="' . ($y_base + 6) . '"'
363 . ' style="' . $a['now_style'] . '; text-anchor: end; font-size: 5pt" transform="rotate(270,' . $x . ',' . $y_base . ')">'
364 . 'now</text>' . "\n";
365 }
199 366
200 // marker
201 $ret .= '<rect'
202 . ' x="' . $x . '"'
203 . ' y="' . ($data_start_y + 2 + $a['h']) . '"'
204 . ' width="' . $a['data_line_width'] . '"'
205 . ' height="1"'
206 . ' style="fill: #333"'
207 . '/>' . "\n";
367 if ($pos > $a['data']['last_data_pos'])
368 break;
208 369
209 370 // value // value
371 $v = sprintf('%u', $v0 * $factor);
372 $y = $y_base + $a['h'] - $v;
373 // TODO: data_line_style should be moved on the <g> tag!
210 374 $ret .= '<rect' $ret .= '<rect'
211 375 . ' x="' . $x . '"' . ' x="' . $x . '"'
212 376 . ' y="' . $y . '"' . ' y="' . $y . '"'
File inc/init.inc.php changed (mode: 100644) (index 3de17e3..54cc667)
3 3
4 4 require_once($INC . "/ver.php"); require_once($INC . "/ver.php");
5 5
6 $rg = array();
7
8 6 $_dt = ini_get('date.timezone'); $_dt = ini_get('date.timezone');
9 7 if (empty($_dt)) if (empty($_dt))
10 8 ini_set('date.timezone', 'UTC'); ini_set('date.timezone', 'UTC');
File inc/mail.inc.php changed (mode: 100644) (index df9a8a4..9d21244)
... ... function rg_mail_template($template, $more)
31 31
32 32 $ret = FALSE; $ret = FALSE;
33 33 while (1) { while (1) {
34 if (!isset($more['ignore_debug']))
35 $more['ignore_debug'] = 0;
36
34 37 if (!isset($more['ui']['ignore_confirmed'])) if (!isset($more['ui']['ignore_confirmed']))
35 38 $more['ui']['ignore_confirmed'] = 0; $more['ui']['ignore_confirmed'] = 0;
36 39
 
... ... function rg_mail_template($template, $more)
65 68
66 69 rg_log("CHECK: mail_template(" . $more['ui']['email'] rg_log("CHECK: mail_template(" . $more['ui']['email']
67 70 . ", $subject, $body, $header, -f $rg_admin_email"); . ", $subject, $body, $header, -f $rg_admin_email");
68 if ($more['debug'] == 1) {
71 if (($more['debug'] == 1) && ($more['ignore_debug'] == 0)) {
69 72 if (!isset($more['ui']['uid'])) if (!isset($more['ui']['uid']))
70 73 $k = $more['ui']['email']; $k = $more['ui']['email'];
71 74 else else
File inc/mr.inc.php changed (mode: 100644) (index dc0eb8c..51482c8)
... ... function rg_mr_data($db, $type, $start, $end, $unit, $mode)
372 372 $q = 'SELECT 1 AS value, itime FROM merge_requests' $q = 'SELECT 1 AS value, itime FROM merge_requests'
373 373 . ' WHERE itime >= @@start@@ AND itime <= @@end@@'; . ' WHERE itime >= @@start@@ AND itime <= @@end@@';
374 374 break; break;
375 default: return FALSE;
375
376 default:
377 rg_internal_error('invalid type');
378 return FALSE;
376 379 } }
377 380
378 return rg_graph_query($db, $start, $end, $unit, $mode, $q, $params);
381 $ret = rg_graph_query($db, $start, $end, $unit, $mode, $q, $params, '');
382 if ($ret === FALSE)
383 rg_mr_set_error(rg_graph_error());
384
385 return $ret;
379 386 } }
380 387
381 388 /* /*
File inc/repo.inc.php changed (mode: 100644) (index bc580ce..783f9d6)
... ... function rg_repo_cosmetic($db, &$row)
144 144 $row['master_name'] = '-'; $row['master_name'] = '-';
145 145 if ($row['master'] > 0) { if ($row['master'] > 0) {
146 146 $_mi = rg_repo_info($db, $row['master'], 0, ''); $_mi = rg_repo_info($db, $row['master'], 0, '');
147 if ($_mi['exists'] = 1)
147 if ($_mi['exists'] == 1)
148 148 $row['master_name'] = $_mi['name']; $row['master_name'] = $_mi['name'];
149 149 } }
150 150
 
... ... function rg_repo_data($db, $type, $start, $end, $unit, $mode)
1588 1588 $q = 'SELECT 1 AS value, itime FROM repo_history' $q = 'SELECT 1 AS value, itime FROM repo_history'
1589 1589 . ' WHERE itime >= @@start@@ AND itime <= @@end@@'; . ' WHERE itime >= @@start@@ AND itime <= @@end@@';
1590 1590 break; break;
1591 default: return FALSE;
1591 default:
1592 rg_internal_error('invalid type');
1593 return FALSE;
1592 1594 } }
1593 1595
1594 return rg_graph_query($db, $start, $end, $unit, $mode, $q, $params);
1596 $ret = rg_graph_query($db, $start, $end, $unit, $mode, $q, $params, '');
1597 if ($ret === FALSE)
1598 rg_repo_set_error(rg_graph_error());
1599
1600 return $ret;
1595 1601 } }
1596 1602
1597 1603 /* /*
 
... ... function rg_repo_admin_delete($db, $rg)
1835 1841 return $ret; return $ret;
1836 1842 } }
1837 1843
1844 /*
1845 * Easy obtain repo name
1846 */
1847 function rg_repo_nice($db, $repo_id)
1848 {
1849 $ri = rg_repo_info($db, $repo_id, 0, '');
1850 if ($ri['exists'] == 1)
1851 return $ri['name'];
1852
1853 return 'n/a';
1854 }
1855
1838 1856 /* /*
1839 1857 * High level function creating/editing a repo * High level function creating/editing a repo
1840 1858 */ */
 
... ... function rg_repo_commit_labels_html($db, $repo_id, $commit)
2311 2329 /* /*
2312 2330 * API dispatch function * API dispatch function
2313 2331 */ */
2314 function rg_repo_api($db, $a)
2332 function rg_repo_api($db, $a, $json)
2315 2333 { {
2316 2334 rg_prof_start('repo_api'); rg_prof_start('repo_api');
2317 2335 rg_log_enter('repo_api'); rg_log_enter('repo_api');
2318 2336
2319 $cmd = $a['cmd'];
2337 $cmd = $json['cmd'];
2320 2338
2321 2339 $ret = array(); $ret = array();
2322 2340 while (1) { while (1) {
2323 if (isset($a['name'])) {
2324 $ri = rg_repo_info($db, 0, $a['connect_uid'],
2325 $a['name']);
2326 } else if (isset($a['repo_id'])) {
2327 $repo_id = intval($a['repo_id']);
2341 if (isset($json['repo'])) {
2342 $ri = rg_repo_info($db, 0, $a['target_ui']['uid'],
2343 $json['repo']);
2344 } else if (isset($json['repo_id'])) {
2345 $repo_id = intval($json['repo_id']);
2328 2346 $ri = rg_repo_info($db, $repo_id, '', ''); $ri = rg_repo_info($db, $repo_id, '', '');
2329 2347 } else { } else {
2330 2348 $ri = FALSE; $ri = FALSE;
2331 2349 } }
2332 2350
2333 2351 if (strcmp($cmd, 'repo_list') == 0) { if (strcmp($cmd, 'repo_list') == 0) {
2334 $params = array('uid' => $a['cui']['uid']);
2352 $params = array('uid' => $a['target_ui']['uid']);
2335 2353 $sql = 'SELECT name FROM repos' $sql = 'SELECT name FROM repos'
2336 2354 . ' WHERE uid = @@uid@@'; . ' WHERE uid = @@uid@@';
2337 2355 $res = rg_sql_query_params($db, $sql, $params); $res = rg_sql_query_params($db, $sql, $params);
 
... ... function rg_repo_api($db, $a)
2347 2365 break; break;
2348 2366 } }
2349 2367
2350 // From this point below, we have a repo
2351
2352 2368 if ($ri === FALSE) { if ($ri === FALSE) {
2353 2369 $ret['error'] = 'no repo_id=/name= specified'; $ret['error'] = 'no repo_id=/name= specified';
2354 2370 break; break;
 
... ... function rg_repo_api($db, $a)
2359 2375 break; break;
2360 2376 } }
2361 2377
2378 // From this point below, we have a repo
2379 rg_stats_conns_set('repo_id', $ri['repo_id']);
2380
2362 2381 $x = array(); $x = array();
2363 2382 $x['obj_id'] = $ri['repo_id']; $x['obj_id'] = $ri['repo_id'];
2364 2383 $x['type'] = 'repo'; $x['type'] = 'repo';
2365 2384 $x['owner'] = $ri['uid']; $x['owner'] = $ri['uid'];
2366 $x['uid'] = $a['cui']['uid'];
2367 $x['username'] = $a['cui']['username'];
2385 $x['uid'] = $a['login_ui']['uid'];
2386 $x['username'] = $a['login_ui']['username'];
2368 2387 $x['needed_rights'] = 'A'; // A = Access repo; E = create/edit $x['needed_rights'] = 'A'; // A = Access repo; E = create/edit
2369 2388 $x['ip'] = $a['ip']; $x['ip'] = $a['ip'];
2370 2389 $x['misc'] = ''; $x['misc'] = '';
 
... ... function rg_repo_api($db, $a)
2379 2398 break; break;
2380 2399 } }
2381 2400
2382 if (strcmp($cmd, 'repo_pr_list') == 0) {
2401 if ((strcmp($cmd, 'repo_pr_list') == 0)
2402 || (strcmp($cmd, 'repo_mr_list') == 0)) {
2383 2403 if (rg_rights_allow($db, $x) !== TRUE) { if (rg_rights_allow($db, $x) !== TRUE) {
2384 2404 $ret['error'] = 'invalid user or no rights'; $ret['error'] = 'invalid user or no rights';
2385 2405 break; break;
2386 2406 } }
2387 2407
2408 $ret['repo_id'] = $ri['repo_id'];
2409
2388 2410 $params = array('repo_id' => $ri['repo_id']); $params = array('repo_id' => $ri['repo_id']);
2389 2411 $sql = 'SELECT * FROM merge_requests' $sql = 'SELECT * FROM merge_requests'
2390 2412 . ' WHERE repo_id = @@repo_id@@'; . ' WHERE repo_id = @@repo_id@@';
 
... ... function rg_repo_api($db, $a)
2393 2415 $ret['error'] = 'internal error'; $ret['error'] = 'internal error';
2394 2416 break; break;
2395 2417 } }
2396 $ret = array();
2418 $ret['list'] = array();
2397 2419 while (($row = rg_sql_fetch_array($res))) { while (($row = rg_sql_fetch_array($res))) {
2398 $ret[] = $row;
2420 unset($row['repo_id']);
2421 $ret['list'][] = $row;
2399 2422 } }
2400 2423 rg_sql_free_result($res); rg_sql_free_result($res);
2401 2424 break; break;
 
... ... function rg_repo_api($db, $a)
2409 2432 break; break;
2410 2433 } }
2411 2434
2435 $ret['repo_id'] = $ri['repo_id'];
2436
2412 2437 $params = array('repo_id' => $ri['repo_id']); $params = array('repo_id' => $ri['repo_id']);
2413 2438 $sql = 'SELECT bug_id FROM bugs' $sql = 'SELECT bug_id FROM bugs'
2414 2439 . ' WHERE repo_id = @@repo_id@@'; . ' WHERE repo_id = @@repo_id@@';
 
... ... function rg_repo_api($db, $a)
2417 2442 $ret['error'] = 'internal error'; $ret['error'] = 'internal error';
2418 2443 break; break;
2419 2444 } }
2420 $ret = array();
2445 $ret['list'] = array();
2421 2446 while (($row = rg_sql_fetch_array($res))) { while (($row = rg_sql_fetch_array($res))) {
2422 $ret[] = $row['bug_id'];
2447 $ret['list'][] = $row['bug_id'];
2423 2448 } }
2424 2449 rg_sql_free_result($res); rg_sql_free_result($res);
2425 2450 break; break;
2426 2451 } }
2427 2452
2428 2453 // TODO: for bugs, we do layer violation here! // TODO: for bugs, we do layer violation here!
2454 // Move this into bug.inc.php and register a function?
2429 2455 if (strcmp($cmd, 'repo_bug_info') == 0) { if (strcmp($cmd, 'repo_bug_info') == 0) {
2430 if (!isset($a['bug_id'])) {
2456 if (!isset($json['bug_id'])) {
2431 2457 $ret['error'] = 'bug_id= para not specified'; $ret['error'] = 'bug_id= para not specified';
2432 2458 break; break;
2433 2459 } }
2434 $bug_id = intval($a['bug_id']);
2460 $bug_id = intval($json['bug_id']);
2435 2461
2436 2462 $y = $x; $y = $x;
2437 2463 $y['needed_rights'] = 'a'; // a = Access bug repo $y['needed_rights'] = 'a'; // a = Access bug repo
 
... ... function rg_repo_api($db, $a)
2446 2472 break; break;
2447 2473 } }
2448 2474
2449 $ret = $bi;
2475 $ret = array_merge($ret, $bi);
2450 2476 break; break;
2451 2477 } }
2452 2478
File inc/sql.inc.php changed (mode: 100644) (index 8c0faeb..0df57c1)
... ... function rg_sql_open_nodelay($h)
57 57 $ret = FALSE; $ret = FALSE;
58 58 while (1) { while (1) {
59 59 if (!isset($rg_sql_conn[$h])) { if (!isset($rg_sql_conn[$h])) {
60 rg_internal_error("Handler $h not present!");
60 rg_internal_error('Handler [' . $h . '] not present!');
61 61 break; break;
62 62 } }
63 63
File inc/ssh.inc.php changed (mode: 100644) (index ca20642..a0ee4b1)
... ... require_once($INC . '/prof.inc.php');
8 8 require_once($INC . '/repo.inc.php'); require_once($INC . '/repo.inc.php');
9 9 require_once($INC . '/totp.inc.php'); require_once($INC . '/totp.inc.php');
10 10 require_once($INC . '/api.inc.php'); require_once($INC . '/api.inc.php');
11 require_once($INC . '/stats.inc.php');
11 12
12 function rg_ssh_status($db, $uid)
13 $rg_ssh_error = '';
14 function rg_ssh_set_error($str)
15 {
16 global $rg_ssh_error;
17
18 $rg_ssh_error = $str;
19 rg_log('ssh_set_error: ' . $str);
20 }
21
22 function rg_ssh_error()
23 {
24 global $rg_ssh_error;
25
26 return $rg_ssh_error;
27 }
28
29 function rg_ssh_status($db, $login_ui)
13 30 { {
14 31 rg_log('ssh_status'); rg_log('ssh_status');
15 32
 
... ... function rg_ssh_status($db, $uid)
21 38 /* /*
22 39 * List repos * List repos
23 40 */ */
24 function rg_ssh_repos($db, $uid)
41 function rg_ssh_repos($db, $login_ui)
25 42 { {
26 43 rg_log('ssh_repos'); rg_log('ssh_repos');
27 44
28 $params = array('uid' => $uid);
45 $params = array('uid' => $login_ui['uid']);
29 46 $sql = 'SELECT * FROM repos' $sql = 'SELECT * FROM repos'
30 47 . ' WHERE uid = @@uid@@' . ' WHERE uid = @@uid@@'
31 48 . ' AND deleted = 0' . ' AND deleted = 0'
32 49 . ' ORDER BY name, itime'; . ' ORDER BY name, itime';
33 $pad = ' ';
34 50 $res = rg_sql_query_params($db, $sql, $params); $res = rg_sql_query_params($db, $sql, $params);
35 51 $rows = rg_sql_num_rows($res); $rows = rg_sql_num_rows($res);
36 52 if ($rows > 0) { if ($rows > 0) {
37 echo 'Repositories (creation, disk used, name):' . "\n";
53 echo 'Repositories (creation (UTC), disk used, name):' . "\n";
38 54 while (($row = rg_sql_fetch_array($res))) { while (($row = rg_sql_fetch_array($res))) {
39 55 $d = rg_1024($row['disk_used_mb'] * 1024 * 1024); $d = rg_1024($row['disk_used_mb'] * 1024 * 1024);
40 56 echo gmdate('Y-m-d', $row['itime']) echo gmdate('Y-m-d', $row['itime'])
 
... ... function rg_ssh_repos($db, $uid)
51 67 /* /*
52 68 * Info about a repo * Info about a repo
53 69 */ */
54 function rg_ssh_repo($db, $uid, $paras)
70 function rg_ssh_repo($db, $login_ui, $paras)
55 71 { {
56 72 rg_log('ssh_repo: ' . rg_array2string($paras)); rg_log('ssh_repo: ' . rg_array2string($paras));
57 73
 
... ... function rg_ssh_repo($db, $uid, $paras)
62 78
63 79 $repo_name = trim($paras[0]); $repo_name = trim($paras[0]);
64 80
65 $ri = rg_repo_info($db, 0, $uid, $repo_name);
81 $ri = rg_repo_info($db, 0, $login_ui['uid'], $repo_name);
66 82 if ($ri['exists'] != 1) { if ($ri['exists'] != 1) {
67 83 fwrite(STDERR, 'Error: unknown repo.' . "\n"); fwrite(STDERR, 'Error: unknown repo.' . "\n");
68 84 exit(0); exit(0);
 
... ... function rg_ssh_totp_verify_ip($db, $uid, $ip)
150 166 /* /*
151 167 * Deal with TOTP stuff * Deal with TOTP stuff
152 168 */ */
153 function rg_ssh_totp($db, $ip, $uid, $paras)
169 function rg_ssh_totp($db, $ip, $login_ui, $paras)
154 170 { {
155 171 global $rg_ssh_host; global $rg_ssh_host;
156 172
157 173 rg_prof_start('ssh_totp'); rg_prof_start('ssh_totp');
158 rg_log_enter('ssh_totp ip=' . $ip . ' uid=' . $uid
174 rg_log_enter('ssh_totp ip=' . $ip . ' uid=' . $login_ui['uid']
159 175 . ' paras=' . rg_array2string($paras)); . ' paras=' . rg_array2string($paras));
160 176
161 177 $cmd = array_shift($paras); $cmd = array_shift($paras);
 
... ... function rg_ssh_totp($db, $ip, $uid, $paras)
164 180 if (empty($paras)) { if (empty($paras)) {
165 181 $secret = rg_totp_base32_generate(16); $secret = rg_totp_base32_generate(16);
166 182
167 $r = rg_totp_enroll($db, $uid, 'SSH', $secret, $ip, 'f');
183 $r = rg_totp_enroll($db, $login_ui['uid'], 'SSH',
184 $secret, $ip, 'f');
168 185 if ($r !== TRUE) { if ($r !== TRUE) {
169 186 fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n"); fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n");
170 187 break; break;
 
... ... function rg_ssh_totp($db, $ip, $uid, $paras)
182 199
183 200 $token = array_shift($paras); $token = array_shift($paras);
184 201
185 $v = rg_totp_device_verify($db, $uid, $token);
202 $v = rg_totp_device_verify($db, $login_ui['uid'], $token);
186 203 if ($v['token_valid'] != 1) { if ($v['token_valid'] != 1) {
187 204 fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n"); fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n");
188 205 break; break;
 
... ... function rg_ssh_totp($db, $ip, $uid, $paras)
215 232 } }
216 233 //rg_log("token=$token days=$days hours=$hours minutes=$minutes"); //rg_log("token=$token days=$days hours=$hours minutes=$minutes");
217 234
218 $v = rg_totp_verify_any($db, $uid, $token);
235 $v = rg_totp_verify_any($db, $login_ui['uid'], $token);
219 236 if ($v['token_valid'] != 1) { if ($v['token_valid'] != 1) {
220 237 fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n"); fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n");
221 238 break; break;
 
... ... function rg_ssh_totp($db, $ip, $uid, $paras)
224 241 $expire_ts = gmmktime(gmdate('H') + $hours, $expire_ts = gmmktime(gmdate('H') + $hours,
225 242 gmdate('i') + $minutes, gmdate('s'), gmdate('m'), gmdate('i') + $minutes, gmdate('s'), gmdate('m'),
226 243 gmdate('d') + $days, gmdate('Y')); gmdate('d') + $days, gmdate('Y'));
227 $r = rg_totp_add_ip($db, $uid, $v['id'], $ip, $expire_ts);
244 $r = rg_totp_add_ip($db, $login_ui['uid'], $v['id'],
245 $ip, $expire_ts);
228 246 if ($r === FALSE) { if ($r === FALSE) {
229 247 fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n"); fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n");
230 248 break; break;
 
... ... function rg_ssh_totp($db, $ip, $uid, $paras)
235 253 break; break;
236 254
237 255 case 'list-val': case 'list-val':
238 $r = rg_ssh_totp_verify_ip($db, $uid, $ip);
256 $r = rg_ssh_totp_verify_ip($db, $login_ui['uid'], $ip);
239 257 if ($r === FALSE) if ($r === FALSE)
240 258 break; break;
241 259
 
... ... function rg_ssh_totp($db, $ip, $uid, $paras)
252 270 case 'unenroll': case 'unenroll':
253 271 $token = array_shift($paras); $token = array_shift($paras);
254 272
255 $v = rg_totp_verify_any($db, $uid, $token);
273 $v = rg_totp_verify_any($db, $login_ui['uid'], $token);
256 274 if ($v['token_valid'] != 1) { if ($v['token_valid'] != 1) {
257 275 fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n"); fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n");
258 276 break; break;
259 277 } }
260 278
261 $r = rg_totp_unenroll($db, $uid);
279 $r = rg_totp_unenroll($db, $login_ui['uid']);
262 280 if ($r !== TRUE) { if ($r !== TRUE) {
263 281 fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n"); fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n");
264 282 break; break;
 
... ... function rg_ssh_totp($db, $ip, $uid, $paras)
270 288 case 'remove-device': case 'remove-device':
271 289 $token = array_shift($paras); $token = array_shift($paras);
272 290
273 $v = rg_totp_device_verify($db, $uid, $token);
291 $v = rg_totp_device_verify($db, $login_ui['uid'], $token);
274 292 if ($v['token_valid'] != 1) { if ($v['token_valid'] != 1) {
275 293 fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n"); fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n");
276 294 break; break;
277 295 } }
278 296
279 297 $a = array($v['id'] => ''); $a = array($v['id'] => '');
280 $r = rg_totp_remove($db, $uid, $a);
298 $r = rg_totp_remove($db, $login_ui['uid'], $a);
281 299 if ($r !== TRUE) { if ($r !== TRUE) {
282 300 fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n"); fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n");
283 301 break; break;
 
... ... function rg_ssh_totp($db, $ip, $uid, $paras)
295 313
296 314 $del_ip = array_shift($paras); $del_ip = array_shift($paras);
297 315
298 if (rg_ssh_totp_verify_ip($db, $uid, $ip) === FALSE)
316 if (rg_ssh_totp_verify_ip($db, $login_ui['uid'], $ip) === FALSE)
299 317 break; break;
300 318
301 $r = rg_totp_del_ip($db, $uid, $del_ip);
319 $r = rg_totp_del_ip($db, $login_ui['uid'], $del_ip);
302 320 if ($r['found'] != 1) { if ($r['found'] != 1) {
303 321 fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n"); fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n");
304 322 break; break;
 
... ... function rg_ssh_totp($db, $ip, $uid, $paras)
332 350 /* /*
333 351 * Deal with API * Deal with API
334 352 */ */
335 function rg_ssh_api($db, $ip, $uid, $paras)
353 function rg_ssh_api($db, $ip, $login_ui, $paras)
336 354 { {
337 355 rg_prof_start('ssh_api'); rg_prof_start('ssh_api');
338 356 rg_log_enter('ssh_api paras=' . rg_array2string($paras)); rg_log_enter('ssh_api paras=' . rg_array2string($paras));
339 357
340 358 $cmd = array_shift($paras); $cmd = array_shift($paras);
359 rg_stats_conns_set('type', 'api-over-ssh');
360
361 $ret = array();
341 362 while (1) { while (1) {
363 if (empty($cmd)) {
364 $ret['error'] = 'missing API command';
365 break;
366 }
367
342 368 $a = array(); $a = array();
343 369 foreach ($paras as $t) { foreach ($paras as $t) {
344 370 $v = explode('=', $t, 2); $v = explode('=', $t, 2);
345 371 if (count($v) != 2) { if (count($v) != 2) {
346 $a['errmsg'] = 'invalid para (no =)';
347 $ret = json_encode($a, JSON_PRETTY_PRINT) . "\n";
372 $ret['error'] = 'invalid para (no =)';
348 373 break; break;
349 374 } }
350 375
351 376 $k = trim($v[0]); $k = trim($v[0]);
352 377 $a[$k] = trim($v[1]); $a[$k] = trim($v[1]);
353 378 } }
354 if (isset($a['errmsg']))
379 if (isset($ret['error']))
355 380 break; break;
356 381
357 382 $a['cmd'] = $cmd; $a['cmd'] = $cmd;
358 $a['connect_uid'] = $uid;
359 $a['ip'] = $ip;
360 $ret = rg_api($db, $a);
383 $x = array();
384 $x['login_ui'] = $login_ui;
385 $x['ip'] = $ip;
386 $ret = array_merge($ret, rg_api($db, $x, $a));
361 387 break; break;
362 388 } }
363 389
390 rg_log_ml('DEBUG: ret: ' . print_r($ret, TRUE));
391
364 392 rg_log_exit(); rg_log_exit();
365 rg_prof_start('ssh_api');
366 rg_log_ml('ret: ' . print_r($ret, TRUE));
367 echo $ret;
393 rg_prof_end('ssh_api');
394 echo json_encode($ret, JSON_PRETTY_PRINT) . "\n";
368 395 } }
369 396
370 397 /* /*
371 398 * Returns TRUE if we need to stop execution * Returns TRUE if we need to stop execution
372 399 */ */
373 function rg_ssh_dispatch($db, $ip, $uid, $orig_cmd)
400 function rg_ssh_dispatch($db, $ip, $login_ui, $orig_cmd)
374 401 { {
375 402 rg_log('ssh_dispatch orig_cmd=[' . $orig_cmd . ']'); rg_log('ssh_dispatch orig_cmd=[' . $orig_cmd . ']');
376 403
 
... ... function rg_ssh_dispatch($db, $ip, $uid, $orig_cmd)
388 415 case '': break; case '': break;
389 416 case 'totp': break; // totp will verify the ip only for some commands case 'totp': break; // totp will verify the ip only for some commands
390 417 default: default:
391 $r = rg_totp_verify_ip($db, $uid, $ip);
418 $r = rg_totp_verify_ip($db, $login_ui['uid'], $ip);
392 419 if (($r['ok'] !== 1) if (($r['ok'] !== 1)
393 420 || ($r['enrolled'] && empty($r['ip_list']))) { || ($r['enrolled'] && empty($r['ip_list']))) {
394 421 fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n"); fwrite(STDERR, 'Error: ' . rg_totp_error() . ".\n");
 
... ... function rg_ssh_dispatch($db, $ip, $uid, $orig_cmd)
399 426
400 427 // Now, we can safely execute the command // Now, we can safely execute the command
401 428 switch ($cmd) { switch ($cmd) {
402 case 'status': rg_ssh_status($db, $uid); return TRUE;
403 case 'repos': rg_ssh_repos($db, $uid); return TRUE;
404 case 'repo': rg_ssh_repo($db, $uid, $paras); return TRUE;
405 case 'totp': rg_ssh_totp($db, $ip, $uid, $paras); return TRUE;
406 case 'api': rg_ssh_api($db, $ip, $uid, $paras); return TRUE;
429 case 'status': rg_ssh_status($db, $login_ui); return TRUE;
430 case 'repos': rg_ssh_repos($db, $login_ui); return TRUE;
431 case 'repo': rg_ssh_repo($db, $login_ui, $paras); return TRUE;
432 case 'totp': rg_ssh_totp($db, $ip, $login_ui, $paras); return TRUE;
433 case 'api': rg_ssh_api($db, $ip, $login_ui, $paras); return TRUE;
407 434 case '': case '':
408 435 fwrite(STDERR, "\n" fwrite(STDERR, "\n"
409 436 . 'Available commmands:' . "\n" . 'Available commmands:' . "\n"
 
... ... function rg_ssh_data($db, $type, $start, $end, $unit, $mode)
430 457 $q = 'SELECT 1 AS value, itime FROM keys' $q = 'SELECT 1 AS value, itime FROM keys'
431 458 . ' WHERE itime >= @@start@@ AND itime <= @@end@@'; . ' WHERE itime >= @@start@@ AND itime <= @@end@@';
432 459 break; break;
433 default: return FALSE;
460 default:
461 rg_internal_error('invalid data');
462 return FALSE;
434 463 } }
435 464
436 return rg_graph_query($db, $start, $end, $unit, $mode, $q, $params);
465 $ret = rg_graph_query($db, $start, $end, $unit, $mode, $q, $params, '');
466 if ($ret === FALSE)
467 rg_ssh_set_error(rg_graph_error());
468
469 return $ret;
437 470 } }
438 471
439 ?>
File inc/stats.inc.php changed (mode: 100644) (index ca1c809..616a6a1)
2 2
3 3 // Gather stats about the system // Gather stats about the system
4 4
5 $rg_stats_error = '';
6 function rg_stats_set_error($str)
7 {
8 global $rg_stats_error;
9
10 $rg_stats_error = $str;
11 rg_log('stats_set_error: ' . $str);
12 }
13
14 function rg_stats_error()
15 {
16 global $rg_stats_error;
17
18 return $rg_stats_error;
19 }
20
5 21 /* /*
6 22 * Returns stats about the disk * Returns stats about the disk
7 23 */ */
 
... ... function rg_stats_data($db, $type, $start, $end, $unit, $mode)
60 76 $q = 'SELECT disk_used_gib AS value, itime FROM stats' $q = 'SELECT disk_used_gib AS value, itime FROM stats'
61 77 . ' WHERE itime >= @@start@@ AND itime <= @@end@@'; . ' WHERE itime >= @@start@@ AND itime <= @@end@@';
62 78 break; break;
79
63 80 case 'mem': case 'mem':
64 81 $q = 'SELECT mem_used_mib AS value, itime FROM stats' $q = 'SELECT mem_used_mib AS value, itime FROM stats'
65 82 . ' WHERE itime >= @@start@@ AND itime <= @@end@@'; . ' WHERE itime >= @@start@@ AND itime <= @@end@@';
66 83 break; break;
84
67 85 case 'load': case 'load':
68 86 $q = 'SELECT load AS value, itime FROM stats' $q = 'SELECT load AS value, itime FROM stats'
69 87 . ' WHERE itime >= @@start@@ AND itime <= @@end@@'; . ' WHERE itime >= @@start@@ AND itime <= @@end@@';
70 88 break; break;
71 default: return FALSE;
89
90 default:
91 rg_internal_error('invalid type');
92 return FALSE;
72 93 } }
73 94
74 return rg_graph_query($db, $start, $end, $unit, $mode, $q, $params);
95 $ret = rg_graph_query($db, $start, $end, $unit, $mode, $q, $params, '');
96 if ($ret === FALSE)
97 rg_stats_set_error(rg_graph_error());
98
99 return $ret;
75 100 } }
101
102 /*
103 * Store 'conns' stats
104 */
105 function rg_stats_conns_insert($db)
106 {
107 global $rg_stats_conns_paras;
108
109 $ret = FALSE;
110 while (1) {
111 if (!isset($rg_stats_conns_paras['elap']))
112 $rg_stats_conns_paras['elap'] = intval((microtime(TRUE) - $rg_stats_conns_paras['start']) * 1000);
113 $rg_stats_conns_paras['start'] = intval($rg_stats_conns_paras['start']);
114
115 $list = array(
116 'ua' => '',
117 'cmd' => '',
118 'referer' => '',
119 'url' => '',
120 'uid' => 0,
121 'repo_id' => 0
122 );
123 foreach ($list as $k => $v)
124 if (!isset($rg_stats_conns_paras[$k]))
125 $rg_stats_conns_paras[$k] = $v;
126
127 $sql = 'INSERT INTO conns_' . gmdate('Y_m', $rg_stats_conns_paras['start'])
128 . ' (type, uid, repo_id, itime, ip, url'
129 . ', referer, elap, ua, cmd)'
130 . ' VALUES (@@type@@, @@uid@@'
131 . ', @@repo_id@@, @@start@@, @@ip@@, @@url@@'
132 . ', @@referer@@, @@elap@@, @@ua@@, @@cmd@@)';
133 $res = rg_sql_query_params($db, $sql, $rg_stats_conns_paras);
134 if ($res == FALSE) {
135 rg_internal_error('cannot insert conns: ' . rg_sql_error());
136 break;
137 }
138
139 $ret = TRUE;
140 break;
141 }
142
143 return $ret;
144 }
145
146 /*
147 * Set a parameter for conns_insert
148 * Added to be able to not pass &$rg everywhere and to not collude with $rg
149 */
150 $rg_stats_conns_paras = array();
151 function rg_stats_conns_set($para, $value)
152 {
153 global $rg_stats_conns_paras;
154
155 rg_log('DEBUG: stats_conns_set ' . $para . '=[' . $value . ']');
156 $rg_stats_conns_paras[$para] = $value;
157 }
158
159 /*
160 * Loads data for graphs
161 * @unit - interval on which a sum is made
162 */
163 function rg_conns_data($db, $type, $start, $end, $unit, $mode)
164 {
165 $params = array('start' => $start, 'end' => $end);
166 switch ($type) {
167 case 'total':
168 $q = 'SELECT 1 AS value, itime FROM conns'
169 . ' WHERE itime >= @@start@@ AND itime <= @@end@@';
170 break;
171
172 default:
173 rg_internal_error('invalid type');
174 return FALSE;
175 }
176
177 $ret = rg_graph_query($db, $start, $end, $unit, $mode, $q, $params, '');
178 if ($ret === FALSE)
179 rg_stats_set_error(rg_graph_error());
180
181 return $ret;
182 }
183
File inc/stats/stats.php changed (mode: 100644) (index 9f787c3..a4de59e)
... ... case 'month':
12 12 case '12hours': case '12hours':
13 13 $period = 'minute'; $period = 'minute';
14 14 $start = gmmktime(gmdate('H') + 12, 0, 0, gmdate('m'), gmdate('d') - 1, gmdate('Y')); $start = gmmktime(gmdate('H') + 12, 0, 0, gmdate('m'), gmdate('d') - 1, gmdate('Y'));
15 $end = gmmktime(gmdate('H'), 0, 0, gmdate('m'), gmdate('d'), gmdate('Y')) - 1;
15 $end = gmmktime(gmdate('H') + 1, 0, 0, gmdate('m'), gmdate('d'), gmdate('Y')) - 1;
16 16 break; break;
17 17
18 18 case 'year': case 'year':
 
... ... if (1) {
51 51 $b['title'] = '🛸 Users'; $b['title'] = '🛸 Users';
52 52 $r = rg_user_data($db, 'create_account', $start, $end, $period, 'sum'); $r = rg_user_data($db, 'create_account', $start, $end, $period, 'sum');
53 53 if ($r === FALSE) { if ($r === FALSE) {
54 $rg['graph']['users'] = 'Error generating user graph!';
54 $rg['graph']['users'] = 'Error generating user graph: '
55 . rg_user_error() . '!';
55 56 } else { } else {
56 57 $b['data'] = $r; $b['data'] = $r;
57 58 $rg['graph']['HTML:users'] = rg_graph($b); $rg['graph']['HTML:users'] = rg_graph($b);
 
... ... if (1) {
61 62 $b['title'] = '🐸 Repositories'; $b['title'] = '🐸 Repositories';
62 63 $r = rg_repo_data($db, 'create_repo', $start, $end, $period, 'sum'); $r = rg_repo_data($db, 'create_repo', $start, $end, $period, 'sum');
63 64 if ($r === FALSE) { if ($r === FALSE) {
64 $rg['graph']['repos'] = 'Error generating repo graph!';
65 $rg['graph']['repos'] = 'Error generating repo graph: '
66 . rg_repo_error() . '!';
65 67 } else { } else {
66 68 $b['data'] = $r; $b['data'] = $r;
67 69 $rg['graph']['HTML:repos'] = rg_graph($b); $rg['graph']['HTML:repos'] = rg_graph($b);
 
... ... if (1) {
71 73 $b['title'] = '🐛 Bugs'; $b['title'] = '🐛 Bugs';
72 74 $r = rg_repo_data($db, 'create_bug', $start, $end, $period, 'sum'); $r = rg_repo_data($db, 'create_bug', $start, $end, $period, 'sum');
73 75 if ($r === FALSE) { if ($r === FALSE) {
74 $rg['graph']['bugs'] = 'Error generating bugs graph!';
76 $rg['graph']['bugs'] = 'Error generating bugs graph: '
77 . rg_repo_error() . '!';
75 78 } else { } else {
76 79 $b['data'] = $r; $b['data'] = $r;
77 80 $rg['graph']['HTML:bugs'] = rg_graph($b); $rg['graph']['HTML:bugs'] = rg_graph($b);
 
... ... if (1) {
81 84 $b['title'] = '⛙ Merge requests'; $b['title'] = '⛙ Merge requests';
82 85 $r = rg_mr_data($db, 'create_mr', $start, $end, $period, 'sum'); $r = rg_mr_data($db, 'create_mr', $start, $end, $period, 'sum');
83 86 if ($r === FALSE) { if ($r === FALSE) {
84 $rg['graph']['mrs'] = 'Error generating mr graph!';
87 $rg['graph']['mrs'] = 'Error generating mr graph: '
88 . rg_mr_error() . '!';
85 89 } else { } else {
86 90 $b['data'] = $r; $b['data'] = $r;
87 91 $rg['graph']['HTML:mrs'] = rg_graph($b); $rg['graph']['HTML:mrs'] = rg_graph($b);
88 92 } }
89 93
94 $b = $a;
95 $b['title'] = '🎥 Requests (web, API, ssh, git)';
96 $r = rg_conns_data($db, 'total', $start, $end, $period, 'sum');
97 if ($r === FALSE) {
98 $rg['graph']['requests'] = 'Error generating requests graph: '
99 . rg_stats_error() . '!';
100 } else {
101 $b['data'] = $r;
102 $rg['graph']['HTML:requests'] = rg_graph($b);
103 }
104
90 105 $b = $a; $b = $a;
91 106 $b['title'] = '📅 Repositories history entries'; $b['title'] = '📅 Repositories history entries';
92 107 $r = rg_repo_data($db, 'history', $start, $end, $period, 'sum'); $r = rg_repo_data($db, 'history', $start, $end, $period, 'sum');
93 108 if ($r === FALSE) { if ($r === FALSE) {
94 $rg['graph']['repo_history'] = 'Error generating repo history graph!';
109 $rg['graph']['repo_history'] = 'Error generating repo history graph: '
110 . rg_repo_error() . '!';
95 111 } else { } else {
96 112 $b['data'] = $r; $b['data'] = $r;
97 113 $rg['graph']['HTML:repo_history'] = rg_graph($b); $rg['graph']['HTML:repo_history'] = rg_graph($b);
 
... ... if (1) {
101 117 $b['title'] = '🔑 SSH keys'; $b['title'] = '🔑 SSH keys';
102 118 $r = rg_ssh_data($db, 'create_key', $start, $end, $period, 'sum'); $r = rg_ssh_data($db, 'create_key', $start, $end, $period, 'sum');
103 119 if ($r === FALSE) { if ($r === FALSE) {
104 $rg['graph']['keys'] = 'Error generating keys graph!';
120 $rg['graph']['keys'] = 'Error generating keys graph: '
121 . rg_ssh_error() . '!';
105 122 } else { } else {
106 123 $b['data'] = $r; $b['data'] = $r;
107 124 $rg['graph']['HTML:keys'] = rg_graph($b); $rg['graph']['HTML:keys'] = rg_graph($b);
 
... ... if (1) {
111 128 $b['title'] = '💽 Disk space used (GiB)'; $b['title'] = '💽 Disk space used (GiB)';
112 129 $r = rg_stats_data($db, 'disk', $start, $end, $period, 'avg'); $r = rg_stats_data($db, 'disk', $start, $end, $period, 'avg');
113 130 if ($r === FALSE) { if ($r === FALSE) {
114 $rg['graph']['disk'] = 'Error generating disk graph!';
131 $rg['graph']['disk'] = 'Error generating disk graph: '
132 . rg_stats_error() . '!';
115 133 } else { } else {
116 134 $b['data'] = $r; $b['data'] = $r;
117 135 $rg['graph']['HTML:disk'] = rg_graph($b); $rg['graph']['HTML:disk'] = rg_graph($b);
 
... ... if (1) {
121 139 $b['title'] = '🧠 Memory used (MiB)'; $b['title'] = '🧠 Memory used (MiB)';
122 140 $r = rg_stats_data($db, 'mem', $start, $end, $period, 'avg'); $r = rg_stats_data($db, 'mem', $start, $end, $period, 'avg');
123 141 if ($r === FALSE) { if ($r === FALSE) {
124 $rg['graph']['mem'] = 'Error generating disk graph!';
142 $rg['graph']['mem'] = 'Error generating disk graph: '
143 . rg_stats_error() . '!';
125 144 } else { } else {
126 145 $b['data'] = $r; $b['data'] = $r;
127 146 $rg['graph']['HTML:mem'] = rg_graph($b); $rg['graph']['HTML:mem'] = rg_graph($b);
 
... ... if (1) {
131 150 $b['title'] = '🚜 Load'; $b['title'] = '🚜 Load';
132 151 $r = rg_stats_data($db, 'load', $start, $end, $period, 'avg'); $r = rg_stats_data($db, 'load', $start, $end, $period, 'avg');
133 152 if ($r === FALSE) { if ($r === FALSE) {
134 $rg['graph']['load'] = 'Error generating disk graph!';
153 $rg['graph']['load'] = 'Error generating disk graph: '
154 . rg_stats_error() . '!';
135 155 } else { } else {
136 156 $b['data'] = $r; $b['data'] = $r;
137 157 $rg['graph']['HTML:load'] = rg_graph($b); $rg['graph']['HTML:load'] = rg_graph($b);
File inc/struct.inc.php changed (mode: 100644) (index bb0fca9..a8d45ef)
... ... $rg_sql_struct[10]['tables'] = array(
207 207 . ", message TEXT NOT NULL)" . ", message TEXT NOT NULL)"
208 208 ); );
209 209 $rg_sql_struct[10]['other'] = array(); $rg_sql_struct[10]['other'] = array();
210 $rg_sql_struct_slaves['repo_history'] = "repo_history";
210 $rg_sql_struct_slaves['repo_history'] = array();
211 211
212 212 $rg_sql_struct[11] = array(); $rg_sql_struct[11] = array();
213 213 $rg_sql_struct[11]['tables'] = array( $rg_sql_struct[11]['tables'] = array(
 
... ... $rg_sql_struct[45]['tables'] = array(
652 652 . 'itime INT NOT NULL' . 'itime INT NOT NULL'
653 653 . ', load INT NOT NULL' . ', load INT NOT NULL'
654 654 . ', disk_used_gib INT NOT NULL' . ', disk_used_gib INT NOT NULL'
655 . ', mem_used_mib INT NOT NULL)'
655 . ', mem_used_mib INT NOT NULL)',
656 'worker_stats' => 'CREATE TABLE worker_stats'
657 . ' (worker_id INT NOT NULL, itime INT NOT NULL'
658 . ', data TEXT NOT NULL)',
659 'conns' => 'CREATE TABLE conns'
660 . ' (type TEXT NOT NULL, uid INT NOT NULL'
661 . ', repo_id INT NOT NULL, itime INT NOT NULL'
662 . ', ip TEXT NOT NULL, url TEXT NOT NULL'
663 . ', referer TEXT NOT NULL, elap INT NOT NULL'
664 . ', ua TEXT NOT NULL, cmd TEXT NOT NULL)'
656 665 ); );
657 666 $rg_sql_struct[45]['other'] = array( $rg_sql_struct[45]['other'] = array(
658 667 'we need to know the subtype of a webhook' => 'we need to know the subtype of a webhook' =>
659 'ALTER TABLE webhooks ADD hsubtype TEXT NOT NULL DEFAULT \'\''
668 'ALTER TABLE webhooks ADD hsubtype TEXT NOT NULL DEFAULT \'\'',
669 'worker_stats id' =>
670 'CREATE INDEX worker_stats_i_worker_id on worker_stats(worker_id)'
660 671 ); );
661 $rg_sql_struct_slaves['stats'] = 'stats';
662
672 $rg_sql_struct_slaves['stats'] = array();
673 $rg_sql_struct_slaves['worker_stats'] = array('extra_index' => array('worker_id'));
674 $rg_sql_struct_slaves['conns'] = array();
663 675
664 676 // Do not forget to add the new created tables to statistics // Do not forget to add the new created tables to statistics
665 677 // This must be the last line // This must be the last line
 
... ... function rg_sql_struct_slaves_update($db)
856 868 { {
857 869 global $rg_sql_struct_slaves; global $rg_sql_struct_slaves;
858 870
859 rg_prof_start("sql_struct_slaves_update");
860 rg_log_enter("sql_struct_slaves_update");
871 rg_prof_start('sql_struct_slaves_update');
872 rg_log_enter('sql_struct_slaves_update');
861 873
862 874 $ret = FALSE; $ret = FALSE;
863 $rollback = 0;
864 $locked = FALSE;
875 $doit = FALSE;
865 876 while (1) { while (1) {
866 877 if (empty($rg_sql_struct_slaves)) { if (empty($rg_sql_struct_slaves)) {
867 878 $ret = TRUE; $ret = TRUE;
868 879 break; break;
869 880 } }
870 881
871 // If we cannot lock, return error
872 if (rg_lock("slave_create.lock") === FALSE)
882 $last_list = rg_state_get($db, 'slaves_create_last_list');
883 if ($last_list === FALSE)
873 884 break; break;
874 $locked = TRUE;
875 885
876 $last_ts = rg_state_get_uint($db, "slaves_create_last_ts");
886 $last_ts = rg_state_get_uint($db, 'slaves_create_last_ts');
877 887 if ($last_ts === FALSE) if ($last_ts === FALSE)
878 888 break; break;
879 889 if ($last_ts == 0) if ($last_ts == 0)
880 $last_ts = gmmktime(0, 0, 0, gmdate("m") - 1, 1, gmdate("Y"));
881 rg_log("last_ts=$last_ts (" . gmdate("Y-m-d", $last_ts) . ")");
890 $last_ts = gmmktime(0, 0, 0, gmdate('m') - 1, 1, gmdate('Y'));
891 rg_log('DEBUG: last_ts=' . $last_ts . ' (' . gmdate('Y-m-d', $last_ts) . ')');
892
893 $cur_list = sha1(rg_serialize($rg_sql_struct_slaves));
894 rg_log('DEBUG: last_list=[' . $last_list . '] cur_list=[' . $cur_list . ']');
895 if (strcmp($last_list, $cur_list) != 0) {
896 rg_log('DEBUG: list of the slaves changed.');
897 // We need to set last_ts
898 $last_ts = gmmktime(0, 0, 0, gmdate('m') - 1, 1, gmdate('Y'));
899 $doit = TRUE;
900 break;
901 }
882 902
883 903 // First second of current month // First second of current month
884 $current_month_ts = gmmktime(0, 0, 0, gmdate("m"), 1, gmdate("Y"));
885 rg_log("current_month_ts=$current_month_ts (" . gmdate("Y-m-d", $current_month_ts) . ")");
904 $current_month_ts = gmmktime(0, 0, 0, gmdate('m'), 1, gmdate('Y'));
905 rg_log('DEBUG: current_month_ts=' . $current_month_ts
906 . ' (' . gmdate('Y-m-d', $current_month_ts) . ')');
886 907
887 908 // Do we have current month and the next one covered? // Do we have current month and the next one covered?
888 909 if ($current_month_ts < $last_ts) { if ($current_month_ts < $last_ts) {
889 rg_log("No update needed!");
910 rg_log('No update needed!');
890 911 $ret = TRUE; $ret = TRUE;
891 912 break; break;
892 913 } }
893 914
915 $doit = TRUE;
916 break;
917 }
918
919 rg_log('DEBUG: doit=' . ($doit ? 1 : 0) . ' ret=' . ($ret === FALSE ? 'FALSE' : 'TRUE'));
920 $rollback = 0;
921 $locked = FALSE;
922 while ($doit) {
923 // If we cannot lock, return error
924 if (rg_lock('slave_create.lock') === FALSE)
925 break;
926 $locked = TRUE;
927
894 928 if (rg_sql_begin($db) !== TRUE) if (rg_sql_begin($db) !== TRUE)
895 929 break; break;
896 930 $rollback = 1; $rollback = 1;
897 931
898 932 $ok = TRUE; $ok = TRUE;
899 $month = gmdate("m", $last_ts) + 1;
900 $year = gmdate("Y", $last_ts);
933 $month = gmdate('m', $last_ts) + 1;
934 $year = gmdate('Y', $last_ts);
901 935 $ts = gmmktime(0, 0, 0, $month, 1, $year); $ts = gmmktime(0, 0, 0, $month, 1, $year);
902 $stop_ts = gmmktime(0, 0, 0, gmdate("m") + 1, 1, gmdate("Y"));
936 $stop_ts = gmmktime(0, 0, 0, gmdate('m') + 1, 1, gmdate('Y'));
903 937 while ($ts <= $stop_ts) { while ($ts <= $stop_ts) {
904 938 $month++; $month++;
905 939 $next_ts = gmmktime(0, 0, 0, $month, 1, $year); $next_ts = gmmktime(0, 0, 0, $month, 1, $year);
906 940
907 foreach ($rg_sql_struct_slaves as $table) {
908 $slave_table = $table . "_" . gmdate("Y_m", $ts);
941 foreach ($rg_sql_struct_slaves as $table => $ti) {
942 $slave_table = $table . '_' . gmdate('Y_m', $ts);
909 943
910 944 // First, check if exists. It is possible that // First, check if exists. It is possible that
911 945 // we did the update but we could not set the cache. // we did the update but we could not set the cache.
912 $sql = "SELECT 1 FROM pg_class"
913 . " WHERE relname = '" . $slave_table . "'";
946 $sql = 'SELECT 1 FROM pg_class'
947 . ' WHERE relname = \'' . $slave_table . '\'';
914 948 $res = rg_sql_query($db, $sql); $res = rg_sql_query($db, $sql);
915 949 if ($res === FALSE) { if ($res === FALSE) {
916 950 $ok = FALSE; $ok = FALSE;
 
... ... function rg_sql_struct_slaves_update($db)
921 955 if ($rows > 0) if ($rows > 0)
922 956 continue; continue;
923 957
924 $sql = "CREATE TABLE " . $slave_table
925 . " (CHECK(itime >= $ts AND itime <= " . ($next_ts - 1) . "))"
926 . " INHERITS (" . $table . ")";
958 $sql = 'CREATE TABLE ' . $slave_table
959 . ' (CHECK(itime >= ' . $ts . ' AND itime <= ' . ($next_ts - 1) . '))'
960 . ' INHERITS (' . $table . ')';
927 961 $res = rg_sql_query($db, $sql); $res = rg_sql_query($db, $sql);
928 962 if ($res === FALSE) { if ($res === FALSE) {
929 963 $ok = FALSE; $ok = FALSE;
 
... ... function rg_sql_struct_slaves_update($db)
931 965 } }
932 966 rg_sql_free_result($res); rg_sql_free_result($res);
933 967
934 $sql = "CREATE INDEX " . $slave_table . "_i_itime"
935 . " ON " . $slave_table
936 . " (itime)";
968 $sql = 'CREATE INDEX ' . $slave_table . '_i_itime'
969 . ' ON ' . $slave_table
970 . ' (itime)';
937 971 $res = rg_sql_query($db, $sql); $res = rg_sql_query($db, $sql);
938 972 if ($res === FALSE) { if ($res === FALSE) {
939 973 $ok = FALSE; $ok = FALSE;
940 974 break; break;
941 975 } }
942 976 rg_sql_free_result($res); rg_sql_free_result($res);
977
978 if (isset($ti['extra_index'])) {
979 foreach ($ti['extra_index'] as $i) {
980 $sql = 'CREATE INDEX ' . $slave_table . '_i_' . $i
981 . ' ON ' . $slave_table
982 . ' (' . $i . ')';
983 $res = rg_sql_query($db, $sql);
984 if ($res === FALSE) {
985 $ok = FALSE;
986 break;
987 }
988 rg_sql_free_result($res);
989 }
990 }
991 if ($ok !== FALSE)
992 break;
943 993 } }
994 if ($ok !== TRUE)
995 break;
996
944 997 $ts = $next_ts; $ts = $next_ts;
945 998 } }
946 if ($ok === FALSE)
999 if ($ok !== TRUE)
947 1000 break; break;
948 1001
949 if (rg_sql_commit($db) !== TRUE)
1002 $r = rg_state_set($db, 'slaves_create_last_ts', $stop_ts);
1003 if ($r !== TRUE) {
1004 rg_log('Cannot set slaves_create_last_list (' . rg_state_error() . ')');
950 1005 break; break;
1006 }
951 1007
952 $r = rg_state_set($db, "slaves_create_last_ts", $stop_ts);
1008 $r = rg_state_set($db, 'slaves_create_last_list', $cur_list);
953 1009 if ($r !== TRUE) { if ($r !== TRUE) {
954 rg_log("Cannot create slave (" . rg_state_error() . ")");
1010 rg_log('Cannot set slaves_create_last_list (' . rg_state_error() . ')');
955 1011 break; break;
956 1012 } }
957 1013
1014 if (rg_sql_commit($db) !== TRUE)
1015 break;
1016
958 1017 $rollback = 0; $rollback = 0;
959 1018 $ret = TRUE; $ret = TRUE;
960 1019 break; break;
 
... ... function rg_sql_struct_slaves_update($db)
964 1023 rg_sql_rollback($db); rg_sql_rollback($db);
965 1024
966 1025 if ($locked === TRUE) if ($locked === TRUE)
967 rg_unlock("slave_create.lock");
1026 rg_unlock('slave_create.lock');
968 1027
969 1028 rg_log_exit(); rg_log_exit();
970 rg_prof_end("sql_struct_slaves_update");
1029 rg_prof_end('sql_struct_slaves_update');
971 1030 return $ret; return $ret;
972 1031 } }
973 1032
File inc/user.inc.php changed (mode: 100644) (index d0fbae0..3851a9f)
... ... require_once($INC . "/cache.inc.php");
10 10 require_once($INC . "/mail.inc.php"); require_once($INC . "/mail.inc.php");
11 11 require_once($INC . "/plan.inc.php"); require_once($INC . "/plan.inc.php");
12 12 require_once($INC . "/totp.inc.php"); require_once($INC . "/totp.inc.php");
13 require_once($INC . '/stats.inc.php');
13 14
14 15 $rg_user_rights = array( $rg_user_rights = array(
15 16 "C" => "Create repository", "C" => "Create repository",
 
... ... function rg_user_data($db, $type, $start, $end, $unit, $mode)
1878 1879 . ' WHERE itime >= @@start@@ AND itime <= @@end@@' . ' WHERE itime >= @@start@@ AND itime <= @@end@@'
1879 1880 . ' AND is_admin = 0'; . ' AND is_admin = 0';
1880 1881 break; break;
1881 default: return FALSE;
1882 default:
1883 rg_internal_error('invalid type');
1884 return FALSE;
1882 1885 } }
1883 1886
1884 return rg_graph_query($db, $start, $end, $unit, $mode, $q, $params);
1887 $ret = rg_graph_query($db, $start, $end, $unit, $mode, $q, $params, '');
1888 if ($ret === FALSE)
1889 rg_user_set_error(rg_graph_error());
1890
1891 return $ret;
1885 1892 } }
1886 1893
1887 1894 /* /*
 
... ... function rg_user_edit_high_level($db, &$rg)
2056 2063 /* /*
2057 2064 * API dispatch function * API dispatch function
2058 2065 */ */
2059 function rg_user_api($db, $a)
2066 function rg_user_api($db, $a, $json)
2060 2067 { {
2061 2068 rg_prof_start('user_api'); rg_prof_start('user_api');
2062 2069 rg_log_enter('user_api'); rg_log_enter('user_api');
2063 2070
2064 $cmd = $a['cmd'];
2071 $cmd = $json['cmd'];
2065 2072
2066 2073 $ret = array(); $ret = array();
2067 2074 while (1) { while (1) {
2068 if (isset($a['user'])) {
2069 $ui = rg_user_info($db, 0, $a['user'], '');
2070 } else if (isset($a['uid'])) {
2071 $ui = rg_user_info($db, $a['uid'], '', '');
2072 } else {
2073 $ret['error'] = 'no uid=/user= specified';
2074 break;
2075 }
2076 if ($ui['exists'] != 1) {
2075 if ($a['target_ui']['exists'] != 1) {
2077 2076 $ret['error'] = 'invalid user or no rights'; $ret['error'] = 'invalid user or no rights';
2078 2077 break; break;
2079 2078 } }
2080 2079
2081 2080 // TODO: allow also a master user to access user info // TODO: allow also a master user to access user info
2082 if (($a['cui']['is_admin'] != 1)
2083 && ($ui['uid'] != $a['cui']['uid'])) {
2081 if (($a['login_ui']['is_admin'] != 1)
2082 && ($a['target_ui']['uid'] != $a['login_ui']['uid'])) {
2084 2083 $ret['error'] = 'invalid user or no rights'; $ret['error'] = 'invalid user or no rights';
2085 2084 rg_log('user has no rights'); rg_log('user has no rights');
2086 2085 break; break;
2087 2086 } }
2088 2087
2089 2088 if (strcmp($cmd, 'user_info') == 0) { if (strcmp($cmd, 'user_info') == 0) {
2090 $ret = $ui;
2089 $ret = $a['target_ui'];
2090 $list = array('pass', 'salt', 'confirm_token');
2091 foreach ($list as $k)
2092 unset($ret[$k]);
2091 2093 break; break;
2092 2094 } }
2093 2095
2094 2096 if (strcmp($cmd, 'user_ssh_keys_list') == 0) { if (strcmp($cmd, 'user_ssh_keys_list') == 0) {
2095 $ret = rg_keys_list($db, $a['cui']);
2097 $ret['list'] = rg_keys_list($db, $a['target_ui']);
2096 2098 break; break;
2097 2099 } }
2098 2100
2099 2101 if (strcmp($cmd, 'user_rights_list') == 0) { if (strcmp($cmd, 'user_rights_list') == 0) {
2100 $params = array('who' => $ui['uid']);
2102 $params = array('who' => $a['target_ui']['uid']);
2101 2103 $sql = 'SELECT * FROM rights' $sql = 'SELECT * FROM rights'
2102 2104 . ' WHERE who = @@who@@'; . ' WHERE who = @@who@@';
2103 2105 $res = rg_sql_query_params($db, $sql, $params); $res = rg_sql_query_params($db, $sql, $params);
 
... ... function rg_user_api($db, $a)
2105 2107 $ret['error'] = 'internal error'; $ret['error'] = 'internal error';
2106 2108 break; break;
2107 2109 } }
2108 $ret = array();
2110 $ret['list'] = array();
2109 2111 while (($row = rg_sql_fetch_array($res))) { while (($row = rg_sql_fetch_array($res))) {
2110 2112 rg_rights_cosmetic($db, $row); rg_rights_cosmetic($db, $row);
2111 $ret[] = $row;
2113 $ret['list'][] = $row;
2112 2114 } }
2113 2115 rg_sql_free_result($res); rg_sql_free_result($res);
2114 2116 break; break;
2115 2117 } }
2116 2118
2117 2119 if (strcmp($cmd, 'user_wh_list') == 0) { if (strcmp($cmd, 'user_wh_list') == 0) {
2118 $r = rg_wh_list($db, $ui['uid']);
2120 $r = rg_wh_list($db, $a['target_ui']['uid']);
2119 2121 if ($r['ok'] !== 1) { if ($r['ok'] !== 1) {
2120 2122 $ret['error'] = rg_wh_error(); $ret['error'] = rg_wh_error();
2121 2123 break; break;
2122 2124 } }
2123 2125 rg_wh_cosmetic($r['list']); rg_wh_cosmetic($r['list']);
2124 2126 // list is indexed by hook_id, remove this // list is indexed by hook_id, remove this
2125 $ret = array();
2127 $ret['list'] = array();
2126 2128 foreach ($r['list'] as $index => $d) foreach ($r['list'] as $index => $d)
2127 $ret[] = $d;
2129 $ret['list'][] = $d;
2128 2130 break; break;
2129 2131 } }
2130 2132
 
... ... function rg_user_http_git($db, $rg, $paras)
2308 2310 break; break;
2309 2311
2310 2312 $ret = TRUE; $ret = TRUE;
2313 rg_stats_conns_set('cmd', $service);
2311 2314
2312 2315 set_time_limit(3600); set_time_limit(3600);
2313 2316
 
... ... function rg_user_http_git($db, $rg, $paras)
2406 2409 } }
2407 2410 $repo_path = $r['repo_path']; $repo_path = $r['repo_path'];
2408 2411
2412 // for 'conns' stats
2413 rg_stats_conns_set('uid', $r['owner_ui']['uid']);
2414 rg_stats_conns_set('repo_id', $r['ri']['repo_id']);
2415
2409 2416 // push_allowed is only about the rights, not about auth/login_tokens // push_allowed is only about the rights, not about auth/login_tokens
2410 2417 rg_log('DEBUG: push=' . $r['push'] rg_log('DEBUG: push=' . $r['push']
2411 2418 . ' push_allowed=' . $r['push_allowed'] . ' push_allowed=' . $r['push_allowed']
File inc/util.inc.php changed (mode: 100644) (index 2ccf8eb..d2f54af)
... ... function rg_gzencode($c, &$orig_len, &$comp_len)
2693 2693 function rg_web_output($c) function rg_web_output($c)
2694 2694 { {
2695 2695 $acc = @$_SERVER['HTTP_ACCEPT_ENCODING']; $acc = @$_SERVER['HTTP_ACCEPT_ENCODING'];
2696 rg_log('DEBUG: client supports: ' . $acc);
2697 2696 if (stristr($acc, 'gzip')) { if (stristr($acc, 'gzip')) {
2698 2697 $c = rg_gzencode($c, $orig_len, $comp_len); $c = rg_gzencode($c, $orig_len, $comp_len);
2699 2698 header('Content-Encoding: gzip'); header('Content-Encoding: gzip');
 
... ... function rg_array_flat($prefix, $a)
2743 2742
2744 2743 return $ret; return $ret;
2745 2744 } }
2745
2746 /*
2747 * Because array_splice destroys the index!
2748 */
2749 function rg_array_top($a, $nr)
2750 {
2751 $ret = array();
2752 $i = 0;
2753 foreach ($a as $k => $v) {
2754 if ($i++ == $nr)
2755 break;
2756 $ret[$k] = $v;
2757 }
2758
2759 return $ret;
2760 }
File inc/workers.inc.php changed (mode: 100644) (index 0bd3745..4aa8f12)
... ... $INC = isset($INC) ? $INC : dirname(__FILE__);
3 3 require_once($INC . '/events.inc.php'); require_once($INC . '/events.inc.php');
4 4 require_once($INC . '/builder.inc.php'); require_once($INC . '/builder.inc.php');
5 5 require_once($INC . '/keys.inc.php'); require_once($INC . '/keys.inc.php');
6 require_once($INC . '/graph.inc.php');
6 7
7 8 $rg_worker_error = ''; $rg_worker_error = '';
8 9
 
... ... function rg_worker_remove($db, $uid, $list)
512 513 return $ret; return $ret;
513 514 } }
514 515
516 /*
517 * Insert worker stats
518 */
519 function rg_worker_stats_insert($db, $worker_id, $ts, $a)
520 {
521 rg_prof_start('worker_stats_insert');
522 rg_log_enter('worker_stats_insert: worker_id=' . $worker_id
523 . ' ts=' . $ts . ' event=' . rg_array2string($a));
524
525 $ret = FALSE;
526 while (1) {
527 $params = array('itime' => $ts,
528 'worker_id' => $worker_id,
529 'data' => rg_serialize($a)
530 );
531 $sql = 'INSERT INTO worker_stats_' . gmdate('Y_m', $ts)
532 . ' (worker_id, itime, data)'
533 . ' VALUES (@@worker_id@@, @@itime@@, @@data@@)';
534 $res = rg_sql_query_params($db, $sql, $params);
535 if ($res === FALSE)
536 break;
537
538 rg_sql_free_result($res);
539 $ret = TRUE;
540 break;
541 }
542
543 rg_log_exit();
544 rg_prof_end('worker_stats_insert');
545 return $ret;
546 }
547
548 /*
549 * Helper for rg_worker_data
550 */
551 function rg_worker_data_decode_load($data)
552 {
553 $r = rg_unserialize($data);
554 if ($r === FALSE)
555 return FALSE;
556
557 return $r['load'];
558 }
559
560 /*
561 * Helper for rg_worker_data
562 */
563 function rg_worker_data_decode_jobs($data)
564 {
565 $r = rg_unserialize($data);
566 if ($r === FALSE)
567 return FALSE;
568
569 return $r['jobs'];
570 }
571
572 /*
573 * Loads data for graphs
574 * @unit - interval on which a sum is made
575 */
576 function rg_worker_data($db, $type, $worker_id, $start, $end, $unit, $mode)
577 {
578 $params = array(
579 'worker_id' => $worker_id,
580 'start' => $start,
581 'end' => $end
582 );
583 $q = 'SELECT data AS value, itime FROM worker_stats'
584 . ' WHERE worker_id = @@worker_id@@'
585 . ' AND itime >= @@start@@ AND itime <= @@end@@';
586
587 switch ($type) {
588 case 'load':
589 $func = 'rg_worker_data_decode_load';
590 break;
591
592 case 'jobs':
593 $func = 'rg_worker_data_decode_jobs';
594 break;
595
596 default:
597 rg_internal_error('invalid type');
598 return FALSE;
599 }
600
601 $ret = rg_graph_query($db, $start, $end, $unit, $mode, $q, $params,
602 $func);
603 if ($ret === FALSE)
604 rg_workers_set_error(rg_graph_error());
605
606 return $ret;
607 }
608
609 /*
610 * Generate graphs(s) for workers
611 * @r - the result of rg_worker_list function
612 * Returns a new 'r' augumented with the graphs.
613 */
614 function rg_worker_graphs($db, $r)
615 {
616 rg_log_ml('DEBUG: worker_graphs: ' . print_r($r, TRUE));
617
618 $period = 'hour';
619 $start = gmmktime(0, 0, 0, gmdate('m') - 1, gmdate('d'), gmdate('Y'));
620 $end = gmmktime(0, 0, 0, gmdate('m'), gmdate('d') + 1, gmdate('Y')) - 1;
621
622 $subtitle = gmdate('Y-m-d H:i:s', $start)
623 . ' - ' . gmdate('Y-m-d H:i:s', $end) . " UTC\n";
624
625 // TODO: set this as default?
626 $a = array(
627 'bg_style' => 'fill: #bdf',
628 'h' => 150,
629 'title_style' => 'color: #fff',
630 'subtitle' => $subtitle,
631 'subtitle_style' => 'color: #00f; font-size: 8pt',
632 'data_style' => 'fill: #ffa',
633 'data_line_style' => 'fill: #f00',
634 'data_line_width' => 1,
635 'gap' => 0,
636 'footer_style' => 'font-color: #000; font-size: 8pt'
637 );
638
639 // TODO: it is not effcient to run the same query two times!
640 foreach ($r as $id => $wi) {
641 $b = $a;
642 $b['title'] = 'Worker [' . $wi['name'] . '] load';
643 $g = rg_worker_data($db, 'load', $id, $start, $end, $period, 'avg');
644 if ($g === FALSE) {
645 $r[$id]['graph_load'] = 'Error generating graph: '
646 . rg_worker_error() . '!';
647 } else {
648 $b['data'] = $g;
649 $r[$id]['HTML:graph_load'] = rg_graph($b);
650 }
651
652 $b = $a;
653 $b['title'] = 'Worker [' . $wi['name'] . '] jobs';
654 $g = rg_worker_data($db, 'jobs', $id, $start, $end, $period, 'sum');
655 if ($g === FALSE) {
656 $r[$id]['graph_jobs'] = 'Error generating graph: '
657 . rg_worker_error() . '!';
658 } else {
659 $b['data'] = $g;
660 $r[$id]['HTML:graph_jobs'] = rg_graph($b);
661 }
662 }
663
664 return $r;
665 }
515 666
516 667 /* /*
517 668 * Workers - add/edit * Workers - add/edit
 
... ... function rg_worker_list_high_level($db, $rg, $paras)
665 816 $ret .= rg_template('user/settings/workers/list_err.html', $ret .= rg_template('user/settings/workers/list_err.html',
666 817 $rg, TRUE /*xss*/); $rg, TRUE /*xss*/);
667 818 } else { } else {
819 $r = rg_worker_graphs($db, $r);
668 820 $rg['rg_form_token'] = rg_token_get($db, $rg, 'workers_list'); $rg['rg_form_token'] = rg_token_get($db, $rg, 'workers_list');
669 821 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
670 822 $ret .= rg_template_table('user/settings/workers/list', $r, $rg); $ret .= rg_template_table('user/settings/workers/list', $r, $rg);
File root/index.php changed (mode: 100644) (index 616c36b..bfc0c5d)
... ... set_time_limit(30);
6 6 $peak0 = memory_get_peak_usage(); $peak0 = memory_get_peak_usage();
7 7
8 8 $rg = array(); $rg = array();
9 $rg['start'] = microtime(TRUE);
9 10
10 11 require_once("/etc/rocketgit/config.php"); require_once("/etc/rocketgit/config.php");
11 12 $INC = dirname(__FILE__) . "/../inc"; $INC = dirname(__FILE__) . "/../inc";
 
... ... rg_prof_start("MAIN");
36 37 rg_log_set_file($rg_log_dir . "/web.log"); rg_log_set_file($rg_log_dir . "/web.log");
37 38
38 39 // database connection // database connection
39 rg_sql_app("rg-web");
40 rg_sql_app('rg-web-' . $rg_log_sid);
40 41 $db = rg_sql_open($rg_sql); $db = rg_sql_open($rg_sql);
41 42
42 43 // Store configuration into 'rg' // Store configuration into 'rg'
 
... ... $rg['rg_redirect_html'] = 0;
54 55 $rg['rg_theme_url'] = '/themes/' . rawurlencode($rg_theme); $rg['rg_theme_url'] = '/themes/' . rawurlencode($rg_theme);
55 56 $rg['login_ui'] = rg_user_empty(); $rg['login_ui'] = rg_user_empty();
56 57 $rg['target_ui'] = array("ok" => 1, "exists" => 0, "uid" => 0); $rg['target_ui'] = array("ok" => 1, "exists" => 0, "uid" => 0);
58 $rg['page_ui'] = array("ok" => 1, "exists" => 0, "uid" => 0);
57 59 $rg['ri'] = array("repo_id" => 0, "uid" => 0); $rg['ri'] = array("repo_id" => 0, "uid" => 0);
58 60 $rg['bug'] = array("bug_id" => 0); $rg['bug'] = array("bug_id" => 0);
59 61 $rg['https'] = strcmp(rg_var_str('HTTPS'), 'on') == 0 ? 1 : 0; $rg['https'] = strcmp(rg_var_str('HTTPS'), 'on') == 0 ? 1 : 0;
60 $rg['debug'] = rg_state_get($db, 'debug');
61 62
62 63
63 64 $sparas = rg_var_str('SCRIPT_NAME'); $sparas = rg_var_str('SCRIPT_NAME');
64 rg_log("DEBUG: sparas=$sparas");
65 rg_log('DEBUG: ' . $_SERVER['REQUEST_METHOD'] . ' sparas=' . $sparas);
65 66 $rg['current_url'] = rawurlencode($sparas); $rg['current_url'] = rawurlencode($sparas);
66 67 $rg['url'] = '/op'; $rg['url'] = '/op';
67 68 $paras = explode("/", trim($sparas, "/")); $paras = explode("/", trim($sparas, "/"));
 
... ... $user = ""; $repo = ""; $organization = 0; // TODO: those are really used?
83 84
84 85 $rg['ua'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ""; $rg['ua'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : "";
85 86 $rg['ip'] = isset($_SERVER['REMOTE_ADDR']) ? rg_fix_ip($_SERVER['REMOTE_ADDR']) : ''; $rg['ip'] = isset($_SERVER['REMOTE_ADDR']) ? rg_fix_ip($_SERVER['REMOTE_ADDR']) : '';
87 $rg['referer'] = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
86 88 $req = $_REQUEST; $req = $_REQUEST;
87 89 if (isset($req['pass']) || isset($req['init::pass']) || isset($req['init::pass2'])) if (isset($req['pass']) || isset($req['init::pass']) || isset($req['init::pass2']))
88 90 $req['pass'] = '*****'; $req['pass'] = '*****';
 
... ... if (isset($req['pass1']))
92 94 $req['pass1'] = '*****'; $req['pass1'] = '*****';
93 95 if (isset($req['pass2'])) if (isset($req['pass2']))
94 96 $req['pass2'] = '*****'; $req['pass2'] = '*****';
95 rg_log("DEBUG: _REQUEST: " . rg_array2string($req));
96 rg_log("DEBUG: _COOKIE: " . rg_array2string($_COOKIE));
97 if (!empty($req))
98 rg_log("DEBUG: _REQUEST: " . rg_array2string($req));
99 if (!empty($_COOKIE))
100 rg_log("DEBUG: _COOKIE: " . rg_array2string($_COOKIE));
97 101 rg_log($rg['ip'] . " ver=$rocketgit_version"); rg_log($rg['ip'] . " ver=$rocketgit_version");
98 102
99 103 // Try to detect if we cloning by http(s) // Try to detect if we cloning by http(s)
 
... ... rg_log_ml('_SERVER: ' . print_r($_SERVER, TRUE));
101 105 $rg['ct'] = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : ''; $rg['ct'] = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '';
102 106
103 107
104 // Force state loading, for sure we will need it
105 rg_cache_get('state');
108 $rg['debug'] = rg_state_get($db, 'debug');
106 109
107 110 $r = rg_struct_ok($db); $r = rg_struct_ok($db);
108 111 if ($r === FALSE) { if ($r === FALSE) {
 
... ... $rg['https_allow'] = $https_allow;
171 174 $rg['base_url'] = rg_base_url(); $rg['base_url'] = rg_base_url();
172 175
173 176
177 $skip_etag_and_compression = FALSE;
178
174 179 // Is it a http push/fetch? // Is it a http push/fetch?
175 180 $r = rg_user_http_git($db, $rg, $paras); $r = rg_user_http_git($db, $rg, $paras);
176 181 if ($r === TRUE) { if ($r === TRUE) {
177 rg_prof_end("MAIN");
178 rg_prof_log();
179 exit(0);
180 }
182 rg_stats_conns_set('type', 'git-over-http');
183 $skip_etag_and_compression = TRUE;
184 } else if (strcmp($_op, 'api') == 0) { // API dispatch
185 rg_stats_conns_set('type', 'api-over-http');
181 186
182 // API dispatch
183 if (strcmp($_op, 'api') == 0) {
184 187 // https://en.wikipedia.org/wiki/Cross-origin_resource_sharing // https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
185 188 header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Origin: *');
186 189 header('Access-Control-Allow-Headers: Authorization'); header('Access-Control-Allow-Headers: Authorization');
 
... ... if (strcmp($_op, 'api') == 0) {
194 197 $_key = trim($_t[1]); $_key = trim($_t[1]);
195 198 else else
196 199 $_key = ''; $_key = '';
197 rg_log('api user=[' . $_user . '] key=[' . $_key . ']!');
198 $body = '';
200 rg_log('api user=[' . $_user . '] key=[' . $_key . ']');
201
199 202 while (1) { while (1) {
200 $ui = rg_user_info($db, 0, $_user, '');
201 if ($ui['ok'] != 1) {
202 $body = array('error' => rg_user_error());
203 echo json_encode($body, JSON_PRETTY_PRINT) . "\n";
203 $key_id = FALSE;
204
205 $rg['login_ui'] = rg_user_info($db, 0, $_user, '');
206 if ($rg['login_ui']['ok'] != 1) {
207 $e = array('error' => rg_user_error());
204 208 break; break;
205 209 } }
206 if ($ui['exists'] != 1) {
207 $body = array('error' => 'invalid user or apikey');
208 echo json_encode($body, JSON_PRETTY_PRINT) . "\n";
210
211 if ($rg['login_ui']['exists'] != 1) {
212 $e = array('error' => 'invalid user or apikey');
209 213 break; break;
210 214 } }
211 215
212 $key_id = rg_ak_valid($db, $ui['uid'], $_key);
216 $key_id = rg_ak_valid($db, $rg['login_ui']['uid'], $_key);
213 217 if ($key_id === FALSE) { if ($key_id === FALSE) {
214 $body = array('error' => 'invalid user or apikey');
215 echo json_encode($body, JSON_PRETTY_PRINT) . "\n";
218 $e = array('error' => 'invalid user or apikey');
216 219 break; break;
217 220 } }
218 221
219 $post = @file_get_contents("php://input");
220 rg_log('post=' . $post);
222 $post = @file_get_contents('php://input');
223 rg_log('post: ' . $post);
221 224
222 $d = @json_decode($post);
223 if ($d === NULL) {
224 rg_log('error parsing!');
225 $body = array('error' => json_last_error_msg());
226 echo json_encode($body, JSON_PRETTY_PRINT) . "\n";
225 $json = @json_decode($post, TRUE);
226 if ($json === NULL) {
227 rg_log('error parsing json ('
228 . json_last_error_msg() . '): [' . $post . ']');
229 $e = array('error' => json_last_error_msg());
227 230 break; break;
228 231 } }
229 232
230 rg_ak_update_use($db, $ui['uid'], $key_id, $rg['ip'], $post);
231
232 // we need to transform the object 'd' into an array
233 $d2 = array();
234 foreach ($d as $k => $v)
235 $d2[$k] = $v;
236 $d2['connect_uid'] = $ui['uid'];
237 $d2['ip'] = $rg['ip'];
238 echo rg_api($db, $d2);
233 $e = rg_api($db, $rg, $json);
239 234 break; break;
240 235 } }
236 $_c = json_encode($e, JSON_PRETTY_PRINT) . "\n";
237 } else { // normal web request
238 rg_stats_conns_set('type', 'http');
239
240 rg_user_login_by_sid($db, $rg);
241 rg_log("After login_by_sid, login_ui=" . rg_array2string($rg['login_ui']));
242 // If user provided an old/expired sid, we generate a new one, pre-login
243 if (($rg['login_ui']['uid'] == 0) && (strncmp($rg['sid'], "X", 1) != 0))
244 $rg['sid'] = "";
245 if (empty($rg['sid'])) {
246 $rg['sid'] = rg_user_set_session_cookie($db, 0 /*uid*/, 600,
247 FALSE /*lock_ip*/, $rg['https'], $rg['hostname']);
248 rg_log("User has no sid, generate one [" . $rg['sid'] . "]");
249 }
241 250
242 rg_prof_end("MAIN");
243 rg_prof_log();
244 exit(0);
245 }
246
247 rg_user_login_by_sid($db, $rg);
248 rg_log("After login_by_sid, login_ui=" . rg_array2string($rg['login_ui']));
249 // If user provided an old/expired sid, we generate a new one, pre-login
250 if (($rg['login_ui']['uid'] == 0) && (strncmp($rg['sid'], "X", 1) != 0))
251 $rg['sid'] = "";
252 if (empty($rg['sid'])) {
253 $rg['sid'] = rg_user_set_session_cookie($db, 0 /*uid*/, 600,
254 FALSE /*lock_ip*/, $rg['https'], $rg['hostname']);
255 rg_log("User has no sid, generate one [" . $rg['sid'] . "]");
256 }
257
258 $body = "";
251 $body = "";
259 252
260 // Some variables from the database
261 $rg['first_install_text'] = "?";
253 // Some variables from the database
254 $rg['first_install_text'] = "?";
262 255
263 $r = rg_state_get($db, "first_install");
264 if ($r === FALSE) {
265 // Probably we cannot connect to database/cache
266 $body .= rg_template('admin/db_error.html', TRUE /*xss*/);
267 } else if ($r === '') {
268 $body .= rg_init($db, $rg);
269 } else {
270 $rg['first_install_text'] = gmdate("Y-m-d", $r);
256 $r = rg_state_get($db, "first_install");
257 if ($r === FALSE) {
258 // Probably we cannot connect to database/cache
259 $body .= rg_template('admin/db_error.html', TRUE /*xss*/);
260 } else if ($r === '') {
261 $body .= rg_init($db, $rg);
262 } else {
263 $rg['first_install_text'] = gmdate("Y-m-d", $r);
271 264
272 rg_log("Dispatching to [$_op]");
273 include($INC . "/dispatch/dispatch.php");
274 }
265 rg_log("Dispatching to [$_op]");
266 include($INC . "/dispatch/dispatch.php");
267 }
275 268
276 if ($rg['login_ui']['uid'] > 0) {
277 $rg['logout_token'] = rg_token_get($db, $rg, 'logout');
278 } else {
279 $rg['logout_token'] = '';
280 }
269 if ($rg['login_ui']['uid'] > 0) {
270 $rg['logout_token'] = rg_token_get($db, $rg, 'logout');
271 } else {
272 $rg['logout_token'] = '';
273 }
281 274
282 275
283 // Redirect if http is not allowed and the user is not logged in
284 if (($rg['https'] == 0)
285 && ($rg['login_ui']['uid'] == 0)
286 && (strcmp($http_allow, '0') == 0))
287 rg_redirect(rg_base_url() . $sparas);
276 // Redirect if http is not allowed and the user is not logged in
277 if (($rg['https'] == 0)
278 && ($rg['login_ui']['uid'] == 0)
279 && (strcmp($http_allow, '0') == 0))
280 rg_redirect(rg_base_url() . $sparas);
288 281
289 282
290 $rg['HTML:rg_body'] = $body;
291 $_c = rg_template('index.html', $rg, TRUE /*xss*/);
283 $rg['HTML:rg_body'] = $body;
284 $_c = rg_template('index.html', $rg, TRUE /*xss*/);
292 285
293 // TODO: really?!
294 header('Cache-Control: private, no-cache');
286 rg_stats_conns_set('uid', $rg['page_ui']['uid']);
287 rg_stats_conns_set('repo_id', $rg['ri']['repo_id']);
288 }
295 289
296 // Caching
297 $proto = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : '';
298 if ((strcmp($proto, 'HTTP/1.1') == 0) || (strcmp($proto, 'HTTP/2.0') == 0)) {
299 while (1) {
300 $we_have = sha1($_c);
301 if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
302 $client_have = $_SERVER['HTTP_IF_NONE_MATCH'];
303
304 if (strcmp($client_have, $we_have) == 0) {
305 rg_log('CACHE: Client has the latest version; no need to resend');
306 header($proto . ' 304 Not modified');
307 break;
290 if ($skip_etag_and_compression == FALSE) {
291 // TODO: really?! What about API?
292 header('Cache-Control: private, no-cache');
293
294 // Caching
295 $proto = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : '';
296 if ((strcmp($proto, 'HTTP/1.1') == 0) || (strcmp($proto, 'HTTP/2.0') == 0)) {
297 while (1) {
298 $we_have = sha1($_c);
299 if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
300 $client_have = $_SERVER['HTTP_IF_NONE_MATCH'];
301
302 if (strcmp($client_have, $we_have) == 0) {
303 rg_log('CACHE: Client has the latest version; no need to resend');
304 header($proto . ' 304 Not modified');
305 break;
306 }
308 307 } }
309 }
310 308
311 header('ETag: ' . $we_have);
309 header('ETag: ' . $we_have);
310 rg_web_output($_c);
311 break;
312 }
313 } else {
314 rg_log('WARN: Un-handled protocol [' . $proto . ']');
312 315 rg_web_output($_c); rg_web_output($_c);
313 break;
314 316 } }
315 } else {
316 rg_log('WARN: Un-handled protocol [' . $proto . ']');
317 rg_web_output($_c);
318 317 } }
319 318
320 rg_prof_end("MAIN");
319 rg_prof_end('MAIN');
321 320 rg_prof_log(); rg_prof_log();
322 321
322 fastcgi_finish_request();
323 // Now, answer was delivered to the client, we can do some boring tasks.
324
325 while (strcmp($_op, 'api') == 0) {
326 if ($key_id === FALSE)
327 break;
328
329 rg_ak_update_use($db, $rg['login_ui']['uid'], $key_id,
330 $rg['ip'], $post);
331 break;
332 }
333
334 $list = array('start', 'ip', 'ua', 'referer');
335 foreach ($list as $k)
336 rg_stats_conns_set($k, $rg[$k]);
337 //TODO: lines below override the good ones in case of api calls
338 //rg_stats_conns_set('uid', $rg['ri']['uid']);
339 //rg_stats_conns_set('repo_id', $rg['ri']['repo_id']);
340 rg_stats_conns_set('url', $sparas);
341 rg_stats_conns_insert($db);
342
File root/themes/default/admin/ldap/list/footer.html changed (mode: 100644) (index 584a718..efcfc6b)
1 </tbody>
1 2 </table> </table>
2 3
3 4 <p> <p>
File root/themes/default/admin/ldap/list/header.html changed (mode: 100644) (index 7f3273e..aba0416)
3 3 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
4 4
5 5 <table> <table>
6 <thead>
6 7 <tr> <tr>
7 8 <th>Select</th> <th>Select</th>
8 9 <th>Name</th> <th>Name</th>
 
23 24 <th>CA certificate</th> <th>CA certificate</th>
24 25 <th>Operations</th> <th>Operations</th>
25 26 </tr> </tr>
27 </thead>
26 28
29 <tbody>
File root/themes/default/admin/plans/list/footer.html changed (mode: 100644) (index 485fb8d..b37d407)
1 </tbody>
1 2 </table> </table>
2 3
3 4 <p> <p>
File root/themes/default/admin/plans/list/header.html changed (mode: 100644) (index 40c2b8e..7295c31)
5 5 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
6 6
7 7 <table> <table>
8 <thead>
8 9 <tr> <tr>
9 10 <th>Select</th> <th>Select</th>
10 11 <th>Position</th> <th>Position</th>
 
18 19 <th>Max private repos</th> <th>Max private repos</th>
19 20 <th>Operations</th> <th>Operations</th>
20 21 </tr> </tr>
22 </thead>
21 23
24 <tbody>
File root/themes/default/builder/cmds/footer.html changed (mode: 100644) (index 000ca4b..02ee59f)
1 </tbody>
1 2 </table> </table>
File root/themes/default/builder/cmds/header.html changed (mode: 100644) (index 18d2269..64332e5)
1 1 <table> <table>
2 <thead>
2 3 <tr> <tr>
3 4 <th>Command</th> <th>Command</th>
4 5 <th>Date added (UTC)</th> <th>Date added (UTC)</th>
 
6 7 <th>Elapsed time</th> <th>Elapsed time</th>
7 8 <th>Log</th> <th>Log</th>
8 9 </tr> </tr>
10 </thead>
9 11
12 <tbody>
File root/themes/default/builder/queue/footer.html changed (mode: 100644) (index 02674f3..59cff56)
1 </tbody>
1 2 </table> </table>
2 3
3 4 <p> <p>
File root/themes/default/builder/queue/header.html changed (mode: 100644) (index ef5cb8a..924e2be)
3 3 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
4 4
5 5 <table> <table>
6 <thead>
6 7 <tr> <tr>
7 8 <th>Select</th> <th>Select</th>
8 9 <th>ID</th> <th>ID</th>
 
13 14 <th>Done (UTC)</th> <th>Done (UTC)</th>
14 15 <th>Request & status</th> <th>Request & status</th>
15 16 </tr> </tr>
17 </thead>
16 18
19 <tbody>
File root/themes/default/doc/api.html changed (mode: 100644) (index 6b77ef7..9caad96)
3 3 <div class="islands"> <div class="islands">
4 4 <div class="island_wide"> <div class="island_wide">
5 5 <div class="island_title">Calling API by SSH or by CURL</div> <div class="island_title">Calling API by SSH or by CURL</div>
6 When requesting data by http, use POST not GET.<br />
7 <br />
8
9 Request fields:<br />
10 'cmd' - what command to execute<br />
11 'opaque' - it is passed back in the answer, unaltered.<br />
12 'user/uid' - the target user; if missing, it is the login user.<br />
13 <br />
6 14 Possible commands:<br /> Possible commands:<br />
7 15 <a href="#user_info">user_info</a><br /> <a href="#user_info">user_info</a><br />
8 16 <a href="#user_rights_list">user_rights_list</a><br /> <a href="#user_rights_list">user_rights_list</a><br />
9 17 <a href="#user_ssh_keys_list">user_ssh_keys_list</a><br /> <a href="#user_ssh_keys_list">user_ssh_keys_list</a><br />
10 18 <a href="#user_wh_list">user_wh_list</a><br /> <a href="#user_wh_list">user_wh_list</a><br />
11 <a href="#repo_bug_info">repo_bug_info</a><br />
12 <a href="#repo_bug_list">repo_bug_list</a><br />
13 19 <a href="#repo_list">repo_list</a><br /> <a href="#repo_list">repo_list</a><br />
14 20 <a href="#repo_info">repo_info</a><br /> <a href="#repo_info">repo_info</a><br />
15 <a href="#repo_pr_list">repo_pr_list</a><br />
21 <a href="#repo_bug_list">repo_bug_list</a><br />
22 <a href="#repo_bug_info">repo_bug_info</a><br />
23 <a href="#repo_mr_list">repo_mr_list</a><br />
24 <br />
25
26
27 Example of error:<br />
28 <div class="term">
29 $ curl --header 'Authorization: bla this_is_your_api_key' \
30 --data '{"cmd": "invalid_cmd", "user": "bla"}' \
31 @@base_url@@/op/api
32 $ ssh rocketgit@rocketgit.com api invalid_cmd
33 {
34 "cmd": "invalid_cmd",
35 "error": "invalid command"
36 }
37 </div>
16 38 <br /> <br />
17 39
40
18 41 <a name="user_info"><b>user_info</b></a><br /> <a name="user_info"><b>user_info</b></a><br />
19 42 <b>Description</b>: List information about a user<br /> <b>Description</b>: List information about a user<br />
20 <b>Parameters</b>: user, uid<br />
43 <b>Parameters</b>: user/uid [optional]<br />
21 44 Example: Example:
22 45 <div class="term"> <div class="term">
23 46 $ curl --header 'Authorization: bla this_is_your_api_key' \ $ curl --header 'Authorization: bla this_is_your_api_key' \
 
... ... $ curl --header 'Authorization: bla this_is_your_api_key' \
25 48 @@base_url@@/op/api @@base_url@@/op/api
26 49 $ ssh rocketgit@rocketgit.com api user_info user=bla $ ssh rocketgit@rocketgit.com api user_info user=bla
27 50 { {
51 "cmd": "user_info",
28 52 "ok": 1, "ok": 1,
29 53 "exists": 1, "exists": 1,
30 54 "uid": "846", "uid": "846",
 
... ... $ ssh rocketgit@rocketgit.com api user_info user=bla
32 56 "rights": "C", "rights": "C",
33 57 "homepage": "\/user\/bla", "homepage": "\/user\/bla",
34 58 "username": "bla", "username": "bla",
35 "salt": "3f786850e387550fdab836ed7e6dc881de23001b",
36 "pass": "162b0b32f024...01cc7884a635be",
37 59 "email": "bla@example.com", "email": "bla@example.com",
38 60 "itime": "1440834245", "itime": "1440834245",
39 61 "suspended": null, "suspended": null,
 
... ... $ ssh rocketgit@rocketgit.com api user_info user=bla
41 63 "last_seen": "1464805192", "last_seen": "1464805192",
42 64 "disk_used_mb": null, "disk_used_mb": null,
43 65 "confirmed": "1468297652", "confirmed": "1468297652",
44 "confirm_token": "c215e946b2b15d66d14b",
45 66 "organization": "0", "organization": "0",
46 67 "realname": "my real name", "realname": "my real name",
47 68 "plan_id": "0", "plan_id": "0",
 
... ... $ ssh rocketgit@rocketgit.com api user_info user=bla
53 74 </div> </div>
54 75 <br /> <br />
55 76
77
56 78 <a name="user_rights_list"><b>user_rights_list</b></a><br /> <a name="user_rights_list"><b>user_rights_list</b></a><br />
57 79 <b>Description</b>: Lists user defined rights<br /> <b>Description</b>: Lists user defined rights<br />
58 <b>Parameters</b>: user<br />
80 <b>Parameters</b>: user/uid [optional]<br />
59 81 Example: Example:
60 82 <div class="term"> <div class="term">
61 83 $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \ $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \
62 84 --data '{"cmd": "user_rights_list", "user": "bla"}' \ --data '{"cmd": "user_rights_list", "user": "bla"}' \
63 85 @@base_url@@/op/api @@base_url@@/op/api
64 86 $ ssh rocketgit@rocketgit.com api user_rights_list user=bla $ ssh rocketgit@rocketgit.com api user_rights_list user=bla
65 [
66 {
67 "type": "repo_path",
68 "obj_id": "831",
69 "uid": "0",
70 "rights": "P",
71 "itime": "1450417938",
72 "misc": "",
73 "prio": "100",
74 "who": "846",
75 "right_id": "79",
76 "ip": "",
77 "misc2": "",
78 "description": "dfdsfds",
79 "username": "*",
80 "who_name": "catab",
81 "rights_text": "Push",
82 "itime_text": "2015-12-18 05:52",
83 "ip_nice": "Any",
84 "HTML:description_nlbr": "dfdsfds",
85 "can_be_deleted": 1
86 },
87 ...
88 ]
87 {
88 "cmd": "user_rights_list",
89 "list": [
90 {
91 "type": "repo_path",
92 "obj_id": "831",
93 "uid": "0",
94 "rights": "P",
95 "itime": "1450417938",
96 "misc": "",
97 "prio": "100",
98 "who": "846",
99 "right_id": "79",
100 "ip": "",
101 "misc2": "",
102 "description": "dfdsfds",
103 "username": "*",
104 "who_name": "catab",
105 "rights_text": "Push",
106 "itime_text": "2015-12-18 05:52",
107 "ip_nice": "Any",
108 "HTML:description_nlbr": "dfdsfds",
109 "can_be_deleted": 1
110 },
111 ...
112 ]
113 }
89 114 </div> </div>
90 115 <br /> <br />
91 116
117
92 118 <a name="user_ssh_keys_list"><b>user_ssh_keys_list</b></a><br /> <a name="user_ssh_keys_list"><b>user_ssh_keys_list</b></a><br />
93 119 <b>Description</b>: Lists SSH keys of a user<br /> <b>Description</b>: Lists SSH keys of a user<br />
94 <b>Parameters</b>: user<br />
120 <b>Parameters</b>: user/uid [optional]<br />
95 121 Example: Example:
96 122 <div class="term"> <div class="term">
97 123 $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \ $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \
98 124 --data '{"cmd": "user_ssh_keys_list", "user": "bla"}' \ --data '{"cmd": "user_ssh_keys_list", "user": "bla"}' \
99 125 @@base_url@@/op/api @@base_url@@/op/api
100 126 $ ssh rocketgit@rocketgit.com api user_ssh_keys_list user=bla $ ssh rocketgit@rocketgit.com api user_ssh_keys_list user=bla
101 [
102 {
103 "ok": 1,
104 "type": "ssh-rsa",
105 "comment": "Key for rocketgit - r1i",
106 "key": "AAAAB3NzaC1yc2...yTRiD8gFdg9UT1bw==",
107 "bits": 4096,
108 "fingerprint_md5": "b1:fd:5f:f0:53:f5:9c:31:b2:de:ff:00:1c:f1:c5:61",
109 "fingerprint_sha256": "SNPwFw0Snaz7pdUAFV4Lrf8LFHqx93I7VmW5LsjTlLS0",
110 "key_id": "438",
111 "itime": "2016-01-27 21:11",
112 "first_use": "2016-01-27 21:13",
113 "last_ip": "192.168.79.154",
114 "last_use": "2016-01-29 18:27",
115 "last_cmd": "git-receive-pack '\/user\/catab\/delme10'",
116 "count": "27"
117 },
118 ...
119 ]
127 {
128 "cmd": "user_ssh_keys_list",
129 "list": [
130 {
131 "ok": 1,
132 "type": "ssh-rsa",
133 "comment": "Key for rocketgit - r1i",
134 "key": "AAAAB3NzaC1yc2...yTRiD8gFdg9UT1bw==",
135 "bits": 4096,
136 "fingerprint_md5": "b1:fd:5f:f0:53:f5:9c:31:b2:de:ff:00:1c:f1:c5:61",
137 "fingerprint_sha256": "SNPwFw0Snaz7pdUAFV4Lrf8LFHqx93I7VmW5LsjTlLS0",
138 "key_id": "438",
139 "itime": "2016-01-27 21:11",
140 "first_use": "2016-01-27 21:13",
141 "last_ip": "192.168.79.154",
142 "last_use": "2016-01-29 18:27",
143 "last_cmd": "git-receive-pack '\/user\/catab\/delme10'",
144 "count": "27"
145 },
146 ...
147 ]
148 }
120 149 </div> </div>
121 150 <br /> <br />
122 151
152
123 153 <a name="user_wh_list"><b>user_wh_list</b></a><br /> <a name="user_wh_list"><b>user_wh_list</b></a><br />
124 154 <b>Description</b>: Lists webhooks of a user<br /> <b>Description</b>: Lists webhooks of a user<br />
125 <b>Parameters</b>: user<br />
155 <b>Parameters</b>: user/uid [optional]<br />
126 156 Example: Example:
127 157 <div class="term"> <div class="term">
128 158 $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \ $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \
129 159 --data '{"cmd": "user_wh_list", "user": "bla"}' \ --data '{"cmd": "user_wh_list", "user": "bla"}' \
130 160 @@base_url@@/op/api @@base_url@@/op/api
131 161 $ ssh rocketgit@rocketgit.com api user_wh_list user=bla $ ssh rocketgit@rocketgit.com api user_wh_list user=bla
132 [
133 {
134 "id": "648",
135 "uid": "846",
136 "itime": "1454001110",
137 "description": "Test Slack integration",
138 "add_ip": "192.168.79.154",
139 "last_output": "* Trying ...H5pQ==\r\n\r\nok",
140 "idata": {
141 "debug": "0",
142 "events": "P",
143 "url": "https:\/\/hooks.slack.com\/services\/ID1\/ID2\/ID3",
144 "itype": "2",
145 "client_cert": "",
146 "client_ca_cert": "",
147 "opaque": "",
148 "key": "",
149 "custom_body": "{\n \"cha...host:\"\n}",
150 "events_text": "Push",
151 "itype_text": "Custom (use custom body field)",
152 "HTML:client_cert_short": "n\/a",
153 "HTML:client_ca_cert_short": "n\/a",
154 "HTML:custom_body_nlbr": "{&lt;br \/&gt;... \/&gt;\n}",
155 "HTML:private": "&lt;table ...&lt;\/table&gt;\n"
156 },
157 "htype": "http",
158 "hsubtype": "slack",
159 "flags": "",
160 "refname": "(test1|master)",
161 "repo": ".*10",
162 "itime_nice": "2016-01-28 17:11",
163 "HTML:flags_text": "",
164 "HTML:description_nice": "Test Slack integration",
165 "HTML:last_output_nice": "* Try...\r\nok"
166 },
167 ...
168 ]
169 </div>
170 <br />
171
172 <a name="repo_bug_info"><b>repo_bug_info</b></a><br />
173 <b>Description</b>: Shows information about a bug<br />
174 <b>Parameters</b>: name/repo_id, bug_id<br />
175 Example:
176 <div class="term">
177 $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \
178 --data '{"cmd": "repo_bug_info", "name": "repo1", "bug_id": 2}' \
179 @@base_url@@/op/api
180 $ ssh rocketgit@rocketgit.com api repo_bug_info name=repo1 bug_id=2
181 162 { {
182 "bug_id": "2",
183 "title": "dsdasds",
184 "body": "OS type(s) and version(s)?",
185 "state": "1",
186 "labels": "",
187 "assigned_to": "bla",
188 "assigned_uid": "846",
189 "itime": 1464812804,
190 "utime": 1464812804,
191 "ip": "192.168.79.154",
192 "repo_id": "1088",
193 "uid": "846",
194 "deleted": 0,
195 "ok": 1,
196 "exists": 1,
197 "owner": "catab",
198 "HTML:body_nlbr": "OS type(s) and version(s)?",
199 "creation": "2016-06-01 20:26",
200 "updated": "2016-06-01 20:26",
201 "deleted_text": "",
202 "deleted_who_name": "",
203 "state_text": "Open"
163 "cmd": "user_wh_list",
164 "list": [
165 {
166 "id": "648",
167 "uid": "846",
168 "itime": "1454001110",
169 "description": "Test Slack integration",
170 "add_ip": "192.168.79.154",
171 "last_output": "* Trying ...H5pQ==\r\n\r\nok",
172 "idata": {
173 "debug": "0",
174 "events": "P",
175 "url": "https:\/\/hooks.slack.com\/services\/ID1\/ID2\/ID3",
176 "itype": "2",
177 "client_cert": "",
178 "client_ca_cert": "",
179 "opaque": "",
180 "key": "",
181 "custom_body": "{\n \"cha...host:\"\n}",
182 "events_text": "Push",
183 "itype_text": "Custom (use custom body field)",
184 "HTML:client_cert_short": "n\/a",
185 "HTML:client_ca_cert_short": "n\/a",
186 "HTML:custom_body_nlbr": "{&lt;br \/&gt;... \/&gt;\n}",
187 "HTML:private": "&lt;table ...&lt;\/table&gt;\n"
188 },
189 "htype": "http",
190 "hsubtype": "slack",
191 "flags": "",
192 "refname": "(test1|master)",
193 "repo": ".*10",
194 "itime_nice": "2016-01-28 17:11",
195 "HTML:flags_text": "",
196 "HTML:description_nice": "Test Slack integration",
197 "HTML:last_output_nice": "* Try...\r\nok"
198 },
199 ...
200 ]
204 201 } }
205 202 </div> </div>
206 203 <br /> <br />
207 204
208 <a name="repo_bug_list"><b>repo_bug_list</b></a><br />
209 <b>Description</b>: Lists the bugs<br />
210 <b>Parameters</b>: name, repo_id<br />
205
206 <a name="repo_list"><b>repo_list</b></a><br />
207 <b>Parameters</b>: user/uid [optional]<br />
211 208 Example: Example:
212 209 <div class="term"> <div class="term">
213 $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \
214 --data '{"cmd": "repo_bug_list", "name": "repo1"}' \
215 @@base_url@@/op/api
216 $ ssh rocketgit@rocketgit.com api repo_bug_list name=repo1
217 [
218 "1",
219 "2",
220 "3"
221 ]
222 </div>
223 <br />
224
225 <a name="repo_list"><b>repo_list</b></a><br />
226 <b>Parameters</b>: none<br />
227 Example:
228 <div class="term">
229 210 $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \ $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \
230 211 --data '{"cmd": "repo_list"}' \ --data '{"cmd": "repo_list"}' \
231 212 @@base_url@@/op/api @@base_url@@/op/api
 
... ... $ ssh rocketgit@rocketgit.com api repo_list
238 219 </div> </div>
239 220 <br /> <br />
240 221
222
241 223 <a name="repo_info"><b>repo_info</b></a><br /> <a name="repo_info"><b>repo_info</b></a><br />
242 224 <b>Description</b>: Shows info about a repository<br /> <b>Description</b>: Shows info about a repository<br />
243 <b>Parameters</b>: name, repo_id<br />
225 <b>Parameters</b>: user/uid [optional], repo/repo_id<br />
244 226 Example: Example:
245 227 <div class="term"> <div class="term">
246 228 $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \ $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \
247 --data '{"cmd": "repo_info", "name": "repo1"}' \
229 --data '{"cmd": "repo_info", "repo": "repo1"}' \
248 230 @@base_url@@/op/api @@base_url@@/op/api
249 $ ssh rocketgit@rocketgit.com api repo_info name=repo1
231 $ ssh rocketgit@rocketgit.com api repo_info repo=repo1
250 232 { {
251 233 "repo_id": "769", "repo_id": "769",
252 234 "name": "repo1", "name": "repo1",
 
... ... $ ssh rocketgit@rocketgit.com api repo_info name=repo1
280 262 </div> </div>
281 263 <br /> <br />
282 264
283 <a name="repo_pr_list"><b>repo_pr_list</b></a><br />
265
266 <a name="repo_bug_list"><b>repo_bug_list</b></a><br />
267 <b>Description</b>: Lists the bugs<br />
268 <b>Parameters</b>: user/uid [optional], repo/repo_id<br />
269 Example:
270 <div class="term">
271 $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \
272 --data '{"cmd": "repo_bug_list", "repo": "repo1"}' \
273 @@base_url@@/op/api
274 $ ssh rocketgit@rocketgit.com api repo_bug_list repo=repo1
275 {
276 "cmd": "repo_bug_list",
277 "repo_id": "100",
278 "list": [
279 "1",
280 "2",
281 "3"
282 ]
283 }
284 </div>
285 <br />
286
287
288 <a name="repo_bug_info"><b>repo_bug_info</b></a><br />
289 <b>Description</b>: Shows information about a bug<br />
290 <b>Parameters</b>: user/uid [optional], repo/repo_id, bug_id<br />
291 Example:
292 <div class="term">
293 $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \
294 --data '{"cmd": "repo_bug_info", "repo": "repo1", "bug_id": 2}' \
295 @@base_url@@/op/api
296 $ ssh rocketgit@rocketgit.com api repo_bug_info repo=repo1 bug_id=2
297 {
298 "cmd": "repo_bug_info",
299 "bug_id": "2",
300 "title": "dsdasds",
301 "body": "OS type(s) and version(s)?",
302 "state": "1",
303 "labels": "",
304 "assigned_to": "bla",
305 "assigned_uid": "846",
306 "itime": 1464812804,
307 "utime": 1464812804,
308 "ip": "192.168.79.154",
309 "repo_id": "1088",
310 "uid": "846",
311 "deleted": 0,
312 "ok": 1,
313 "exists": 1,
314 "owner": "catab",
315 "HTML:body_nlbr": "OS type(s) and version(s)?",
316 "creation": "2016-06-01 20:26",
317 "updated": "2016-06-01 20:26",
318 "deleted_text": "",
319 "deleted_who_name": "",
320 "state_text": "Open"
321 }
322 </div>
323 <br />
324
325
326 <a name="repo_mr_list"><b>repo_mr_list</b></a><br />
284 327 <b>Description</b>: Lists the merge requests<br /> <b>Description</b>: Lists the merge requests<br />
285 <b>Parameters</b>: name, repo_id<br />
328 <b>Parameters</b>: user/uid [optional], repo/repo_id<br />
286 329 Example: Example:
287 330 <div class="term"> <div class="term">
288 331 $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \ $ curl --header 'Authorization: put_here_your_username this_is_your_api_key' \
289 --data '{"cmd": "repo_pr_list", "name": "repo1"}' \
332 --data '{"cmd": "repo_mr_list", "repo": "repo1"}' \
290 333 @@base_url@@/op/api @@base_url@@/op/api
291 $ ssh rocketgit@rocketgit.com api repo_pr_list name=repo1
292 [
293 {
294 "repo_id": "769",
295 "itime": "1330296541",
296 "namespace": "rg_b21751c3",
297 "refname": "refs\/heads\/master",
298 "old_rev": "afd1df2940fe440cde9b8ede988ff24c051a10d6",
299 "new_rev": "f919c9bf863471aeb97da6aa2380319a1bee6eda",
300 "done": "0",
301 "ip": "2002:2e66:5950::1",
302 "id": "5",
303 "who": "0"
304 },
305 ...
306 ]
334 $ ssh rocketgit@rocketgit.com api repo_mr_list repo=repo1
335 {
336 "cmd": "repo_mr_list",
337 "repo_id": "100",
338 "list": [
339 {
340 "itime": "1330296541",
341 "namespace": "rg_b21751c3",
342 "refname": "refs\/heads\/master",
343 "old_rev": "afd1df2940fe440cde9b8ede988ff24c051a10d6",
344 "new_rev": "f919c9bf863471aeb97da6aa2380319a1bee6eda",
345 "done": "0",
346 "ip": "2002:2e66:5950::1",
347 "id": "5",
348 "who": "0"
349 },
350 ...
351 ]
352 }
307 353 </div> </div>
308 354 </div> </div>
309 355 </div> </div>
File root/themes/default/hints/repo/clone_owner.html changed (mode: 100644) (index cc6ddf1..4597308)
... ... cd local_project_dir<br />
18 18 git remote set-url origin @@ri::clone_url_http@@<br /> git remote set-url origin @@ri::clone_url_http@@<br />
19 19 # or<br /> # or<br />
20 20 git remote set-url origin @@ri::clone_url_ssh@@<br /> git remote set-url origin @@ri::clone_url_ssh@@<br />
21 git push origin --all<br />
22 git push origin --tags<br />
23 21 </div> </div>
24 22 <br /> <br />
25 23
File root/themes/default/hints/repo/edit_repo_path_rights.html changed (mode: 100644) (index 8fdc968..3682d72)
1 1 <br /> <br />
2 2 Examples: Examples:
3 3 <table> <table>
4 <thead>
4 5 <tr> <tr>
5 6 <th>User</th> <th>User</th>
6 7 <th>Path</th> <th>Path</th>
7 8 <th>Right</th> <th>Right</th>
8 9 <th>Description</th> <th>Description</th>
9 10 </tr> </tr>
11 </thead>
10 12
13 <tbody>
11 14 <tr> <tr>
12 15 <td>*</td><td>.*\.exe</td><td>no rights selected</td> <td>*</td><td>.*\.exe</td><td>no rights selected</td>
13 16 <td>No user is allowed to push .exe files</td> <td>No user is allowed to push .exe files</td>
 
... ... Examples:
30 33 <td>This is a drop all rule. Can be used, for example, to block <td>This is a drop all rule. Can be used, for example, to block
31 34 all the rules that might follow.</td> all the rules that might follow.</td>
32 35 </tr> </tr>
36 </tbody>
33 37 </table> </table>
File root/themes/default/hints/repo/edit_repo_refs_rights.html changed (mode: 100644) (index ceb982d..3378a38)
... ... automatically prepended.<br />
15 15
16 16 Examples:<br /> Examples:<br />
17 17 <table> <table>
18 <thead>
18 19 <tr> <tr>
19 20 <th>User</th> <th>User</th>
20 21 <th>Reference</th> <th>Reference</th>
21 22 <th>Rights</th> <th>Rights</th>
22 23 <th>Description</th> <th>Description</th>
23 24 </tr> </tr>
25 </thead>
24 26
27 <tbody>
25 28 <tr> <tr>
26 29 <td>fred</td><td>users/secret</td><td>no rights selected</td> <td>fred</td><td>users/secret</td><td>no rights selected</td>
27 30 <td>User fred cannot push into /refs/heads/users/secret reference</td> <td>User fred cannot push into /refs/heads/users/secret reference</td>
 
... ... Examples:<br />
49 52 <td>This is a drop all rule. Can be used, for example, to block <td>This is a drop all rule. Can be used, for example, to block
50 53 all the rules that might follow.</td> all the rules that might follow.</td>
51 54 </tr> </tr>
55 </tbody>
52 56 </table> </table>
File root/themes/default/main.css changed (mode: 100644) (index 6c2c618..cd26f5f)
... ... th, td {
31 31 border: 1px solid #aaa; border: 1px solid #aaa;
32 32 } }
33 33
34 thead tr {
35 background-color: #ddd;
36 }
37
38 tbody tr:nth-child(even) {
39 background-color: #e9e9e9;
40 }
41
34 42 a { a {
35 43 text-decoration: none; text-decoration: none;
36 44 } }
37 45
38 46 .xcode { .xcode {
39 47 border-left: 4px solid #f00; border-left: 4px solid #f00;
40 font-size: 10pt;
48 font-size: 9pt;
41 49 margin: 5px; margin: 5px;
42 50 padding-left: 5px; padding-left: 5px;
43 51 font-family: monospace; font-family: monospace;
 
... ... x.buttons form input[type="submit"], x.buttons form input, x.buttons form select
321 329
322 330 .repo_desc { .repo_desc {
323 331 font-size: 10pt; font-size: 10pt;
324 color: #888;
332 color: #333;
325 333 margin: 3px 0px; margin: 3px 0px;
326 334 } }
327 335
File root/themes/default/repo/bug/list/footer.html changed (mode: 100644) (index 000ca4b..02ee59f)
1 </tbody>
1 2 </table> </table>
File root/themes/default/repo/bug/list/header.html changed (mode: 100644) (index ae04d36..85c657a)
1 1 <table> <table>
2 <thead>
2 3 <tr> <tr>
3 4 <th>ID</th> <th>ID</th>
4 5 <th>Creation date (UTC)</th> <th>Creation date (UTC)</th>
 
8 9 <th>Assigned to</th> <th>Assigned to</th>
9 10 <th>Last update</th> <th>Last update</th>
10 11 </tr> </tr>
12 </thead>
11 13
14 <tbody>
File root/themes/default/repo/cl/list/footer.html changed (mode: 100644) (index 000ca4b..02ee59f)
1 </tbody>
1 2 </table> </table>
File root/themes/default/repo/cl/list/header.html changed (mode: 100644) (index 73a377b..05331a4)
1 1 <b>Labels associated with this commit:</b><br /> <b>Labels associated with this commit:</b><br />
2 2 <table> <table>
3 <thead>
3 4 <tr> <tr>
4 5 <th>Date/time (UTC)</th> <th>Date/time (UTC)</th>
5 6 <th>Type</th> <th>Type</th>
6 7 <th>Misc</th> <th>Misc</th>
7 8 <th>Labels</th> <th>Labels</th>
8 9 </tr> </tr>
10 </thead>
9 11
12 <tbody>
File root/themes/default/repo/fstat/footer.html changed (mode: 100644) (index 000ca4b..02ee59f)
1 </tbody>
1 2 </table> </table>
File root/themes/default/repo/fstat/header.html changed (mode: 100644) (index 73eefdd..f157fab)
1 1 <table> <table>
2 <thead>
2 3 <tr> <tr>
3 4 <th>File</th> <th>File</th>
4 5 <th>Lines added</th> <th>Lines added</th>
5 6 <th>Lines deleted</th> <th>Lines deleted</th>
6 7 </tr> </tr>
8 </thead>
9
10 <tbody>
File root/themes/default/repo/history/footer.html changed (mode: 100644) (index 000ca4b..02ee59f)
1 </tbody>
1 2 </table> </table>
File root/themes/default/repo/history/header.html changed (mode: 100644) (index c0f66ae..ce1c6d8)
1 1 <table> <table>
2 <thead>
2 3 <tr> <tr>
3 4 <th>Date (UTC)</th> <th>Date (UTC)</th>
4 5 <th>User</th> <th>User</th>
5 6 <th>Event</th> <th>Event</th>
6 7 </tr> </tr>
8 </thead>
9
10 <tbody>
File root/themes/default/repo/list/footer.html changed (mode: 100644) (index 000ca4b..02ee59f)
1 </tbody>
1 2 </table> </table>
File root/themes/default/repo/list/header.html changed (mode: 100644) (index 3b0bba8..6592042)
1 1 <table> <table>
2 <thead>
2 3 <tr> <tr>
3 4 <th>User / repo name</th> <th>User / repo name</th>
4 5 <th>Description</th> <th>Description</th>
 
8 9 <th>License</th> <th>License</th>
9 10 <th>Disk used</th> <th>Disk used</th>
10 11 </tr> </tr>
12 </thead>
13
14 <tbody>
File root/themes/default/repo/log/footer.html changed (mode: 100644) (index 4518f02..a572053)
1 </tbody>
1 2 </table> </table>
2 3 </div> </div>
3 4
File root/themes/default/repo/log/header.html changed (mode: 100644) (index d2f8f2c..08d8f5f)
2 2
3 3 <span><b>List of commits</b>:</span> <span><b>List of commits</b>:</span>
4 4 <table class="table_log"> <table class="table_log">
5 <thead>
5 6 <tr> <tr>
6 7 <th>Subject</th> <th>Subject</th>
7 8 <th>Hash</th> <th>Hash</th>
8 9 <th>Author</th> <th>Author</th>
9 10 <th>Date (UTC)</th> <th>Date (UTC)</th>
10 11 </tr> </tr>
12 </thead>
11 13
14 <tbody>
File root/themes/default/repo/mr/list/footer.html changed (mode: 100644) (index 000ca4b..02ee59f)
1 </tbody>
1 2 </table> </table>
File root/themes/default/repo/mr/list/header.html changed (mode: 100644) (index 27faab3..f48e044)
1 1 <table> <table>
2 <thead>
2 3 <tr> <tr>
3 4 <th>ID</th> <th>ID</th>
4 5 <th>Date / time</th> <th>Date / time</th>
 
9 10 @@if("@@mr::op@@" == "closed"){{<th>Done</th>}} @@if("@@mr::op@@" == "closed"){{<th>Done</th>}}
10 11 @@if(@@can_admin@@ == 1){{<th>IP</th>}} @@if(@@can_admin@@ == 1){{<th>IP</th>}}
11 12 </tr> </tr>
13 </thead>
12 14
15 <tbody>
File root/themes/default/repo/stats/authors/footer.html changed (mode: 100644) (index 000ca4b..02ee59f)
1 </tbody>
1 2 </table> </table>
File root/themes/default/repo/stats/authors/header.html changed (mode: 100644) (index f1fb4c9..11b83dc)
1 1 <br /> <br />
2 2
3 3 <table> <table>
4 <thead>
4 5 <tr> <tr>
5 6 <th>Author</th> <th>Author</th>
6 7 <th>Commits</th> <th>Commits</th>
 
9 10 <th>First commit</th> <th>First commit</th>
10 11 <th>Last commit</th> <th>Last commit</th>
11 12 </tr> </tr>
13 </thead>
14
15 <tbody>
File root/themes/default/repo/tree/footer.html changed (mode: 100644) (index 000ca4b..02ee59f)
1 </tbody>
1 2 </table> </table>
File root/themes/default/repo/tree/header.html changed (mode: 100644) (index c97773a..2aef16f)
1 1 <br /> <br />
2 2 <table> <table>
3 <thead>
3 4 <tr> <tr>
4 5 <th>Mode</th> <th>Mode</th>
5 6 <th>Type</th> <th>Type</th>
 
7 8 <th>Ref</th> <th>Ref</th>
8 9 <th>File</th> <th>File</th>
9 10 </tr> </tr>
11 </thead>
12
13 <tbody>
File root/themes/default/stats/stats.html changed (mode: 100644) (index 88ea680..2a0355c)
8 8
9 9 @@graph::mrs@@ @@graph::mrs@@
10 10
11 @@graph::requests@@
12
11 13 @@graph::repo_history@@ @@graph::repo_history@@
12 14
13 15 @@graph::keys@@ @@graph::keys@@
File root/themes/default/user/keys/list/footer.html changed (mode: 100644) (index b63f104..774c516)
1 </tbody>
1 2 </table> </table>
2 3
3 4 <p> <p>
File root/themes/default/user/keys/list/header.html changed (mode: 100644) (index caf91a5..750638c)
5 5 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
6 6
7 7 <table> <table>
8 <thead>
8 9 <tr> <tr>
9 10 <th>Select</th> <th>Select</th>
10 11 <th>Upload date (UTC)</th> <th>Upload date (UTC)</th>
 
17 18 <th>Last command</th> <th>Last command</th>
18 19 <th>Count</th> <th>Count</th>
19 20 </tr> </tr>
21 </thead>
20 22
23 <tbody>
File root/themes/default/user/repo/rights/list_repo/footer.html changed (mode: 100644) (index e55cbdd..9d188fc)
1 </tbody>
1 2 </table> </table>
2 3
3 4 <p> <p>
File root/themes/default/user/repo/rights/list_repo/header.html changed (mode: 100644) (index 6b221d0..f6b20b5)
5 5 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
6 6
7 7 <table> <table>
8 <thead>
8 9 <tr> <tr>
9 10 <th>Select</th> <th>Select</th>
10 11 <th>Priority</th> <th>Priority</th>
 
16 17 <th>Description</th> <th>Description</th>
17 18 <th>Operations</th> <th>Operations</th>
18 19 </tr> </tr>
20 <thead>
21
22 <tbody>
File root/themes/default/user/repo/rights/list_repo_path/footer.html changed (mode: 100644) (index e55cbdd..9d188fc)
1 </tbody>
1 2 </table> </table>
2 3
3 4 <p> <p>
File root/themes/default/user/repo/rights/list_repo_path/header.html changed (mode: 100644) (index a6c317b..3b85bf4)
5 5 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
6 6
7 7 <table> <table>
8 <thead>
8 9 <tr> <tr>
9 10 <th>Select</th> <th>Select</th>
10 11 <th>Priority</th> <th>Priority</th>
 
17 18 <th>Description</th> <th>Description</th>
18 19 <th>Operations</th> <th>Operations</th>
19 20 </tr> </tr>
21 </thead>
22
23 <tbody>
File root/themes/default/user/repo/rights/list_repo_refs/footer.html changed (mode: 100644) (index e55cbdd..9d188fc)
1 </tbody>
1 2 </table> </table>
2 3
3 4 <p> <p>
File root/themes/default/user/repo/rights/list_repo_refs/header.html changed (mode: 100644) (index b009d51..131d711)
5 5 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
6 6
7 7 <table> <table>
8 <thead>
8 9 <tr> <tr>
9 10 <th>Select</th> <th>Select</th>
10 11 <th>Priority</th> <th>Priority</th>
 
17 18 <th>Description</th> <th>Description</th>
18 19 <th>Operations</th> <th>Operations</th>
19 20 </tr> </tr>
21 </thead>
22
23 <tbody>
File root/themes/default/user/settings/apikeys/hints.html changed (mode: 100644) (index 2bcf3ee..b89fb41)
... ... API keys are used to access RocketGit's API by HTTP(S).<br />
3 3 Check <a href="/op/doc/api">API documentation</a> for more info.<br /> Check <a href="/op/doc/api">API documentation</a> for more info.<br />
4 4 Example: Example:
5 5 <div class="term"> <div class="term">
6 $ curl --header 'Authorization: @@login_ui::username@@ insert_here_the_key' \
6 $ curl --header 'Authorization: @@login_ui::username@@ put_here_the_apikey' \
7 7 --data '{"cmd": "user_info", "user": "@@login_ui::username@@"}' \ --data '{"cmd": "user_info", "user": "@@login_ui::username@@"}' \
8 8 @@base_url@@/op/api @@base_url@@/op/api
9 9
File root/themes/default/user/settings/apikeys/list/footer.html changed (mode: 100644) (index b63f104..774c516)
1 </tbody>
1 2 </table> </table>
2 3
3 4 <p> <p>
File root/themes/default/user/settings/apikeys/list/header.html changed (mode: 100644) (index 5ee5b72..3d23ccb)
6 6 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
7 7
8 8 <table> <table>
9 <thead>
9 10 <tr> <tr>
10 11 <th>Select</th> <th>Select</th>
11 12 <th>Upload date (UTC)</th> <th>Upload date (UTC)</th>
 
16 17 <th>Last command</th> <th>Last command</th>
17 18 <th>Count</th> <th>Count</th>
18 19 </tr> </tr>
20 </thead>
19 21
22 <tbody>
File root/themes/default/user/settings/totp/list/footer.html changed (mode: 100644) (index 57cd6b7..467afa4)
1 </tbody>
1 2 </table> </table>
2 3
3 4 <p> <p>
File root/themes/default/user/settings/totp/list/header.html changed (mode: 100644) (index aadb70b..e7f571b)
6 6 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
7 7
8 8 <table> <table>
9 <thead>
9 10 <tr> <tr>
10 11 <th>Select</th> <th>Select</th>
11 12 <th>Name</th> <th>Name</th>
 
14 15 <th>Confirmed?</th> <th>Confirmed?</th>
15 16 <th>Last time used (UTC)</th> <th>Last time used (UTC)</th>
16 17 </tr> </tr>
18 </thead>
19
20 <tbody>
File root/themes/default/user/settings/totp/sc/list/footer.html changed (mode: 100644) (index 57cd6b7..467afa4)
1 </tbody>
1 2 </table> </table>
2 3
3 4 <p> <p>
File root/themes/default/user/settings/totp/sc/list/header.html changed (mode: 100644) (index 2b50a37..fdd35ef)
6 6 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
7 7
8 8 <table> <table>
9 <thead>
9 10 <tr> <tr>
10 11 <th>Select</th> <th>Select</th>
11 12 <th>Date (UTC)</th> <th>Date (UTC)</th>
12 13 <th>Scratch codes left</th> <th>Scratch codes left</th>
13 14 </tr> </tr>
15 </thead>
16
17 <tbody>
File root/themes/default/user/settings/wh/list/footer.html changed (mode: 100644) (index 57cd6b7..467afa4)
1 </tbody>
1 2 </table> </table>
2 3
3 4 <p> <p>
File root/themes/default/user/settings/wh/list/header.html changed (mode: 100644) (index b3dbc76..56d858a)
3 3 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
4 4
5 5 <table> <table>
6 <thead>
6 7 <tr> <tr>
7 8 <th>ID</th> <th>ID</th>
8 9 <th>Select</th> <th>Select</th>
 
16 17 <th>Flags</th> <th>Flags</th>
17 18 <th>Info</th> <th>Info</th>
18 19 </tr> </tr>
20 </thead>
21
22 <tbody>
File root/themes/default/user/settings/wh/plugins_list/footer.html changed (mode: 100644) (index 27bf87e..3506766)
1 </tbody>
1 2 </table> </table>
2 3
3 4 </div> </div>
File root/themes/default/user/settings/wh/plugins_list/header.html changed (mode: 100644) (index c1bca63..836e840)
2 2
3 3 Please choose one of the following hook types: Please choose one of the following hook types:
4 4 <table> <table>
5 <thead>
5 6 <tr> <tr>
6 7 <th>Type</th> <th>Type</th>
7 8 <th>Description</th> <th>Description</th>
8 9 <th>Add</th> <th>Add</th>
9 10 </tr> </tr>
11 </thead>
12
13 <tbody>
File root/themes/default/user/settings/workers/list/footer.html changed (mode: 100644) (index e1edf9c..8c4858f)
1 </tbody>
1 2 </table> </table>
2 3
3 4 <p> <p>
File root/themes/default/user/settings/workers/list/header.html changed (mode: 100644) (index 72073f1..8208c8a)
6 6 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
7 7
8 8 <table> <table>
9 <thead>
9 10 <tr> <tr>
10 11 <th>Select</th> <th>Select</th>
11 <th>Add date (UTC)</th>
12 12 <th>Name</th> <th>Name</th>
13 <th>Host</th>
14 <th>Arch</th>
15 <th>Environments</th>
13 <th>Add date (UTC)</th>
14 <th>Host / arch / environments</th>
16 15 <th>Cost</th> <th>Cost</th>
17 16 <th>Max workers</th> <th>Max workers</th>
18 17 <th>Last connect (UTC)</th> <th>Last connect (UTC)</th>
19 18 <th>Last IP</th> <th>Last IP</th>
20 19 <th>Operations</th> <th>Operations</th>
20 <th>Load graph</th>
21 <th>Jobs graph</th>
21 22 </tr> </tr>
23 </thead>
22 24
25 <tbody>
File root/themes/default/user/settings/workers/list/line.html changed (mode: 100644) (index 8ae3ac8..b216c95)
1 1 <tr> <tr>
2 2 <td><input type="checkbox" name="delete_ids[@@id@@]" /></td> <td><input type="checkbox" name="delete_ids[@@id@@]" /></td>
3 <td>@@itime_nice@@</td>
4 3 <td>@@name@@</td> <td>@@name@@</td>
5 <td><small>@@host@@</small></td>
6 <td>@@arch@@</td>
7 <td>@@envs_nice@@</td>
4 <td>@@itime_nice@@</td>
5 <td>@@host@@<br />@@arch@@<br /><small>@@envs_nice@@</small></td>
8 6 <td>@@cost@@</td> <td>@@cost@@</td>
9 7 <td>@@workers@@</td> <td>@@workers@@</td>
10 8 <td>@@last_connect_nice@@</td> <td>@@last_connect_nice@@</td>
11 9 <td>@@last_ip@@</td> <td>@@last_ip@@</td>
12 10 <td><a href="@@url@@/edit/@@id@@">Edit</a></td> <td><a href="@@url@@/edit/@@id@@">Edit</a></td>
11 <td>@@graph_load@@</td>
12 <td>@@graph_jobs@@</td>
13 13 </tr> </tr>
14
File scripts/builder.TODO changed (mode: 100644) (index 3868239..297cf10)
1 1 [ ] Add branch in 'build_jobs' table, to know what branch triggered the build. [ ] Add branch in 'build_jobs' table, to know what branch triggered the build.
2 2 [ ] On success/error, allow the calling of another webhook? [ ] On success/error, allow the calling of another webhook?
3 This way we can build a complex pipe system.
3 This way we can build a complex pipeline.
4 4 [ ] Add an optional timeout for the commands. [ ] Add an optional timeout for the commands.
5 5 [ ] Look at some pipeline presentation to be inspired. [ ] Look at some pipeline presentation to be inspired.
6 6 [ ] Switch to an encrypted channel (https and/or ssh) [ ] Switch to an encrypted channel (https and/or ssh)
File scripts/builder.php changed (mode: 100644) (index d3e26c4..344bb38)
... ... function xdispatch_one($key, $data)
90 90 return; return;
91 91 } }
92 92
93 rg_log_ml('DEBUG: u: ' . print_r($u, TRUE));
93 //rg_log_ml('DEBUG: u: ' . print_r($u, TRUE));
94 94
95 95 if (strcmp($u['op'], 'ANN') == 0) { if (strcmp($u['op'], 'ANN') == 0) {
96 96 $now = time(); $now = time();
 
... ... function xdispatch_one($key, $data)
228 228 } }
229 229
230 230 if (strcmp($u['op'], 'WORKER_STATS') == 0) { if (strcmp($u['op'], 'WORKER_STATS') == 0) {
231 rg_log_ml('Worker stats received TODO');
231 $_x = $u; unset($_x['op']);
232 $_ts = $_x['ts']; unset($_x['ts']);
233 rg_worker_stats_insert($s['db'], $s['worker_id'], $_ts, $_x);
232 234 return; return;
233 235 } }
234 236
File scripts/remote.php changed (mode: 100644) (index 7608b4e..a6329ae)
... ... require_once($INC . "/util.inc.php");
11 11 require_once($INC . "/log.inc.php"); require_once($INC . "/log.inc.php");
12 12 require_once($INC . "/sql.inc.php"); require_once($INC . "/sql.inc.php");
13 13 require_once($INC . "/struct.inc.php"); require_once($INC . "/struct.inc.php");
14 require_once($INC . "/user.inc.php");
14 15 require_once($INC . "/repo.inc.php"); require_once($INC . "/repo.inc.php");
15 16 require_once($INC . "/prof.inc.php"); require_once($INC . "/prof.inc.php");
16 17 require_once($INC . "/ssh.inc.php"); require_once($INC . "/ssh.inc.php");
17 18 require_once($INC . "/keys.inc.php"); require_once($INC . "/keys.inc.php");
18 19 require_once($INC . "/fixes.inc.php"); require_once($INC . "/fixes.inc.php");
19 20 require_once($INC . "/plan.inc.php"); require_once($INC . "/plan.inc.php");
21 require_once($INC . '/stats.inc.php');
20 22 require_once($INC . "/ver.php"); require_once($INC . "/ver.php");
21 23
22 24 rg_prof_start("remote.php"); rg_prof_start("remote.php");
23 25
24 26 rg_log_set_file($rg_log_dir . "/remote.log"); rg_log_set_file($rg_log_dir . "/remote.log");
25 27
28 $rg = array();
29 $rg['start'] = microtime(TRUE);
30 rg_stats_conns_set('start', $rg['start']);
31
26 32 function info($str) function info($str)
27 33 { {
28 34 rg_log("Sending: " . $str); rg_log("Sending: " . $str);
 
... ... rg_log("Start ($rocketgit_version)...");
65 71 $label = @file_get_contents("/proc/self/attr/current"); $label = @file_get_contents("/proc/self/attr/current");
66 72 rg_log("SELINUX: " . $label); rg_log("SELINUX: " . $label);
67 73
68 rg_sql_app("rg-remote");
74 rg_sql_app('rg-remote-' . $rg_log_sid);
69 75 $db = rg_sql_open($rg_sql); $db = rg_sql_open($rg_sql);
70 76 if ($db === FALSE) if ($db === FALSE)
71 77 fatal("Internal error (db)!"); fatal("Internal error (db)!");
 
... ... $login_ui = array('uid' => 0,
91 97 if (isset($_SERVER['SSH_CONNECTION'])) { if (isset($_SERVER['SSH_CONNECTION'])) {
92 98 rg_log("SSH connection: " . $_SERVER['SSH_CONNECTION']); rg_log("SSH connection: " . $_SERVER['SSH_CONNECTION']);
93 99
100 rg_stats_conns_set('type', 'ssh');
101
94 102 // we do not have host info // we do not have host info
95 103 $host = ''; $host = '';
96 104
 
... ... if (isset($_SERVER['SSH_CONNECTION'])) {
116 124
117 125 $ssh_client = getenv("SSH_CLIENT"); $ssh_client = getenv("SSH_CLIENT");
118 126 $_t = explode(" ", $ssh_client); $_t = explode(" ", $ssh_client);
119 $ip = rg_fix_ip($_t[0]);
127 $rg['ip'] = rg_fix_ip($_t[0]);
128 rg_stats_conns_set('ip', $rg['ip']);
120 129
121 130 info('== Welcome to RocketGit! =='); info('== Welcome to RocketGit! ==');
122 info('you are connecting from IP ' . $ip . '.');
131 info('you are connecting from IP ' . $rg['ip'] . '.');
123 132 info('date/time: ' . gmdate('Y-m-d H:i:s') info('date/time: ' . gmdate('Y-m-d H:i:s')
124 133 . ', debug id ' . $rg_log_sid . '.'); . ', debug id ' . $rg_log_sid . '.');
125 134
135 $must_exit = FALSE;
126 136 if (strstr($flags, 'N')) { if (strstr($flags, 'N')) {
127 137 $login_ui = rg_user_info($db, $login_uid, '', ''); $login_ui = rg_user_info($db, $login_uid, '', '');
128 138 if ($login_ui['exists'] != 1) if ($login_ui['exists'] != 1)
 
... ... if (isset($_SERVER['SSH_CONNECTION'])) {
131 141 . $login_ui['username'] . '\'.'); . $login_ui['username'] . '\'.');
132 142
133 143 putenv('ROCKETGIT_SHOW_INFO=0'); putenv('ROCKETGIT_SHOW_INFO=0');
134 }
135 144
136 // Only normal keys can execute some commands
137 if (strstr($flags, 'N'))
138 $must_exit = rg_ssh_dispatch($db, $ip, $login_uid, $cmd_repo);
139 else
140 $must_exit = FALSE;
145 // We assume that the login user is the target user and no repo
146 rg_stats_conns_set('uid', $login_ui['uid']);
147 rg_stats_conns_set('repo_id', 0);
148 rg_stats_conns_set('type', 'ssh');
141 149
142 // Only normal keys can update stats
143 if (strstr($flags, 'N')) {
150 // Only normal keys can execute some commands
151 $must_exit = rg_ssh_dispatch($db, $rg['ip'], $login_ui, $cmd_repo);
152
153 // Only normal keys can update stats
144 154 // We do this operation after dispatch to not impact the latency. // We do this operation after dispatch to not impact the latency.
145 155 // TODO: This should be put in a queue for performance reasons // TODO: This should be put in a queue for performance reasons
146 156 // At the same time, update stats? events? // At the same time, update stats? events?
147 $_r = rg_keys_update_use($db, $login_ui['uid'], $key_id, $ip,
157 $_r = rg_keys_update_use($db, $login_ui['uid'], $key_id, $rg['ip'],
148 158 $cmd_repo); $cmd_repo);
149 159 if ($_r !== TRUE) if ($_r !== TRUE)
150 160 rg_internal_error("Cannot update key last_use!"); rg_internal_error("Cannot update key last_use!");
151 }
152 161
153 if ($must_exit) {
154 rg_prof_end("remote.php");
155 rg_prof_log();
156 exit(0);
162 if ($must_exit) {
163 rg_stats_conns_insert($db);
164 rg_prof_end('remote.php');
165 rg_prof_log();
166 exit(0);
167 }
157 168 } }
169
170 rg_stats_conns_set('type', 'git-over-ssh');
158 171 } else { } else {
159 172 rg_log("git-daemon connection..."); rg_log("git-daemon connection...");
160 173 rg_log_ml('_SERVER: ' . print_r($_SERVER, true)); rg_log_ml('_SERVER: ' . print_r($_SERVER, true));
161 174
175 rg_stats_conns_set('type', 'git');
176
162 177 // we have no client info // we have no client info
163 178 $login_uid = 0; $login_uid = 0;
164 179 $key_id = 0; $key_id = 0;
 
... ... if (isset($_SERVER['SSH_CONNECTION'])) {
193 208 $v = explode(':', $host_port); $v = explode(':', $host_port);
194 209 $host = $v[0]; $host = $v[0];
195 210
196 $ip = rg_fix_ip(getenv("REMOTE_HOST"));
211 $rg['ip'] = rg_fix_ip(getenv("REMOTE_HOST"));
212 rg_stats_conns_set('ip', $rg['ip']);
197 213 } }
198 214
199 215 if (strncasecmp($cmd_repo, 'git-upload-pack', 15) == 0) { if (strncasecmp($cmd_repo, 'git-upload-pack', 15) == 0) {
200 $cmd = 'git-upload-pack';
216 $rg['cmd'] = 'git-upload-pack';
201 217 } else if (strncasecmp($cmd_repo, 'git-receive-pack', 16) == 0) { } else if (strncasecmp($cmd_repo, 'git-receive-pack', 16) == 0) {
202 $cmd = 'git-receive-pack';
218 $rg['cmd'] = 'git-receive-pack';
203 219 } else { } else {
204 $cmd = $cmd_repo;
220 $rg['cmd'] = $cmd_repo;
205 221 } }
222 rg_stats_conns_set('cmd', $rg['cmd']);
206 223
207 224 // extract repository name // extract repository name
208 $_t = substr($cmd_repo, strlen($cmd)); // skip cmd
209 $_t = trim($_t, "' ");
210 $_t = ltrim($_t, "/");
225 $rg['url'] = substr($cmd_repo, strlen($rg['cmd'])); // skip cmd
226 $rg['url'] = trim($rg['url'], "' ");
227 rg_stats_conns_set('url', $rg['url']);
228 $_t = ltrim($rg['url'], "/");
211 229 $_t = preg_replace('/\.git$/' , '', $_t); $_t = preg_replace('/\.git$/' , '', $_t);
212 230 $_t = explode("/", $_t); $_t = explode("/", $_t);
213 231 if (strcmp($_t[0], "user") == 0) { if (strcmp($_t[0], "user") == 0) {
 
... ... if (strcmp($_t[0], "user") == 0) {
220 238 $repo = isset($_t[1]) ? $_t[1] : ""; $repo = isset($_t[1]) ? $_t[1] : "";
221 239 } }
222 240
223 rg_log("ip=[$ip] host=[$host] cmd=[$cmd] prefix=[$prefix] user=[$user] repo=[$repo].");
241 rg_log('ip=[' . $rg['ip'] . '] host=[' . $host . '] cmd=[' . $rg['cmd'] . ']'
242 . ' prefix=[' . $prefix . '] user=[' . $user . ']'
243 . ' repo=[' . $repo . '].');
224 244
225 245 if (strstr($flags, 'W')) { if (strstr($flags, 'W')) {
226 246 // We are a worker, the command may be only for cloning! // We are a worker, the command may be only for cloning!
227 if (strcmp($cmd, 'git-upload-pack') != 0)
247 if (strcmp($rg['cmd'], 'git-upload-pack') != 0)
228 248 fatal('A worker can only clone!'); fatal('A worker can only clone!');
229 249 } }
230 250
 
... ... $helper_flags = '';
233 253 if (($login_uid == 0) && strstr($flags, 'W')) if (($login_uid == 0) && strstr($flags, 'W'))
234 254 $helper_flags .= 'B'; $helper_flags .= 'B';
235 255
236 $r = rg_repo_fetch_push_helper($db, $host, $ip, $login_ui, $prefix, $user,
237 $repo, $cmd, $helper_flags);
256 $r = rg_repo_fetch_push_helper($db, $host, $rg['ip'], $login_ui, $prefix,
257 $user, $repo, $rg['cmd'], $helper_flags);
238 258 rg_log_ml('DEBUG: repo_fetch_push_helper: ' . print_r($r, TRUE)); rg_log_ml('DEBUG: repo_fetch_push_helper: ' . print_r($r, TRUE));
239 259 if (($r['ok'] !== 1) || ($r['allow'] !== 1)) if (($r['ok'] !== 1) || ($r['allow'] !== 1))
240 260 fatal($r['errmsg']); fatal($r['errmsg']);
241 261
242 $run = "git-shell -c \"" . $cmd . " " . escapeshellarg($r['repo_path']) . "\"";
243 //$run = $cmd . ' ' . escapeshellarg($r['repo_path']);
262 $run = "git-shell -c \"" . $rg['cmd'] . " " . escapeshellarg($r['repo_path']) . "\"";
263 //$run = $rg['cmd'] . ' ' . escapeshellarg($r['repo_path']);
244 264 rg_log("Running [$run]..."); rg_log("Running [$run]...");
245 rg_prof_start($cmd);
265 rg_prof_start($rg['cmd']);
246 266 // TODO: shouldn't we use rg_exec to capture stderr? // TODO: shouldn't we use rg_exec to capture stderr?
247 267 passthru($run, $ret); passthru($run, $ret);
248 rg_prof_end($cmd);
268 rg_prof_end($rg['cmd']);
249 269 rg_log("[$run] returned $ret."); rg_log("[$run] returned $ret.");
250 270
251 rg_prof_end("remote.php");
271 if (!strstr($flags, 'W')) {
272 $repo_id = 0;
273 $uid = 0;
274
275 $_ui = rg_user_info($db, 0, $user, '');
276 if ($_ui['exists'] == 1)
277 $uid = $_ui['uid'];
278
279 if ($uid > 0) {
280 rg_stats_conns_set('uid', $uid);
281
282 $_ri = rg_repo_info($db, 0, $uid, $repo);
283 if ($_ri['exists'] == 1)
284 $repo_id = $_ri['repo_id'];
285
286 rg_stats_conns_set('repo_id', $repo_id);
287 }
288
289 rg_stats_conns_insert($db);
290 }
291
292 rg_prof_end('remote.php');
252 293 rg_prof_log(); rg_prof_log();
253 ?>
File scripts/worker.TODO changed (mode: 100644) (index 531353e..bf8e159)
28 28 [ ] Take load in consideration? [ ] Take load in consideration?
29 29 [ ] Specify a pool size per 'env' section? [ ] Specify a pool size per 'env' section?
30 30 [ ] Specify a global max pool size? [ ] Specify a global max pool size?
31 [ ] When strting, load all $conf['state'] . '/job-*.ser' files and send a DON
32 command to the server.
31 [ ] When starting, load all $conf['state'] . '/job-*.ser' files and send a DON
32 command to the server. Or maybe ask the server if needed?
33 33 [ ] Add a build_job_history table to store the tries to show them on the web? [ ] Add a build_job_history table to store the tries to show them on the web?
34 [ ] At start, check that all templates are available.
35 34 [ ] If the user never confirmed the e-mail address, maybe we should not allow [ ] If the user never confirmed the e-mail address, maybe we should not allow
36 35 network access to the build jobs? Or, maybe, do not allow build jobs? network access to the build jobs? Or, maybe, do not allow build jobs?
37 [ ] Report load of the worker to the server to be able to build a graph?
36 Maybe do not allow to add hooks?
37 [ ] Build a load graph based on stats.
38 38 [ ] Allow admin, when adding a worker, to disable network access. [ ] Allow admin, when adding a worker, to disable network access.
39 39 [ ] Should we validate we are talking with the correct server? I think yes. [ ] Should we validate we are talking with the correct server? I think yes.
40 At least on tcp:// connections.
40 At least on tcp:// connections. Do we already do this?
41 41 [ ] [ ]
File scripts/worker.php changed (mode: 100644) (index 57d8376..7b83c10)
... ... function load_config($file)
195 195 // Validate the path to the templates and images // Validate the path to the templates and images
196 196 foreach ($conf['env'] as $name => &$i) { foreach ($conf['env'] as $name => &$i) {
197 197 if (!isset($i['image'])) { if (!isset($i['image'])) {
198 // TODO: send this error to rocketgit to be sent by e-mail?
198 199 rg_log('Warning! Environment ' . $name . ' is missing \'image\' declaration' rg_log('Warning! Environment ' . $name . ' is missing \'image\' declaration'
199 200 . '; I will disable it.'); . '; I will disable it.');
200 201 unset($conf['env'][$name]); unset($conf['env'][$name]);
 
... ... function start_worker($job)
454 455 . ' -o IdentityFile=' . escapeshellarg($conf['state'] . '/key'); . ' -o IdentityFile=' . escapeshellarg($conf['state'] . '/key');
455 456 putenv($_env); putenv($_env);
456 457 $_s = time(); $_s = time();
457 $cmd = ' git clone'
458 $cmd = 'git clone'
458 459 . ' --recurse-submodules' . ' --recurse-submodules'
459 460 //TODO . ' --shallow-submodules' //TODO . ' --shallow-submodules'
460 461 . ' --no-checkout' . ' --no-checkout'
 
... ... function start_worker($job)
539 540 } }
540 541
541 542 // Store commands // Store commands
542 // TODO: set TMP somewhere on /mnt? (bind mount /mnt/tmp into /tmp)?
543 543 $r = @file_put_contents($job['main'] . '/root/rg.sh', $r = @file_put_contents($job['main'] . '/root/rg.sh',
544 544 '#!/bin/bash' . "\n" '#!/bin/bash' . "\n"
545 . 'mkdir /mnt/tmp && chmod 1777 /mnt/tmp' . "\n"
546 . 'mount --bind /mnt/tmp /tmp' . "\n"
547 . 'mkdir -p /mnt/var/tmp && chmod 1777 /mnt/var/tmp' . "\n"
548 . 'mount --bind /mnt/var/tmp /var/tmp' . "\n"
549 . "\n"
545 550 . 'mkdir /mnt/status' . "\n" . 'mkdir /mnt/status' . "\n"
546 551 . 'chown -R build:build /mnt/git /mnt/status' . "\n" . 'chown -R build:build /mnt/git /mnt/status' . "\n"
547 552 . 'echo "PATH=${PATH}"' . "\n" . 'echo "PATH=${PATH}"' . "\n"
File tests/_run_tests.sh changed (mode: 100755) (index 19e50dd..1947aef)
2 2
3 3 . ./env.txt . ./env.txt
4 4
5 tests="http_304 ldap_core ldap \
5 tests="http_api http_304 ldap_core ldap \
6 6 admin_set_web git_big_push admin_set_git by_http wh_lambda http_keys \ admin_set_web git_big_push admin_set_git by_http wh_lambda http_keys \
7 7 http_forgot \ http_forgot \
8 8 api wh_cloud pr_anon wh_http ssh http_totp totp git_log1 \ api wh_cloud pr_anon wh_http ssh http_totp totp git_log1 \
File tests/common.php changed (mode: 100644) (index 563c78e..163f603)
... ... if ($r !== TRUE) {
45 45
46 46 $r = rg_sql_struct_slaves_update($db); $r = rg_sql_struct_slaves_update($db);
47 47 if ($r !== TRUE) { if ($r !== TRUE) {
48 rg_log("Cannot create slaves!");
48 rg_log('Cannot create slaves: ' . rg_sql_error());
49 49 exit(1); exit(1);
50 50 } }
51 51
File tests/http.inc.php changed (mode: 100644) (index 115beaf..e565632)
... ... function do_req($url, &$data, &$headers)
47 47 mkdir($path); mkdir($path);
48 48 $cookie_jar = $path . '/' . $http_client; $cookie_jar = $path . '/' . $http_client;
49 49
50 if (!is_array($data))
50 if (is_null($data))
51 51 $data = array(); $data = array();
52 52
53 53 if (!is_array($headers)) { if (!is_array($headers)) {
 
... ... function do_req($url, &$data, &$headers)
63 63 $url .= '&_testns=' . $_testns; $url .= '&_testns=' . $_testns;
64 64 $url .= '&rg_log_sid=' . $rg_log_sid; $url .= '&rg_log_sid=' . $rg_log_sid;
65 65
66 rg_log_ml("do_req url[$url] data=" . print_r($data, TRUE)
67 . "headers=" . print_r($headers, TRUE));
66 rg_log_ml('do_req url: ' . $url . "\n"
67 . 'data=' . print_r($data, TRUE) . "\n"
68 . 'headers=' . print_r($headers, TRUE));
68 69
69 70 $c = FALSE; $c = FALSE;
70 71 if (isset($http_handles[$http_client])) if (isset($http_handles[$http_client]))
 
... ... function do_req($url, &$data, &$headers)
117 118 rg_log_ml("Cannot load (url=$url), data: " rg_log_ml("Cannot load (url=$url), data: "
118 119 . print_r($data, TRUE)); . print_r($data, TRUE));
119 120 rg_log("curl error: " . curl_error($c)); rg_log("curl error: " . curl_error($c));
120 return FALSE;
121 exit(1);
121 122 } }
122 123
123 124 $ret = array(); $ret = array();
124 $header_size = curl_getinfo($c, CURLINFO_HEADER_SIZE);
125 $ret['ci'] = @curl_getinfo($c);
126 if ($ret['ci'] === FALSE) {
127 rg_log('Cannot call curl_getinfo!');
128 exit(1);
129 }
130
131 //rg_log_ml('DEBUG: ci: ' . print_r($ret['ci'], TRUE));
132
133 if ($ret['ci']['http_code'] == 500)
134 return $ret;
135
136 $header_size = $ret['ci']['header_size'];
137 //rg_log('DEBUG: r (len=' . strlen($r) . '): ' . $r);
138 //rg_log('DEBUG: header_size: ' . $header_size);
125 139 $ret['header'] = substr($r, 0, $header_size); $ret['header'] = substr($r, 0, $header_size);
126 140 $ret['body'] = substr($r, $header_size); $ret['body'] = substr($r, $header_size);
127 141
128 // Check for XSS
129 if (stristr($ret['body'], '<xss>')) {
130 file_put_contents('http_xss.out', $ret['body']);
131 rg_log("Found <xss> token! Check http_xss.out. Not good!");
142 if ($ret['ci']['http_code'] != 200)
143 return $ret;
144
145 if (stristr($ret['header'], 'Content-Type: text/html')) {
146 // Check for XSS
147 if (stristr($ret['body'], '<xss>')) {
148 file_put_contents('http_xss.out', $ret['body']);
149 rg_log("Found <xss> token! Check http_xss.out. Not good!");
150 exit(1);
151 }
152 }
153
154 // TODO: should we compress the file downloads?
155 if (stristr($ret['header'], 'Content-Disposition: attachment'))
156 return $ret;
157
158 if (!stristr($ret['header'], 'Content-Encoding: gzip')) {
159 rg_log_ml('headers: ' . print_r($ret['header'], TRUE));
160 rg_log('Content is not compressed!');
161 exit(1);
162 }
163
164 if (!stristr($ret['header'], "\n" . 'ETag: ')) {
165 rg_log_ml('headers: ' . print_r($ret['header'], TRUE));
166 rg_log('ETag is not present!');
132 167 exit(1); exit(1);
133 168 } }
134 169
 
... ... function do_req($url, &$data, &$headers)
151 186 exit(1); exit(1);
152 187 } }
153 188 } else if (stristr($ret['header'], 'Content-Type: application/json')) { } else if (stristr($ret['header'], 'Content-Type: application/json')) {
154 if (@json_decode($ret['body'], TRUE) === NULL) {
155 rg_log_ml('body: ' . $ret['body']);
189 $ret['json'] = @json_decode($ret['body'], TRUE);
190 if ($ret['json'] === NULL) {
191 rg_log('body: ' . $ret['body']);
156 192 rg_log('Cannot decode JSON: ' . json_last_error_msg() . '!'); rg_log('Cannot decode JSON: ' . json_last_error_msg() . '!');
157 193 exit(1); exit(1);
158 194 } }
195 rg_log_ml('Decoded JSON: ' . print_r($ret['json'], TRUE));
159 196 } else { } else {
160 197 rg_log('I do not know how to deal with this content-type!'); rg_log('I do not know how to deal with this content-type!');
161 198 exit(1); exit(1);
 
... ... function do_req($url, &$data, &$headers)
194 231 $ret['tokens'] = array(); $ret['tokens'] = array();
195 232 $x = preg_match_all('/ name="token" value="([a-zA-Z0-9_:]*)"/', $x = preg_match_all('/ name="token" value="([a-zA-Z0-9_:]*)"/',
196 233 $ret['body'], $matches); $ret['body'], $matches);
197 //rg_log_ml('DEBUG: matches: ' . print_r($matches, TRUE));
234 //rg_log_ml('DEBUG: tokens matches: ' . print_r($matches, TRUE));
198 235 if (($x === FALSE) || (!isset($matches[1]))) { if (($x === FALSE) || (!isset($matches[1]))) {
199 236 //rg_log("CHECK: no token found"); //rg_log("CHECK: no token found");
200 237 } else { } else {
 
... ... function do_req($url, &$data, &$headers)
211 248 } }
212 249 rg_log('DEBUG ret[tokens]: ' . rg_array2string($ret['tokens']) . '.'); rg_log('DEBUG ret[tokens]: ' . rg_array2string($ret['tokens']) . '.');
213 250
251 // Collect '<input>' tags
252 $ret['inputs'] = array();
253 $x = preg_match_all('/<input .* name="(.*?)" .*value="(.*?)"/uD',
254 $ret['body'], $matches);
255 //rg_log_ml('DEBUG: inputs matches: ' . print_r($matches, TRUE));
256 if (($x === FALSE) || (!isset($matches[1]))) {
257 //rg_log("CHECK: no token found");
258 } else {
259 foreach ($matches[1] as $i => $d)
260 $ret['inputs'][$d] = $matches[2][$i];
261 }
262 //rg_log_ml('DEBUG ret[inputs]: ' .print_r($ret['inputs'], TRUE));
263
214 264 // find logout token // find logout token
215 265 $x = preg_match('/logout\?token=([a-zA-Z0-9:]*)"/', $ret['body'], $matches); $x = preg_match('/logout\?token=([a-zA-Z0-9:]*)"/', $ret['body'], $matches);
216 266 //rg_log_ml('DEBUG: matches[logout]: ' . print_r($matches, TRUE)); //rg_log_ml('DEBUG: matches[logout]: ' . print_r($matches, TRUE));
File tests/http_304.php changed (mode: 100644) (index 4d5f026..3d99dc8)
... ... $_testns = 'http_304';
21 21 prepare_http(); prepare_http();
22 22
23 23 rg_log(''); rg_log('');
24 rg_log_enter('Loading main page...');
24 rg_log_enter('Loading main page to get ETag value...');
25 25 $data = array(); $headers = array(); $data = array(); $headers = array();
26 26 $r = do_req($test_url . '/', $data, $headers); $r = do_req($test_url . '/', $data, $headers);
27 if (!stristr($r['header'], 'Content-Encoding: gzip')) {
28 rg_log_ml('headers: ' . print_r($r['header'], TRUE));
29 rg_log('Content is not compressed!');
30 exit(1);
31 }
32 if (!stristr($r['header'], "\n" . 'ETag: ')) {
33 rg_log_ml('headers: ' . print_r($r['header'], TRUE));
34 rg_log('ETag is not present!');
35 exit(1);
36 }
37 27 rg_log_ml('Headers: ' . print_r($r['header'], TRUE)); rg_log_ml('Headers: ' . print_r($r['header'], TRUE));
38 28 $x = explode("\nETag: ", $r['header'], 2); $x = explode("\nETag: ", $r['header'], 2);
39 29 $y = explode("\n", $x[1], 2); $y = explode("\n", $x[1], 2);
File tests/http_api.php added (mode: 100644) (index 0000000..e7317c1)
1 <?php
2 error_reporting(E_ALL | E_STRICT);
3 ini_set('track_errors', 'On');
4
5 $rg_cache_debug = TRUE;
6 $test_normal = TRUE;
7
8 $INC = dirname(__FILE__) . '/../inc';
9 require_once(dirname(__FILE__) . '/config.php');
10 require_once($INC . '/init.inc.php');
11 require_once($INC . '/util.inc.php');
12 require_once('helpers.inc.php');
13 require_once('http.inc.php');
14
15 rg_log_set_file('http_api.log');
16
17 require_once('common.php');
18
19 $_testns = 'http_api';
20
21 prepare_http();
22
23 rg_test_create_user($db, $u);
24 rg_test_create_repo_no_dir($db, $u, $repo);
25
26 $r = test_login($test_url, $u);
27 if ($r === FALSE)
28 exit(1);
29
30 rg_test_upload_ssh_key($db, $u, 'http_api', $kn);
31
32 rg_log('');
33 rg_log_enter('Loading api keys form...');
34 $url = '/op/settings/apikeys/add';
35 $headers = array();
36 $data = array();
37 $r = do_req($test_url . $url, $data, $headers);
38 if ($r === FALSE) {
39 rg_log('Cannot load form.');
40 exit(1);
41 }
42 $token = @$r['tokens']['ak_add'];
43 if (empty($token)) {
44 rg_log_ml('r: ' . print_r($r, TRUE));
45 rg_log('Seems I cannot load the token!');
46 exit(1);
47 }
48 $key = $r['inputs']['ak::key'];
49 rg_log_exit();
50
51
52 rg_log('');
53 rg_log_enter('Posting api keys add form (token=' . $token . ')...');
54 $data = array('doit' => 1, 'token' => $token,
55 'ak::name' => 'ak<xss>', 'ak::key' => $key);
56 $r = do_req($test_url . $url, $data, $headers);
57 if ($r === FALSE) {
58 rg_log('Cannot post request.');
59 exit(1);
60 }
61 $sql = 'SELECT * FROM apikeys WHERE uid = ' . $u['uid'];
62 $res = rg_sql_query($db, $sql);
63 $row = rg_sql_fetch_array($res);
64 rg_sql_free_result($res);
65 if (strcmp($row['key'], $key) != 0) {
66 rg_log('The key not found in the database (db=' . $row['key']
67 . '; post=' . $key . ')!');
68 exit(1);
69 }
70 rg_log_exit();
71
72
73 // TODO: what happens if the CT is not json?
74 // sh = Standard Headers
75 $sh = array('Content-Type: application/json');
76
77 $url = '/op/api';
78
79
80 rg_log('');
81 rg_log_enter('Calling API: user_info (without authorization)...');
82 $headers = $sh;
83 $a = array('cmd' => 'user_info', 'user' => $u['username']);
84 $data = json_encode($a);
85 $r = do_req($test_url . $url, $data, $headers);
86 if (@strcmp($r['json']['error'], 'invalid user or apikey') != 0) {
87 rg_log('Cannot call api.');
88 exit(1);
89 }
90 rg_log_exit();
91
92
93 // From now on, we only try with the key...
94 $sh[] = 'Authorization: ' . $u['username'] . ' ' . $key;
95
96
97 rg_log('');
98 rg_log_enter('Calling API: invalid command...');
99 $headers = $sh;
100 $a = array('cmd' => 'invalid command');
101 $data = json_encode($a);
102 $r = do_req($test_url . $url, $data, $headers);
103 if (@strcmp($r['json']['error'], 'invalid command') != 0) {
104 rg_log('Cannot call api.');
105 exit(1);
106 }
107 rg_log_exit();
108
109
110 rg_log('');
111 rg_log_enter('Calling API: user_info (with authorization)...');
112 $headers = $sh;
113 $a = array('cmd' => 'user_info', 'user' => $u['username']);
114 $data = json_encode($a);
115 $r = do_req($test_url . $url, $data, $headers);
116 if (@strcmp($r['json']['email'], $u['email']) != 0) {
117 rg_log('E-mail ot returned for user_info?!');
118 exit(1);
119 }
120 rg_log_exit();
121
122
123 rg_log('');
124 rg_log_enter('Calling API: user_ssh_key_list (uid instead or user)...');
125 $headers = $sh;
126 $a = array('cmd' => 'user_ssh_keys_list', 'uid' => $u['uid'], 'opaque' => 'abc');
127 $data = json_encode($a);
128 $r = do_req($test_url . $url, $data, $headers);
129 if (!isset($r['json']['list'][0]['last_use'])) {
130 rg_log('NO last_use field for the first key!');
131 exit(1);
132 }
133 if (@strcmp($r['json']['opaque'], 'abc') != 0) {
134 rg_log('Opaque value is missing/wrong!');
135 exit(1);
136 }
137 rg_log_exit();
138
139
140 rg_prof_log();
141 rg_log('OK!');
142
File tools/rg_authorize changed (mode: 100755) (index 7d240f3..885dc56)
... ... rg_prof_start('MAIN');
27 27 rg_log_set_file($rg_log_dir . '/authorize.log'); rg_log_set_file($rg_log_dir . '/authorize.log');
28 28 rg_log_set_sid('000000'); // to spread the logs rg_log_set_sid('000000'); // to spread the logs
29 29
30 rg_sql_app('rg_authorize');
30 rg_sql_app('rg_authorize-' . $rg_log_sid);
31 31 $db = rg_sql_open($rg_sql); $db = rg_sql_open($rg_sql);
32 32 if ($db === FALSE) { if ($db === FALSE) {
33 33 rg_log('Cannot connect to db!'); rg_log('Cannot connect to db!');
Date/time (UTC) Type Misc Labels
2020-06-10 09:22 build CentOS-8-x86_64 worker/r1 builder/color=fff worker_elap/21s wait_time/525315s date/2020-06-04 time/07:24
2020-06-10 09:22 build fedora-31-x86_64 worker/r1 builder/color=fff worker_elap/27s wait_time/525315s date/2020-06-04 time/07:24
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/catalinux/rocketgit

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/catalinux/rocketgit

Clone this repository using git:
git clone git://git.rocketgit.com/user/catalinux/rocketgit

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main