##// END OF EJS Templates
repository-permissions: enable shortcut to set private mode in permission page.
ergo -
r3809:d49b6555 stable
parent child Browse files
Show More
@@ -1,500 +1,504 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 from rhodecode.apps._base import add_route_with_slash
20 from rhodecode.apps._base import add_route_with_slash
21
21
22
22
23 def includeme(config):
23 def includeme(config):
24
24
25 # repo creating checks, special cases that aren't repo routes
25 # repo creating checks, special cases that aren't repo routes
26 config.add_route(
26 config.add_route(
27 name='repo_creating',
27 name='repo_creating',
28 pattern='/{repo_name:.*?[^/]}/repo_creating')
28 pattern='/{repo_name:.*?[^/]}/repo_creating')
29
29
30 config.add_route(
30 config.add_route(
31 name='repo_creating_check',
31 name='repo_creating_check',
32 pattern='/{repo_name:.*?[^/]}/repo_creating_check')
32 pattern='/{repo_name:.*?[^/]}/repo_creating_check')
33
33
34 # Summary
34 # Summary
35 # NOTE(marcink): one additional route is defined in very bottom, catch
35 # NOTE(marcink): one additional route is defined in very bottom, catch
36 # all pattern
36 # all pattern
37 config.add_route(
37 config.add_route(
38 name='repo_summary_explicit',
38 name='repo_summary_explicit',
39 pattern='/{repo_name:.*?[^/]}/summary', repo_route=True)
39 pattern='/{repo_name:.*?[^/]}/summary', repo_route=True)
40 config.add_route(
40 config.add_route(
41 name='repo_summary_commits',
41 name='repo_summary_commits',
42 pattern='/{repo_name:.*?[^/]}/summary-commits', repo_route=True)
42 pattern='/{repo_name:.*?[^/]}/summary-commits', repo_route=True)
43
43
44 # Commits
44 # Commits
45 config.add_route(
45 config.add_route(
46 name='repo_commit',
46 name='repo_commit',
47 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}', repo_route=True)
47 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}', repo_route=True)
48
48
49 config.add_route(
49 config.add_route(
50 name='repo_commit_children',
50 name='repo_commit_children',
51 pattern='/{repo_name:.*?[^/]}/changeset_children/{commit_id}', repo_route=True)
51 pattern='/{repo_name:.*?[^/]}/changeset_children/{commit_id}', repo_route=True)
52
52
53 config.add_route(
53 config.add_route(
54 name='repo_commit_parents',
54 name='repo_commit_parents',
55 pattern='/{repo_name:.*?[^/]}/changeset_parents/{commit_id}', repo_route=True)
55 pattern='/{repo_name:.*?[^/]}/changeset_parents/{commit_id}', repo_route=True)
56
56
57 config.add_route(
57 config.add_route(
58 name='repo_commit_raw',
58 name='repo_commit_raw',
59 pattern='/{repo_name:.*?[^/]}/changeset-diff/{commit_id}', repo_route=True)
59 pattern='/{repo_name:.*?[^/]}/changeset-diff/{commit_id}', repo_route=True)
60
60
61 config.add_route(
61 config.add_route(
62 name='repo_commit_patch',
62 name='repo_commit_patch',
63 pattern='/{repo_name:.*?[^/]}/changeset-patch/{commit_id}', repo_route=True)
63 pattern='/{repo_name:.*?[^/]}/changeset-patch/{commit_id}', repo_route=True)
64
64
65 config.add_route(
65 config.add_route(
66 name='repo_commit_download',
66 name='repo_commit_download',
67 pattern='/{repo_name:.*?[^/]}/changeset-download/{commit_id}', repo_route=True)
67 pattern='/{repo_name:.*?[^/]}/changeset-download/{commit_id}', repo_route=True)
68
68
69 config.add_route(
69 config.add_route(
70 name='repo_commit_data',
70 name='repo_commit_data',
71 pattern='/{repo_name:.*?[^/]}/changeset-data/{commit_id}', repo_route=True)
71 pattern='/{repo_name:.*?[^/]}/changeset-data/{commit_id}', repo_route=True)
72
72
73 config.add_route(
73 config.add_route(
74 name='repo_commit_comment_create',
74 name='repo_commit_comment_create',
75 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/create', repo_route=True)
75 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/create', repo_route=True)
76
76
77 config.add_route(
77 config.add_route(
78 name='repo_commit_comment_preview',
78 name='repo_commit_comment_preview',
79 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/preview', repo_route=True)
79 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/preview', repo_route=True)
80
80
81 config.add_route(
81 config.add_route(
82 name='repo_commit_comment_delete',
82 name='repo_commit_comment_delete',
83 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/{comment_id}/delete', repo_route=True)
83 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}/comment/{comment_id}/delete', repo_route=True)
84
84
85 # still working url for backward compat.
85 # still working url for backward compat.
86 config.add_route(
86 config.add_route(
87 name='repo_commit_raw_deprecated',
87 name='repo_commit_raw_deprecated',
88 pattern='/{repo_name:.*?[^/]}/raw-changeset/{commit_id}', repo_route=True)
88 pattern='/{repo_name:.*?[^/]}/raw-changeset/{commit_id}', repo_route=True)
89
89
90 # Files
90 # Files
91 config.add_route(
91 config.add_route(
92 name='repo_archivefile',
92 name='repo_archivefile',
93 pattern='/{repo_name:.*?[^/]}/archive/{fname:.*}', repo_route=True)
93 pattern='/{repo_name:.*?[^/]}/archive/{fname:.*}', repo_route=True)
94
94
95 config.add_route(
95 config.add_route(
96 name='repo_files_diff',
96 name='repo_files_diff',
97 pattern='/{repo_name:.*?[^/]}/diff/{f_path:.*}', repo_route=True)
97 pattern='/{repo_name:.*?[^/]}/diff/{f_path:.*}', repo_route=True)
98 config.add_route( # legacy route to make old links work
98 config.add_route( # legacy route to make old links work
99 name='repo_files_diff_2way_redirect',
99 name='repo_files_diff_2way_redirect',
100 pattern='/{repo_name:.*?[^/]}/diff-2way/{f_path:.*}', repo_route=True)
100 pattern='/{repo_name:.*?[^/]}/diff-2way/{f_path:.*}', repo_route=True)
101
101
102 config.add_route(
102 config.add_route(
103 name='repo_files',
103 name='repo_files',
104 pattern='/{repo_name:.*?[^/]}/files/{commit_id}/{f_path:.*}', repo_route=True)
104 pattern='/{repo_name:.*?[^/]}/files/{commit_id}/{f_path:.*}', repo_route=True)
105 config.add_route(
105 config.add_route(
106 name='repo_files:default_path',
106 name='repo_files:default_path',
107 pattern='/{repo_name:.*?[^/]}/files/{commit_id}/', repo_route=True)
107 pattern='/{repo_name:.*?[^/]}/files/{commit_id}/', repo_route=True)
108 config.add_route(
108 config.add_route(
109 name='repo_files:default_commit',
109 name='repo_files:default_commit',
110 pattern='/{repo_name:.*?[^/]}/files', repo_route=True)
110 pattern='/{repo_name:.*?[^/]}/files', repo_route=True)
111
111
112 config.add_route(
112 config.add_route(
113 name='repo_files:rendered',
113 name='repo_files:rendered',
114 pattern='/{repo_name:.*?[^/]}/render/{commit_id}/{f_path:.*}', repo_route=True)
114 pattern='/{repo_name:.*?[^/]}/render/{commit_id}/{f_path:.*}', repo_route=True)
115
115
116 config.add_route(
116 config.add_route(
117 name='repo_files:annotated',
117 name='repo_files:annotated',
118 pattern='/{repo_name:.*?[^/]}/annotate/{commit_id}/{f_path:.*}', repo_route=True)
118 pattern='/{repo_name:.*?[^/]}/annotate/{commit_id}/{f_path:.*}', repo_route=True)
119 config.add_route(
119 config.add_route(
120 name='repo_files:annotated_previous',
120 name='repo_files:annotated_previous',
121 pattern='/{repo_name:.*?[^/]}/annotate-previous/{commit_id}/{f_path:.*}', repo_route=True)
121 pattern='/{repo_name:.*?[^/]}/annotate-previous/{commit_id}/{f_path:.*}', repo_route=True)
122
122
123 config.add_route(
123 config.add_route(
124 name='repo_nodetree_full',
124 name='repo_nodetree_full',
125 pattern='/{repo_name:.*?[^/]}/nodetree_full/{commit_id}/{f_path:.*}', repo_route=True)
125 pattern='/{repo_name:.*?[^/]}/nodetree_full/{commit_id}/{f_path:.*}', repo_route=True)
126 config.add_route(
126 config.add_route(
127 name='repo_nodetree_full:default_path',
127 name='repo_nodetree_full:default_path',
128 pattern='/{repo_name:.*?[^/]}/nodetree_full/{commit_id}/', repo_route=True)
128 pattern='/{repo_name:.*?[^/]}/nodetree_full/{commit_id}/', repo_route=True)
129
129
130 config.add_route(
130 config.add_route(
131 name='repo_files_nodelist',
131 name='repo_files_nodelist',
132 pattern='/{repo_name:.*?[^/]}/nodelist/{commit_id}/{f_path:.*}', repo_route=True)
132 pattern='/{repo_name:.*?[^/]}/nodelist/{commit_id}/{f_path:.*}', repo_route=True)
133
133
134 config.add_route(
134 config.add_route(
135 name='repo_file_raw',
135 name='repo_file_raw',
136 pattern='/{repo_name:.*?[^/]}/raw/{commit_id}/{f_path:.*}', repo_route=True)
136 pattern='/{repo_name:.*?[^/]}/raw/{commit_id}/{f_path:.*}', repo_route=True)
137
137
138 config.add_route(
138 config.add_route(
139 name='repo_file_download',
139 name='repo_file_download',
140 pattern='/{repo_name:.*?[^/]}/download/{commit_id}/{f_path:.*}', repo_route=True)
140 pattern='/{repo_name:.*?[^/]}/download/{commit_id}/{f_path:.*}', repo_route=True)
141 config.add_route( # backward compat to keep old links working
141 config.add_route( # backward compat to keep old links working
142 name='repo_file_download:legacy',
142 name='repo_file_download:legacy',
143 pattern='/{repo_name:.*?[^/]}/rawfile/{commit_id}/{f_path:.*}',
143 pattern='/{repo_name:.*?[^/]}/rawfile/{commit_id}/{f_path:.*}',
144 repo_route=True)
144 repo_route=True)
145
145
146 config.add_route(
146 config.add_route(
147 name='repo_file_history',
147 name='repo_file_history',
148 pattern='/{repo_name:.*?[^/]}/history/{commit_id}/{f_path:.*}', repo_route=True)
148 pattern='/{repo_name:.*?[^/]}/history/{commit_id}/{f_path:.*}', repo_route=True)
149
149
150 config.add_route(
150 config.add_route(
151 name='repo_file_authors',
151 name='repo_file_authors',
152 pattern='/{repo_name:.*?[^/]}/authors/{commit_id}/{f_path:.*}', repo_route=True)
152 pattern='/{repo_name:.*?[^/]}/authors/{commit_id}/{f_path:.*}', repo_route=True)
153
153
154 config.add_route(
154 config.add_route(
155 name='repo_files_remove_file',
155 name='repo_files_remove_file',
156 pattern='/{repo_name:.*?[^/]}/remove_file/{commit_id}/{f_path:.*}',
156 pattern='/{repo_name:.*?[^/]}/remove_file/{commit_id}/{f_path:.*}',
157 repo_route=True)
157 repo_route=True)
158 config.add_route(
158 config.add_route(
159 name='repo_files_delete_file',
159 name='repo_files_delete_file',
160 pattern='/{repo_name:.*?[^/]}/delete_file/{commit_id}/{f_path:.*}',
160 pattern='/{repo_name:.*?[^/]}/delete_file/{commit_id}/{f_path:.*}',
161 repo_route=True)
161 repo_route=True)
162 config.add_route(
162 config.add_route(
163 name='repo_files_edit_file',
163 name='repo_files_edit_file',
164 pattern='/{repo_name:.*?[^/]}/edit_file/{commit_id}/{f_path:.*}',
164 pattern='/{repo_name:.*?[^/]}/edit_file/{commit_id}/{f_path:.*}',
165 repo_route=True)
165 repo_route=True)
166 config.add_route(
166 config.add_route(
167 name='repo_files_update_file',
167 name='repo_files_update_file',
168 pattern='/{repo_name:.*?[^/]}/update_file/{commit_id}/{f_path:.*}',
168 pattern='/{repo_name:.*?[^/]}/update_file/{commit_id}/{f_path:.*}',
169 repo_route=True)
169 repo_route=True)
170 config.add_route(
170 config.add_route(
171 name='repo_files_add_file',
171 name='repo_files_add_file',
172 pattern='/{repo_name:.*?[^/]}/add_file/{commit_id}/{f_path:.*}',
172 pattern='/{repo_name:.*?[^/]}/add_file/{commit_id}/{f_path:.*}',
173 repo_route=True)
173 repo_route=True)
174 config.add_route(
174 config.add_route(
175 name='repo_files_upload_file',
175 name='repo_files_upload_file',
176 pattern='/{repo_name:.*?[^/]}/upload_file/{commit_id}/{f_path:.*}',
176 pattern='/{repo_name:.*?[^/]}/upload_file/{commit_id}/{f_path:.*}',
177 repo_route=True)
177 repo_route=True)
178 config.add_route(
178 config.add_route(
179 name='repo_files_create_file',
179 name='repo_files_create_file',
180 pattern='/{repo_name:.*?[^/]}/create_file/{commit_id}/{f_path:.*}',
180 pattern='/{repo_name:.*?[^/]}/create_file/{commit_id}/{f_path:.*}',
181 repo_route=True)
181 repo_route=True)
182
182
183 # Refs data
183 # Refs data
184 config.add_route(
184 config.add_route(
185 name='repo_refs_data',
185 name='repo_refs_data',
186 pattern='/{repo_name:.*?[^/]}/refs-data', repo_route=True)
186 pattern='/{repo_name:.*?[^/]}/refs-data', repo_route=True)
187
187
188 config.add_route(
188 config.add_route(
189 name='repo_refs_changelog_data',
189 name='repo_refs_changelog_data',
190 pattern='/{repo_name:.*?[^/]}/refs-data-changelog', repo_route=True)
190 pattern='/{repo_name:.*?[^/]}/refs-data-changelog', repo_route=True)
191
191
192 config.add_route(
192 config.add_route(
193 name='repo_stats',
193 name='repo_stats',
194 pattern='/{repo_name:.*?[^/]}/repo_stats/{commit_id}', repo_route=True)
194 pattern='/{repo_name:.*?[^/]}/repo_stats/{commit_id}', repo_route=True)
195
195
196 # Commits
196 # Commits
197 config.add_route(
197 config.add_route(
198 name='repo_commits',
198 name='repo_commits',
199 pattern='/{repo_name:.*?[^/]}/commits', repo_route=True)
199 pattern='/{repo_name:.*?[^/]}/commits', repo_route=True)
200 config.add_route(
200 config.add_route(
201 name='repo_commits_file',
201 name='repo_commits_file',
202 pattern='/{repo_name:.*?[^/]}/commits/{commit_id}/{f_path:.*}', repo_route=True)
202 pattern='/{repo_name:.*?[^/]}/commits/{commit_id}/{f_path:.*}', repo_route=True)
203 config.add_route(
203 config.add_route(
204 name='repo_commits_elements',
204 name='repo_commits_elements',
205 pattern='/{repo_name:.*?[^/]}/commits_elements', repo_route=True)
205 pattern='/{repo_name:.*?[^/]}/commits_elements', repo_route=True)
206 config.add_route(
206 config.add_route(
207 name='repo_commits_elements_file',
207 name='repo_commits_elements_file',
208 pattern='/{repo_name:.*?[^/]}/commits_elements/{commit_id}/{f_path:.*}', repo_route=True)
208 pattern='/{repo_name:.*?[^/]}/commits_elements/{commit_id}/{f_path:.*}', repo_route=True)
209
209
210 # Changelog (old deprecated name for commits page)
210 # Changelog (old deprecated name for commits page)
211 config.add_route(
211 config.add_route(
212 name='repo_changelog',
212 name='repo_changelog',
213 pattern='/{repo_name:.*?[^/]}/changelog', repo_route=True)
213 pattern='/{repo_name:.*?[^/]}/changelog', repo_route=True)
214 config.add_route(
214 config.add_route(
215 name='repo_changelog_file',
215 name='repo_changelog_file',
216 pattern='/{repo_name:.*?[^/]}/changelog/{commit_id}/{f_path:.*}', repo_route=True)
216 pattern='/{repo_name:.*?[^/]}/changelog/{commit_id}/{f_path:.*}', repo_route=True)
217
217
218 # Compare
218 # Compare
219 config.add_route(
219 config.add_route(
220 name='repo_compare_select',
220 name='repo_compare_select',
221 pattern='/{repo_name:.*?[^/]}/compare', repo_route=True)
221 pattern='/{repo_name:.*?[^/]}/compare', repo_route=True)
222
222
223 config.add_route(
223 config.add_route(
224 name='repo_compare',
224 name='repo_compare',
225 pattern='/{repo_name:.*?[^/]}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}', repo_route=True)
225 pattern='/{repo_name:.*?[^/]}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}', repo_route=True)
226
226
227 # Tags
227 # Tags
228 config.add_route(
228 config.add_route(
229 name='tags_home',
229 name='tags_home',
230 pattern='/{repo_name:.*?[^/]}/tags', repo_route=True)
230 pattern='/{repo_name:.*?[^/]}/tags', repo_route=True)
231
231
232 # Branches
232 # Branches
233 config.add_route(
233 config.add_route(
234 name='branches_home',
234 name='branches_home',
235 pattern='/{repo_name:.*?[^/]}/branches', repo_route=True)
235 pattern='/{repo_name:.*?[^/]}/branches', repo_route=True)
236
236
237 # Bookmarks
237 # Bookmarks
238 config.add_route(
238 config.add_route(
239 name='bookmarks_home',
239 name='bookmarks_home',
240 pattern='/{repo_name:.*?[^/]}/bookmarks', repo_route=True)
240 pattern='/{repo_name:.*?[^/]}/bookmarks', repo_route=True)
241
241
242 # Forks
242 # Forks
243 config.add_route(
243 config.add_route(
244 name='repo_fork_new',
244 name='repo_fork_new',
245 pattern='/{repo_name:.*?[^/]}/fork', repo_route=True,
245 pattern='/{repo_name:.*?[^/]}/fork', repo_route=True,
246 repo_forbid_when_archived=True,
246 repo_forbid_when_archived=True,
247 repo_accepted_types=['hg', 'git'])
247 repo_accepted_types=['hg', 'git'])
248
248
249 config.add_route(
249 config.add_route(
250 name='repo_fork_create',
250 name='repo_fork_create',
251 pattern='/{repo_name:.*?[^/]}/fork/create', repo_route=True,
251 pattern='/{repo_name:.*?[^/]}/fork/create', repo_route=True,
252 repo_forbid_when_archived=True,
252 repo_forbid_when_archived=True,
253 repo_accepted_types=['hg', 'git'])
253 repo_accepted_types=['hg', 'git'])
254
254
255 config.add_route(
255 config.add_route(
256 name='repo_forks_show_all',
256 name='repo_forks_show_all',
257 pattern='/{repo_name:.*?[^/]}/forks', repo_route=True,
257 pattern='/{repo_name:.*?[^/]}/forks', repo_route=True,
258 repo_accepted_types=['hg', 'git'])
258 repo_accepted_types=['hg', 'git'])
259 config.add_route(
259 config.add_route(
260 name='repo_forks_data',
260 name='repo_forks_data',
261 pattern='/{repo_name:.*?[^/]}/forks/data', repo_route=True,
261 pattern='/{repo_name:.*?[^/]}/forks/data', repo_route=True,
262 repo_accepted_types=['hg', 'git'])
262 repo_accepted_types=['hg', 'git'])
263
263
264 # Pull Requests
264 # Pull Requests
265 config.add_route(
265 config.add_route(
266 name='pullrequest_show',
266 name='pullrequest_show',
267 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}',
267 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}',
268 repo_route=True)
268 repo_route=True)
269
269
270 config.add_route(
270 config.add_route(
271 name='pullrequest_show_all',
271 name='pullrequest_show_all',
272 pattern='/{repo_name:.*?[^/]}/pull-request',
272 pattern='/{repo_name:.*?[^/]}/pull-request',
273 repo_route=True, repo_accepted_types=['hg', 'git'])
273 repo_route=True, repo_accepted_types=['hg', 'git'])
274
274
275 config.add_route(
275 config.add_route(
276 name='pullrequest_show_all_data',
276 name='pullrequest_show_all_data',
277 pattern='/{repo_name:.*?[^/]}/pull-request-data',
277 pattern='/{repo_name:.*?[^/]}/pull-request-data',
278 repo_route=True, repo_accepted_types=['hg', 'git'])
278 repo_route=True, repo_accepted_types=['hg', 'git'])
279
279
280 config.add_route(
280 config.add_route(
281 name='pullrequest_repo_refs',
281 name='pullrequest_repo_refs',
282 pattern='/{repo_name:.*?[^/]}/pull-request/refs/{target_repo_name:.*?[^/]}',
282 pattern='/{repo_name:.*?[^/]}/pull-request/refs/{target_repo_name:.*?[^/]}',
283 repo_route=True)
283 repo_route=True)
284
284
285 config.add_route(
285 config.add_route(
286 name='pullrequest_repo_targets',
286 name='pullrequest_repo_targets',
287 pattern='/{repo_name:.*?[^/]}/pull-request/repo-targets',
287 pattern='/{repo_name:.*?[^/]}/pull-request/repo-targets',
288 repo_route=True)
288 repo_route=True)
289
289
290 config.add_route(
290 config.add_route(
291 name='pullrequest_new',
291 name='pullrequest_new',
292 pattern='/{repo_name:.*?[^/]}/pull-request/new',
292 pattern='/{repo_name:.*?[^/]}/pull-request/new',
293 repo_route=True, repo_accepted_types=['hg', 'git'],
293 repo_route=True, repo_accepted_types=['hg', 'git'],
294 repo_forbid_when_archived=True)
294 repo_forbid_when_archived=True)
295
295
296 config.add_route(
296 config.add_route(
297 name='pullrequest_create',
297 name='pullrequest_create',
298 pattern='/{repo_name:.*?[^/]}/pull-request/create',
298 pattern='/{repo_name:.*?[^/]}/pull-request/create',
299 repo_route=True, repo_accepted_types=['hg', 'git'],
299 repo_route=True, repo_accepted_types=['hg', 'git'],
300 repo_forbid_when_archived=True)
300 repo_forbid_when_archived=True)
301
301
302 config.add_route(
302 config.add_route(
303 name='pullrequest_update',
303 name='pullrequest_update',
304 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/update',
304 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/update',
305 repo_route=True, repo_forbid_when_archived=True)
305 repo_route=True, repo_forbid_when_archived=True)
306
306
307 config.add_route(
307 config.add_route(
308 name='pullrequest_merge',
308 name='pullrequest_merge',
309 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/merge',
309 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/merge',
310 repo_route=True, repo_forbid_when_archived=True)
310 repo_route=True, repo_forbid_when_archived=True)
311
311
312 config.add_route(
312 config.add_route(
313 name='pullrequest_delete',
313 name='pullrequest_delete',
314 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/delete',
314 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/delete',
315 repo_route=True, repo_forbid_when_archived=True)
315 repo_route=True, repo_forbid_when_archived=True)
316
316
317 config.add_route(
317 config.add_route(
318 name='pullrequest_comment_create',
318 name='pullrequest_comment_create',
319 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment',
319 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment',
320 repo_route=True)
320 repo_route=True)
321
321
322 config.add_route(
322 config.add_route(
323 name='pullrequest_comment_delete',
323 name='pullrequest_comment_delete',
324 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment/{comment_id}/delete',
324 pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id:\d+}/comment/{comment_id}/delete',
325 repo_route=True, repo_accepted_types=['hg', 'git'])
325 repo_route=True, repo_accepted_types=['hg', 'git'])
326
326
327 # Artifacts, (EE feature)
327 # Artifacts, (EE feature)
328 config.add_route(
328 config.add_route(
329 name='repo_artifacts_list',
329 name='repo_artifacts_list',
330 pattern='/{repo_name:.*?[^/]}/artifacts', repo_route=True)
330 pattern='/{repo_name:.*?[^/]}/artifacts', repo_route=True)
331
331
332 # Settings
332 # Settings
333 config.add_route(
333 config.add_route(
334 name='edit_repo',
334 name='edit_repo',
335 pattern='/{repo_name:.*?[^/]}/settings', repo_route=True)
335 pattern='/{repo_name:.*?[^/]}/settings', repo_route=True)
336 # update is POST on edit_repo
336 # update is POST on edit_repo
337
337
338 # Settings advanced
338 # Settings advanced
339 config.add_route(
339 config.add_route(
340 name='edit_repo_advanced',
340 name='edit_repo_advanced',
341 pattern='/{repo_name:.*?[^/]}/settings/advanced', repo_route=True)
341 pattern='/{repo_name:.*?[^/]}/settings/advanced', repo_route=True)
342 config.add_route(
342 config.add_route(
343 name='edit_repo_advanced_archive',
343 name='edit_repo_advanced_archive',
344 pattern='/{repo_name:.*?[^/]}/settings/advanced/archive', repo_route=True)
344 pattern='/{repo_name:.*?[^/]}/settings/advanced/archive', repo_route=True)
345 config.add_route(
345 config.add_route(
346 name='edit_repo_advanced_delete',
346 name='edit_repo_advanced_delete',
347 pattern='/{repo_name:.*?[^/]}/settings/advanced/delete', repo_route=True)
347 pattern='/{repo_name:.*?[^/]}/settings/advanced/delete', repo_route=True)
348 config.add_route(
348 config.add_route(
349 name='edit_repo_advanced_locking',
349 name='edit_repo_advanced_locking',
350 pattern='/{repo_name:.*?[^/]}/settings/advanced/locking', repo_route=True)
350 pattern='/{repo_name:.*?[^/]}/settings/advanced/locking', repo_route=True)
351 config.add_route(
351 config.add_route(
352 name='edit_repo_advanced_journal',
352 name='edit_repo_advanced_journal',
353 pattern='/{repo_name:.*?[^/]}/settings/advanced/journal', repo_route=True)
353 pattern='/{repo_name:.*?[^/]}/settings/advanced/journal', repo_route=True)
354 config.add_route(
354 config.add_route(
355 name='edit_repo_advanced_fork',
355 name='edit_repo_advanced_fork',
356 pattern='/{repo_name:.*?[^/]}/settings/advanced/fork', repo_route=True)
356 pattern='/{repo_name:.*?[^/]}/settings/advanced/fork', repo_route=True)
357
357
358 config.add_route(
358 config.add_route(
359 name='edit_repo_advanced_hooks',
359 name='edit_repo_advanced_hooks',
360 pattern='/{repo_name:.*?[^/]}/settings/advanced/hooks', repo_route=True)
360 pattern='/{repo_name:.*?[^/]}/settings/advanced/hooks', repo_route=True)
361
361
362 # Caches
362 # Caches
363 config.add_route(
363 config.add_route(
364 name='edit_repo_caches',
364 name='edit_repo_caches',
365 pattern='/{repo_name:.*?[^/]}/settings/caches', repo_route=True)
365 pattern='/{repo_name:.*?[^/]}/settings/caches', repo_route=True)
366
366
367 # Permissions
367 # Permissions
368 config.add_route(
368 config.add_route(
369 name='edit_repo_perms',
369 name='edit_repo_perms',
370 pattern='/{repo_name:.*?[^/]}/settings/permissions', repo_route=True)
370 pattern='/{repo_name:.*?[^/]}/settings/permissions', repo_route=True)
371
371
372 config.add_route(
373 name='edit_repo_perms_set_private',
374 pattern='/{repo_name:.*?[^/]}/settings/permissions/set_private', repo_route=True)
375
372 # Permissions Branch (EE feature)
376 # Permissions Branch (EE feature)
373 config.add_route(
377 config.add_route(
374 name='edit_repo_perms_branch',
378 name='edit_repo_perms_branch',
375 pattern='/{repo_name:.*?[^/]}/settings/branch_permissions', repo_route=True)
379 pattern='/{repo_name:.*?[^/]}/settings/branch_permissions', repo_route=True)
376 config.add_route(
380 config.add_route(
377 name='edit_repo_perms_branch_delete',
381 name='edit_repo_perms_branch_delete',
378 pattern='/{repo_name:.*?[^/]}/settings/branch_permissions/{rule_id}/delete',
382 pattern='/{repo_name:.*?[^/]}/settings/branch_permissions/{rule_id}/delete',
379 repo_route=True)
383 repo_route=True)
380
384
381 # Maintenance
385 # Maintenance
382 config.add_route(
386 config.add_route(
383 name='edit_repo_maintenance',
387 name='edit_repo_maintenance',
384 pattern='/{repo_name:.*?[^/]}/settings/maintenance', repo_route=True)
388 pattern='/{repo_name:.*?[^/]}/settings/maintenance', repo_route=True)
385
389
386 config.add_route(
390 config.add_route(
387 name='edit_repo_maintenance_execute',
391 name='edit_repo_maintenance_execute',
388 pattern='/{repo_name:.*?[^/]}/settings/maintenance/execute', repo_route=True)
392 pattern='/{repo_name:.*?[^/]}/settings/maintenance/execute', repo_route=True)
389
393
390 # Fields
394 # Fields
391 config.add_route(
395 config.add_route(
392 name='edit_repo_fields',
396 name='edit_repo_fields',
393 pattern='/{repo_name:.*?[^/]}/settings/fields', repo_route=True)
397 pattern='/{repo_name:.*?[^/]}/settings/fields', repo_route=True)
394 config.add_route(
398 config.add_route(
395 name='edit_repo_fields_create',
399 name='edit_repo_fields_create',
396 pattern='/{repo_name:.*?[^/]}/settings/fields/create', repo_route=True)
400 pattern='/{repo_name:.*?[^/]}/settings/fields/create', repo_route=True)
397 config.add_route(
401 config.add_route(
398 name='edit_repo_fields_delete',
402 name='edit_repo_fields_delete',
399 pattern='/{repo_name:.*?[^/]}/settings/fields/{field_id}/delete', repo_route=True)
403 pattern='/{repo_name:.*?[^/]}/settings/fields/{field_id}/delete', repo_route=True)
400
404
401 # Locking
405 # Locking
402 config.add_route(
406 config.add_route(
403 name='repo_edit_toggle_locking',
407 name='repo_edit_toggle_locking',
404 pattern='/{repo_name:.*?[^/]}/settings/toggle_locking', repo_route=True)
408 pattern='/{repo_name:.*?[^/]}/settings/toggle_locking', repo_route=True)
405
409
406 # Remote
410 # Remote
407 config.add_route(
411 config.add_route(
408 name='edit_repo_remote',
412 name='edit_repo_remote',
409 pattern='/{repo_name:.*?[^/]}/settings/remote', repo_route=True)
413 pattern='/{repo_name:.*?[^/]}/settings/remote', repo_route=True)
410 config.add_route(
414 config.add_route(
411 name='edit_repo_remote_pull',
415 name='edit_repo_remote_pull',
412 pattern='/{repo_name:.*?[^/]}/settings/remote/pull', repo_route=True)
416 pattern='/{repo_name:.*?[^/]}/settings/remote/pull', repo_route=True)
413 config.add_route(
417 config.add_route(
414 name='edit_repo_remote_push',
418 name='edit_repo_remote_push',
415 pattern='/{repo_name:.*?[^/]}/settings/remote/push', repo_route=True)
419 pattern='/{repo_name:.*?[^/]}/settings/remote/push', repo_route=True)
416
420
417 # Statistics
421 # Statistics
418 config.add_route(
422 config.add_route(
419 name='edit_repo_statistics',
423 name='edit_repo_statistics',
420 pattern='/{repo_name:.*?[^/]}/settings/statistics', repo_route=True)
424 pattern='/{repo_name:.*?[^/]}/settings/statistics', repo_route=True)
421 config.add_route(
425 config.add_route(
422 name='edit_repo_statistics_reset',
426 name='edit_repo_statistics_reset',
423 pattern='/{repo_name:.*?[^/]}/settings/statistics/update', repo_route=True)
427 pattern='/{repo_name:.*?[^/]}/settings/statistics/update', repo_route=True)
424
428
425 # Issue trackers
429 # Issue trackers
426 config.add_route(
430 config.add_route(
427 name='edit_repo_issuetracker',
431 name='edit_repo_issuetracker',
428 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers', repo_route=True)
432 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers', repo_route=True)
429 config.add_route(
433 config.add_route(
430 name='edit_repo_issuetracker_test',
434 name='edit_repo_issuetracker_test',
431 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/test', repo_route=True)
435 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/test', repo_route=True)
432 config.add_route(
436 config.add_route(
433 name='edit_repo_issuetracker_delete',
437 name='edit_repo_issuetracker_delete',
434 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/delete', repo_route=True)
438 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/delete', repo_route=True)
435 config.add_route(
439 config.add_route(
436 name='edit_repo_issuetracker_update',
440 name='edit_repo_issuetracker_update',
437 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/update', repo_route=True)
441 pattern='/{repo_name:.*?[^/]}/settings/issue_trackers/update', repo_route=True)
438
442
439 # VCS Settings
443 # VCS Settings
440 config.add_route(
444 config.add_route(
441 name='edit_repo_vcs',
445 name='edit_repo_vcs',
442 pattern='/{repo_name:.*?[^/]}/settings/vcs', repo_route=True)
446 pattern='/{repo_name:.*?[^/]}/settings/vcs', repo_route=True)
443 config.add_route(
447 config.add_route(
444 name='edit_repo_vcs_update',
448 name='edit_repo_vcs_update',
445 pattern='/{repo_name:.*?[^/]}/settings/vcs/update', repo_route=True)
449 pattern='/{repo_name:.*?[^/]}/settings/vcs/update', repo_route=True)
446
450
447 # svn pattern
451 # svn pattern
448 config.add_route(
452 config.add_route(
449 name='edit_repo_vcs_svn_pattern_delete',
453 name='edit_repo_vcs_svn_pattern_delete',
450 pattern='/{repo_name:.*?[^/]}/settings/vcs/svn_pattern/delete', repo_route=True)
454 pattern='/{repo_name:.*?[^/]}/settings/vcs/svn_pattern/delete', repo_route=True)
451
455
452 # Repo Review Rules (EE feature)
456 # Repo Review Rules (EE feature)
453 config.add_route(
457 config.add_route(
454 name='repo_reviewers',
458 name='repo_reviewers',
455 pattern='/{repo_name:.*?[^/]}/settings/review/rules', repo_route=True)
459 pattern='/{repo_name:.*?[^/]}/settings/review/rules', repo_route=True)
456
460
457 config.add_route(
461 config.add_route(
458 name='repo_default_reviewers_data',
462 name='repo_default_reviewers_data',
459 pattern='/{repo_name:.*?[^/]}/settings/review/default-reviewers', repo_route=True)
463 pattern='/{repo_name:.*?[^/]}/settings/review/default-reviewers', repo_route=True)
460
464
461 # Repo Automation (EE feature)
465 # Repo Automation (EE feature)
462 config.add_route(
466 config.add_route(
463 name='repo_automation',
467 name='repo_automation',
464 pattern='/{repo_name:.*?[^/]}/settings/automation', repo_route=True)
468 pattern='/{repo_name:.*?[^/]}/settings/automation', repo_route=True)
465
469
466 # Strip
470 # Strip
467 config.add_route(
471 config.add_route(
468 name='edit_repo_strip',
472 name='edit_repo_strip',
469 pattern='/{repo_name:.*?[^/]}/settings/strip', repo_route=True)
473 pattern='/{repo_name:.*?[^/]}/settings/strip', repo_route=True)
470
474
471 config.add_route(
475 config.add_route(
472 name='strip_check',
476 name='strip_check',
473 pattern='/{repo_name:.*?[^/]}/settings/strip_check', repo_route=True)
477 pattern='/{repo_name:.*?[^/]}/settings/strip_check', repo_route=True)
474
478
475 config.add_route(
479 config.add_route(
476 name='strip_execute',
480 name='strip_execute',
477 pattern='/{repo_name:.*?[^/]}/settings/strip_execute', repo_route=True)
481 pattern='/{repo_name:.*?[^/]}/settings/strip_execute', repo_route=True)
478
482
479 # Audit logs
483 # Audit logs
480 config.add_route(
484 config.add_route(
481 name='edit_repo_audit_logs',
485 name='edit_repo_audit_logs',
482 pattern='/{repo_name:.*?[^/]}/settings/audit_logs', repo_route=True)
486 pattern='/{repo_name:.*?[^/]}/settings/audit_logs', repo_route=True)
483
487
484 # ATOM/RSS Feed
488 # ATOM/RSS Feed
485 config.add_route(
489 config.add_route(
486 name='rss_feed_home',
490 name='rss_feed_home',
487 pattern='/{repo_name:.*?[^/]}/feed/rss', repo_route=True)
491 pattern='/{repo_name:.*?[^/]}/feed/rss', repo_route=True)
488
492
489 config.add_route(
493 config.add_route(
490 name='atom_feed_home',
494 name='atom_feed_home',
491 pattern='/{repo_name:.*?[^/]}/feed/atom', repo_route=True)
495 pattern='/{repo_name:.*?[^/]}/feed/atom', repo_route=True)
492
496
493 # NOTE(marcink): needs to be at the end for catch-all
497 # NOTE(marcink): needs to be at the end for catch-all
494 add_route_with_slash(
498 add_route_with_slash(
495 config,
499 config,
496 name='repo_summary',
500 name='repo_summary',
497 pattern='/{repo_name:.*?[^/]}', repo_route=True)
501 pattern='/{repo_name:.*?[^/]}', repo_route=True)
498
502
499 # Scan module for configuration decorators.
503 # Scan module for configuration decorators.
500 config.scan('.views', ignore='.tests')
504 config.scan('.views', ignore='.tests')
@@ -1,107 +1,134 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2019 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22
22
23 from pyramid.httpexceptions import HTTPFound
23 from pyramid.httpexceptions import HTTPFound
24 from pyramid.view import view_config
24 from pyramid.view import view_config
25
25
26 from rhodecode import events
26 from rhodecode import events
27 from rhodecode.apps._base import RepoAppView
27 from rhodecode.apps._base import RepoAppView
28 from rhodecode.lib import helpers as h
28 from rhodecode.lib import helpers as h
29 from rhodecode.lib import audit_logger
29 from rhodecode.lib import audit_logger
30 from rhodecode.lib.auth import (
30 from rhodecode.lib.auth import (
31 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
31 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
32 from rhodecode.lib.utils2 import safe_int
32 from rhodecode.lib.utils2 import safe_int
33 from rhodecode.model.db import UserGroup
33 from rhodecode.model.db import UserGroup
34 from rhodecode.model.forms import RepoPermsForm
34 from rhodecode.model.forms import RepoPermsForm
35 from rhodecode.model.meta import Session
35 from rhodecode.model.meta import Session
36 from rhodecode.model.repo import RepoModel
36 from rhodecode.model.repo import RepoModel
37
37
38 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
39
39
40
40
41 class RepoSettingsPermissionsView(RepoAppView):
41 class RepoSettingsPermissionsView(RepoAppView):
42
42
43 def load_default_context(self):
43 def load_default_context(self):
44 c = self._get_local_tmpl_context()
44 c = self._get_local_tmpl_context()
45 return c
45 return c
46
46
47 @LoginRequired()
47 @LoginRequired()
48 @HasRepoPermissionAnyDecorator('repository.admin')
48 @HasRepoPermissionAnyDecorator('repository.admin')
49 @view_config(
49 @view_config(
50 route_name='edit_repo_perms', request_method='GET',
50 route_name='edit_repo_perms', request_method='GET',
51 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
51 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
52 def edit_permissions(self):
52 def edit_permissions(self):
53 _ = self.request.translate
53 _ = self.request.translate
54 c = self.load_default_context()
54 c = self.load_default_context()
55 c.active = 'permissions'
55 c.active = 'permissions'
56 if self.request.GET.get('branch_permissions'):
56 if self.request.GET.get('branch_permissions'):
57 h.flash(_('Explicitly add user or user group with write+ '
57 h.flash(_('Explicitly add user or user group with write+ '
58 'permission to modify their branch permissions.'),
58 'permission to modify their branch permissions.'),
59 category='notice')
59 category='notice')
60 return self._get_template_context(c)
60 return self._get_template_context(c)
61
61
62 @LoginRequired()
62 @LoginRequired()
63 @HasRepoPermissionAnyDecorator('repository.admin')
63 @HasRepoPermissionAnyDecorator('repository.admin')
64 @CSRFRequired()
64 @CSRFRequired()
65 @view_config(
65 @view_config(
66 route_name='edit_repo_perms', request_method='POST',
66 route_name='edit_repo_perms', request_method='POST',
67 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
67 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
68 def edit_permissions_update(self):
68 def edit_permissions_update(self):
69 _ = self.request.translate
69 _ = self.request.translate
70 c = self.load_default_context()
70 c = self.load_default_context()
71 c.active = 'permissions'
71 c.active = 'permissions'
72 data = self.request.POST
72 data = self.request.POST
73 # store private flag outside of HTML to verify if we can modify
73 # store private flag outside of HTML to verify if we can modify
74 # default user permissions, prevents submission of FAKE post data
74 # default user permissions, prevents submission of FAKE post data
75 # into the form for private repos
75 # into the form for private repos
76 data['repo_private'] = self.db_repo.private
76 data['repo_private'] = self.db_repo.private
77 form = RepoPermsForm(self.request.translate)().to_python(data)
77 form = RepoPermsForm(self.request.translate)().to_python(data)
78 changes = RepoModel().update_permissions(
78 changes = RepoModel().update_permissions(
79 self.db_repo_name, form['perm_additions'], form['perm_updates'],
79 self.db_repo_name, form['perm_additions'], form['perm_updates'],
80 form['perm_deletions'])
80 form['perm_deletions'])
81
81
82 action_data = {
82 action_data = {
83 'added': changes['added'],
83 'added': changes['added'],
84 'updated': changes['updated'],
84 'updated': changes['updated'],
85 'deleted': changes['deleted'],
85 'deleted': changes['deleted'],
86 }
86 }
87 audit_logger.store_web(
87 audit_logger.store_web(
88 'repo.edit.permissions', action_data=action_data,
88 'repo.edit.permissions', action_data=action_data,
89 user=self._rhodecode_user, repo=self.db_repo)
89 user=self._rhodecode_user, repo=self.db_repo)
90
90
91 Session().commit()
91 Session().commit()
92 h.flash(_('Repository permissions updated'), category='success')
92 h.flash(_('Repository permissions updated'), category='success')
93
93
94 affected_user_ids = []
94 affected_user_ids = []
95 for change in changes['added'] + changes['updated'] + changes['deleted']:
95 for change in changes['added'] + changes['updated'] + changes['deleted']:
96 if change['type'] == 'user':
96 if change['type'] == 'user':
97 affected_user_ids.append(change['id'])
97 affected_user_ids.append(change['id'])
98 if change['type'] == 'user_group':
98 if change['type'] == 'user_group':
99 user_group = UserGroup.get(safe_int(change['id']))
99 user_group = UserGroup.get(safe_int(change['id']))
100 if user_group:
100 if user_group:
101 group_members_ids = [x.user_id for x in user_group.members]
101 group_members_ids = [x.user_id for x in user_group.members]
102 affected_user_ids.extend(group_members_ids)
102 affected_user_ids.extend(group_members_ids)
103
103
104 events.trigger(events.UserPermissionsChange(affected_user_ids))
104 events.trigger(events.UserPermissionsChange(affected_user_ids))
105
105
106 raise HTTPFound(
106 raise HTTPFound(
107 h.route_path('edit_repo_perms', repo_name=self.db_repo_name))
107 h.route_path('edit_repo_perms', repo_name=self.db_repo_name))
108
109 @LoginRequired()
110 @HasRepoPermissionAnyDecorator('repository.admin')
111 @CSRFRequired()
112 @view_config(
113 route_name='edit_repo_perms_set_private', request_method='POST',
114 renderer='json_ext')
115 def edit_permissions_set_private_repo(self):
116 _ = self.request.translate
117 self.load_default_context()
118
119 try:
120 RepoModel().update(
121 self.db_repo, **{'repo_private': True, 'repo_name': self.db_repo_name})
122 Session().commit()
123
124 h.flash(_('Repository `{}` private mode set successfully').format(self.db_repo_name),
125 category='success')
126 except Exception:
127 log.exception("Exception during update of repository")
128 h.flash(_('Error occurred during update of repository {}').format(
129 self.db_repo_name), category='error')
130
131 return {
132 'redirect_url': h.route_path('edit_repo_perms', repo_name=self.db_repo_name),
133 'private': True
134 }
@@ -1,1073 +1,1072 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2019 RhodeCode GmbH
3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import re
22 import re
23 import shutil
23 import shutil
24 import time
24 import time
25 import logging
25 import logging
26 import traceback
26 import traceback
27 import datetime
27 import datetime
28
28
29 from pyramid.threadlocal import get_current_request
29 from pyramid.threadlocal import get_current_request
30 from zope.cachedescriptors.property import Lazy as LazyProperty
30 from zope.cachedescriptors.property import Lazy as LazyProperty
31
31
32 from rhodecode import events
32 from rhodecode import events
33 from rhodecode.lib.auth import HasUserGroupPermissionAny
33 from rhodecode.lib.auth import HasUserGroupPermissionAny
34 from rhodecode.lib.caching_query import FromCache
34 from rhodecode.lib.caching_query import FromCache
35 from rhodecode.lib.exceptions import AttachedForksError, AttachedPullRequestsError
35 from rhodecode.lib.exceptions import AttachedForksError, AttachedPullRequestsError
36 from rhodecode.lib.hooks_base import log_delete_repository
36 from rhodecode.lib.hooks_base import log_delete_repository
37 from rhodecode.lib.user_log_filter import user_log_filter
37 from rhodecode.lib.user_log_filter import user_log_filter
38 from rhodecode.lib.utils import make_db_config
38 from rhodecode.lib.utils import make_db_config
39 from rhodecode.lib.utils2 import (
39 from rhodecode.lib.utils2 import (
40 safe_str, safe_unicode, remove_prefix, obfuscate_url_pw,
40 safe_str, safe_unicode, remove_prefix, obfuscate_url_pw,
41 get_current_rhodecode_user, safe_int, datetime_to_time,
41 get_current_rhodecode_user, safe_int, datetime_to_time,
42 action_logger_generic)
42 action_logger_generic)
43 from rhodecode.lib.vcs.backends import get_backend
43 from rhodecode.lib.vcs.backends import get_backend
44 from rhodecode.model import BaseModel
44 from rhodecode.model import BaseModel
45 from rhodecode.model.db import (
45 from rhodecode.model.db import (
46 _hash_key, joinedload, or_, Repository, UserRepoToPerm, UserGroupRepoToPerm,
46 _hash_key, joinedload, or_, Repository, UserRepoToPerm, UserGroupRepoToPerm,
47 UserRepoGroupToPerm, UserGroupRepoGroupToPerm, User, Permission,
47 UserRepoGroupToPerm, UserGroupRepoGroupToPerm, User, Permission,
48 Statistics, UserGroup, RepoGroup, RepositoryField, UserLog)
48 Statistics, UserGroup, RepoGroup, RepositoryField, UserLog)
49
49
50 from rhodecode.model.settings import VcsSettingsModel
50 from rhodecode.model.settings import VcsSettingsModel
51
51
52
52
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
55
55
56 class RepoModel(BaseModel):
56 class RepoModel(BaseModel):
57
57
58 cls = Repository
58 cls = Repository
59
59
60 def _get_user_group(self, users_group):
60 def _get_user_group(self, users_group):
61 return self._get_instance(UserGroup, users_group,
61 return self._get_instance(UserGroup, users_group,
62 callback=UserGroup.get_by_group_name)
62 callback=UserGroup.get_by_group_name)
63
63
64 def _get_repo_group(self, repo_group):
64 def _get_repo_group(self, repo_group):
65 return self._get_instance(RepoGroup, repo_group,
65 return self._get_instance(RepoGroup, repo_group,
66 callback=RepoGroup.get_by_group_name)
66 callback=RepoGroup.get_by_group_name)
67
67
68 def _create_default_perms(self, repository, private):
68 def _create_default_perms(self, repository, private):
69 # create default permission
69 # create default permission
70 default = 'repository.read'
70 default = 'repository.read'
71 def_user = User.get_default_user()
71 def_user = User.get_default_user()
72 for p in def_user.user_perms:
72 for p in def_user.user_perms:
73 if p.permission.permission_name.startswith('repository.'):
73 if p.permission.permission_name.startswith('repository.'):
74 default = p.permission.permission_name
74 default = p.permission.permission_name
75 break
75 break
76
76
77 default_perm = 'repository.none' if private else default
77 default_perm = 'repository.none' if private else default
78
78
79 repo_to_perm = UserRepoToPerm()
79 repo_to_perm = UserRepoToPerm()
80 repo_to_perm.permission = Permission.get_by_key(default_perm)
80 repo_to_perm.permission = Permission.get_by_key(default_perm)
81
81
82 repo_to_perm.repository = repository
82 repo_to_perm.repository = repository
83 repo_to_perm.user_id = def_user.user_id
83 repo_to_perm.user_id = def_user.user_id
84
84
85 return repo_to_perm
85 return repo_to_perm
86
86
87 @LazyProperty
87 @LazyProperty
88 def repos_path(self):
88 def repos_path(self):
89 """
89 """
90 Gets the repositories root path from database
90 Gets the repositories root path from database
91 """
91 """
92 settings_model = VcsSettingsModel(sa=self.sa)
92 settings_model = VcsSettingsModel(sa=self.sa)
93 return settings_model.get_repos_location()
93 return settings_model.get_repos_location()
94
94
95 def get(self, repo_id):
95 def get(self, repo_id):
96 repo = self.sa.query(Repository) \
96 repo = self.sa.query(Repository) \
97 .filter(Repository.repo_id == repo_id)
97 .filter(Repository.repo_id == repo_id)
98
98
99 return repo.scalar()
99 return repo.scalar()
100
100
101 def get_repo(self, repository):
101 def get_repo(self, repository):
102 return self._get_repo(repository)
102 return self._get_repo(repository)
103
103
104 def get_by_repo_name(self, repo_name, cache=False):
104 def get_by_repo_name(self, repo_name, cache=False):
105 repo = self.sa.query(Repository) \
105 repo = self.sa.query(Repository) \
106 .filter(Repository.repo_name == repo_name)
106 .filter(Repository.repo_name == repo_name)
107
107
108 if cache:
108 if cache:
109 name_key = _hash_key(repo_name)
109 name_key = _hash_key(repo_name)
110 repo = repo.options(
110 repo = repo.options(
111 FromCache("sql_cache_short", "get_repo_%s" % name_key))
111 FromCache("sql_cache_short", "get_repo_%s" % name_key))
112 return repo.scalar()
112 return repo.scalar()
113
113
114 def _extract_id_from_repo_name(self, repo_name):
114 def _extract_id_from_repo_name(self, repo_name):
115 if repo_name.startswith('/'):
115 if repo_name.startswith('/'):
116 repo_name = repo_name.lstrip('/')
116 repo_name = repo_name.lstrip('/')
117 by_id_match = re.match(r'^_(\d{1,})', repo_name)
117 by_id_match = re.match(r'^_(\d{1,})', repo_name)
118 if by_id_match:
118 if by_id_match:
119 return by_id_match.groups()[0]
119 return by_id_match.groups()[0]
120
120
121 def get_repo_by_id(self, repo_name):
121 def get_repo_by_id(self, repo_name):
122 """
122 """
123 Extracts repo_name by id from special urls.
123 Extracts repo_name by id from special urls.
124 Example url is _11/repo_name
124 Example url is _11/repo_name
125
125
126 :param repo_name:
126 :param repo_name:
127 :return: repo object if matched else None
127 :return: repo object if matched else None
128 """
128 """
129
129
130 try:
130 try:
131 _repo_id = self._extract_id_from_repo_name(repo_name)
131 _repo_id = self._extract_id_from_repo_name(repo_name)
132 if _repo_id:
132 if _repo_id:
133 return self.get(_repo_id)
133 return self.get(_repo_id)
134 except Exception:
134 except Exception:
135 log.exception('Failed to extract repo_name from URL')
135 log.exception('Failed to extract repo_name from URL')
136
136
137 return None
137 return None
138
138
139 def get_repos_for_root(self, root, traverse=False):
139 def get_repos_for_root(self, root, traverse=False):
140 if traverse:
140 if traverse:
141 like_expression = u'{}%'.format(safe_unicode(root))
141 like_expression = u'{}%'.format(safe_unicode(root))
142 repos = Repository.query().filter(
142 repos = Repository.query().filter(
143 Repository.repo_name.like(like_expression)).all()
143 Repository.repo_name.like(like_expression)).all()
144 else:
144 else:
145 if root and not isinstance(root, RepoGroup):
145 if root and not isinstance(root, RepoGroup):
146 raise ValueError(
146 raise ValueError(
147 'Root must be an instance '
147 'Root must be an instance '
148 'of RepoGroup, got:{} instead'.format(type(root)))
148 'of RepoGroup, got:{} instead'.format(type(root)))
149 repos = Repository.query().filter(Repository.group == root).all()
149 repos = Repository.query().filter(Repository.group == root).all()
150 return repos
150 return repos
151
151
152 def get_url(self, repo, request=None, permalink=False):
152 def get_url(self, repo, request=None, permalink=False):
153 if not request:
153 if not request:
154 request = get_current_request()
154 request = get_current_request()
155
155
156 if not request:
156 if not request:
157 return
157 return
158
158
159 if permalink:
159 if permalink:
160 return request.route_url(
160 return request.route_url(
161 'repo_summary', repo_name='_{}'.format(safe_str(repo.repo_id)))
161 'repo_summary', repo_name='_{}'.format(safe_str(repo.repo_id)))
162 else:
162 else:
163 return request.route_url(
163 return request.route_url(
164 'repo_summary', repo_name=safe_str(repo.repo_name))
164 'repo_summary', repo_name=safe_str(repo.repo_name))
165
165
166 def get_commit_url(self, repo, commit_id, request=None, permalink=False):
166 def get_commit_url(self, repo, commit_id, request=None, permalink=False):
167 if not request:
167 if not request:
168 request = get_current_request()
168 request = get_current_request()
169
169
170 if not request:
170 if not request:
171 return
171 return
172
172
173 if permalink:
173 if permalink:
174 return request.route_url(
174 return request.route_url(
175 'repo_commit', repo_name=safe_str(repo.repo_id),
175 'repo_commit', repo_name=safe_str(repo.repo_id),
176 commit_id=commit_id)
176 commit_id=commit_id)
177
177
178 else:
178 else:
179 return request.route_url(
179 return request.route_url(
180 'repo_commit', repo_name=safe_str(repo.repo_name),
180 'repo_commit', repo_name=safe_str(repo.repo_name),
181 commit_id=commit_id)
181 commit_id=commit_id)
182
182
183 def get_repo_log(self, repo, filter_term):
183 def get_repo_log(self, repo, filter_term):
184 repo_log = UserLog.query()\
184 repo_log = UserLog.query()\
185 .filter(or_(UserLog.repository_id == repo.repo_id,
185 .filter(or_(UserLog.repository_id == repo.repo_id,
186 UserLog.repository_name == repo.repo_name))\
186 UserLog.repository_name == repo.repo_name))\
187 .options(joinedload(UserLog.user))\
187 .options(joinedload(UserLog.user))\
188 .options(joinedload(UserLog.repository))\
188 .options(joinedload(UserLog.repository))\
189 .order_by(UserLog.action_date.desc())
189 .order_by(UserLog.action_date.desc())
190
190
191 repo_log = user_log_filter(repo_log, filter_term)
191 repo_log = user_log_filter(repo_log, filter_term)
192 return repo_log
192 return repo_log
193
193
194 @classmethod
194 @classmethod
195 def update_commit_cache(cls, repositories=None):
195 def update_commit_cache(cls, repositories=None):
196 if not repositories:
196 if not repositories:
197 repositories = Repository.getAll()
197 repositories = Repository.getAll()
198 for repo in repositories:
198 for repo in repositories:
199 repo.update_commit_cache()
199 repo.update_commit_cache()
200
200
201 def get_repos_as_dict(self, repo_list=None, admin=False,
201 def get_repos_as_dict(self, repo_list=None, admin=False,
202 super_user_actions=False, short_name=None):
202 super_user_actions=False, short_name=None):
203 _render = get_current_request().get_partial_renderer(
203 _render = get_current_request().get_partial_renderer(
204 'rhodecode:templates/data_table/_dt_elements.mako')
204 'rhodecode:templates/data_table/_dt_elements.mako')
205 c = _render.get_call_context()
205 c = _render.get_call_context()
206
206
207 def quick_menu(repo_name):
207 def quick_menu(repo_name):
208 return _render('quick_menu', repo_name)
208 return _render('quick_menu', repo_name)
209
209
210 def repo_lnk(name, rtype, rstate, private, archived, fork_of):
210 def repo_lnk(name, rtype, rstate, private, archived, fork_of):
211 if short_name is not None:
211 if short_name is not None:
212 short_name_var = short_name
212 short_name_var = short_name
213 else:
213 else:
214 short_name_var = not admin
214 short_name_var = not admin
215 return _render('repo_name', name, rtype, rstate, private, archived, fork_of,
215 return _render('repo_name', name, rtype, rstate, private, archived, fork_of,
216 short_name=short_name_var, admin=False)
216 short_name=short_name_var, admin=False)
217
217
218 def last_change(last_change):
218 def last_change(last_change):
219 if admin and isinstance(last_change, datetime.datetime) and not last_change.tzinfo:
219 if admin and isinstance(last_change, datetime.datetime) and not last_change.tzinfo:
220 last_change = last_change + datetime.timedelta(seconds=
220 last_change = last_change + datetime.timedelta(seconds=
221 (datetime.datetime.now() - datetime.datetime.utcnow()).seconds)
221 (datetime.datetime.now() - datetime.datetime.utcnow()).seconds)
222 return _render("last_change", last_change)
222 return _render("last_change", last_change)
223
223
224 def rss_lnk(repo_name):
224 def rss_lnk(repo_name):
225 return _render("rss", repo_name)
225 return _render("rss", repo_name)
226
226
227 def atom_lnk(repo_name):
227 def atom_lnk(repo_name):
228 return _render("atom", repo_name)
228 return _render("atom", repo_name)
229
229
230 def last_rev(repo_name, cs_cache):
230 def last_rev(repo_name, cs_cache):
231 return _render('revision', repo_name, cs_cache.get('revision'),
231 return _render('revision', repo_name, cs_cache.get('revision'),
232 cs_cache.get('raw_id'), cs_cache.get('author'),
232 cs_cache.get('raw_id'), cs_cache.get('author'),
233 cs_cache.get('message'), cs_cache.get('date'))
233 cs_cache.get('message'), cs_cache.get('date'))
234
234
235 def desc(desc):
235 def desc(desc):
236 return _render('repo_desc', desc, c.visual.stylify_metatags)
236 return _render('repo_desc', desc, c.visual.stylify_metatags)
237
237
238 def state(repo_state):
238 def state(repo_state):
239 return _render("repo_state", repo_state)
239 return _render("repo_state", repo_state)
240
240
241 def repo_actions(repo_name):
241 def repo_actions(repo_name):
242 return _render('repo_actions', repo_name, super_user_actions)
242 return _render('repo_actions', repo_name, super_user_actions)
243
243
244 def user_profile(username):
244 def user_profile(username):
245 return _render('user_profile', username)
245 return _render('user_profile', username)
246
246
247 repos_data = []
247 repos_data = []
248 for repo in repo_list:
248 for repo in repo_list:
249 cs_cache = repo.changeset_cache
249 cs_cache = repo.changeset_cache
250 row = {
250 row = {
251 "menu": quick_menu(repo.repo_name),
251 "menu": quick_menu(repo.repo_name),
252
252
253 "name": repo_lnk(repo.repo_name, repo.repo_type, repo.repo_state,
253 "name": repo_lnk(repo.repo_name, repo.repo_type, repo.repo_state,
254 repo.private, repo.archived, repo.fork),
254 repo.private, repo.archived, repo.fork),
255 "name_raw": repo.repo_name.lower(),
255 "name_raw": repo.repo_name.lower(),
256
256
257 "last_change": last_change(repo.last_commit_change),
257 "last_change": last_change(repo.last_commit_change),
258 "last_change_raw": datetime_to_time(repo.last_commit_change),
258 "last_change_raw": datetime_to_time(repo.last_commit_change),
259
259
260 "last_changeset": last_rev(repo.repo_name, cs_cache),
260 "last_changeset": last_rev(repo.repo_name, cs_cache),
261 "last_changeset_raw": cs_cache.get('revision'),
261 "last_changeset_raw": cs_cache.get('revision'),
262
262
263 "desc": desc(repo.description_safe),
263 "desc": desc(repo.description_safe),
264 "owner": user_profile(repo.user.username),
264 "owner": user_profile(repo.user.username),
265
265
266 "state": state(repo.repo_state),
266 "state": state(repo.repo_state),
267 "rss": rss_lnk(repo.repo_name),
267 "rss": rss_lnk(repo.repo_name),
268
268
269 "atom": atom_lnk(repo.repo_name),
269 "atom": atom_lnk(repo.repo_name),
270 }
270 }
271 if admin:
271 if admin:
272 row.update({
272 row.update({
273 "action": repo_actions(repo.repo_name),
273 "action": repo_actions(repo.repo_name),
274 })
274 })
275 repos_data.append(row)
275 repos_data.append(row)
276
276
277 return repos_data
277 return repos_data
278
278
279 def _get_defaults(self, repo_name):
279 def _get_defaults(self, repo_name):
280 """
280 """
281 Gets information about repository, and returns a dict for
281 Gets information about repository, and returns a dict for
282 usage in forms
282 usage in forms
283
283
284 :param repo_name:
284 :param repo_name:
285 """
285 """
286
286
287 repo_info = Repository.get_by_repo_name(repo_name)
287 repo_info = Repository.get_by_repo_name(repo_name)
288
288
289 if repo_info is None:
289 if repo_info is None:
290 return None
290 return None
291
291
292 defaults = repo_info.get_dict()
292 defaults = repo_info.get_dict()
293 defaults['repo_name'] = repo_info.just_name
293 defaults['repo_name'] = repo_info.just_name
294
294
295 groups = repo_info.groups_with_parents
295 groups = repo_info.groups_with_parents
296 parent_group = groups[-1] if groups else None
296 parent_group = groups[-1] if groups else None
297
297
298 # we use -1 as this is how in HTML, we mark an empty group
298 # we use -1 as this is how in HTML, we mark an empty group
299 defaults['repo_group'] = getattr(parent_group, 'group_id', -1)
299 defaults['repo_group'] = getattr(parent_group, 'group_id', -1)
300
300
301 keys_to_process = (
301 keys_to_process = (
302 {'k': 'repo_type', 'strip': False},
302 {'k': 'repo_type', 'strip': False},
303 {'k': 'repo_enable_downloads', 'strip': True},
303 {'k': 'repo_enable_downloads', 'strip': True},
304 {'k': 'repo_description', 'strip': True},
304 {'k': 'repo_description', 'strip': True},
305 {'k': 'repo_enable_locking', 'strip': True},
305 {'k': 'repo_enable_locking', 'strip': True},
306 {'k': 'repo_landing_rev', 'strip': True},
306 {'k': 'repo_landing_rev', 'strip': True},
307 {'k': 'clone_uri', 'strip': False},
307 {'k': 'clone_uri', 'strip': False},
308 {'k': 'push_uri', 'strip': False},
308 {'k': 'push_uri', 'strip': False},
309 {'k': 'repo_private', 'strip': True},
309 {'k': 'repo_private', 'strip': True},
310 {'k': 'repo_enable_statistics', 'strip': True}
310 {'k': 'repo_enable_statistics', 'strip': True}
311 )
311 )
312
312
313 for item in keys_to_process:
313 for item in keys_to_process:
314 attr = item['k']
314 attr = item['k']
315 if item['strip']:
315 if item['strip']:
316 attr = remove_prefix(item['k'], 'repo_')
316 attr = remove_prefix(item['k'], 'repo_')
317
317
318 val = defaults[attr]
318 val = defaults[attr]
319 if item['k'] == 'repo_landing_rev':
319 if item['k'] == 'repo_landing_rev':
320 val = ':'.join(defaults[attr])
320 val = ':'.join(defaults[attr])
321 defaults[item['k']] = val
321 defaults[item['k']] = val
322 if item['k'] == 'clone_uri':
322 if item['k'] == 'clone_uri':
323 defaults['clone_uri_hidden'] = repo_info.clone_uri_hidden
323 defaults['clone_uri_hidden'] = repo_info.clone_uri_hidden
324 if item['k'] == 'push_uri':
324 if item['k'] == 'push_uri':
325 defaults['push_uri_hidden'] = repo_info.push_uri_hidden
325 defaults['push_uri_hidden'] = repo_info.push_uri_hidden
326
326
327 # fill owner
327 # fill owner
328 if repo_info.user:
328 if repo_info.user:
329 defaults.update({'user': repo_info.user.username})
329 defaults.update({'user': repo_info.user.username})
330 else:
330 else:
331 replacement_user = User.get_first_super_admin().username
331 replacement_user = User.get_first_super_admin().username
332 defaults.update({'user': replacement_user})
332 defaults.update({'user': replacement_user})
333
333
334 return defaults
334 return defaults
335
335
336 def update(self, repo, **kwargs):
336 def update(self, repo, **kwargs):
337 try:
337 try:
338 cur_repo = self._get_repo(repo)
338 cur_repo = self._get_repo(repo)
339 source_repo_name = cur_repo.repo_name
339 source_repo_name = cur_repo.repo_name
340 if 'user' in kwargs:
340 if 'user' in kwargs:
341 cur_repo.user = User.get_by_username(kwargs['user'])
341 cur_repo.user = User.get_by_username(kwargs['user'])
342
342
343 if 'repo_group' in kwargs:
343 if 'repo_group' in kwargs:
344 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
344 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
345 log.debug('Updating repo %s with params:%s', cur_repo, kwargs)
345 log.debug('Updating repo %s with params:%s', cur_repo, kwargs)
346
346
347 update_keys = [
347 update_keys = [
348 (1, 'repo_description'),
348 (1, 'repo_description'),
349 (1, 'repo_landing_rev'),
349 (1, 'repo_landing_rev'),
350 (1, 'repo_private'),
350 (1, 'repo_private'),
351 (1, 'repo_enable_downloads'),
351 (1, 'repo_enable_downloads'),
352 (1, 'repo_enable_locking'),
352 (1, 'repo_enable_locking'),
353 (1, 'repo_enable_statistics'),
353 (1, 'repo_enable_statistics'),
354 (0, 'clone_uri'),
354 (0, 'clone_uri'),
355 (0, 'push_uri'),
355 (0, 'push_uri'),
356 (0, 'fork_id')
356 (0, 'fork_id')
357 ]
357 ]
358 for strip, k in update_keys:
358 for strip, k in update_keys:
359 if k in kwargs:
359 if k in kwargs:
360 val = kwargs[k]
360 val = kwargs[k]
361 if strip:
361 if strip:
362 k = remove_prefix(k, 'repo_')
362 k = remove_prefix(k, 'repo_')
363
363
364 setattr(cur_repo, k, val)
364 setattr(cur_repo, k, val)
365
365
366 new_name = cur_repo.get_new_name(kwargs['repo_name'])
366 new_name = cur_repo.get_new_name(kwargs['repo_name'])
367 cur_repo.repo_name = new_name
367 cur_repo.repo_name = new_name
368
368
369 # if private flag is set, reset default permission to NONE
369 # if private flag is set, reset default permission to NONE
370 if kwargs.get('repo_private'):
370 if kwargs.get('repo_private'):
371 EMPTY_PERM = 'repository.none'
371 EMPTY_PERM = 'repository.none'
372 RepoModel().grant_user_permission(
372 RepoModel().grant_user_permission(
373 repo=cur_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM
373 repo=cur_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM
374 )
374 )
375
375
376 # handle extra fields
376 # handle extra fields
377 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX),
377 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
378 kwargs):
379 k = RepositoryField.un_prefix_key(field)
378 k = RepositoryField.un_prefix_key(field)
380 ex_field = RepositoryField.get_by_key_name(
379 ex_field = RepositoryField.get_by_key_name(
381 key=k, repo=cur_repo)
380 key=k, repo=cur_repo)
382 if ex_field:
381 if ex_field:
383 ex_field.field_value = kwargs[field]
382 ex_field.field_value = kwargs[field]
384 self.sa.add(ex_field)
383 self.sa.add(ex_field)
385 cur_repo.updated_on = datetime.datetime.now()
384 cur_repo.updated_on = datetime.datetime.now()
386 self.sa.add(cur_repo)
385 self.sa.add(cur_repo)
387
386
388 if source_repo_name != new_name:
387 if source_repo_name != new_name:
389 # rename repository
388 # rename repository
390 self._rename_filesystem_repo(
389 self._rename_filesystem_repo(
391 old=source_repo_name, new=new_name)
390 old=source_repo_name, new=new_name)
392
391
393 return cur_repo
392 return cur_repo
394 except Exception:
393 except Exception:
395 log.error(traceback.format_exc())
394 log.error(traceback.format_exc())
396 raise
395 raise
397
396
398 def _create_repo(self, repo_name, repo_type, description, owner,
397 def _create_repo(self, repo_name, repo_type, description, owner,
399 private=False, clone_uri=None, repo_group=None,
398 private=False, clone_uri=None, repo_group=None,
400 landing_rev='rev:tip', fork_of=None,
399 landing_rev='rev:tip', fork_of=None,
401 copy_fork_permissions=False, enable_statistics=False,
400 copy_fork_permissions=False, enable_statistics=False,
402 enable_locking=False, enable_downloads=False,
401 enable_locking=False, enable_downloads=False,
403 copy_group_permissions=False,
402 copy_group_permissions=False,
404 state=Repository.STATE_PENDING):
403 state=Repository.STATE_PENDING):
405 """
404 """
406 Create repository inside database with PENDING state, this should be
405 Create repository inside database with PENDING state, this should be
407 only executed by create() repo. With exception of importing existing
406 only executed by create() repo. With exception of importing existing
408 repos
407 repos
409 """
408 """
410 from rhodecode.model.scm import ScmModel
409 from rhodecode.model.scm import ScmModel
411
410
412 owner = self._get_user(owner)
411 owner = self._get_user(owner)
413 fork_of = self._get_repo(fork_of)
412 fork_of = self._get_repo(fork_of)
414 repo_group = self._get_repo_group(safe_int(repo_group))
413 repo_group = self._get_repo_group(safe_int(repo_group))
415
414
416 try:
415 try:
417 repo_name = safe_unicode(repo_name)
416 repo_name = safe_unicode(repo_name)
418 description = safe_unicode(description)
417 description = safe_unicode(description)
419 # repo name is just a name of repository
418 # repo name is just a name of repository
420 # while repo_name_full is a full qualified name that is combined
419 # while repo_name_full is a full qualified name that is combined
421 # with name and path of group
420 # with name and path of group
422 repo_name_full = repo_name
421 repo_name_full = repo_name
423 repo_name = repo_name.split(Repository.NAME_SEP)[-1]
422 repo_name = repo_name.split(Repository.NAME_SEP)[-1]
424
423
425 new_repo = Repository()
424 new_repo = Repository()
426 new_repo.repo_state = state
425 new_repo.repo_state = state
427 new_repo.enable_statistics = False
426 new_repo.enable_statistics = False
428 new_repo.repo_name = repo_name_full
427 new_repo.repo_name = repo_name_full
429 new_repo.repo_type = repo_type
428 new_repo.repo_type = repo_type
430 new_repo.user = owner
429 new_repo.user = owner
431 new_repo.group = repo_group
430 new_repo.group = repo_group
432 new_repo.description = description or repo_name
431 new_repo.description = description or repo_name
433 new_repo.private = private
432 new_repo.private = private
434 new_repo.archived = False
433 new_repo.archived = False
435 new_repo.clone_uri = clone_uri
434 new_repo.clone_uri = clone_uri
436 new_repo.landing_rev = landing_rev
435 new_repo.landing_rev = landing_rev
437
436
438 new_repo.enable_statistics = enable_statistics
437 new_repo.enable_statistics = enable_statistics
439 new_repo.enable_locking = enable_locking
438 new_repo.enable_locking = enable_locking
440 new_repo.enable_downloads = enable_downloads
439 new_repo.enable_downloads = enable_downloads
441
440
442 if repo_group:
441 if repo_group:
443 new_repo.enable_locking = repo_group.enable_locking
442 new_repo.enable_locking = repo_group.enable_locking
444
443
445 if fork_of:
444 if fork_of:
446 parent_repo = fork_of
445 parent_repo = fork_of
447 new_repo.fork = parent_repo
446 new_repo.fork = parent_repo
448
447
449 events.trigger(events.RepoPreCreateEvent(new_repo))
448 events.trigger(events.RepoPreCreateEvent(new_repo))
450
449
451 self.sa.add(new_repo)
450 self.sa.add(new_repo)
452
451
453 EMPTY_PERM = 'repository.none'
452 EMPTY_PERM = 'repository.none'
454 if fork_of and copy_fork_permissions:
453 if fork_of and copy_fork_permissions:
455 repo = fork_of
454 repo = fork_of
456 user_perms = UserRepoToPerm.query() \
455 user_perms = UserRepoToPerm.query() \
457 .filter(UserRepoToPerm.repository == repo).all()
456 .filter(UserRepoToPerm.repository == repo).all()
458 group_perms = UserGroupRepoToPerm.query() \
457 group_perms = UserGroupRepoToPerm.query() \
459 .filter(UserGroupRepoToPerm.repository == repo).all()
458 .filter(UserGroupRepoToPerm.repository == repo).all()
460
459
461 for perm in user_perms:
460 for perm in user_perms:
462 UserRepoToPerm.create(
461 UserRepoToPerm.create(
463 perm.user, new_repo, perm.permission)
462 perm.user, new_repo, perm.permission)
464
463
465 for perm in group_perms:
464 for perm in group_perms:
466 UserGroupRepoToPerm.create(
465 UserGroupRepoToPerm.create(
467 perm.users_group, new_repo, perm.permission)
466 perm.users_group, new_repo, perm.permission)
468 # in case we copy permissions and also set this repo to private
467 # in case we copy permissions and also set this repo to private
469 # override the default user permission to make it a private repo
468 # override the default user permission to make it a private repo
470 if private:
469 if private:
471 RepoModel(self.sa).grant_user_permission(
470 RepoModel(self.sa).grant_user_permission(
472 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
471 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
473
472
474 elif repo_group and copy_group_permissions:
473 elif repo_group and copy_group_permissions:
475 user_perms = UserRepoGroupToPerm.query() \
474 user_perms = UserRepoGroupToPerm.query() \
476 .filter(UserRepoGroupToPerm.group == repo_group).all()
475 .filter(UserRepoGroupToPerm.group == repo_group).all()
477
476
478 group_perms = UserGroupRepoGroupToPerm.query() \
477 group_perms = UserGroupRepoGroupToPerm.query() \
479 .filter(UserGroupRepoGroupToPerm.group == repo_group).all()
478 .filter(UserGroupRepoGroupToPerm.group == repo_group).all()
480
479
481 for perm in user_perms:
480 for perm in user_perms:
482 perm_name = perm.permission.permission_name.replace(
481 perm_name = perm.permission.permission_name.replace(
483 'group.', 'repository.')
482 'group.', 'repository.')
484 perm_obj = Permission.get_by_key(perm_name)
483 perm_obj = Permission.get_by_key(perm_name)
485 UserRepoToPerm.create(perm.user, new_repo, perm_obj)
484 UserRepoToPerm.create(perm.user, new_repo, perm_obj)
486
485
487 for perm in group_perms:
486 for perm in group_perms:
488 perm_name = perm.permission.permission_name.replace(
487 perm_name = perm.permission.permission_name.replace(
489 'group.', 'repository.')
488 'group.', 'repository.')
490 perm_obj = Permission.get_by_key(perm_name)
489 perm_obj = Permission.get_by_key(perm_name)
491 UserGroupRepoToPerm.create(perm.users_group, new_repo, perm_obj)
490 UserGroupRepoToPerm.create(perm.users_group, new_repo, perm_obj)
492
491
493 if private:
492 if private:
494 RepoModel(self.sa).grant_user_permission(
493 RepoModel(self.sa).grant_user_permission(
495 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
494 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
496
495
497 else:
496 else:
498 perm_obj = self._create_default_perms(new_repo, private)
497 perm_obj = self._create_default_perms(new_repo, private)
499 self.sa.add(perm_obj)
498 self.sa.add(perm_obj)
500
499
501 # now automatically start following this repository as owner
500 # now automatically start following this repository as owner
502 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id, owner.user_id)
501 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id, owner.user_id)
503
502
504 # we need to flush here, in order to check if database won't
503 # we need to flush here, in order to check if database won't
505 # throw any exceptions, create filesystem dirs at the very end
504 # throw any exceptions, create filesystem dirs at the very end
506 self.sa.flush()
505 self.sa.flush()
507 events.trigger(events.RepoCreateEvent(new_repo))
506 events.trigger(events.RepoCreateEvent(new_repo))
508 return new_repo
507 return new_repo
509
508
510 except Exception:
509 except Exception:
511 log.error(traceback.format_exc())
510 log.error(traceback.format_exc())
512 raise
511 raise
513
512
514 def create(self, form_data, cur_user):
513 def create(self, form_data, cur_user):
515 """
514 """
516 Create repository using celery tasks
515 Create repository using celery tasks
517
516
518 :param form_data:
517 :param form_data:
519 :param cur_user:
518 :param cur_user:
520 """
519 """
521 from rhodecode.lib.celerylib import tasks, run_task
520 from rhodecode.lib.celerylib import tasks, run_task
522 return run_task(tasks.create_repo, form_data, cur_user)
521 return run_task(tasks.create_repo, form_data, cur_user)
523
522
524 def update_permissions(self, repo, perm_additions=None, perm_updates=None,
523 def update_permissions(self, repo, perm_additions=None, perm_updates=None,
525 perm_deletions=None, check_perms=True,
524 perm_deletions=None, check_perms=True,
526 cur_user=None):
525 cur_user=None):
527 if not perm_additions:
526 if not perm_additions:
528 perm_additions = []
527 perm_additions = []
529 if not perm_updates:
528 if not perm_updates:
530 perm_updates = []
529 perm_updates = []
531 if not perm_deletions:
530 if not perm_deletions:
532 perm_deletions = []
531 perm_deletions = []
533
532
534 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
533 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
535
534
536 changes = {
535 changes = {
537 'added': [],
536 'added': [],
538 'updated': [],
537 'updated': [],
539 'deleted': []
538 'deleted': []
540 }
539 }
541 # update permissions
540 # update permissions
542 for member_id, perm, member_type in perm_updates:
541 for member_id, perm, member_type in perm_updates:
543 member_id = int(member_id)
542 member_id = int(member_id)
544 if member_type == 'user':
543 if member_type == 'user':
545 member_name = User.get(member_id).username
544 member_name = User.get(member_id).username
546 # this updates also current one if found
545 # this updates also current one if found
547 self.grant_user_permission(
546 self.grant_user_permission(
548 repo=repo, user=member_id, perm=perm)
547 repo=repo, user=member_id, perm=perm)
549 elif member_type == 'user_group':
548 elif member_type == 'user_group':
550 # check if we have permissions to alter this usergroup
549 # check if we have permissions to alter this usergroup
551 member_name = UserGroup.get(member_id).users_group_name
550 member_name = UserGroup.get(member_id).users_group_name
552 if not check_perms or HasUserGroupPermissionAny(
551 if not check_perms or HasUserGroupPermissionAny(
553 *req_perms)(member_name, user=cur_user):
552 *req_perms)(member_name, user=cur_user):
554 self.grant_user_group_permission(
553 self.grant_user_group_permission(
555 repo=repo, group_name=member_id, perm=perm)
554 repo=repo, group_name=member_id, perm=perm)
556 else:
555 else:
557 raise ValueError("member_type must be 'user' or 'user_group' "
556 raise ValueError("member_type must be 'user' or 'user_group' "
558 "got {} instead".format(member_type))
557 "got {} instead".format(member_type))
559 changes['updated'].append({'type': member_type, 'id': member_id,
558 changes['updated'].append({'type': member_type, 'id': member_id,
560 'name': member_name, 'new_perm': perm})
559 'name': member_name, 'new_perm': perm})
561
560
562 # set new permissions
561 # set new permissions
563 for member_id, perm, member_type in perm_additions:
562 for member_id, perm, member_type in perm_additions:
564 member_id = int(member_id)
563 member_id = int(member_id)
565 if member_type == 'user':
564 if member_type == 'user':
566 member_name = User.get(member_id).username
565 member_name = User.get(member_id).username
567 self.grant_user_permission(
566 self.grant_user_permission(
568 repo=repo, user=member_id, perm=perm)
567 repo=repo, user=member_id, perm=perm)
569 elif member_type == 'user_group':
568 elif member_type == 'user_group':
570 # check if we have permissions to alter this usergroup
569 # check if we have permissions to alter this usergroup
571 member_name = UserGroup.get(member_id).users_group_name
570 member_name = UserGroup.get(member_id).users_group_name
572 if not check_perms or HasUserGroupPermissionAny(
571 if not check_perms or HasUserGroupPermissionAny(
573 *req_perms)(member_name, user=cur_user):
572 *req_perms)(member_name, user=cur_user):
574 self.grant_user_group_permission(
573 self.grant_user_group_permission(
575 repo=repo, group_name=member_id, perm=perm)
574 repo=repo, group_name=member_id, perm=perm)
576 else:
575 else:
577 raise ValueError("member_type must be 'user' or 'user_group' "
576 raise ValueError("member_type must be 'user' or 'user_group' "
578 "got {} instead".format(member_type))
577 "got {} instead".format(member_type))
579
578
580 changes['added'].append({'type': member_type, 'id': member_id,
579 changes['added'].append({'type': member_type, 'id': member_id,
581 'name': member_name, 'new_perm': perm})
580 'name': member_name, 'new_perm': perm})
582 # delete permissions
581 # delete permissions
583 for member_id, perm, member_type in perm_deletions:
582 for member_id, perm, member_type in perm_deletions:
584 member_id = int(member_id)
583 member_id = int(member_id)
585 if member_type == 'user':
584 if member_type == 'user':
586 member_name = User.get(member_id).username
585 member_name = User.get(member_id).username
587 self.revoke_user_permission(repo=repo, user=member_id)
586 self.revoke_user_permission(repo=repo, user=member_id)
588 elif member_type == 'user_group':
587 elif member_type == 'user_group':
589 # check if we have permissions to alter this usergroup
588 # check if we have permissions to alter this usergroup
590 member_name = UserGroup.get(member_id).users_group_name
589 member_name = UserGroup.get(member_id).users_group_name
591 if not check_perms or HasUserGroupPermissionAny(
590 if not check_perms or HasUserGroupPermissionAny(
592 *req_perms)(member_name, user=cur_user):
591 *req_perms)(member_name, user=cur_user):
593 self.revoke_user_group_permission(
592 self.revoke_user_group_permission(
594 repo=repo, group_name=member_id)
593 repo=repo, group_name=member_id)
595 else:
594 else:
596 raise ValueError("member_type must be 'user' or 'user_group' "
595 raise ValueError("member_type must be 'user' or 'user_group' "
597 "got {} instead".format(member_type))
596 "got {} instead".format(member_type))
598
597
599 changes['deleted'].append({'type': member_type, 'id': member_id,
598 changes['deleted'].append({'type': member_type, 'id': member_id,
600 'name': member_name, 'new_perm': perm})
599 'name': member_name, 'new_perm': perm})
601 return changes
600 return changes
602
601
603 def create_fork(self, form_data, cur_user):
602 def create_fork(self, form_data, cur_user):
604 """
603 """
605 Simple wrapper into executing celery task for fork creation
604 Simple wrapper into executing celery task for fork creation
606
605
607 :param form_data:
606 :param form_data:
608 :param cur_user:
607 :param cur_user:
609 """
608 """
610 from rhodecode.lib.celerylib import tasks, run_task
609 from rhodecode.lib.celerylib import tasks, run_task
611 return run_task(tasks.create_repo_fork, form_data, cur_user)
610 return run_task(tasks.create_repo_fork, form_data, cur_user)
612
611
613 def archive(self, repo):
612 def archive(self, repo):
614 """
613 """
615 Archive given repository. Set archive flag.
614 Archive given repository. Set archive flag.
616
615
617 :param repo:
616 :param repo:
618 """
617 """
619 repo = self._get_repo(repo)
618 repo = self._get_repo(repo)
620 if repo:
619 if repo:
621
620
622 try:
621 try:
623 repo.archived = True
622 repo.archived = True
624 self.sa.add(repo)
623 self.sa.add(repo)
625 self.sa.commit()
624 self.sa.commit()
626 except Exception:
625 except Exception:
627 log.error(traceback.format_exc())
626 log.error(traceback.format_exc())
628 raise
627 raise
629
628
630 def delete(self, repo, forks=None, pull_requests=None, fs_remove=True, cur_user=None):
629 def delete(self, repo, forks=None, pull_requests=None, fs_remove=True, cur_user=None):
631 """
630 """
632 Delete given repository, forks parameter defines what do do with
631 Delete given repository, forks parameter defines what do do with
633 attached forks. Throws AttachedForksError if deleted repo has attached
632 attached forks. Throws AttachedForksError if deleted repo has attached
634 forks
633 forks
635
634
636 :param repo:
635 :param repo:
637 :param forks: str 'delete' or 'detach'
636 :param forks: str 'delete' or 'detach'
638 :param pull_requests: str 'delete' or None
637 :param pull_requests: str 'delete' or None
639 :param fs_remove: remove(archive) repo from filesystem
638 :param fs_remove: remove(archive) repo from filesystem
640 """
639 """
641 if not cur_user:
640 if not cur_user:
642 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
641 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
643 repo = self._get_repo(repo)
642 repo = self._get_repo(repo)
644 if repo:
643 if repo:
645 if forks == 'detach':
644 if forks == 'detach':
646 for r in repo.forks:
645 for r in repo.forks:
647 r.fork = None
646 r.fork = None
648 self.sa.add(r)
647 self.sa.add(r)
649 elif forks == 'delete':
648 elif forks == 'delete':
650 for r in repo.forks:
649 for r in repo.forks:
651 self.delete(r, forks='delete')
650 self.delete(r, forks='delete')
652 elif [f for f in repo.forks]:
651 elif [f for f in repo.forks]:
653 raise AttachedForksError()
652 raise AttachedForksError()
654
653
655 # check for pull requests
654 # check for pull requests
656 pr_sources = repo.pull_requests_source
655 pr_sources = repo.pull_requests_source
657 pr_targets = repo.pull_requests_target
656 pr_targets = repo.pull_requests_target
658 if pull_requests != 'delete' and (pr_sources or pr_targets):
657 if pull_requests != 'delete' and (pr_sources or pr_targets):
659 raise AttachedPullRequestsError()
658 raise AttachedPullRequestsError()
660
659
661 old_repo_dict = repo.get_dict()
660 old_repo_dict = repo.get_dict()
662 events.trigger(events.RepoPreDeleteEvent(repo))
661 events.trigger(events.RepoPreDeleteEvent(repo))
663 try:
662 try:
664 self.sa.delete(repo)
663 self.sa.delete(repo)
665 if fs_remove:
664 if fs_remove:
666 self._delete_filesystem_repo(repo)
665 self._delete_filesystem_repo(repo)
667 else:
666 else:
668 log.debug('skipping removal from filesystem')
667 log.debug('skipping removal from filesystem')
669 old_repo_dict.update({
668 old_repo_dict.update({
670 'deleted_by': cur_user,
669 'deleted_by': cur_user,
671 'deleted_on': time.time(),
670 'deleted_on': time.time(),
672 })
671 })
673 log_delete_repository(**old_repo_dict)
672 log_delete_repository(**old_repo_dict)
674 events.trigger(events.RepoDeleteEvent(repo))
673 events.trigger(events.RepoDeleteEvent(repo))
675 except Exception:
674 except Exception:
676 log.error(traceback.format_exc())
675 log.error(traceback.format_exc())
677 raise
676 raise
678
677
679 def grant_user_permission(self, repo, user, perm):
678 def grant_user_permission(self, repo, user, perm):
680 """
679 """
681 Grant permission for user on given repository, or update existing one
680 Grant permission for user on given repository, or update existing one
682 if found
681 if found
683
682
684 :param repo: Instance of Repository, repository_id, or repository name
683 :param repo: Instance of Repository, repository_id, or repository name
685 :param user: Instance of User, user_id or username
684 :param user: Instance of User, user_id or username
686 :param perm: Instance of Permission, or permission_name
685 :param perm: Instance of Permission, or permission_name
687 """
686 """
688 user = self._get_user(user)
687 user = self._get_user(user)
689 repo = self._get_repo(repo)
688 repo = self._get_repo(repo)
690 permission = self._get_perm(perm)
689 permission = self._get_perm(perm)
691
690
692 # check if we have that permission already
691 # check if we have that permission already
693 obj = self.sa.query(UserRepoToPerm) \
692 obj = self.sa.query(UserRepoToPerm) \
694 .filter(UserRepoToPerm.user == user) \
693 .filter(UserRepoToPerm.user == user) \
695 .filter(UserRepoToPerm.repository == repo) \
694 .filter(UserRepoToPerm.repository == repo) \
696 .scalar()
695 .scalar()
697 if obj is None:
696 if obj is None:
698 # create new !
697 # create new !
699 obj = UserRepoToPerm()
698 obj = UserRepoToPerm()
700 obj.repository = repo
699 obj.repository = repo
701 obj.user = user
700 obj.user = user
702 obj.permission = permission
701 obj.permission = permission
703 self.sa.add(obj)
702 self.sa.add(obj)
704 log.debug('Granted perm %s to %s on %s', perm, user, repo)
703 log.debug('Granted perm %s to %s on %s', perm, user, repo)
705 action_logger_generic(
704 action_logger_generic(
706 'granted permission: {} to user: {} on repo: {}'.format(
705 'granted permission: {} to user: {} on repo: {}'.format(
707 perm, user, repo), namespace='security.repo')
706 perm, user, repo), namespace='security.repo')
708 return obj
707 return obj
709
708
710 def revoke_user_permission(self, repo, user):
709 def revoke_user_permission(self, repo, user):
711 """
710 """
712 Revoke permission for user on given repository
711 Revoke permission for user on given repository
713
712
714 :param repo: Instance of Repository, repository_id, or repository name
713 :param repo: Instance of Repository, repository_id, or repository name
715 :param user: Instance of User, user_id or username
714 :param user: Instance of User, user_id or username
716 """
715 """
717
716
718 user = self._get_user(user)
717 user = self._get_user(user)
719 repo = self._get_repo(repo)
718 repo = self._get_repo(repo)
720
719
721 obj = self.sa.query(UserRepoToPerm) \
720 obj = self.sa.query(UserRepoToPerm) \
722 .filter(UserRepoToPerm.repository == repo) \
721 .filter(UserRepoToPerm.repository == repo) \
723 .filter(UserRepoToPerm.user == user) \
722 .filter(UserRepoToPerm.user == user) \
724 .scalar()
723 .scalar()
725 if obj:
724 if obj:
726 self.sa.delete(obj)
725 self.sa.delete(obj)
727 log.debug('Revoked perm on %s on %s', repo, user)
726 log.debug('Revoked perm on %s on %s', repo, user)
728 action_logger_generic(
727 action_logger_generic(
729 'revoked permission from user: {} on repo: {}'.format(
728 'revoked permission from user: {} on repo: {}'.format(
730 user, repo), namespace='security.repo')
729 user, repo), namespace='security.repo')
731
730
732 def grant_user_group_permission(self, repo, group_name, perm):
731 def grant_user_group_permission(self, repo, group_name, perm):
733 """
732 """
734 Grant permission for user group on given repository, or update
733 Grant permission for user group on given repository, or update
735 existing one if found
734 existing one if found
736
735
737 :param repo: Instance of Repository, repository_id, or repository name
736 :param repo: Instance of Repository, repository_id, or repository name
738 :param group_name: Instance of UserGroup, users_group_id,
737 :param group_name: Instance of UserGroup, users_group_id,
739 or user group name
738 or user group name
740 :param perm: Instance of Permission, or permission_name
739 :param perm: Instance of Permission, or permission_name
741 """
740 """
742 repo = self._get_repo(repo)
741 repo = self._get_repo(repo)
743 group_name = self._get_user_group(group_name)
742 group_name = self._get_user_group(group_name)
744 permission = self._get_perm(perm)
743 permission = self._get_perm(perm)
745
744
746 # check if we have that permission already
745 # check if we have that permission already
747 obj = self.sa.query(UserGroupRepoToPerm) \
746 obj = self.sa.query(UserGroupRepoToPerm) \
748 .filter(UserGroupRepoToPerm.users_group == group_name) \
747 .filter(UserGroupRepoToPerm.users_group == group_name) \
749 .filter(UserGroupRepoToPerm.repository == repo) \
748 .filter(UserGroupRepoToPerm.repository == repo) \
750 .scalar()
749 .scalar()
751
750
752 if obj is None:
751 if obj is None:
753 # create new
752 # create new
754 obj = UserGroupRepoToPerm()
753 obj = UserGroupRepoToPerm()
755
754
756 obj.repository = repo
755 obj.repository = repo
757 obj.users_group = group_name
756 obj.users_group = group_name
758 obj.permission = permission
757 obj.permission = permission
759 self.sa.add(obj)
758 self.sa.add(obj)
760 log.debug('Granted perm %s to %s on %s', perm, group_name, repo)
759 log.debug('Granted perm %s to %s on %s', perm, group_name, repo)
761 action_logger_generic(
760 action_logger_generic(
762 'granted permission: {} to usergroup: {} on repo: {}'.format(
761 'granted permission: {} to usergroup: {} on repo: {}'.format(
763 perm, group_name, repo), namespace='security.repo')
762 perm, group_name, repo), namespace='security.repo')
764
763
765 return obj
764 return obj
766
765
767 def revoke_user_group_permission(self, repo, group_name):
766 def revoke_user_group_permission(self, repo, group_name):
768 """
767 """
769 Revoke permission for user group on given repository
768 Revoke permission for user group on given repository
770
769
771 :param repo: Instance of Repository, repository_id, or repository name
770 :param repo: Instance of Repository, repository_id, or repository name
772 :param group_name: Instance of UserGroup, users_group_id,
771 :param group_name: Instance of UserGroup, users_group_id,
773 or user group name
772 or user group name
774 """
773 """
775 repo = self._get_repo(repo)
774 repo = self._get_repo(repo)
776 group_name = self._get_user_group(group_name)
775 group_name = self._get_user_group(group_name)
777
776
778 obj = self.sa.query(UserGroupRepoToPerm) \
777 obj = self.sa.query(UserGroupRepoToPerm) \
779 .filter(UserGroupRepoToPerm.repository == repo) \
778 .filter(UserGroupRepoToPerm.repository == repo) \
780 .filter(UserGroupRepoToPerm.users_group == group_name) \
779 .filter(UserGroupRepoToPerm.users_group == group_name) \
781 .scalar()
780 .scalar()
782 if obj:
781 if obj:
783 self.sa.delete(obj)
782 self.sa.delete(obj)
784 log.debug('Revoked perm to %s on %s', repo, group_name)
783 log.debug('Revoked perm to %s on %s', repo, group_name)
785 action_logger_generic(
784 action_logger_generic(
786 'revoked permission from usergroup: {} on repo: {}'.format(
785 'revoked permission from usergroup: {} on repo: {}'.format(
787 group_name, repo), namespace='security.repo')
786 group_name, repo), namespace='security.repo')
788
787
789 def delete_stats(self, repo_name):
788 def delete_stats(self, repo_name):
790 """
789 """
791 removes stats for given repo
790 removes stats for given repo
792
791
793 :param repo_name:
792 :param repo_name:
794 """
793 """
795 repo = self._get_repo(repo_name)
794 repo = self._get_repo(repo_name)
796 try:
795 try:
797 obj = self.sa.query(Statistics) \
796 obj = self.sa.query(Statistics) \
798 .filter(Statistics.repository == repo).scalar()
797 .filter(Statistics.repository == repo).scalar()
799 if obj:
798 if obj:
800 self.sa.delete(obj)
799 self.sa.delete(obj)
801 except Exception:
800 except Exception:
802 log.error(traceback.format_exc())
801 log.error(traceback.format_exc())
803 raise
802 raise
804
803
805 def add_repo_field(self, repo_name, field_key, field_label, field_value='',
804 def add_repo_field(self, repo_name, field_key, field_label, field_value='',
806 field_type='str', field_desc=''):
805 field_type='str', field_desc=''):
807
806
808 repo = self._get_repo(repo_name)
807 repo = self._get_repo(repo_name)
809
808
810 new_field = RepositoryField()
809 new_field = RepositoryField()
811 new_field.repository = repo
810 new_field.repository = repo
812 new_field.field_key = field_key
811 new_field.field_key = field_key
813 new_field.field_type = field_type # python type
812 new_field.field_type = field_type # python type
814 new_field.field_value = field_value
813 new_field.field_value = field_value
815 new_field.field_desc = field_desc
814 new_field.field_desc = field_desc
816 new_field.field_label = field_label
815 new_field.field_label = field_label
817 self.sa.add(new_field)
816 self.sa.add(new_field)
818 return new_field
817 return new_field
819
818
820 def delete_repo_field(self, repo_name, field_key):
819 def delete_repo_field(self, repo_name, field_key):
821 repo = self._get_repo(repo_name)
820 repo = self._get_repo(repo_name)
822 field = RepositoryField.get_by_key_name(field_key, repo)
821 field = RepositoryField.get_by_key_name(field_key, repo)
823 if field:
822 if field:
824 self.sa.delete(field)
823 self.sa.delete(field)
825
824
826 def _create_filesystem_repo(self, repo_name, repo_type, repo_group,
825 def _create_filesystem_repo(self, repo_name, repo_type, repo_group,
827 clone_uri=None, repo_store_location=None,
826 clone_uri=None, repo_store_location=None,
828 use_global_config=False):
827 use_global_config=False):
829 """
828 """
830 makes repository on filesystem. It's group aware means it'll create
829 makes repository on filesystem. It's group aware means it'll create
831 a repository within a group, and alter the paths accordingly of
830 a repository within a group, and alter the paths accordingly of
832 group location
831 group location
833
832
834 :param repo_name:
833 :param repo_name:
835 :param alias:
834 :param alias:
836 :param parent:
835 :param parent:
837 :param clone_uri:
836 :param clone_uri:
838 :param repo_store_location:
837 :param repo_store_location:
839 """
838 """
840 from rhodecode.lib.utils import is_valid_repo, is_valid_repo_group
839 from rhodecode.lib.utils import is_valid_repo, is_valid_repo_group
841 from rhodecode.model.scm import ScmModel
840 from rhodecode.model.scm import ScmModel
842
841
843 if Repository.NAME_SEP in repo_name:
842 if Repository.NAME_SEP in repo_name:
844 raise ValueError(
843 raise ValueError(
845 'repo_name must not contain groups got `%s`' % repo_name)
844 'repo_name must not contain groups got `%s`' % repo_name)
846
845
847 if isinstance(repo_group, RepoGroup):
846 if isinstance(repo_group, RepoGroup):
848 new_parent_path = os.sep.join(repo_group.full_path_splitted)
847 new_parent_path = os.sep.join(repo_group.full_path_splitted)
849 else:
848 else:
850 new_parent_path = repo_group or ''
849 new_parent_path = repo_group or ''
851
850
852 if repo_store_location:
851 if repo_store_location:
853 _paths = [repo_store_location]
852 _paths = [repo_store_location]
854 else:
853 else:
855 _paths = [self.repos_path, new_parent_path, repo_name]
854 _paths = [self.repos_path, new_parent_path, repo_name]
856 # we need to make it str for mercurial
855 # we need to make it str for mercurial
857 repo_path = os.path.join(*map(lambda x: safe_str(x), _paths))
856 repo_path = os.path.join(*map(lambda x: safe_str(x), _paths))
858
857
859 # check if this path is not a repository
858 # check if this path is not a repository
860 if is_valid_repo(repo_path, self.repos_path):
859 if is_valid_repo(repo_path, self.repos_path):
861 raise Exception('This path %s is a valid repository' % repo_path)
860 raise Exception('This path %s is a valid repository' % repo_path)
862
861
863 # check if this path is a group
862 # check if this path is a group
864 if is_valid_repo_group(repo_path, self.repos_path):
863 if is_valid_repo_group(repo_path, self.repos_path):
865 raise Exception('This path %s is a valid group' % repo_path)
864 raise Exception('This path %s is a valid group' % repo_path)
866
865
867 log.info('creating repo %s in %s from url: `%s`',
866 log.info('creating repo %s in %s from url: `%s`',
868 repo_name, safe_unicode(repo_path),
867 repo_name, safe_unicode(repo_path),
869 obfuscate_url_pw(clone_uri))
868 obfuscate_url_pw(clone_uri))
870
869
871 backend = get_backend(repo_type)
870 backend = get_backend(repo_type)
872
871
873 config_repo = None if use_global_config else repo_name
872 config_repo = None if use_global_config else repo_name
874 if config_repo and new_parent_path:
873 if config_repo and new_parent_path:
875 config_repo = Repository.NAME_SEP.join(
874 config_repo = Repository.NAME_SEP.join(
876 (new_parent_path, config_repo))
875 (new_parent_path, config_repo))
877 config = make_db_config(clear_session=False, repo=config_repo)
876 config = make_db_config(clear_session=False, repo=config_repo)
878 config.set('extensions', 'largefiles', '')
877 config.set('extensions', 'largefiles', '')
879
878
880 # patch and reset hooks section of UI config to not run any
879 # patch and reset hooks section of UI config to not run any
881 # hooks on creating remote repo
880 # hooks on creating remote repo
882 config.clear_section('hooks')
881 config.clear_section('hooks')
883
882
884 # TODO: johbo: Unify this, hardcoded "bare=True" does not look nice
883 # TODO: johbo: Unify this, hardcoded "bare=True" does not look nice
885 if repo_type == 'git':
884 if repo_type == 'git':
886 repo = backend(
885 repo = backend(
887 repo_path, config=config, create=True, src_url=clone_uri,
886 repo_path, config=config, create=True, src_url=clone_uri,
888 bare=True)
887 bare=True)
889 else:
888 else:
890 repo = backend(
889 repo = backend(
891 repo_path, config=config, create=True, src_url=clone_uri)
890 repo_path, config=config, create=True, src_url=clone_uri)
892
891
893 repo.install_hooks()
892 repo.install_hooks()
894
893
895 log.debug('Created repo %s with %s backend',
894 log.debug('Created repo %s with %s backend',
896 safe_unicode(repo_name), safe_unicode(repo_type))
895 safe_unicode(repo_name), safe_unicode(repo_type))
897 return repo
896 return repo
898
897
899 def _rename_filesystem_repo(self, old, new):
898 def _rename_filesystem_repo(self, old, new):
900 """
899 """
901 renames repository on filesystem
900 renames repository on filesystem
902
901
903 :param old: old name
902 :param old: old name
904 :param new: new name
903 :param new: new name
905 """
904 """
906 log.info('renaming repo from %s to %s', old, new)
905 log.info('renaming repo from %s to %s', old, new)
907
906
908 old_path = os.path.join(self.repos_path, old)
907 old_path = os.path.join(self.repos_path, old)
909 new_path = os.path.join(self.repos_path, new)
908 new_path = os.path.join(self.repos_path, new)
910 if os.path.isdir(new_path):
909 if os.path.isdir(new_path):
911 raise Exception(
910 raise Exception(
912 'Was trying to rename to already existing dir %s' % new_path
911 'Was trying to rename to already existing dir %s' % new_path
913 )
912 )
914 shutil.move(old_path, new_path)
913 shutil.move(old_path, new_path)
915
914
916 def _delete_filesystem_repo(self, repo):
915 def _delete_filesystem_repo(self, repo):
917 """
916 """
918 removes repo from filesystem, the removal is acctually made by
917 removes repo from filesystem, the removal is acctually made by
919 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
918 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
920 repository is no longer valid for rhodecode, can be undeleted later on
919 repository is no longer valid for rhodecode, can be undeleted later on
921 by reverting the renames on this repository
920 by reverting the renames on this repository
922
921
923 :param repo: repo object
922 :param repo: repo object
924 """
923 """
925 rm_path = os.path.join(self.repos_path, repo.repo_name)
924 rm_path = os.path.join(self.repos_path, repo.repo_name)
926 repo_group = repo.group
925 repo_group = repo.group
927 log.info("Removing repository %s", rm_path)
926 log.info("Removing repository %s", rm_path)
928 # disable hg/git internal that it doesn't get detected as repo
927 # disable hg/git internal that it doesn't get detected as repo
929 alias = repo.repo_type
928 alias = repo.repo_type
930
929
931 config = make_db_config(clear_session=False)
930 config = make_db_config(clear_session=False)
932 config.set('extensions', 'largefiles', '')
931 config.set('extensions', 'largefiles', '')
933 bare = getattr(repo.scm_instance(config=config), 'bare', False)
932 bare = getattr(repo.scm_instance(config=config), 'bare', False)
934
933
935 # skip this for bare git repos
934 # skip this for bare git repos
936 if not bare:
935 if not bare:
937 # disable VCS repo
936 # disable VCS repo
938 vcs_path = os.path.join(rm_path, '.%s' % alias)
937 vcs_path = os.path.join(rm_path, '.%s' % alias)
939 if os.path.exists(vcs_path):
938 if os.path.exists(vcs_path):
940 shutil.move(vcs_path, os.path.join(rm_path, 'rm__.%s' % alias))
939 shutil.move(vcs_path, os.path.join(rm_path, 'rm__.%s' % alias))
941
940
942 _now = datetime.datetime.now()
941 _now = datetime.datetime.now()
943 _ms = str(_now.microsecond).rjust(6, '0')
942 _ms = str(_now.microsecond).rjust(6, '0')
944 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
943 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
945 repo.just_name)
944 repo.just_name)
946 if repo_group:
945 if repo_group:
947 # if repository is in group, prefix the removal path with the group
946 # if repository is in group, prefix the removal path with the group
948 args = repo_group.full_path_splitted + [_d]
947 args = repo_group.full_path_splitted + [_d]
949 _d = os.path.join(*args)
948 _d = os.path.join(*args)
950
949
951 if os.path.isdir(rm_path):
950 if os.path.isdir(rm_path):
952 shutil.move(rm_path, os.path.join(self.repos_path, _d))
951 shutil.move(rm_path, os.path.join(self.repos_path, _d))
953
952
954 # finally cleanup diff-cache if it exists
953 # finally cleanup diff-cache if it exists
955 cached_diffs_dir = repo.cached_diffs_dir
954 cached_diffs_dir = repo.cached_diffs_dir
956 if os.path.isdir(cached_diffs_dir):
955 if os.path.isdir(cached_diffs_dir):
957 shutil.rmtree(cached_diffs_dir)
956 shutil.rmtree(cached_diffs_dir)
958
957
959
958
960 class ReadmeFinder:
959 class ReadmeFinder:
961 """
960 """
962 Utility which knows how to find a readme for a specific commit.
961 Utility which knows how to find a readme for a specific commit.
963
962
964 The main idea is that this is a configurable algorithm. When creating an
963 The main idea is that this is a configurable algorithm. When creating an
965 instance you can define parameters, currently only the `default_renderer`.
964 instance you can define parameters, currently only the `default_renderer`.
966 Based on this configuration the method :meth:`search` behaves slightly
965 Based on this configuration the method :meth:`search` behaves slightly
967 different.
966 different.
968 """
967 """
969
968
970 readme_re = re.compile(r'^readme(\.[^\.]+)?$', re.IGNORECASE)
969 readme_re = re.compile(r'^readme(\.[^\.]+)?$', re.IGNORECASE)
971 path_re = re.compile(r'^docs?', re.IGNORECASE)
970 path_re = re.compile(r'^docs?', re.IGNORECASE)
972
971
973 default_priorities = {
972 default_priorities = {
974 None: 0,
973 None: 0,
975 '.text': 2,
974 '.text': 2,
976 '.txt': 3,
975 '.txt': 3,
977 '.rst': 1,
976 '.rst': 1,
978 '.rest': 2,
977 '.rest': 2,
979 '.md': 1,
978 '.md': 1,
980 '.mkdn': 2,
979 '.mkdn': 2,
981 '.mdown': 3,
980 '.mdown': 3,
982 '.markdown': 4,
981 '.markdown': 4,
983 }
982 }
984
983
985 path_priority = {
984 path_priority = {
986 'doc': 0,
985 'doc': 0,
987 'docs': 1,
986 'docs': 1,
988 }
987 }
989
988
990 FALLBACK_PRIORITY = 99
989 FALLBACK_PRIORITY = 99
991
990
992 RENDERER_TO_EXTENSION = {
991 RENDERER_TO_EXTENSION = {
993 'rst': ['.rst', '.rest'],
992 'rst': ['.rst', '.rest'],
994 'markdown': ['.md', 'mkdn', '.mdown', '.markdown'],
993 'markdown': ['.md', 'mkdn', '.mdown', '.markdown'],
995 }
994 }
996
995
997 def __init__(self, default_renderer=None):
996 def __init__(self, default_renderer=None):
998 self._default_renderer = default_renderer
997 self._default_renderer = default_renderer
999 self._renderer_extensions = self.RENDERER_TO_EXTENSION.get(
998 self._renderer_extensions = self.RENDERER_TO_EXTENSION.get(
1000 default_renderer, [])
999 default_renderer, [])
1001
1000
1002 def search(self, commit, path='/'):
1001 def search(self, commit, path='/'):
1003 """
1002 """
1004 Find a readme in the given `commit`.
1003 Find a readme in the given `commit`.
1005 """
1004 """
1006 nodes = commit.get_nodes(path)
1005 nodes = commit.get_nodes(path)
1007 matches = self._match_readmes(nodes)
1006 matches = self._match_readmes(nodes)
1008 matches = self._sort_according_to_priority(matches)
1007 matches = self._sort_according_to_priority(matches)
1009 if matches:
1008 if matches:
1010 return matches[0].node
1009 return matches[0].node
1011
1010
1012 paths = self._match_paths(nodes)
1011 paths = self._match_paths(nodes)
1013 paths = self._sort_paths_according_to_priority(paths)
1012 paths = self._sort_paths_according_to_priority(paths)
1014 for path in paths:
1013 for path in paths:
1015 match = self.search(commit, path=path)
1014 match = self.search(commit, path=path)
1016 if match:
1015 if match:
1017 return match
1016 return match
1018
1017
1019 return None
1018 return None
1020
1019
1021 def _match_readmes(self, nodes):
1020 def _match_readmes(self, nodes):
1022 for node in nodes:
1021 for node in nodes:
1023 if not node.is_file():
1022 if not node.is_file():
1024 continue
1023 continue
1025 path = node.path.rsplit('/', 1)[-1]
1024 path = node.path.rsplit('/', 1)[-1]
1026 match = self.readme_re.match(path)
1025 match = self.readme_re.match(path)
1027 if match:
1026 if match:
1028 extension = match.group(1)
1027 extension = match.group(1)
1029 yield ReadmeMatch(node, match, self._priority(extension))
1028 yield ReadmeMatch(node, match, self._priority(extension))
1030
1029
1031 def _match_paths(self, nodes):
1030 def _match_paths(self, nodes):
1032 for node in nodes:
1031 for node in nodes:
1033 if not node.is_dir():
1032 if not node.is_dir():
1034 continue
1033 continue
1035 match = self.path_re.match(node.path)
1034 match = self.path_re.match(node.path)
1036 if match:
1035 if match:
1037 yield node.path
1036 yield node.path
1038
1037
1039 def _priority(self, extension):
1038 def _priority(self, extension):
1040 renderer_priority = (
1039 renderer_priority = (
1041 0 if extension in self._renderer_extensions else 1)
1040 0 if extension in self._renderer_extensions else 1)
1042 extension_priority = self.default_priorities.get(
1041 extension_priority = self.default_priorities.get(
1043 extension, self.FALLBACK_PRIORITY)
1042 extension, self.FALLBACK_PRIORITY)
1044 return (renderer_priority, extension_priority)
1043 return (renderer_priority, extension_priority)
1045
1044
1046 def _sort_according_to_priority(self, matches):
1045 def _sort_according_to_priority(self, matches):
1047
1046
1048 def priority_and_path(match):
1047 def priority_and_path(match):
1049 return (match.priority, match.path)
1048 return (match.priority, match.path)
1050
1049
1051 return sorted(matches, key=priority_and_path)
1050 return sorted(matches, key=priority_and_path)
1052
1051
1053 def _sort_paths_according_to_priority(self, paths):
1052 def _sort_paths_according_to_priority(self, paths):
1054
1053
1055 def priority_and_path(path):
1054 def priority_and_path(path):
1056 return (self.path_priority.get(path, self.FALLBACK_PRIORITY), path)
1055 return (self.path_priority.get(path, self.FALLBACK_PRIORITY), path)
1057
1056
1058 return sorted(paths, key=priority_and_path)
1057 return sorted(paths, key=priority_and_path)
1059
1058
1060
1059
1061 class ReadmeMatch:
1060 class ReadmeMatch:
1062
1061
1063 def __init__(self, node, match, priority):
1062 def __init__(self, node, match, priority):
1064 self.node = node
1063 self.node = node
1065 self._match = match
1064 self._match = match
1066 self.priority = priority
1065 self.priority = priority
1067
1066
1068 @property
1067 @property
1069 def path(self):
1068 def path(self):
1070 return self.node.path
1069 return self.node.path
1071
1070
1072 def __repr__(self):
1071 def __repr__(self):
1073 return '<ReadmeMatch {} priority={}'.format(self.path, self.priority)
1072 return '<ReadmeMatch {} priority={}'.format(self.path, self.priority)
@@ -1,375 +1,376 b''
1
1
2 /******************************************************************************
2 /******************************************************************************
3 * *
3 * *
4 * DO NOT CHANGE THIS FILE MANUALLY *
4 * DO NOT CHANGE THIS FILE MANUALLY *
5 * *
5 * *
6 * *
6 * *
7 * This file is automatically generated when the app starts up with *
7 * This file is automatically generated when the app starts up with *
8 * generate_js_files = true *
8 * generate_js_files = true *
9 * *
9 * *
10 * To add a route here pass jsroute=True to the route definition in the app *
10 * To add a route here pass jsroute=True to the route definition in the app *
11 * *
11 * *
12 ******************************************************************************/
12 ******************************************************************************/
13 function registerRCRoutes() {
13 function registerRCRoutes() {
14 // routes registration
14 // routes registration
15 pyroutes.register('favicon', '/favicon.ico', []);
15 pyroutes.register('favicon', '/favicon.ico', []);
16 pyroutes.register('robots', '/robots.txt', []);
16 pyroutes.register('robots', '/robots.txt', []);
17 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
17 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
18 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
18 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
19 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
19 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
20 pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
20 pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
21 pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
21 pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
22 pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/_settings/integrations', ['repo_group_name']);
22 pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/_settings/integrations', ['repo_group_name']);
23 pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/_settings/integrations/new', ['repo_group_name']);
23 pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/_settings/integrations/new', ['repo_group_name']);
24 pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/_settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
24 pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/_settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
25 pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/_settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
25 pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/_settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
26 pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/_settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
26 pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/_settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
27 pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']);
27 pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']);
28 pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']);
28 pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']);
29 pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
29 pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
30 pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
30 pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
31 pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
31 pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
32 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
32 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
33 pyroutes.register('ops_ping', '/_admin/ops/ping', []);
33 pyroutes.register('ops_ping', '/_admin/ops/ping', []);
34 pyroutes.register('ops_error_test', '/_admin/ops/error', []);
34 pyroutes.register('ops_error_test', '/_admin/ops/error', []);
35 pyroutes.register('ops_redirect_test', '/_admin/ops/redirect', []);
35 pyroutes.register('ops_redirect_test', '/_admin/ops/redirect', []);
36 pyroutes.register('ops_ping_legacy', '/_admin/ping', []);
36 pyroutes.register('ops_ping_legacy', '/_admin/ping', []);
37 pyroutes.register('ops_error_test_legacy', '/_admin/error_test', []);
37 pyroutes.register('ops_error_test_legacy', '/_admin/error_test', []);
38 pyroutes.register('admin_home', '/_admin', []);
38 pyroutes.register('admin_home', '/_admin', []);
39 pyroutes.register('admin_audit_logs', '/_admin/audit_logs', []);
39 pyroutes.register('admin_audit_logs', '/_admin/audit_logs', []);
40 pyroutes.register('admin_audit_log_entry', '/_admin/audit_logs/%(audit_log_id)s', ['audit_log_id']);
40 pyroutes.register('admin_audit_log_entry', '/_admin/audit_logs/%(audit_log_id)s', ['audit_log_id']);
41 pyroutes.register('pull_requests_global_0', '/_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']);
41 pyroutes.register('pull_requests_global_0', '/_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']);
42 pyroutes.register('pull_requests_global_1', '/_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']);
42 pyroutes.register('pull_requests_global_1', '/_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']);
43 pyroutes.register('pull_requests_global', '/_admin/pull-request/%(pull_request_id)s', ['pull_request_id']);
43 pyroutes.register('pull_requests_global', '/_admin/pull-request/%(pull_request_id)s', ['pull_request_id']);
44 pyroutes.register('admin_settings_open_source', '/_admin/settings/open_source', []);
44 pyroutes.register('admin_settings_open_source', '/_admin/settings/open_source', []);
45 pyroutes.register('admin_settings_vcs_svn_generate_cfg', '/_admin/settings/vcs/svn_generate_cfg', []);
45 pyroutes.register('admin_settings_vcs_svn_generate_cfg', '/_admin/settings/vcs/svn_generate_cfg', []);
46 pyroutes.register('admin_settings_system', '/_admin/settings/system', []);
46 pyroutes.register('admin_settings_system', '/_admin/settings/system', []);
47 pyroutes.register('admin_settings_system_update', '/_admin/settings/system/updates', []);
47 pyroutes.register('admin_settings_system_update', '/_admin/settings/system/updates', []);
48 pyroutes.register('admin_settings_exception_tracker', '/_admin/settings/exceptions', []);
48 pyroutes.register('admin_settings_exception_tracker', '/_admin/settings/exceptions', []);
49 pyroutes.register('admin_settings_exception_tracker_delete_all', '/_admin/settings/exceptions/delete', []);
49 pyroutes.register('admin_settings_exception_tracker_delete_all', '/_admin/settings/exceptions/delete', []);
50 pyroutes.register('admin_settings_exception_tracker_show', '/_admin/settings/exceptions/%(exception_id)s', ['exception_id']);
50 pyroutes.register('admin_settings_exception_tracker_show', '/_admin/settings/exceptions/%(exception_id)s', ['exception_id']);
51 pyroutes.register('admin_settings_exception_tracker_delete', '/_admin/settings/exceptions/%(exception_id)s/delete', ['exception_id']);
51 pyroutes.register('admin_settings_exception_tracker_delete', '/_admin/settings/exceptions/%(exception_id)s/delete', ['exception_id']);
52 pyroutes.register('admin_settings_sessions', '/_admin/settings/sessions', []);
52 pyroutes.register('admin_settings_sessions', '/_admin/settings/sessions', []);
53 pyroutes.register('admin_settings_sessions_cleanup', '/_admin/settings/sessions/cleanup', []);
53 pyroutes.register('admin_settings_sessions_cleanup', '/_admin/settings/sessions/cleanup', []);
54 pyroutes.register('admin_settings_process_management', '/_admin/settings/process_management', []);
54 pyroutes.register('admin_settings_process_management', '/_admin/settings/process_management', []);
55 pyroutes.register('admin_settings_process_management_data', '/_admin/settings/process_management/data', []);
55 pyroutes.register('admin_settings_process_management_data', '/_admin/settings/process_management/data', []);
56 pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []);
56 pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []);
57 pyroutes.register('admin_settings_process_management_master_signal', '/_admin/settings/process_management/master_signal', []);
57 pyroutes.register('admin_settings_process_management_master_signal', '/_admin/settings/process_management/master_signal', []);
58 pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []);
58 pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []);
59 pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []);
59 pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []);
60 pyroutes.register('admin_settings', '/_admin/settings', []);
60 pyroutes.register('admin_settings', '/_admin/settings', []);
61 pyroutes.register('admin_settings_update', '/_admin/settings/update', []);
61 pyroutes.register('admin_settings_update', '/_admin/settings/update', []);
62 pyroutes.register('admin_settings_global', '/_admin/settings/global', []);
62 pyroutes.register('admin_settings_global', '/_admin/settings/global', []);
63 pyroutes.register('admin_settings_global_update', '/_admin/settings/global/update', []);
63 pyroutes.register('admin_settings_global_update', '/_admin/settings/global/update', []);
64 pyroutes.register('admin_settings_vcs', '/_admin/settings/vcs', []);
64 pyroutes.register('admin_settings_vcs', '/_admin/settings/vcs', []);
65 pyroutes.register('admin_settings_vcs_update', '/_admin/settings/vcs/update', []);
65 pyroutes.register('admin_settings_vcs_update', '/_admin/settings/vcs/update', []);
66 pyroutes.register('admin_settings_vcs_svn_pattern_delete', '/_admin/settings/vcs/svn_pattern_delete', []);
66 pyroutes.register('admin_settings_vcs_svn_pattern_delete', '/_admin/settings/vcs/svn_pattern_delete', []);
67 pyroutes.register('admin_settings_mapping', '/_admin/settings/mapping', []);
67 pyroutes.register('admin_settings_mapping', '/_admin/settings/mapping', []);
68 pyroutes.register('admin_settings_mapping_update', '/_admin/settings/mapping/update', []);
68 pyroutes.register('admin_settings_mapping_update', '/_admin/settings/mapping/update', []);
69 pyroutes.register('admin_settings_visual', '/_admin/settings/visual', []);
69 pyroutes.register('admin_settings_visual', '/_admin/settings/visual', []);
70 pyroutes.register('admin_settings_visual_update', '/_admin/settings/visual/update', []);
70 pyroutes.register('admin_settings_visual_update', '/_admin/settings/visual/update', []);
71 pyroutes.register('admin_settings_issuetracker', '/_admin/settings/issue-tracker', []);
71 pyroutes.register('admin_settings_issuetracker', '/_admin/settings/issue-tracker', []);
72 pyroutes.register('admin_settings_issuetracker_update', '/_admin/settings/issue-tracker/update', []);
72 pyroutes.register('admin_settings_issuetracker_update', '/_admin/settings/issue-tracker/update', []);
73 pyroutes.register('admin_settings_issuetracker_test', '/_admin/settings/issue-tracker/test', []);
73 pyroutes.register('admin_settings_issuetracker_test', '/_admin/settings/issue-tracker/test', []);
74 pyroutes.register('admin_settings_issuetracker_delete', '/_admin/settings/issue-tracker/delete', []);
74 pyroutes.register('admin_settings_issuetracker_delete', '/_admin/settings/issue-tracker/delete', []);
75 pyroutes.register('admin_settings_email', '/_admin/settings/email', []);
75 pyroutes.register('admin_settings_email', '/_admin/settings/email', []);
76 pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []);
76 pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []);
77 pyroutes.register('admin_settings_hooks', '/_admin/settings/hooks', []);
77 pyroutes.register('admin_settings_hooks', '/_admin/settings/hooks', []);
78 pyroutes.register('admin_settings_hooks_update', '/_admin/settings/hooks/update', []);
78 pyroutes.register('admin_settings_hooks_update', '/_admin/settings/hooks/update', []);
79 pyroutes.register('admin_settings_hooks_delete', '/_admin/settings/hooks/delete', []);
79 pyroutes.register('admin_settings_hooks_delete', '/_admin/settings/hooks/delete', []);
80 pyroutes.register('admin_settings_search', '/_admin/settings/search', []);
80 pyroutes.register('admin_settings_search', '/_admin/settings/search', []);
81 pyroutes.register('admin_settings_labs', '/_admin/settings/labs', []);
81 pyroutes.register('admin_settings_labs', '/_admin/settings/labs', []);
82 pyroutes.register('admin_settings_labs_update', '/_admin/settings/labs/update', []);
82 pyroutes.register('admin_settings_labs_update', '/_admin/settings/labs/update', []);
83 pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []);
83 pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []);
84 pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []);
84 pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []);
85 pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []);
85 pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []);
86 pyroutes.register('admin_permissions_global_update', '/_admin/permissions/global/update', []);
86 pyroutes.register('admin_permissions_global_update', '/_admin/permissions/global/update', []);
87 pyroutes.register('admin_permissions_object', '/_admin/permissions/object', []);
87 pyroutes.register('admin_permissions_object', '/_admin/permissions/object', []);
88 pyroutes.register('admin_permissions_object_update', '/_admin/permissions/object/update', []);
88 pyroutes.register('admin_permissions_object_update', '/_admin/permissions/object/update', []);
89 pyroutes.register('admin_permissions_ips', '/_admin/permissions/ips', []);
89 pyroutes.register('admin_permissions_ips', '/_admin/permissions/ips', []);
90 pyroutes.register('admin_permissions_overview', '/_admin/permissions/overview', []);
90 pyroutes.register('admin_permissions_overview', '/_admin/permissions/overview', []);
91 pyroutes.register('admin_permissions_auth_token_access', '/_admin/permissions/auth_token_access', []);
91 pyroutes.register('admin_permissions_auth_token_access', '/_admin/permissions/auth_token_access', []);
92 pyroutes.register('admin_permissions_ssh_keys', '/_admin/permissions/ssh_keys', []);
92 pyroutes.register('admin_permissions_ssh_keys', '/_admin/permissions/ssh_keys', []);
93 pyroutes.register('admin_permissions_ssh_keys_data', '/_admin/permissions/ssh_keys/data', []);
93 pyroutes.register('admin_permissions_ssh_keys_data', '/_admin/permissions/ssh_keys/data', []);
94 pyroutes.register('admin_permissions_ssh_keys_update', '/_admin/permissions/ssh_keys/update', []);
94 pyroutes.register('admin_permissions_ssh_keys_update', '/_admin/permissions/ssh_keys/update', []);
95 pyroutes.register('users', '/_admin/users', []);
95 pyroutes.register('users', '/_admin/users', []);
96 pyroutes.register('users_data', '/_admin/users_data', []);
96 pyroutes.register('users_data', '/_admin/users_data', []);
97 pyroutes.register('users_create', '/_admin/users/create', []);
97 pyroutes.register('users_create', '/_admin/users/create', []);
98 pyroutes.register('users_new', '/_admin/users/new', []);
98 pyroutes.register('users_new', '/_admin/users/new', []);
99 pyroutes.register('user_edit', '/_admin/users/%(user_id)s/edit', ['user_id']);
99 pyroutes.register('user_edit', '/_admin/users/%(user_id)s/edit', ['user_id']);
100 pyroutes.register('user_edit_advanced', '/_admin/users/%(user_id)s/edit/advanced', ['user_id']);
100 pyroutes.register('user_edit_advanced', '/_admin/users/%(user_id)s/edit/advanced', ['user_id']);
101 pyroutes.register('user_edit_global_perms', '/_admin/users/%(user_id)s/edit/global_permissions', ['user_id']);
101 pyroutes.register('user_edit_global_perms', '/_admin/users/%(user_id)s/edit/global_permissions', ['user_id']);
102 pyroutes.register('user_edit_global_perms_update', '/_admin/users/%(user_id)s/edit/global_permissions/update', ['user_id']);
102 pyroutes.register('user_edit_global_perms_update', '/_admin/users/%(user_id)s/edit/global_permissions/update', ['user_id']);
103 pyroutes.register('user_update', '/_admin/users/%(user_id)s/update', ['user_id']);
103 pyroutes.register('user_update', '/_admin/users/%(user_id)s/update', ['user_id']);
104 pyroutes.register('user_delete', '/_admin/users/%(user_id)s/delete', ['user_id']);
104 pyroutes.register('user_delete', '/_admin/users/%(user_id)s/delete', ['user_id']);
105 pyroutes.register('user_enable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_enable', ['user_id']);
105 pyroutes.register('user_enable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_enable', ['user_id']);
106 pyroutes.register('user_disable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_disable', ['user_id']);
106 pyroutes.register('user_disable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_disable', ['user_id']);
107 pyroutes.register('user_create_personal_repo_group', '/_admin/users/%(user_id)s/create_repo_group', ['user_id']);
107 pyroutes.register('user_create_personal_repo_group', '/_admin/users/%(user_id)s/create_repo_group', ['user_id']);
108 pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
108 pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
109 pyroutes.register('edit_user_ssh_keys', '/_admin/users/%(user_id)s/edit/ssh_keys', ['user_id']);
109 pyroutes.register('edit_user_ssh_keys', '/_admin/users/%(user_id)s/edit/ssh_keys', ['user_id']);
110 pyroutes.register('edit_user_ssh_keys_generate_keypair', '/_admin/users/%(user_id)s/edit/ssh_keys/generate', ['user_id']);
110 pyroutes.register('edit_user_ssh_keys_generate_keypair', '/_admin/users/%(user_id)s/edit/ssh_keys/generate', ['user_id']);
111 pyroutes.register('edit_user_ssh_keys_add', '/_admin/users/%(user_id)s/edit/ssh_keys/new', ['user_id']);
111 pyroutes.register('edit_user_ssh_keys_add', '/_admin/users/%(user_id)s/edit/ssh_keys/new', ['user_id']);
112 pyroutes.register('edit_user_ssh_keys_delete', '/_admin/users/%(user_id)s/edit/ssh_keys/delete', ['user_id']);
112 pyroutes.register('edit_user_ssh_keys_delete', '/_admin/users/%(user_id)s/edit/ssh_keys/delete', ['user_id']);
113 pyroutes.register('edit_user_emails', '/_admin/users/%(user_id)s/edit/emails', ['user_id']);
113 pyroutes.register('edit_user_emails', '/_admin/users/%(user_id)s/edit/emails', ['user_id']);
114 pyroutes.register('edit_user_emails_add', '/_admin/users/%(user_id)s/edit/emails/new', ['user_id']);
114 pyroutes.register('edit_user_emails_add', '/_admin/users/%(user_id)s/edit/emails/new', ['user_id']);
115 pyroutes.register('edit_user_emails_delete', '/_admin/users/%(user_id)s/edit/emails/delete', ['user_id']);
115 pyroutes.register('edit_user_emails_delete', '/_admin/users/%(user_id)s/edit/emails/delete', ['user_id']);
116 pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']);
116 pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']);
117 pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']);
117 pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']);
118 pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']);
118 pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']);
119 pyroutes.register('edit_user_perms_summary', '/_admin/users/%(user_id)s/edit/permissions_summary', ['user_id']);
119 pyroutes.register('edit_user_perms_summary', '/_admin/users/%(user_id)s/edit/permissions_summary', ['user_id']);
120 pyroutes.register('edit_user_perms_summary_json', '/_admin/users/%(user_id)s/edit/permissions_summary/json', ['user_id']);
120 pyroutes.register('edit_user_perms_summary_json', '/_admin/users/%(user_id)s/edit/permissions_summary/json', ['user_id']);
121 pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']);
121 pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']);
122 pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']);
122 pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']);
123 pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']);
123 pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']);
124 pyroutes.register('edit_user_caches', '/_admin/users/%(user_id)s/edit/caches', ['user_id']);
124 pyroutes.register('edit_user_caches', '/_admin/users/%(user_id)s/edit/caches', ['user_id']);
125 pyroutes.register('edit_user_caches_update', '/_admin/users/%(user_id)s/edit/caches/update', ['user_id']);
125 pyroutes.register('edit_user_caches_update', '/_admin/users/%(user_id)s/edit/caches/update', ['user_id']);
126 pyroutes.register('user_groups', '/_admin/user_groups', []);
126 pyroutes.register('user_groups', '/_admin/user_groups', []);
127 pyroutes.register('user_groups_data', '/_admin/user_groups_data', []);
127 pyroutes.register('user_groups_data', '/_admin/user_groups_data', []);
128 pyroutes.register('user_groups_new', '/_admin/user_groups/new', []);
128 pyroutes.register('user_groups_new', '/_admin/user_groups/new', []);
129 pyroutes.register('user_groups_create', '/_admin/user_groups/create', []);
129 pyroutes.register('user_groups_create', '/_admin/user_groups/create', []);
130 pyroutes.register('repos', '/_admin/repos', []);
130 pyroutes.register('repos', '/_admin/repos', []);
131 pyroutes.register('repo_new', '/_admin/repos/new', []);
131 pyroutes.register('repo_new', '/_admin/repos/new', []);
132 pyroutes.register('repo_create', '/_admin/repos/create', []);
132 pyroutes.register('repo_create', '/_admin/repos/create', []);
133 pyroutes.register('repo_groups', '/_admin/repo_groups', []);
133 pyroutes.register('repo_groups', '/_admin/repo_groups', []);
134 pyroutes.register('repo_groups_data', '/_admin/repo_groups_data', []);
134 pyroutes.register('repo_groups_data', '/_admin/repo_groups_data', []);
135 pyroutes.register('repo_group_new', '/_admin/repo_group/new', []);
135 pyroutes.register('repo_group_new', '/_admin/repo_group/new', []);
136 pyroutes.register('repo_group_create', '/_admin/repo_group/create', []);
136 pyroutes.register('repo_group_create', '/_admin/repo_group/create', []);
137 pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []);
137 pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []);
138 pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []);
138 pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []);
139 pyroutes.register('channelstream_proxy', '/_channelstream', []);
139 pyroutes.register('channelstream_proxy', '/_channelstream', []);
140 pyroutes.register('upload_file', '/_file_store/upload', []);
140 pyroutes.register('upload_file', '/_file_store/upload', []);
141 pyroutes.register('download_file', '/_file_store/download/%(fid)s', ['fid']);
141 pyroutes.register('download_file', '/_file_store/download/%(fid)s', ['fid']);
142 pyroutes.register('logout', '/_admin/logout', []);
142 pyroutes.register('logout', '/_admin/logout', []);
143 pyroutes.register('reset_password', '/_admin/password_reset', []);
143 pyroutes.register('reset_password', '/_admin/password_reset', []);
144 pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []);
144 pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []);
145 pyroutes.register('home', '/', []);
145 pyroutes.register('home', '/', []);
146 pyroutes.register('user_autocomplete_data', '/_users', []);
146 pyroutes.register('user_autocomplete_data', '/_users', []);
147 pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
147 pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
148 pyroutes.register('repo_list_data', '/_repos', []);
148 pyroutes.register('repo_list_data', '/_repos', []);
149 pyroutes.register('repo_group_list_data', '/_repo_groups', []);
149 pyroutes.register('repo_group_list_data', '/_repo_groups', []);
150 pyroutes.register('goto_switcher_data', '/_goto_data', []);
150 pyroutes.register('goto_switcher_data', '/_goto_data', []);
151 pyroutes.register('markup_preview', '/_markup_preview', []);
151 pyroutes.register('markup_preview', '/_markup_preview', []);
152 pyroutes.register('file_preview', '/_file_preview', []);
152 pyroutes.register('file_preview', '/_file_preview', []);
153 pyroutes.register('store_user_session_value', '/_store_session_attr', []);
153 pyroutes.register('store_user_session_value', '/_store_session_attr', []);
154 pyroutes.register('journal', '/_admin/journal', []);
154 pyroutes.register('journal', '/_admin/journal', []);
155 pyroutes.register('journal_rss', '/_admin/journal/rss', []);
155 pyroutes.register('journal_rss', '/_admin/journal/rss', []);
156 pyroutes.register('journal_atom', '/_admin/journal/atom', []);
156 pyroutes.register('journal_atom', '/_admin/journal/atom', []);
157 pyroutes.register('journal_public', '/_admin/public_journal', []);
157 pyroutes.register('journal_public', '/_admin/public_journal', []);
158 pyroutes.register('journal_public_atom', '/_admin/public_journal/atom', []);
158 pyroutes.register('journal_public_atom', '/_admin/public_journal/atom', []);
159 pyroutes.register('journal_public_atom_old', '/_admin/public_journal_atom', []);
159 pyroutes.register('journal_public_atom_old', '/_admin/public_journal_atom', []);
160 pyroutes.register('journal_public_rss', '/_admin/public_journal/rss', []);
160 pyroutes.register('journal_public_rss', '/_admin/public_journal/rss', []);
161 pyroutes.register('journal_public_rss_old', '/_admin/public_journal_rss', []);
161 pyroutes.register('journal_public_rss_old', '/_admin/public_journal_rss', []);
162 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
162 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
163 pyroutes.register('repo_creating', '/%(repo_name)s/repo_creating', ['repo_name']);
163 pyroutes.register('repo_creating', '/%(repo_name)s/repo_creating', ['repo_name']);
164 pyroutes.register('repo_creating_check', '/%(repo_name)s/repo_creating_check', ['repo_name']);
164 pyroutes.register('repo_creating_check', '/%(repo_name)s/repo_creating_check', ['repo_name']);
165 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
165 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
166 pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
166 pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
167 pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
167 pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
168 pyroutes.register('repo_commit_children', '/%(repo_name)s/changeset_children/%(commit_id)s', ['repo_name', 'commit_id']);
168 pyroutes.register('repo_commit_children', '/%(repo_name)s/changeset_children/%(commit_id)s', ['repo_name', 'commit_id']);
169 pyroutes.register('repo_commit_parents', '/%(repo_name)s/changeset_parents/%(commit_id)s', ['repo_name', 'commit_id']);
169 pyroutes.register('repo_commit_parents', '/%(repo_name)s/changeset_parents/%(commit_id)s', ['repo_name', 'commit_id']);
170 pyroutes.register('repo_commit_raw', '/%(repo_name)s/changeset-diff/%(commit_id)s', ['repo_name', 'commit_id']);
170 pyroutes.register('repo_commit_raw', '/%(repo_name)s/changeset-diff/%(commit_id)s', ['repo_name', 'commit_id']);
171 pyroutes.register('repo_commit_patch', '/%(repo_name)s/changeset-patch/%(commit_id)s', ['repo_name', 'commit_id']);
171 pyroutes.register('repo_commit_patch', '/%(repo_name)s/changeset-patch/%(commit_id)s', ['repo_name', 'commit_id']);
172 pyroutes.register('repo_commit_download', '/%(repo_name)s/changeset-download/%(commit_id)s', ['repo_name', 'commit_id']);
172 pyroutes.register('repo_commit_download', '/%(repo_name)s/changeset-download/%(commit_id)s', ['repo_name', 'commit_id']);
173 pyroutes.register('repo_commit_data', '/%(repo_name)s/changeset-data/%(commit_id)s', ['repo_name', 'commit_id']);
173 pyroutes.register('repo_commit_data', '/%(repo_name)s/changeset-data/%(commit_id)s', ['repo_name', 'commit_id']);
174 pyroutes.register('repo_commit_comment_create', '/%(repo_name)s/changeset/%(commit_id)s/comment/create', ['repo_name', 'commit_id']);
174 pyroutes.register('repo_commit_comment_create', '/%(repo_name)s/changeset/%(commit_id)s/comment/create', ['repo_name', 'commit_id']);
175 pyroutes.register('repo_commit_comment_preview', '/%(repo_name)s/changeset/%(commit_id)s/comment/preview', ['repo_name', 'commit_id']);
175 pyroutes.register('repo_commit_comment_preview', '/%(repo_name)s/changeset/%(commit_id)s/comment/preview', ['repo_name', 'commit_id']);
176 pyroutes.register('repo_commit_comment_delete', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/delete', ['repo_name', 'commit_id', 'comment_id']);
176 pyroutes.register('repo_commit_comment_delete', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/delete', ['repo_name', 'commit_id', 'comment_id']);
177 pyroutes.register('repo_commit_raw_deprecated', '/%(repo_name)s/raw-changeset/%(commit_id)s', ['repo_name', 'commit_id']);
177 pyroutes.register('repo_commit_raw_deprecated', '/%(repo_name)s/raw-changeset/%(commit_id)s', ['repo_name', 'commit_id']);
178 pyroutes.register('repo_archivefile', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
178 pyroutes.register('repo_archivefile', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
179 pyroutes.register('repo_files_diff', '/%(repo_name)s/diff/%(f_path)s', ['repo_name', 'f_path']);
179 pyroutes.register('repo_files_diff', '/%(repo_name)s/diff/%(f_path)s', ['repo_name', 'f_path']);
180 pyroutes.register('repo_files_diff_2way_redirect', '/%(repo_name)s/diff-2way/%(f_path)s', ['repo_name', 'f_path']);
180 pyroutes.register('repo_files_diff_2way_redirect', '/%(repo_name)s/diff-2way/%(f_path)s', ['repo_name', 'f_path']);
181 pyroutes.register('repo_files', '/%(repo_name)s/files/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
181 pyroutes.register('repo_files', '/%(repo_name)s/files/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
182 pyroutes.register('repo_files:default_path', '/%(repo_name)s/files/%(commit_id)s/', ['repo_name', 'commit_id']);
182 pyroutes.register('repo_files:default_path', '/%(repo_name)s/files/%(commit_id)s/', ['repo_name', 'commit_id']);
183 pyroutes.register('repo_files:default_commit', '/%(repo_name)s/files', ['repo_name']);
183 pyroutes.register('repo_files:default_commit', '/%(repo_name)s/files', ['repo_name']);
184 pyroutes.register('repo_files:rendered', '/%(repo_name)s/render/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
184 pyroutes.register('repo_files:rendered', '/%(repo_name)s/render/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
185 pyroutes.register('repo_files:annotated', '/%(repo_name)s/annotate/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
185 pyroutes.register('repo_files:annotated', '/%(repo_name)s/annotate/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
186 pyroutes.register('repo_files:annotated_previous', '/%(repo_name)s/annotate-previous/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
186 pyroutes.register('repo_files:annotated_previous', '/%(repo_name)s/annotate-previous/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
187 pyroutes.register('repo_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
187 pyroutes.register('repo_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
188 pyroutes.register('repo_nodetree_full:default_path', '/%(repo_name)s/nodetree_full/%(commit_id)s/', ['repo_name', 'commit_id']);
188 pyroutes.register('repo_nodetree_full:default_path', '/%(repo_name)s/nodetree_full/%(commit_id)s/', ['repo_name', 'commit_id']);
189 pyroutes.register('repo_files_nodelist', '/%(repo_name)s/nodelist/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
189 pyroutes.register('repo_files_nodelist', '/%(repo_name)s/nodelist/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
190 pyroutes.register('repo_file_raw', '/%(repo_name)s/raw/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
190 pyroutes.register('repo_file_raw', '/%(repo_name)s/raw/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
191 pyroutes.register('repo_file_download', '/%(repo_name)s/download/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
191 pyroutes.register('repo_file_download', '/%(repo_name)s/download/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
192 pyroutes.register('repo_file_download:legacy', '/%(repo_name)s/rawfile/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
192 pyroutes.register('repo_file_download:legacy', '/%(repo_name)s/rawfile/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
193 pyroutes.register('repo_file_history', '/%(repo_name)s/history/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
193 pyroutes.register('repo_file_history', '/%(repo_name)s/history/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
194 pyroutes.register('repo_file_authors', '/%(repo_name)s/authors/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
194 pyroutes.register('repo_file_authors', '/%(repo_name)s/authors/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
195 pyroutes.register('repo_files_remove_file', '/%(repo_name)s/remove_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
195 pyroutes.register('repo_files_remove_file', '/%(repo_name)s/remove_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
196 pyroutes.register('repo_files_delete_file', '/%(repo_name)s/delete_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
196 pyroutes.register('repo_files_delete_file', '/%(repo_name)s/delete_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
197 pyroutes.register('repo_files_edit_file', '/%(repo_name)s/edit_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
197 pyroutes.register('repo_files_edit_file', '/%(repo_name)s/edit_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
198 pyroutes.register('repo_files_update_file', '/%(repo_name)s/update_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
198 pyroutes.register('repo_files_update_file', '/%(repo_name)s/update_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
199 pyroutes.register('repo_files_add_file', '/%(repo_name)s/add_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
199 pyroutes.register('repo_files_add_file', '/%(repo_name)s/add_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
200 pyroutes.register('repo_files_upload_file', '/%(repo_name)s/upload_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
200 pyroutes.register('repo_files_upload_file', '/%(repo_name)s/upload_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
201 pyroutes.register('repo_files_create_file', '/%(repo_name)s/create_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
201 pyroutes.register('repo_files_create_file', '/%(repo_name)s/create_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
202 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
202 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
203 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
203 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
204 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
204 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
205 pyroutes.register('repo_commits', '/%(repo_name)s/commits', ['repo_name']);
205 pyroutes.register('repo_commits', '/%(repo_name)s/commits', ['repo_name']);
206 pyroutes.register('repo_commits_file', '/%(repo_name)s/commits/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
206 pyroutes.register('repo_commits_file', '/%(repo_name)s/commits/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
207 pyroutes.register('repo_commits_elements', '/%(repo_name)s/commits_elements', ['repo_name']);
207 pyroutes.register('repo_commits_elements', '/%(repo_name)s/commits_elements', ['repo_name']);
208 pyroutes.register('repo_commits_elements_file', '/%(repo_name)s/commits_elements/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
208 pyroutes.register('repo_commits_elements_file', '/%(repo_name)s/commits_elements/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
209 pyroutes.register('repo_changelog', '/%(repo_name)s/changelog', ['repo_name']);
209 pyroutes.register('repo_changelog', '/%(repo_name)s/changelog', ['repo_name']);
210 pyroutes.register('repo_changelog_file', '/%(repo_name)s/changelog/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
210 pyroutes.register('repo_changelog_file', '/%(repo_name)s/changelog/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
211 pyroutes.register('repo_compare_select', '/%(repo_name)s/compare', ['repo_name']);
211 pyroutes.register('repo_compare_select', '/%(repo_name)s/compare', ['repo_name']);
212 pyroutes.register('repo_compare', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']);
212 pyroutes.register('repo_compare', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']);
213 pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']);
213 pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']);
214 pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']);
214 pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']);
215 pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']);
215 pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']);
216 pyroutes.register('repo_fork_new', '/%(repo_name)s/fork', ['repo_name']);
216 pyroutes.register('repo_fork_new', '/%(repo_name)s/fork', ['repo_name']);
217 pyroutes.register('repo_fork_create', '/%(repo_name)s/fork/create', ['repo_name']);
217 pyroutes.register('repo_fork_create', '/%(repo_name)s/fork/create', ['repo_name']);
218 pyroutes.register('repo_forks_show_all', '/%(repo_name)s/forks', ['repo_name']);
218 pyroutes.register('repo_forks_show_all', '/%(repo_name)s/forks', ['repo_name']);
219 pyroutes.register('repo_forks_data', '/%(repo_name)s/forks/data', ['repo_name']);
219 pyroutes.register('repo_forks_data', '/%(repo_name)s/forks/data', ['repo_name']);
220 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
220 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
221 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
221 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
222 pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
222 pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
223 pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
223 pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
224 pyroutes.register('pullrequest_repo_targets', '/%(repo_name)s/pull-request/repo-targets', ['repo_name']);
224 pyroutes.register('pullrequest_repo_targets', '/%(repo_name)s/pull-request/repo-targets', ['repo_name']);
225 pyroutes.register('pullrequest_new', '/%(repo_name)s/pull-request/new', ['repo_name']);
225 pyroutes.register('pullrequest_new', '/%(repo_name)s/pull-request/new', ['repo_name']);
226 pyroutes.register('pullrequest_create', '/%(repo_name)s/pull-request/create', ['repo_name']);
226 pyroutes.register('pullrequest_create', '/%(repo_name)s/pull-request/create', ['repo_name']);
227 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s/update', ['repo_name', 'pull_request_id']);
227 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s/update', ['repo_name', 'pull_request_id']);
228 pyroutes.register('pullrequest_merge', '/%(repo_name)s/pull-request/%(pull_request_id)s/merge', ['repo_name', 'pull_request_id']);
228 pyroutes.register('pullrequest_merge', '/%(repo_name)s/pull-request/%(pull_request_id)s/merge', ['repo_name', 'pull_request_id']);
229 pyroutes.register('pullrequest_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/delete', ['repo_name', 'pull_request_id']);
229 pyroutes.register('pullrequest_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/delete', ['repo_name', 'pull_request_id']);
230 pyroutes.register('pullrequest_comment_create', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment', ['repo_name', 'pull_request_id']);
230 pyroutes.register('pullrequest_comment_create', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment', ['repo_name', 'pull_request_id']);
231 pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/delete', ['repo_name', 'pull_request_id', 'comment_id']);
231 pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/delete', ['repo_name', 'pull_request_id', 'comment_id']);
232 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
232 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
233 pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']);
233 pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']);
234 pyroutes.register('edit_repo_advanced_archive', '/%(repo_name)s/settings/advanced/archive', ['repo_name']);
234 pyroutes.register('edit_repo_advanced_archive', '/%(repo_name)s/settings/advanced/archive', ['repo_name']);
235 pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']);
235 pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']);
236 pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']);
236 pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']);
237 pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']);
237 pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']);
238 pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']);
238 pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']);
239 pyroutes.register('edit_repo_advanced_hooks', '/%(repo_name)s/settings/advanced/hooks', ['repo_name']);
239 pyroutes.register('edit_repo_advanced_hooks', '/%(repo_name)s/settings/advanced/hooks', ['repo_name']);
240 pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
240 pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
241 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
241 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
242 pyroutes.register('edit_repo_perms_set_private', '/%(repo_name)s/settings/permissions/set_private', ['repo_name']);
242 pyroutes.register('edit_repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']);
243 pyroutes.register('edit_repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']);
243 pyroutes.register('edit_repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']);
244 pyroutes.register('edit_repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']);
244 pyroutes.register('edit_repo_fields', '/%(repo_name)s/settings/fields', ['repo_name']);
245 pyroutes.register('edit_repo_fields', '/%(repo_name)s/settings/fields', ['repo_name']);
245 pyroutes.register('edit_repo_fields_create', '/%(repo_name)s/settings/fields/create', ['repo_name']);
246 pyroutes.register('edit_repo_fields_create', '/%(repo_name)s/settings/fields/create', ['repo_name']);
246 pyroutes.register('edit_repo_fields_delete', '/%(repo_name)s/settings/fields/%(field_id)s/delete', ['repo_name', 'field_id']);
247 pyroutes.register('edit_repo_fields_delete', '/%(repo_name)s/settings/fields/%(field_id)s/delete', ['repo_name', 'field_id']);
247 pyroutes.register('repo_edit_toggle_locking', '/%(repo_name)s/settings/toggle_locking', ['repo_name']);
248 pyroutes.register('repo_edit_toggle_locking', '/%(repo_name)s/settings/toggle_locking', ['repo_name']);
248 pyroutes.register('edit_repo_remote', '/%(repo_name)s/settings/remote', ['repo_name']);
249 pyroutes.register('edit_repo_remote', '/%(repo_name)s/settings/remote', ['repo_name']);
249 pyroutes.register('edit_repo_remote_pull', '/%(repo_name)s/settings/remote/pull', ['repo_name']);
250 pyroutes.register('edit_repo_remote_pull', '/%(repo_name)s/settings/remote/pull', ['repo_name']);
250 pyroutes.register('edit_repo_statistics', '/%(repo_name)s/settings/statistics', ['repo_name']);
251 pyroutes.register('edit_repo_statistics', '/%(repo_name)s/settings/statistics', ['repo_name']);
251 pyroutes.register('edit_repo_statistics_reset', '/%(repo_name)s/settings/statistics/update', ['repo_name']);
252 pyroutes.register('edit_repo_statistics_reset', '/%(repo_name)s/settings/statistics/update', ['repo_name']);
252 pyroutes.register('edit_repo_issuetracker', '/%(repo_name)s/settings/issue_trackers', ['repo_name']);
253 pyroutes.register('edit_repo_issuetracker', '/%(repo_name)s/settings/issue_trackers', ['repo_name']);
253 pyroutes.register('edit_repo_issuetracker_test', '/%(repo_name)s/settings/issue_trackers/test', ['repo_name']);
254 pyroutes.register('edit_repo_issuetracker_test', '/%(repo_name)s/settings/issue_trackers/test', ['repo_name']);
254 pyroutes.register('edit_repo_issuetracker_delete', '/%(repo_name)s/settings/issue_trackers/delete', ['repo_name']);
255 pyroutes.register('edit_repo_issuetracker_delete', '/%(repo_name)s/settings/issue_trackers/delete', ['repo_name']);
255 pyroutes.register('edit_repo_issuetracker_update', '/%(repo_name)s/settings/issue_trackers/update', ['repo_name']);
256 pyroutes.register('edit_repo_issuetracker_update', '/%(repo_name)s/settings/issue_trackers/update', ['repo_name']);
256 pyroutes.register('edit_repo_vcs', '/%(repo_name)s/settings/vcs', ['repo_name']);
257 pyroutes.register('edit_repo_vcs', '/%(repo_name)s/settings/vcs', ['repo_name']);
257 pyroutes.register('edit_repo_vcs_update', '/%(repo_name)s/settings/vcs/update', ['repo_name']);
258 pyroutes.register('edit_repo_vcs_update', '/%(repo_name)s/settings/vcs/update', ['repo_name']);
258 pyroutes.register('edit_repo_vcs_svn_pattern_delete', '/%(repo_name)s/settings/vcs/svn_pattern/delete', ['repo_name']);
259 pyroutes.register('edit_repo_vcs_svn_pattern_delete', '/%(repo_name)s/settings/vcs/svn_pattern/delete', ['repo_name']);
259 pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']);
260 pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']);
260 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/settings/review/default-reviewers', ['repo_name']);
261 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/settings/review/default-reviewers', ['repo_name']);
261 pyroutes.register('edit_repo_strip', '/%(repo_name)s/settings/strip', ['repo_name']);
262 pyroutes.register('edit_repo_strip', '/%(repo_name)s/settings/strip', ['repo_name']);
262 pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']);
263 pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']);
263 pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']);
264 pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']);
264 pyroutes.register('edit_repo_audit_logs', '/%(repo_name)s/settings/audit_logs', ['repo_name']);
265 pyroutes.register('edit_repo_audit_logs', '/%(repo_name)s/settings/audit_logs', ['repo_name']);
265 pyroutes.register('rss_feed_home', '/%(repo_name)s/feed/rss', ['repo_name']);
266 pyroutes.register('rss_feed_home', '/%(repo_name)s/feed/rss', ['repo_name']);
266 pyroutes.register('atom_feed_home', '/%(repo_name)s/feed/atom', ['repo_name']);
267 pyroutes.register('atom_feed_home', '/%(repo_name)s/feed/atom', ['repo_name']);
267 pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']);
268 pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']);
268 pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']);
269 pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']);
269 pyroutes.register('edit_repo_group', '/%(repo_group_name)s/_edit', ['repo_group_name']);
270 pyroutes.register('edit_repo_group', '/%(repo_group_name)s/_edit', ['repo_group_name']);
270 pyroutes.register('edit_repo_group_advanced', '/%(repo_group_name)s/_settings/advanced', ['repo_group_name']);
271 pyroutes.register('edit_repo_group_advanced', '/%(repo_group_name)s/_settings/advanced', ['repo_group_name']);
271 pyroutes.register('edit_repo_group_advanced_delete', '/%(repo_group_name)s/_settings/advanced/delete', ['repo_group_name']);
272 pyroutes.register('edit_repo_group_advanced_delete', '/%(repo_group_name)s/_settings/advanced/delete', ['repo_group_name']);
272 pyroutes.register('edit_repo_group_perms', '/%(repo_group_name)s/_settings/permissions', ['repo_group_name']);
273 pyroutes.register('edit_repo_group_perms', '/%(repo_group_name)s/_settings/permissions', ['repo_group_name']);
273 pyroutes.register('edit_repo_group_perms_update', '/%(repo_group_name)s/_settings/permissions/update', ['repo_group_name']);
274 pyroutes.register('edit_repo_group_perms_update', '/%(repo_group_name)s/_settings/permissions/update', ['repo_group_name']);
274 pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']);
275 pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']);
275 pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']);
276 pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']);
276 pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']);
277 pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']);
277 pyroutes.register('edit_user_group_perms_summary', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary', ['user_group_id']);
278 pyroutes.register('edit_user_group_perms_summary', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary', ['user_group_id']);
278 pyroutes.register('edit_user_group_perms_summary_json', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary/json', ['user_group_id']);
279 pyroutes.register('edit_user_group_perms_summary_json', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary/json', ['user_group_id']);
279 pyroutes.register('edit_user_group', '/_admin/user_groups/%(user_group_id)s/edit', ['user_group_id']);
280 pyroutes.register('edit_user_group', '/_admin/user_groups/%(user_group_id)s/edit', ['user_group_id']);
280 pyroutes.register('user_groups_update', '/_admin/user_groups/%(user_group_id)s/update', ['user_group_id']);
281 pyroutes.register('user_groups_update', '/_admin/user_groups/%(user_group_id)s/update', ['user_group_id']);
281 pyroutes.register('edit_user_group_global_perms', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions', ['user_group_id']);
282 pyroutes.register('edit_user_group_global_perms', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions', ['user_group_id']);
282 pyroutes.register('edit_user_group_global_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions/update', ['user_group_id']);
283 pyroutes.register('edit_user_group_global_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions/update', ['user_group_id']);
283 pyroutes.register('edit_user_group_perms', '/_admin/user_groups/%(user_group_id)s/edit/permissions', ['user_group_id']);
284 pyroutes.register('edit_user_group_perms', '/_admin/user_groups/%(user_group_id)s/edit/permissions', ['user_group_id']);
284 pyroutes.register('edit_user_group_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/permissions/update', ['user_group_id']);
285 pyroutes.register('edit_user_group_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/permissions/update', ['user_group_id']);
285 pyroutes.register('edit_user_group_advanced', '/_admin/user_groups/%(user_group_id)s/edit/advanced', ['user_group_id']);
286 pyroutes.register('edit_user_group_advanced', '/_admin/user_groups/%(user_group_id)s/edit/advanced', ['user_group_id']);
286 pyroutes.register('edit_user_group_advanced_sync', '/_admin/user_groups/%(user_group_id)s/edit/advanced/sync', ['user_group_id']);
287 pyroutes.register('edit_user_group_advanced_sync', '/_admin/user_groups/%(user_group_id)s/edit/advanced/sync', ['user_group_id']);
287 pyroutes.register('user_groups_delete', '/_admin/user_groups/%(user_group_id)s/delete', ['user_group_id']);
288 pyroutes.register('user_groups_delete', '/_admin/user_groups/%(user_group_id)s/delete', ['user_group_id']);
288 pyroutes.register('search', '/_admin/search', []);
289 pyroutes.register('search', '/_admin/search', []);
289 pyroutes.register('search_repo', '/%(repo_name)s/_search', ['repo_name']);
290 pyroutes.register('search_repo', '/%(repo_name)s/_search', ['repo_name']);
290 pyroutes.register('search_repo_alt', '/%(repo_name)s/search', ['repo_name']);
291 pyroutes.register('search_repo_alt', '/%(repo_name)s/search', ['repo_name']);
291 pyroutes.register('search_repo_group', '/%(repo_group_name)s/_search', ['repo_group_name']);
292 pyroutes.register('search_repo_group', '/%(repo_group_name)s/_search', ['repo_group_name']);
292 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
293 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
293 pyroutes.register('user_group_profile', '/_profile_user_group/%(user_group_name)s', ['user_group_name']);
294 pyroutes.register('user_group_profile', '/_profile_user_group/%(user_group_name)s', ['user_group_name']);
294 pyroutes.register('my_account_profile', '/_admin/my_account/profile', []);
295 pyroutes.register('my_account_profile', '/_admin/my_account/profile', []);
295 pyroutes.register('my_account_edit', '/_admin/my_account/edit', []);
296 pyroutes.register('my_account_edit', '/_admin/my_account/edit', []);
296 pyroutes.register('my_account_update', '/_admin/my_account/update', []);
297 pyroutes.register('my_account_update', '/_admin/my_account/update', []);
297 pyroutes.register('my_account_password', '/_admin/my_account/password', []);
298 pyroutes.register('my_account_password', '/_admin/my_account/password', []);
298 pyroutes.register('my_account_password_update', '/_admin/my_account/password/update', []);
299 pyroutes.register('my_account_password_update', '/_admin/my_account/password/update', []);
299 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
300 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
300 pyroutes.register('my_account_ssh_keys', '/_admin/my_account/ssh_keys', []);
301 pyroutes.register('my_account_ssh_keys', '/_admin/my_account/ssh_keys', []);
301 pyroutes.register('my_account_ssh_keys_generate', '/_admin/my_account/ssh_keys/generate', []);
302 pyroutes.register('my_account_ssh_keys_generate', '/_admin/my_account/ssh_keys/generate', []);
302 pyroutes.register('my_account_ssh_keys_add', '/_admin/my_account/ssh_keys/new', []);
303 pyroutes.register('my_account_ssh_keys_add', '/_admin/my_account/ssh_keys/new', []);
303 pyroutes.register('my_account_ssh_keys_delete', '/_admin/my_account/ssh_keys/delete', []);
304 pyroutes.register('my_account_ssh_keys_delete', '/_admin/my_account/ssh_keys/delete', []);
304 pyroutes.register('my_account_user_group_membership', '/_admin/my_account/user_group_membership', []);
305 pyroutes.register('my_account_user_group_membership', '/_admin/my_account/user_group_membership', []);
305 pyroutes.register('my_account_emails', '/_admin/my_account/emails', []);
306 pyroutes.register('my_account_emails', '/_admin/my_account/emails', []);
306 pyroutes.register('my_account_emails_add', '/_admin/my_account/emails/new', []);
307 pyroutes.register('my_account_emails_add', '/_admin/my_account/emails/new', []);
307 pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []);
308 pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []);
308 pyroutes.register('my_account_repos', '/_admin/my_account/repos', []);
309 pyroutes.register('my_account_repos', '/_admin/my_account/repos', []);
309 pyroutes.register('my_account_watched', '/_admin/my_account/watched', []);
310 pyroutes.register('my_account_watched', '/_admin/my_account/watched', []);
310 pyroutes.register('my_account_bookmarks', '/_admin/my_account/bookmarks', []);
311 pyroutes.register('my_account_bookmarks', '/_admin/my_account/bookmarks', []);
311 pyroutes.register('my_account_bookmarks_update', '/_admin/my_account/bookmarks/update', []);
312 pyroutes.register('my_account_bookmarks_update', '/_admin/my_account/bookmarks/update', []);
312 pyroutes.register('my_account_goto_bookmark', '/_admin/my_account/bookmark/%(bookmark_id)s', ['bookmark_id']);
313 pyroutes.register('my_account_goto_bookmark', '/_admin/my_account/bookmark/%(bookmark_id)s', ['bookmark_id']);
313 pyroutes.register('my_account_perms', '/_admin/my_account/perms', []);
314 pyroutes.register('my_account_perms', '/_admin/my_account/perms', []);
314 pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []);
315 pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []);
315 pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []);
316 pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []);
316 pyroutes.register('my_account_pullrequests', '/_admin/my_account/pull_requests', []);
317 pyroutes.register('my_account_pullrequests', '/_admin/my_account/pull_requests', []);
317 pyroutes.register('my_account_pullrequests_data', '/_admin/my_account/pull_requests/data', []);
318 pyroutes.register('my_account_pullrequests_data', '/_admin/my_account/pull_requests/data', []);
318 pyroutes.register('notifications_show_all', '/_admin/notifications', []);
319 pyroutes.register('notifications_show_all', '/_admin/notifications', []);
319 pyroutes.register('notifications_mark_all_read', '/_admin/notifications/mark_all_read', []);
320 pyroutes.register('notifications_mark_all_read', '/_admin/notifications/mark_all_read', []);
320 pyroutes.register('notifications_show', '/_admin/notifications/%(notification_id)s', ['notification_id']);
321 pyroutes.register('notifications_show', '/_admin/notifications/%(notification_id)s', ['notification_id']);
321 pyroutes.register('notifications_update', '/_admin/notifications/%(notification_id)s/update', ['notification_id']);
322 pyroutes.register('notifications_update', '/_admin/notifications/%(notification_id)s/update', ['notification_id']);
322 pyroutes.register('notifications_delete', '/_admin/notifications/%(notification_id)s/delete', ['notification_id']);
323 pyroutes.register('notifications_delete', '/_admin/notifications/%(notification_id)s/delete', ['notification_id']);
323 pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []);
324 pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []);
324 pyroutes.register('gists_show', '/_admin/gists', []);
325 pyroutes.register('gists_show', '/_admin/gists', []);
325 pyroutes.register('gists_new', '/_admin/gists/new', []);
326 pyroutes.register('gists_new', '/_admin/gists/new', []);
326 pyroutes.register('gists_create', '/_admin/gists/create', []);
327 pyroutes.register('gists_create', '/_admin/gists/create', []);
327 pyroutes.register('gist_show', '/_admin/gists/%(gist_id)s', ['gist_id']);
328 pyroutes.register('gist_show', '/_admin/gists/%(gist_id)s', ['gist_id']);
328 pyroutes.register('gist_delete', '/_admin/gists/%(gist_id)s/delete', ['gist_id']);
329 pyroutes.register('gist_delete', '/_admin/gists/%(gist_id)s/delete', ['gist_id']);
329 pyroutes.register('gist_edit', '/_admin/gists/%(gist_id)s/edit', ['gist_id']);
330 pyroutes.register('gist_edit', '/_admin/gists/%(gist_id)s/edit', ['gist_id']);
330 pyroutes.register('gist_edit_check_revision', '/_admin/gists/%(gist_id)s/edit/check_revision', ['gist_id']);
331 pyroutes.register('gist_edit_check_revision', '/_admin/gists/%(gist_id)s/edit/check_revision', ['gist_id']);
331 pyroutes.register('gist_update', '/_admin/gists/%(gist_id)s/update', ['gist_id']);
332 pyroutes.register('gist_update', '/_admin/gists/%(gist_id)s/update', ['gist_id']);
332 pyroutes.register('gist_show_rev', '/_admin/gists/%(gist_id)s/%(revision)s', ['gist_id', 'revision']);
333 pyroutes.register('gist_show_rev', '/_admin/gists/%(gist_id)s/%(revision)s', ['gist_id', 'revision']);
333 pyroutes.register('gist_show_formatted', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s', ['gist_id', 'revision', 'format']);
334 pyroutes.register('gist_show_formatted', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s', ['gist_id', 'revision', 'format']);
334 pyroutes.register('gist_show_formatted_path', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s/%(f_path)s', ['gist_id', 'revision', 'format', 'f_path']);
335 pyroutes.register('gist_show_formatted_path', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s/%(f_path)s', ['gist_id', 'revision', 'format', 'f_path']);
335 pyroutes.register('debug_style_home', '/_admin/debug_style', []);
336 pyroutes.register('debug_style_home', '/_admin/debug_style', []);
336 pyroutes.register('debug_style_template', '/_admin/debug_style/t/%(t_path)s', ['t_path']);
337 pyroutes.register('debug_style_template', '/_admin/debug_style/t/%(t_path)s', ['t_path']);
337 pyroutes.register('apiv2', '/_admin/api', []);
338 pyroutes.register('apiv2', '/_admin/api', []);
338 pyroutes.register('admin_settings_license', '/_admin/settings/license', []);
339 pyroutes.register('admin_settings_license', '/_admin/settings/license', []);
339 pyroutes.register('admin_settings_license_unlock', '/_admin/settings/license_unlock', []);
340 pyroutes.register('admin_settings_license_unlock', '/_admin/settings/license_unlock', []);
340 pyroutes.register('login', '/_admin/login', []);
341 pyroutes.register('login', '/_admin/login', []);
341 pyroutes.register('register', '/_admin/register', []);
342 pyroutes.register('register', '/_admin/register', []);
342 pyroutes.register('repo_reviewers_review_rule_new', '/%(repo_name)s/settings/review/rules/new', ['repo_name']);
343 pyroutes.register('repo_reviewers_review_rule_new', '/%(repo_name)s/settings/review/rules/new', ['repo_name']);
343 pyroutes.register('repo_reviewers_review_rule_edit', '/%(repo_name)s/settings/review/rules/%(rule_id)s', ['repo_name', 'rule_id']);
344 pyroutes.register('repo_reviewers_review_rule_edit', '/%(repo_name)s/settings/review/rules/%(rule_id)s', ['repo_name', 'rule_id']);
344 pyroutes.register('repo_reviewers_review_rule_delete', '/%(repo_name)s/settings/review/rules/%(rule_id)s/delete', ['repo_name', 'rule_id']);
345 pyroutes.register('repo_reviewers_review_rule_delete', '/%(repo_name)s/settings/review/rules/%(rule_id)s/delete', ['repo_name', 'rule_id']);
345 pyroutes.register('plugin_admin_chat', '/_admin/plugin_admin_chat/%(action)s', ['action']);
346 pyroutes.register('plugin_admin_chat', '/_admin/plugin_admin_chat/%(action)s', ['action']);
346 pyroutes.register('edit_user_auth_tokens', '/_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']);
347 pyroutes.register('edit_user_auth_tokens', '/_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']);
347 pyroutes.register('edit_user_auth_tokens_add', '/_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']);
348 pyroutes.register('edit_user_auth_tokens_add', '/_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']);
348 pyroutes.register('admin_settings_scheduler_show_tasks', '/_admin/settings/scheduler/_tasks', []);
349 pyroutes.register('admin_settings_scheduler_show_tasks', '/_admin/settings/scheduler/_tasks', []);
349 pyroutes.register('admin_settings_scheduler_show_all', '/_admin/settings/scheduler', []);
350 pyroutes.register('admin_settings_scheduler_show_all', '/_admin/settings/scheduler', []);
350 pyroutes.register('admin_settings_scheduler_new', '/_admin/settings/scheduler/new', []);
351 pyroutes.register('admin_settings_scheduler_new', '/_admin/settings/scheduler/new', []);
351 pyroutes.register('admin_settings_scheduler_create', '/_admin/settings/scheduler/create', []);
352 pyroutes.register('admin_settings_scheduler_create', '/_admin/settings/scheduler/create', []);
352 pyroutes.register('admin_settings_scheduler_edit', '/_admin/settings/scheduler/%(schedule_id)s', ['schedule_id']);
353 pyroutes.register('admin_settings_scheduler_edit', '/_admin/settings/scheduler/%(schedule_id)s', ['schedule_id']);
353 pyroutes.register('admin_settings_scheduler_update', '/_admin/settings/scheduler/%(schedule_id)s/update', ['schedule_id']);
354 pyroutes.register('admin_settings_scheduler_update', '/_admin/settings/scheduler/%(schedule_id)s/update', ['schedule_id']);
354 pyroutes.register('admin_settings_scheduler_delete', '/_admin/settings/scheduler/%(schedule_id)s/delete', ['schedule_id']);
355 pyroutes.register('admin_settings_scheduler_delete', '/_admin/settings/scheduler/%(schedule_id)s/delete', ['schedule_id']);
355 pyroutes.register('admin_settings_scheduler_execute', '/_admin/settings/scheduler/%(schedule_id)s/execute', ['schedule_id']);
356 pyroutes.register('admin_settings_scheduler_execute', '/_admin/settings/scheduler/%(schedule_id)s/execute', ['schedule_id']);
356 pyroutes.register('admin_settings_automation', '/_admin/settings/automation', []);
357 pyroutes.register('admin_settings_automation', '/_admin/settings/automation', []);
357 pyroutes.register('admin_settings_automation_update', '/_admin/settings/automation/%(entry_id)s/update', ['entry_id']);
358 pyroutes.register('admin_settings_automation_update', '/_admin/settings/automation/%(entry_id)s/update', ['entry_id']);
358 pyroutes.register('admin_permissions_branch', '/_admin/permissions/branch', []);
359 pyroutes.register('admin_permissions_branch', '/_admin/permissions/branch', []);
359 pyroutes.register('admin_permissions_branch_update', '/_admin/permissions/branch/update', []);
360 pyroutes.register('admin_permissions_branch_update', '/_admin/permissions/branch/update', []);
360 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
361 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
361 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
362 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
362 pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []);
363 pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []);
363 pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []);
364 pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []);
364 pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']);
365 pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']);
365 pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']);
366 pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']);
366 pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']);
367 pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']);
367 pyroutes.register('repo_artifacts_get', '/%(repo_name)s/artifacts/download/%(uid)s', ['repo_name', 'uid']);
368 pyroutes.register('repo_artifacts_get', '/%(repo_name)s/artifacts/download/%(uid)s', ['repo_name', 'uid']);
368 pyroutes.register('repo_artifacts_store', '/%(repo_name)s/artifacts/store', ['repo_name']);
369 pyroutes.register('repo_artifacts_store', '/%(repo_name)s/artifacts/store', ['repo_name']);
369 pyroutes.register('repo_artifacts_delete', '/%(repo_name)s/artifacts/delete/%(uid)s', ['repo_name', 'uid']);
370 pyroutes.register('repo_artifacts_delete', '/%(repo_name)s/artifacts/delete/%(uid)s', ['repo_name', 'uid']);
370 pyroutes.register('repo_automation', '/%(repo_name)s/settings/automation', ['repo_name']);
371 pyroutes.register('repo_automation', '/%(repo_name)s/settings/automation', ['repo_name']);
371 pyroutes.register('repo_automation_update', '/%(repo_name)s/settings/automation/%(entry_id)s/update', ['repo_name', 'entry_id']);
372 pyroutes.register('repo_automation_update', '/%(repo_name)s/settings/automation/%(entry_id)s/update', ['repo_name', 'entry_id']);
372 pyroutes.register('edit_repo_remote_push', '/%(repo_name)s/settings/remote/push', ['repo_name']);
373 pyroutes.register('edit_repo_remote_push', '/%(repo_name)s/settings/remote/push', ['repo_name']);
373 pyroutes.register('edit_repo_perms_branch', '/%(repo_name)s/settings/branch_permissions', ['repo_name']);
374 pyroutes.register('edit_repo_perms_branch', '/%(repo_name)s/settings/branch_permissions', ['repo_name']);
374 pyroutes.register('edit_repo_perms_branch_delete', '/%(repo_name)s/settings/branch_permissions/%(rule_id)s/delete', ['repo_name', 'rule_id']);
375 pyroutes.register('edit_repo_perms_branch_delete', '/%(repo_name)s/settings/branch_permissions/%(rule_id)s/delete', ['repo_name', 'rule_id']);
375 }
376 }
@@ -1,202 +1,222 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2
2
3 <div class="panel panel-default">
3 <div class="panel panel-default">
4 <div class="panel-heading">
4 <div class="panel-heading">
5 <h3 class="panel-title">${_('Repository Permissions')}</h3>
5 <h3 class="panel-title">${_('Repository Permissions')}</h3>
6 </div>
6 </div>
7 <div class="panel-body">
7 <div class="panel-body">
8 ${h.secure_form(h.route_path('edit_repo_perms', repo_name=c.repo_name), request=request)}
8 ${h.secure_form(h.route_path('edit_repo_perms', repo_name=c.repo_name), request=request)}
9 <table id="permissions_manage" class="rctable permissions">
9 <table id="permissions_manage" class="rctable permissions">
10 <tr>
10 <tr>
11 <th class="td-radio">${_('None')}</th>
11 <th class="td-radio">${_('None')}</th>
12 <th class="td-radio">${_('Read')}</th>
12 <th class="td-radio">${_('Read')}</th>
13 <th class="td-radio">${_('Write')}</th>
13 <th class="td-radio">${_('Write')}</th>
14 <th class="td-radio">${_('Admin')}</th>
14 <th class="td-radio">${_('Admin')}</th>
15 <th class="td-owner">${_('User/User Group')}</th>
15 <th class="td-owner">${_('User/User Group')}</th>
16 <th class="td-action"></th>
16 <th class="td-action"></th>
17 <th class="td-action"></th>
17 <th class="td-action"></th>
18 </tr>
18 </tr>
19 ## USERS
19 ## USERS
20 %for _user in c.rhodecode_db_repo.permissions():
20 %for _user in c.rhodecode_db_repo.permissions():
21 %if getattr(_user, 'admin_row', None) or getattr(_user, 'owner_row', None):
21 %if getattr(_user, 'admin_row', None) or getattr(_user, 'owner_row', None):
22 <tr class="perm_admin_row">
22 <tr class="perm_admin_row">
23 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.none', disabled="disabled")}</td>
23 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.none', disabled="disabled")}</td>
24 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.read', disabled="disabled")}</td>
24 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.read', disabled="disabled")}</td>
25 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.write', disabled="disabled")}</td>
25 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.write', disabled="disabled")}</td>
26 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.admin', 'repository.admin', disabled="disabled")}</td>
26 <td class="td-radio">${h.radio('admin_perm_%s' % _user.user_id,'repository.admin', 'repository.admin', disabled="disabled")}</td>
27 <td class="td-user">
27 <td class="td-user">
28 ${base.gravatar(_user.email, 16)}
28 ${base.gravatar(_user.email, 16)}
29 ${h.link_to_user(_user.username)}
29 ${h.link_to_user(_user.username)}
30 %if getattr(_user, 'admin_row', None):
30 %if getattr(_user, 'admin_row', None):
31 (${_('super admin')})
31 (${_('super admin')})
32 %endif
32 %endif
33 %if getattr(_user, 'owner_row', None):
33 %if getattr(_user, 'owner_row', None):
34 (${_('owner')})
34 (${_('owner')})
35 %endif
35 %endif
36 </td>
36 </td>
37 <td></td>
37 <td></td>
38 <td class="quick_repo_menu">
38 <td class="quick_repo_menu">
39 % if c.rhodecode_user.is_admin:
39 % if c.rhodecode_user.is_admin:
40 <i class="icon-more"></i>
40 <i class="icon-more"></i>
41 <div class="menu_items_container" style="display: none;">
41 <div class="menu_items_container" style="display: none;">
42 <ul class="menu_items">
42 <ul class="menu_items">
43 <li>
43 <li>
44 ${h.link_to('show permissions', h.route_path('edit_user_perms_summary', user_id=_user.user_id, _anchor='repositories-permissions'))}
44 ${h.link_to('show permissions', h.route_path('edit_user_perms_summary', user_id=_user.user_id, _anchor='repositories-permissions'))}
45 </li>
45 </li>
46 </ul>
46 </ul>
47 </div>
47 </div>
48 % endif
48 % endif
49 </td>
49 </td>
50 </tr>
50 </tr>
51 %elif _user.username == h.DEFAULT_USER and c.rhodecode_db_repo.private:
51 %elif _user.username == h.DEFAULT_USER and c.rhodecode_db_repo.private:
52 <tr>
52 <tr>
53 <td colspan="4">
53 <td colspan="4">
54 <span class="private_repo_msg">
54 <span class="private_repo_msg">
55 <strong title="${h.tooltip(_user.permission)}">${_('private repository')}</strong>
55 <strong title="${h.tooltip(_user.permission)}">${_('private repository')}</strong>
56 </span>
56 </span>
57 </td>
57 </td>
58 <td class="private_repo_msg">
58 <td class="private_repo_msg">
59 ${base.gravatar(h.DEFAULT_USER_EMAIL, 16)}
59 ${base.gravatar(h.DEFAULT_USER_EMAIL, 16)}
60 ${h.DEFAULT_USER} - ${_('only users/user groups explicitly added here will have access')}</td>
60 ${h.DEFAULT_USER} - ${_('only users/user groups explicitly added here will have access')}</td>
61 <td></td>
61 <td></td>
62 <td class="quick_repo_menu">
62 <td class="quick_repo_menu">
63 % if c.rhodecode_user.is_admin:
63 % if c.rhodecode_user.is_admin:
64 <i class="icon-more"></i>
64 <i class="icon-more"></i>
65 <div class="menu_items_container" style="display: none;">
65 <div class="menu_items_container" style="display: none;">
66 <ul class="menu_items">
66 <ul class="menu_items">
67 <li>
67 <li>
68 ${h.link_to('show permissions', h.route_path('admin_permissions_overview', _anchor='repositories-permissions'))}
68 ${h.link_to('show permissions', h.route_path('admin_permissions_overview', _anchor='repositories-permissions'))}
69 </li>
69 </li>
70 </ul>
70 </ul>
71 </div>
71 </div>
72 % endif
72 % endif
73 </td>
73 </td>
74 </tr>
74 </tr>
75 %else:
75 %else:
76 <% used_by_n_rules = len(getattr(_user, 'branch_rules', None) or []) %>
76 <% used_by_n_rules = len(getattr(_user, 'branch_rules', None) or []) %>
77 <tr>
77 <tr>
78 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.none', checked=_user.permission=='repository.none', disabled="disabled" if (used_by_n_rules and _user.username != h.DEFAULT_USER) else None)}</td>
78 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.none', checked=_user.permission=='repository.none', disabled="disabled" if (used_by_n_rules and _user.username != h.DEFAULT_USER) else None)}</td>
79 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.read', checked=_user.permission=='repository.read', disabled="disabled" if (used_by_n_rules and _user.username != h.DEFAULT_USER) else None)}</td>
79 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.read', checked=_user.permission=='repository.read', disabled="disabled" if (used_by_n_rules and _user.username != h.DEFAULT_USER) else None)}</td>
80 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.write', checked=_user.permission=='repository.write')}</td>
80 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.write', checked=_user.permission=='repository.write')}</td>
81 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.admin', checked=_user.permission=='repository.admin')}</td>
81 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.admin', checked=_user.permission=='repository.admin')}</td>
82 <td class="td-user">
82 <td class="td-user">
83 ${base.gravatar(_user.email, 16)}
83 ${base.gravatar(_user.email, 16)}
84 <span class="user">
84 <span class="user">
85 % if _user.username == h.DEFAULT_USER:
85 % if _user.username == h.DEFAULT_USER:
86 ${h.DEFAULT_USER} <span class="user-perm-help-text"> - ${_('permission for all other users')}</span>
86 ${h.DEFAULT_USER} <span class="user-perm-help-text"> - ${_('permission for all other users')}</span>
87 % else:
87 % else:
88 ${h.link_to_user(_user.username)}
88 ${h.link_to_user(_user.username)}
89 %if getattr(_user, 'duplicate_perm', None):
89 %if getattr(_user, 'duplicate_perm', None):
90 (${_('inactive duplicate')})
90 (${_('inactive duplicate')})
91 %endif
91 %endif
92 %if getattr(_user, 'branch_rules', None):
92 %if getattr(_user, 'branch_rules', None):
93 % if used_by_n_rules == 1:
93 % if used_by_n_rules == 1:
94 (${_('used by {} branch rule, requires write+ permissions').format(used_by_n_rules)})
94 (${_('used by {} branch rule, requires write+ permissions').format(used_by_n_rules)})
95 % else:
95 % else:
96 (${_('used by {} branch rules, requires write+ permissions').format(used_by_n_rules)})
96 (${_('used by {} branch rules, requires write+ permissions').format(used_by_n_rules)})
97 % endif
97 % endif
98 %endif
98 %endif
99 % endif
99 % endif
100 </span>
100 </span>
101 </td>
101 </td>
102 <td class="td-action">
102 <td class="td-action">
103 %if _user.username != h.DEFAULT_USER and getattr(_user, 'branch_rules', None) is None:
103 %if _user.username != h.DEFAULT_USER and getattr(_user, 'branch_rules', None) is None:
104 <span class="btn btn-link btn-danger revoke_perm"
104 <span class="btn btn-link btn-danger revoke_perm"
105 member="${_user.user_id}" member_type="user">
105 member="${_user.user_id}" member_type="user">
106 ${_('Remove')}
106 ${_('Remove')}
107 </span>
107 </span>
108 %elif _user.username == h.DEFAULT_USER:
109 <span class="tooltip btn btn-link btn-default" onclick="enablePrivateRepo(); return false" title="${_('Private repositories are only visible to people explicitly added as collaborators.')}">
110 ${_('set private mode')}
111 </span>
108 %endif
112 %endif
109 </td>
113 </td>
110 <td class="quick_repo_menu">
114 <td class="quick_repo_menu">
111 % if c.rhodecode_user.is_admin:
115 % if c.rhodecode_user.is_admin:
112 <i class="icon-more"></i>
116 <i class="icon-more"></i>
113 <div class="menu_items_container" style="display: none;">
117 <div class="menu_items_container" style="display: none;">
114 <ul class="menu_items">
118 <ul class="menu_items">
115 <li>
119 <li>
116 % if _user.username == h.DEFAULT_USER:
120 % if _user.username == h.DEFAULT_USER:
117 ${h.link_to('show permissions', h.route_path('admin_permissions_overview', _anchor='repositories-permissions'))}
121 ${h.link_to('show permissions', h.route_path('admin_permissions_overview', _anchor='repositories-permissions'))}
118 % else:
122 % else:
119 ${h.link_to('show permissions', h.route_path('edit_user_perms_summary', user_id=_user.user_id, _anchor='repositories-permissions'))}
123 ${h.link_to('show permissions', h.route_path('edit_user_perms_summary', user_id=_user.user_id, _anchor='repositories-permissions'))}
120 % endif
124 % endif
121 </li>
125 </li>
122 </ul>
126 </ul>
123 </div>
127 </div>
124 % endif
128 % endif
125 </td>
129 </td>
126 </tr>
130 </tr>
127 %endif
131 %endif
128 %endfor
132 %endfor
129
133
130 ## USER GROUPS
134 ## USER GROUPS
131 %for _user_group in c.rhodecode_db_repo.permission_user_groups(with_members=True):
135 %for _user_group in c.rhodecode_db_repo.permission_user_groups(with_members=True):
132 <tr>
136 <tr>
133 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.none', checked=_user_group.permission=='repository.none')}</td>
137 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.none', checked=_user_group.permission=='repository.none')}</td>
134 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.read', checked=_user_group.permission=='repository.read')}</td>
138 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.read', checked=_user_group.permission=='repository.read')}</td>
135 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.write', checked=_user_group.permission=='repository.write')}</td>
139 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.write', checked=_user_group.permission=='repository.write')}</td>
136 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.admin', checked=_user_group.permission=='repository.admin')}</td>
140 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.admin', checked=_user_group.permission=='repository.admin')}</td>
137 <td class="td-componentname">
141 <td class="td-componentname">
138 <i class="icon-user-group"></i>
142 <i class="icon-user-group"></i>
139 %if c.is_super_admin:
143 %if c.is_super_admin:
140 <a href="${h.route_path('edit_user_group',user_group_id=_user_group.users_group_id)}">
144 <a href="${h.route_path('edit_user_group',user_group_id=_user_group.users_group_id)}">
141 ${_user_group.users_group_name}
145 ${_user_group.users_group_name}
142 </a>
146 </a>
143 %else:
147 %else:
144 ${h.link_to_group(_user_group.users_group_name)}
148 ${h.link_to_group(_user_group.users_group_name)}
145 %endif
149 %endif
146 (${_('members')}: ${len(_user_group.members)})
150 (${_('members')}: ${len(_user_group.members)})
147 </td>
151 </td>
148 <td class="td-action">
152 <td class="td-action">
149 <span class="btn btn-link btn-danger revoke_perm"
153 <span class="btn btn-link btn-danger revoke_perm"
150 member="${_user_group.users_group_id}" member_type="user_group">
154 member="${_user_group.users_group_id}" member_type="user_group">
151 ${_('Remove')}
155 ${_('Remove')}
152 </span>
156 </span>
153 </td>
157 </td>
154 <td class="quick_repo_menu">
158 <td class="quick_repo_menu">
155 % if c.rhodecode_user.is_admin:
159 % if c.rhodecode_user.is_admin:
156 <i class="icon-more"></i>
160 <i class="icon-more"></i>
157 <div class="menu_items_container" style="display: none;">
161 <div class="menu_items_container" style="display: none;">
158 <ul class="menu_items">
162 <ul class="menu_items">
159 <li>
163 <li>
160 ${h.link_to('show permissions', h.route_path('edit_user_group_perms_summary', user_group_id=_user_group.users_group_id, _anchor='repositories-permissions'))}
164 ${h.link_to('show permissions', h.route_path('edit_user_group_perms_summary', user_group_id=_user_group.users_group_id, _anchor='repositories-permissions'))}
161 </li>
165 </li>
162 </ul>
166 </ul>
163 </div>
167 </div>
164 % endif
168 % endif
165 </td>
169 </td>
166 </tr>
170 </tr>
167 %endfor
171 %endfor
168 <tr class="new_members" id="add_perm_input"></tr>
172 <tr class="new_members" id="add_perm_input"></tr>
169
173
170 <tr>
174 <tr>
171 <td></td>
175 <td></td>
172 <td></td>
176 <td></td>
173 <td></td>
177 <td></td>
174 <td></td>
178 <td></td>
175 <td></td>
179 <td></td>
176 <td>
180 <td>
177 <span id="add_perm" class="link">
181 <span id="add_perm" class="link">
178 ${_('Add user/user group')}
182 ${_('Add user/user group')}
179 </span>
183 </span>
180 </td>
184 </td>
181 <td></td>
185 <td></td>
182 </tr>
186 </tr>
183
187
184 </table>
188 </table>
185
189
186 <div class="buttons">
190 <div class="buttons">
187 ${h.submit('save',_('Save'),class_="btn btn-primary")}
191 ${h.submit('save',_('Save'),class_="btn btn-primary")}
188 ${h.reset('reset',_('Reset'),class_="btn btn-danger")}
192 ${h.reset('reset',_('Reset'),class_="btn btn-danger")}
189 </div>
193 </div>
190 ${h.end_form()}
194 ${h.end_form()}
191 </div>
195 </div>
192 </div>
196 </div>
193
197
194 <script type="text/javascript">
198 <script type="text/javascript">
195 $('#add_perm').on('click', function(e){
199 $('#add_perm').on('click', function(e){
196 addNewPermInput($(this), 'repository');
200 addNewPermInput($(this), 'repository');
197 });
201 });
198 $('.revoke_perm').on('click', function(e){
202 $('.revoke_perm').on('click', function(e){
199 markRevokePermInput($(this), 'repository');
203 markRevokePermInput($(this), 'repository');
200 });
204 });
201 quick_repo_menu();
205 quick_repo_menu();
206
207 var enablePrivateRepo = function () {
208 var postData = {
209 'csrf_token': CSRF_TOKEN
210 };
211
212 var success = function(o) {
213 var defaultUrl = pyroutes.url('edit_repo_perms', {"repo_name": templateContext.repo_name});
214 window.location = o.redirect_url || defaultUrl;
215 };
216
217 ajaxPOST(
218 pyroutes.url('edit_repo_perms_set_private', {"repo_name": templateContext.repo_name}),
219 postData,
220 success);
221 }
202 </script>
222 </script>
General Comments 0
You need to be logged in to leave comments. Login now