File Makefile.in changed (mode: 100644) (index 7528f39..00feb72) | |||
... | ... | install: all | |
54 | 54 | @mkdir -pv $(I_VAR_LIB)/$(PRJ)/qstats | @mkdir -pv $(I_VAR_LIB)/$(PRJ)/qstats |
55 | 55 | @mkdir -pv $(I_VAR_LIB)/$(PRJ)/sockets | @mkdir -pv $(I_VAR_LIB)/$(PRJ)/sockets |
56 | 56 | @echo "Fixing rights..." | @echo "Fixing rights..." |
57 | @-chown -R rocketgit:rocketgit $(I_VAR_LIB)/$(PRJ) | ||
58 | 57 | @-find $(I_VAR_LIB)/$(PRJ) -type d -exec chmod 0755 {} \; | @-find $(I_VAR_LIB)/$(PRJ) -type d -exec chmod 0755 {} \; |
59 | 58 | @-find $(I_VAR_LIB)/$(PRJ) -type f -exec chmod 0600 {} \; | @-find $(I_VAR_LIB)/$(PRJ) -type f -exec chmod 0600 {} \; |
59 | @mkdir -pv --mode=0700 $(I_VAR_LIB)/$(PRJ)/tmp | ||
60 | @-chown -R rocketgit:rocketgit $(I_VAR_LIB)/$(PRJ) | ||
60 | 61 | @ | @ |
61 | 62 | @echo "Installing SELinux stuff..." | @echo "Installing SELinux stuff..." |
62 | 63 | @mkdir -pv --mode=0755 $(I_USR_SHARE)/selinux/targeted | @mkdir -pv --mode=0755 $(I_USR_SHARE)/selinux/targeted |
File TODO changed (mode: 100644) (index 279f1f2..931fa4b) | |||
1 | 1 | == Where I stopped last time == | == Where I stopped last time == |
2 | [ ] Seems that somehow I managed to arrive at | ||
3 | 'http://r1i:9000/op/repo/create/create'! Not good! | ||
4 | I think by creating repositories. | ||
5 | [ ] wh test is not working. | ||
6 | [ ] rg_debug is sent twice for wh.php unit testing. | ||
2 | 7 | [ ] | [ ] |
3 | 8 | ||
4 | 9 | == BEFORE NEXT RELEASE == | == BEFORE NEXT RELEASE == |
10 | [ ] For events, very probably I have to disable the cache. | ||
11 | Scenario: adding a webhook1, add a repo1, add a webhook2, | ||
12 | add a repo2. webhook2 will not trigger on repo2 creating because | ||
13 | only webhook1 is in cache! Very bad! | ||
14 | [ ] Add notifications for hook add? | ||
15 | [ ] Send an e-mail if webhook fails? Flag when configuring webhook? | ||
16 | [ ] unit test: generate a CA, client cert, server cert, and use openssl | ||
17 | s_server to test? Or maybe curl in mode server? Or php in listen | ||
18 | mode? | ||
19 | [ ] Clean 'tmp' folder. | ||
20 | [ ] Document webhooks, mostly 'PHP serialize' type. But also other things. | ||
21 | [ ] Do not forget that cache.php has its own memory cache! | ||
22 | I must not update the database and expect it to see good values. | ||
23 | [ ] wh: Add: tag push, issue, merge request | ||
24 | [ ] wh: add also XML, JSON | ||
25 | [ ] wh: add other conection types: websocket, socket (low priority) | ||
26 | [ ] How "Delete selected" button should be aligned? | ||
27 | [ ] Use rg_var_a2s for checkboxes. | ||
28 | [ ] http://www.w3.org/TR/clipboard-apis/ | ||
29 | 1. maybe support javascript copy API | ||
30 | 2. The boxes with a border on the left would be nice for hints. | ||
31 | [ ] Evaluate https://www.gnu.org/software/repo-criteria.html | ||
32 | Also in Compare.txt | ||
5 | 33 | [ ] When I am in "My repositories" and I am doing a search, other users' | [ ] When I am in "My repositories" and I am doing a search, other users' |
6 | 34 | repositories are shown. | repositories are shown. |
7 | 35 | [ ] In user/home-page.php, in hints section, add a message when the user is | [ ] In user/home-page.php, in hints section, add a message when the user is |
8 | 36 | low on scratch codes. Not hint. | low on scratch codes. Not hint. |
9 | [ ] If 'rg_debug'? is defined, do not send mails. | ||
10 | 37 | [ ] test with "short" (0 prepended) codes in unit testing. | [ ] test with "short" (0 prepended) codes in unit testing. |
11 | 38 | For scs, done, test for devices? This is a little bit harder. | For scs, done, test for devices? This is a little bit harder. |
12 | 39 | [ ] totp:ssh: do we need a command to remove a set of scratch codes? | [ ] totp:ssh: do we need a command to remove a set of scratch codes? |
13 | 40 | Something like 'remove-sc [<itime>]'. If <itime> is missing, list the | Something like 'remove-sc [<itime>]'. If <itime> is missing, list the |
14 | 41 | sets. The IP must be authorized? | sets. The IP must be authorized? |
15 | [ ] http hook: use curl's CURLOPT_SSLCERT to authenticate to the client server. | ||
16 | 42 | [ ] In report, just show the newly added repos, not the totals. Totals in body. | [ ] In report, just show the newly added repos, not the totals. Totals in body. |
17 | 43 | [ ] Apply to become a member of Software Freedom Conservancy? | [ ] Apply to become a member of Software Freedom Conservancy? |
18 | [ ] Why do we index 'users' by 'username'?! Seems wrong! | ||
44 | [ ] Why do we have an index by 'users.username'?! Seems wrong! | ||
19 | 45 | [ ] totp: add sc for ssh! | [ ] totp: add sc for ssh! |
20 | 46 | Should I validate one after asking the user to store them safe? | Should I validate one after asking the user to store them safe? |
21 | 47 | Think about power down before scratch codes hit the printer. | Think about power down before scratch codes hit the printer. |
22 | 48 | [ ] Get rid of {{}} stuff. | [ ] Get rid of {{}} stuff. |
23 | [ ] Some other menus were added, we must load all this pages. | ||
49 | [ ] Some other menus were added, we must load all this pages in unit tests. | ||
24 | 50 | At least totp/{list,enroll,sc}. | At least totp/{list,enroll,sc}. |
25 | 51 | [ ] I inconsistently use /op/repo/create and /user/catab/settings! | [ ] I inconsistently use /op/repo/create and /user/catab/settings! |
26 | 52 | Why not /user/catab/repo/create? | Why not /user/catab/repo/create? |
63 | 89 | [ ] Report number of lines of code (and how much a project worth) and | [ ] Report number of lines of code (and how much a project worth) and |
64 | 90 | number of other type of documents. | number of other type of documents. |
65 | 91 | [ ] Add some flags for users: "Coming from GitHub", to be able to give | [ ] Add some flags for users: "Coming from GitHub", to be able to give |
66 | tailored hints. | ||
92 | specific hints. | ||
67 | 93 | [ ] totp: warn user that if a token is not validated for 1 month will be deleted? | [ ] totp: warn user that if a token is not validated for 1 month will be deleted? |
68 | 94 | [ ] totp: allow prefix for IP addresses. | [ ] totp: allow prefix for IP addresses. |
69 | 95 | [ ] totp: think about authorizing a push, not the ip (ip may be dynamic). | [ ] totp: think about authorizing a push, not the ip (ip may be dynamic). |
83 | 109 | the browser. | the browser. |
84 | 110 | [ ] Document how to deny non ascii filenames using repo_path. | [ ] Document how to deny non ascii filenames using repo_path. |
85 | 111 | [ ] When a right denies access, also output the description of that right. | [ ] When a right denies access, also output the description of that right. |
112 | Maybe add a new box for the text to be shown to the user? | ||
86 | 113 | [ ] Tell clear that rg can be used also for books, articles, documentation etc. | [ ] Tell clear that rg can be used also for books, articles, documentation etc. |
87 | 114 | [ ] Include uid in namespace path to avoid clashes with other users? | [ ] Include uid in namespace path to avoid clashes with other users? |
88 | 115 | [ ] ssh: show the fingerprint of the used key? | [ ] ssh: show the fingerprint of the used key? |
103 | 130 | 'password/token', right? Also, for https, I cannot provide the token, | 'password/token', right? Also, for https, I cannot provide the token, |
104 | 131 | only user/pass. Maybe appending token to the pass. | only user/pass. Maybe appending token to the pass. |
105 | 132 | [ ] Can I remove the redirect after login (that means another request)? | [ ] Can I remove the redirect after login (that means another request)? |
133 | Adding a user is pretty light, we should allow the redirect. | ||
106 | 134 | [ ] In the report, send also stats about the events, especially the failed ones. | [ ] In the report, send also stats about the events, especially the failed ones. |
107 | 135 | [ ] Document backup procedure. | [ ] Document backup procedure. |
108 | 136 | [ ] "Forgot password": rate limit it! | [ ] "Forgot password": rate limit it! |
129 | 157 | Instruct user to remove the token if the phone is lost. But, remind | Instruct user to remove the token if the phone is lost. But, remind |
130 | 158 | user that the account may not be compromised without pass. | user that the account may not be compromised without pass. |
131 | 159 | [ ] totp: think about loosing the phone. | [ ] totp: think about loosing the phone. |
132 | [ ] totp: warn about time desync; maybe ask the user to press the 'sync' in | ||
133 | the mobile app. | ||
134 | 160 | [ ] totp: what if I encrypt key with the password and decrypt only at login? | [ ] totp: what if I encrypt key with the password and decrypt only at login? |
135 | 161 | (If somebody steals the database, will not have the keys). | (If somebody steals the database, will not have the keys). |
136 | 162 | Cannot do. We need it also at push by ssh. | Cannot do. We need it also at push by ssh. |
137 | 163 | [ ] totp: hints for ssh | [ ] totp: hints for ssh |
138 | 164 | [ ] totp: Implement 2 factor auth | [ ] totp: Implement 2 factor auth |
139 | (check https://korg.wiki.kernel.org/userdoc/gitolite_2fa) | ||
165 | (check https://korg.wiki.kernel.org/userdoc/gitolite_2fa). Done! | ||
140 | 166 | [ ] Use PAM (man pam_start) to be able to use any type of auth, including LDAP. | [ ] Use PAM (man pam_start) to be able to use any type of auth, including LDAP. |
141 | 167 | [ ] http://www.cybertec.at/shrinking-the-storage-footprint-of-data/ | [ ] http://www.cybertec.at/shrinking-the-storage-footprint-of-data/ |
142 | 168 | [ ] Allow repo admins/owners to delete notes/bugs/etc. | [ ] Allow repo admins/owners to delete notes/bugs/etc. |
152 | 178 | [ ] I should show some plan 'islands' when you create the account | [ ] I should show some plan 'islands' when you create the account |
153 | 179 | so the user will know the disk space and bandwidth. | so the user will know the disk space and bandwidth. |
154 | 180 | [ ] In a table, if nothing can be deleted, do not show the delete button. | [ ] In a table, if nothing can be deleted, do not show the delete button. |
155 | [ ] web hooks: start with a http post to a user server. | ||
156 | warn the user if is not working? | ||
157 | 181 | [ ] When giving some users rights to your repo, do not spam them with | [ ] When giving some users rights to your repo, do not spam them with |
158 | 182 | messages. The user must agree to be spammed. Best, no notification | messages. The user must agree to be spammed. Best, no notification |
159 | 183 | is ever issued. User may go to project to activate them if s/he wants. | is ever issued. User may go to project to activate them if s/he wants. |
196 | 220 | [ ] Add sha1sum of the VM images | [ ] Add sha1sum of the VM images |
197 | 221 | [ ] ssh: Show user the entry that must be added for known_hosts | [ ] ssh: Show user the entry that must be added for known_hosts |
198 | 222 | [ ] LDAP: http://mageconfig.blogspot.ro/2014/06/configure-gitgerrit-with-open-ldap-for.html | [ ] LDAP: http://mageconfig.blogspot.ro/2014/06/configure-gitgerrit-with-open-ldap-for.html |
199 | [ ] Leave alone the ssh key comment! More exactly, do not convert unk chars. | ||
200 | 223 | [ ] Pass only uid to events, we already have it in cache! | [ ] Pass only uid to events, we already have it in cache! |
201 | 224 | [ ] 'confirmed' should be built in the event handlers not in callers. | [ ] 'confirmed' should be built in the event handlers not in callers. |
202 | 225 | It is already checked in rg_mail_template! | It is already checked in rg_mail_template! |
225 | 248 | [ ] Allow creating tags/branches on web interface. | [ ] Allow creating tags/branches on web interface. |
226 | 249 | [ ] Use a separate template for main rocketgit.com site. The other users | [ ] Use a separate template for main rocketgit.com site. The other users |
227 | 250 | should not see the same pages. | should not see the same pages. |
228 | [ ] git-filter-branch is very powerful: offer it to the clients! | ||
251 | [ ] git-filter-branch is very powerful: offer it to the users! | ||
229 | 252 | [ ] word-break: break-all; pentru tabelele cu cod. asta permite wrap-ul | [ ] word-break: break-all; pentru tabelele cu cod. asta permite wrap-ul |
230 | 253 | oriunde - still needed?! | oriunde - still needed?! |
231 | 254 | [ ] Backup for rg2! | [ ] Backup for rg2! |
300 | 323 | [ ] Before custom hooks, allow enforcing a custom regex for a commit. | [ ] Before custom hooks, allow enforcing a custom regex for a commit. |
301 | 324 | [ ] rg_repo_delete trebuie sa stearga si rights si bugs si notes si bug files | [ ] rg_repo_delete trebuie sa stearga si rights si bugs si notes si bug files |
302 | 325 | si watch-uri. | si watch-uri. |
303 | [ ] For unit testing, we need to pass a debug para in http requests and the | ||
304 | mails to be saved in a folder, so we can parse them and verify them. | ||
305 | 326 | [ ] Expose "git reflog". | [ ] Expose "git reflog". |
306 | 327 | [ ] Should I allow state select when adding a bug? Better to consider it open? | [ ] Should I allow state select when adding a bug? Better to consider it open? |
307 | 328 | [ ] Add regex for label filtering, maybe for other fields? | [ ] Add regex for label filtering, maybe for other fields? |
308 | 329 | [ ] Add regex for search? | [ ] Add regex for search? |
309 | 330 | [ ] When showing diff, for the list of files, make links to chunks inside page. | [ ] When showing diff, for the list of files, make links to chunks inside page. |
331 | Already done? | ||
310 | 332 | [ ] php-opcache in docs? | [ ] php-opcache in docs? |
311 | 333 | [ ] Drop OUTPUT to prevent some attacks? Document in README? | [ ] Drop OUTPUT to prevent some attacks? Document in README? |
312 | 334 | [ ] Seems I cache not set values: first_install is still "?"! | [ ] Seems I cache not set values: first_install is still "?"! |
... | ... | mails to be saved in a folder, so we can parse them and verify them. | |
325 | 347 | [ ] HTTP_X_FORWARDED_FOR variable as this data is effectively user input and | [ ] HTTP_X_FORWARDED_FOR variable as this data is effectively user input and |
326 | 348 | therefore susceptible to spoofing. | therefore susceptible to spoofing. |
327 | 349 | [ ] Try to remove non critical queries from main page loading. Just schedule | [ ] Try to remove non critical queries from main page loading. Just schedule |
328 | the operations for later. | ||
350 | the operations for later (register_shutdown_function?). | ||
329 | 351 | [ ] We should not delete the tokens. They will be cleaned hourly? | [ ] We should not delete the tokens. They will be cleaned hourly? |
330 | 352 | [ ] Remove all texts from code and move them to templates. | [ ] Remove all texts from code and move them to templates. |
331 | 353 | [ ] Storing password in database must apply multiple hashes. Check owasp. | [ ] Storing password in database must apply multiple hashes. Check owasp. |
... | ... | But, we have a problem with the expiration time! | |
473 | 495 | [ ] repos.disk_quota_mb must be dropped and do a look-up in plan. | [ ] repos.disk_quota_mb must be dropped and do a look-up in plan. |
474 | 496 | [ ] Integrate max_public/private_repos into HL. | [ ] Integrate max_public/private_repos into HL. |
475 | 497 | [ ] Allow specifying base language for a project. | [ ] Allow specifying base language for a project. |
498 | [ ] Add country when creating a user? | ||
476 | 499 | [ ] When changing db structure, invalidate all caches. | [ ] When changing db structure, invalidate all caches. |
477 | 500 | [ ] When we will switch to C, check UTF-8 validation. | [ ] When we will switch to C, check UTF-8 validation. |
478 | 501 | [ ] Check http://blog.wikichoon.com/2014/04/github-doesnt-support-pull-request.html | [ ] Check http://blog.wikichoon.com/2014/04/github-doesnt-support-pull-request.html |
... | ... | But, we have a problem with the expiration time! | |
528 | 551 | private dir. | private dir. |
529 | 552 | - "USER" is the user that is logged in. Maybe find a better string | - "USER" is the user that is logged in. Maybe find a better string |
530 | 553 | because we may have a user "USER". | because we may have a user "USER". |
531 | - Also limit by IP and by time. | ||
554 | - Also limit by time. | ||
532 | 555 | - We have a problem: some rights do not map correctly to the plan above. | - We have a problem: some rights do not map correctly to the plan above. |
533 | 556 | For example, A(admin) etc. Seems we need to have >2 categories. | For example, A(admin) etc. Seems we need to have >2 categories. |
534 | 557 | - Also, we will have problems classifying a project as public or private. | - Also, we will have problems classifying a project as public or private. |
... | ... | But, we have a problem with the expiration time! | |
598 | 621 | [ ] Check http://nvie.com/posts/a-successful-git-branching-model/ | [ ] Check http://nvie.com/posts/a-successful-git-branching-model/ |
599 | 622 | [ ] After resetting password, go to the login form, with user pre-filed so | [ ] After resetting password, go to the login form, with user pre-filed so |
600 | 623 | the user can cache the password. | the user can cache the password. |
601 | [ ] Add number of bugs multiplied with a value to total disk space. | ||
624 | [ ] Add number of bugs multiplied with a factor to total disk space. | ||
625 | Same for any row in the database. Should we do it? | ||
602 | 626 | [ ] How should I verify repo rights? | [ ] How should I verify repo rights? |
603 | 627 | if (admin) | if (admin) |
604 | 628 | if (owner) | if (owner) |
File inc/bug.inc.php changed (mode: 100644) (index b050efe..f77b6e2) | |||
... | ... | function rg_bug_event_add_one($db, $event) | |
50 | 50 | ||
51 | 51 | $ret = FALSE; | $ret = FALSE; |
52 | 52 | while (1) { | while (1) { |
53 | if ($event['debug'] == 1) { | ||
54 | rg_cache_set('DEBUG::bug_event_add_one', $event, 0); | ||
55 | $ret = array(); | ||
56 | break; | ||
57 | } | ||
58 | |||
53 | 59 | // lookup user email | // lookup user email |
54 | 60 | $ui = rg_user_info($db, $event['ui']['uid'], '', ''); | $ui = rg_user_info($db, $event['ui']['uid'], '', ''); |
55 | 61 | if ($ui['exists'] != 1) { | if ($ui['exists'] != 1) { |
... | ... | function rg_bug_event_note_add_one($db, $event) | |
127 | 133 | ||
128 | 134 | $ret = FALSE; | $ret = FALSE; |
129 | 135 | while (1) { | while (1) { |
136 | if ($event['debug'] == 1) { | ||
137 | rg_cache_set('DEBUG::bug_event_note_add_one', $event, 0); | ||
138 | $ret = array(); | ||
139 | break; | ||
140 | } | ||
141 | |||
130 | 142 | // lookup user email | // lookup user email |
131 | 143 | $ui = rg_user_info($db, $event['ui']['uid'], '', ''); | $ui = rg_user_info($db, $event['ui']['uid'], '', ''); |
132 | 144 | if ($ui['exists'] != 1) { | if ($ui['exists'] != 1) { |
File inc/events.inc.php changed (mode: 100644) (index 9f67caa..bb4b73f) | |||
... | ... | function rg_event_signal_daemon($ev_id, $timeout) | |
52 | 52 | { | { |
53 | 53 | global $rg_event_socket; | global $rg_event_socket; |
54 | 54 | ||
55 | if (empty($rg_event_socket)) | ||
55 | if (empty($rg_event_socket)) { | ||
56 | rg_log('DEBUG: rg_event_socket is not defined!'); | ||
56 | 57 | return TRUE; | return TRUE; |
58 | } | ||
57 | 59 | ||
58 | 60 | if ($timeout === NULL) | if ($timeout === NULL) |
59 | 61 | $s_timeout = "forever"; | $s_timeout = "forever"; |
... | ... | function rg_event_signal_daemon($ev_id, $timeout) | |
86 | 88 | */ | */ |
87 | 89 | function rg_event_add($db, $event) | function rg_event_add($db, $event) |
88 | 90 | { | { |
91 | global $rg_debug; | ||
92 | |||
89 | 93 | rg_prof_start("event_add"); | rg_prof_start("event_add"); |
90 | 94 | rg_log_enter("event_add: event=" . rg_array2string($event)); | rg_log_enter("event_add: event=" . rg_array2string($event)); |
91 | 95 | ||
92 | 96 | if (!isset($event['IP'])) | if (!isset($event['IP'])) |
93 | 97 | $event['IP'] = rg_var_str('REMOTE_ADDR'); | $event['IP'] = rg_var_str('REMOTE_ADDR'); |
94 | 98 | ||
99 | if (!isset($event['debug'])) | ||
100 | $event['debug'] = 0; | ||
101 | if ($event['debug'] == 0) | ||
102 | $event['debug'] = rg_var_uint('rg_debug'); | ||
103 | if ($rg_debug) | ||
104 | $event['debug'] = 1; | ||
105 | |||
95 | 106 | $ret = FALSE; | $ret = FALSE; |
96 | 107 | while (1) { | while (1) { |
97 | 108 | $now = time(); | $now = time(); |
... | ... | function rg_event_process($db, $event) | |
146 | 157 | break; | break; |
147 | 158 | } | } |
148 | 159 | ||
160 | if (!is_array($evs)) | ||
161 | rg_internal_error("evs is not array!"); | ||
162 | |||
149 | 163 | if (empty($evs)) { | if (empty($evs)) { |
150 | 164 | $ret = TRUE; | $ret = TRUE; |
151 | 165 | break; | break; |
152 | 166 | } | } |
153 | 167 | ||
168 | // TODO: here we must do a transaction? | ||
169 | |||
154 | 170 | $r = TRUE; | $r = TRUE; |
155 | if (!is_array($evs)) | ||
156 | rg_internal_error("evs is not array!"); | ||
157 | 171 | foreach ($evs as $index => $ev) { | foreach ($evs as $index => $ev) { |
158 | 172 | $r = rg_event_add($db, $ev); | $r = rg_event_add($db, $ev); |
159 | 173 | if ($r !== TRUE) | if ($r !== TRUE) |
... | ... | function rg_event_process($db, $event) | |
162 | 176 | if ($r !== TRUE) | if ($r !== TRUE) |
163 | 177 | break; | break; |
164 | 178 | ||
165 | rg_event_signal_daemon("", 0); | ||
166 | |||
167 | 179 | $ret = TRUE; | $ret = TRUE; |
168 | 180 | break; | break; |
169 | 181 | } | } |
... | ... | function rg_event_process_queue($db, &$notify_list) | |
238 | 250 | ||
239 | 251 | // We limit to be able to deal with high prio tasks | // We limit to be able to deal with high prio tasks |
240 | 252 | $sql = "SELECT * FROM events" | $sql = "SELECT * FROM events" |
241 | . " WHERE fail = 0 AND next_try < $now" | ||
253 | . " WHERE fail = 0" | ||
254 | . " AND next_try < $now" | ||
242 | 255 | . " ORDER BY prio, id" | . " ORDER BY prio, id" |
243 | 256 | . " FOR UPDATE" | . " FOR UPDATE" |
244 | 257 | . " LIMIT 100"; | . " LIMIT 100"; |
... | ... | function rg_event_process_queue($db, &$notify_list) | |
253 | 266 | while (($row = rg_sql_fetch_array($res))) { | while (($row = rg_sql_fetch_array($res))) { |
254 | 267 | $params = array('id' => $row['id']); | $params = array('id' => $row['id']); |
255 | 268 | ||
269 | $sql = "UPDATE events SET fail = 1 WHERE id = @@id@@"; | ||
256 | 270 | while (1) { | while (1) { |
257 | 271 | $ev = unserialize($row['data']); | $ev = unserialize($row['data']); |
258 | 272 | if ($ev === FALSE) { | if ($ev === FALSE) { |
259 | 273 | rg_internal_error("Cannot unserialize data"); | rg_internal_error("Cannot unserialize data"); |
260 | $sql = "UPDATE events SET fail = 1 WHERE id = @@id@@"; | ||
261 | 274 | break; | break; |
262 | 275 | } | } |
263 | 276 | ||
... | ... | function rg_event_process_queue($db, &$notify_list) | |
266 | 279 | ||
267 | 280 | $r = rg_event_process($db, $ev); | $r = rg_event_process($db, $ev); |
268 | 281 | if ($r !== TRUE) { | if ($r !== TRUE) { |
282 | if ($ev['debug'] == 1) | ||
283 | break; | ||
284 | |||
269 | 285 | $sql = "UPDATE events" | $sql = "UPDATE events" |
270 | 286 | . " SET tries = tries + 1" | . " SET tries = tries + 1" |
271 | 287 | . ", next_try = $now + tries * 600" | . ", next_try = $now + tries * 600" |
File inc/keys.inc.php changed (mode: 100644) (index 2999cea..a7a062c) | |||
... | ... | function rg_keys_event_notify_user($db, $event) | |
101 | 101 | // TODO: del: Take care: we already deleted the keys. We cannot inspect | // TODO: del: Take care: we already deleted the keys. We cannot inspect |
102 | 102 | // them anymore! Maybe put info in the event. | // them anymore! Maybe put info in the event. |
103 | 103 | ||
104 | $r = rg_mail_template("mail/user/key/" . $event['op'], $event); | ||
105 | if ($r === FALSE) | ||
106 | return FALSE; | ||
104 | $ret = FALSE; | ||
105 | while (1) { | ||
106 | if ($event['debug'] == 1) { | ||
107 | rg_cache_set('DEBUG::keys_event_notify_user', $event, 0); | ||
108 | $ret = array(); | ||
109 | break; | ||
110 | } | ||
111 | |||
112 | $r = rg_mail_template("mail/user/key/" . $event['op'], $event); | ||
113 | if ($r === FALSE) | ||
114 | break; | ||
115 | |||
116 | $ret = array(); | ||
117 | break; | ||
118 | } | ||
107 | 119 | ||
108 | 120 | rg_prof_end("keys_event_notify_user"); | rg_prof_end("keys_event_notify_user"); |
109 | return array(); | ||
121 | return $ret; | ||
110 | 122 | } | } |
111 | 123 | ||
112 | 124 | /* | /* |
File inc/repo.inc.php changed (mode: 100644) (index d97d4af..747b083) | |||
... | ... | require_once($INC . "/git.inc.php"); | |
7 | 7 | require_once($INC . "/rights.inc.php"); | require_once($INC . "/rights.inc.php"); |
8 | 8 | require_once($INC . "/prof.inc.php"); | require_once($INC . "/prof.inc.php"); |
9 | 9 | require_once($INC . "/events.inc.php"); | require_once($INC . "/events.inc.php"); |
10 | require_once($INC . "/webhooks.inc.php"); | ||
10 | 11 | ||
11 | 12 | $rg_repo_refs_rights = array( | $rg_repo_refs_rights = array( |
12 | 13 | "F" => "Fetch", | "F" => "Fetch", |
... | ... | function rg_repo_event_new($db, $event) | |
274 | 275 | $x['notification'] .= "-notify"; | $x['notification'] .= "-notify"; |
275 | 276 | $ret[] = $x; | $ret[] = $x; |
276 | 277 | ||
278 | // webhook | ||
279 | $x = $event; | ||
280 | $x['category'] = 10000; | ||
281 | $x['prio'] = 50; | ||
282 | $x['wh_event'] = 'C'; // see rg_wh_events array | ||
283 | $ri = &$event['ri']; | ||
284 | $x['wh_data'] = array( | ||
285 | 'name' => $ri['name'], | ||
286 | 'public' => $ri['public'], | ||
287 | 'description' => $ri['description'], | ||
288 | 'itime' => $ri['itime'], | ||
289 | 'license' => $ri['license'] | ||
290 | ); | ||
291 | $ret[] = $x; | ||
292 | |||
277 | 293 | // add a history entry | // add a history entry |
278 | 294 | $x = $event; | $x = $event; |
279 | 295 | $x['category'] = 3006; | $x['category'] = 3006; |
... | ... | function rg_repo_event_notify_user($db, $event) | |
458 | 474 | { | { |
459 | 475 | rg_prof_start("repo_event_notify_user"); | rg_prof_start("repo_event_notify_user"); |
460 | 476 | ||
461 | $r = rg_mail_template("mail/user/repo/" . $event['op'], $event); | ||
462 | if ($r === FALSE) | ||
463 | return FALSE; | ||
477 | $ret = FALSE; | ||
478 | while (1) { | ||
479 | if ($event['debug'] == 1) { | ||
480 | rg_cache_set('DEBUG::repo_event_notify_user', $event, 0); | ||
481 | $ret = array(); | ||
482 | break; | ||
483 | } | ||
484 | |||
485 | $r = rg_mail_template("mail/user/repo/" . $event['op'], $event); | ||
486 | if ($r === FALSE) | ||
487 | break; | ||
488 | |||
489 | $ret = array(); | ||
490 | break; | ||
491 | } | ||
464 | 492 | ||
465 | 493 | rg_prof_end("repo_event_notify_user"); | rg_prof_end("repo_event_notify_user"); |
466 | return array(); | ||
494 | return $ret; | ||
467 | 495 | } | } |
468 | 496 | ||
469 | 497 | /* | /* |
... | ... | function rg_repo_edit($db, $login_ui, &$new) | |
908 | 936 | ||
909 | 937 | if ($new['repo_id'] == 0) { | if ($new['repo_id'] == 0) { |
910 | 938 | // Check if name is already taken | // Check if name is already taken |
911 | $ri = rg_repo_info($db, 0, $login_ui['uid'], $new['name']); | ||
939 | $ri = rg_repo_info($db, 0, $login_ui['uid'], | ||
940 | $new['name']); | ||
912 | 941 | if ($ri['ok'] != 1) | if ($ri['ok'] != 1) |
913 | 942 | break; | break; |
914 | 943 | if ($ri['exists'] == 1) { | if ($ri['exists'] == 1) { |
915 | rg_repo_set_error("name already taken; choose a different one"); | ||
944 | rg_repo_set_error('name already taken;' | ||
945 | . ' choose a different one'); | ||
916 | 946 | break; | break; |
917 | 947 | } | } |
918 | 948 | } else { | } else { |
... | ... | function rg_repo_edit($db, $login_ui, &$new) | |
922 | 952 | if ($ri['ok'] != 1) | if ($ri['ok'] != 1) |
923 | 953 | break; | break; |
924 | 954 | if ($ri['exists'] != 1) { | if ($ri['exists'] != 1) { |
925 | rg_repo_set_error("repo " . $new['repo_id'] . " does not exists."); | ||
955 | rg_repo_set_error('repo ' . $new['repo_id'] | ||
956 | . ' does not exists.'); | ||
926 | 957 | break; | break; |
927 | 958 | } | } |
928 | 959 | } | } |
... | ... | function rg_repo_edit($db, $login_ui, &$new) | |
976 | 1007 | if ($new['repo_id'] == 0) { | if ($new['repo_id'] == 0) { |
977 | 1008 | $row = rg_sql_fetch_array($res); | $row = rg_sql_fetch_array($res); |
978 | 1009 | if ($row === FALSE) { | if ($row === FALSE) { |
979 | rg_repo_set_error("cannot fetch row: " . rg_sql_error()); | ||
1010 | rg_repo_set_error('cannot fetch row'); | ||
980 | 1011 | break; | break; |
981 | 1012 | } | } |
982 | 1013 | } | } |
... | ... | function rg_repo_edit($db, $login_ui, &$new) | |
1025 | 1056 | rg_cache_set("repo_by_name::" . $login_ui['uid'] . "::" | rg_cache_set("repo_by_name::" . $login_ui['uid'] . "::" |
1026 | 1057 | . $new['name'], $new['repo_id'], RG_SOCKET_NO_WAIT); | . $new['name'], $new['repo_id'], RG_SOCKET_NO_WAIT); |
1027 | 1058 | ||
1028 | rg_event_signal_daemon("", 0); | ||
1059 | rg_event_signal_daemon('', 0); | ||
1029 | 1060 | ||
1030 | 1061 | $ret = TRUE; | $ret = TRUE; |
1031 | 1062 | break; | break; |
File inc/struct.inc.php changed (mode: 100644) (index b39dbd8..decbaae) | |||
... | ... | $rg_sql_struct[34]['tables'] = array( | |
451 | 451 | ); | ); |
452 | 452 | $rg_sql_struct[34]['other'] = array( | $rg_sql_struct[34]['other'] = array( |
453 | 453 | "scratch_codes_i_uid" => | "scratch_codes_i_uid" => |
454 | "CREATE INDEX scratch_codes_i_uid ON scratch_codes(uid)", | ||
454 | "CREATE INDEX scratch_codes_i_uid ON scratch_codes(uid)" | ||
455 | ); | ||
456 | |||
457 | $rg_sql_struct[35] = array(); | ||
458 | $rg_sql_struct[35]['tables'] = array( | ||
459 | "webhooks" => | ||
460 | "CREATE TABLE webhooks (id SERIAL" | ||
461 | . ", uid INT NOT NULL DEFAULT 0" | ||
462 | . ", repo_id INT NOT NULL DEFAULT 0" | ||
463 | . ", itime INT NOT NULL DEFAULT 0" | ||
464 | . ", events TEXT NOT NULL DEFAULT ''" | ||
465 | . ", url TEXT NOT NULL DEFAULT ''" | ||
466 | . ", type SMALLINT NOT NULL DEFAULT 0" | ||
467 | . ", client_cert TEXT NOT NULL DEFAULT ''" | ||
468 | . ", client_ca_cert TEXT NOT NULL DEFAULT ''" | ||
469 | . ", flags TEXT NOT NULL DEFAULT ''" | ||
470 | . ", add_ip TEXT NOT NULL DEFAULT ''" | ||
471 | . ", description TEXT NOT NULL DEFAULT ''" | ||
472 | . ")" | ||
473 | ); | ||
474 | $rg_sql_struct[35]['other'] = array( | ||
475 | "webhooks_i_uid" => | ||
476 | "CREATE INDEX webhooks_i_uid ON webhooks(uid)" | ||
455 | 477 | ); | ); |
456 | 478 | ||
457 | 479 | // This must be the last line | // This must be the last line |
File inc/totp.inc.php changed (mode: 100644) (index 96502f1..2dbebcd) | |||
... | ... | function rg_totp_set_last_use($db, $uid, $id, $tc, $ts) | |
269 | 269 | . ', conf = @@conf@@' | . ', conf = @@conf@@' |
270 | 270 | . ' WHERE uid = @@uid@@' | . ' WHERE uid = @@uid@@' |
271 | 271 | . ' AND id = @@id@@'; | . ' AND id = @@id@@'; |
272 | $res = rg_sql_query_params($db, $sql, $params); | ||
273 | if ($res === FALSE) { | ||
274 | rg_totp_set_error('cannot update last used (' . rg_sql_error()); | ||
272 | $res = rg_sql_query_params($db, $sql, $params); | ||
273 | if ($res === FALSE) { | ||
274 | rg_totp_set_error('cannot update last used (' . rg_sql_error()); | ||
275 | 275 | break; | break; |
276 | } | ||
277 | rg_sql_free_result($res); | ||
276 | } | ||
277 | rg_sql_free_result($res); | ||
278 | 278 | ||
279 | 279 | $key = 'user' . '::' . $uid . '::' . 'login_tokens' | $key = 'user' . '::' . $uid . '::' . 'login_tokens' |
280 | 280 | . '::' . 'device' . '::' . $id; | . '::' . 'device' . '::' . $id; |
... | ... | function rg_totp_device_list($db, $uid) | |
311 | 311 | break; | break; |
312 | 312 | } | } |
313 | 313 | ||
314 | $ret = array(); | ||
315 | $ret['ok'] = 0; | ||
316 | |||
317 | 314 | $params = array('uid' => $uid); | $params = array('uid' => $uid); |
318 | 315 | $sql = 'SELECT * FROM login_tokens' | $sql = 'SELECT * FROM login_tokens' |
319 | 316 | . ' WHERE uid = @@uid@@' | . ' WHERE uid = @@uid@@' |
... | ... | function rg_totp_enroll($db, $uid, $name, $secret, $ip, $conf) | |
443 | 440 | break; | break; |
444 | 441 | } | } |
445 | 442 | $row = rg_sql_fetch_array($res); | $row = rg_sql_fetch_array($res); |
446 | rg_sql_free_result($res); | ||
443 | rg_sql_free_result($res); | ||
447 | 444 | ||
448 | 445 | $params['id'] = $row['id']; | $params['id'] = $row['id']; |
449 | 446 | rg_totp_cosmetic($params); | rg_totp_cosmetic($params); |
... | ... | function rg_totp_add_ip($db, $uid, $token_id, $ip, $expire_ts) | |
484 | 481 | rg_totp_set_error('cannot insert login token ip; try again later'); | rg_totp_set_error('cannot insert login token ip; try again later'); |
485 | 482 | break; | break; |
486 | 483 | } | } |
487 | rg_sql_free_result($res); | ||
484 | rg_sql_free_result($res); | ||
488 | 485 | ||
489 | 486 | unset($params['uid']); | unset($params['uid']); |
490 | 487 | $eip = str_replace(':', '_', $ip); | $eip = str_replace(':', '_', $ip); |
... | ... | function rg_totp_del_ip($db, $uid, $ip) | |
528 | 525 | break; | break; |
529 | 526 | } | } |
530 | 527 | $aff = rg_sql_affected_rows($res); | $aff = rg_sql_affected_rows($res); |
531 | rg_sql_free_result($res); | ||
528 | rg_sql_free_result($res); | ||
532 | 529 | ||
533 | 530 | $ret['ok'] = 1; | $ret['ok'] = 1; |
534 | 531 | ||
... | ... | function rg_totp_remove($db, $uid, $list) | |
704 | 701 | break; | break; |
705 | 702 | } | } |
706 | 703 | ||
707 | rg_log_exit(); | ||
704 | rg_log_exit(); | ||
708 | 705 | rg_prof_end('totp_remove'); | rg_prof_end('totp_remove'); |
709 | 706 | return $ret; | return $ret; |
710 | 707 | } | } |
... | ... | function rg_totp_sc_generate($db, $uid, $count) | |
872 | 869 | rg_totp_set_error('cannot insert scratch codes; try again later'); | rg_totp_set_error('cannot insert scratch codes; try again later'); |
873 | 870 | break; | break; |
874 | 871 | } | } |
875 | rg_sql_free_result($res); | ||
872 | rg_sql_free_result($res); | ||
876 | 873 | ||
877 | 874 | rg_totp_cosmetic($params); | rg_totp_cosmetic($params); |
878 | 875 | $key = 'user' . '::' . $uid . '::' . 'login_tokens' | $key = 'user' . '::' . $uid . '::' . 'login_tokens' |
... | ... | function rg_totp_sc_remove($db, $uid, $itime, $token) | |
921 | 918 | break; | break; |
922 | 919 | } | } |
923 | 920 | ||
924 | rg_log_exit(); | ||
921 | rg_log_exit(); | ||
925 | 922 | rg_prof_end('totp_sc_remove'); | rg_prof_end('totp_sc_remove'); |
926 | 923 | return $ret; | return $ret; |
927 | 924 | } | } |
... | ... | function rg_totp_sc_remove_list($db, $uid, $list) | |
969 | 966 | break; | break; |
970 | 967 | } | } |
971 | 968 | ||
972 | rg_log_exit(); | ||
969 | rg_log_exit(); | ||
973 | 970 | rg_prof_end('totp_sc_remove_list'); | rg_prof_end('totp_sc_remove_list'); |
974 | 971 | return $ret; | return $ret; |
975 | 972 | } | } |
... | ... | function rg_totp_unenroll($db, $uid) | |
1008 | 1005 | $params = array('uid' => $uid); | $params = array('uid' => $uid); |
1009 | 1006 | $list = array('login_tokens', 'login_tokens_ip', 'scratch_codes'); | $list = array('login_tokens', 'login_tokens_ip', 'scratch_codes'); |
1010 | 1007 | foreach ($list as $t) { | foreach ($list as $t) { |
1011 | $sql = 'DELETE FROM ' . $t | ||
1008 | $sql = 'DELETE FROM ' . $t | ||
1012 | 1009 | . ' WHERE uid = @@uid@@'; | . ' WHERE uid = @@uid@@'; |
1013 | 1010 | $res = rg_sql_query_params($db, $sql, $params); | $res = rg_sql_query_params($db, $sql, $params); |
1014 | 1011 | if (!$res) { | if (!$res) { |
... | ... | function rg_totp_list_high_level($db, $rg, $paras) | |
1238 | 1235 | } else { | } else { |
1239 | 1236 | $rg['rg_form_token'] = rg_token_get($db, $rg, 'login_tokens_list'); | $rg['rg_form_token'] = rg_token_get($db, $rg, 'login_tokens_list'); |
1240 | 1237 | $rg['HTML:del_errmsg'] = rg_template_errmsg($del_errmsg); | $rg['HTML:del_errmsg'] = rg_template_errmsg($del_errmsg); |
1241 | $ret .= rg_template_table('user/settings/totp/list', $r['list'], $rg); | ||
1238 | $ret .= rg_template_table('user/settings/totp/list', | ||
1239 | $r['list'], $rg); | ||
1242 | 1240 | } | } |
1243 | 1241 | ||
1244 | 1242 | rg_log_exit(); | rg_log_exit(); |
... | ... | function rg_totp_enroll_high_level($db, $rg, $paras) | |
1256 | 1254 | ||
1257 | 1255 | $now = time(); | $now = time(); |
1258 | 1256 | ||
1259 | $rg['totp'] = array(); | ||
1260 | |||
1261 | 1257 | $ret = ''; | $ret = ''; |
1262 | 1258 | $errmsg = array(); | $errmsg = array(); |
1263 | 1259 | ||
1264 | $rg['totp']['name'] = rg_var_str('totp::name'); | ||
1265 | |||
1266 | 1260 | $enroll = rg_var_uint('enroll'); | $enroll = rg_var_uint('enroll'); |
1267 | 1261 | while ($enroll == 1) { | while ($enroll == 1) { |
1268 | 1262 | $name = rg_var_str('totp::name'); | $name = rg_var_str('totp::name'); |
... | ... | function rg_totp_enroll_high_level($db, $rg, $paras) | |
1317 | 1311 | $secret = rg_totp_base32_generate(16); | $secret = rg_totp_base32_generate(16); |
1318 | 1312 | } | } |
1319 | 1313 | ||
1314 | $rg['totp'] = array(); | ||
1320 | 1315 | $rg['totp']['name'] = $name; | $rg['totp']['name'] = $name; |
1321 | 1316 | $rg['totp']['ver'] = $ver; | $rg['totp']['ver'] = $ver; |
1322 | 1317 | $rg['totp']['secret'] = $secret; | $rg['totp']['secret'] = $secret; |
... | ... | function rg_totp_enroll_high_level($db, $rg, $paras) | |
1330 | 1325 | } | } |
1331 | 1326 | ||
1332 | 1327 | $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); | $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); |
1333 | |||
1334 | 1328 | $rg['rg_form_token'] = rg_token_get($db, $rg, 'user_totp_enroll'); | $rg['rg_form_token'] = rg_token_get($db, $rg, 'user_totp_enroll'); |
1335 | rg_log_ml('DEBUG rg: ' . print_r($rg, TRUE)); | ||
1336 | 1329 | $ret .= rg_template('user/settings/totp/enroll.html', $rg, TRUE /*xss*/); | $ret .= rg_template('user/settings/totp/enroll.html', $rg, TRUE /*xss*/); |
1337 | 1330 | ||
1338 | 1331 | rg_log_exit(); | rg_log_exit(); |
File inc/user.inc.php changed (mode: 100644) (index 1c4bf0d..11fea9c) | |||
... | ... | function rg_user_event_notify_user($db, $event) | |
92 | 92 | { | { |
93 | 93 | rg_log("user_event_notify_user: event=" . rg_array2string($event)); | rg_log("user_event_notify_user: event=" . rg_array2string($event)); |
94 | 94 | ||
95 | if ($event['debug'] == 1) { | ||
96 | rg_cache_set('DEBUG::user_event_notify_user', $event, 0); | ||
97 | return array(); | ||
98 | } | ||
99 | |||
95 | 100 | if (strcmp($event['op'], "rename") == 0) { | if (strcmp($event['op'], "rename") == 0) { |
96 | 101 | $r = rg_mail_template("mail/user/rename", $event); | $r = rg_mail_template("mail/user/rename", $event); |
97 | 102 | } else { | } else { |
File inc/user/settings.php changed (mode: 100644) (index cddd83b..3890c4a) | |||
1 | 1 | <?php | <?php |
2 | 2 | rg_log("FILE: /inc/user/settings"); | rg_log("FILE: /inc/user/settings"); |
3 | require_once($INC . '/webhooks.inc.php'); | ||
3 | 4 | ||
4 | 5 | $_settings = ''; | $_settings = ''; |
5 | 6 | ||
... | ... | case 'keys': | |
37 | 38 | case 'totp': | case 'totp': |
38 | 39 | $_settings .= rg_totp_high_level($db, $rg, $paras); | $_settings .= rg_totp_high_level($db, $rg, $paras); |
39 | 40 | break; | break; |
41 | |||
42 | case 'wh': | ||
43 | $_settings .= rg_wh_high_level($db, $rg, $paras); | ||
44 | break; | ||
40 | 45 | } | } |
41 | 46 | ||
42 | 47 | ?> | ?> |
File inc/util.inc.php changed (mode: 100644) (index d94706d..6313a70) | |||
... | ... | function rg_var_cookie_re($name, $re) | |
357 | 357 | return preg_replace($re, '', $_COOKIE[$name]); | return preg_replace($re, '', $_COOKIE[$name]); |
358 | 358 | } | } |
359 | 359 | ||
360 | /* | ||
361 | * Gets data from request and transforms it into an array | ||
362 | * Usefull for checkboxes. | ||
363 | * (a2s = array2string) | ||
364 | */ | ||
365 | function rg_var_a2s($var) | ||
366 | { | ||
367 | $r = rg_var_str($var); | ||
368 | if (!is_array($r)) | ||
369 | return $r; | ||
370 | |||
371 | $ret = ''; | ||
372 | foreach ($r as $s => $junk) | ||
373 | $ret .= $s; | ||
374 | |||
375 | return $ret; | ||
376 | } | ||
377 | |||
360 | 378 | /* | /* |
361 | 379 | * Enforce chars in a name. It is used for user and repo. | * Enforce chars in a name. It is used for user and repo. |
362 | 380 | */ | */ |
... | ... | function rg_age($ts) | |
1595 | 1613 | return $ret; | return $ret; |
1596 | 1614 | } | } |
1597 | 1615 | ||
1616 | /* | ||
1617 | * Creates a temporary file | ||
1618 | */ | ||
1619 | function rg_tmp_file($file, $content) | ||
1620 | { | ||
1621 | global $rg_state_dir; | ||
1622 | |||
1623 | $final_name = $rg_state_dir . '/tmp/' . $file; | ||
1624 | $r = @file_put_contents($final_name, $content); | ||
1625 | if ($r === FALSE) | ||
1626 | return FALSE; | ||
1627 | // TODO: log error messege? | ||
1628 | |||
1629 | return $final_name; | ||
1630 | } | ||
1631 | |||
1598 | 1632 | ?> | ?> |
File inc/webhooks.inc.php added (mode: 100644) (index 0000000..5da2344) | |||
1 | <?php | ||
2 | require_once($INC . "/util.inc.php"); | ||
3 | require_once($INC . "/log.inc.php"); | ||
4 | require_once($INC . "/sql.inc.php"); | ||
5 | require_once($INC . "/prof.inc.php"); | ||
6 | |||
7 | $rg_wh_error = ""; | ||
8 | |||
9 | function rg_wh_set_error($str) | ||
10 | { | ||
11 | global $rg_wh_error; | ||
12 | |||
13 | $rg_wh_error = $str; | ||
14 | rg_log($str); | ||
15 | } | ||
16 | |||
17 | function rg_wh_error() | ||
18 | { | ||
19 | global $rg_wh_error; | ||
20 | return $rg_wh_error; | ||
21 | } | ||
22 | |||
23 | $rg_wh_functions = array( | ||
24 | 10000 => 'rg_wh_send', | ||
25 | 10001 => 'rg_wh_send_one' | ||
26 | ); | ||
27 | rg_event_register_functions($rg_wh_functions); | ||
28 | |||
29 | /* | ||
30 | * Helper for rg_wh_send | ||
31 | */ | ||
32 | function rg_wh_send_one($db, $event) | ||
33 | { | ||
34 | rg_prof_start('wh_send_helper'); | ||
35 | |||
36 | $wh = &$event['wh']; | ||
37 | $info = &$wh['info']; | ||
38 | |||
39 | rg_log('flags=' . $info['flags']); | ||
40 | |||
41 | $headers = array(); | ||
42 | |||
43 | $c = curl_init($info['url']); | ||
44 | curl_setopt($c, CURLOPT_POST, 1); | ||
45 | curl_setopt($c, CURLOPT_POSTFIELDS, $wh['data']); | ||
46 | curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE); | ||
47 | curl_setopt($c, CURLOPT_FOLLOWLOCATION, 0); | ||
48 | curl_setopt($c, CURLOPT_HEADER, 1); | ||
49 | curl_setopt($c, CURLOPT_HTTPHEADER, $headers); | ||
50 | curl_setopt($c, CURLOPT_USERAGENT, 'RocketGit WebHook'); | ||
51 | curl_setopt($c, CURLOPT_CONNECTTIMEOUT, 30); | ||
52 | curl_setopt($c, CURLOPT_ENCODING, ''); // => use all methods | ||
53 | curl_setopt($c, CURLOPT_VERBOSE, TRUE); | ||
54 | curl_setopt($c, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); | ||
55 | $err = @fopen('php://temp', 'w'); | ||
56 | if ($err !== FALSE) | ||
57 | curl_setopt($c, CURLOPT_STDERR, $err); | ||
58 | |||
59 | if (strchr($info['flags'], 'I')) | ||
60 | curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE); | ||
61 | |||
62 | if (strchr($info['flags'], 'H')) | ||
63 | curl_setopt($c, CURLOPT_SSL_VERIFYHOST, FALSE); | ||
64 | |||
65 | $ret = FALSE; | ||
66 | $cert_file = FALSE; | ||
67 | $ca_file = FALSE; | ||
68 | while (1) { | ||
69 | if (!empty($info['client_cert'])) { | ||
70 | $f = 'wh-' . $event['ui']['uid'] . '-' . $wh['id'] . '-client'; | ||
71 | $cert_file = rg_tmp_file($f, $info['client_cert']); | ||
72 | if ($cert_file === FALSE) | ||
73 | break; | ||
74 | |||
75 | curl_setopt($c, CURLOPT_SSLCERT, $cert_file); | ||
76 | } | ||
77 | |||
78 | if (!empty($info['client_ca_cert'])) { | ||
79 | $f = 'wh-' . $event['ui']['uid'] . '-' . $wh['id'] . '-ca'; | ||
80 | $ca_file = rg_tmp_file($f, $info['client_ca_cert']); | ||
81 | if ($ca_file === FALSE) | ||
82 | break; | ||
83 | |||
84 | curl_setopt($c, CURLOPT_CAINFO, $ca_file); | ||
85 | } | ||
86 | |||
87 | $r = curl_exec($c); | ||
88 | if ($r === FALSE) { | ||
89 | rg_log('Cannot execute curl: ' . curl_error($c)); | ||
90 | $info = curl_getinfo($c); | ||
91 | rg_log_ml('Debug: ' . print_r($info, TRUE)); | ||
92 | |||
93 | if ($event['debug'] == 1) | ||
94 | rg_cache_set('DEBUG::webhooks::' . $event['ui']['uid'] | ||
95 | . '::' . $wh['id'], | ||
96 | 'BAD', RG_SOCKET_NO_WAIT); | ||
97 | break; | ||
98 | } | ||
99 | |||
100 | rg_log_ml('Answer: ' . print_r($r, TRUE)); | ||
101 | |||
102 | if ($err !== FALSE) { | ||
103 | rewind($err); | ||
104 | $xerr = @fread($err, 4 * 4096); | ||
105 | fclose($err); | ||
106 | rg_log_ml('xerr = ' . $xerr); | ||
107 | } | ||
108 | |||
109 | if ($event['debug'] == 1) | ||
110 | rg_cache_set('DEBUG::webhooks::' . $event['ui']['uid'] | ||
111 | . '::' . $wh['id'], | ||
112 | 'OK', RG_SOCKET_NO_WAIT); | ||
113 | |||
114 | $ret = array(); | ||
115 | break; | ||
116 | } | ||
117 | curl_close($c); | ||
118 | |||
119 | if ($cert_file !== FALSE) | ||
120 | @unlink($cert_file); | ||
121 | |||
122 | if ($ca_file !== FALSE) | ||
123 | @unlink($ca_file); | ||
124 | |||
125 | rg_prof_end('wh_send_helper'); | ||
126 | return $ret; | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * Generic function which will be called when a webhook must be posted | ||
131 | */ | ||
132 | function rg_wh_send($db, $event) | ||
133 | { | ||
134 | rg_prof_start('wh_send'); | ||
135 | |||
136 | rg_log_ml('event: ' . print_r($event, TRUE)); | ||
137 | |||
138 | // First, get the list of hooks | ||
139 | $r = rg_wh_list($db, $event['ui']['uid']); | ||
140 | if ($r['ok'] != 1) | ||
141 | return FALSE; | ||
142 | |||
143 | // Filter them by repo_id | ||
144 | $real_list = array(); | ||
145 | foreach ($r['list'] as $id => $info) { | ||
146 | if (($info['repo_id'] != 0) | ||
147 | && ($event['ri']['repo_id'] != $info['repo_id'])) { | ||
148 | rg_log('hook is not for this repo'); | ||
149 | continue; | ||
150 | } | ||
151 | |||
152 | // If the web hook does not contain our type, skip it | ||
153 | if (!strchr($info['events'], $event['wh_event'])) { | ||
154 | rg_log($event['wh_event'] . ' is not present in ' . $info['events']); | ||
155 | continue; | ||
156 | } | ||
157 | |||
158 | $real_list[] = $id; | ||
159 | } | ||
160 | |||
161 | // Something to do? | ||
162 | if (empty($real_list)) | ||
163 | return array(); | ||
164 | |||
165 | $cache = array(); | ||
166 | $wh = array(); | ||
167 | $ret = array(); | ||
168 | foreach ($real_list as $id) { | ||
169 | $wh['info'] = $r['list'][$id]; | ||
170 | $wh['id'] = $id; | ||
171 | |||
172 | $type = $wh['info']['type']; | ||
173 | if (!isset($cache[$type])) { | ||
174 | switch ($type) { | ||
175 | case 0: // http post | ||
176 | $cache[$type] = &$event['wh_data']; | ||
177 | break; | ||
178 | |||
179 | case 1: // php serialize | ||
180 | $cache[$type] = array( | ||
181 | 'data' => serialize($event['wh_data'])); | ||
182 | break; | ||
183 | |||
184 | default: | ||
185 | rg_log('Unknown type ' . $type . '!'); | ||
186 | $cache[$type] = ''; | ||
187 | break; | ||
188 | } | ||
189 | } | ||
190 | $wh['data'] = $cache[$type]; | ||
191 | |||
192 | $x = $event; | ||
193 | $x['category'] = 10001; | ||
194 | $x['wh'] = $wh; | ||
195 | $ret[] = $x; | ||
196 | } | ||
197 | |||
198 | rg_prof_end('wh_send'); | ||
199 | return $ret; | ||
200 | } | ||
201 | |||
202 | $rg_wh_types = array( | ||
203 | 0 => 'HTTP (application/x-www-form-urlencoded)', | ||
204 | 1 => 'PHP serialize' | ||
205 | ); | ||
206 | /* | ||
207 | * Transforms a type into HTML select | ||
208 | */ | ||
209 | function rg_wh_select_type($type) | ||
210 | { | ||
211 | global $rg_wh_types; | ||
212 | |||
213 | $ret = '<select name="wh::type" id="type">'; | ||
214 | foreach ($rg_wh_types as $_type => $name) { | ||
215 | $add = ''; | ||
216 | if ($_type == $type) | ||
217 | $add = ' selected'; | ||
218 | |||
219 | $ret .= '<option value="' . $_type . '"' . $add . '>' | ||
220 | . $name | ||
221 | . '</option>' . "\n"; | ||
222 | } | ||
223 | $ret .= '</select>' . "\n"; | ||
224 | |||
225 | return $ret; | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * Returns type text based on id | ||
230 | */ | ||
231 | function rg_wh_type($type) | ||
232 | { | ||
233 | global $rg_wh_types; | ||
234 | |||
235 | foreach ($rg_wh_types as $_type => $name) | ||
236 | if ($_type == $type) | ||
237 | return $name; | ||
238 | } | ||
239 | |||
240 | $rg_wh_events = array( | ||
241 | 'C' => 'Create repository', | ||
242 | 'P' => 'Push', | ||
243 | 'B' => 'Create branch' | ||
244 | ); | ||
245 | /* | ||
246 | * Generates event list as html | ||
247 | */ | ||
248 | function rg_wh_check_events($events) | ||
249 | { | ||
250 | global $rg_wh_events; | ||
251 | |||
252 | $ret = '<fieldset>'; | ||
253 | $ret .= '<legend>Select trigger events</legend>'; | ||
254 | $br = ''; | ||
255 | foreach ($rg_wh_events as $id => $name) { | ||
256 | $add = ''; | ||
257 | if (strchr($events, $id)) | ||
258 | $add = ' checked="checked"'; | ||
259 | |||
260 | $ret .= $br | ||
261 | . '<input type="checkbox" name="wh::events[' . $id . ']"' | ||
262 | . ' id="events-' . $id . '"' | ||
263 | . $add . ' />' | ||
264 | . "\n" | ||
265 | . '<label for="events-' . $id . '">' . $name . '</label>'; | ||
266 | $br = '<br />' . "\n"; | ||
267 | } | ||
268 | $ret .= '</fieldset>' . "\n"; | ||
269 | |||
270 | return $ret; | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * Generates an events list as text | ||
275 | */ | ||
276 | function rg_wh_events($events) | ||
277 | { | ||
278 | global $rg_wh_events; | ||
279 | |||
280 | $a = array(); | ||
281 | foreach ($rg_wh_events as $id => $name) { | ||
282 | if (strchr($events, $id)) | ||
283 | $a[] = $name; | ||
284 | } | ||
285 | |||
286 | return implode(', ', $a); | ||
287 | } | ||
288 | |||
289 | $rg_wh_flags = array( | ||
290 | 'I' => 'Do not verify the certificate', | ||
291 | 'H' => 'Do not verify the hostname' | ||
292 | ); | ||
293 | /* | ||
294 | * Generates flags list | ||
295 | */ | ||
296 | function rg_wh_check_flags($flags) | ||
297 | { | ||
298 | global $rg_wh_flags; | ||
299 | |||
300 | $ret = '<fieldset>'; | ||
301 | $ret .= '<legend>Flags</legend>'; | ||
302 | $br = ''; | ||
303 | foreach ($rg_wh_flags as $id => $name) { | ||
304 | $add = ''; | ||
305 | if (strchr($flags, $id)) | ||
306 | $add = ' checked="checked"'; | ||
307 | |||
308 | $ret .= $br | ||
309 | . '<input type="checkbox" name="wh::flags[' . $id . ']"' | ||
310 | . ' id="flags-' . $id . '"' | ||
311 | . $add . ' />' | ||
312 | . "\n" | ||
313 | . '<label for="flags-' . $id . '">' . $name . '</label>'; | ||
314 | $br = '<br />' . "\n"; | ||
315 | } | ||
316 | $ret .= '</fieldset>' . "\n"; | ||
317 | |||
318 | return $ret; | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * Generates a flags list as text | ||
323 | */ | ||
324 | function rg_wh_flags($flags) | ||
325 | { | ||
326 | global $rg_wh_flags; | ||
327 | |||
328 | $a = array(); | ||
329 | foreach ($rg_wh_flags as $id => $name) { | ||
330 | if (strchr($flags, $id)) | ||
331 | $a[] = $name; | ||
332 | } | ||
333 | |||
334 | return implode(', ', $a); | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * Some cosmetics applied to a webhook | ||
339 | */ | ||
340 | function rg_wh_cosmetic(&$list) | ||
341 | { | ||
342 | foreach ($list as $id => &$row) { | ||
343 | if (isset($row['itime'])) | ||
344 | $row['itime_nice'] = gmdate('Y-m-d H:i', $row['itime']); | ||
345 | |||
346 | if (isset($row['description'])) | ||
347 | $row['HTML:description_nice'] = | ||
348 | nl2br(rg_xss_safe($row['description'])); | ||
349 | |||
350 | if (isset($row['type'])) | ||
351 | $row['type_text'] = rg_wh_type($row['type']); | ||
352 | |||
353 | if (isset($row['events'])) | ||
354 | $row['events_text'] = rg_wh_events($row['events']); | ||
355 | |||
356 | if (isset($row['flags'])) | ||
357 | $row['flags_text'] = rg_wh_flags($row['flags']); | ||
358 | |||
359 | if (isset($row['client_cert'])) | ||
360 | $row['HTML:client_cert_short'] = | ||
361 | empty($row['client_cert']) ? | ||
362 | '' : nl2br(rg_xss_safe(substr($row['client_cert'], 0, 32))) . '...'; | ||
363 | |||
364 | if (isset($row['client_ca_cert'])) | ||
365 | $row['HTML:client_ca_cert_short'] = | ||
366 | empty($row['client_ca_cert']) ? | ||
367 | '' : nl2br(rg_xss_safe(substr($row['client_ca_cert'], 0, 32))) . '...'; | ||
368 | } | ||
369 | } | ||
370 | |||
371 | /* | ||
372 | * Returns a list of webhooks associated with a user | ||
373 | * @repo_id may be 0 => hooks installed on user account | ||
374 | */ | ||
375 | function rg_wh_list($db, $uid) | ||
376 | { | ||
377 | rg_prof_start('wh_list'); | ||
378 | rg_log_enter('wh_list'); | ||
379 | |||
380 | $ret = array('ok' => 0, 'list' => array()); | ||
381 | while (1) { | ||
382 | $key = 'user' . '::' . $uid . '::' . 'wh'; | ||
383 | $r = rg_cache_get($key); | ||
384 | if ($r !== FALSE) { | ||
385 | $ret['list'] = $r; | ||
386 | $ret['ok'] = 1; | ||
387 | break; | ||
388 | } | ||
389 | |||
390 | $params = array('uid' => $uid); | ||
391 | $sql = 'SELECT * FROM webhooks' | ||
392 | . ' WHERE uid = @@uid@@'; | ||
393 | $res = rg_sql_query_params($db, $sql, $params); | ||
394 | if ($res === FALSE) { | ||
395 | rg_wh_set_error('cannot load data'); | ||
396 | break; | ||
397 | } | ||
398 | |||
399 | while (($row = rg_sql_fetch_array($res))) { | ||
400 | $id = $row['id']; | ||
401 | |||
402 | $ret['list'][$id] = $row; | ||
403 | } | ||
404 | rg_sql_free_result($res); | ||
405 | |||
406 | rg_cache_set($key, $ret['list'], RG_SOCKET_NO_WAIT); | ||
407 | $ret['ok'] = 1; | ||
408 | break; | ||
409 | } | ||
410 | |||
411 | rg_log_exit(); | ||
412 | rg_prof_end('wh_list'); | ||
413 | return $ret; | ||
414 | } | ||
415 | |||
416 | /* | ||
417 | * Adds/edits a webhook | ||
418 | */ | ||
419 | function rg_wh_add($db, $uid, $data) | ||
420 | { | ||
421 | rg_prof_start('wh_add'); | ||
422 | rg_log_enter('wh_add'); | ||
423 | |||
424 | $ret = array('ok' => 0); | ||
425 | while (1) { | ||
426 | $params = $data; | ||
427 | $params['uid'] = $uid; | ||
428 | $params['itime'] = time(); | ||
429 | |||
430 | if ($data['id'] == 0) | ||
431 | $sql = 'INSERT INTO webhooks (uid, repo_id, itime, events' | ||
432 | . ', url, client_cert, client_ca_cert, flags' | ||
433 | . ', add_ip, description)' | ||
434 | . ' VALUES (@@uid@@, @@repo_id@@, @@itime@@' | ||
435 | . ', @@events@@, @@url@@, @@client_cert@@' | ||
436 | . ', @@client_ca_cert@@, @@flags@@, @@add_ip@@' | ||
437 | . ', @@description@@)' | ||
438 | . ' RETURNING id'; | ||
439 | else | ||
440 | $sql = 'UPDATE webhooks' | ||
441 | . ' SET events = @@events@@' | ||
442 | . ', url = @@url@@' | ||
443 | . ', client_cert = @@client_cert@@' | ||
444 | . ', client_ca_cert = @@client_ca_cert@@' | ||
445 | . ', flags = @@flags@@' | ||
446 | . ', type = @@type@@' | ||
447 | . ', description = @@description@@' | ||
448 | . ' WHERE uid = @@uid@@' | ||
449 | . ' AND id = @@id@@'; | ||
450 | |||
451 | $res = rg_sql_query_params($db, $sql, $params); | ||
452 | if ($res === FALSE) { | ||
453 | rg_wh_set_error('cannot insert/update data'); | ||
454 | break; | ||
455 | } | ||
456 | if ($data['id'] == 0) | ||
457 | $row = rg_sql_fetch_array($res); | ||
458 | rg_sql_free_result($res); | ||
459 | |||
460 | if ($data['id'] == 0) | ||
461 | $params['id'] = $row['id']; | ||
462 | $key = 'user' . '::' . $uid . '::' . 'wh' | ||
463 | . '::' . $params['id']; | ||
464 | rg_cache_set($key, $params, RG_SOCKET_NO_WAIT); | ||
465 | |||
466 | $ret['ok'] = 1; | ||
467 | break; | ||
468 | } | ||
469 | |||
470 | rg_log_exit(); | ||
471 | rg_prof_end('wh_add'); | ||
472 | return $ret; | ||
473 | } | ||
474 | |||
475 | /* | ||
476 | * Removes a list of webhooks | ||
477 | */ | ||
478 | function rg_wh_remove($db, $uid, $list) | ||
479 | { | ||
480 | rg_prof_start('wh_remove'); | ||
481 | rg_log_enter('wh_remove'); | ||
482 | |||
483 | $ret = array('ok' => 0); | ||
484 | while (1) { | ||
485 | if (empty($list)) { | ||
486 | rg_wh_set_error('you did not select anything'); | ||
487 | break; | ||
488 | } | ||
489 | |||
490 | $my_list = array(); | ||
491 | foreach ($list as $id => $junk) | ||
492 | $my_list[] = sprintf("%u", $id); | ||
493 | |||
494 | $params = array('uid' => $uid); | ||
495 | $sql_list = implode(', ', $my_list); | ||
496 | |||
497 | $sql = 'DELETE FROM webhooks' | ||
498 | . ' WHERE uid = @@uid@@' | ||
499 | . ' AND id IN (' . $sql_list . ')'; | ||
500 | $res = rg_sql_query_params($db, $sql, $params); | ||
501 | if ($res === FALSE) { | ||
502 | rg_wh_set_error('cannot remove webhooks'); | ||
503 | break; | ||
504 | } | ||
505 | rg_sql_free_result($res); | ||
506 | |||
507 | foreach ($my_list as $junk => $id) { | ||
508 | $key = 'user' . '::' . $uid . '::' . 'wh' . '::' . $id; | ||
509 | rg_cache_unset($key, RG_SOCKET_NO_WAIT); | ||
510 | } | ||
511 | |||
512 | $ret['ok'] = 1; | ||
513 | break; | ||
514 | } | ||
515 | |||
516 | rg_log_exit(); | ||
517 | rg_prof_end('wh_remove'); | ||
518 | return $ret; | ||
519 | } | ||
520 | |||
521 | /* | ||
522 | * High level function to list the webhooks | ||
523 | */ | ||
524 | function rg_wh_list_high_level($db, $rg, $paras) | ||
525 | { | ||
526 | rg_prof_start('wh_list_high_level'); | ||
527 | rg_log_enter('wh_list_high_level'); | ||
528 | |||
529 | $ret = ''; | ||
530 | |||
531 | $errmsg = array(); | ||
532 | |||
533 | $delete = rg_var_uint('delete'); | ||
534 | while ($delete == 1) { | ||
535 | if (!rg_valid_referer()) { | ||
536 | $errmsg[] = 'invalid referer; try again'; | ||
537 | break; | ||
538 | } | ||
539 | |||
540 | if (!rg_token_valid($db, $rg, 'wh_list', FALSE)) { | ||
541 | $errmsg[] = 'invalid token; try again.'; | ||
542 | break; | ||
543 | } | ||
544 | |||
545 | $list = rg_var_str("delete_list"); | ||
546 | $r = rg_wh_remove($db, $rg['login_ui']['uid'], $list); | ||
547 | if ($r['ok'] !== 1) { | ||
548 | $errmsg[] = 'cannot delete: ' . rg_wh_error(); | ||
549 | break; | ||
550 | } | ||
551 | |||
552 | $ret .= rg_template('user/settings/wh/delete_ok.html', | ||
553 | $rg, TRUE /*xss*/); | ||
554 | break; | ||
555 | } | ||
556 | |||
557 | $r = rg_wh_list($db, $rg['login_ui']['uid']); | ||
558 | if ($r['ok'] !== 1) { | ||
559 | $rg['errmsg'] = rg_wh_error(); | ||
560 | $ret .= rg_template('user/settings/wh/list_err.html', | ||
561 | $rg, TRUE /*xss*/); | ||
562 | } else { | ||
563 | rg_wh_cosmetic($r['list']); | ||
564 | //rg_log_ml("DEBUG: r[list]: " . print_r($r['list'], TRUE)); | ||
565 | $rg['rg_form_token'] = rg_token_get($db, $rg, 'wh_list'); | ||
566 | $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); | ||
567 | $ret .= rg_template_table('user/settings/wh/list', | ||
568 | $r['list'], $rg); | ||
569 | } | ||
570 | |||
571 | rg_log_exit(); | ||
572 | rg_prof_end('wh_list_high_level'); | ||
573 | return $ret; | ||
574 | } | ||
575 | |||
576 | /* | ||
577 | * High level function to add/edit a web hook | ||
578 | */ | ||
579 | function rg_wh_add_high_level($db, $rg, $paras) | ||
580 | { | ||
581 | rg_prof_start('wh_add_high_level'); | ||
582 | rg_log_enter('wh_add_high_level'); | ||
583 | |||
584 | $ret = ''; | ||
585 | $errmsg = array(); | ||
586 | $show_form = TRUE; | ||
587 | |||
588 | $rg['wh'] = array(); | ||
589 | // We need the id in any case | ||
590 | $rg['wh']['id'] = rg_var_str('wh::id'); | ||
591 | |||
592 | $add = rg_var_uint('add'); | ||
593 | while ($add == 1) { | ||
594 | $rg['wh']['repo_id'] = rg_var_uint('wh::repo_id'); | ||
595 | $rg['wh']['itime'] = time(); | ||
596 | $rg['wh']['events'] = rg_var_a2s('wh::events'); // TODO | ||
597 | $rg['wh']['url'] = rg_var_str('wh::url'); | ||
598 | $rg['wh']['type'] = rg_var_uint('wh::type'); | ||
599 | $rg['wh']['client_cert'] = trim(rg_var_str('wh::client_cert')); | ||
600 | $rg['wh']['client_ca_cert'] = trim(rg_var_str('wh::client_ca_cert')); | ||
601 | $rg['wh']['flags'] = rg_var_a2s('wh::flags'); | ||
602 | $rg['wh']['add_ip'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''; | ||
603 | $rg['wh']['description'] = rg_var_str('wh::description'); | ||
604 | |||
605 | // TODO: validate here the paras | ||
606 | if ((strncasecmp($rg['wh']['url'], "http", 4) != 0) | ||
607 | || (strncasecmp($rg['wh']['url'], "https", 5) != 0)) { | ||
608 | $errmsg[] = 'invalid protocol; only http and https supported now'; | ||
609 | break; | ||
610 | } | ||
611 | |||
612 | if (!rg_valid_referer()) { | ||
613 | $errmsg[] = 'invalid referer; try again'; | ||
614 | break; | ||
615 | } | ||
616 | |||
617 | if (!rg_token_valid($db, $rg, 'wh_add', FALSE)) { | ||
618 | $errmsg[] = 'invalid token; try again.'; | ||
619 | break; | ||
620 | } | ||
621 | |||
622 | $r = rg_wh_add($db, $rg['login_ui']['uid'], $rg['wh']); | ||
623 | if ($r['ok'] !== 1) { | ||
624 | $errmsg[] = rg_wh_error(); | ||
625 | break; | ||
626 | } | ||
627 | |||
628 | $ret .= rg_template('user/settings/wh/edit_ok.html', | ||
629 | $rg, TRUE /*xss*/); | ||
630 | |||
631 | $show_form = FALSE; | ||
632 | break; | ||
633 | } | ||
634 | |||
635 | if ($show_form) { | ||
636 | // defaults | ||
637 | if ($add == 0) { | ||
638 | // TODO: if edit, load data based on id | ||
639 | if ($rg['wh']['id'] > 0) { | ||
640 | rg_log('TODO: edit is not yet implemented'); | ||
641 | } else { | ||
642 | // here is clear an add | ||
643 | $rg['wh']['id'] = 0; | ||
644 | $rg['wh']['events'] = ''; | ||
645 | $rg['wh']['url'] = ''; | ||
646 | $rg['wh']['type'] = 0; | ||
647 | $rg['wh']['client_cert'] = ''; | ||
648 | $rg['wh']['client_ca_cert'] = ''; | ||
649 | $rg['wh']['flags'] = ''; | ||
650 | $rg['wh']['description'] = ''; | ||
651 | } | ||
652 | } | ||
653 | |||
654 | $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); | ||
655 | $rg['HTML:check_flags'] = rg_wh_check_flags($rg['wh']['flags']); | ||
656 | $rg['HTML:check_events'] = rg_wh_check_events($rg['wh']['events']); | ||
657 | $rg['HTML:select_type'] = rg_wh_select_type($rg['wh']['type']); | ||
658 | $rg['rg_form_token'] = rg_token_get($db, $rg, 'wh_add'); | ||
659 | $ret .= rg_template('user/settings/wh/add_edit.html', | ||
660 | $rg, TRUE /*xss*/); | ||
661 | } | ||
662 | |||
663 | rg_log_exit(); | ||
664 | rg_prof_end('wh_add_high_level'); | ||
665 | return $ret; | ||
666 | } | ||
667 | |||
668 | /* | ||
669 | * Main HL function for webhooks | ||
670 | */ | ||
671 | function rg_wh_high_level($db, $rg, $paras) | ||
672 | { | ||
673 | rg_prof_start('wh_high_level'); | ||
674 | rg_log_enter('wh_high_level'); | ||
675 | |||
676 | $ret = ''; | ||
677 | |||
678 | $op = empty($paras) ? 'list' : array_shift($paras); | ||
679 | $rg['menu']['wh'][$op] = 1; | ||
680 | |||
681 | rg_log("DEBUG: op=$op"); | ||
682 | $ret .= rg_template('user/settings/wh/menu.html', $rg, TRUE /*xss*/); | ||
683 | |||
684 | switch ($op) { | ||
685 | case 'add': $ret .= rg_wh_add_high_level($db, $rg, $paras); break; | ||
686 | default: $ret .= rg_wh_list_high_level($db, $rg, $paras); break; | ||
687 | } | ||
688 | |||
689 | rg_log_exit(); | ||
690 | rg_prof_end('wh_high_level'); | ||
691 | return $ret; | ||
692 | } | ||
693 | |||
694 | ?> |
File rocketgit.spec.in changed (mode: 100644) (index 4cf6dc8..51a49f9) | |||
... | ... | rm -rf ${RPM_BUILD_ROOT} | |
95 | 95 | %attr(0755,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/repos | %attr(0755,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/repos |
96 | 96 | %attr(0755,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/q_merge_requests | %attr(0755,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/q_merge_requests |
97 | 97 | %attr(0755,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/sockets | %attr(0755,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/sockets |
98 | %attr(0700,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/tmp | ||
98 | 99 | @USR_SHARE@/@PRJ@/* | @USR_SHARE@/@PRJ@/* |
99 | 100 | @USR_SHARE@/selinux/*/@PRJ@.pp | @USR_SHARE@/selinux/*/@PRJ@.pp |
100 | 101 |
File root/themes/default/main.css changed (mode: 100644) (index 672c0b9..945fcc5) | |||
... | ... | form textarea, form select { | |
54 | 54 | margin: 2px 0px; | margin: 2px 0px; |
55 | 55 | } | } |
56 | 56 | form input[type="checkbox"] { | form input[type="checkbox"] { |
57 | margin-right: 4pt; | ||
57 | margin-right: 2pt; | ||
58 | 58 | } | } |
59 | 59 | form input[type="radio"] { | form input[type="radio"] { |
60 | margin-right: 4pt; | ||
60 | margin-right: 2pt; | ||
61 | 61 | } | } |
62 | 62 | form select option { padding: 1px 4px 1px 4px; } | form select option { padding: 1px 4px 1px 4px; } |
63 | 63 | form input[type="submit"] { | form input[type="submit"] { |
... | ... | legend { padding: 0px 2pt; } | |
281 | 281 | margin-top: 20px; | margin-top: 20px; |
282 | 282 | } | } |
283 | 283 | ||
284 | .rg_wh_list {} | ||
285 | |||
284 | 286 | .blob_title { | .blob_title { |
285 | 287 | font-size: 11pt; | font-size: 11pt; |
286 | 288 | color: #F00; | color: #F00; |
File root/themes/default/repo/add_edit.html changed (mode: 100644) (index fcdca7d..2564a21) | |||
18 | 18 | </p> | </p> |
19 | 19 | ||
20 | 20 | <p> | <p> |
21 | <label for="license">License(s)</label><br /> | ||
21 | <label for="license">License(s) (recommended: GPLv3)</label><br /> | ||
22 | 22 | <input type="text" name="license" id="license" value="@@ri::license@@" /> | <input type="text" name="license" id="license" value="@@ri::license@@" /> |
23 | 23 | </p> | </p> |
24 | 24 |
File root/themes/default/tos.html changed (mode: 100644) (index 34f31b4..0f87fcc) | |||
5 | 5 | <div class="island_cell"> | <div class="island_cell"> |
6 | 6 | <div class="island"> | <div class="island"> |
7 | 7 | ||
8 | The RocketGit code is copyright (c) 2015 by Catalin BOIE and is | ||
9 | covered by <a href="https://gnu.org/licenses/agpl.html">Affero GPLv3</a> | ||
8 | The RocketGit code is copyright (c) 2015 Catalin BOIE and it is | ||
9 | covered by the | ||
10 | <a href="https://gnu.org/licenses/agpl.html">Affero GPLv3</a> | ||
10 | 11 | license.<br /> | license.<br /> |
11 | 12 | <br /> | <br /> |
12 | 13 | ||
13 | The service offered by rocketgit.com site is covered by the | ||
14 | following terms:<br /> | ||
15 | |||
16 | - If you do not agree the terms, you cannot use our services | ||
17 | and will result in account termination.<br /> | ||
14 | The services offered by the rocketgit.com site are covered by the | ||
15 | terms below. If you do not agree with these terms, please do not use | ||
16 | this site or any of the services provided by it. By continuing to | ||
17 | use them, you agree to be bound by this terms.<br /> | ||
18 | <br > | ||
18 | 19 | ||
19 | 20 | - You must understand that we cannot review all content hosted here, | - You must understand that we cannot review all content hosted here, |
20 | 21 | therefore you agree to be exposed to any type of content. | therefore you agree to be exposed to any type of content. |
72 | 73 | - We may modify this document at any time. You are responsible to | - We may modify this document at any time. You are responsible to |
73 | 74 | check this document from time to time for changes.<br /> | check this document from time to time for changes.<br /> |
74 | 75 | ||
76 | - Disrespecting the terms above will result in account termination.<br /> | ||
77 | |||
75 | 78 | - You must enjoy your stay here.<br /> | - You must enjoy your stay here.<br /> |
76 | 79 | </div> | </div> |
77 | 80 | </div> | </div> |
File root/themes/default/user/settings/menu.html changed (mode: 100644) (index ca19265..bcb50e1) | |||
6 | 6 | <li@@if(@@set_menu::change_pass@@ == 1){{ class="selected"}}{{}}><a href="/op/settings/change_pass">Change password</a></li> | <li@@if(@@set_menu::change_pass@@ == 1){{ class="selected"}}{{}}><a href="/op/settings/change_pass">Change password</a></li> |
7 | 7 | <li@@if(@@set_menu::keys@@ == 1){{ class="selected"}}{{}}><a href="/op/settings/keys">SSH keys</a></li> | <li@@if(@@set_menu::keys@@ == 1){{ class="selected"}}{{}}><a href="/op/settings/keys">SSH keys</a></li> |
8 | 8 | <li@@if(@@set_menu::totp@@ == 1){{ class="selected"}}{{}}><a href="/op/settings/totp">Login tokens</a></li> | <li@@if(@@set_menu::totp@@ == 1){{ class="selected"}}{{}}><a href="/op/settings/totp">Login tokens</a></li> |
9 | <li@@if(@@set_menu::wh@@ == 1){{ class="selected"}}{{}}><a href="/op/settings/wh">Webhooks</a></li> | ||
9 | 10 | </ul> | </ul> |
10 | 11 | </div> | </div> |
File root/themes/default/user/settings/totp/delete_ok.html changed (mode: 100644) (index 03b636e..bb40ba1) | |||
1 | 1 | <div class="mess ok"> | <div class="mess ok"> |
2 | Login token deleted with success. | ||
2 | Login token(s) deleted with success. | ||
3 | 3 | </div> | </div> |
File root/themes/default/user/settings/wh/add_edit.html added (mode: 100644) (index 0000000..14233f0) | |||
1 | <div class="formarea"> | ||
2 | |||
3 | <div class="formarea_title">@@if(@@wh::id@@ == 0){{Add}}{{Edit}} a webhook</div> | ||
4 | |||
5 | @@errmsg@@ | ||
6 | |||
7 | <form method="post" action="/op/settings/wh/add"> | ||
8 | <input type="hidden" name="add" value="1" /> | ||
9 | <input type="hidden" name="token" value="@@rg_form_token@@" /> | ||
10 | |||
11 | <p> | ||
12 | <label for="url">URL (example: https://my_server_dot_com/hook.cgi; only http/https are supported)</label><br /> | ||
13 | <input type="text" name="wh::url" id="url" value="@@wh::url@@" /> | ||
14 | </p> | ||
15 | |||
16 | <p> | ||
17 | <label for="type">Type</label><br /> | ||
18 | @@select_type@@ | ||
19 | </p> | ||
20 | |||
21 | @@check_events@@ | ||
22 | |||
23 | @@check_flags@@ | ||
24 | |||
25 | <p> | ||
26 | <label for="description">Description</label><br /> | ||
27 | <textarea name="wh::description" id="description" rows="3" cols="80"> | ||
28 | @@wh::description@@ | ||
29 | </textarea> | ||
30 | </p> | ||
31 | |||
32 | <p> | ||
33 | <label for="client_cert">Optional concatenated certificate and key used to | ||
34 | authenticate us to the server (PEM format, no password)</label><br /> | ||
35 | <textarea name="wh::client_cert" id="client_cert" rows="3" cols="80"> | ||
36 | @@wh::client_cert@@ | ||
37 | </textarea> | ||
38 | </p> | ||
39 | |||
40 | <p> | ||
41 | <label for="client_ca_cert">Optional certificate(s) used to authenticate your server (PEM format, no password)</label><br /> | ||
42 | <textarea name="wh::client_ca_cert" id="client_ca_cert" rows="3" cols="80"> | ||
43 | @@wh::client_ca_cert@@ | ||
44 | </textarea> | ||
45 | </p> | ||
46 | |||
47 | <input type="submit" name="button" value="@@if(@@wh::id@@ == 0){{Add}}{{Edit}}" /> | ||
48 | |||
49 | </form> | ||
50 | </div> |
File root/themes/default/user/settings/wh/delete_ok.html added (mode: 100644) (index 0000000..f001c96) | |||
1 | <div class="mess ok"> | ||
2 | Webhook(s) deleted with success. | ||
3 | </div> |
File root/themes/default/user/settings/wh/edit_ok.html added (mode: 100644) (index 0000000..0b7043a) | |||
1 | <div class="mess ok"> | ||
2 | Webhook added/edited with success. | ||
3 | </div> |
File root/themes/default/user/settings/wh/hints.html added (mode: 100644) (index 0000000..22bb562) | |||
1 | Webhooks helps you to trigger some actions on your server when an event | ||
2 | happens with you repositories. |
File root/themes/default/user/settings/wh/list/footer.html copied from file root/themes/default/user/settings/totp/list/footer.html (similarity 100%) |
File root/themes/default/user/settings/wh/list/header.html added (mode: 100644) (index 0000000..1a91665) | |||
1 | <div class="rg_wh_list"> | ||
2 | |||
3 | @@errmsg@@ | ||
4 | |||
5 | <form method="post" action="/op/settings/wh/list"> | ||
6 | <input type="hidden" name="delete" value="1" /> | ||
7 | <input type="hidden" name="token" value="@@rg_form_token@@" /> | ||
8 | |||
9 | <table summary="webhooks"> | ||
10 | <tr> | ||
11 | <th>Select</th> | ||
12 | <th>Date (UTC)</th> | ||
13 | <th>Events</th> | ||
14 | <th>URL</th> | ||
15 | <th>Description</th> | ||
16 | <th>Client cert</th> | ||
17 | <th>CA cert</th> | ||
18 | <th>Type</th> | ||
19 | <th>Flags</th> | ||
20 | <th>Add IP</th> | ||
21 | </tr> |
File root/themes/default/user/settings/wh/list/line.html added (mode: 100644) (index 0000000..36181e6) | |||
1 | <tr> | ||
2 | <td><input type="checkbox" name="delete_list[@@id@@]" /></td> | ||
3 | <td>@@itime_nice@@</td> | ||
4 | <td>@@events_text@@</td> | ||
5 | <td>@@url@@</td> | ||
6 | <td>@@description@@</td> | ||
7 | <td>@@client_cert_short@@</td> | ||
8 | <td>@@client_ca_cert_short@@</td> | ||
9 | <td>@@type_text@@</td> | ||
10 | <td>@@flags_text@@</td> | ||
11 | <td>@@add_ip@@</td> | ||
12 | </tr> |
File root/themes/default/user/settings/wh/list/nodata.html copied from file root/themes/default/user/settings/totp/list/nodata.html (similarity 66%) (mode: 100644) (index 5c1aea8..8408cd3) | |||
1 | 1 | @@del_status@@ | @@del_status@@ |
2 | 2 | ||
3 | 3 | <div class="mess ok"> | <div class="mess ok"> |
4 | No login tokens found. | ||
4 | No webhooks present. | ||
5 | 5 | </div> | </div> |
File root/themes/default/user/settings/wh/list_err.html added (mode: 100644) (index 0000000..b3c9532) | |||
1 | <div class="mess error"> | ||
2 | Could not load webhooks (@@errmsg@@). Please try again later. | ||
3 | </div> |
File root/themes/default/user/settings/wh/menu.html added (mode: 100644) (index 0000000..2d75c30) | |||
1 | <div class="menu menu3"> | ||
2 | <ul> | ||
3 | <li@@if(@@menu::wh::list@@ == 1){{ class="selected"}}><a href="/op/settings/wh/list">List</a></li> | ||
4 | <li@@if(@@menu::wh::add@@ == 1){{ class="selected"}}><a href="/op/settings/wh/add">Add</a></li> | ||
5 | </ul> | ||
6 | </div> |
File scripts/cache.php changed (mode: 100644) (index a07bcab..21ba6b5) | |||
... | ... | do { | |
377 | 377 | rg_destroy($key, $conn_table); | rg_destroy($key, $conn_table); |
378 | 378 | } | } |
379 | 379 | ||
380 | rg_handle_idle($conn_table); | ||
380 | // TODO: if we activate this, we broke the connection with events.php | ||
381 | //rg_handle_idle($conn_table); | ||
381 | 382 | } while (1); | } while (1); |
382 | 383 | ||
383 | 384 | socket_close($master); | socket_close($master); |
File tests/.gitignore changed (mode: 100644) (index 8151b7c..a329ce5) | |||
... | ... | q_merge_requests | |
17 | 17 | qstats | qstats |
18 | 18 | git_bin | git_bin |
19 | 19 | keys/* | keys/* |
20 | *.pid | ||
21 | ca |
File tests/Makefile changed (mode: 100644) (index 0c7b822..6fb4e7c) | |||
1 | tests := ssh http_totp totp git_log1.sh \ | ||
1 | tests := wh ssh http_totp totp git_log1.sh \ | ||
2 | 2 | http_admin http_bug \ | http_admin http_bug \ |
3 | 3 | http_create_account http_login http_settings http_csrf http_top \ | http_create_account http_login http_settings http_csrf http_top \ |
4 | 4 | token util log state cache prof db event rights keys user repo git \ | token util log state cache prof db event rights keys user repo git \ |
... | ... | all: $(tests) | |
10 | 10 | @-ls -l err-* | @-ls -l err-* |
11 | 11 | @echo "Do not forget to check for errors in /var/log/rocketgit!" | @echo "Do not forget to check for errors in /var/log/rocketgit!" |
12 | 12 | ||
13 | wh: | ||
14 | php wh.php | ||
15 | |||
13 | 16 | ssh: | ssh: |
14 | 17 | php ssh.php | php ssh.php |
15 | 18 | ||
... | ... | git2: | |
95 | 98 | clean: | clean: |
96 | 99 | @rm -rf git_log1 *.log *.strace *.strace.* *.out *.lock err-* *.diff \ | @rm -rf git_log1 *.log *.strace *.strace.* *.out *.lock err-* *.diff \ |
97 | 100 | http.arond *.pub git2key git2 *.in q_merge_requests/mr-* \ | http.arond *.pub git2key git2 *.in q_merge_requests/mr-* \ |
98 | qstats/* repos/* helper helper.pub keys/* | ||
99 | |||
101 | qstats/* repos/* helper helper.pub keys/* ca *.pid |
File tests/ca.sh added (mode: 100755) (index 0000000..64ccaed) | |||
1 | #!/bin/bash | ||
2 | |||
3 | set -e | ||
4 | |||
5 | # Generates a CA | ||
6 | |||
7 | if [ -z "${1}" ]; then | ||
8 | echo "Usage: ca.sh name_of_the_ca" | ||
9 | exit 1 | ||
10 | fi | ||
11 | |||
12 | ca_conf=${PWD}/ca.conf | ||
13 | |||
14 | mkdir -p "ca/${1}" | ||
15 | cd "ca/${1}" | ||
16 | |||
17 | mkdir -p certs private csr | ||
18 | |||
19 | if [ ! -r private/cakey.pem ]; then | ||
20 | echo "Creating CA key..." | ||
21 | openssl genrsa -out private/cakey.pem 2048 | ||
22 | fi | ||
23 | |||
24 | if [ ! -r certs/cacert.pem ]; then | ||
25 | echo "Generating cert..." | ||
26 | openssl req -new -x509 \ | ||
27 | -days 3650 \ | ||
28 | -extensions v3_ca \ | ||
29 | -key private/cakey.pem \ | ||
30 | -out certs/cacert.pem \ | ||
31 | -subj "/C=XX/ST=XXX/L=XXX/O=XXX/CN=ca.example.com" | ||
32 | fi | ||
33 | |||
34 | for i in localhost client; do | ||
35 | if [ ! -r private/${i}.key ]; then | ||
36 | echo "Generating ${i} key..." | ||
37 | openssl genrsa -out private/${i}.key 2048 | ||
38 | fi | ||
39 | |||
40 | if [ ! -r csr/${i}.csr ]; then | ||
41 | echo "Generating ${i} csr..." | ||
42 | openssl req -new -key private/${i}.key -out csr/${i}.csr \ | ||
43 | -subj "/C=XX/ST=XXX/L=XXX/O=XXX/CN=${i}" | ||
44 | fi | ||
45 | |||
46 | if [ ! -r certs/${i}.pem ]; then | ||
47 | echo "Generating ${i} cert..." | ||
48 | openssl x509 -req -in csr/${i}.csr \ | ||
49 | -CA certs/cacert.pem \ | ||
50 | -CAkey private/cakey.pem \ | ||
51 | -CAcreateserial \ | ||
52 | -days 500 \ | ||
53 | -out certs/${i}.pem | ||
54 | fi | ||
55 | done | ||
56 | |||
57 | chmod -R 0600 private | ||
58 | |||
59 | echo "CA_SH_OK" |
File tests/config.php changed (mode: 100644) (index 6b47d20..1890788) | |||
... | ... | $rg_git_port = 9418; | |
36 | 36 | ||
37 | 37 | // For http testing | // For http testing |
38 | 38 | $test_url = "http://r1i:9000"; | $test_url = "http://r1i:9000"; |
39 | $rg_debug = 1; | ||
39 | 40 | ||
40 | 41 | ?> | ?> |
File tests/helpers.inc.php changed (mode: 100644) (index e17349f..6b03636) | |||
... | ... | function rg_test_create_repo($db, $rg_ui, &$extra) | |
123 | 123 | $new['license'] = 'GPL <xss>'; | $new['license'] = 'GPL <xss>'; |
124 | 124 | $_repo_id++; | $_repo_id++; |
125 | 125 | ||
126 | rg_log("Deleting repo " . $repo_id); | ||
126 | rg_log("Deleting repo " . $repo_id . "/" . $new['name']); | ||
127 | 127 | $sql = 'DELETE FROM repos WHERE repo_id = ' . $repo_id | $sql = 'DELETE FROM repos WHERE repo_id = ' . $repo_id |
128 | 128 | . ' OR name = \'' . $new['name'] . '\''; | . ' OR name = \'' . $new['name'] . '\''; |
129 | 129 | $res = rg_sql_query($db, $sql); | $res = rg_sql_query($db, $sql); |
... | ... | function rg_test_sc_generate($db, $rg_ui, $good_sid) | |
252 | 252 | return $sc; | return $sc; |
253 | 253 | } | } |
254 | 254 | ||
255 | /* | ||
256 | * Helper for adding a webhook | ||
257 | */ | ||
258 | function rg_test_wh_add_edit($db, $rg_ui, $good_sid, $extra) | ||
259 | { | ||
260 | global $test_url; | ||
261 | |||
262 | rg_log("Loading webhook add form..."); | ||
263 | $data = array(); | ||
264 | $headers = array("Cookie: sid=" . $good_sid); | ||
265 | $r = do_req($test_url . "/op/settings/wh/add", $data, $headers); | ||
266 | if ($r === FALSE) { | ||
267 | rg_log("Cannot load form!"); | ||
268 | exit(1); | ||
269 | } | ||
270 | if (empty($r['tokens']['wh_add'])) { | ||
271 | rg_log_ml("token not found! r:" . print_r($r, TRUE)); | ||
272 | exit(1); | ||
273 | } | ||
274 | |||
275 | rg_log("Adding webhook..."); | ||
276 | $data = array('add' => 1, 'token' => $r['tokens']['wh_add']); | ||
277 | $data = array_merge($data, $extra); | ||
278 | $headers = array('Cookie: sid=' . $good_sid); | ||
279 | $r = do_req($test_url . '/op/settings/wh/add', $data, $headers); | ||
280 | if ($r === FALSE) { | ||
281 | rg_log_ml("Cannot add webhook: " . print_r($r, TRUE)); | ||
282 | exit(1); | ||
283 | } | ||
284 | |||
285 | if (!strstr($r['body'], 'with success')) { | ||
286 | rg_log_ml("Cannot add webhook (no success message): " . print_r($r, TRUE)); | ||
287 | exit(1); | ||
288 | } | ||
289 | } | ||
290 | |||
255 | 291 | ?> | ?> |
File tests/http.inc.php changed (mode: 100644) (index e6c9857..94ba37a) | |||
... | ... | function do_req($url, &$data, &$headers) | |
13 | 13 | if (!is_array($data)) | if (!is_array($data)) |
14 | 14 | $data = array(); | $data = array(); |
15 | 15 | ||
16 | $data['rg_rebug'] = 1; | ||
17 | |||
16 | 18 | if (!is_array($headers)) { | if (!is_array($headers)) { |
17 | 19 | rg_log("Headers is not an array, reset it."); | rg_log("Headers is not an array, reset it."); |
18 | 20 | $headers = array(); | $headers = array(); |
File tests/wh-helper.sh added (mode: 100755) (index 0000000..9bfb8e9) | |||
1 | #!/bin/bash | ||
2 | |||
3 | echo "HTTP/1.1 200 OK" | ||
4 | echo "Content-Length: 3" | ||
5 | echo "" | ||
6 | echo -n "OK!" |
File tests/wh-stunnel.conf added (mode: 100644) (index 0000000..5555be0) | |||
1 | debug = 5 | ||
2 | log = overwrite | ||
3 | CAfile = ca/wh/certs/cacert.pem | ||
4 | cert = ca/wh/certs/localhost.pem | ||
5 | key = ca/wh/private/localhost.key | ||
6 | output = wh-stunnel.log | ||
7 | foreground = yes | ||
8 | exec = ./wh-helper.sh | ||
9 | syslog = no | ||
10 | socket = a:SO_REUSEADDR=yes | ||
11 | |||
12 | [me] | ||
13 | accept = 127.0.0.1:64000 | ||
14 | verify = 2 |
File tests/wh-test.sh added (mode: 100755) (index 0000000..dd7636a) | |||
1 | #!/bin/bash | ||
2 | |||
3 | curl \ | ||
4 | --verbose \ | ||
5 | --cacert ca/wh/certs/cacert.pem \ | ||
6 | --cert ca/wh/certs/client.pem \ | ||
7 | --key ca/wh/private/client.key \ | ||
8 | https://localhost:64000 \ | ||
9 | -d a=1 |
File tests/wh.php added (mode: 100644) (index 0000000..cab3d90) | |||
1 | <?php | ||
2 | error_reporting(E_ALL | E_STRICT); | ||
3 | ini_set("track_errors", "On"); | ||
4 | |||
5 | $INC = dirname(__FILE__) . "/../inc"; | ||
6 | require_once(dirname(__FILE__) . "/config.php"); | ||
7 | require_once($INC . "/init.inc.php"); | ||
8 | require_once($INC . "/user.inc.php"); | ||
9 | require_once("helpers.inc.php"); | ||
10 | require_once("http.inc.php"); | ||
11 | |||
12 | rg_log_set_file("wh.log"); | ||
13 | |||
14 | $rg_sql = "host=localhost user=rocketgit dbname=rocketgit connect_timeout=10"; | ||
15 | $rg_no_db = TRUE; | ||
16 | require_once("common.php"); | ||
17 | |||
18 | $_testns = 'ssh'; | ||
19 | $rg_cache_enable = TRUE; | ||
20 | $rg_cache_debug = TRUE; | ||
21 | $rg_event_socket = "/var/lib/rocketgit/sockets/event.sock"; | ||
22 | $port = 64000; | ||
23 | |||
24 | |||
25 | function clean($pid) | ||
26 | { | ||
27 | rg_log("Killing pid $pid..."); | ||
28 | $r = posix_kill($pid, SIGQUIT); | ||
29 | if ($r === FALSE) | ||
30 | rg_log('Fail to kill!'); | ||
31 | |||
32 | system('fuser -k wh-stunnel.log'); | ||
33 | } | ||
34 | |||
35 | |||
36 | rg_log(''); | ||
37 | rg_log('Generating certificates...'); | ||
38 | $r = shell_exec('./ca.sh wh'); | ||
39 | if (!strstr($r, 'CA_SH_OK')) { | ||
40 | rg_log_ml('r: ' . print_r($r, TRUE)); | ||
41 | rg_log('Cannot generate certificates!'); | ||
42 | exit(1); | ||
43 | } | ||
44 | |||
45 | |||
46 | rg_log(''); | ||
47 | rg_log('Starting stunnel1...'); | ||
48 | $pid = pcntl_fork(); | ||
49 | if ($pid == -1) { | ||
50 | rg_log('Cannot fork1'); | ||
51 | exit(1); | ||
52 | } | ||
53 | if ($pid == 0) { //child | ||
54 | $r = exec('stunnel wh-stunnel.conf 2>/dev/null'); | ||
55 | exit(0); | ||
56 | } | ||
57 | register_shutdown_function('clean', $pid); | ||
58 | |||
59 | |||
60 | rg_log(''); | ||
61 | rg_log("Creating a user..."); | ||
62 | rg_test_create_user($db, $rg_ui); | ||
63 | $key = 'DEBUG::webhooks::' . $rg_ui['uid']; | ||
64 | |||
65 | |||
66 | rg_log(''); | ||
67 | rg_log('Login...'); | ||
68 | $r = test_login($test_url, $rg_ui, $good_sid); | ||
69 | if ($r === FALSE) { | ||
70 | rg_log("Cannot login!"); | ||
71 | exit(1); | ||
72 | } | ||
73 | |||
74 | |||
75 | rg_log(''); | ||
76 | rg_log('Registering webhook1...'); | ||
77 | $extra = array('wh::url' => 'https://localhost:' . $port . '/wh.html', | ||
78 | 'wh::type' => 0, | ||
79 | 'wh::events[C]' => 'on', | ||
80 | 'wh::events[P]' => 'on', | ||
81 | 'wh::events[B]' => 'on', | ||
82 | 'wh::description' => 'description1 <xss>', | ||
83 | 'wh::client_cert' => '', | ||
84 | 'wh::client_ca_cert' => file_get_contents('ca/wh/certs/cacert.pem') | ||
85 | ); | ||
86 | rg_test_wh_add_edit($db, $rg_ui, $good_sid, $extra); | ||
87 | |||
88 | |||
89 | rg_log(''); | ||
90 | rg_log('Registering webhook2...'); | ||
91 | $extra = array('wh::url' => 'https://localhost:' . $port . '/wh.html', | ||
92 | 'wh::type' => 0, | ||
93 | 'wh::events[C]' => 'on', | ||
94 | 'wh::events[P]' => 'on', | ||
95 | 'wh::events[B]' => 'on', | ||
96 | 'wh::description' => 'description <xss>', | ||
97 | 'wh::client_cert' => file_get_contents('ca/wh/certs/client.pem') | ||
98 | . file_get_contents('ca/wh/private/client.key'), | ||
99 | 'wh::client_ca_cert' => file_get_contents('ca/wh/certs/cacert.pem') | ||
100 | ); | ||
101 | rg_test_wh_add_edit($db, $rg_ui, $good_sid, $extra); | ||
102 | |||
103 | |||
104 | rg_log('Finding out the ids...'); | ||
105 | for ($i = 0; $i < 10; $i++) { | ||
106 | $r = rg_cache_get('user::' . $rg_ui['uid'] . '::wh'); | ||
107 | if ($r !== FALSE) | ||
108 | break; | ||
109 | sleep(1); | ||
110 | } | ||
111 | if ($r === FALSE) { | ||
112 | rg_log('Cannot get id from cache'); | ||
113 | exit(1); | ||
114 | } | ||
115 | rg_log_ml('r=' . print_r($r, TRUE)); | ||
116 | $t = array_keys($r); | ||
117 | $wh_id1 = $t[0]; | ||
118 | $wh_id2 = $t[1]; | ||
119 | rg_log('wh_id1=' . $wh_id1); | ||
120 | rg_log('wh_id2=' . $wh_id2); | ||
121 | |||
122 | |||
123 | rg_log(''); | ||
124 | rg_log('Creating a repo and waiting for trigger'); | ||
125 | rg_log("rg_debug=$rg_debug."); | ||
126 | $repo = array(); | ||
127 | rg_test_create_repo($db, $rg_ui, $repo); | ||
128 | |||
129 | |||
130 | rg_log(''); | ||
131 | rg_log('Testing if the curl posted with success'); | ||
132 | for ($i = 0; $i < 10; $i++) { | ||
133 | $r = rg_cache_get($key. '::' . $wh_id1); | ||
134 | rg_log_ml('cache: ' . $r); | ||
135 | if ($r !== FALSE) | ||
136 | break; | ||
137 | sleep(1); | ||
138 | } | ||
139 | if ($r === FALSE) { | ||
140 | rg_log('Seems the event does not set the cache!'); | ||
141 | exit(1); | ||
142 | } | ||
143 | if (strcmp($r, "BAD") != 0) { | ||
144 | rg_log('Seems the webhook executed correctly without client cert!'); | ||
145 | exit(1); | ||
146 | } | ||
147 | |||
148 | |||
149 | rg_log(''); | ||
150 | rg_log('Testing if the curl posted with success'); | ||
151 | for ($i = 0; $i < 10; $i++) { | ||
152 | $r = rg_cache_get($key. '::' . $wh_id2); | ||
153 | if ($r !== FALSE) | ||
154 | break; | ||
155 | rg_log_ml('cache: ' . print_r($r, TRUE)); | ||
156 | sleep(1); | ||
157 | } | ||
158 | if (strcmp($r, "OK") != 0) { | ||
159 | rg_log('Seems the webhook did not returned success!'); | ||
160 | exit(1); | ||
161 | } | ||
162 | |||
163 | |||
164 | rg_log(''); | ||
165 | rg_log('Testing the edit of webhook1...'); | ||
166 | $extra = array('wh::url' => 'https://localhost:' . $port . '/wh.html', | ||
167 | 'wh::id' => $wh_id1, | ||
168 | 'wh::type' => 1, | ||
169 | 'wh::flags[I]' => 'on', | ||
170 | 'wh::events[C]' => 'on', | ||
171 | 'wh::events[B]' => 'on', | ||
172 | 'wh::description' => 'desc2', | ||
173 | 'wh::client_cert' => 'abc', | ||
174 | 'wh::client_ca_cert' => 'zzz' | ||
175 | ); | ||
176 | rg_test_wh_add_edit($db, $rg_ui, $good_sid, $extra); | ||
177 | $sql = "SELECT * FROM webhooks WHERE uid = " . $rg_ui['uid'] | ||
178 | . " AND id = " . $wh_id1; | ||
179 | $res = rg_sql_query($db, $sql); | ||
180 | $row = rg_sql_fetch_array($res); | ||
181 | rg_sql_free_result($res); | ||
182 | $key1 = 'user' . '::' . $rg_ui['uid'] . '::' . 'wh' . '::' . $wh_id1; | ||
183 | rg_cache_core_unset($key1); // else we will get previous copy! | ||
184 | $c = rg_cache_get($key1); | ||
185 | $list = array('flags' => 'I', 'events' => 'CB', 'type' => '1', | ||
186 | 'description' => 'desc2', 'client_cert' => 'abc', | ||
187 | 'client_ca_cert' => 'zzz'); | ||
188 | foreach ($list as $k => $v) { | ||
189 | if (strcmp($row[$k], $v) != 0) { | ||
190 | rg_log_ml('row: ' . print_r($row, TRUE)); | ||
191 | rg_log("db: Seems that $k was not updated [" . $row[$k] . "] != " . $v); | ||
192 | exit(1); | ||
193 | } | ||
194 | |||
195 | if (strcmp($c[$k], $v) != 0) { | ||
196 | rg_log_ml('c: ' . print_r($c, TRUE)); | ||
197 | rg_log("cache: Seems that $k was not updated [" . $c[$k] . "] != " . $v); | ||
198 | exit(1); | ||
199 | } | ||
200 | } | ||
201 | |||
202 | |||
203 | rg_log(''); | ||
204 | rg_log_enter('Testing the delete - loading form...'); | ||
205 | $data = array(); | ||
206 | $headers = array("Cookie: sid=" . $good_sid); | ||
207 | $r = do_req($test_url . "/op/settings/wh/list", $data, $headers); | ||
208 | if ($r === FALSE) { | ||
209 | rg_log("Cannot load list form."); | ||
210 | exit(1); | ||
211 | } | ||
212 | if (!isset($r['tokens']['wh_list'])) { | ||
213 | rg_log_ml('tokens: ' . print_r($r['tokens'], TRUE)); | ||
214 | rg_log('Cannot find wh_list token!'); | ||
215 | exit(1); | ||
216 | } | ||
217 | $good_token = $r['tokens']['wh_list']; | ||
218 | $data = array( 'delete' => 1, | ||
219 | 'token' => $good_token, | ||
220 | 'delete_list[' . $wh_id1 . ']' => 'on'); | ||
221 | $r = do_req($test_url . "/op/settings/wh/list", $data, $headers); | ||
222 | if (!strstr($r['body'], 'deleted with success')) { | ||
223 | rg_log_ml('r: ' . print_r($r, TRUE)); | ||
224 | rg_log("Cannot delete webhook!"); | ||
225 | exit(1); | ||
226 | } | ||
227 | $sql = "SELECT id FROM webhooks WHERE id = " . $wh_id1; | ||
228 | $res = rg_sql_query($db, $sql); | ||
229 | $rows = rg_sql_num_rows($res); | ||
230 | rg_sql_free_result($res); | ||
231 | if ($rows != 0) { | ||
232 | rg_log("Cannot delete webhook - sql still returns data!"); | ||
233 | exit(1); | ||
234 | } | ||
235 | $key = 'user::' . $rg_ui['uid'] . '::wh::' . $wh_id1; | ||
236 | rg_cache_core_unset($key); // else we will get data from local mem! | ||
237 | $r = rg_cache_get($key); | ||
238 | if (strcmp($r, '') != 0) { | ||
239 | rg_log_ml($key . ': ' . print_r($r, TRUE)); | ||
240 | rg_log('Deleted webhooks are still in cache!'); | ||
241 | exit(1); | ||
242 | } | ||
243 | rg_log_exit(); | ||
244 | |||
245 | |||
246 | rg_log("OK!"); | ||
247 | ?> |