File TODO changed (mode: 100644) (index 19ede7c..a8bfdcf) |
1 |
1 |
== Where I stopped last time == |
== Where I stopped last time == |
2 |
|
[ ] unit testing for forgot_link - seems is not working! |
|
3 |
|
[ ] Visit all functions in git.int to not pass unescaped references to bash. |
|
|
2 |
|
|
|
3 |
|
== BEFORE NEXT RELEASE == |
|
4 |
|
[ ] build: Document how to start builder.sh (from cron or let it read the conf |
|
5 |
|
file). Or, never install worker.conf and let an admin to rename |
|
6 |
|
worker.conf.sample into worker.conf |
|
7 |
|
[ ] build: for admin, we can access "Workers" two ways: |
|
8 |
|
- Settings -> Workers |
|
9 |
|
- Admin -> Workers |
|
10 |
|
[ ] worker: allow a custom virsh command (to be able to connect to other host) |
|
11 |
|
[ ] git diff does not execute arbitrary commands from .gitattributes?! |
|
12 |
|
--no-ext-diff, --no-textconv |
|
13 |
|
[ ] When we build for multiple architectures, we may reuse the initial image... |
|
14 |
|
[ ] build: when we should fallback to global workers? Maybe the user |
|
15 |
|
does not want to use the global ones! |
|
16 |
|
[ ] build: try to rebuild the master image with all the packages a user needs, |
|
17 |
|
so, the start-up cost will be smaller. |
|
18 |
|
[ ] build: we must add an event when a job is done. |
|
19 |
|
[ ] build: What if I tunnel everything using SSH? |
|
20 |
|
Take care to not allow a worker to fetch any repo. The server must |
|
21 |
|
provide a key that will allow only a repo/head to be cloned. |
|
22 |
|
Probably the best way is to use the socket for notifications and |
|
23 |
|
use the API to get the job and post the job. |
|
24 |
|
[ ] debian: deal with config files (do not overwrite them) |
|
25 |
|
[ ] build: Ask softiron to donate an "Overdrive 1000" for builds on 64bit ARM. |
|
26 |
|
[ ] build: document colors (/color=fff) |
|
27 |
|
[ ] build: provide real link to the repo for cloning. |
|
28 |
|
Done, but if ssh is disabled, allow https! |
|
29 |
|
[ ] build: we must be able to specify a color for labels. |
|
30 |
|
[ ] build: when listing workers, add some info about what they are doing? |
|
31 |
|
Pay attention to security issues: we do not want to list private repos! |
|
32 |
|
[ ] build: allow meta rocketgit tags in commit message to trigger some hooks. |
|
33 |
|
[ ] build: warn user about the unprotected channel with the master process. |
|
34 |
|
[ ] build: add a "Download" button for worker configuration. |
|
35 |
|
[ ] build: if a worker losts conectivity, at reconnect may send DON jobs |
|
36 |
|
to the server. But in the mean time the server may already |
|
37 |
|
redistributed the job to other worker. Just ignore the DON. |
|
38 |
|
But, a worker must ask the server if the job is still needed before |
|
39 |
|
starting to work. |
|
40 |
|
[ ] build: what happens if worker process crashes? We loose all state (pids, |
|
41 |
|
virtual machines etc.). We must save this info to be able recover! |
|
42 |
|
[ ] build: do load testing (Cosmin R) |
|
43 |
|
[ ] We may want to cut the network access for user 'build' inside the worker. |
|
44 |
|
[ ] If user is using firewalld: |
|
45 |
|
firewall-cmd --permanent --add-port=19999/tcp |
|
46 |
|
firewall-cmd --reload |
|
47 |
|
[ ] Register with freecode.club |
|
48 |
|
[ ] build: give error if we cannot install one of the packages. |
|
49 |
|
[ ] build: allow user to install some dependencies. |
|
50 |
|
Or maybe try to detect from the spec file? |
|
51 |
|
We also must specify how to install packages. |
|
52 |
|
[ ] wh: we do not have the time of last run! |
|
53 |
|
[ ] build: allow adding environment variables for a job. |
|
54 |
|
[ ] Somehow, warn the user that no environments are available and instruct |
|
55 |
|
she/him to add workers. |
|
56 |
|
[ ] css: 'mess' class has a 5px top margin. it is not ok (check edit webhook). |
|
57 |
|
[ ] Filter environment (allow only a-zA-Z0-9_.) |
|
58 |
|
[ ] Join builders.inc.php and workers.inc.php? |
|
59 |
|
[ ] build: builder.php: we should wait for a notification instead to poll |
|
60 |
|
the database. |
|
61 |
|
[ ] build: enforce a max build time; use cost; use max_workers. |
|
62 |
|
[ ] build: If a user has own workers, do not use global ones (of course, |
|
63 |
|
arch is taken in consideration). |
|
64 |
|
[ ] build: show user the status of the workers. Also, how much time they |
|
65 |
|
were used and what builds they did. |
|
66 |
|
[ ] build: find a way to reuse machines, so we avoid the startup cost. |
|
67 |
|
Take care also about package instalation. |
|
68 |
|
[ ] build: avoid starting a lot of services. We do not need them! |
|
69 |
|
[ ] Some daemon to synchronize two instances (master standby or just |
|
70 |
|
load balancing)? |
|
71 |
|
[ ] build: Use 'type' field! |
|
72 |
|
[ ] build: 'key' is still used? |
|
73 |
|
I think yes. It will be presented when a user validates the worker. |
|
74 |
|
[ ] build: Reload worker config somehow. |
|
75 |
|
[ ] log2listing: seems I do not add labels per commit but only at the end! |
4 |
76 |
[ ] The verification of user-provided CSRF crumbs with the expected value did |
[ ] The verification of user-provided CSRF crumbs with the expected value did |
5 |
77 |
not use a constant-time comparison algorithm, potentially allowing |
not use a constant-time comparison algorithm, potentially allowing |
6 |
78 |
attackers to use statistical methods to determine valid CSRF crumbs |
attackers to use statistical methods to determine valid CSRF crumbs |
7 |
79 |
using brute-force methods. |
using brute-force methods. |
8 |
80 |
[ ] clone seems to be done by git and not by ssh! |
[ ] clone seems to be done by git and not by ssh! |
9 |
|
[ ] build: environment lists must be with checkboxes |
|
10 |
|
[ ] build: when a client connects, add the environments to the env table. |
|
11 |
|
Allow to expire? or allow the admin to do it? |
|
12 |
|
[ ] log2listing: seems I do not add labels per commit but only at the end! |
|
13 |
|
[ ] Oracle: libsepol.print_missing_requirements: rocketgit's global |
|
14 |
|
requirements were |
|
15 |
|
not met: type/attribute passwd_file_t (No such file or directory). |
|
16 |
|
libsemanage.semanage_link_sandbox: Link packages failed (No such file |
|
17 |
|
or directory). /usr/sbin/semodule: Failed! |
|
18 |
|
[ ] Document how to start builder.sh (from cron or let it read the conf file) |
|
19 |
|
[ ] Forgot password does not redirect - no message! |
|
20 |
|
[ ] |
|
21 |
|
|
|
22 |
|
++ |
|
23 |
|
Allow workes to connect, but admin must validate them before being able |
|
24 |
|
to build something. At the same time, also set the auth key? |
|
25 |
|
Also, client must generate a ssh key and the public part must be sent to |
|
26 |
|
the server. After validation, the user can clone by ssh! |
|
27 |
|
I think is better to create an archive of the repo and transfer it by |
|
28 |
|
the same protocol. Not clear if I should use "git clone" or "git archive". |
|
29 |
|
++ |
|
30 |
|
|
|
31 |
|
== BEFORE NEXT RELEASE == |
|
|
81 |
|
[ ] About SSH/API keys and rights: there is some interference between these |
|
82 |
|
and granting rights. Seems, as we grant users some rights, we also |
|
83 |
|
grant API keys some rights. Maybe add the key in rights?! |
|
84 |
|
Which rights?! It is not clear how should I link the api key |
|
85 |
|
with a right. What sense makes the 'user' field next to the api key?! |
|
86 |
|
And how do I show the api key? As the short name or as the id? |
|
87 |
|
OK, but this makes sense only for repos! What about users, webhooks |
|
88 |
|
etc.? Maybe repo 'rights' makes sense from cloning. |
|
89 |
|
API makes sense for API manipulation. What about cloning using an |
|
90 |
|
APIKEY? |
|
91 |
|
So, the API keys is just another authentication method. |
|
92 |
|
This means that the 'rights' tabs should be moved in settings?! |
|
93 |
|
Probably no. But we will need also rights in Settings to control |
|
94 |
|
!repo stuff. |
|
95 |
|
[ ] Unit testing for API keys |
|
96 |
|
[ ] Probably, also ssh keys must have some actions allowed attached to them. |
|
97 |
|
How it will work?! By default, all rights. |
|
98 |
|
Use case: allow a key only to push on some repos (regex) |
|
99 |
|
Use case: allow a key to only access repo APIs. |
|
100 |
|
[ ] Scan SSH/API keys and notify user whey were used too long ago, and ask |
|
101 |
|
the user to remove them? |
|
102 |
|
[ ] From time to time, regenerate the passwords with other salt to protect |
|
103 |
|
against stolen db and brute force attacks. |
|
104 |
|
[ ] Respect .gitattributes file |
|
105 |
|
[ ] Get rid of "Please login first"! Just show the login form! |
|
106 |
|
[ ] Sometimes we send cosmetic data to cache! Not good! At least in totp.inc.php! |
|
107 |
|
[ ] LIST_LOADED/LOADED etc. is not used: at least on totp.inc.php! |
|
108 |
|
[ ] A difference between paid accounts and free ones: how much time we keep the |
|
109 |
|
logs. |
|
110 |
|
[ ] Add an API layer to be able to use other git hosting scripts to connect to me |
|
111 |
|
[ ] Sign some contract with Nitrokey.com to provide keys to the users. |
|
112 |
|
[ ] build: allow user to specify some packages to be installed first? |
32 |
113 |
[ ] Get rid of php-mbstring! It is not in main repo on Oracle Linux! |
[ ] Get rid of php-mbstring! It is not in main repo on Oracle Linux! |
33 |
114 |
[ ] Destroy storage for 'build' machines |
[ ] Destroy storage for 'build' machines |
34 |
115 |
[ ] If a user types a wrong e-mail at registration phase, and without |
[ ] If a user types a wrong e-mail at registration phase, and without |
File inc/apikeys.inc.php added (mode: 100644) (index 0000000..49f213a) |
|
1 |
|
<?php |
|
2 |
|
// This files deals with keys used to call the API (over HTTPS) |
|
3 |
|
require_once($INC . '/sql.inc.php'); |
|
4 |
|
require_once($INC . '/state.inc.php'); |
|
5 |
|
require_once($INC . '/prof.inc.php'); |
|
6 |
|
require_once($INC . '/events.inc.php'); |
|
7 |
|
require_once($INC . '/cache.inc.php'); |
|
8 |
|
|
|
9 |
|
$rg_ak_error = ''; |
|
10 |
|
|
|
11 |
|
function rg_ak_set_error($str) |
|
12 |
|
{ |
|
13 |
|
global $rg_ak_error; |
|
14 |
|
$rg_ak_error = $str; |
|
15 |
|
rg_log($str); |
|
16 |
|
} |
|
17 |
|
|
|
18 |
|
function rg_ak_error() |
|
19 |
|
{ |
|
20 |
|
global $rg_ak_error; |
|
21 |
|
return $rg_ak_error; |
|
22 |
|
} |
|
23 |
|
|
|
24 |
|
/* |
|
25 |
|
* Events functions |
|
26 |
|
*/ |
|
27 |
|
$rg_ak_functions = array( |
|
28 |
|
'ak_event_new' => 'rg_ak_event_new', |
|
29 |
|
'ak_event_del' => 'rg_ak_event_del', |
|
30 |
|
'ak_event_notify_user' => 'rg_ak_event_notify_user' |
|
31 |
|
); |
|
32 |
|
rg_event_register_functions($rg_ak_functions); |
|
33 |
|
|
|
34 |
|
/* |
|
35 |
|
* Event for adding a new api key |
|
36 |
|
*/ |
|
37 |
|
function rg_ak_event_new($db, $event) |
|
38 |
|
{ |
|
39 |
|
$ret = array(); |
|
40 |
|
|
|
41 |
|
$event['op'] = 'new'; |
|
42 |
|
|
|
43 |
|
// notify user |
|
44 |
|
$a = array('category' => 'ak_event_notify_user', 'prio' => 100); |
|
45 |
|
$ret[] = array_merge($event, $a); |
|
46 |
|
|
|
47 |
|
return $ret; |
|
48 |
|
} |
|
49 |
|
|
|
50 |
|
/* |
|
51 |
|
* Event for deleting a key |
|
52 |
|
*/ |
|
53 |
|
function rg_ak_event_del($db, $event) |
|
54 |
|
{ |
|
55 |
|
$ret = array(); |
|
56 |
|
$event['op'] = 'del'; |
|
57 |
|
|
|
58 |
|
// notify user |
|
59 |
|
$a = array('category' => 'ak_event_notify_user', 'prio' => 100); |
|
60 |
|
$ret[] = array_merge($event, $a); |
|
61 |
|
|
|
62 |
|
return $ret; |
|
63 |
|
} |
|
64 |
|
|
|
65 |
|
/* |
|
66 |
|
* Notify user that a new key was added to the keyring |
|
67 |
|
*/ |
|
68 |
|
function rg_ak_event_notify_user($db, $event) |
|
69 |
|
{ |
|
70 |
|
rg_prof_start('ak_event_notify_user'); |
|
71 |
|
rg_log('ak_event_notify_user: event=' . rg_array2string($event)); |
|
72 |
|
|
|
73 |
|
$ret = FALSE; |
|
74 |
|
while (1) { |
|
75 |
|
$r = rg_mail_template('mail/user/ak/' . $event['op'], $event); |
|
76 |
|
if ($r === FALSE) |
|
77 |
|
break; |
|
78 |
|
|
|
79 |
|
$ret = array(); |
|
80 |
|
break; |
|
81 |
|
} |
|
82 |
|
|
|
83 |
|
rg_prof_end('ak_event_notify_user'); |
|
84 |
|
return $ret; |
|
85 |
|
} |
|
86 |
|
|
|
87 |
|
/* |
|
88 |
|
* Remove api keys from database for user 'ui' |
|
89 |
|
*/ |
|
90 |
|
function rg_ak_remove($db, $uid, $list) |
|
91 |
|
{ |
|
92 |
|
rg_prof_start('ak_remove'); |
|
93 |
|
rg_log_enter('ak_remove: list=' . rg_array2string($list)); |
|
94 |
|
|
|
95 |
|
$ret = FALSE; |
|
96 |
|
while (1) { |
|
97 |
|
$my_list = array(); |
|
98 |
|
foreach ($list as $key_id => $junk) |
|
99 |
|
$my_list[] = sprintf('%u', $key_id); |
|
100 |
|
|
|
101 |
|
$params = array('uid' => $uid); |
|
102 |
|
$sql_list = implode(', ', $my_list); |
|
103 |
|
$sql = 'DELETE FROM apikeys' |
|
104 |
|
. ' WHERE uid = @@uid@@' |
|
105 |
|
. ' AND key_id IN (' . $sql_list . ')'; |
|
106 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
107 |
|
if ($res === FALSE) { |
|
108 |
|
rg_ak_set_error('cannot delete api keys'); |
|
109 |
|
break; |
|
110 |
|
} |
|
111 |
|
rg_sql_free_result($res); |
|
112 |
|
|
|
113 |
|
$event = array( |
|
114 |
|
'category' => 'rg_ak_event_del', |
|
115 |
|
'prio' => 50, |
|
116 |
|
'ui' => array('uid' => $uid), |
|
117 |
|
'keys' => implode(',', $my_list)); |
|
118 |
|
$r = rg_event_add($db, $event); |
|
119 |
|
if ($r !== TRUE) { |
|
120 |
|
rg_ak_set_error('cannot add event' |
|
121 |
|
. ' (' . rg_event_error() . ')'); |
|
122 |
|
break; |
|
123 |
|
} |
|
124 |
|
|
|
125 |
|
$key = 'user' . '::' . $uid . '::' . 'apikeys' . '::' . 'list'; |
|
126 |
|
foreach ($my_list as $_key_id) |
|
127 |
|
rg_cache_unset($key . '::' . $_key_id, |
|
128 |
|
RG_SOCKET_NO_WAIT); |
|
129 |
|
|
|
130 |
|
rg_event_signal_daemon('', 0); |
|
131 |
|
$ret = TRUE; |
|
132 |
|
break; |
|
133 |
|
} |
|
134 |
|
|
|
135 |
|
rg_log_exit(); |
|
136 |
|
rg_prof_end('ak_remove'); |
|
137 |
|
return $ret; |
|
138 |
|
} |
|
139 |
|
|
|
140 |
|
/* |
|
141 |
|
* Adds an apikey |
|
142 |
|
* Returns the key_id of the key. |
|
143 |
|
*/ |
|
144 |
|
function rg_ak_add($db, $uid, $key, $name) |
|
145 |
|
{ |
|
146 |
|
rg_prof_start('ak_add'); |
|
147 |
|
rg_log_enter('ak_add: key=' . $key . ' name=' . $name); |
|
148 |
|
|
|
149 |
|
$ret = FALSE; |
|
150 |
|
$do_rollback = 0; |
|
151 |
|
while (1) { |
|
152 |
|
$itime = time(); |
|
153 |
|
|
|
154 |
|
$r = rg_sql_begin($db); |
|
155 |
|
if ($r !== TRUE) { |
|
156 |
|
rg_ak_set_error('cannot start transaction'); |
|
157 |
|
break; |
|
158 |
|
} |
|
159 |
|
$do_rollback = 1; |
|
160 |
|
|
|
161 |
|
$params = array( |
|
162 |
|
'itime' => $itime, |
|
163 |
|
'uid' => $uid, |
|
164 |
|
'key' => $key, |
|
165 |
|
'name' => $name, |
|
166 |
|
'count' => 0, |
|
167 |
|
'first_use' => 0); |
|
168 |
|
$sql = 'INSERT INTO apikeys (itime, uid, key, name)' |
|
169 |
|
. ' VALUES (@@itime@@, @@uid@@, @@key@@, @@name@@)' |
|
170 |
|
. ' RETURNING key_id'; |
|
171 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
172 |
|
if ($res === FALSE) { |
|
173 |
|
rg_ak_set_error('cannot insert key'); |
|
174 |
|
break; |
|
175 |
|
} |
|
176 |
|
$row = rg_sql_fetch_array($res); |
|
177 |
|
$key_id = $row['key_id']; |
|
178 |
|
rg_sql_free_result($res); |
|
179 |
|
|
|
180 |
|
$event = array( |
|
181 |
|
'category' => 'ak_event_new', |
|
182 |
|
'prio' => 50, |
|
183 |
|
'ui' => array('uid' => $uid), |
|
184 |
|
'key' => $key, |
|
185 |
|
'name' => $name, |
|
186 |
|
'key_id' => $key_id); |
|
187 |
|
$r = rg_event_add($db, $event); |
|
188 |
|
if ($r !== TRUE) { |
|
189 |
|
rg_ak_set_error('cannot add event' |
|
190 |
|
. ' (' . rg_event_error() . ')'); |
|
191 |
|
break; |
|
192 |
|
} |
|
193 |
|
|
|
194 |
|
$r = rg_sql_commit($db); |
|
195 |
|
if ($r !== TRUE) { |
|
196 |
|
rg_ak_set_error('cannot commit transaction'); |
|
197 |
|
break; |
|
198 |
|
} |
|
199 |
|
$do_rollback = 0; |
|
200 |
|
|
|
201 |
|
$_key = 'user' . '::' . $uid . '::' |
|
202 |
|
. 'apikeys' . '::' . 'list' . '::' . $key_id; |
|
203 |
|
rg_cache_merge($_key, $params, RG_SOCKET_NO_WAIT); |
|
204 |
|
|
|
205 |
|
rg_event_signal_daemon('', 0); |
|
206 |
|
|
|
207 |
|
$ret = $key_id; |
|
208 |
|
break; |
|
209 |
|
} |
|
210 |
|
|
|
211 |
|
if ($do_rollback == 1) |
|
212 |
|
rg_sql_rollback($db); |
|
213 |
|
|
|
214 |
|
rg_log_exit(); |
|
215 |
|
rg_prof_end('ak_add'); |
|
216 |
|
return $ret; |
|
217 |
|
} |
|
218 |
|
|
|
219 |
|
/* |
|
220 |
|
* Update first_use, last_use, last_ip and count |
|
221 |
|
*/ |
|
222 |
|
function rg_ak_update_use($db, $uid, $key_id, $ip, $cmd) |
|
223 |
|
{ |
|
224 |
|
rg_prof_start('ak_update_use'); |
|
225 |
|
rg_log_enter('ak_update_use: uid=' . $uid . ' key_id=' . $key_id |
|
226 |
|
. ', ip=' . $ip . ', cmd=' . $cmd); |
|
227 |
|
|
|
228 |
|
$ret = FALSE; |
|
229 |
|
while (1) { |
|
230 |
|
$now = time(); |
|
231 |
|
|
|
232 |
|
$update_first_use = TRUE; |
|
233 |
|
$update_last_use = TRUE; |
|
234 |
|
|
|
235 |
|
$key = 'user' . '::' . $uid . '::' . 'apikeys' |
|
236 |
|
. ' ::' . 'list' . '::' . $key_id; |
|
237 |
|
$c = rg_cache_get($key); |
|
238 |
|
if ($c !== FALSE) { |
|
239 |
|
if (isset($c['first_use']) && ($c['first_use'] > 0)) |
|
240 |
|
$update_first_use = FALSE; |
|
241 |
|
|
|
242 |
|
// We will not update the field if is too soon |
|
243 |
|
if (isset($c['last_use']) |
|
244 |
|
&& (strcmp($ip, $c['last_ip']) == 0) |
|
245 |
|
&& (strcmp($cmd, $c['last_cmd']) == 0) |
|
246 |
|
&& ($now - $c['last_use'] < 60)) |
|
247 |
|
$update_last_use = FALSE; |
|
248 |
|
} |
|
249 |
|
|
|
250 |
|
$params = array( |
|
251 |
|
'now' => $now, |
|
252 |
|
'key_id' => $key_id, |
|
253 |
|
'ip' => $ip, |
|
254 |
|
'last_cmd' => $cmd); |
|
255 |
|
|
|
256 |
|
if ($update_first_use) { |
|
257 |
|
$sql = 'UPDATE apikeys SET first_use = @@now@@' |
|
258 |
|
. ' WHERE first_use = 0' |
|
259 |
|
. ' AND key_id = @@key_id@@'; |
|
260 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
261 |
|
if ($res === FALSE) { |
|
262 |
|
rg_ak_set_error('cannot update apikey\'s first use'); |
|
263 |
|
break; |
|
264 |
|
} |
|
265 |
|
rg_sql_free_result($res); |
|
266 |
|
|
|
267 |
|
rg_cache_set($key . '::' . 'first_use', $now, |
|
268 |
|
RG_SOCKET_NO_WAIT); |
|
269 |
|
} |
|
270 |
|
|
|
271 |
|
if ($update_last_use) { |
|
272 |
|
$sql = 'UPDATE apikeys SET last_use = @@now@@' |
|
273 |
|
. ', last_ip = @@ip@@' |
|
274 |
|
. ', last_cmd = @@last_cmd@@' |
|
275 |
|
. ', count = count + 1' |
|
276 |
|
. ' WHERE key_id = @@key_id@@'; |
|
277 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
278 |
|
if ($res === FALSE) { |
|
279 |
|
rg_ak_set_error('cannot update key'); |
|
280 |
|
break; |
|
281 |
|
} |
|
282 |
|
rg_sql_free_result($res); |
|
283 |
|
|
|
284 |
|
$a = array( |
|
285 |
|
'last_use' => $now, |
|
286 |
|
'last_ip' => $ip, |
|
287 |
|
'last_cmd' => $cmd); |
|
288 |
|
rg_cache_merge($key, $a, RG_SOCKET_NO_WAIT); |
|
289 |
|
} |
|
290 |
|
|
|
291 |
|
$ret = TRUE; |
|
292 |
|
break; |
|
293 |
|
} |
|
294 |
|
|
|
295 |
|
rg_log_exit(); |
|
296 |
|
rg_prof_end('ak_update_use'); |
|
297 |
|
return $ret; |
|
298 |
|
} |
|
299 |
|
|
|
300 |
|
/* |
|
301 |
|
* Cosmetic changes for a key |
|
302 |
|
*/ |
|
303 |
|
function rg_ak_cosmetic(&$row) |
|
304 |
|
{ |
|
305 |
|
if ($row['itime'] == 0) |
|
306 |
|
$row['itime_nice'] = 'N/A'; |
|
307 |
|
else |
|
308 |
|
$row['itime_nice'] = gmdate('Y-m-d H:i', $row['itime']); |
|
309 |
|
|
|
310 |
|
if ($row['first_use'] == 0) |
|
311 |
|
$row['first_use_nice'] = 'N/A'; |
|
312 |
|
else |
|
313 |
|
$row['first_use_nice'] = gmdate('Y-m-d H:i', $row['first_use']); |
|
314 |
|
|
|
315 |
|
if (empty($row['last_ip'])) |
|
316 |
|
$row['last_ip'] = 'N/A'; |
|
317 |
|
|
|
318 |
|
if ($row['last_use'] == 0) |
|
319 |
|
$row['last_use_nice'] = 'N/A'; |
|
320 |
|
else |
|
321 |
|
$row['last_use_nice'] = gmdate('Y-m-d H:i', $row['last_use']); |
|
322 |
|
|
|
323 |
|
if (empty($row['last_cmd'])) |
|
324 |
|
$row['last_cmd'] = 'N/A'; |
|
325 |
|
} |
|
326 |
|
|
|
327 |
|
/* |
|
328 |
|
* List keys |
|
329 |
|
*/ |
|
330 |
|
function rg_ak_list($db, $uid) |
|
331 |
|
{ |
|
332 |
|
rg_prof_start('ak_list'); |
|
333 |
|
rg_log_enter('ak_list: uid=' . $uid); |
|
334 |
|
|
|
335 |
|
$ret = FALSE; |
|
336 |
|
while (1) { |
|
337 |
|
$key = 'user' . '::' . $uid . '::' . 'apikeys'; |
|
338 |
|
$c = rg_cache_get($key); |
|
339 |
|
//rg_log_ml('DEBUG: cache: ' . print_r($c, TRUE)); |
|
340 |
|
if (($c !== FALSE) && isset($c['LOADED'])) { |
|
341 |
|
$ret = $c['list']; |
|
342 |
|
|
|
343 |
|
foreach ($ret as $key_id => &$i) |
|
344 |
|
rg_ak_cosmetic($i); |
|
345 |
|
break; |
|
346 |
|
} |
|
347 |
|
|
|
348 |
|
$params = array('uid' => $uid); |
|
349 |
|
$sql = 'SELECT * FROM apikeys WHERE uid = @@uid@@' |
|
350 |
|
. ' ORDER BY itime DESC'; |
|
351 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
352 |
|
if ($res === FALSE) { |
|
353 |
|
rg_ak_set_error('cannot query'); |
|
354 |
|
break; |
|
355 |
|
} |
|
356 |
|
|
|
357 |
|
$ret = array(); |
|
358 |
|
while (($row = rg_sql_fetch_array($res))) { |
|
359 |
|
$key_id = $row['key_id']; |
|
360 |
|
$ret[$key_id] = $row; |
|
361 |
|
} |
|
362 |
|
rg_sql_free_result($res); |
|
363 |
|
|
|
364 |
|
$a = array('LOADED' => 1, 'list' => $ret); |
|
365 |
|
rg_cache_set($key, $a, RG_SOCKET_NO_WAIT); |
|
366 |
|
|
|
367 |
|
foreach ($ret as $key_id => &$i) |
|
368 |
|
rg_ak_cosmetic($i); |
|
369 |
|
break; |
|
370 |
|
} |
|
371 |
|
|
|
372 |
|
rg_log_exit(); |
|
373 |
|
rg_prof_end('ak_list'); |
|
374 |
|
return $ret; |
|
375 |
|
} |
|
376 |
|
|
|
377 |
|
/* |
|
378 |
|
* Validates a api keys |
|
379 |
|
* Returns the key_id of the matching key or FALSE |
|
380 |
|
*/ |
|
381 |
|
function rg_ak_valid($db, $uid, $apikey) |
|
382 |
|
{ |
|
383 |
|
rg_prof_start('ak_valid'); |
|
384 |
|
rg_log_enter('ak_valid'); |
|
385 |
|
|
|
386 |
|
$ret = FALSE; |
|
387 |
|
while (1) { |
|
388 |
|
$key = 'user' . '::' . $uid . '::' . 'apikeys'; |
|
389 |
|
$c = rg_cache_get($key); |
|
390 |
|
if (($c === FALSE) || !isset($c['LOADED'])) { |
|
391 |
|
$params = array('uid' => $uid); |
|
392 |
|
$sql = 'SELECT * FROM apikeys WHERE uid = @@uid@@'; |
|
393 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
394 |
|
if ($res === FALSE) { |
|
395 |
|
rg_ak_set_error('canno load list'); |
|
396 |
|
break; |
|
397 |
|
} |
|
398 |
|
|
|
399 |
|
$list = array(); |
|
400 |
|
while (($row = rg_sql_fetch_array($res))) { |
|
401 |
|
$key_id = intval($row['key_id']); |
|
402 |
|
unset($row['key_id']); |
|
403 |
|
$list[$key_id] = $row; |
|
404 |
|
} |
|
405 |
|
rg_sql_free_result($res); |
|
406 |
|
|
|
407 |
|
$a = array('LOADED' => 1, 'list' => $list); |
|
408 |
|
rg_cache_set($key, $a, RG_SOCKET_NO_WAIT); |
|
409 |
|
} else { |
|
410 |
|
$list = $c['list']; |
|
411 |
|
} |
|
412 |
|
|
|
413 |
|
foreach ($list as $key_id => $info) { |
|
414 |
|
if (strcmp($info['key'], $apikey) == 0) { |
|
415 |
|
$ret = $key_id; |
|
416 |
|
break; |
|
417 |
|
} |
|
418 |
|
} |
|
419 |
|
|
|
420 |
|
break; |
|
421 |
|
} |
|
422 |
|
|
|
423 |
|
rg_log_exit(); |
|
424 |
|
rg_prof_end('ak_valid'); |
|
425 |
|
return $ret; |
|
426 |
|
} |
|
427 |
|
|
|
428 |
|
/* |
|
429 |
|
* High-level function for listing api keys |
|
430 |
|
*/ |
|
431 |
|
function rg_ak_list_high_level($db, $rg, $paras) |
|
432 |
|
{ |
|
433 |
|
rg_prof_start('ak_list_high_level'); |
|
434 |
|
rg_log_enter('ak_list_high_level'); |
|
435 |
|
|
|
436 |
|
$ret = ''; |
|
437 |
|
|
|
438 |
|
$errmsg = array(); |
|
439 |
|
$rg['HTML:status'] = ''; |
|
440 |
|
|
|
441 |
|
$doit = rg_var_uint('doit'); |
|
442 |
|
while ($doit == 1) { |
|
443 |
|
if (!rg_valid_referer()) { |
|
444 |
|
$errmsg[] = 'invalid referer; try again'; |
|
445 |
|
break; |
|
446 |
|
} |
|
447 |
|
|
|
448 |
|
if (!rg_token_valid($db, $rg, 'ak_list', FALSE)) { |
|
449 |
|
$errmsg[] = 'invalid token; try again.'; |
|
450 |
|
break; |
|
451 |
|
} |
|
452 |
|
|
|
453 |
|
$list = rg_var_str('key_delete_ids'); |
|
454 |
|
$r = rg_ak_remove($db, $rg['login_ui']['uid'], $list); |
|
455 |
|
if ($r !== TRUE) { |
|
456 |
|
$errmsg[] = 'cannot delete: ' . rg_ak_error(); |
|
457 |
|
break; |
|
458 |
|
} |
|
459 |
|
|
|
460 |
|
$rg['HTML:status'] = rg_template( |
|
461 |
|
'user/settings/apikeys/delete_ok.html', |
|
462 |
|
$rg, TRUE /*xss*/); |
|
463 |
|
break; |
|
464 |
|
} |
|
465 |
|
|
|
466 |
|
$r = rg_ak_list($db, $rg['login_ui']['uid']); |
|
467 |
|
if ($r === FALSE) { |
|
468 |
|
$rg['errmsg'] = rg_ak_error(); |
|
469 |
|
$ret .= rg_template('user/settings/apikeys/list_err.html', |
|
470 |
|
$rg, TRUE /*xss*/); |
|
471 |
|
} else { |
|
472 |
|
$rg['rg_form_token'] = rg_token_get($db, $rg, 'ak_list'); |
|
473 |
|
$rg['HTML:errmsg'] = rg_template_errmsg($errmsg); |
|
474 |
|
$ret .= rg_template_table('user/settings/apikeys/list', $r, $rg); |
|
475 |
|
} |
|
476 |
|
|
|
477 |
|
rg_log_exit(); |
|
478 |
|
rg_prof_end('ak_list_high_level'); |
|
479 |
|
return $ret; |
|
480 |
|
} |
|
481 |
|
|
|
482 |
|
/* |
|
483 |
|
* Enroll function for adding a api key |
|
484 |
|
*/ |
|
485 |
|
function rg_ak_add_high_level($db, $rg, $paras) |
|
486 |
|
{ |
|
487 |
|
rg_prof_start('ak_add_high_level'); |
|
488 |
|
rg_log_enter('ak_add_high_level'); |
|
489 |
|
|
|
490 |
|
$ret = ''; |
|
491 |
|
$errmsg = array(); |
|
492 |
|
|
|
493 |
|
$rg['ak'] = array(); |
|
494 |
|
$rg['ak']['name'] = ''; |
|
495 |
|
$rg['ak']['key'] = rg_id(32);; |
|
496 |
|
|
|
497 |
|
$doit = rg_var_uint('doit'); |
|
498 |
|
rg_log('DEBUG: doit=' . $doit); |
|
499 |
|
while ($doit == 1) { |
|
500 |
|
$rg['ak']['name'] = rg_var_str('ak::name'); |
|
501 |
|
$rg['ak']['key'] = rg_var_str('ak::key'); |
|
502 |
|
|
|
503 |
|
if (strlen($rg['ak']['name']) == 0) { |
|
504 |
|
$errmsg[] = 'invalid name'; |
|
505 |
|
break; |
|
506 |
|
} |
|
507 |
|
|
|
508 |
|
if (!rg_valid_referer()) { |
|
509 |
|
$errmsg[] = 'invalid referer; try again'; |
|
510 |
|
break; |
|
511 |
|
} |
|
512 |
|
|
|
513 |
|
if (!rg_token_valid($db, $rg, 'ak_add', FALSE)) { |
|
514 |
|
$errmsg[] = 'invalid token; try again'; |
|
515 |
|
break; |
|
516 |
|
} |
|
517 |
|
|
|
518 |
|
$r = rg_ak_add($db, $rg['login_ui']['uid'], $rg['ak']['key'], |
|
519 |
|
$rg['ak']['name']); |
|
520 |
|
if ($r === FALSE) { |
|
521 |
|
$errmsg[] = rg_ak_error(); |
|
522 |
|
break; |
|
523 |
|
} |
|
524 |
|
|
|
525 |
|
$ret .= rg_template('user/settings/apikeys/add_ok.html', |
|
526 |
|
$rg, TRUE /*xss*/); |
|
527 |
|
|
|
528 |
|
$rg['ak']['name'] = ''; |
|
529 |
|
$rg['ak']['key'] = rg_id(32); |
|
530 |
|
break; |
|
531 |
|
} |
|
532 |
|
|
|
533 |
|
$rg['HTML:errmsg'] = rg_template_errmsg($errmsg); |
|
534 |
|
$rg['rg_form_token'] = rg_token_get($db, $rg, 'ak_add'); |
|
535 |
|
$ret .= rg_template('user/settings/apikeys/add.html', $rg, TRUE /*xss*/); |
|
536 |
|
|
|
537 |
|
rg_log_exit(); |
|
538 |
|
rg_prof_end('ak_add_high_level'); |
|
539 |
|
return $ret; |
|
540 |
|
} |
|
541 |
|
|
|
542 |
|
/* |
|
543 |
|
* Main HL function for api keys |
|
544 |
|
*/ |
|
545 |
|
function rg_ak_high_level($db, &$rg, $paras) |
|
546 |
|
{ |
|
547 |
|
rg_prof_start('ak_high_level'); |
|
548 |
|
rg_log_enter('ak_high_level paras: ' . rg_array2string($paras)); |
|
549 |
|
|
|
550 |
|
$ret = ''; |
|
551 |
|
|
|
552 |
|
$op = empty($paras) ? 'list' : array_shift($paras); |
|
553 |
|
$rg['menu']['ak'][$op] = 1; |
|
554 |
|
|
|
555 |
|
$rg['HTML:menu_level2'] = |
|
556 |
|
rg_template('user/settings/apikeys/menu.html', $rg, TRUE /*xss*/); |
|
557 |
|
|
|
558 |
|
switch ($op) { |
|
559 |
|
case 'add': |
|
560 |
|
$ret .= rg_ak_add_high_level($db, $rg, $paras); |
|
561 |
|
break; |
|
562 |
|
|
|
563 |
|
default: |
|
564 |
|
$ret .= rg_ak_list_high_level($db, $rg, $paras); |
|
565 |
|
break; |
|
566 |
|
} |
|
567 |
|
|
|
568 |
|
$hints = array(); |
|
569 |
|
$hints[]['HTML:hint'] = rg_template('user/settings/apikeys/hints.html', |
|
570 |
|
$rg, TRUE /*xss*/); |
|
571 |
|
$ret .= rg_template_table('hints/list', $hints, $rg); |
|
572 |
|
|
|
573 |
|
rg_log_exit(); |
|
574 |
|
rg_prof_end('ak_high_level'); |
|
575 |
|
return $ret; |
|
576 |
|
} |
|
577 |
|
|
|
578 |
|
?> |
File inc/conn.inc.php changed (mode: 100644) (index ecb8c94..0887a04) |
... |
... |
function rg_conn_prepare($s) |
14 |
14 |
return addcslashes($s, "\n\r\\"); |
return addcslashes($s, "\n\r\\"); |
15 |
15 |
} |
} |
16 |
16 |
|
|
|
17 |
|
/* |
|
18 |
|
* Shutts down a connection |
|
19 |
|
*/ |
|
20 |
|
function rg_conn_shutdown($key, $what) |
|
21 |
|
{ |
|
22 |
|
global $rg_conns; |
|
23 |
|
|
|
24 |
|
if (!isset($rg_conns[$key]['socket'])) |
|
25 |
|
return; |
|
26 |
|
|
|
27 |
|
if (!is_resource($rg_conns[$key]['socket'])) |
|
28 |
|
return; |
|
29 |
|
|
|
30 |
|
@socket_shutdown($rg_conns[$key]['socket'], $what); |
|
31 |
|
rg_log($key . ': shutdown ' . $what); |
|
32 |
|
} |
|
33 |
|
|
17 |
34 |
/* |
/* |
18 |
35 |
* Destroys a connection |
* Destroys a connection |
19 |
36 |
*/ |
*/ |
|
... |
... |
function rg_conn_destroy($key) |
28 |
45 |
if ($rg_conns[$key]['exit_on_close']) |
if ($rg_conns[$key]['exit_on_close']) |
29 |
46 |
exit(1); |
exit(1); |
30 |
47 |
|
|
|
48 |
|
if (isset($rg_conns[$key]['func_destroy'])) |
|
49 |
|
$rg_conns[$key]['func_destroy']($key); |
|
50 |
|
|
31 |
51 |
if (isset($rg_events['r'][$key])) |
if (isset($rg_events['r'][$key])) |
32 |
52 |
unset($rg_events['r'][$key]); |
unset($rg_events['r'][$key]); |
33 |
53 |
if (isset($rg_events['w'][$key])) |
if (isset($rg_events['w'][$key])) |
|
... |
... |
function rg_conn_new($key, $socket) |
46 |
66 |
global $rg_conns; |
global $rg_conns; |
47 |
67 |
global $rg_events; |
global $rg_events; |
48 |
68 |
|
|
|
69 |
|
$ip = '?'; |
|
70 |
|
$port ='?'; |
|
71 |
|
if (strcmp($key, 'master') != 0) |
|
72 |
|
@socket_getpeername($socket, $ip, $port); |
|
73 |
|
|
49 |
74 |
$rg_conns[$key] = array( |
$rg_conns[$key] = array( |
50 |
75 |
'socket' => $socket, |
'socket' => $socket, |
51 |
76 |
'recv' => '', |
'recv' => '', |
|
... |
... |
function rg_conn_new($key, $socket) |
53 |
78 |
'itime' => time(), |
'itime' => time(), |
54 |
79 |
'exit_on_close' => 0, |
'exit_on_close' => 0, |
55 |
80 |
'func_error' => 'rg_conn_func_error', |
'func_error' => 'rg_conn_func_error', |
56 |
|
'func_close' => 'rg_conn_func_close' |
|
|
81 |
|
'func_close' => 'rg_conn_func_close', |
|
82 |
|
'ip' => $ip, |
|
83 |
|
'port' => $port |
57 |
84 |
); |
); |
58 |
85 |
|
|
59 |
86 |
$rg_events['r'][$key] = $socket; |
$rg_events['r'][$key] = $socket; |
|
... |
... |
function rg_conn_send($key) |
85 |
112 |
rg_log('SEND: ' . $s['send']); |
rg_log('SEND: ' . $s['send']); |
86 |
113 |
$r = @socket_send($s['socket'], $s['send'], strlen($s['send']), 0); |
$r = @socket_send($s['socket'], $s['send'], strlen($s['send']), 0); |
87 |
114 |
if ($r === FALSE) { |
if ($r === FALSE) { |
88 |
|
rg_log('Cannot receive!'); |
|
|
115 |
|
rg_log('Cannot send: ' . socket_strerror(socket_last_error())); |
89 |
116 |
$s['func_error']($key); |
$s['func_error']($key); |
90 |
117 |
rg_conn_destroy($key); |
rg_conn_destroy($key); |
91 |
118 |
return FALSE; |
return FALSE; |
|
... |
... |
function rg_conn_recv($key) |
111 |
138 |
if (isset($s['func_new'])) { |
if (isset($s['func_new'])) { |
112 |
139 |
$client = @socket_accept($s['socket']); |
$client = @socket_accept($s['socket']); |
113 |
140 |
if ($client === FALSE) { |
if ($client === FALSE) { |
114 |
|
rg_log('Cannot accept!'); |
|
|
141 |
|
rg_log($key . ':Cannot accept!'); |
115 |
142 |
return; |
return; |
116 |
143 |
} |
} |
117 |
144 |
|
|
|
... |
... |
function rg_conn_recv($key) |
129 |
156 |
|
|
130 |
157 |
$r = @socket_recv($s['socket'], $buf, 4096, 0); |
$r = @socket_recv($s['socket'], $buf, 4096, 0); |
131 |
158 |
if ($r === FALSE) { |
if ($r === FALSE) { |
132 |
|
rg_log('Cannot receive!'); |
|
|
159 |
|
rg_log($key . ':Cannot receive (err): ' . socket_strerror(socket_last_error())); |
133 |
160 |
$s['func_error']($key); |
$s['func_error']($key); |
134 |
161 |
rg_conn_destroy($key); |
rg_conn_destroy($key); |
135 |
162 |
return FALSE; |
return FALSE; |
136 |
163 |
} |
} |
137 |
164 |
if ($r === 0) { |
if ($r === 0) { |
138 |
|
rg_log('Cannot receive!'); |
|
|
165 |
|
rg_log($key . ':Cannot receive (0): ' . socket_strerror(socket_last_error())); |
139 |
166 |
$s['func_close']($key); |
$s['func_close']($key); |
140 |
167 |
rg_conn_destroy($key); |
rg_conn_destroy($key); |
141 |
168 |
return FALSE; |
return FALSE; |
|
... |
... |
function rg_conn_recv($key) |
150 |
177 |
} |
} |
151 |
178 |
|
|
152 |
179 |
if (!isset($s['func_cmd'])) { |
if (!isset($s['func_cmd'])) { |
153 |
|
rg_log_ml('key=' . $key . '; s: ' . print_r($s, TRUE)); |
|
154 |
|
rg_log('Neithter func_data nor func_cmd present!'); |
|
|
180 |
|
rg_log_ml($key . ': s: ' . print_r($s, TRUE)); |
|
181 |
|
rg_log($key . ':Neither func_data nor func_cmd present!'); |
155 |
182 |
return; |
return; |
156 |
183 |
} |
} |
157 |
184 |
|
|
|
... |
... |
function rg_conn_wait($timeout) |
186 |
213 |
if ($r === 0) |
if ($r === 0) |
187 |
214 |
return; |
return; |
188 |
215 |
|
|
|
216 |
|
if (!empty($r2)) |
|
217 |
|
rg_log_ml('read events: ' . print_r($r2, TRUE)); |
189 |
218 |
foreach ($r2 as $key => $sock) |
foreach ($r2 as $key => $sock) |
190 |
219 |
rg_conn_recv($key); |
rg_conn_recv($key); |
191 |
220 |
|
|
|
221 |
|
if (!empty($w2)) |
|
222 |
|
rg_log_ml('write events: ' . print_r($w2, TRUE)); |
192 |
223 |
foreach ($w2 as $key => $sock) |
foreach ($w2 as $key => $sock) |
193 |
224 |
rg_conn_send($key); |
rg_conn_send($key); |
194 |
225 |
|
|
|
226 |
|
if (!empty($e2)) |
|
227 |
|
rg_log_ml('error events: ' . print_r($e2, TRUE)); |
195 |
228 |
foreach ($e2 as $key => $sock) |
foreach ($e2 as $key => $sock) |
196 |
229 |
rg_conn_destroy($key); |
rg_conn_destroy($key); |
197 |
230 |
} |
} |
File inc/repo.inc.php changed (mode: 100644) (index 93f20df..ce5f443) |
... |
... |
function rg_repo_cosmetic($db, &$row) |
138 |
138 |
$row['clone_url'] = $row['clone_url_git']; |
$row['clone_url'] = $row['clone_url_git']; |
139 |
139 |
} |
} |
140 |
140 |
|
|
141 |
|
$master_repo = '-'; |
|
|
141 |
|
$row['master_name'] = '-'; |
142 |
142 |
if ($row['master'] > 0) { |
if ($row['master'] > 0) { |
143 |
|
$master_repo = '?'; |
|
144 |
143 |
$_mi = rg_repo_info($db, $row['master'], 0, ''); |
$_mi = rg_repo_info($db, $row['master'], 0, ''); |
145 |
144 |
if ($_mi['exists'] = 1) |
if ($_mi['exists'] = 1) |
146 |
|
$master_repo = $_mi['name']; |
|
|
145 |
|
$row['master_name'] = $_mi['name']; |
147 |
146 |
} |
} |
148 |
|
$row['clone_of'] = $master_repo; |
|
149 |
147 |
|
|
150 |
148 |
if (isset($row['disk_used_mb'])) |
if (isset($row['disk_used_mb'])) |
151 |
149 |
$row['disk_used'] = rg_1024($row['disk_used_mb'] * 1024 * 1024); |
$row['disk_used'] = rg_1024($row['disk_used_mb'] * 1024 * 1024); |
|
... |
... |
function rg_repo_edit_high_level($db, &$rg) |
1813 |
1811 |
$x['owner'] = $rg['ri']['uid']; |
$x['owner'] = $rg['ri']['uid']; |
1814 |
1812 |
$x['uid'] = $rg['login_ui']['uid']; |
$x['uid'] = $rg['login_ui']['uid']; |
1815 |
1813 |
$x['username'] = $rg['login_ui']['username']; |
$x['username'] = $rg['login_ui']['username']; |
1816 |
|
$x['needed_rights'] = 'E'; |
|
|
1814 |
|
$x['needed_rights'] = 'E'; // E = create/edit |
1817 |
1815 |
$x['ip'] = $rg['ip']; |
$x['ip'] = $rg['ip']; |
1818 |
1816 |
$x['misc'] = ""; |
$x['misc'] = ""; |
1819 |
1817 |
if (rg_rights_allow($db, $x) !== TRUE) { |
if (rg_rights_allow($db, $x) !== TRUE) { |
|
... |
... |
function rg_repo_commit_labels_html($db, $repo_id, $commit) |
2254 |
2252 |
return $ret; |
return $ret; |
2255 |
2253 |
} |
} |
2256 |
2254 |
|
|
|
2255 |
|
/* |
|
2256 |
|
* API dispatch function |
|
2257 |
|
*/ |
|
2258 |
|
function rg_repo_api($db, $a) |
|
2259 |
|
{ |
|
2260 |
|
rg_prof_start('repo_api'); |
|
2261 |
|
rg_log_enter('repo_api'); |
|
2262 |
|
|
|
2263 |
|
$cmd = $a['cmd']; |
|
2264 |
|
|
|
2265 |
|
$ret = array(); |
|
2266 |
|
while (1) { |
|
2267 |
|
if (isset($a['name'])) { |
|
2268 |
|
$ri = rg_repo_info($db, 0, $a['connect_uid'], |
|
2269 |
|
$a['name']); |
|
2270 |
|
} else if (isset($a['repo_id'])) { |
|
2271 |
|
$repo_id = intval($a['repo_id']); |
|
2272 |
|
$ri = rg_repo_info($db, $repo_id, '', ''); |
|
2273 |
|
} else { |
|
2274 |
|
$ri = FALSE; |
|
2275 |
|
} |
|
2276 |
|
|
|
2277 |
|
if (strcmp($cmd, 'repo_list') == 0) { |
|
2278 |
|
$params = array('uid' => $a['cui']['uid']); |
|
2279 |
|
$sql = 'SELECT name FROM repos' |
|
2280 |
|
. ' WHERE uid = @@uid@@'; |
|
2281 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
2282 |
|
if ($res === FALSE) { |
|
2283 |
|
$ret['error'] = 'internal error'; |
|
2284 |
|
break; |
|
2285 |
|
} |
|
2286 |
|
$ret = array(); |
|
2287 |
|
while (($row = rg_sql_fetch_array($res))) { |
|
2288 |
|
$ret[] = $row['name']; |
|
2289 |
|
} |
|
2290 |
|
rg_sql_free_result($res); |
|
2291 |
|
break; |
|
2292 |
|
} |
|
2293 |
|
|
|
2294 |
|
// From this point below, we have a repo |
|
2295 |
|
|
|
2296 |
|
if ($ri === FALSE) { |
|
2297 |
|
$ret['error'] = 'no repo_id=/name= specified'; |
|
2298 |
|
break; |
|
2299 |
|
} |
|
2300 |
|
|
|
2301 |
|
if ($ri['exists'] != 1) { |
|
2302 |
|
$ret['error'] = 'invalid user or no rights'; |
|
2303 |
|
break; |
|
2304 |
|
} |
|
2305 |
|
|
|
2306 |
|
$x = array(); |
|
2307 |
|
$x['obj_id'] = $ri['repo_id']; |
|
2308 |
|
$x['type'] = 'repo'; |
|
2309 |
|
$x['owner'] = $ri['uid']; |
|
2310 |
|
$x['uid'] = $a['cui']['uid']; |
|
2311 |
|
$x['username'] = $a['cui']['username']; |
|
2312 |
|
$x['needed_rights'] = 'A'; // A = Access repo; E = create/edit |
|
2313 |
|
$x['ip'] = $a['ip']; |
|
2314 |
|
$x['misc'] = ''; |
|
2315 |
|
|
|
2316 |
|
if (strcmp($cmd, 'repo_info') == 0) { |
|
2317 |
|
if (rg_rights_allow($db, $x) !== TRUE) { |
|
2318 |
|
$ret['error'] = 'invalid user or no rights'; |
|
2319 |
|
break; |
|
2320 |
|
} |
|
2321 |
|
|
|
2322 |
|
$ret = $ri; |
|
2323 |
|
break; |
|
2324 |
|
} |
|
2325 |
|
|
|
2326 |
|
if (strcmp($cmd, 'repo_pr_list') == 0) { |
|
2327 |
|
if (rg_rights_allow($db, $x) !== TRUE) { |
|
2328 |
|
$ret['error'] = 'invalid user or no rights'; |
|
2329 |
|
break; |
|
2330 |
|
} |
|
2331 |
|
|
|
2332 |
|
$params = array('repo_id' => $ri['repo_id']); |
|
2333 |
|
$sql = 'SELECT * FROM merge_requests' |
|
2334 |
|
. ' WHERE repo_id = @@repo_id@@'; |
|
2335 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
2336 |
|
if ($res === FALSE) { |
|
2337 |
|
$ret['error'] = 'internal error'; |
|
2338 |
|
break; |
|
2339 |
|
} |
|
2340 |
|
$ret = array(); |
|
2341 |
|
while (($row = rg_sql_fetch_array($res))) { |
|
2342 |
|
$ret[] = $row; |
|
2343 |
|
} |
|
2344 |
|
rg_sql_free_result($res); |
|
2345 |
|
break; |
|
2346 |
|
} |
|
2347 |
|
|
|
2348 |
|
if (strcmp($cmd, 'repo_bug_list') == 0) { |
|
2349 |
|
$y = $x; |
|
2350 |
|
$y['needed_rights'] = 'a'; // a = Access bug repo |
|
2351 |
|
if (rg_rights_allow($db, $y) !== TRUE) { |
|
2352 |
|
$ret['error'] = 'invalid user or no rights'; |
|
2353 |
|
break; |
|
2354 |
|
} |
|
2355 |
|
|
|
2356 |
|
$params = array('repo_id' => $ri['repo_id']); |
|
2357 |
|
$sql = 'SELECT bug_id FROM bugs' |
|
2358 |
|
. ' WHERE repo_id = @@repo_id@@'; |
|
2359 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
2360 |
|
if ($res === FALSE) { |
|
2361 |
|
$ret['error'] = 'internal error'; |
|
2362 |
|
break; |
|
2363 |
|
} |
|
2364 |
|
$ret = array(); |
|
2365 |
|
while (($row = rg_sql_fetch_array($res))) { |
|
2366 |
|
$ret[] = $row['bug_id']; |
|
2367 |
|
} |
|
2368 |
|
rg_sql_free_result($res); |
|
2369 |
|
break; |
|
2370 |
|
} |
|
2371 |
|
|
|
2372 |
|
// TODO: for bugs, we do layer violation here! |
|
2373 |
|
if (strcmp($cmd, 'repo_bug_info') == 0) { |
|
2374 |
|
if (!isset($a['bug_id'])) { |
|
2375 |
|
$ret['error'] = 'bug_id= para not specified'; |
|
2376 |
|
break; |
|
2377 |
|
} |
|
2378 |
|
$bug_id = intval($a['bug_id']); |
|
2379 |
|
|
|
2380 |
|
$y = $x; |
|
2381 |
|
$y['needed_rights'] = 'a'; // a = Access bug repo |
|
2382 |
|
if (rg_rights_allow($db, $y) !== TRUE) { |
|
2383 |
|
$ret['error'] = 'invalid user or no rights'; |
|
2384 |
|
break; |
|
2385 |
|
} |
|
2386 |
|
|
|
2387 |
|
$bi = rg_bug_info($db, $ri['repo_id'], $bug_id); |
|
2388 |
|
if ($bi['exists'] != 1) { |
|
2389 |
|
$ret['error'] = 'bug does not exists'; |
|
2390 |
|
break; |
|
2391 |
|
} |
|
2392 |
|
|
|
2393 |
|
$ret = $bi; |
|
2394 |
|
break; |
|
2395 |
|
} |
|
2396 |
|
|
|
2397 |
|
$ret['error'] = 'invalid command'; |
|
2398 |
|
break; |
|
2399 |
|
} |
|
2400 |
|
|
|
2401 |
|
rg_log_exit(); |
|
2402 |
|
rg_prof_end('repo_api'); |
|
2403 |
|
return $ret; |
|
2404 |
|
} |
|
2405 |
|
|
2257 |
2406 |
?> |
?> |
File inc/user.inc.php changed (mode: 100644) (index ff1c4cd..36975b5) |
... |
... |
function rg_user_edit($db, $d) |
528 |
528 |
|
|
529 |
529 |
if ($d['uid'] == 0) { // add |
if ($d['uid'] == 0) { // add |
530 |
530 |
$d['uid'] = $row['uid']; |
$d['uid'] = $row['uid']; |
531 |
|
rg_cache_set('user' . '::' . $d['uid'] . '::' . ':info', |
|
|
531 |
|
rg_cache_set('user' . '::' . $d['uid'] . '::' . 'info', |
532 |
532 |
$d, RG_SOCKET_NO_WAIT); |
$d, RG_SOCKET_NO_WAIT); |
533 |
533 |
|
|
534 |
534 |
$event = array('category' => 2000, 'prio' => 50, |
$event = array('category' => 2000, 'prio' => 50, |
|
... |
... |
function rg_user_remove($db, $rg, $uid) |
594 |
594 |
rg_sql_free_result($res); |
rg_sql_free_result($res); |
595 |
595 |
|
|
596 |
596 |
// invalidate cache |
// invalidate cache |
597 |
|
rg_cache_unset('user' . '::' . $uid . 'info', RG_SOCKET_NO_WAIT); |
|
|
597 |
|
rg_cache_unset('user' . '::' . $uid, RG_SOCKET_NO_WAIT); |
598 |
598 |
|
|
599 |
599 |
$ret = TRUE; |
$ret = TRUE; |
600 |
600 |
break; |
break; |
|
... |
... |
function rg_user_forgot_pass_uid($db, $token) |
1160 |
1160 |
rg_prof_start("user_forgot_pass_uid"); |
rg_prof_start("user_forgot_pass_uid"); |
1161 |
1161 |
rg_log_enter("user_forgot_pass_uid: token=$token"); |
rg_log_enter("user_forgot_pass_uid: token=$token"); |
1162 |
1162 |
|
|
|
1163 |
|
if (strlen($token) > 20) |
|
1164 |
|
$token = substr($token, 0, 20); |
|
1165 |
|
|
1163 |
1166 |
$ret = array(); |
$ret = array(); |
1164 |
1167 |
$ret['ok'] = 0; |
$ret['ok'] = 0; |
1165 |
1168 |
$ret['uid'] = 0; |
$ret['uid'] = 0; |
|
... |
... |
function rg_user_forgot_pass_uid($db, $token) |
1172 |
1175 |
. " AND expire > @@now@@"; |
. " AND expire > @@now@@"; |
1173 |
1176 |
$res = rg_sql_query_params($db, $sql, $params); |
$res = rg_sql_query_params($db, $sql, $params); |
1174 |
1177 |
if ($res === FALSE) { |
if ($res === FALSE) { |
1175 |
|
rg_user_set_error("cannot lookup token (" . rg_sql_error() . ")"); |
|
|
1178 |
|
rg_user_set_error('cannot lookup token'); |
1176 |
1179 |
break; |
break; |
1177 |
1180 |
} |
} |
1178 |
1181 |
|
|
|
... |
... |
function rg_user_forgot_pass_uid($db, $token) |
1182 |
1185 |
if ($rows > 0) |
if ($rows > 0) |
1183 |
1186 |
$row = rg_sql_fetch_array($res); |
$row = rg_sql_fetch_array($res); |
1184 |
1187 |
rg_sql_free_result($res); |
rg_sql_free_result($res); |
1185 |
|
if ($rows == 0) |
|
|
1188 |
|
if ($rows == 0) { |
|
1189 |
|
rg_user_set_error('invalid token'); |
1186 |
1190 |
break; |
break; |
|
1191 |
|
} |
1187 |
1192 |
|
|
1188 |
1193 |
$ret['uid'] = $row['uid']; |
$ret['uid'] = $row['uid']; |
1189 |
1194 |
break; |
break; |
|
... |
... |
function rg_user_forgot_pass_mail_prepare($db, $email) |
1250 |
1255 |
|
|
1251 |
1256 |
/* |
/* |
1252 |
1257 |
* Reset password function (send mail) |
* Reset password function (send mail) |
1253 |
|
* TODO: Convert to rg_mail_template! Maybe also other functions! |
|
1254 |
1258 |
*/ |
*/ |
1255 |
|
function rg_user_forgot_pass_mail($db, $email) |
|
|
1259 |
|
function rg_user_forgot_pass_mail($db, $rg, $email) |
1256 |
1260 |
{ |
{ |
1257 |
1261 |
global $php_errormsg; |
global $php_errormsg; |
1258 |
1262 |
global $rg_admin_name, $rg_admin_email; |
global $rg_admin_name, $rg_admin_email; |
|
... |
... |
function rg_user_forgot_pass_mail($db, $email) |
1274 |
1278 |
|
|
1275 |
1279 |
$ret['exists'] = 1; |
$ret['exists'] = 1; |
1276 |
1280 |
|
|
1277 |
|
$headers = "From: $rg_admin_name <$rg_admin_email>"; |
|
1278 |
|
|
|
1279 |
|
$base_url = rg_base_url(); |
|
|
1281 |
|
$rg['ui'] = array('email' => $email); |
|
1282 |
|
$rg['forgot_token'] = $r['token']; |
1280 |
1283 |
|
|
1281 |
|
if (!mail($email, |
|
1282 |
|
"Forgot password", |
|
1283 |
|
"Hello!\n\n" |
|
1284 |
|
. "If you want to reset the password, follow:\n" |
|
1285 |
|
. $base_url |
|
1286 |
|
. rg_re_url("/op/forgot_link") . "/" . $r['token'] |
|
1287 |
|
. "\n\nRocketGit team", |
|
1288 |
|
$headers, |
|
1289 |
|
"-f $rg_admin_email")) { |
|
1290 |
|
rg_user_set_error("cannot send mail ($php_errormsg)!"); |
|
|
1284 |
|
$r = rg_mail_template('mail/user/forgot/recover', $rg); |
|
1285 |
|
if ($r === FALSE) { |
|
1286 |
|
rg_user_set_error(rg_mail_error()); |
1291 |
1287 |
break; |
break; |
1292 |
1288 |
} |
} |
1293 |
1289 |
|
|
|
... |
... |
function rg_user_forgot_pass_mail($db, $email) |
1295 |
1291 |
break; |
break; |
1296 |
1292 |
} |
} |
1297 |
1293 |
|
|
1298 |
|
rg_log("DEBUG: user_forgot_pass_mail: ret=" . rg_array2string($ret) . "."); |
|
|
1294 |
|
//rg_log("DEBUG: user_forgot_pass_mail: ret=" . rg_array2string($ret) . "."); |
1299 |
1295 |
rg_log_exit(); |
rg_log_exit(); |
1300 |
1296 |
rg_prof_end('user_forgot_pass_mail'); |
rg_prof_end('user_forgot_pass_mail'); |
1301 |
1297 |
return $ret; |
return $ret; |
|
... |
... |
function rg_user_edit_high_level($db, &$rg) |
1640 |
1636 |
return $ret; |
return $ret; |
1641 |
1637 |
} |
} |
1642 |
1638 |
|
|
|
1639 |
|
/* |
|
1640 |
|
* API dispatch function |
|
1641 |
|
*/ |
|
1642 |
|
function rg_user_api($db, $a) |
|
1643 |
|
{ |
|
1644 |
|
rg_prof_start('user_api'); |
|
1645 |
|
rg_log_enter('user_api'); |
|
1646 |
|
|
|
1647 |
|
$cmd = $a['cmd']; |
|
1648 |
|
|
|
1649 |
|
$ret = array(); |
|
1650 |
|
while (1) { |
|
1651 |
|
if (isset($a['user'])) { |
|
1652 |
|
$ui = rg_user_info($db, 0, $a['user'], ''); |
|
1653 |
|
} else if (isset($a['uid'])) { |
|
1654 |
|
$ui = rg_user_info($db, $a['uid'], '', ''); |
|
1655 |
|
} else { |
|
1656 |
|
$ret['error'] = 'no uid=/user= specified'; |
|
1657 |
|
break; |
|
1658 |
|
} |
|
1659 |
|
if ($ui['exists'] != 1) { |
|
1660 |
|
$ret['error'] = 'invalid user or no rights'; |
|
1661 |
|
break; |
|
1662 |
|
} |
|
1663 |
|
|
|
1664 |
|
// TODO: allow also a master user to access user info |
|
1665 |
|
if (($a['cui']['is_admin'] != 1) |
|
1666 |
|
&& ($ui['uid'] != $a['cui']['uid'])) { |
|
1667 |
|
$ret['error'] = 'invalid user or no rights'; |
|
1668 |
|
rg_log('user has no rights'); |
|
1669 |
|
break; |
|
1670 |
|
} |
|
1671 |
|
|
|
1672 |
|
if (strcmp($cmd, 'user_info') == 0) { |
|
1673 |
|
$ret = $ui; |
|
1674 |
|
break; |
|
1675 |
|
} |
|
1676 |
|
|
|
1677 |
|
if (strcmp($cmd, 'user_ssh_keys_list') == 0) { |
|
1678 |
|
$ret = rg_keys_list($db, $a['cui']); |
|
1679 |
|
break; |
|
1680 |
|
} |
|
1681 |
|
|
|
1682 |
|
if (strcmp($cmd, 'user_rights_list') == 0) { |
|
1683 |
|
$params = array('who' => $ui['uid']); |
|
1684 |
|
$sql = 'SELECT * FROM rights' |
|
1685 |
|
. ' WHERE who = @@who@@'; |
|
1686 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
1687 |
|
if ($res === FALSE) { |
|
1688 |
|
$ret['error'] = 'internal error'; |
|
1689 |
|
break; |
|
1690 |
|
} |
|
1691 |
|
$ret = array(); |
|
1692 |
|
while (($row = rg_sql_fetch_array($res))) { |
|
1693 |
|
rg_rights_cosmetic($db, $row); |
|
1694 |
|
$ret[] = $row; |
|
1695 |
|
} |
|
1696 |
|
rg_sql_free_result($res); |
|
1697 |
|
break; |
|
1698 |
|
} |
|
1699 |
|
|
|
1700 |
|
if (strcmp($cmd, 'user_wh_list') == 0) { |
|
1701 |
|
$r = rg_wh_list($db, $ui['uid']); |
|
1702 |
|
if ($r['ok'] !== 1) { |
|
1703 |
|
$ret['error'] = rg_wh_error(); |
|
1704 |
|
break; |
|
1705 |
|
} |
|
1706 |
|
rg_wh_cosmetic($r['list']); |
|
1707 |
|
// list is indexed by hook_id, remove this |
|
1708 |
|
$ret = array(); |
|
1709 |
|
foreach ($r['list'] as $index => $d) |
|
1710 |
|
$ret[] = $d; |
|
1711 |
|
break; |
|
1712 |
|
} |
|
1713 |
|
|
|
1714 |
|
$ret['error'] = 'invalid command'; |
|
1715 |
|
break; |
|
1716 |
|
} |
|
1717 |
|
|
|
1718 |
|
rg_log_exit(); |
|
1719 |
|
rg_prof_end('user_api'); |
|
1720 |
|
return $ret; |
|
1721 |
|
} |
|
1722 |
|
|
1643 |
1723 |
?> |
?> |
File inc/user/keys/keys.php changed (mode: 100644) (index 2c9c6f2..dfd7d1e) |
1 |
1 |
<?php |
<?php |
2 |
|
rg_log("FILE: /inc/user/keys/keys"); |
|
|
2 |
|
rg_log('FILE: /inc/user/keys/keys'); |
3 |
3 |
|
|
4 |
4 |
$_keys = ''; |
$_keys = ''; |
5 |
5 |
|
|
|
... |
... |
$del_errmsg = array(); |
9 |
9 |
$key = trim(rg_var_str('key')); |
$key = trim(rg_var_str('key')); |
10 |
10 |
$key = str_replace("\n", ' ', $key); |
$key = str_replace("\n", ' ', $key); |
11 |
11 |
$key = str_replace("\r", ' ', $key); |
$key = str_replace("\r", ' ', $key); |
12 |
|
$key_id = rg_var_uint("key_id"); |
|
13 |
|
$key_delete_ids = rg_var_str("key_delete_ids"); |
|
|
12 |
|
$key_id = rg_var_uint('key_id'); |
|
13 |
|
$key_delete_ids = rg_var_str('key_delete_ids'); |
14 |
14 |
|
|
15 |
15 |
$rg['HTML:add_status'] = ''; |
$rg['HTML:add_status'] = ''; |
16 |
16 |
$rg['HTML:del_status'] = ''; |
$rg['HTML:del_status'] = ''; |
17 |
17 |
|
|
18 |
|
while (rg_var_uint("add") == 1) { |
|
|
18 |
|
while (rg_var_uint('add') == 1) { |
19 |
19 |
if (!rg_valid_referer()) { |
if (!rg_valid_referer()) { |
20 |
|
$add_errmsg[] = "invalid referer; try again"; |
|
|
20 |
|
$add_errmsg[] = 'invalid referer; try again'; |
21 |
21 |
break; |
break; |
22 |
22 |
} |
} |
23 |
23 |
|
|
24 |
24 |
if (!rg_token_valid($db, $rg, 'keys', FALSE)) { |
if (!rg_token_valid($db, $rg, 'keys', FALSE)) { |
25 |
|
$add_errmsg[] = "Invalid token. Try again."; |
|
|
25 |
|
$add_errmsg[] = 'invalid token; try again'; |
26 |
26 |
break; |
break; |
27 |
27 |
} |
} |
28 |
28 |
|
|
|
... |
... |
while (rg_var_uint("add") == 1) { |
32 |
32 |
break; |
break; |
33 |
33 |
} |
} |
34 |
34 |
|
|
35 |
|
$rg['HTML:add_status'] = rg_template("user/keys/add_ok.html", $rg, TRUE /* xss */); |
|
|
35 |
|
$rg['HTML:add_status'] = rg_template('user/keys/add_ok.html', $rg, TRUE /* xss */); |
36 |
36 |
$key = ''; |
$key = ''; |
37 |
37 |
break; |
break; |
38 |
38 |
} |
} |
39 |
39 |
|
|
40 |
|
while (rg_var_uint("delete") == 1) { |
|
|
40 |
|
while (rg_var_uint('delete') == 1) { |
41 |
41 |
if (!rg_valid_referer()) { |
if (!rg_valid_referer()) { |
42 |
|
$del_errmsg[] = "invalid referer; try again"; |
|
|
42 |
|
$del_errmsg[] = 'invalid referer; try again'; |
43 |
43 |
break; |
break; |
44 |
44 |
} |
} |
45 |
45 |
|
|
46 |
46 |
if (!rg_token_valid($db, $rg, 'keys', FALSE)) { |
if (!rg_token_valid($db, $rg, 'keys', FALSE)) { |
47 |
|
$del_errmsg[] = "Invalid token. Try again."; |
|
|
47 |
|
$del_errmsg[] = 'invalid token; try again'; |
48 |
48 |
break; |
break; |
49 |
49 |
} |
} |
50 |
50 |
|
|
51 |
51 |
if (empty($key_delete_ids)) { |
if (empty($key_delete_ids)) { |
52 |
|
$del_errmsg[] = "No keys selected."; |
|
|
52 |
|
$del_errmsg[] = 'no keys selected'; |
53 |
53 |
break; |
break; |
54 |
54 |
} |
} |
55 |
55 |
|
|
|
... |
... |
while (rg_var_uint("delete") == 1) { |
58 |
58 |
break; |
break; |
59 |
59 |
} |
} |
60 |
60 |
|
|
61 |
|
$rg['HTML:del_status'] = rg_template("user/keys/remove_ok.html", $rg, TRUE /* xss */); |
|
|
61 |
|
$rg['HTML:del_status'] = rg_template('user/keys/remove_ok.html', $rg, TRUE /* xss */); |
62 |
62 |
break; |
break; |
63 |
63 |
} |
} |
64 |
64 |
|
|
|
... |
... |
$rg['HTML:del_errmsg'] = rg_template_errmsg($del_errmsg); |
67 |
67 |
|
|
68 |
68 |
$rg['key'] = $key; |
$rg['key'] = $key; |
69 |
69 |
$rg['rg_form_token'] = rg_token_get($db, $rg, 'keys'); |
$rg['rg_form_token'] = rg_token_get($db, $rg, 'keys'); |
70 |
|
$rg['HTML:add_form'] = rg_template("user/keys/add.html", $rg, TRUE /*xss*/); |
|
|
70 |
|
$rg['HTML:add_form'] = rg_template('user/keys/add.html', $rg, TRUE /*xss*/); |
71 |
71 |
|
|
72 |
72 |
$keys_list = rg_keys_list($db, $rg['login_ui']); |
$keys_list = rg_keys_list($db, $rg['login_ui']); |
73 |
73 |
if ($keys_list === FALSE) |
if ($keys_list === FALSE) |
74 |
|
$rg['HTML:keys'] = rg_warning("Could not load keys. Try later."); // TODO |
|
|
74 |
|
$rg['HTML:keys'] = rg_warning('Could not load keys. Try later.'); // TODO |
75 |
75 |
else |
else |
76 |
|
$rg['HTML:keys'] = rg_template_table("user/keys/list", $keys_list, $rg); |
|
|
76 |
|
$rg['HTML:keys'] = rg_template_table('user/keys/list', $keys_list, $rg); |
77 |
77 |
|
|
78 |
78 |
$hints = array(); |
$hints = array(); |
79 |
79 |
if ($rg_ssh_port != 0) |
if ($rg_ssh_port != 0) |
80 |
|
$hints[]['HTML:hint'] = rg_template("hints/ssh/key.html", $rg, TRUE /* xss */); |
|
81 |
|
$rg['HTML:hints'] = rg_template_table("hints/list", $hints, $rg); |
|
|
80 |
|
$hints[]['HTML:hint'] = rg_template('hints/ssh/key.html', $rg, TRUE /* xss */); |
|
81 |
|
$rg['HTML:hints'] = rg_template_table('hints/list', $hints, $rg); |
82 |
82 |
|
|
83 |
83 |
$_keys .= rg_template('user/keys/main.html', $rg, TRUE /*xss*/); |
$_keys .= rg_template('user/keys/main.html', $rg, TRUE /*xss*/); |
84 |
84 |
?> |
?> |
File inc/wh/build.inc.php changed (mode: 100644) (index f694916..decb485) |
... |
... |
require_once($INC . "/wh/core.inc.php"); |
9 |
9 |
|
|
10 |
10 |
$rg_wh_build_functions = array( |
$rg_wh_build_functions = array( |
11 |
11 |
'wh_build_send' => 'rg_wh_build_send', |
'wh_build_send' => 'rg_wh_build_send', |
12 |
|
'wh_build_send_one' => 'rg_wh_build_send_one' |
|
|
12 |
|
'wh_build_send_one' => 'rg_wh_build_send_one', |
|
13 |
|
'wh_build_job_done' => 'rg_wh_build_job_done' |
13 |
14 |
); |
); |
14 |
15 |
rg_event_register_functions($rg_wh_build_functions); |
rg_event_register_functions($rg_wh_build_functions); |
15 |
16 |
|
|
16 |
17 |
|
|
|
18 |
|
/* |
|
19 |
|
* This is called when a job is done |
|
20 |
|
*/ |
|
21 |
|
function rg_wh_build_job_done($db, $ev) |
|
22 |
|
{ |
|
23 |
|
rg_prof_start('wh_build_job_done'); |
|
24 |
|
rg_log_ml('wh_build_job_done: ev: ' . print_r($ev, TRUE)); |
|
25 |
|
|
|
26 |
|
$ret = FALSE; |
|
27 |
|
while (1) { |
|
28 |
|
$s = $ev['status']; |
|
29 |
|
$out = 'Worker: ' . $ev['job']['worker_name'] . "\n"; |
|
30 |
|
$out .= 'Date (UTC): ' |
|
31 |
|
. gmdate('Y-m-d H:i', $ev['job']['done']) . "\n"; |
|
32 |
|
$out .= 'Elapsed time: ' |
|
33 |
|
. ($ev['job']['done'] - $ev['job']['worker_started']) |
|
34 |
|
. 's' . "\n"; |
|
35 |
|
$out .= "\n"; |
|
36 |
|
$out .= 'Packages:' . "\n" . $s['packages']; |
|
37 |
|
foreach ($s['cmds'] as $index => $i) { |
|
38 |
|
if (empty($ev['job']['cmds'][$index]['cmd'])) |
|
39 |
|
continue; |
|
40 |
|
|
|
41 |
|
$out .= "\n\n" . 'Command[' |
|
42 |
|
. $ev['job']['cmds'][$index]['cmd'] . ']: ' |
|
43 |
|
. "\n" . $i['log']; |
|
44 |
|
} |
|
45 |
|
|
|
46 |
|
rg_wh_set_last_output($db, $ev['ui']['uid'], |
|
47 |
|
$ev['job']['hook_id'], $out); |
|
48 |
|
$ret = array(); |
|
49 |
|
break; |
|
50 |
|
} |
|
51 |
|
|
|
52 |
|
rg_prof_end('wh_build_job_done'); |
|
53 |
|
return $ret; |
|
54 |
|
} |
|
55 |
|
|
17 |
56 |
/* |
/* |
18 |
57 |
* Helper for rg_wh_build_send |
* Helper for rg_wh_build_send |
19 |
58 |
*/ |
*/ |
|
... |
... |
function rg_wh_build_send_one($db, $event) |
31 |
70 |
// replace ##tags## |
// replace ##tags## |
32 |
71 |
rg_wh_replace_tags($event); |
rg_wh_replace_tags($event); |
33 |
72 |
|
|
34 |
|
// we need to copy 'flags'/'url' because we pass idata |
|
35 |
|
$wh['idata']['flags'] = $wh['flags']; |
|
36 |
|
$wh['idata']['url'] = $event['ri']['clone_url']; |
|
37 |
|
$wh['idata']['head'] = $event['new_rev']; |
|
38 |
|
|
|
39 |
|
// TODO: still have to pass env |
|
40 |
|
// TODO: also, e-mail notification |
|
41 |
|
$wh['idata']['env'] = 'fedora23-server-x86_64'; |
|
|
73 |
|
$a = $wh['idata']; |
|
74 |
|
$a['hook_id'] = $wh['id']; |
|
75 |
|
$a['uid'] = $event['ui']['uid']; |
|
76 |
|
$a['flags'] = $wh['flags']; |
|
77 |
|
$a['url'] = $event['ri']['clone_url']; |
|
78 |
|
$a['head'] = $event['new_rev']; |
|
79 |
|
$a['env'] = $event['env']; |
|
80 |
|
$a['packages'] = $event['packages']; |
|
81 |
|
// TODO: pass e-mail notification |
42 |
82 |
|
|
43 |
83 |
// Call the function |
// Call the function |
44 |
|
$r = rg_builder_add($db, $event['ri']['repo_id'], $wh['idata']); |
|
|
84 |
|
$r = rg_builder_add($db, $event['ri']['repo_id'], $a); |
45 |
85 |
if ($r['ok'] != 1) { |
if ($r['ok'] != 1) { |
46 |
86 |
$last_output .= $r['error']; |
$last_output .= $r['error']; |
47 |
87 |
break; |
break; |
|
... |
... |
function rg_wh_build_send_one($db, $event) |
51 |
91 |
break; |
break; |
52 |
92 |
} |
} |
53 |
93 |
|
|
54 |
|
rg_wh_set_last_output($db, $event['ui']['uid'], $wh['id'], |
|
55 |
|
substr($last_output, 0, 4096)); |
|
|
94 |
|
if (!empty($last_output)) |
|
95 |
|
rg_wh_set_last_output($db, $event['ui']['uid'], $wh['id'], |
|
96 |
|
substr($last_output, 0, 4096)); |
56 |
97 |
|
|
57 |
98 |
rg_prof_end('wh_build_send_one'); |
rg_prof_end('wh_build_send_one'); |
58 |
99 |
return $ret; |
return $ret; |
|
... |
... |
function rg_wh_build_send($db, $event) |
96 |
137 |
|
|
97 |
138 |
$x = $event; |
$x = $event; |
98 |
139 |
$x['category'] = 'wh_build_send_one'; |
$x['category'] = 'wh_build_send_one'; |
99 |
|
$x['wh'] = $wh; |
|
100 |
140 |
$x['debug'] = $wh['idata']['debug']; |
$x['debug'] = $wh['idata']['debug']; |
101 |
|
$ret[] = $x; |
|
|
141 |
|
$x['packages'] = $wh['idata']['packages']; |
|
142 |
|
$envs = $wh['idata']['envs']; unset($wh['idata']['envs']); |
|
143 |
|
$x['wh'] = $wh; |
|
144 |
|
foreach ($envs as $env => $junk) { |
|
145 |
|
$y = $x; |
|
146 |
|
$y['env'] = $env; |
|
147 |
|
$ret[] = $y; |
|
148 |
|
} |
102 |
149 |
} |
} |
103 |
150 |
|
|
104 |
151 |
rg_prof_end('wh_build_send'); |
rg_prof_end('wh_build_send'); |
|
... |
... |
function rg_wh_build_cosmetic(&$row) |
112 |
159 |
{ |
{ |
113 |
160 |
$f = rg_template('user/settings/wh/build/show_one.html', |
$f = rg_template('user/settings/wh/build/show_one.html', |
114 |
161 |
$rg, TRUE/*xss*/); |
$rg, TRUE/*xss*/); |
115 |
|
|
|
116 |
162 |
$list = ''; |
$list = ''; |
117 |
163 |
foreach ($row['idata']['cmds'] as $i => &$info) { |
foreach ($row['idata']['cmds'] as $i => &$info) { |
118 |
164 |
if (empty($info['cmd'])) |
if (empty($info['cmd'])) |
|
... |
... |
function rg_wh_build_cosmetic(&$row) |
125 |
171 |
$row['idata']['HTML:wh_list'] = |
$row['idata']['HTML:wh_list'] = |
126 |
172 |
rg_template_string($list, 0 /*off*/, $row['idata'], TRUE /*xss*/); |
rg_template_string($list, 0 /*off*/, $row['idata'], TRUE /*xss*/); |
127 |
173 |
|
|
|
174 |
|
$f = rg_template('user/settings/wh/build/env_show_one.html', |
|
175 |
|
$rg, TRUE/*xss*/); |
|
176 |
|
$list = ''; |
|
177 |
|
//rg_log_ml('DEBUG: envs: ' . print_r($row['idata']['envs'], TRUE)); |
|
178 |
|
foreach ($row['idata']['envs'] as $env => $junk) { |
|
179 |
|
$list .= str_replace('##env##', $env, $f); |
|
180 |
|
} |
|
181 |
|
$row['idata']['HTML:envs_list'] = |
|
182 |
|
rg_template_string($list, 0 /*off*/, $row['idata'], TRUE /*xss*/); |
|
183 |
|
|
128 |
184 |
$row['idata']['HTML:private'] = rg_template( |
$row['idata']['HTML:private'] = rg_template( |
129 |
185 |
'user/settings/wh/build/show.html', $row['idata'], TRUE /*xss*/); |
'user/settings/wh/build/show.html', $row['idata'], TRUE /*xss*/); |
130 |
186 |
} |
} |
|
... |
... |
function rg_wh_build_fill_vars(&$rg) |
159 |
215 |
$a['cmds'][$i]['abort'] = strcasecmp($x, 'on') == 0 ? 1 : 0; |
$a['cmds'][$i]['abort'] = strcasecmp($x, 'on') == 0 ? 1 : 0; |
160 |
216 |
} |
} |
161 |
217 |
|
|
|
218 |
|
$a['envs'] = array(); |
|
219 |
|
$envs = rg_var_str('wh::idata::envs'); |
|
220 |
|
//rg_log_ml('envs: ' . print_r($envs, TRUE)); |
|
221 |
|
foreach ($envs as $env => $on) |
|
222 |
|
$a['envs'][$env] = strcasecmp($on, 'on') == 0 ? 1 : 0; |
|
223 |
|
|
|
224 |
|
$a['packages'] = trim(rg_var_str('wh::idata::packages')); |
|
225 |
|
$a['packages'] = str_replace(';', ' ', $a['packages']); |
|
226 |
|
$a['packages'] = str_replace(',', ' ', $a['packages']); |
|
227 |
|
$a['packages'] = str_replace('\r', ' ', $a['packages']); |
|
228 |
|
$a['packages'] = str_replace('\n', ' ', $a['packages']); |
|
229 |
|
$a['packages'] = str_replace('\t', ' ', $a['packages']); |
|
230 |
|
|
162 |
231 |
//rg_log_ml('DEBUG: after fill_vars: ' . print_r($a, TRUE)); |
//rg_log_ml('DEBUG: after fill_vars: ' . print_r($a, TRUE)); |
163 |
232 |
} |
} |
164 |
233 |
|
|
|
... |
... |
function rg_wh_build_validate_vars($rg, &$errmsg) |
175 |
244 |
while (1) { |
while (1) { |
176 |
245 |
$all_empty = TRUE; |
$all_empty = TRUE; |
177 |
246 |
|
|
178 |
|
rg_log_ml('DEBUG: cmds:' . print_r($a['idata']['cmds'], TRUE)); |
|
|
247 |
|
//rg_log_ml('DEBUG: cmds:' . print_r($a['idata']['cmds'], TRUE)); |
179 |
248 |
if (empty($a['idata']['cmds'])) { |
if (empty($a['idata']['cmds'])) { |
180 |
249 |
$errmsg[] = rg_template('user/settings/wh/build/inv_cmd.txt', |
$errmsg[] = rg_template('user/settings/wh/build/inv_cmd.txt', |
181 |
250 |
$rg, TRUE /*xss*/); |
$rg, TRUE /*xss*/); |
182 |
251 |
break; |
break; |
183 |
252 |
} |
} |
184 |
253 |
|
|
|
254 |
|
//rg_log_ml('DEBUG: envs:' . print_r($a['idata']['envs'], TRUE)); |
|
255 |
|
if (empty($a['idata']['envs'])) { |
|
256 |
|
$errmsg[] = rg_template('user/settings/wh/build/inv_env.txt', |
|
257 |
|
$rg, TRUE /*xss*/); |
|
258 |
|
break; |
|
259 |
|
} |
|
260 |
|
|
185 |
261 |
$ret = TRUE; |
$ret = TRUE; |
186 |
262 |
break; |
break; |
187 |
263 |
} |
} |
|
... |
... |
function rg_wh_build_validate_vars($rg, &$errmsg) |
192 |
268 |
/* |
/* |
193 |
269 |
* Transfers to $rg the custom parameters - used when showing the form |
* Transfers to $rg the custom parameters - used when showing the form |
194 |
270 |
*/ |
*/ |
195 |
|
function rg_wh_build_add_form(&$rg) |
|
|
271 |
|
function rg_wh_build_add_form($db, &$rg) |
196 |
272 |
{ |
{ |
197 |
273 |
$f = rg_template_blind('user/settings/wh/build/form_cmd.html'); |
$f = rg_template_blind('user/settings/wh/build/form_cmd.html'); |
198 |
|
|
|
199 |
274 |
$cmds = ''; |
$cmds = ''; |
200 |
275 |
for ($i = 1; $i <= 5; $i++) |
for ($i = 1; $i <= 5; $i++) |
201 |
276 |
$cmds .= str_replace('##i##', $i, $f); |
$cmds .= str_replace('##i##', $i, $f); |
202 |
|
|
|
203 |
277 |
//rg_log_ml('DEBUG: cmds=' . $cmds); |
//rg_log_ml('DEBUG: cmds=' . $cmds); |
204 |
|
|
|
205 |
278 |
$rg['HTML:cmds'] = |
$rg['HTML:cmds'] = |
206 |
279 |
rg_template_string($cmds, 0 /*off*/, $rg, TRUE /*xss*/); |
rg_template_string($cmds, 0 /*off*/, $rg, TRUE /*xss*/); |
207 |
280 |
|
|
|
281 |
|
$envs = rg_worker_environments($db, $rg['login_ui']['uid']); |
|
282 |
|
$f = rg_template_blind('user/settings/wh/build/form_env.html'); |
|
283 |
|
$_s = ''; |
|
284 |
|
foreach ($envs as $env) |
|
285 |
|
$_s .= str_replace('##env##', $env, $f); |
|
286 |
|
rg_log_ml('envs: ' . $_s); |
|
287 |
|
$rg['HTML:envs'] = |
|
288 |
|
rg_template_string($_s, 0 /*off*/, $rg, TRUE /*xss*/); |
|
289 |
|
|
|
290 |
|
// 'packages' was added later |
|
291 |
|
if (!isset($rg['wh']['idata']['packages'])) |
|
292 |
|
$rg['wh']['idata']['packages'] = ''; |
|
293 |
|
|
|
294 |
|
//rg_log_ml('DEBUG:rg: ' . print_r($rg, TRUE)); |
|
295 |
|
|
208 |
296 |
$rg['HTML:custom_form'] = rg_template('user/settings/wh/build/form.html', |
$rg['HTML:custom_form'] = rg_template('user/settings/wh/build/form.html', |
209 |
297 |
$rg, TRUE /*xss*/); |
$rg, TRUE /*xss*/); |
210 |
298 |
} |
} |
|
... |
... |
function rg_wh_build_default_paras(&$rg) |
235 |
323 |
for ($i = 1; $i <= 5; $i++) |
for ($i = 1; $i <= 5; $i++) |
236 |
324 |
$a['cmds'][$i] = $t; |
$a['cmds'][$i] = $t; |
237 |
325 |
|
|
|
326 |
|
$a['envs'] = array(); |
|
327 |
|
$a['packages'] = ''; |
|
328 |
|
|
238 |
329 |
$a['events'] = 'P'; |
$a['events'] = 'P'; |
239 |
330 |
} |
} |
240 |
331 |
|
|
File inc/workers.inc.php added (mode: 100644) (index 0000000..7e77f17) |
|
1 |
|
<?php |
|
2 |
|
$INC = isset($INC) ? $INC : dirname(__FILE__); |
|
3 |
|
require_once($INC . '/events.inc.php'); |
|
4 |
|
|
|
5 |
|
$rg_worker_error = ''; |
|
6 |
|
|
|
7 |
|
function rg_worker_set_error($str) |
|
8 |
|
{ |
|
9 |
|
global $rg_worker_error; |
|
10 |
|
$rg_worker_error = $str; |
|
11 |
|
rg_log($str); |
|
12 |
|
} |
|
13 |
|
|
|
14 |
|
function rg_worker_error() |
|
15 |
|
{ |
|
16 |
|
global $rg_worker_error; |
|
17 |
|
return $rg_worker_error; |
|
18 |
|
} |
|
19 |
|
|
|
20 |
|
/* |
|
21 |
|
* Event functions |
|
22 |
|
*/ |
|
23 |
|
$rg_worker_functions = array( |
|
24 |
|
'worker_event_add' => 'rg_worker_event_add', |
|
25 |
|
'worker_event_del' => 'rg_worker_event_del' |
|
26 |
|
); |
|
27 |
|
rg_event_register_functions($rg_worker_functions); |
|
28 |
|
|
|
29 |
|
/* |
|
30 |
|
* Event for adding a worker |
|
31 |
|
*/ |
|
32 |
|
function rg_worker_event_add($db, $ev) |
|
33 |
|
{ |
|
34 |
|
$ret = array(); |
|
35 |
|
|
|
36 |
|
$ret[] = array_merge($ev, array('category' => 1002, 'prio' => 10)); |
|
37 |
|
|
|
38 |
|
return $ret; |
|
39 |
|
} |
|
40 |
|
|
|
41 |
|
/* |
|
42 |
|
* Event for deleting a worker |
|
43 |
|
*/ |
|
44 |
|
function rg_worker_event_del($db, $ev) |
|
45 |
|
{ |
|
46 |
|
$ret = array(); |
|
47 |
|
|
|
48 |
|
$ret[] = array_merge($ev, array('category' => 1002, 'prio' => 10)); |
|
49 |
|
|
|
50 |
|
return $ret; |
|
51 |
|
} |
|
52 |
|
|
|
53 |
|
/* |
|
54 |
|
* Helper for sorting by time |
|
55 |
|
*/ |
|
56 |
|
function rg_worker_sort_time_desc($a, $b) |
|
57 |
|
{ |
|
58 |
|
if ($a['itime'] > $b['itime']) |
|
59 |
|
return 1; |
|
60 |
|
if ($a['itime'] < $b['itime']) |
|
61 |
|
return -1; |
|
62 |
|
return 0; |
|
63 |
|
} |
|
64 |
|
|
|
65 |
|
/* |
|
66 |
|
* Cosmetic function (one element) |
|
67 |
|
*/ |
|
68 |
|
function rg_worker_cosmetic_one(&$row) |
|
69 |
|
{ |
|
70 |
|
$row['itime_nice'] = gmdate('Y-m-d H:i', $row['itime']); |
|
71 |
|
if ($row['last_connect'] == 0) |
|
72 |
|
$row['last_connect_nice'] = 'n/a'; |
|
73 |
|
else |
|
74 |
|
$row['last_connect_nice'] = gmdate('Y-m-d H:i', |
|
75 |
|
$row['last_connect']); |
|
76 |
|
|
|
77 |
|
if (empty($row['env'])) { |
|
78 |
|
$row['HTML:envs_nice'] = 'n/a'; |
|
79 |
|
} else { |
|
80 |
|
$list = @unserialize($row['env']); |
|
81 |
|
$t = array(); |
|
82 |
|
foreach ($list as $env => $env_info) |
|
83 |
|
$t[] = rg_xss_safe($env); |
|
84 |
|
sort($t); |
|
85 |
|
$row['HTML:envs_nice'] = implode('<br />', $t); |
|
86 |
|
} |
|
87 |
|
} |
|
88 |
|
|
|
89 |
|
/* |
|
90 |
|
* Cosmetic function (array) |
|
91 |
|
*/ |
|
92 |
|
function rg_worker_cosmetic(&$a) |
|
93 |
|
{ |
|
94 |
|
foreach ($a as &$row) |
|
95 |
|
rg_worker_cosmetic_one($row); |
|
96 |
|
uasort($a, 'rg_worker_sort_time_desc'); |
|
97 |
|
} |
|
98 |
|
|
|
99 |
|
/* |
|
100 |
|
* Sorts the list of workers. |
|
101 |
|
* It is used when selecting a server to send the job. |
|
102 |
|
*/ |
|
103 |
|
function rg_worker_sort($a, $b) |
|
104 |
|
{ |
|
105 |
|
if ($a['cost'] > $b['cost']) |
|
106 |
|
return 1; |
|
107 |
|
if ($a['cost'] < $b['cost']) |
|
108 |
|
return -1; |
|
109 |
|
return 0; |
|
110 |
|
} |
|
111 |
|
|
|
112 |
|
/* |
|
113 |
|
* Sorts the list of workers by name. |
|
114 |
|
*/ |
|
115 |
|
function rg_worker_sort_alpha($a, $b) |
|
116 |
|
{ |
|
117 |
|
return strcmp($a, $b); |
|
118 |
|
} |
|
119 |
|
|
|
120 |
|
/* |
|
121 |
|
* Loads info about a worker |
|
122 |
|
*/ |
|
123 |
|
function rg_worker_list($db, $uid) |
|
124 |
|
{ |
|
125 |
|
rg_prof_start('worker_list'); |
|
126 |
|
rg_log_enter('worker_list uid=' . $uid); |
|
127 |
|
|
|
128 |
|
$ret = FALSE; |
|
129 |
|
while (1) { |
|
130 |
|
$key = 'workers' . '::' . $uid; |
|
131 |
|
$c = rg_cache_get($key); |
|
132 |
|
if (($c !== FALSE) && isset($c['LOADED'])) { |
|
133 |
|
$ret = $c['list']; |
|
134 |
|
rg_worker_cosmetic($ret); |
|
135 |
|
break; |
|
136 |
|
} |
|
137 |
|
|
|
138 |
|
$params = array('uid' => $uid); |
|
139 |
|
$sql = 'SELECT * FROM workers' |
|
140 |
|
. ' WHERE uid = @@uid@@'; |
|
141 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
142 |
|
if ($res === FALSE) { |
|
143 |
|
rg_worker_set_error('cannot load list'); |
|
144 |
|
break; |
|
145 |
|
} |
|
146 |
|
|
|
147 |
|
$ret = array(); |
|
148 |
|
while (($row = rg_sql_fetch_array($res))) { |
|
149 |
|
$id = $row['id']; |
|
150 |
|
$ret[$id] = $row; |
|
151 |
|
} |
|
152 |
|
rg_sql_free_result($res); |
|
153 |
|
|
|
154 |
|
$a = array('LOADED' => 1, 'list' => $ret); |
|
155 |
|
rg_cache_set($key, $a, RG_SOCKET_NO_WAIT); |
|
156 |
|
|
|
157 |
|
rg_worker_cosmetic($ret); |
|
158 |
|
break; |
|
159 |
|
} |
|
160 |
|
|
|
161 |
|
rg_log_exit(); |
|
162 |
|
rg_prof_end('worker_list'); |
|
163 |
|
return $ret; |
|
164 |
|
} |
|
165 |
|
|
|
166 |
|
/* |
|
167 |
|
* Returns a list of workers, including the global ones |
|
168 |
|
*/ |
|
169 |
|
function rg_worker_list_all($db, $uid) |
|
170 |
|
{ |
|
171 |
|
$l1 = rg_worker_list($db, $uid); |
|
172 |
|
if ($l1 === FALSE) |
|
173 |
|
return FALSE; |
|
174 |
|
|
|
175 |
|
$l2 = rg_worker_list($db, 0); |
|
176 |
|
if ($l2 === FALSE) |
|
177 |
|
return FALSE; |
|
178 |
|
|
|
179 |
|
$ret = array(); |
|
180 |
|
foreach ($l1 as $id => $i) |
|
181 |
|
$ret[$id] = $i; |
|
182 |
|
foreach ($l2 as $id => $i) |
|
183 |
|
$ret[$id] = $i; |
|
184 |
|
|
|
185 |
|
uasort($ret, 'rg_worker_sort'); |
|
186 |
|
return $ret; |
|
187 |
|
} |
|
188 |
|
|
|
189 |
|
/* |
|
190 |
|
* Searches for a worker, by name |
|
191 |
|
* Returns -1 on error, 0 if not found or the info if found |
|
192 |
|
*/ |
|
193 |
|
function rg_worker_find_by_id($db, $uid, $id) |
|
194 |
|
{ |
|
195 |
|
rg_log_enter('worker_find_by_uid uid=' . $uid . ' id=' . $id); |
|
196 |
|
|
|
197 |
|
$ret = -1; |
|
198 |
|
while (1) { |
|
199 |
|
$wi = rg_worker_list($db, $uid); |
|
200 |
|
if ($wi === FALSE) |
|
201 |
|
break; |
|
202 |
|
|
|
203 |
|
$ret = 0; |
|
204 |
|
|
|
205 |
|
foreach ($wi as $_id => $i) { |
|
206 |
|
if ($_id == $id) { |
|
207 |
|
$ret = $i; |
|
208 |
|
break; |
|
209 |
|
} |
|
210 |
|
} |
|
211 |
|
break; |
|
212 |
|
} |
|
213 |
|
|
|
214 |
|
rg_log_exit(); |
|
215 |
|
return $ret; |
|
216 |
|
} |
|
217 |
|
|
|
218 |
|
/* |
|
219 |
|
* Searches for a worker, by name |
|
220 |
|
* Returns -1 on error, 0 if not found or the info if found |
|
221 |
|
*/ |
|
222 |
|
function rg_worker_find_by_name($db, $uid, $name) |
|
223 |
|
{ |
|
224 |
|
rg_log_enter('worker_find_by_name uid=' . $uid . ' name=' . $name); |
|
225 |
|
|
|
226 |
|
$ret = -1; |
|
227 |
|
while (1) { |
|
228 |
|
$wi = rg_worker_list($db, $uid); |
|
229 |
|
if ($wi === FALSE) |
|
230 |
|
break; |
|
231 |
|
|
|
232 |
|
$ret = 0; |
|
233 |
|
|
|
234 |
|
foreach ($wi as $id => $i) { |
|
235 |
|
rg_log('DEBUG: comparing with [' . $i['name'] . ']...'); |
|
236 |
|
if (strcasecmp($i['name'], $name) == 0) { |
|
237 |
|
$ret = $i; |
|
238 |
|
break; |
|
239 |
|
} |
|
240 |
|
} |
|
241 |
|
break; |
|
242 |
|
} |
|
243 |
|
|
|
244 |
|
rg_log_exit(); |
|
245 |
|
return $ret; |
|
246 |
|
} |
|
247 |
|
|
|
248 |
|
/* |
|
249 |
|
* Adds a new worker |
|
250 |
|
*/ |
|
251 |
|
function rg_worker_add($db, $uid, $a) |
|
252 |
|
{ |
|
253 |
|
rg_prof_start('worker_add'); |
|
254 |
|
rg_log_enter('worker_add'); |
|
255 |
|
|
|
256 |
|
//rg_log_ml('DEBUG: a: ' . print_r($a, TRUE)); |
|
257 |
|
|
|
258 |
|
$ret = FALSE; |
|
259 |
|
while (1) { |
|
260 |
|
$params = array(); |
|
261 |
|
$params['uid'] = $uid; |
|
262 |
|
$params['id'] = $a['id']; |
|
263 |
|
$params['name'] = $a['name']; |
|
264 |
|
$params['cost'] = $a['cost']; |
|
265 |
|
$params['workers'] = $a['workers']; |
|
266 |
|
|
|
267 |
|
if ($a['id'] == 0) { |
|
268 |
|
$params['itime'] = time(); |
|
269 |
|
$params['uname'] = ''; |
|
270 |
|
$params['host'] = ''; |
|
271 |
|
$params['arch'] = ''; |
|
272 |
|
$params['last_connect'] = ''; |
|
273 |
|
$params['last_ip'] = ''; |
|
274 |
|
|
|
275 |
|
$sql = 'INSERT INTO workers (itime, uid, name' |
|
276 |
|
. ', key, who, cost, workers)' |
|
277 |
|
. ' VALUES (@@itime@@, @@uid@@, @@name@@' |
|
278 |
|
. ', @@key@@, @@who@@, @@cost@@, @@workers@@)' |
|
279 |
|
. ' RETURNING id'; |
|
280 |
|
} else { |
|
281 |
|
$sql = 'UPDATE workers SET name = @@name@@' |
|
282 |
|
. ', cost = @@cost@@' |
|
283 |
|
. ', workers = @@workers@@' |
|
284 |
|
. ' WHERE uid = @@uid@@ AND id = @@id@@'; |
|
285 |
|
} |
|
286 |
|
|
|
287 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
288 |
|
if ($res === FALSE) { |
|
289 |
|
rg_worker_set_error('cannot insert/update'); |
|
290 |
|
break; |
|
291 |
|
} |
|
292 |
|
$row = rg_sql_fetch_array($res); |
|
293 |
|
rg_sql_free_result($res); |
|
294 |
|
|
|
295 |
|
if ($a['id'] == 0) |
|
296 |
|
$id = $row['id']; |
|
297 |
|
else |
|
298 |
|
$id = $a['id']; |
|
299 |
|
|
|
300 |
|
$event = array( |
|
301 |
|
'category' => 'worker_event_add', |
|
302 |
|
'prio' => 50, |
|
303 |
|
'ui' => array('uid' => $uid), |
|
304 |
|
'add' => $a['id'] == 0 ? 1 : 0, |
|
305 |
|
'id' => $id); |
|
306 |
|
$r = rg_event_add($db, $event); |
|
307 |
|
if ($r !== TRUE) { |
|
308 |
|
rg_worker_set_error('cannot add event' |
|
309 |
|
. ' (' . rg_event_error() . ')'); |
|
310 |
|
break; |
|
311 |
|
} |
|
312 |
|
|
|
313 |
|
$key = 'workers' . '::' . $uid . '::' . 'list' . '::' . $id; |
|
314 |
|
unset($params['uid']); |
|
315 |
|
$params['id'] = $id; |
|
316 |
|
rg_cache_merge($key, $params, RG_SOCKET_NO_WAIT); |
|
317 |
|
|
|
318 |
|
rg_event_signal_daemon('', 0); |
|
319 |
|
|
|
320 |
|
$ret = TRUE; |
|
321 |
|
break; |
|
322 |
|
} |
|
323 |
|
|
|
324 |
|
rg_log_exit(); |
|
325 |
|
rg_prof_end('worker_add'); |
|
326 |
|
|
|
327 |
|
return $ret; |
|
328 |
|
} |
|
329 |
|
|
|
330 |
|
/* |
|
331 |
|
* Updates 'last_connect' and 'last_ip', 'uname', 'host', 'arch', 'env' |
|
332 |
|
*/ |
|
333 |
|
function rg_worker_update($db, $uid, $id, $a) |
|
334 |
|
{ |
|
335 |
|
rg_prof_start('worker_update'); |
|
336 |
|
rg_log_enter('worker_update'); |
|
337 |
|
|
|
338 |
|
rg_log_ml('DEBUG: a: ' . print_r($a, TRUE)); |
|
339 |
|
|
|
340 |
|
$ret = FALSE; |
|
341 |
|
while (1) { |
|
342 |
|
$params = $a; |
|
343 |
|
$params['uid'] = $uid; |
|
344 |
|
$params['id'] = $id; |
|
345 |
|
$params['last_connect'] = time(); |
|
346 |
|
$params['env'] = serialize($a['env']); |
|
347 |
|
|
|
348 |
|
$sql = 'UPDATE workers SET' |
|
349 |
|
. ' name = @@name@@' |
|
350 |
|
. ', last_connect = @@last_connect@@' |
|
351 |
|
. ', last_ip = @@ip@@' |
|
352 |
|
. ', uname = @@uname@@' |
|
353 |
|
. ', host = @@host@@' |
|
354 |
|
. ', arch = @@arch@@' |
|
355 |
|
. ', env = @@env@@' |
|
356 |
|
. ', ssh_key = @@ssh_key@@' |
|
357 |
|
. ' WHERE uid = @@uid@@' |
|
358 |
|
. ' AND id = @@id@@'; |
|
359 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
360 |
|
if ($res === FALSE) { |
|
361 |
|
rg_worker_set_error('cannot update fields'); |
|
362 |
|
break; |
|
363 |
|
} |
|
364 |
|
rg_sql_free_result($res); |
|
365 |
|
|
|
366 |
|
$key = 'workers' . '::' . $uid . '::' . 'list' . '::' . $id; |
|
367 |
|
unset($params['uid']); |
|
368 |
|
rg_cache_merge($key, $params, RG_SOCKET_NO_WAIT); |
|
369 |
|
|
|
370 |
|
$ret = TRUE; |
|
371 |
|
break; |
|
372 |
|
} |
|
373 |
|
|
|
374 |
|
rg_log_exit(); |
|
375 |
|
rg_prof_end('worker_update'); |
|
376 |
|
|
|
377 |
|
return $ret; |
|
378 |
|
} |
|
379 |
|
|
|
380 |
|
/* |
|
381 |
|
* Returns a list of available environments |
|
382 |
|
* It also order by cost. |
|
383 |
|
*/ |
|
384 |
|
function rg_worker_environments($db, $uid) |
|
385 |
|
{ |
|
386 |
|
rg_prof_start('worker_environments'); |
|
387 |
|
rg_log_enter('worker_environments'); |
|
388 |
|
|
|
389 |
|
$ret = FALSE; |
|
390 |
|
while (1) { |
|
391 |
|
$user_envs = array(); |
|
392 |
|
if ($uid > 0) { |
|
393 |
|
$r = rg_worker_list($db, $uid); |
|
394 |
|
if ($r === FALSE) |
|
395 |
|
break; |
|
396 |
|
} |
|
397 |
|
|
|
398 |
|
$global_envs = rg_worker_list($db, 0); |
|
399 |
|
if ($global_envs === FALSE) |
|
400 |
|
break; |
|
401 |
|
|
|
402 |
|
$r = array_merge($user_envs, $global_envs); |
|
403 |
|
$ret = array(); |
|
404 |
|
foreach ($r as $id => $i) { |
|
405 |
|
$list = @unserialize($i['env']); |
|
406 |
|
if ($list === FALSE) |
|
407 |
|
continue; |
|
408 |
|
|
|
409 |
|
foreach ($list as $env => $junk) |
|
410 |
|
$ret[$env] = $env; |
|
411 |
|
} |
|
412 |
|
|
|
413 |
|
uksort($ret, 'rg_worker_sort_alpha'); |
|
414 |
|
//rg_log_ml('DEBUG: workers_environments: ret=' . print_r($ret, TRUE)); |
|
415 |
|
break; |
|
416 |
|
} |
|
417 |
|
|
|
418 |
|
rg_log_exit(); |
|
419 |
|
rg_prof_end('worker_environments'); |
|
420 |
|
return $ret; |
|
421 |
|
} |
|
422 |
|
|
|
423 |
|
/* |
|
424 |
|
* Remove workers from database |
|
425 |
|
*/ |
|
426 |
|
function rg_worker_remove($db, $uid, $list) |
|
427 |
|
{ |
|
428 |
|
rg_prof_start('workers_remove'); |
|
429 |
|
rg_log_enter('workers_remove: list=' . rg_array2string($list)); |
|
430 |
|
|
|
431 |
|
$ret = FALSE; |
|
432 |
|
while (1) { |
|
433 |
|
$my_list = array(); |
|
434 |
|
foreach ($list as $key_id => $junk) |
|
435 |
|
$my_list[] = sprintf('%u', $key_id); |
|
436 |
|
|
|
437 |
|
$params = array('uid' => $uid); |
|
438 |
|
$sql_list = implode(', ', $my_list); |
|
439 |
|
$sql = 'DELETE FROM workers' |
|
440 |
|
. ' WHERE uid = @@uid@@' |
|
441 |
|
. ' AND id IN (' . $sql_list . ')'; |
|
442 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
443 |
|
if ($res === FALSE) { |
|
444 |
|
rg_worker_set_error('cannot delete api keys'); |
|
445 |
|
break; |
|
446 |
|
} |
|
447 |
|
rg_sql_free_result($res); |
|
448 |
|
|
|
449 |
|
$event = array( |
|
450 |
|
'category' => 'worker_event_del', |
|
451 |
|
'prio' => 50, |
|
452 |
|
'ui' => array('uid' => $uid), |
|
453 |
|
'keys' => implode(',', $my_list)); |
|
454 |
|
$r = rg_event_add($db, $event); |
|
455 |
|
if ($r !== TRUE) { |
|
456 |
|
rg_worker_set_error('cannot add event' |
|
457 |
|
. ' (' . rg_event_error() . ')'); |
|
458 |
|
break; |
|
459 |
|
} |
|
460 |
|
|
|
461 |
|
$key = 'workers' . '::' . $uid . '::' . 'list'; |
|
462 |
|
foreach ($my_list as $_key_id) |
|
463 |
|
rg_cache_unset($key . '::' . $_key_id, |
|
464 |
|
RG_SOCKET_NO_WAIT); |
|
465 |
|
|
|
466 |
|
rg_event_signal_daemon('', 0); |
|
467 |
|
$ret = TRUE; |
|
468 |
|
break; |
|
469 |
|
} |
|
470 |
|
|
|
471 |
|
rg_log_exit(); |
|
472 |
|
rg_prof_end('workers_remove'); |
|
473 |
|
return $ret; |
|
474 |
|
} |
|
475 |
|
|
|
476 |
|
|
|
477 |
|
/* |
|
478 |
|
* Workers - add |
|
479 |
|
*/ |
|
480 |
|
function rg_worker_add_high_level($db, $rg, $op, $paras) |
|
481 |
|
{ |
|
482 |
|
rg_prof_start('worker_add_high_level'); |
|
483 |
|
rg_log_enter('worker_add_high_level op=' . $op); |
|
484 |
|
|
|
485 |
|
$ret = ''; |
|
486 |
|
$errmsg = array(); |
|
487 |
|
|
|
488 |
|
$rg['worker'] = array(); |
|
489 |
|
if (strcmp($op, 'add') == 0) { |
|
490 |
|
$rg['worker']['id'] = 0; |
|
491 |
|
$rg['worker']['name'] = ''; |
|
492 |
|
$rg['worker']['key'] = rg_id(32); |
|
493 |
|
$rg['worker']['cost'] = 10; |
|
494 |
|
$rg['worker']['workers'] = 1; |
|
495 |
|
} else { |
|
496 |
|
if (isset($paras[0])) { |
|
497 |
|
$id = intval($paras[0]); |
|
498 |
|
$r = rg_worker_find_by_id($db, $rg['login_ui']['uid'], |
|
499 |
|
$id); |
|
500 |
|
if ($r === -1) |
|
501 |
|
$errmsg[] = 'error loading list; try again later'; |
|
502 |
|
else if ($r === 0) |
|
503 |
|
$errmsg[] = 'invalid id for edit'; |
|
504 |
|
else |
|
505 |
|
$rg['worker'] = $r; |
|
506 |
|
} else { |
|
507 |
|
$errmsg[] = 'no worker id received'; |
|
508 |
|
} |
|
509 |
|
} |
|
510 |
|
rg_log_ml('DEBUG: rg[worker]: ' . print_r($rg['worker'], TRUE)); |
|
511 |
|
|
|
512 |
|
$doit = rg_var_uint('doit'); |
|
513 |
|
while ($doit == 1) { |
|
514 |
|
if ($rg['worker']['id'] == 0) { |
|
515 |
|
$rg['worker']['id'] = rg_var_uint('worker::id'); |
|
516 |
|
$rg['worker']['key'] = rg_var_str('worker::key'); |
|
517 |
|
} |
|
518 |
|
$rg['worker']['name'] = rg_var_str('worker::name'); |
|
519 |
|
$rg['worker']['cost'] = rg_var_uint('worker::cost'); |
|
520 |
|
$rg['worker']['workers'] = rg_var_uint('worker::workers'); |
|
521 |
|
|
|
522 |
|
if ($rg['worker']['id'] == 0) { |
|
523 |
|
$len = strlen($rg['worker']['key']); |
|
524 |
|
if ($len < 32) { |
|
525 |
|
$errmsg[] = 'invalid key (len = ' . $len . ')'; |
|
526 |
|
break; |
|
527 |
|
} |
|
528 |
|
} |
|
529 |
|
|
|
530 |
|
if (empty($rg['worker']['name'])) { |
|
531 |
|
$errmsg[] = 'invalid name'; |
|
532 |
|
break; |
|
533 |
|
} |
|
534 |
|
|
|
535 |
|
if (!rg_valid_referer()) { |
|
536 |
|
$errmsg[] = 'invalid referer; try again'; |
|
537 |
|
break; |
|
538 |
|
} |
|
539 |
|
|
|
540 |
|
if (!rg_token_valid($db, $rg, 'worker_add', FALSE)) { |
|
541 |
|
$errmsg[] = 'invalid token; try again'; |
|
542 |
|
break; |
|
543 |
|
} |
|
544 |
|
|
|
545 |
|
if ($rg['login_ui']['is_admin'] == 1) { |
|
546 |
|
$rg['worker']['who'] = 0; |
|
547 |
|
$target_uid = 0; |
|
548 |
|
} else { |
|
549 |
|
$rg['worker']['who'] = $rg['login_ui']['uid']; |
|
550 |
|
$target_uid = $rg['login_ui']['uid']; |
|
551 |
|
} |
|
552 |
|
$r = rg_worker_add($db, $target_uid, $rg['worker']); |
|
553 |
|
if ($r === FALSE) { |
|
554 |
|
$errmsg[] = rg_worker_error(); |
|
555 |
|
break; |
|
556 |
|
} |
|
557 |
|
|
|
558 |
|
$ret .= rg_template('user/settings/workers/add_ok.html', |
|
559 |
|
$rg, TRUE /*xss*/); |
|
560 |
|
|
|
561 |
|
$rg['worker']['id'] = 0; |
|
562 |
|
$rg['worker']['name'] = ''; |
|
563 |
|
$rg['worker']['key'] = rg_id(32); |
|
564 |
|
$rg['worker']['cost'] = 10; |
|
565 |
|
$rg['worker']['workers'] = 1; |
|
566 |
|
break; |
|
567 |
|
} |
|
568 |
|
|
|
569 |
|
$rg['HTML:errmsg'] = rg_template_errmsg($errmsg); |
|
570 |
|
$rg['rg_form_token'] = rg_token_get($db, $rg, 'worker_add'); |
|
571 |
|
$ret .= rg_template('user/settings/workers/add.html', |
|
572 |
|
$rg, TRUE /*xss*/); |
|
573 |
|
|
|
574 |
|
rg_log_exit(); |
|
575 |
|
rg_prof_end('worker_add_high_level'); |
|
576 |
|
return $ret; |
|
577 |
|
} |
|
578 |
|
|
|
579 |
|
/* |
|
580 |
|
* Workers - list |
|
581 |
|
*/ |
|
582 |
|
function rg_worker_list_high_level($db, $rg, $paras) |
|
583 |
|
{ |
|
584 |
|
rg_prof_start('worker_list_high_level'); |
|
585 |
|
rg_log_enter('worker_list_high_level'); |
|
586 |
|
|
|
587 |
|
$ret = ''; |
|
588 |
|
|
|
589 |
|
$errmsg = array(); |
|
590 |
|
$rg['HTML:status'] = ''; |
|
591 |
|
|
|
592 |
|
if ($rg['login_ui']['is_admin'] == 1) |
|
593 |
|
$target_uid = 0; |
|
594 |
|
else |
|
595 |
|
$target_uid = $rg['login_ui']['uid']; |
|
596 |
|
|
|
597 |
|
$doit = rg_var_uint('doit'); |
|
598 |
|
while ($doit == 1) { |
|
599 |
|
if (!rg_valid_referer()) { |
|
600 |
|
$errmsg[] = 'invalid referer; try again'; |
|
601 |
|
break; |
|
602 |
|
} |
|
603 |
|
|
|
604 |
|
if (!rg_token_valid($db, $rg, 'workers_list', FALSE)) { |
|
605 |
|
$errmsg[] = 'invalid token; try again.'; |
|
606 |
|
break; |
|
607 |
|
} |
|
608 |
|
|
|
609 |
|
$list = rg_var_str('delete_ids'); |
|
610 |
|
$r = rg_worker_remove($db, $target_uid, $list); |
|
611 |
|
if ($r !== TRUE) { |
|
612 |
|
$errmsg[] = 'cannot delete: ' . rg_worker_error(); |
|
613 |
|
break; |
|
614 |
|
} |
|
615 |
|
|
|
616 |
|
$rg['HTML:status'] = rg_template( |
|
617 |
|
'user/settings/workers/delete_ok.html', |
|
618 |
|
$rg, TRUE /*xss*/); |
|
619 |
|
break; |
|
620 |
|
} |
|
621 |
|
|
|
622 |
|
$r = rg_worker_list($db, $target_uid); |
|
623 |
|
if ($r === FALSE) { |
|
624 |
|
$rg['errmsg'] = rg_worker_error(); |
|
625 |
|
$ret .= rg_template('user/settings/workers/list_err.html', |
|
626 |
|
$rg, TRUE /*xss*/); |
|
627 |
|
} else { |
|
628 |
|
$rg['rg_form_token'] = rg_token_get($db, $rg, 'workers_list'); |
|
629 |
|
$rg['HTML:errmsg'] = rg_template_errmsg($errmsg); |
|
630 |
|
$ret .= rg_template_table('user/settings/workers/list', $r, $rg); |
|
631 |
|
} |
|
632 |
|
|
|
633 |
|
rg_log_exit(); |
|
634 |
|
rg_prof_end('worker_list_high_level'); |
|
635 |
|
return $ret; |
|
636 |
|
} |
|
637 |
|
|
|
638 |
|
/* |
|
639 |
|
* Deals with workers |
|
640 |
|
*/ |
|
641 |
|
function rg_worker_high_level($db, &$rg, $paras) |
|
642 |
|
{ |
|
643 |
|
rg_prof_start('worker_high_level'); |
|
644 |
|
rg_log_enter('worker_high_level'); |
|
645 |
|
|
|
646 |
|
$ret = ''; |
|
647 |
|
|
|
648 |
|
$op = empty($paras) ? 'list' : array_shift($paras); |
|
649 |
|
$rg['menu']['worker'][$op] = 1; |
|
650 |
|
|
|
651 |
|
$rg['HTML:menu_level2'] = |
|
652 |
|
rg_template('user/settings/workers/menu.html', $rg, TRUE /*xss*/); |
|
653 |
|
|
|
654 |
|
switch ($op) { |
|
655 |
|
case 'edit': |
|
656 |
|
case 'add': |
|
657 |
|
$ret .= rg_worker_add_high_level($db, $rg, $op, $paras); |
|
658 |
|
break; |
|
659 |
|
|
|
660 |
|
default: |
|
661 |
|
$ret .= rg_worker_list_high_level($db, $rg, $paras); |
|
662 |
|
break; |
|
663 |
|
} |
|
664 |
|
|
|
665 |
|
$hints = array(); |
|
666 |
|
$hints[]['HTML:hint'] = rg_template('user/settings/workers/hints.html', |
|
667 |
|
$rg, TRUE /*xss*/); |
|
668 |
|
$ret .= rg_template_table('hints/list', $hints, $rg); |
|
669 |
|
|
|
670 |
|
rg_log_exit(); |
|
671 |
|
rg_prof_end('worker_high_level'); |
|
672 |
|
return $ret; |
|
673 |
|
} |
|
674 |
|
|
|
675 |
|
?> |
File root/index.php changed (mode: 100644) (index 53ef7a8..07e7eee) |
... |
... |
include_once($INC . "/bug.inc.php"); |
23 |
23 |
include_once($INC . "/fixes.inc.php"); |
include_once($INC . "/fixes.inc.php"); |
24 |
24 |
include_once($INC . "/plan.inc.php"); |
include_once($INC . "/plan.inc.php"); |
25 |
25 |
include_once($INC . "/admin.inc.php"); |
include_once($INC . "/admin.inc.php"); |
|
26 |
|
include_once($INC . "/api.inc.php"); |
|
27 |
|
include_once($INC . "/apikeys.inc.php"); |
26 |
28 |
include_once($INC . "/ver.php"); |
include_once($INC . "/ver.php"); |
27 |
29 |
|
|
28 |
30 |
rg_prof_start("MAIN"); |
rg_prof_start("MAIN"); |
|
... |
... |
$rg['target_ui'] = array("ok" => 1, "exists" => 0, "uid" => 0); |
52 |
54 |
$rg['ri'] = array("repo_id" => 0, "uid" => 0); |
$rg['ri'] = array("repo_id" => 0, "uid" => 0); |
53 |
55 |
$rg['bug'] = array("bug_id" => 0); |
$rg['bug'] = array("bug_id" => 0); |
54 |
56 |
$rg['debug'] = rg_var_uint('rg_debug'); |
$rg['debug'] = rg_var_uint('rg_debug'); |
|
57 |
|
$rg['base_url'] = rg_base_url(); |
55 |
58 |
|
|
56 |
59 |
// We have variable 'vv' passed from webserver - build 'op' and rest of paras |
// We have variable 'vv' passed from webserver - build 'op' and rest of paras |
57 |
60 |
$sparas = rg_var_str("vv"); |
$sparas = rg_var_str("vv"); |
58 |
61 |
rg_log("DEBUG: sparas=$sparas"); |
rg_log("DEBUG: sparas=$sparas"); |
59 |
62 |
$rg['current_url'] = rawurlencode($sparas); |
$rg['current_url'] = rawurlencode($sparas); |
60 |
|
$rg['url'] = "/op"; |
|
|
63 |
|
$rg['url'] = '/op'; |
61 |
64 |
$paras = explode("/", trim($sparas, "/")); |
$paras = explode("/", trim($sparas, "/")); |
62 |
65 |
$_t = empty($paras) ? "" : $paras[0]; |
$_t = empty($paras) ? "" : $paras[0]; |
63 |
66 |
if (strcmp($_t, "op") == 0) { |
if (strcmp($_t, "op") == 0) { |
64 |
67 |
array_shift($paras); |
array_shift($paras); |
65 |
|
$_op = empty($paras) ? "" : array_shift($paras); |
|
|
68 |
|
$_op = empty($paras) ? '' : array_shift($paras); |
66 |
69 |
} else { |
} else { |
67 |
|
$_op = ""; |
|
|
70 |
|
$_op = ''; |
68 |
71 |
} |
} |
69 |
72 |
|
|
70 |
73 |
$rg['doit'] = rg_var_uint("doit"); |
$rg['doit'] = rg_var_uint("doit"); |
|
... |
... |
if ($good == 0) { |
118 |
121 |
exit(0); |
exit(0); |
119 |
122 |
} |
} |
120 |
123 |
|
|
121 |
|
if (strcmp($service, "git-upload-packXXX") == 0) { |
|
|
124 |
|
if (0 && strcmp($service, "git-upload-packXXX") == 0) { |
122 |
125 |
rg_log("We have a fetch by http!"); |
rg_log("We have a fetch by http!"); |
123 |
126 |
// TODO: settimelimit to a resonable value |
// TODO: settimelimit to a resonable value |
124 |
127 |
putenv("GIT_HTTP_EXPORT_ALL=1"); |
putenv("GIT_HTTP_EXPORT_ALL=1"); |
|
... |
... |
if (strcmp($service, "git-upload-packXXX") == 0) { |
129 |
132 |
exit(0); |
exit(0); |
130 |
133 |
} |
} |
131 |
134 |
|
|
|
135 |
|
// API dispatch |
|
136 |
|
if (strcmp($_op, 'api') == 0) { |
|
137 |
|
$_auth = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : ''; |
|
138 |
|
$_t = explode(' ', $_auth, 2); |
|
139 |
|
$_user = trim($_t[0]); |
|
140 |
|
$_key = trim($_t[1]); |
|
141 |
|
rg_log('api user=[' . $_user . '] key=[' . $_key . ']!'); |
|
142 |
|
$body = ''; |
|
143 |
|
while (1) { |
|
144 |
|
$ui = rg_user_info($db, 0, $_user, ''); |
|
145 |
|
if ($ui['ok'] != 1) { |
|
146 |
|
$body = array('error' => rg_user_error()); |
|
147 |
|
echo json_encode($body, JSON_PRETTY_PRINT) . "\n"; |
|
148 |
|
break; |
|
149 |
|
} |
|
150 |
|
if ($ui['exists'] != 1) { |
|
151 |
|
$body = array('error' => 'invalid user or apikey'); |
|
152 |
|
echo json_encode($body, JSON_PRETTY_PRINT) . "\n"; |
|
153 |
|
break; |
|
154 |
|
} |
|
155 |
|
|
|
156 |
|
$key_id = rg_ak_valid($db, $ui['uid'], $_key); |
|
157 |
|
if ($key_id === FALSE) { |
|
158 |
|
$body = array('error' => 'invalid user or apikey'); |
|
159 |
|
echo json_encode($body, JSON_PRETTY_PRINT) . "\n"; |
|
160 |
|
break; |
|
161 |
|
} |
|
162 |
|
|
|
163 |
|
$post = @file_get_contents("php://input"); |
|
164 |
|
rg_log('post=' . $post); |
|
165 |
|
|
|
166 |
|
$d = @json_decode($post); |
|
167 |
|
if ($d === NULL) { |
|
168 |
|
rg_log('error parsing!'); |
|
169 |
|
$body = array('error' => json_last_error_msg()); |
|
170 |
|
echo json_encode($body, JSON_PRETTY_PRINT) . "\n"; |
|
171 |
|
break; |
|
172 |
|
} |
|
173 |
|
|
|
174 |
|
rg_ak_update_use($db, $ui['uid'], $key_id, $rg['ip'], $post); |
|
175 |
|
|
|
176 |
|
// we need to transform the object 'd' into an array |
|
177 |
|
$d2 = array(); |
|
178 |
|
foreach ($d as $k => $v) |
|
179 |
|
$d2[$k] = $v; |
|
180 |
|
$d2['connect_uid'] = $ui['uid']; |
|
181 |
|
$d2['ip'] = $rg['ip']; |
|
182 |
|
echo rg_api($db, $d2); |
|
183 |
|
break; |
|
184 |
|
} |
|
185 |
|
|
|
186 |
|
rg_prof_end("MAIN"); |
|
187 |
|
rg_prof_log(); |
|
188 |
|
exit(0); |
|
189 |
|
} |
|
190 |
|
|
132 |
191 |
rg_user_login_by_sid($db, $rg); |
rg_user_login_by_sid($db, $rg); |
133 |
192 |
rg_log("After login_by_sid, login_ui=" . rg_array2string($rg['login_ui'])); |
rg_log("After login_by_sid, login_ui=" . rg_array2string($rg['login_ui'])); |
134 |
193 |
// If user provided an old/expired sid, we generate a new one, pre-login |
// If user provided an old/expired sid, we generate a new one, pre-login |
File root/themes/default/doc/api.html added (mode: 100644) (index 0000000..6558691) |
|
1 |
|
<div class="main_title">API documentation</div> |
|
2 |
|
|
|
3 |
|
<div class="islands"> |
|
4 |
|
<div class="island_row"> |
|
5 |
|
<div class="island_cell"> |
|
6 |
|
<div class="island"> |
|
7 |
|
<div class="island_title">Calling API by SSH or by CURL</div> |
|
8 |
|
Possible commands:<br /> |
|
9 |
|
<a href="#user_info">user_info<a/><br /> |
|
10 |
|
<a href="#user_rights_list">user_rights_list</a><br /> |
|
11 |
|
<a href="#user_ssh_keys_list">user_ssh_keys_list</a><br /> |
|
12 |
|
<a href="#user_wh_list">user_wh_list</a><br /> |
|
13 |
|
<a href="#repo_bug_info">repo_bug_info</a><br /> |
|
14 |
|
<a href="#repo_bug_list">repo_bug_list</a><br /> |
|
15 |
|
<a href="#repo_list">repo_list</a><br /> |
|
16 |
|
<a href="#repo_info">repo_info</a><br /> |
|
17 |
|
<a href="#repo_pr_list">repo_pr_list</a><br /> |
|
18 |
|
<br /> |
|
19 |
|
|
|
20 |
|
<a name="user_info"><b>user_info</b></a><br /> |
|
21 |
|
<b>Description</b>: List information abot a user<br /> |
|
22 |
|
<b>Parameters</b>: user, uid<br /> |
|
23 |
|
Example: |
|
24 |
|
<div class="term"> |
|
25 |
|
$ curl --header 'Authorization: bla this_is_bla_api_key' \ |
|
26 |
|
--data '{"cmd": "user_info", "user": "bla"}' \ |
|
27 |
|
@@base_url@@/op/api |
|
28 |
|
$ ssh rocketgit@rocketgit.com api user_info user=bla |
|
29 |
|
{ |
|
30 |
|
"ok": 1, |
|
31 |
|
"exists": 1, |
|
32 |
|
"uid": "846", |
|
33 |
|
"is_admin": "0", |
|
34 |
|
"rights": "C", |
|
35 |
|
"homepage": "\/user\/bla", |
|
36 |
|
"username": "bla", |
|
37 |
|
"salt": "3f786850e387550fdab836ed7e6dc881de23001b", |
|
38 |
|
"pass": "162b0b32f024...01cc7884a635be", |
|
39 |
|
"email": "bla@example.com", |
|
40 |
|
"itime": "1440834245", |
|
41 |
|
"suspended": null, |
|
42 |
|
"session_time": "3600", |
|
43 |
|
"last_seen": "1464805192", |
|
44 |
|
"disk_used_mb": null, |
|
45 |
|
"confirmed": "1", |
|
46 |
|
"confirm_token": "c215e946b2b15d66d14b", |
|
47 |
|
"organization": "0", |
|
48 |
|
"realname": "my real name", |
|
49 |
|
"plan_id": "0", |
|
50 |
|
"last_ip": "192.168.79.154", |
|
51 |
|
"itime_nice": "2015-08-29", |
|
52 |
|
"email_md5": "60b725f10c9c85c70d97880dfe8191b3", |
|
53 |
|
"HTML:gravatar": "<img src=\"https:\/\/www.gravatar.com\/avatar\/60...b3?s=64&r=g\" alt=\"avatar\" width=\"64\" height=\"64\" \/>" |
|
54 |
|
} |
|
55 |
|
</div> |
|
56 |
|
<br /> |
|
57 |
|
|
|
58 |
|
<a name="user_rights_list"><b>user_rights_list</b></a><br /> |
|
59 |
|
<b>Description</b>: Lists user defined rights<br /> |
|
60 |
|
<b>Parameters</b>: user<br /> |
|
61 |
|
Example: |
|
62 |
|
<div class="term"> |
|
63 |
|
$ curl --header 'Authorization: bla this_is_bla_api_key' \ |
|
64 |
|
--data '{"cmd": "user_rights_list", "user": "bla"}' \ |
|
65 |
|
@@base_url@@/op/api |
|
66 |
|
$ ssh rocketgit@rocketgit.com api user_rights_list user=bla |
|
67 |
|
[ |
|
68 |
|
{ |
|
69 |
|
"type": "repo_path", |
|
70 |
|
"obj_id": "831", |
|
71 |
|
"uid": "0", |
|
72 |
|
"rights": "P", |
|
73 |
|
"itime": "1450417938", |
|
74 |
|
"misc": "", |
|
75 |
|
"prio": "100", |
|
76 |
|
"who": "846", |
|
77 |
|
"right_id": "79", |
|
78 |
|
"ip": "", |
|
79 |
|
"misc2": "", |
|
80 |
|
"<b>Description</b>": "dfdsfds", |
|
81 |
|
"username": "*", |
|
82 |
|
"who_name": "catab", |
|
83 |
|
"rights_text": "Push", |
|
84 |
|
"itime_text": "2015-12-18 05:52", |
|
85 |
|
"ip_nice": "Any", |
|
86 |
|
"HTML:<b>Description</b>_nlbr": "dfdsfds", |
|
87 |
|
"can_be_deleted": 1 |
|
88 |
|
}, |
|
89 |
|
... |
|
90 |
|
] |
|
91 |
|
</div> |
|
92 |
|
<br /> |
|
93 |
|
|
|
94 |
|
<a name="user_ssh_keys_list"><b>user_ssh_keys_list</b></a><br /> |
|
95 |
|
<b>Description</b>: Lists SSH keys of a user<br /> |
|
96 |
|
<b>Parameters</b>: user<br /> |
|
97 |
|
Example: |
|
98 |
|
<div class="term"> |
|
99 |
|
$ curl --header 'Authorization: bla this_is_bla_api_key' \ |
|
100 |
|
--data '{"cmd": "user_ssh_keys_list", "user": "bla"}' \ |
|
101 |
|
@@base_url@@/op/api |
|
102 |
|
$ ssh rocketgit@rocketgit.com api user_ssh_keys_list user=bla |
|
103 |
|
[ |
|
104 |
|
{ |
|
105 |
|
"ok": 1, |
|
106 |
|
"type": "ssh-rsa", |
|
107 |
|
"comment": "Key for rocketgit - r1i", |
|
108 |
|
"key": "AAAAB3NzaC1yc2...yTRiD8gFdg9UT1bw==", |
|
109 |
|
"bits": 4096, |
|
110 |
|
"fingerprint_md5": "b1:fd:5f:f0:53:f5:9c:31:b2:de:ff:00:1c:f1:c5:61", |
|
111 |
|
"fingerprint_sha256": "SNPwFw0Snaz7pdUAFV4Lrf8LFHqx93I7VmW5LsjTlLS0", |
|
112 |
|
"key_id": "438", |
|
113 |
|
"itime": "2016-01-27 21:11", |
|
114 |
|
"first_use": "2016-01-27 21:13", |
|
115 |
|
"last_ip": "192.168.79.154", |
|
116 |
|
"last_use": "2016-01-29 18:27", |
|
117 |
|
"last_cmd": "git-receive-pack '\/user\/catab\/delme10'", |
|
118 |
|
"count": "27" |
|
119 |
|
}, |
|
120 |
|
... |
|
121 |
|
] |
|
122 |
|
</div> |
|
123 |
|
<br /> |
|
124 |
|
|
|
125 |
|
<a name="user_wh_list"><b>user_wh_list</b></a><br /> |
|
126 |
|
<b>Description</b>: Lists webhooks of a user<br /> |
|
127 |
|
<b>Parameters</b>: user<br /> |
|
128 |
|
Example: |
|
129 |
|
<div class="term"> |
|
130 |
|
$ curl --header 'Authorization: bla this_is_bla_api_key' \ |
|
131 |
|
--data '{"cmd": "user_wh_list", "user": "bla"}' \ |
|
132 |
|
@@base_url@@/op/api |
|
133 |
|
$ ssh rocketgit@rocketgit.com api user_wh_list user=bla |
|
134 |
|
[ |
|
135 |
|
{ |
|
136 |
|
"id": "648", |
|
137 |
|
"uid": "846", |
|
138 |
|
"itime": "1454001110", |
|
139 |
|
"<b>Description</b>": "Test Slack integration", |
|
140 |
|
"add_ip": "192.168.79.154", |
|
141 |
|
"last_output": "* Trying ...H5pQ==\r\n\r\nok", |
|
142 |
|
"idata": { |
|
143 |
|
"debug": "0", |
|
144 |
|
"events": "P", |
|
145 |
|
"url": "https:\/\/hooks.slack.com\/services\/T...D\/B...N\/j...E", |
|
146 |
|
"itype": "2", |
|
147 |
|
"client_cert": "", |
|
148 |
|
"client_ca_cert": "", |
|
149 |
|
"opaque": "", |
|
150 |
|
"key": "", |
|
151 |
|
"custom_body": "{\n \"cha...host:\"\n}", |
|
152 |
|
"events_text": "Push", |
|
153 |
|
"itype_text": "Custom (use custom body field)", |
|
154 |
|
"HTML:client_cert_short": "n\/a", |
|
155 |
|
"HTML:client_ca_cert_short": "n\/a", |
|
156 |
|
"HTML:custom_body_nlbr": "{<br \/>... \/>\n}", |
|
157 |
|
"HTML:private": "<table ...<\/table>\n" |
|
158 |
|
}, |
|
159 |
|
"htype": "http", |
|
160 |
|
"flags": "", |
|
161 |
|
"refname": "(test1|master)", |
|
162 |
|
"repo": ".*10", |
|
163 |
|
"itime_nice": "2016-01-28 17:11", |
|
164 |
|
"HTML:flags_text": "", |
|
165 |
|
"HTML:<b>Description</b>_nice": "Test Slack integration", |
|
166 |
|
"HTML:last_output_nice": "* Try...\r\nok" |
|
167 |
|
}, |
|
168 |
|
... |
|
169 |
|
] |
|
170 |
|
</div> |
|
171 |
|
<br /> |
|
172 |
|
|
|
173 |
|
<a name="repo_bug_info"><b>repo_bug_info</b></a><br /> |
|
174 |
|
<b>Description</b>: Shows information about a bug<br /> |
|
175 |
|
<b>Parameters</b>: name/repo_id, bug_id<br /> |
|
176 |
|
Example: |
|
177 |
|
<div class="term"> |
|
178 |
|
$ curl --header 'Authorization: bla this_is_bla_api_key' \ |
|
179 |
|
--data '{"cmd": "repo_bug_info", "name": "repo1", "bug_id": 2}' \ |
|
180 |
|
@@base_url@@/op/api |
|
181 |
|
$ ssh rocketgit@rocketgit.com api repo_bug_info name=repo1 bug_id=2 |
|
182 |
|
{ |
|
183 |
|
"bug_id": "2", |
|
184 |
|
"title": "dsdasds", |
|
185 |
|
"body": "OS type(s) and version(s)?", |
|
186 |
|
"state": "1", |
|
187 |
|
"labels": "", |
|
188 |
|
"assigned_to": "bla", |
|
189 |
|
"assigned_uid": "846", |
|
190 |
|
"itime": 1464812804, |
|
191 |
|
"utime": 1464812804, |
|
192 |
|
"ip": "192.168.79.154", |
|
193 |
|
"repo_id": "1088", |
|
194 |
|
"uid": "846", |
|
195 |
|
"deleted": 0, |
|
196 |
|
"ok": 1, |
|
197 |
|
"exists": 1, |
|
198 |
|
"owner": "catab", |
|
199 |
|
"HTML:body_nlbr": "OS type(s) and version(s)?", |
|
200 |
|
"creation": "2016-06-01 20:26", |
|
201 |
|
"updated": "2016-06-01 20:26", |
|
202 |
|
"deleted_text": "", |
|
203 |
|
"deleted_who_name": "", |
|
204 |
|
"state_text": "Open" |
|
205 |
|
} |
|
206 |
|
</div> |
|
207 |
|
<br /> |
|
208 |
|
|
|
209 |
|
<a name="repo_bug_list"><b>repo_bug_list</b></a><br /> |
|
210 |
|
<b>Description</b>: Lists the bugs<br /> |
|
211 |
|
<b>Parameters</b>: name, repo_id<br /> |
|
212 |
|
Example: |
|
213 |
|
<div class="term"> |
|
214 |
|
$ curl --header 'Authorization: bla this_is_bla_api_key' \ |
|
215 |
|
--data '{"cmd": "repo_bug_list", "name": "repo1"}' \ |
|
216 |
|
@@base_url@@/op/api |
|
217 |
|
$ ssh rocketgit@rocketgit.com api repo_bug_list name=repo1 |
|
218 |
|
[ |
|
219 |
|
"1", |
|
220 |
|
"2", |
|
221 |
|
"3" |
|
222 |
|
] |
|
223 |
|
</div> |
|
224 |
|
<br /> |
|
225 |
|
|
|
226 |
|
<a name="repo_list"><b>repo_list</b></a><br /> |
|
227 |
|
<b>Parameters</b>: none<br /> |
|
228 |
|
Example: |
|
229 |
|
<div class="term"> |
|
230 |
|
$ curl --header 'Authorization: bla this_is_bla_api_key' \ |
|
231 |
|
--data '{"cmd": "repo_list"}' \ |
|
232 |
|
@@base_url@@/op/api |
|
233 |
|
$ ssh rocketgit@rocketgit.com api repo_list |
|
234 |
|
[ |
|
235 |
|
"repo1", |
|
236 |
|
"repo2", |
|
237 |
|
"repo3" |
|
238 |
|
] |
|
239 |
|
</div> |
|
240 |
|
<br /> |
|
241 |
|
|
|
242 |
|
<a name="repo_info"><b>repo_info</b></a><br /> |
|
243 |
|
<b>Description</b>: Shows info about a repository<br /> |
|
244 |
|
<b>Parameters</b>: name, repo_id<br /> |
|
245 |
|
Example: |
|
246 |
|
<div class="term"> |
|
247 |
|
$ curl --header 'Authorization: bla this_is_bla_api_key' \ |
|
248 |
|
--data '{"cmd": "repo_info", "name": "repo1"}' \ |
|
249 |
|
@@base_url@@/op/api |
|
250 |
|
$ ssh rocketgit@rocketgit.com api repo_info name=repo1 |
|
251 |
|
{ |
|
252 |
|
"repo_id": "769", |
|
253 |
|
"name": "repo1", |
|
254 |
|
"uid": "846", |
|
255 |
|
"itime": "1447874006", |
|
256 |
|
"disk_quota_mb": null, |
|
257 |
|
"max_commit_size": "0", |
|
258 |
|
"master": "0", |
|
259 |
|
"<b>Description</b>": "here is a <b>Description</b>", |
|
260 |
|
"git_dir_done": "1", |
|
261 |
|
"deleted": "0", |
|
262 |
|
"disk_used_mb": "0", |
|
263 |
|
"public": "1", |
|
264 |
|
"last_bug_id": "1", |
|
265 |
|
"license": "GPLv3", |
|
266 |
|
"template": "", |
|
267 |
|
"last_mr_id": "0", |
|
268 |
|
"ok": 1, |
|
269 |
|
"exists": 1, |
|
270 |
|
"clone_url": "ssh:\/\/rocketgit@rg.embedromix.ro:2222\/user\/bla\/repo1", |
|
271 |
|
"HTML:<b>Description</b>_nlbr": "here is a <b>Description</b>", |
|
272 |
|
"HTML:itime_nice": "2015-11-18", |
|
273 |
|
"owner": "bla", |
|
274 |
|
"url_user": "http:\/\/r1i:9000\/user\/bla", |
|
275 |
|
"url_repo": "http:\/\/r1i:9000\/user\/bla\/repo1", |
|
276 |
|
"clone_url_ssh": "ssh:\/\/rocketgit@rg.embedromix.ro:2222\/user\/bla\/repo1", |
|
277 |
|
"clone_url_git": "git:\/\/rg.embedromix.ro\/user\/bla\/repo1", |
|
278 |
|
"master_name": "-", |
|
279 |
|
"disk_used": "0B" |
|
280 |
|
} |
|
281 |
|
</div> |
|
282 |
|
<br /> |
|
283 |
|
|
|
284 |
|
<a name="repo_pr_list"><b>repo_pr_list</b></a><br /> |
|
285 |
|
<b>Description</b>: Lists the pull requests<br /> |
|
286 |
|
<b>Parameters</b>: name, repo_id<br /> |
|
287 |
|
Example: |
|
288 |
|
<div class="term"> |
|
289 |
|
$ curl --header 'Authorization: bla this_is_bla_api_key' \ |
|
290 |
|
--data '{"cmd": "repo_pr_list", "name": "repo1"}' \ |
|
291 |
|
@@base_url@@/op/api |
|
292 |
|
$ ssh rocketgit@rocketgit.com api repo_pr_list name=repo1 |
|
293 |
|
[ |
|
294 |
|
{ |
|
295 |
|
"repo_id": "769", |
|
296 |
|
"itime": "1330296541", |
|
297 |
|
"namespace": "rg_b21751c3", |
|
298 |
|
"refname": "refs\/heads\/master", |
|
299 |
|
"old_rev": "afd1df2940fe440cde9b8ede988ff24c051a10d6", |
|
300 |
|
"new_rev": "f919c9bf863471aeb97da6aa2380319a1bee6eda", |
|
301 |
|
"done": "0", |
|
302 |
|
"ip": "2002:2e66:5950::1", |
|
303 |
|
"id": "5", |
|
304 |
|
"who": "0" |
|
305 |
|
}, |
|
306 |
|
... |
|
307 |
|
] |
|
308 |
|
</div> |
|
309 |
|
</div> |
|
310 |
|
</div> |
|
311 |
|
</div> |
|
312 |
|
|
|
313 |
|
</div> |
File root/themes/default/features.html changed (mode: 100644) (index cb6c2cf..4b7c407) |
2 |
2 |
|
|
3 |
3 |
<div class="islands"> |
<div class="islands"> |
4 |
4 |
<div class="island_row"> |
<div class="island_row"> |
5 |
|
<div class="island_cell"> |
|
6 |
|
<div class="island"> |
|
|
5 |
|
<div class="island_cell"> |
|
6 |
|
<div class="island"> |
7 |
7 |
<div class="island_title">FLOS (Free, Libre and Open-Source) software</div> |
<div class="island_title">FLOS (Free, Libre and Open-Source) software</div> |
8 |
8 |
RocketGit is licensed under |
RocketGit is licensed under |
9 |
9 |
the GNU Affero General Public License v3+, therefore you have the freedom |
the GNU Affero General Public License v3+, therefore you have the freedom |
|
16 |
16 |
</div> |
</div> |
17 |
17 |
</div> |
</div> |
18 |
18 |
|
|
19 |
|
<div class="island_cell"> |
|
20 |
|
<div class="island"> |
|
|
19 |
|
<div class="island_cell"> |
|
20 |
|
<div class="island"> |
21 |
21 |
<div class="island_title">Fastest</div> |
<div class="island_title">Fastest</div> |
22 |
22 |
RocketGit is extremely fast as it doesn't contain any Java, |
RocketGit is extremely fast as it doesn't contain any Java, |
23 |
23 |
Javascript or Flash. And we plan to rewrite it in C for maximum speed. |
Javascript or Flash. And we plan to rewrite it in C for maximum speed. |
24 |
24 |
</div> |
</div> |
25 |
25 |
</div> |
</div> |
26 |
26 |
|
|
27 |
|
<div class="island_cell"> |
|
28 |
|
<div class="island"> |
|
|
27 |
|
<div class="island_cell"> |
|
28 |
|
<div class="island"> |
29 |
29 |
<div class="island_title">Lightest</div> |
<div class="island_title">Lightest</div> |
30 |
30 |
RocketGit is really compact, therefore even if you choose to |
RocketGit is really compact, therefore even if you choose to |
31 |
31 |
install it on your machine instead of using it in your web |
install it on your machine instead of using it in your web |
|
36 |
36 |
</div> |
</div> |
37 |
37 |
|
|
38 |
38 |
<div class="island_row"> |
<div class="island_row"> |
39 |
|
<div class="island_cell"> |
|
40 |
|
<div class="island"> |
|
|
39 |
|
<div class="island_cell"> |
|
40 |
|
<div class="island"> |
41 |
41 |
<div class="island_title">Ready to use</div> |
<div class="island_title">Ready to use</div> |
42 |
42 |
You can just open your web browser and start using |
You can just open your web browser and start using |
43 |
43 |
RocketGit, but even if you choose to install RocketGit on your |
RocketGit, but even if you choose to install RocketGit on your |
|
46 |
46 |
</div> |
</div> |
47 |
47 |
</div> |
</div> |
48 |
48 |
|
|
49 |
|
<div class="island_cell"> |
|
50 |
|
<div class="island"> |
|
|
49 |
|
<div class="island_cell"> |
|
50 |
|
<div class="island"> |
51 |
51 |
<div class="island_title">Very easy to maintain</div> |
<div class="island_title">Very easy to maintain</div> |
52 |
52 |
RocketGit has very few dependencies, all packed |
RocketGit has very few dependencies, all packed |
53 |
53 |
in the main-stream distributions, therefore you just upgrade your |
in the main-stream distributions, therefore you just upgrade your |
|
55 |
55 |
</div> |
</div> |
56 |
56 |
</div> |
</div> |
57 |
57 |
|
|
58 |
|
<div class="island_cell"> |
|
59 |
|
<div class="island"> |
|
|
58 |
|
<div class="island_cell"> |
|
59 |
|
<div class="island"> |
60 |
60 |
<div class="island_title">Corporate friendly</div> |
<div class="island_title">Corporate friendly</div> |
61 |
61 |
RocketGit is SELinux protected, |
RocketGit is SELinux protected, |
62 |
62 |
therefore you can keep your system secure while using it. |
therefore you can keep your system secure while using it. |
|
67 |
67 |
</div> |
</div> |
68 |
68 |
|
|
69 |
69 |
<div class="island_row"> |
<div class="island_row"> |
70 |
|
<div class="island_cell"> |
|
71 |
|
<div class="island"> |
|
|
70 |
|
<div class="island_cell"> |
|
71 |
|
<div class="island"> |
72 |
72 |
<div class="island_title">Platform independent</div> |
<div class="island_title">Platform independent</div> |
73 |
73 |
You can use RocketGit in your web browser (no matter what |
You can use RocketGit in your web browser (no matter what |
74 |
74 |
operating system is running on your machine) or you can choose to |
operating system is running on your machine) or you can choose to |
|
77 |
77 |
</div> |
</div> |
78 |
78 |
</div> |
</div> |
79 |
79 |
|
|
80 |
|
<div class="island_cell"> |
|
81 |
|
<div class="island"> |
|
|
80 |
|
<div class="island_cell"> |
|
81 |
|
<div class="island"> |
82 |
82 |
<div class="island_title">Integrated bug tracker</div> |
<div class="island_title">Integrated bug tracker</div> |
83 |
83 |
RocketGit provides the simplest and the most powerful bug tracker: |
RocketGit provides the simplest and the most powerful bug tracker: |
84 |
84 |
minimal input fields, flexible label based tagging |
minimal input fields, flexible label based tagging |
|
86 |
86 |
</div> |
</div> |
87 |
87 |
</div> |
</div> |
88 |
88 |
|
|
89 |
|
<div class="island_cell"> |
|
90 |
|
<div class="island"> |
|
|
89 |
|
<div class="island_cell"> |
|
90 |
|
<div class="island"> |
91 |
91 |
<div class="island_title">Easy to contribute</div> |
<div class="island_title">Easy to contribute</div> |
92 |
92 |
With the anonymous push feature, it becomes very easy to contribute |
With the anonymous push feature, it becomes very easy to contribute |
93 |
93 |
to a project: a clone and a push. You do not even need an account on |
to a project: a clone and a push. You do not even need an account on |
|
97 |
97 |
</div> |
</div> |
98 |
98 |
|
|
99 |
99 |
<div class="island_row"> |
<div class="island_row"> |
100 |
|
<div class="island_cell"> |
|
101 |
|
<div class="island"> |
|
|
100 |
|
<div class="island_cell"> |
|
101 |
|
<div class="island"> |
102 |
102 |
<div class="island_title">Powerful rights management</div> |
<div class="island_title">Powerful rights management</div> |
103 |
103 |
You have a wide range of possibilities to block access to a repository. |
You have a wide range of possibilities to block access to a repository. |
104 |
104 |
You can filter by IPv4/IPv6 addresses (including prefix length), |
You can filter by IPv4/IPv6 addresses (including prefix length), |
|
109 |
109 |
</div> |
</div> |
110 |
110 |
</div> |
</div> |
111 |
111 |
|
|
112 |
|
<div class="island_cell"> |
|
113 |
|
<div class="island"> |
|
|
112 |
|
<div class="island_cell"> |
|
113 |
|
<div class="island"> |
114 |
114 |
<div class="island_title">Web hooks</div> |
<div class="island_title">Web hooks</div> |
115 |
115 |
We provide flexible web hooks allowing you to automate your tasks. |
We provide flexible web hooks allowing you to automate your tasks. |
116 |
116 |
You can easily store a repository archive in |
You can easily store a repository archive in |
|
125 |
125 |
</div> |
</div> |
126 |
126 |
</div> |
</div> |
127 |
127 |
|
|
128 |
|
<div class="island_cell"> |
|
129 |
|
<div class="island"> |
|
|
128 |
|
<div class="island_cell"> |
|
129 |
|
<div class="island"> |
130 |
130 |
<div class="island_title">Built on top of top software</div> |
<div class="island_title">Built on top of top software</div> |
131 |
131 |
RocketGit has been created by using the best products to build upon: |
RocketGit has been created by using the best products to build upon: |
132 |
132 |
Linux, Git, OpenSSH, PostgreSQL, Apache, PHP and SELinux. |
Linux, Git, OpenSSH, PostgreSQL, Apache, PHP and SELinux. |
|
135 |
135 |
</div> |
</div> |
136 |
136 |
|
|
137 |
137 |
<div class="island_row"> |
<div class="island_row"> |
138 |
|
<div class="island_cell"> |
|
139 |
|
<div class="island"> |
|
|
138 |
|
<div class="island_cell"> |
|
139 |
|
<div class="island"> |
140 |
140 |
<div class="island_title">Are there features that you need and they are not here?</div> |
<div class="island_title">Are there features that you need and they are not here?</div> |
141 |
141 |
Do not worry! Let us know by leaving a |
Do not worry! Let us know by leaving a |
142 |
142 |
<a href="/op/suggestion">suggestion</a> (you must be logged in) |
<a href="/op/suggestion">suggestion</a> (you must be logged in) |
File scripts/builder.php changed (mode: 100644) (index 250ef08..fc8b401) |
1 |
1 |
<?php |
<?php |
2 |
2 |
// This is called by cron, and is persistent. |
// This is called by cron, and is persistent. |
3 |
3 |
// It takes care of build jobs. |
// It takes care of build jobs. |
|
4 |
|
// It can be run on the same machine as the webserver. |
4 |
5 |
error_reporting(E_ALL); |
error_reporting(E_ALL); |
5 |
6 |
ini_set("track_errors", "On"); |
ini_set("track_errors", "On"); |
6 |
7 |
set_time_limit(0); |
set_time_limit(0); |
|
... |
... |
require_once($INC . "/admin.inc.php"); |
27 |
28 |
require_once($INC . "/ver.php"); |
require_once($INC . "/ver.php"); |
28 |
29 |
require_once($INC . "/builder.inc.php"); |
require_once($INC . "/builder.inc.php"); |
29 |
30 |
require_once($INC . "/conn.inc.php"); |
require_once($INC . "/conn.inc.php"); |
|
31 |
|
require_once($INC . "/workers.inc.php"); |
|
32 |
|
|
|
33 |
|
if ($rg_builder_port == 0) |
|
34 |
|
exit(0); |
|
35 |
|
|
|
36 |
|
/* |
|
37 |
|
* Called when a connection closes |
|
38 |
|
*/ |
|
39 |
|
function xdestroy($key) |
|
40 |
|
{ |
|
41 |
|
global $workers; |
|
42 |
|
$workers--; |
|
43 |
|
} |
30 |
44 |
|
|
31 |
45 |
/* |
/* |
32 |
46 |
* Called when a new client connects |
* Called when a new client connects |
|
... |
... |
require_once($INC . "/conn.inc.php"); |
34 |
48 |
function xnew($key, $arg) |
function xnew($key, $arg) |
35 |
49 |
{ |
{ |
36 |
50 |
global $rg_conns; |
global $rg_conns; |
|
51 |
|
global $workers; |
37 |
52 |
|
|
38 |
53 |
$s = &$rg_conns[$key]; |
$s = &$rg_conns[$key]; |
39 |
54 |
$s['func_cmd'] = 'xdispatch'; |
$s['func_cmd'] = 'xdispatch'; |
|
55 |
|
$s['func_destroy'] = 'xdestroy'; |
40 |
56 |
$s['db'] = $arg; |
$s['db'] = $arg; |
41 |
57 |
$s['auth'] = 0; |
$s['auth'] = 0; |
|
58 |
|
$s['is_master'] = 0; |
|
59 |
|
$workers++; |
42 |
60 |
} |
} |
43 |
61 |
|
|
|
62 |
|
/* |
|
63 |
|
* Dispatch a command from a worker |
|
64 |
|
*/ |
44 |
65 |
function xdispatch($key, $line) |
function xdispatch($key, $line) |
45 |
66 |
{ |
{ |
46 |
67 |
global $rg_conns; |
global $rg_conns; |
47 |
68 |
global $jobs; |
global $jobs; |
48 |
|
global $rg_builder_key; |
|
49 |
69 |
|
|
50 |
70 |
rg_log('Dispatch[' . $key . ']'); |
rg_log('Dispatch[' . $key . ']'); |
51 |
71 |
|
|
|
... |
... |
function xdispatch($key, $line) |
56 |
76 |
$x = stripcslashes($d); |
$x = stripcslashes($d); |
57 |
77 |
$u = @unserialize($x); |
$u = @unserialize($x); |
58 |
78 |
if ($u === FALSE) { |
if ($u === FALSE) { |
59 |
|
rg_conn_destroy($key); |
|
|
79 |
|
rg_conn_enq($key, 'ERR malformed command' . "\n"); |
|
80 |
|
rg_conn_shutdown($key, 2); |
60 |
81 |
return; |
return; |
61 |
82 |
} |
} |
62 |
83 |
|
|
|
... |
... |
function xdispatch($key, $line) |
64 |
85 |
|
|
65 |
86 |
if (strcmp($cmd, 'ANN ') == 0) { |
if (strcmp($cmd, 'ANN ') == 0) { |
66 |
87 |
$now = time(); |
$now = time(); |
67 |
|
if ($u['boot_time'] < $now - 10) { |
|
|
88 |
|
if (($u['boot_time'] < $now - 30) || ($u['boot_time'] > $now + 30)) { |
68 |
89 |
rg_log('boot_time is too old; abort'); |
rg_log('boot_time is too old; abort'); |
69 |
|
rg_conn_destroy($key); |
|
|
90 |
|
rg_conn_enq($key, 'ERR time not in sync between worker' |
|
91 |
|
. ' and server' . "\n"); |
|
92 |
|
rg_conn_shutdown($key, 2); |
|
93 |
|
return; |
|
94 |
|
} |
|
95 |
|
|
|
96 |
|
// Lookup user first |
|
97 |
|
if (!isset($u['type'])) |
|
98 |
|
$u['type'] = 'global'; |
|
99 |
|
if (strcasecmp($u['type'], 'global') == 0) { |
|
100 |
|
$worker_uid = 0; |
|
101 |
|
} else if (!isset($u['user'])) { |
|
102 |
|
rg_log('user field is not present; abort'); |
|
103 |
|
rg_conn_enq($key, 'ERR user not defined in conf file' . "\n"); |
|
104 |
|
rg_conn_shutdown($key, 2); |
|
105 |
|
return; |
|
106 |
|
} else { |
|
107 |
|
$w_ui = rg_user_info($s['db'], 0, $u['user'], ''); |
|
108 |
|
if ($w_ui['exists'] !== 1) { |
|
109 |
|
rg_log('invalid user; abort'); |
|
110 |
|
rg_conn_enq($key, 'ERR invalid user' . "\n"); |
|
111 |
|
rg_conn_shutdown($key, 2); |
|
112 |
|
return; |
|
113 |
|
} |
|
114 |
|
|
|
115 |
|
$worker_uid = $w_ui['uid']; |
|
116 |
|
} |
|
117 |
|
|
|
118 |
|
// Check if worker is registered |
|
119 |
|
$wi = rg_worker_find_by_name($s['db'], $worker_uid, $u['name']); |
|
120 |
|
if ($wi === -1) { |
|
121 |
|
rg_log('cannot load worker info: ' |
|
122 |
|
. rg_worker_error() . '; abort'); |
|
123 |
|
rg_conn_enq($key, 'ERR internal error' . "\n"); |
|
124 |
|
rg_conn_shutdown($key, 2); |
70 |
125 |
return; |
return; |
71 |
126 |
} |
} |
72 |
|
$sign = hash_hmac('sha512', $u['boot_time'], $rg_builder_key); |
|
|
127 |
|
if ($wi === 0) { |
|
128 |
|
rg_log('name [' . $u['name'] . '] not found; abort'); |
|
129 |
|
$err = 'ERR builder name not found, add it in the web' |
|
130 |
|
. ' interface!' . "\n"; |
|
131 |
|
rg_conn_enq($key, $err); |
|
132 |
|
rg_conn_shutdown($key, 2); |
|
133 |
|
return; |
|
134 |
|
} |
|
135 |
|
|
|
136 |
|
$sign = hash_hmac('sha512', $u['boot_time'], $wi['key']); |
73 |
137 |
if (strcmp($sign, $u['sign']) != 0) { |
if (strcmp($sign, $u['sign']) != 0) { |
74 |
138 |
rg_log('signature is not ok [' . $sign . ']' |
rg_log('signature is not ok [' . $sign . ']' |
75 |
139 |
. ' != [' . $u['sign'] . ']'); |
. ' != [' . $u['sign'] . ']'); |
76 |
|
rg_conn_destroy($key); |
|
|
140 |
|
rg_conn_enq($key, 'ERR wrong signature' . "\n"); |
|
141 |
|
rg_conn_shutdown($key, 2); |
77 |
142 |
return; |
return; |
78 |
143 |
} |
} |
|
144 |
|
$s['worker_id'] = $wi['id']; |
|
145 |
|
$s['worker_uid'] = $worker_uid; |
79 |
146 |
$s['ann'] = $u; |
$s['ann'] = $u; |
80 |
147 |
$s['auth'] = 1; |
$s['auth'] = 1; |
81 |
|
rg_log('Peer announced itself!'); |
|
82 |
|
} else if (strcmp($cmd, 'STA ') == 0) { |
|
83 |
|
if ($s['auth'] != 1) { |
|
84 |
|
rg_log($key . ':Client not authenticated!'); |
|
85 |
|
$a = array('error' => 'client not authenticated'); |
|
86 |
|
$cmd = 'ERR ' . rg_conn_prepare($a) . "\n"; |
|
87 |
|
rg_conn_enq($key, $cmd); |
|
88 |
|
return; |
|
89 |
|
} |
|
|
148 |
|
$s['active_jobs'] = 0; |
|
149 |
|
|
|
150 |
|
$a = array(); |
|
151 |
|
$a['name'] = $u['name']; |
|
152 |
|
$a['uname'] = $u['uname']; |
|
153 |
|
$a['host'] = $u['host']; |
|
154 |
|
$a['arch'] = $u['arch']; |
|
155 |
|
$a['env'] = $u['env']; |
|
156 |
|
$a['ssh_key'] = $u['ssh_key']; |
|
157 |
|
$a['ip'] = rg_fix_ip($s['ip']); |
|
158 |
|
rg_worker_update($s['db'], $worker_uid, $wi['id'], $a); |
|
159 |
|
|
|
160 |
|
rg_log($key . ':Peer [' . $u['name'] . '] announce'); |
|
161 |
|
return; |
|
162 |
|
} |
|
163 |
|
|
|
164 |
|
if ($s['auth'] != 1) { |
|
165 |
|
rg_log($key . ':Client not authenticated!'); |
|
166 |
|
$a = array('error' => 'client not authenticated'); |
|
167 |
|
$cmd = 'ERR ' . rg_conn_prepare($a) . "\n"; |
|
168 |
|
rg_conn_enq($key, $cmd); |
|
169 |
|
return; |
|
170 |
|
} |
|
171 |
|
|
|
172 |
|
if (strcmp($cmd, 'STA ') == 0) { |
90 |
173 |
$jid = $u['id']; |
$jid = $u['id']; |
91 |
174 |
$jobs[$jid]['worker'] = $key; |
$jobs[$jid]['worker'] = $key; |
|
175 |
|
$jobs[$jid]['worker_name'] = $s['ann']['name']; |
92 |
176 |
$jobs[$jid]['worker_started'] = time(); |
$jobs[$jid]['worker_started'] = time(); |
|
177 |
|
$s['active_jobs'] += 1; |
93 |
178 |
rg_log('Job started: ' . $jid); |
rg_log('Job started: ' . $jid); |
94 |
|
} else if (strcmp($cmd, 'DON ') == 0) { |
|
95 |
|
if ($s['auth'] != 1) { |
|
96 |
|
rg_log($key . ':Client not authenticated!'); |
|
97 |
|
$a = array('error' => 'client not authenticated'); |
|
98 |
|
$cmd = 'ERR ' . rg_conn_prepare($a) . "\n"; |
|
99 |
|
rg_conn_enq($key, $cmd); |
|
|
179 |
|
return; |
|
180 |
|
} |
|
181 |
|
|
|
182 |
|
if (strcmp($cmd, 'DON ') == 0) { |
|
183 |
|
$s['active_jobs'] -= 1; |
|
184 |
|
|
|
185 |
|
$jid = $u['id']; |
|
186 |
|
if (isset($u['error'])) { |
|
187 |
|
rg_log('job failed with error: ' . $u['error']); |
|
188 |
|
// Delay job and retry (on another worker) |
|
189 |
|
$jobs[$jid]['next_try'] = time() + 60; |
|
190 |
|
$k = $s['worker_id']; |
|
191 |
|
$jobs[$jid]['avoid'][$k] = 1; |
100 |
192 |
return; |
return; |
101 |
193 |
} |
} |
102 |
|
$jid = $u['id']; |
|
|
194 |
|
|
103 |
195 |
$r = rg_builder_done($s['db'], $jobs[$jid], $u['status']); |
$r = rg_builder_done($s['db'], $jobs[$jid], $u['status']); |
104 |
196 |
if ($r === TRUE) { |
if ($r === TRUE) { |
105 |
197 |
unset($jobs[$jid]); |
unset($jobs[$jid]); |
|
... |
... |
function xdispatch($key, $line) |
108 |
200 |
$cmd = 'DRE ' . rg_conn_prepare($a) . "\n"; |
$cmd = 'DRE ' . rg_conn_prepare($a) . "\n"; |
109 |
201 |
rg_conn_enq($key, $cmd); |
rg_conn_enq($key, $cmd); |
110 |
202 |
} |
} |
111 |
|
} else { |
|
112 |
|
rg_log('Unknown command [' . $cmd . ']!'); |
|
|
203 |
|
return; |
113 |
204 |
} |
} |
|
205 |
|
|
|
206 |
|
rg_log('Unknown command [' . $cmd . ']!'); |
114 |
207 |
} |
} |
115 |
208 |
|
|
116 |
|
function rg_process_queue($db, &$job) |
|
|
209 |
|
function rg_process_job($db, &$job) |
117 |
210 |
{ |
{ |
118 |
211 |
global $rg_conns; |
global $rg_conns; |
119 |
212 |
|
|
120 |
|
rg_log('process_queue: worker=' . $job['worker']); |
|
|
213 |
|
// Job is already in progress? |
121 |
214 |
if (!empty($job['worker'])) |
if (!empty($job['worker'])) |
122 |
215 |
return; |
return; |
123 |
216 |
|
|
|
217 |
|
// Should we delay because of a previous fail? |
|
218 |
|
if (isset($job['next_try']) && ($job['next_try'] < time())) |
|
219 |
|
return; |
|
220 |
|
|
124 |
221 |
rg_log_ml('Processing job: ' . print_r($job, TRUE)); |
rg_log_ml('Processing job: ' . print_r($job, TRUE)); |
125 |
222 |
|
|
126 |
|
// Find a target for this job |
|
|
223 |
|
// Get the worker list, so we can sort it |
|
224 |
|
$workers_list = rg_worker_list_all($db, $job['uid']); |
|
225 |
|
if ($workers_list === FALSE) { |
|
226 |
|
rg_log('cannot load workers list: ' . rg_worker_error()); |
|
227 |
|
$job['next_try'] = time() + 60; |
|
228 |
|
return; |
|
229 |
|
} |
|
230 |
|
//rg_log_ml('DEBUG: workers list: ' . print_r($workers_list, TRUE)); |
|
231 |
|
|
|
232 |
|
// Trying to find a worker in the list of connections |
127 |
233 |
$found = FALSE; |
$found = FALSE; |
128 |
234 |
foreach ($rg_conns as $key => $i) { |
foreach ($rg_conns as $key => $i) { |
129 |
|
// Is it a worker? |
|
|
235 |
|
if (strcmp($key, 'master') == 0) |
|
236 |
|
continue; |
|
237 |
|
|
130 |
238 |
if (!isset($i['ann'])) { |
if (!isset($i['ann'])) { |
131 |
239 |
rg_log('Conn ' . $key . ' has no announce.'); |
rg_log('Conn ' . $key . ' has no announce.'); |
132 |
240 |
// TODO: close after some time? |
// TODO: close after some time? |
|
... |
... |
function rg_process_queue($db, &$job) |
138 |
246 |
continue; |
continue; |
139 |
247 |
} |
} |
140 |
248 |
|
|
|
249 |
|
if (($i['worker_uid'] > 0) && ($i['worker_uid'] != $job['uid'])) { |
|
250 |
|
//rg_log('uid does not match, try next'); |
|
251 |
|
continue; |
|
252 |
|
} |
|
253 |
|
|
|
254 |
|
$k = $i['worker_uid']; |
|
255 |
|
if (!isset($workers_list[$k])) { |
|
256 |
|
rg_log('Worker ' . $k . ' not found in workers_list! Strange!'); |
|
257 |
|
continue; |
|
258 |
|
} |
|
259 |
|
$wi = $workers_list[$k]; |
|
260 |
|
|
|
261 |
|
if (isset($job['avoid'][$k])) { |
|
262 |
|
rg_log('We must avoid worker ' . $k); |
|
263 |
|
continue; |
|
264 |
|
} |
|
265 |
|
|
|
266 |
|
rg_log('DEBUG: selected worker ' . $k); |
|
267 |
|
|
|
268 |
|
// If number of active jobs is == max workers, skip it |
|
269 |
|
if ($wi['workers'] <= $i['active_jobs']) { |
|
270 |
|
rg_log('DEBUG: workers=' . $wi['workers'] |
|
271 |
|
. ' active_jobs=' . $i['active_jobs']); |
|
272 |
|
continue; |
|
273 |
|
} |
|
274 |
|
|
141 |
275 |
foreach ($i['ann']['env'] as $env => $junk) { |
foreach ($i['ann']['env'] as $env => $junk) { |
142 |
|
if (strcmp($job['env'], $env) != 0) { |
|
143 |
|
rg_log('job env [' . $job['env'] . ']' |
|
144 |
|
. ' != worker [' . $env . ']'); |
|
|
276 |
|
if (strcasecmp($job['env'], $env) != 0) { |
|
277 |
|
//rg_log('DEBUG job env [' . $job['env'] . ']' |
|
278 |
|
// . ' != worker [' . $env . ']'); |
145 |
279 |
continue; |
continue; |
146 |
280 |
} |
} |
147 |
281 |
|
|
148 |
|
// Remove some stuff |
|
149 |
|
$job2 = $job; |
|
150 |
|
unset($job2['worker']); |
|
151 |
|
unset($job2['events']); |
|
152 |
|
unset($job2['flags']); |
|
|
282 |
|
// Send only what is really needed |
|
283 |
|
$job2 = array(); |
|
284 |
|
$job2['cmds'] = $job['cmds']; |
|
285 |
|
$job2['packages'] = $job['packages']; |
|
286 |
|
$job2['hook_id'] = $job['hook_id']; |
|
287 |
|
$job2['url'] = $job['url']; |
|
288 |
|
$job2['head'] = $job['head']; |
|
289 |
|
$job2['env'] = $job['env']; |
|
290 |
|
$job2['id'] = $job['id']; |
153 |
291 |
|
|
154 |
292 |
$cmd = 'BLD ' . rg_conn_prepare($job2) . "\n"; |
$cmd = 'BLD ' . rg_conn_prepare($job2) . "\n"; |
155 |
293 |
rg_conn_enq($key, $cmd); |
rg_conn_enq($key, $cmd); |
|
... |
... |
function rg_process_queue($db, &$job) |
157 |
295 |
$job['worker'] = $key; |
$job['worker'] = $key; |
158 |
296 |
$job['worker_started'] = 0; |
$job['worker_started'] = 0; |
159 |
297 |
$job['worker_sent'] = time(); |
$job['worker_sent'] = time(); |
160 |
|
rg_log_ml('After sending BLD: ' . print_r($job, TRUE)); |
|
|
298 |
|
rg_log_ml('DEBUG: After sending BLD: job: ' . print_r($job, TRUE)); |
161 |
299 |
// TODO: after some time, if worker_started is still 0, |
// TODO: after some time, if worker_started is still 0, |
162 |
300 |
// mark the 'worker' as '' to be able to go in other place |
// mark the 'worker' as '' to be able to go in other place |
163 |
301 |
// TODO: maybe the client must resync with server to |
// TODO: maybe the client must resync with server to |
|
... |
... |
rg_prof_start("MAIN"); |
177 |
315 |
|
|
178 |
316 |
rg_log_set_file($rg_log_dir . "/builder.log"); |
rg_log_set_file($rg_log_dir . "/builder.log"); |
179 |
317 |
rg_log_set_sid("000000"); // to spread the logs |
rg_log_set_sid("000000"); // to spread the logs |
180 |
|
// We must disable cache, else, we will not receive the updates because |
|
181 |
|
// of the core cache. Do not forget that we are a long live process. |
|
182 |
|
$rg_cache_core_enable = FALSE; |
|
183 |
318 |
|
|
184 |
319 |
rg_log("Start (ver=$rocketgit_version)..."); |
rg_log("Start (ver=$rocketgit_version)..."); |
185 |
320 |
|
|
|
... |
... |
rg_conn_new('master', $socket); |
225 |
360 |
$rg_conns['master']['exit_on_close'] = 1; |
$rg_conns['master']['exit_on_close'] = 1; |
226 |
361 |
$rg_conns['master']['func_new'] = 'xnew'; |
$rg_conns['master']['func_new'] = 'xnew'; |
227 |
362 |
$rg_conns['master']['func_new_arg'] = $db; |
$rg_conns['master']['func_new_arg'] = $db; |
|
363 |
|
$rg_conns['master']['is_master'] = 1; |
228 |
364 |
|
|
229 |
365 |
$jobs = array(); |
$jobs = array(); |
230 |
366 |
|
|
|
367 |
|
$workers = 0; |
231 |
368 |
$original_mtime = @filemtime(__FILE__); |
$original_mtime = @filemtime(__FILE__); |
232 |
369 |
do { |
do { |
233 |
370 |
rg_log_buffer_clear(); |
rg_log_buffer_clear(); |
234 |
371 |
|
|
|
372 |
|
// We do not want stale entries! |
|
373 |
|
rg_cache_core_destroy(); |
|
374 |
|
|
235 |
375 |
// Check our mtime so we can upgrade the software and this script |
// Check our mtime so we can upgrade the software and this script |
236 |
376 |
// will restart. |
// will restart. |
237 |
377 |
clearstatcache(); |
clearstatcache(); |
|
... |
... |
do { |
242 |
382 |
break; |
break; |
243 |
383 |
} |
} |
244 |
384 |
|
|
245 |
|
$r = rg_builder_load_jobs($db); |
|
246 |
|
if ($r['ok'] != 1) { |
|
247 |
|
rg_log('Cannot load jobs from database!'); |
|
248 |
|
sleep(30); |
|
249 |
|
continue; |
|
250 |
|
} |
|
251 |
|
|
|
252 |
|
foreach ($r['list'] as $jid => $job) { |
|
253 |
|
if (!isset($jobs[$jid])) { |
|
254 |
|
$job['worker'] = ''; |
|
255 |
|
$job['url'] = 'git://rg.embedromix.ro/user/catab/delme10'; // TODO |
|
256 |
|
$jobs[$jid] = $job; |
|
|
385 |
|
if ($workers > 0) { |
|
386 |
|
$r = rg_builder_load_jobs($db); |
|
387 |
|
if ($r['ok'] != 1) { |
|
388 |
|
rg_log('Cannot load jobs from database! Sleeping 30s...'); |
|
389 |
|
sleep(30); |
|
390 |
|
continue; |
257 |
391 |
} |
} |
258 |
392 |
|
|
259 |
|
$r = rg_process_queue($db, $jobs[$jid]); |
|
|
393 |
|
foreach ($r['list'] as $jid => $job) { |
|
394 |
|
if (!isset($jobs[$jid])) { |
|
395 |
|
$job['worker'] = ''; |
|
396 |
|
$job['avoid'] = array(); // to avoid workers |
|
397 |
|
$jobs[$jid] = $job; |
|
398 |
|
} |
|
399 |
|
|
|
400 |
|
$r = rg_process_job($db, $jobs[$jid]); |
|
401 |
|
if ($r === FALSE) |
|
402 |
|
break; |
|
403 |
|
} |
260 |
404 |
if ($r === FALSE) |
if ($r === FALSE) |
261 |
405 |
break; |
break; |
262 |
406 |
} |
} |
263 |
|
if ($r === FALSE) |
|
264 |
|
break; |
|
265 |
407 |
|
|
266 |
408 |
rg_log("Waiting for connections..."); |
rg_log("Waiting for connections..."); |
267 |
409 |
rg_conn_wait(10); |
rg_conn_wait(10); |
File scripts/remote.php changed (mode: 100644) (index c9a2684..5379e0d) |
... |
... |
if (isset($_SERVER['SSH_CONNECTION'])) { |
85 |
85 |
|
|
86 |
86 |
// first parameter must be uid of the user |
// first parameter must be uid of the user |
87 |
87 |
$login_uid = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : 0; |
$login_uid = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : 0; |
88 |
|
if ($login_uid == 0) |
|
89 |
|
fatal("uid not provided!"); |
|
90 |
88 |
rg_log("uid is $login_uid."); |
rg_log("uid is $login_uid."); |
91 |
89 |
|
|
92 |
90 |
// second parameter must be the ssh key id |
// second parameter must be the ssh key id |
93 |
91 |
$key_id = isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : 0; |
$key_id = isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : 0; |
94 |
|
if ($key_id == 0) |
|
95 |
|
fatal("key_id not provided!"); |
|
|
92 |
|
// TODO: because of build system, 0 may be valid. |
|
93 |
|
//if ($key_id == 0) |
|
94 |
|
// fatal("key_id not provided!"); |
96 |
95 |
rg_log("key_id is $key_id."); |
rg_log("key_id is $key_id."); |
97 |
96 |
|
|
|
97 |
|
// Third para is 'flags' |
|
98 |
|
$flags = isset($_SERVER['argv'][3]) ? $_SERVER['argv'][3] : ''; |
|
99 |
|
rg_log('flags=' . $flags); |
|
100 |
|
|
98 |
101 |
if (!isset($_SERVER['SSH_ORIGINAL_COMMAND'])) |
if (!isset($_SERVER['SSH_ORIGINAL_COMMAND'])) |
99 |
102 |
$cmd_repo = ""; |
$cmd_repo = ""; |
100 |
103 |
else |
else |
|
... |
... |
if (isset($_SERVER['SSH_CONNECTION'])) { |
114 |
117 |
|
|
115 |
118 |
putenv('ROCKETGIT_INFO_SHOW=1'); |
putenv('ROCKETGIT_INFO_SHOW=1'); |
116 |
119 |
|
|
117 |
|
$must_exit = rg_ssh_dispatch($db, $ip, $login_uid, $cmd_repo); |
|
118 |
|
|
|
119 |
|
// We do this operation after dispatch to not impact the latency. |
|
120 |
|
// TODO: This should be put in a queue for performance reasons |
|
121 |
|
// At the same time, update stats? events? |
|
122 |
|
$_r = rg_keys_update_use($db, $conn_ui['uid'], $key_id, $ip, $cmd_repo); |
|
123 |
|
if ($_r !== TRUE) |
|
124 |
|
rg_internal_error("Cannot update key last_use!"); |
|
|
120 |
|
// Only normal keys can execute some commands |
|
121 |
|
if (strstr($flags, 'N')) |
|
122 |
|
$must_exit = rg_ssh_dispatch($db, $ip, $login_uid, $cmd_repo); |
|
123 |
|
else |
|
124 |
|
$must_exit = FALSE; |
|
125 |
|
|
|
126 |
|
// Only normal keys can update stats |
|
127 |
|
if (strstr($flags, 'N')) { |
|
128 |
|
// We do this operation after dispatch to not impact the latency. |
|
129 |
|
// TODO: This should be put in a queue for performance reasons |
|
130 |
|
// At the same time, update stats? events? |
|
131 |
|
$_r = rg_keys_update_use($db, $conn_ui['uid'], $key_id, $ip, |
|
132 |
|
$cmd_repo); |
|
133 |
|
if ($_r !== TRUE) |
|
134 |
|
rg_internal_error("Cannot update key last_use!"); |
|
135 |
|
} |
125 |
136 |
|
|
126 |
137 |
if ($must_exit) { |
if ($must_exit) { |
127 |
138 |
rg_prof_end("remote.php"); |
rg_prof_end("remote.php"); |
|
... |
... |
if (isset($_SERVER['SSH_CONNECTION'])) { |
134 |
145 |
// we have no client info |
// we have no client info |
135 |
146 |
$login_uid = 0; |
$login_uid = 0; |
136 |
147 |
$key_id = 0; |
$key_id = 0; |
|
148 |
|
$flags = ''; |
137 |
149 |
$conn_ui = array('uid' => 0, |
$conn_ui = array('uid' => 0, |
138 |
150 |
'username' => 'anonymous user', |
'username' => 'anonymous user', |
139 |
151 |
'organization' => 0); |
'organization' => 0); |
|
... |
... |
if (strcmp($_t[0], "user") == 0) { |
191 |
203 |
|
|
192 |
204 |
rg_log("host=[$host] cmd=[$cmd] prefix=[$prefix] user=[$user] repo=[$repo]."); |
rg_log("host=[$host] cmd=[$cmd] prefix=[$prefix] user=[$user] repo=[$repo]."); |
193 |
205 |
|
|
|
206 |
|
if (strstr($flags, 'W')) { |
|
207 |
|
// We are a worker, the command may be only for clonning! |
|
208 |
|
if (strcmp($cmd, 'git-upload-pack') != 0) |
|
209 |
|
fatal('A worker can only clone!'); |
|
210 |
|
} |
|
211 |
|
|
194 |
212 |
// validity/security checks |
// validity/security checks |
195 |
213 |
// Load info about the owner |
// Load info about the owner |
196 |
214 |
if (rg_user_ok($user) !== TRUE) |
if (rg_user_ok($user) !== TRUE) |
|
... |
... |
putenv("ROCKETGIT_REPO_ID=" . $ri['repo_id']); |
277 |
295 |
putenv("ROCKETGIT_REPO_PATH=" . $repo_path); |
putenv("ROCKETGIT_REPO_PATH=" . $repo_path); |
278 |
296 |
putenv("ROCKETGIT_REPO_NAME=" . $ri['name']); |
putenv("ROCKETGIT_REPO_NAME=" . $ri['name']); |
279 |
297 |
putenv("ROCKETGIT_REPO_UID=" . $ri['uid']); |
putenv("ROCKETGIT_REPO_UID=" . $ri['uid']); |
280 |
|
putenv("ROCKETGIT_CLONE_URL=" . $ri['clone_url']); |
|
|
298 |
|
putenv("ROCKETGIT_REPO_CLONE_URL=" . $ri['clone_url']); |
281 |
299 |
putenv("ROCKETGIT_IP=$ip"); |
putenv("ROCKETGIT_IP=$ip"); |
282 |
300 |
putenv("ROCKETGIT_ITIME=" . microtime(TRUE)); |
putenv("ROCKETGIT_ITIME=" . microtime(TRUE)); |
283 |
301 |
putenv("ROCKETGIT_HOST=" . $host); |
putenv("ROCKETGIT_HOST=" . $host); |
File scripts/worker.php changed (mode: 100644) (index 16328b0..92b7ab7) |
1 |
1 |
<?php |
<?php |
2 |
2 |
// Client for continuous integration and deployment |
// Client for continuous integration and deployment |
|
3 |
|
// It can run on the same machine as the web server. |
3 |
4 |
error_reporting(E_ALL); |
error_reporting(E_ALL); |
4 |
5 |
ini_set('track_errors', 'On'); |
ini_set('track_errors', 'On'); |
5 |
6 |
set_time_limit(0); |
set_time_limit(0); |
|
... |
... |
set_time_limit(0); |
7 |
8 |
define('RG_JOB_INIT', 1); |
define('RG_JOB_INIT', 1); |
8 |
9 |
define('RG_JOB_HELPER_STARTED', 2); |
define('RG_JOB_HELPER_STARTED', 2); |
9 |
10 |
define('RG_JOB_STARTED', 3); |
define('RG_JOB_STARTED', 3); |
|
11 |
|
define('RG_JOB_ERROR', 4); |
10 |
12 |
define('RG_JOB_DONE', 10); |
define('RG_JOB_DONE', 10); |
11 |
13 |
|
|
12 |
14 |
$_s = microtime(TRUE); |
$_s = microtime(TRUE); |
|
... |
... |
require_once($INC . "/conn.inc.php"); |
20 |
22 |
|
|
21 |
23 |
rg_prof_start('MAIN'); |
rg_prof_start('MAIN'); |
22 |
24 |
|
|
|
25 |
|
// TODO: use different files for different workers! |
23 |
26 |
rg_log_set_file($rg_log_dir . '/worker.log'); |
rg_log_set_file($rg_log_dir . '/worker.log'); |
24 |
27 |
rg_log_set_sid("000000"); // to spread the logs |
rg_log_set_sid("000000"); // to spread the logs |
25 |
28 |
|
|
|
29 |
|
if (!isset($_SERVER['argv'][1])) |
|
30 |
|
$conf_file = '/etc/rocketgit/worker.conf'; |
|
31 |
|
else |
|
32 |
|
$conf_file = $_SERVER['argv'][1]; |
|
33 |
|
rg_log('conf_file=' . $conf_file); |
26 |
34 |
|
|
27 |
35 |
/* |
/* |
28 |
36 |
* Load configuration file |
* Load configuration file |
29 |
37 |
*/ |
*/ |
30 |
38 |
function reload_config() |
function reload_config() |
31 |
39 |
{ |
{ |
|
40 |
|
global $conf_file; |
32 |
41 |
global $conf; |
global $conf; |
33 |
42 |
|
|
34 |
|
$_conf = @file('/etc/rocketgit/worker.conf'); |
|
|
43 |
|
$_conf = @file($conf_file); |
|
44 |
|
if ($_conf === FALSE) { |
|
45 |
|
// worker.conf not found |
|
46 |
|
exit(0); |
|
47 |
|
} |
|
48 |
|
|
35 |
49 |
$last_key = FALSE; |
$last_key = FALSE; |
36 |
|
if ($_conf !== FALSE) { |
|
37 |
|
$conf = array('env' => array()); |
|
38 |
|
foreach ($_conf as $line) { |
|
39 |
|
if (empty(trim($line))) |
|
40 |
|
continue; |
|
|
50 |
|
$conf = array('env' => array()); |
|
51 |
|
foreach ($_conf as $line) { |
|
52 |
|
$tline = trim($line); |
|
53 |
|
if (empty($tline)) |
|
54 |
|
continue; |
41 |
55 |
|
|
42 |
|
if (strncmp($line, '#', 1) == 0) |
|
|
56 |
|
if (strncmp($tline, '#', 1) == 0) |
|
57 |
|
continue; |
|
58 |
|
|
|
59 |
|
$t = explode('=', $line, 2); |
|
60 |
|
if (count($t) != 2) { |
|
61 |
|
rg_log('Invalid line [' . $line . ']!'); |
|
62 |
|
continue; |
|
63 |
|
} |
|
64 |
|
|
|
65 |
|
$var = trim($t[0]); |
|
66 |
|
$value = trim($t[1]); |
|
67 |
|
|
|
68 |
|
if (strcmp($var, 'env') == 0) { |
|
69 |
|
$conf['env'][$value] = array('paras' => ''); |
|
70 |
|
$last_parent = &$conf['env'][$value]; |
|
71 |
|
} else if ((strncmp($line, " ", 1) == 0) |
|
72 |
|
|| (strncmp($line, "\t", 1) == 0)) { |
|
73 |
|
if ($last_parent === FALSE) { |
|
74 |
|
rg_log('Invalid line [' . $line . ']!'); |
43 |
75 |
continue; |
continue; |
|
76 |
|
} |
44 |
77 |
|
|
45 |
78 |
$t = explode('=', $line, 2); |
$t = explode('=', $line, 2); |
46 |
79 |
if (count($t) != 2) { |
if (count($t) != 2) { |
|
... |
... |
function reload_config() |
50 |
83 |
|
|
51 |
84 |
$var = trim($t[0]); |
$var = trim($t[0]); |
52 |
85 |
$value = trim($t[1]); |
$value = trim($t[1]); |
|
86 |
|
$last_parent[$var] = $value; |
|
87 |
|
} else { |
|
88 |
|
$conf[$var] = $value; |
|
89 |
|
$last_parent = FALSE; |
|
90 |
|
} |
|
91 |
|
} |
53 |
92 |
|
|
54 |
|
if (strcmp($var, 'env') == 0) { |
|
55 |
|
$conf['env'][$value] = array('paras' => ''); |
|
56 |
|
$last_parent = &$conf['env'][$value]; |
|
57 |
|
} else if ((strncmp($line, " ", 1) == 0) |
|
58 |
|
|| (strncmp($line, "\t", 1) == 0)) { |
|
59 |
|
if ($last_parent === FALSE) { |
|
60 |
|
rg_log('Invalid line [' . $line . ']!'); |
|
61 |
|
continue; |
|
62 |
|
} |
|
63 |
|
|
|
64 |
|
$t = explode('=', $line, 2); |
|
65 |
|
if (count($t) != 2) { |
|
66 |
|
rg_log('Invalid line [' . $line . ']!'); |
|
67 |
|
continue; |
|
68 |
|
} |
|
69 |
|
|
|
70 |
|
$var = trim($t[0]); |
|
71 |
|
$value = trim($t[1]); |
|
72 |
|
$last_parent[$var] = $value; |
|
73 |
|
} else { |
|
74 |
|
$conf[$var] = $value; |
|
75 |
|
$last_parent = FALSE; |
|
76 |
|
} |
|
|
93 |
|
if (!file_exists($conf['state'] . '/key.pub')) { |
|
94 |
|
rg_log('Creating SSH key...'); |
|
95 |
|
$cmd = 'ssh-keygen -t rsa -b 4096 -N \'\'' |
|
96 |
|
. ' -C \'Key to connect to builder\'' |
|
97 |
|
. ' -f ' . escapeshellarg($conf['state'] . '/key'); |
|
98 |
|
$r = rg_exec($cmd); |
|
99 |
|
if ($r['ok'] != 1) { |
|
100 |
|
rg_log('Cannot create key: ' . $r['data'] . '!'); |
|
101 |
|
sleep(60); |
|
102 |
|
exit(0); |
77 |
103 |
} |
} |
78 |
|
} else { |
|
79 |
|
$conf = array( |
|
80 |
|
'workers' => '1', |
|
81 |
|
'cost' => 1, |
|
82 |
|
'env' => array() |
|
83 |
|
); |
|
84 |
104 |
} |
} |
|
105 |
|
$conf['ssh_key'] = @file_get_contents($conf['state'] . '/key.pub'); |
|
106 |
|
if ($conf['ssh_key'] === FALSE) { |
|
107 |
|
rg_log('Cannot load key!'); |
|
108 |
|
sleep(60); |
|
109 |
|
exit(0); |
|
110 |
|
} |
|
111 |
|
|
85 |
112 |
rg_log_ml('conf: ' . print_r($conf, TRUE)); |
rg_log_ml('conf: ' . print_r($conf, TRUE)); |
86 |
113 |
} |
} |
87 |
114 |
|
|
|
... |
... |
function start_worker($job) |
146 |
173 |
break; |
break; |
147 |
174 |
} |
} |
148 |
175 |
|
|
|
176 |
|
// Seems that mkfs is not in PATH when it is runned from cron |
|
177 |
|
$path = getenv('PATH'); |
|
178 |
|
putenv('PATH=' . $path . ':/usr/sbin'); |
|
179 |
|
|
149 |
180 |
$r = rg_exec('mkfs.ext4 -L RG ' . $img2); |
$r = rg_exec('mkfs.ext4 -L RG ' . $img2); |
150 |
181 |
if ($r['ok'] !== 1) { |
if ($r['ok'] !== 1) { |
151 |
182 |
$reason = 'cannot create fs: ' . $r['errmsg']; |
$reason = 'cannot create fs: ' . $r['errmsg']; |
|
... |
... |
function start_worker($job) |
166 |
197 |
$do_umount = TRUE; |
$do_umount = TRUE; |
167 |
198 |
|
|
168 |
199 |
// Clone repo |
// Clone repo |
|
200 |
|
putenv('GIT_SSH_COMMAND=ssh' |
|
201 |
|
. ' -o PasswordAuthentication=no' |
|
202 |
|
. ' -o IdentityFile=' |
|
203 |
|
. escapeshellarg($conf['state'] . '/key')); |
169 |
204 |
$cmd = 'git clone --depth 1' |
$cmd = 'git clone --depth 1' |
170 |
205 |
. ' ' . escapeshellarg($job['url']) |
. ' ' . escapeshellarg($job['url']) |
171 |
206 |
. ' ' . $emain . '/root/git'; |
. ' ' . $emain . '/root/git'; |
|
... |
... |
function start_worker($job) |
176 |
211 |
} |
} |
177 |
212 |
|
|
178 |
213 |
// Build command list |
// Build command list |
|
214 |
|
// TODO: document how a user can add labels in configure or make |
179 |
215 |
$s = 'export RG_LABELS=/mnt/status/RG_LABELS' . "\n\n"; |
$s = 'export RG_LABELS=/mnt/status/RG_LABELS' . "\n\n"; |
180 |
216 |
$s .= 'cd /mnt/git' . "\n\n"; |
$s .= 'cd /mnt/git' . "\n\n"; |
181 |
217 |
$s .= 'git checkout ' . escapeshellarg($job['head']) . "\n"; |
$s .= 'git checkout ' . escapeshellarg($job['head']) . "\n"; |
182 |
218 |
foreach ($job['cmds'] as $name => $i) { |
foreach ($job['cmds'] as $name => $i) { |
|
219 |
|
if (empty($i['cmd'])) |
|
220 |
|
continue; |
|
221 |
|
|
183 |
222 |
$prefix = '/mnt/status/' |
$prefix = '/mnt/status/' |
184 |
223 |
. escapeshellarg($name); |
. escapeshellarg($name); |
185 |
224 |
|
|
|
... |
... |
function start_worker($job) |
221 |
260 |
break; |
break; |
222 |
261 |
} |
} |
223 |
262 |
|
|
|
263 |
|
// Prepare packages - for now, we must list every package |
|
264 |
|
// on a single line to avoid not available packages |
|
265 |
|
$pkgs = explode(' ', $job['packages']); |
|
266 |
|
if (count($pkgs) > 0) { |
|
267 |
|
$p_i_cmd = ''; |
|
268 |
|
$p_i_cmd .= '> /mnt/packages.log' . "\n"; |
|
269 |
|
foreach ($pkgs as $p) { |
|
270 |
|
$p_i_cmd .= $env['pkg_cmd'] |
|
271 |
|
. ' ' . escapeshellarg($p) |
|
272 |
|
. ' >> /mnt/packages.log 2>&1' . "\n"; |
|
273 |
|
} |
|
274 |
|
} |
|
275 |
|
|
224 |
276 |
// Store commands |
// Store commands |
225 |
277 |
$r = @file_put_contents($job['main'] . '/root/rg.sh', |
$r = @file_put_contents($job['main'] . '/root/rg.sh', |
226 |
278 |
'mkdir /mnt/status' . "\n" |
'mkdir /mnt/status' . "\n" |
227 |
279 |
. 'chown -R build:build /mnt/git /mnt/status' . "\n" |
. 'chown -R build:build /mnt/git /mnt/status' . "\n" |
228 |
280 |
. 'date +%s > /mnt/T_START' . "\n" |
. 'date +%s > /mnt/T_START' . "\n" |
|
281 |
|
. '# Waiting for net...' . "\n" |
|
282 |
|
. 'while [ -z "`ip ro li | grep ^default`" ]; do' . "\n" |
|
283 |
|
. ' sleep 1' . "\n" |
|
284 |
|
. 'done' . "\n" |
|
285 |
|
. 'date +%s > /mnt/T_NET_OK' . "\n\n" |
|
286 |
|
. $p_i_cmd |
|
287 |
|
. 'date +%s > /mnt/T_PKGS_OK' . "\n\n" |
229 |
288 |
. 'su - build -c /mnt/build.sh' . "\n" |
. 'su - build -c /mnt/build.sh' . "\n" |
230 |
|
. 'date +%s > /mnt/T_DONE' . "\n" |
|
|
289 |
|
. 'date +%s > /mnt/T_DONE' . "\n\n" |
231 |
290 |
. 'sync' . "\n" |
. 'sync' . "\n" |
232 |
291 |
. 'shutdown -h now' |
. 'shutdown -h now' |
233 |
292 |
); |
); |
|
... |
... |
function start_worker($job) |
260 |
319 |
. ' --memory 256' |
. ' --memory 256' |
261 |
320 |
. ' --vcpus 1' |
. ' --vcpus 1' |
262 |
321 |
. ' --graphics none' |
. ' --graphics none' |
263 |
|
. ' --network none' |
|
|
322 |
|
. ' --network network=default' |
264 |
323 |
. ' --security type=dynamic' |
. ' --security type=dynamic' |
265 |
|
. ' --os-variant fedora22' |
|
|
324 |
|
. ' --os-variant ' . escapeshellarg($env['os-variant']) |
266 |
325 |
. ' --import' |
. ' --import' |
267 |
326 |
. ' --disk path=' . $img . ',discard=unmap' |
. ' --disk path=' . $img . ',discard=unmap' |
268 |
327 |
. ' --disk path=' . $img2 . ',discard=unmap' |
. ' --disk path=' . $img2 . ',discard=unmap' |
269 |
328 |
. ' --rng /dev/random' |
. ' --rng /dev/random' |
|
329 |
|
. ' --memballoon virtio' |
270 |
330 |
. ' ' . $env['paras']); |
. ' ' . $env['paras']); |
271 |
331 |
if ($r['ok'] !== 1) { |
if ($r['ok'] !== 1) { |
272 |
332 |
$reason = 'cannot define and start virtual machine: ' . $r['errmsg']; |
$reason = 'cannot define and start virtual machine: ' . $r['errmsg']; |
|
... |
... |
function start_worker($job) |
279 |
339 |
if ($do_umount) |
if ($do_umount) |
280 |
340 |
rg_exec('umount ' . $emain . '/root'); |
rg_exec('umount ' . $emain . '/root'); |
281 |
341 |
|
|
|
342 |
|
// Seems that any error above must retrigger the build on other worker |
282 |
343 |
if ($err) |
if ($err) |
283 |
|
@file_put_contents($job['main'] . '/error', $reason); |
|
|
344 |
|
@file_put_contents($job['main'] . '/error.log', $reason); |
284 |
345 |
} |
} |
285 |
346 |
|
|
286 |
347 |
/* |
/* |
287 |
|
* Handle commands |
|
|
348 |
|
* Handle received commands |
288 |
349 |
*/ |
*/ |
289 |
350 |
function xhandle($key, $cmd0) |
function xhandle($key, $cmd0) |
290 |
351 |
{ |
{ |
|
... |
... |
function xhandle($key, $cmd0) |
304 |
365 |
$jid = $job['id']; |
$jid = $job['id']; |
305 |
366 |
|
|
306 |
367 |
if (strcmp($cmd, 'BLD ') == 0) { |
if (strcmp($cmd, 'BLD ') == 0) { |
|
368 |
|
// TODO: should we confirm quickly if the job is accepted, |
|
369 |
|
// even if we could not fork? |
307 |
370 |
if (isset($jobs[$jid])) { |
if (isset($jobs[$jid])) { |
|
371 |
|
// TODO: this should not happen, right? |
308 |
372 |
rg_log('Job ' . $jid . ' already in queue!'); |
rg_log('Job ' . $jid . ' already in queue!'); |
309 |
373 |
return; |
return; |
310 |
374 |
} |
} |
311 |
375 |
|
|
312 |
376 |
$jobs[$jid] = $job; |
$jobs[$jid] = $job; |
313 |
|
$jobs[$jid]['main'] = $conf['state'] . '/j-' . $jid; |
|
|
377 |
|
$jobs[$jid]['main'] = $conf['state'] . '/rocketgit-j-' . $jid; |
314 |
378 |
$jobs[$jid]['state'] = RG_JOB_INIT; |
$jobs[$jid]['state'] = RG_JOB_INIT; |
315 |
379 |
|
|
316 |
380 |
rg_log_ml('build job: ' . print_r($job, TRUE)); |
rg_log_ml('build job: ' . print_r($job, TRUE)); |
|
... |
... |
function xhandle($key, $cmd0) |
327 |
391 |
exit(0); |
exit(0); |
328 |
392 |
} |
} |
329 |
393 |
|
|
330 |
|
rg_log('Started builder with pid ' . $pid); |
|
|
394 |
|
rg_log('Started worker with pid ' . $pid); |
331 |
395 |
$jobs[$jid]['state'] = RG_JOB_HELPER_STARTED; |
$jobs[$jid]['state'] = RG_JOB_HELPER_STARTED; |
332 |
396 |
$pid_to_jid[$pid] = $jid; |
$pid_to_jid[$pid] = $jid; |
333 |
397 |
$err = FALSE; |
$err = FALSE; |
|
... |
... |
function xhandle($key, $cmd0) |
342 |
406 |
return; |
return; |
343 |
407 |
} |
} |
344 |
408 |
rg_conn_enq('master', 'STA ' . rg_conn_prepare($a) . "\n"); |
rg_conn_enq('master', 'STA ' . rg_conn_prepare($a) . "\n"); |
345 |
|
} else if (strcmp($cmd, 'DRE ') == 0) { |
|
|
409 |
|
} else if (strcmp($cmd, 'DRE ') == 0) { // DRE = done received |
|
410 |
|
// So, we can clean up everything related to this job |
|
411 |
|
// TODO: do we clear the state file? |
346 |
412 |
rg_log('DRE command'); |
rg_log('DRE command'); |
347 |
413 |
$job = &$jobs[$jid]; |
$job = &$jobs[$jid]; |
348 |
414 |
unset($pid_to_jid[$job['pid']]); |
unset($pid_to_jid[$job['pid']]); |
|
... |
... |
function xhandle($key, $cmd0) |
355 |
421 |
|
|
356 |
422 |
/* |
/* |
357 |
423 |
* Extracts info from the virtual disk |
* Extracts info from the virtual disk |
|
424 |
|
* TODO: if something fails, we may keep the file mounted! |
358 |
425 |
*/ |
*/ |
359 |
426 |
function rg_job_extract_info(&$job) |
function rg_job_extract_info(&$job) |
360 |
427 |
{ |
{ |
|
... |
... |
function rg_job_extract_info(&$job) |
366 |
433 |
|
|
367 |
434 |
while (1) { |
while (1) { |
368 |
435 |
if (!is_dir($job['main'])) { |
if (!is_dir($job['main'])) { |
369 |
|
$job['error'] = 'Main dir not presend;' |
|
|
436 |
|
$job['error'] = 'Main dir [' . $job['main'] |
|
437 |
|
. '] not presend;' |
370 |
438 |
. ' probably disk space problems'; |
. ' probably disk space problems'; |
371 |
439 |
break; |
break; |
372 |
440 |
} |
} |
373 |
441 |
|
|
374 |
|
$r = @file_get_contents($job['main'] . '/error'); |
|
|
442 |
|
$r = @file_get_contents($job['main'] . '/error.log'); |
375 |
443 |
if ($r !== FALSE) { |
if ($r !== FALSE) { |
376 |
444 |
$job['error'] = $r; |
$job['error'] = $r; |
377 |
445 |
break; |
break; |
|
... |
... |
function rg_job_extract_info(&$job) |
384 |
452 |
break; |
break; |
385 |
453 |
} |
} |
386 |
454 |
|
|
|
455 |
|
$labels = @file($job['main'] . '/root/status/RG_LABELS'); |
|
456 |
|
if ($labels === FALSE) |
|
457 |
|
$labels = array(); |
|
458 |
|
foreach ($labels as $index => $l) |
|
459 |
|
$labels[$index] = trim($l); |
|
460 |
|
// Add worker name as label |
|
461 |
|
$labels[] = 'worker/' . $conf['name'] . '/color=fff'; |
|
462 |
|
|
387 |
463 |
$job['status'] = array( |
$job['status'] = array( |
|
464 |
|
'packages' => @trim(file_get_contents($job['main'] . '/root/packages.log')), |
388 |
465 |
'start' => @trim(file_get_contents($job['main'] . '/root/T_START')), |
'start' => @trim(file_get_contents($job['main'] . '/root/T_START')), |
|
466 |
|
'net_ok' => @trim(file_get_contents($job['main'] . '/root/T_NET_OK')), |
|
467 |
|
'pkgs_ok' => @trim(file_get_contents($job['main'] . '/root/T_PKGS_OK')), |
389 |
468 |
'done' => @trim(file_get_contents($job['main'] . '/root/T_DONE')), |
'done' => @trim(file_get_contents($job['main'] . '/root/T_DONE')), |
390 |
|
'labels' => @file($job['main'] . '/root/status/RG_LABELS') |
|
|
469 |
|
'labels' => $labels |
391 |
470 |
); |
); |
392 |
|
foreach ($job['status']['labels'] as $index => $l) |
|
393 |
|
$job['status']['labels'][$index] = trim($l); |
|
394 |
471 |
|
|
395 |
472 |
$job['status']['cmds'] = array(); |
$job['status']['cmds'] = array(); |
396 |
473 |
foreach ($job['cmds'] as $cmd => $i) { |
foreach ($job['cmds'] as $cmd => $i) { |
|
... |
... |
function rg_job_extract_info(&$job) |
402 |
479 |
'start' => @trim(file_get_contents($sd . '.start')), |
'start' => @trim(file_get_contents($sd . '.start')), |
403 |
480 |
'done' => @trim(file_get_contents($sd . '.done')), |
'done' => @trim(file_get_contents($sd . '.done')), |
404 |
481 |
'log' => @file_get_contents($sd . '.log', FALSE, |
'log' => @file_get_contents($sd . '.log', FALSE, |
405 |
|
NULL, -1, 2048) |
|
|
482 |
|
NULL, -1, 4 * 4096) |
406 |
483 |
); |
); |
407 |
484 |
} |
} |
408 |
485 |
unset($job['cmds']); |
unset($job['cmds']); |
|
... |
... |
function rg_job_extract_info(&$job) |
428 |
505 |
|
|
429 |
506 |
reload_config(); |
reload_config(); |
430 |
507 |
|
|
|
508 |
|
|
431 |
509 |
$socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP); |
$socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP); |
432 |
510 |
if ($socket === FALSE) { |
if ($socket === FALSE) { |
433 |
511 |
rg_log('Cannot create socket!'); |
rg_log('Cannot create socket!'); |
|
... |
... |
while(1) { |
470 |
548 |
break; |
break; |
471 |
549 |
|
|
472 |
550 |
$jid = $pid_to_jid[$pid]; |
$jid = $pid_to_jid[$pid]; |
473 |
|
rg_log('Pid ' . $pid . ' exited (job ' . $jid . ')!'); |
|
|
551 |
|
rg_log('Pid ' . $pid . ' exited (job ' . $jid . ')' |
|
552 |
|
. ' with status ' . $status . '!'); |
474 |
553 |
unset($pid_to_jid[$pid]); |
unset($pid_to_jid[$pid]); |
475 |
554 |
$jobs[$jid]['state'] = RG_JOB_STARTED; |
$jobs[$jid]['state'] = RG_JOB_STARTED; |
476 |
555 |
} |
} |
|
... |
... |
while(1) { |
492 |
571 |
|
|
493 |
572 |
$name = 'rg-worker-' . $jid; |
$name = 'rg-worker-' . $jid; |
494 |
573 |
$k = array_search($name, $vms); |
$k = array_search($name, $vms); |
495 |
|
if ($k === FALSE) { |
|
496 |
|
rg_log('VM finished'); |
|
497 |
|
$job['state'] = RG_JOB_DONE; |
|
|
574 |
|
if ($k !== FALSE) { |
|
575 |
|
//rg_log('VM in progress'); |
|
576 |
|
// TODO: if too much time, abort (kill |
|
577 |
|
// worker and destroy virtual machine) |
|
578 |
|
//TODO: $job['error'] = 'too much time'; |
|
579 |
|
continue; |
|
580 |
|
} |
498 |
581 |
|
|
499 |
|
rg_job_extract_info($job); |
|
|
582 |
|
rg_log('VM ' . $jid . ' finished'); |
500 |
583 |
|
|
501 |
|
// TODO: store in fs to be able to still inform the |
|
502 |
|
// master if we are crashing. |
|
|
584 |
|
rg_job_extract_info($job); |
|
585 |
|
if (isset($job['error'])) |
|
586 |
|
$job['state'] = RG_JOB_ERROR; |
|
587 |
|
else |
503 |
588 |
$job['state'] = RG_JOB_DONE; |
$job['state'] = RG_JOB_DONE; |
504 |
|
@file_put_contents($job['main'] . '/job.ser', |
|
505 |
|
serialize($job)); |
|
506 |
589 |
|
|
507 |
|
rg_conn_enq('master', 'DON ' |
|
508 |
|
. rg_conn_prepare($job) . "\n"); |
|
509 |
|
} else { |
|
510 |
|
//rg_log('VM in progress'); |
|
511 |
|
// TODO: if too much time, abort |
|
|
590 |
|
// TODO: store in fs to be able to still inform the |
|
591 |
|
// master if we are crashing. |
|
592 |
|
@file_put_contents($job['main'] . '/job.ser', serialize($job)); |
|
593 |
|
|
|
594 |
|
$xjob = $job; |
|
595 |
|
unset($xjob['debug']); |
|
596 |
|
unset($xjob['packages']); |
|
597 |
|
unset($xjob['main']); |
|
598 |
|
rg_conn_enq('master', 'DON ' . rg_conn_prepare($xjob) . "\n"); |
|
599 |
|
|
|
600 |
|
// TODO: do we destroy the pool in case of crash? |
|
601 |
|
$cmd = 'virsh pool-destroy rocketgit-j-' . $jid; |
|
602 |
|
$r = rg_exec($cmd); |
|
603 |
|
if ($r['ok'] != 1) { |
|
604 |
|
$job['error'] = 'Could not destroy pool: ' . $r['data']; |
|
605 |
|
rg_log('Error: ' . $job['error']); |
|
606 |
|
//break; TODO: do we need to do this?! |
|
607 |
|
} |
|
608 |
|
|
|
609 |
|
// TODO: do we clean the pool in case of crash? |
|
610 |
|
$cmd = 'virsh pool-undefine rocketgit-j-' . $jid; |
|
611 |
|
$r = rg_exec($cmd); |
|
612 |
|
if ($r['ok'] != 1) { |
|
613 |
|
$job['error'] = 'Could not undefine pool: ' . $r['data']; |
|
614 |
|
rg_log('Error: ' . $job['error']); |
|
615 |
|
//break; TODO: do we need to do this?! |
|
616 |
|
} |
|
617 |
|
|
|
618 |
|
// TODO: do we clean the machine in case of crash? |
|
619 |
|
$cmd = 'virsh undefine rg-worker-' . escapeshellarg($jid); |
|
620 |
|
$r = rg_exec($cmd); |
|
621 |
|
if ($r['ok'] != 1) { |
|
622 |
|
$job['error'] = 'Could not undefine machine: ' . $r['data']; |
|
623 |
|
rg_log('Error: ' . $job['error']); |
|
624 |
|
//break; TODO |
512 |
625 |
} |
} |
513 |
626 |
} |
} |
514 |
627 |
} |
} |
File tests/http_forgot.php added (mode: 100644) (index 0000000..c0779b4) |
|
1 |
|
<?php |
|
2 |
|
// |
|
3 |
|
// Will test the forgot password feature |
|
4 |
|
// |
|
5 |
|
|
|
6 |
|
error_reporting(E_ALL | E_STRICT); |
|
7 |
|
ini_set("track_errors", "On"); |
|
8 |
|
|
|
9 |
|
$INC = dirname(__FILE__) . "/../inc"; |
|
10 |
|
require_once(dirname(__FILE__) . "/config.php"); |
|
11 |
|
require_once($INC . "/init.inc.php"); |
|
12 |
|
require_once($INC . "/util.inc.php"); |
|
13 |
|
require_once("helpers.inc.php"); |
|
14 |
|
require_once("http.inc.php"); |
|
15 |
|
|
|
16 |
|
rg_log_set_file("http_forgot.log"); |
|
17 |
|
|
|
18 |
|
$rg_sql = "host=localhost user=rocketgit dbname=rocketgit connect_timeout=10"; |
|
19 |
|
$rg_no_db = TRUE; |
|
20 |
|
require_once("common.php"); |
|
21 |
|
|
|
22 |
|
$_testns = 'http_forgot'; |
|
23 |
|
$rg_cache_enable = TRUE; |
|
24 |
|
$rg_cache_debug = TRUE; |
|
25 |
|
|
|
26 |
|
$rg_user_max_len = 60; |
|
27 |
|
|
|
28 |
|
rg_test_create_user($db, $rg_ui); |
|
29 |
|
|
|
30 |
|
|
|
31 |
|
rg_log(''); |
|
32 |
|
rg_log_enter('Loading forgot pass form...'); |
|
33 |
|
$data = array(); |
|
34 |
|
$r = do_req($test_url . '/op/forgot_send', $data, $headers); |
|
35 |
|
if ($r === FALSE) { |
|
36 |
|
rg_log("Cannot load forgot pass page!"); |
|
37 |
|
exit(1); |
|
38 |
|
} |
|
39 |
|
rg_log('Posting the forgot pass form...'); |
|
40 |
|
$data = array( |
|
41 |
|
'email' => $rg_ui['email'], |
|
42 |
|
'doit' => 1 |
|
43 |
|
); |
|
44 |
|
$r = do_req($test_url . '/op/forgot_send', $data, $headers); |
|
45 |
|
if (!strstr($r['body'], 'your inbox and follow the instructions')) { |
|
46 |
|
rg_log_ml('r: ' . print_r($r, TRUE)); |
|
47 |
|
rg_log("Cannot post forgot pass form!"); |
|
48 |
|
exit(1); |
|
49 |
|
} |
|
50 |
|
$sql = 'SELECT token FROM forgot_pass WHERE uid = ' . $rg_ui['uid']; |
|
51 |
|
$res = rg_sql_query($db, $sql); |
|
52 |
|
$rows = rg_sql_num_rows($res); |
|
53 |
|
if ($rows > 0) |
|
54 |
|
$row = rg_sql_fetch_array($res); |
|
55 |
|
rg_sql_free_result($res); |
|
56 |
|
if ($rows != 1) { |
|
57 |
|
rg_log("Seems the token is not in the database or there are multiple ones!"); |
|
58 |
|
exit(1); |
|
59 |
|
} |
|
60 |
|
$db_token = $row['token']; |
|
61 |
|
rg_log_exit(); |
|
62 |
|
|
|
63 |
|
|
|
64 |
|
rg_log(''); |
|
65 |
|
rg_log_enter('Loading token from mail...'); |
|
66 |
|
$k = 'DEBUG::nouid::mail'; |
|
67 |
|
$c = rg_cache_get($k); |
|
68 |
|
if (($c === FALSE) || !isset($c['body'])) { |
|
69 |
|
rg_log_ml(print_r($c, TRUE)); |
|
70 |
|
rg_log('No c or no body in c var!'); |
|
71 |
|
exit(1); |
|
72 |
|
} |
|
73 |
|
$s = strstr($c['body'], '/op/forgot_link/'); |
|
74 |
|
if ($s === FALSE) { |
|
75 |
|
rg_log_ml(print_r($c['body'], TRUE)); |
|
76 |
|
rg_log('No link in body!'); |
|
77 |
|
exit(1); |
|
78 |
|
} |
|
79 |
|
|
|
80 |
|
$s = substr($s, 16, 20); |
|
81 |
|
if (strcmp($db_token, $s) != 0) { |
|
82 |
|
rg_log('db token != mail token! [' . $db_token . '] != [' . $s . ']'); |
|
83 |
|
exit(1); |
|
84 |
|
} |
|
85 |
|
|
|
86 |
|
// we add junk because I've seen cases when some junk was appended |
|
87 |
|
$s .= 'junk'; |
|
88 |
|
|
|
89 |
|
$data = array(); |
|
90 |
|
$r = do_req($test_url . '/op/forgot_link/' . $s, $data, $headers); |
|
91 |
|
if ($r === FALSE) { |
|
92 |
|
rg_log("Cannot load forgot_link page!"); |
|
93 |
|
exit(1); |
|
94 |
|
} |
|
95 |
|
|
|
96 |
|
rg_log('Posting the forgot link form...'); |
|
97 |
|
$pass = rg_id(10); |
|
98 |
|
$data = array( |
|
99 |
|
'forgot_token' => $s, |
|
100 |
|
'pass1' => $pass, |
|
101 |
|
'pass2' => $pass, |
|
102 |
|
'lock_ip' => 1, |
|
103 |
|
'doit' => 1 |
|
104 |
|
); |
|
105 |
|
$r = do_req($test_url . '/op/forgot_link', $data, $headers); |
|
106 |
|
if (!strstr($r['body'], 'Home page of user')) { |
|
107 |
|
rg_log_ml('r: ' . print_r($r, TRUE)); |
|
108 |
|
rg_log('Cannot post forgot link form!'); |
|
109 |
|
exit(1); |
|
110 |
|
} |
|
111 |
|
$sql = 'SELECT salt, pass FROM users WHERE uid = ' . $rg_ui['uid']; |
|
112 |
|
$res = rg_sql_query($db, $sql); |
|
113 |
|
$rows = rg_sql_num_rows($res); |
|
114 |
|
if ($rows > 0) |
|
115 |
|
$row = rg_sql_fetch_array($res); |
|
116 |
|
rg_sql_free_result($res); |
|
117 |
|
if ($rows != 1) { |
|
118 |
|
rg_log('Seems the password was not changed!'); |
|
119 |
|
exit(1); |
|
120 |
|
} |
|
121 |
|
$good_pass = rg_user_pass($row['salt'], $pass); |
|
122 |
|
if (strcmp($good_pass, $row['pass']) != 0) { |
|
123 |
|
rg_log_ml('row: ' . print_r($row, TRUE)); |
|
124 |
|
rg_log('passwords are not the same pass=[' . $pass . ']!'); |
|
125 |
|
exit(1); |
|
126 |
|
} |
|
127 |
|
rg_log_exit(); |
|
128 |
|
|
|
129 |
|
// TODO: make sure that the entry from forgot_pass is gone |
|
130 |
|
|
|
131 |
|
|
|
132 |
|
rg_prof_log(); |
|
133 |
|
rg_log("OK!"); |
|
134 |
|
?> |