##// END OF EJS Templates
feat(vcs clients filtering): added changes related to vcs client filtering needed for EE. Fixes: RCCE-41
ilin.s -
r5522:33fc2e7c default
parent child Browse files
Show More
@@ -0,0 +1,62 b''
1 <style>
2 .form-group {
3 margin-bottom: 15px;
4 }
5
6 .form-group label {
7 display: flex;
8 align-items: left;
9 font-weight: bold;
10 }
11
12 .form-control {
13 width: 60%;
14 padding: 10px;
15 font-size: 1rem;
16 line-height: 1.5;
17 border: 1px solid #ced4da;
18 border-radius: 4px;
19 box-sizing: border-box;
20 }
21
22 .btn-primary {
23 background-color: #007bff;
24 border: none;
25 padding: 10px 20px;
26 color: white;
27 font-size: 1rem;
28 border-radius: 4px;
29 cursor: pointer;
30 }
31
32 .btn-primary:hover {
33 background-color: #0056b3;
34 }
35 .form-group .help_block {
36 display: block;
37 width: 100%;
38 margin-top: 10px;
39 text-align: left;
40 font-size: 0.875rem;
41 }
42 </style>
43
44 <div>
45 <div class="form-group">
46 ${h.secure_form(h.route_path('check_2fa'), request=request, id='allowed_clients_form')}
47 <p><label for="git">${_('git')}:</label>
48 ${h.text('git', class_="form-control", value=initial_git)}</p>
49 <p><label for="hg">${_('hg')}:</label>
50 ${h.text('hg', class_="form-control", value=initial_hg)}</p>
51 <p><label for="svn">${_('svn')}:</label>
52 ${h.text('svn', class_="form-control", value=initial_svn)}</p>
53 %for k, v in errors.items():
54 <span class="error-message">${k}: ${v}</span>
55 <br />
56 %endfor
57 <p class="help_block">${_('Set rules for allowed git, hg or svn client versions. You can set exact version (for example 2.0.9) or use comparison operators to set earliest or latest version (>=2.6.0)')}</p>
58
59 ${h.submit('send', _('Save'), class_="btn btn-primary")}
60 ${h.end_form()}
61 </div>
62 </div>
@@ -1,1115 +1,1124 b''
1 # Copyright (C) 2016-2023 RhodeCode GmbH
1 # Copyright (C) 2016-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19
19
20 from rhodecode.apps._base import ADMIN_PREFIX
20 from rhodecode.apps._base import ADMIN_PREFIX
21 from rhodecode.apps._base.navigation import includeme as nav_includeme
21 from rhodecode.apps._base.navigation import includeme as nav_includeme
22 from rhodecode.apps.admin.views.main_views import AdminMainView
22 from rhodecode.apps.admin.views.main_views import AdminMainView
23
23
24
24
25 def admin_routes(config):
25 def admin_routes(config):
26 """
26 """
27 Admin prefixed routes
27 Admin prefixed routes
28 """
28 """
29 from rhodecode.apps.admin.views.audit_logs import AdminAuditLogsView
29 from rhodecode.apps.admin.views.audit_logs import AdminAuditLogsView
30 from rhodecode.apps.admin.views.artifacts import AdminArtifactsView
30 from rhodecode.apps.admin.views.artifacts import AdminArtifactsView
31 from rhodecode.apps.admin.views.automation import AdminAutomationView
31 from rhodecode.apps.admin.views.automation import AdminAutomationView
32 from rhodecode.apps.admin.views.scheduler import AdminSchedulerView
32 from rhodecode.apps.admin.views.scheduler import AdminSchedulerView
33 from rhodecode.apps.admin.views.defaults import AdminDefaultSettingsView
33 from rhodecode.apps.admin.views.defaults import AdminDefaultSettingsView
34 from rhodecode.apps.admin.views.exception_tracker import ExceptionsTrackerView
34 from rhodecode.apps.admin.views.exception_tracker import ExceptionsTrackerView
35 from rhodecode.apps.admin.views.open_source_licenses import OpenSourceLicensesAdminSettingsView
35 from rhodecode.apps.admin.views.open_source_licenses import OpenSourceLicensesAdminSettingsView
36 from rhodecode.apps.admin.views.permissions import AdminPermissionsView
36 from rhodecode.apps.admin.views.permissions import AdminPermissionsView
37 from rhodecode.apps.admin.views.process_management import AdminProcessManagementView
37 from rhodecode.apps.admin.views.process_management import AdminProcessManagementView
38 from rhodecode.apps.admin.views.repo_groups import AdminRepoGroupsView
38 from rhodecode.apps.admin.views.repo_groups import AdminRepoGroupsView
39 from rhodecode.apps.admin.views.repositories import AdminReposView
39 from rhodecode.apps.admin.views.repositories import AdminReposView
40 from rhodecode.apps.admin.views.sessions import AdminSessionSettingsView
40 from rhodecode.apps.admin.views.sessions import AdminSessionSettingsView
41 from rhodecode.apps.admin.views.settings import AdminSettingsView
41 from rhodecode.apps.admin.views.settings import AdminSettingsView
42 from rhodecode.apps.admin.views.svn_config import AdminSvnConfigView
42 from rhodecode.apps.admin.views.svn_config import AdminSvnConfigView
43 from rhodecode.apps.admin.views.system_info import AdminSystemInfoSettingsView
43 from rhodecode.apps.admin.views.system_info import AdminSystemInfoSettingsView
44 from rhodecode.apps.admin.views.user_groups import AdminUserGroupsView
44 from rhodecode.apps.admin.views.user_groups import AdminUserGroupsView
45 from rhodecode.apps.admin.views.users import AdminUsersView, UsersView
45 from rhodecode.apps.admin.views.users import AdminUsersView, UsersView
46 from rhodecode.apps.admin.views.security import AdminSecurityView
46 from rhodecode.apps.admin.views.security import AdminSecurityView
47
47
48 # Security EE feature
48 # Security EE feature
49
49
50 config.add_route(
50 config.add_route(
51 'admin_security',
51 'admin_security',
52 pattern=ADMIN_PREFIX + '/security')
52 pattern='/security')
53 config.add_view(
53 config.add_view(
54 AdminSecurityView,
54 AdminSecurityView,
55 attr='security' ,
55 attr='security',
56 route_name='admin_security', request_method='GET',
56 route_name='admin_security', request_method='GET',
57 renderer='rhodecode:templates/admin/security/security.mako')
57 renderer='rhodecode:templates/admin/security/security.mako')
58
58
59 config.add_route(
59 config.add_route(
60 name='admin_security_update',
60 name='admin_security_update',
61 pattern=ADMIN_PREFIX + '/security/update')
61 pattern='/security/update')
62 config.add_view(
62 config.add_view(
63 AdminSecurityView,
63 AdminSecurityView,
64 attr='security_update',
64 attr='security_update',
65 route_name='admin_security_update', request_method='POST',
65 route_name='admin_security_update', request_method='POST',
66 renderer='rhodecode:templates/admin/security/security.mako')
66 renderer='rhodecode:templates/admin/security/security.mako')
67
67
68 config.add_route(
69 name='admin_security_modify_allowed_vcs_client_versions',
70 pattern='/security/modify/allowed_vcs_client_versions')
71 config.add_view(
72 AdminSecurityView,
73 attr='vcs_whitelisted_client_versions_edit',
74 route_name='admin_security_modify_allowed_vcs_client_versions', request_method=('GET', 'POST'),
75 renderer='rhodecode:templates/admin/security/edit_allowed_vcs_client_versions.mako')
76
68
77
69 config.add_route(
78 config.add_route(
70 name='admin_audit_logs',
79 name='admin_audit_logs',
71 pattern='/audit_logs')
80 pattern='/audit_logs')
72 config.add_view(
81 config.add_view(
73 AdminAuditLogsView,
82 AdminAuditLogsView,
74 attr='admin_audit_logs',
83 attr='admin_audit_logs',
75 route_name='admin_audit_logs', request_method='GET',
84 route_name='admin_audit_logs', request_method='GET',
76 renderer='rhodecode:templates/admin/admin_audit_logs.mako')
85 renderer='rhodecode:templates/admin/admin_audit_logs.mako')
77
86
78 config.add_route(
87 config.add_route(
79 name='admin_audit_log_entry',
88 name='admin_audit_log_entry',
80 pattern='/audit_logs/{audit_log_id}')
89 pattern='/audit_logs/{audit_log_id}')
81 config.add_view(
90 config.add_view(
82 AdminAuditLogsView,
91 AdminAuditLogsView,
83 attr='admin_audit_log_entry',
92 attr='admin_audit_log_entry',
84 route_name='admin_audit_log_entry', request_method='GET',
93 route_name='admin_audit_log_entry', request_method='GET',
85 renderer='rhodecode:templates/admin/admin_audit_log_entry.mako')
94 renderer='rhodecode:templates/admin/admin_audit_log_entry.mako')
86
95
87 # Artifacts EE feature
96 # Artifacts EE feature
88 config.add_route(
97 config.add_route(
89 'admin_artifacts',
98 'admin_artifacts',
90 pattern=ADMIN_PREFIX + '/artifacts')
99 pattern=ADMIN_PREFIX + '/artifacts')
91 config.add_route(
100 config.add_route(
92 'admin_artifacts_show_all',
101 'admin_artifacts_show_all',
93 pattern=ADMIN_PREFIX + '/artifacts')
102 pattern=ADMIN_PREFIX + '/artifacts')
94 config.add_view(
103 config.add_view(
95 AdminArtifactsView,
104 AdminArtifactsView,
96 attr='artifacts',
105 attr='artifacts',
97 route_name='admin_artifacts', request_method='GET',
106 route_name='admin_artifacts', request_method='GET',
98 renderer='rhodecode:templates/admin/artifacts/artifacts.mako')
107 renderer='rhodecode:templates/admin/artifacts/artifacts.mako')
99 config.add_view(
108 config.add_view(
100 AdminArtifactsView,
109 AdminArtifactsView,
101 attr='artifacts',
110 attr='artifacts',
102 route_name='admin_artifacts_show_all', request_method='GET',
111 route_name='admin_artifacts_show_all', request_method='GET',
103 renderer='rhodecode:templates/admin/artifacts/artifacts.mako')
112 renderer='rhodecode:templates/admin/artifacts/artifacts.mako')
104
113
105 # EE views
114 # EE views
106 config.add_route(
115 config.add_route(
107 name='admin_artifacts_show_info',
116 name='admin_artifacts_show_info',
108 pattern=ADMIN_PREFIX + '/artifacts/{uid}')
117 pattern=ADMIN_PREFIX + '/artifacts/{uid}')
109 config.add_route(
118 config.add_route(
110 name='admin_artifacts_delete',
119 name='admin_artifacts_delete',
111 pattern=ADMIN_PREFIX + '/artifacts/{uid}/delete')
120 pattern=ADMIN_PREFIX + '/artifacts/{uid}/delete')
112 config.add_route(
121 config.add_route(
113 name='admin_artifacts_update',
122 name='admin_artifacts_update',
114 pattern=ADMIN_PREFIX + '/artifacts/{uid}/update')
123 pattern=ADMIN_PREFIX + '/artifacts/{uid}/update')
115
124
116 # Automation EE feature
125 # Automation EE feature
117 config.add_route(
126 config.add_route(
118 'admin_automation',
127 'admin_automation',
119 pattern=ADMIN_PREFIX + '/automation')
128 pattern=ADMIN_PREFIX + '/automation')
120 config.add_view(
129 config.add_view(
121 AdminAutomationView,
130 AdminAutomationView,
122 attr='automation',
131 attr='automation',
123 route_name='admin_automation', request_method='GET',
132 route_name='admin_automation', request_method='GET',
124 renderer='rhodecode:templates/admin/automation/automation.mako')
133 renderer='rhodecode:templates/admin/automation/automation.mako')
125
134
126 # Scheduler EE feature
135 # Scheduler EE feature
127 config.add_route(
136 config.add_route(
128 'admin_scheduler',
137 'admin_scheduler',
129 pattern=ADMIN_PREFIX + '/scheduler')
138 pattern=ADMIN_PREFIX + '/scheduler')
130 config.add_view(
139 config.add_view(
131 AdminSchedulerView,
140 AdminSchedulerView,
132 attr='scheduler',
141 attr='scheduler',
133 route_name='admin_scheduler', request_method='GET',
142 route_name='admin_scheduler', request_method='GET',
134 renderer='rhodecode:templates/admin/scheduler/scheduler.mako')
143 renderer='rhodecode:templates/admin/scheduler/scheduler.mako')
135
144
136 config.add_route(
145 config.add_route(
137 name='admin_settings_open_source',
146 name='admin_settings_open_source',
138 pattern='/settings/open_source')
147 pattern='/settings/open_source')
139 config.add_view(
148 config.add_view(
140 OpenSourceLicensesAdminSettingsView,
149 OpenSourceLicensesAdminSettingsView,
141 attr='open_source_licenses',
150 attr='open_source_licenses',
142 route_name='admin_settings_open_source', request_method='GET',
151 route_name='admin_settings_open_source', request_method='GET',
143 renderer='rhodecode:templates/admin/settings/settings.mako')
152 renderer='rhodecode:templates/admin/settings/settings.mako')
144
153
145 config.add_route(
154 config.add_route(
146 name='admin_settings_vcs_svn_generate_cfg',
155 name='admin_settings_vcs_svn_generate_cfg',
147 pattern='/settings/vcs/svn_generate_cfg')
156 pattern='/settings/vcs/svn_generate_cfg')
148 config.add_view(
157 config.add_view(
149 AdminSvnConfigView,
158 AdminSvnConfigView,
150 attr='vcs_svn_generate_config',
159 attr='vcs_svn_generate_config',
151 route_name='admin_settings_vcs_svn_generate_cfg',
160 route_name='admin_settings_vcs_svn_generate_cfg',
152 request_method='POST', renderer='json')
161 request_method='POST', renderer='json')
153
162
154 config.add_route(
163 config.add_route(
155 name='admin_settings_system',
164 name='admin_settings_system',
156 pattern='/settings/system')
165 pattern='/settings/system')
157 config.add_view(
166 config.add_view(
158 AdminSystemInfoSettingsView,
167 AdminSystemInfoSettingsView,
159 attr='settings_system_info',
168 attr='settings_system_info',
160 route_name='admin_settings_system', request_method='GET',
169 route_name='admin_settings_system', request_method='GET',
161 renderer='rhodecode:templates/admin/settings/settings.mako')
170 renderer='rhodecode:templates/admin/settings/settings.mako')
162
171
163 config.add_route(
172 config.add_route(
164 name='admin_settings_system_update',
173 name='admin_settings_system_update',
165 pattern='/settings/system/updates')
174 pattern='/settings/system/updates')
166 config.add_view(
175 config.add_view(
167 AdminSystemInfoSettingsView,
176 AdminSystemInfoSettingsView,
168 attr='settings_system_info_check_update',
177 attr='settings_system_info_check_update',
169 route_name='admin_settings_system_update', request_method='GET',
178 route_name='admin_settings_system_update', request_method='GET',
170 renderer='rhodecode:templates/admin/settings/settings_system_update.mako')
179 renderer='rhodecode:templates/admin/settings/settings_system_update.mako')
171
180
172 config.add_route(
181 config.add_route(
173 name='admin_settings_exception_tracker',
182 name='admin_settings_exception_tracker',
174 pattern='/settings/exceptions')
183 pattern='/settings/exceptions')
175 config.add_view(
184 config.add_view(
176 ExceptionsTrackerView,
185 ExceptionsTrackerView,
177 attr='browse_exceptions',
186 attr='browse_exceptions',
178 route_name='admin_settings_exception_tracker', request_method='GET',
187 route_name='admin_settings_exception_tracker', request_method='GET',
179 renderer='rhodecode:templates/admin/settings/settings.mako')
188 renderer='rhodecode:templates/admin/settings/settings.mako')
180
189
181 config.add_route(
190 config.add_route(
182 name='admin_settings_exception_tracker_delete_all',
191 name='admin_settings_exception_tracker_delete_all',
183 pattern='/settings/exceptions_delete_all')
192 pattern='/settings/exceptions_delete_all')
184 config.add_view(
193 config.add_view(
185 ExceptionsTrackerView,
194 ExceptionsTrackerView,
186 attr='exception_delete_all',
195 attr='exception_delete_all',
187 route_name='admin_settings_exception_tracker_delete_all', request_method='POST',
196 route_name='admin_settings_exception_tracker_delete_all', request_method='POST',
188 renderer='rhodecode:templates/admin/settings/settings.mako')
197 renderer='rhodecode:templates/admin/settings/settings.mako')
189
198
190 config.add_route(
199 config.add_route(
191 name='admin_settings_exception_tracker_show',
200 name='admin_settings_exception_tracker_show',
192 pattern='/settings/exceptions/{exception_id}')
201 pattern='/settings/exceptions/{exception_id}')
193 config.add_view(
202 config.add_view(
194 ExceptionsTrackerView,
203 ExceptionsTrackerView,
195 attr='exception_show',
204 attr='exception_show',
196 route_name='admin_settings_exception_tracker_show', request_method='GET',
205 route_name='admin_settings_exception_tracker_show', request_method='GET',
197 renderer='rhodecode:templates/admin/settings/settings.mako')
206 renderer='rhodecode:templates/admin/settings/settings.mako')
198
207
199 config.add_route(
208 config.add_route(
200 name='admin_settings_exception_tracker_delete',
209 name='admin_settings_exception_tracker_delete',
201 pattern='/settings/exceptions/{exception_id}/delete')
210 pattern='/settings/exceptions/{exception_id}/delete')
202 config.add_view(
211 config.add_view(
203 ExceptionsTrackerView,
212 ExceptionsTrackerView,
204 attr='exception_delete',
213 attr='exception_delete',
205 route_name='admin_settings_exception_tracker_delete', request_method='POST',
214 route_name='admin_settings_exception_tracker_delete', request_method='POST',
206 renderer='rhodecode:templates/admin/settings/settings.mako')
215 renderer='rhodecode:templates/admin/settings/settings.mako')
207
216
208 config.add_route(
217 config.add_route(
209 name='admin_settings_sessions',
218 name='admin_settings_sessions',
210 pattern='/settings/sessions')
219 pattern='/settings/sessions')
211 config.add_view(
220 config.add_view(
212 AdminSessionSettingsView,
221 AdminSessionSettingsView,
213 attr='settings_sessions',
222 attr='settings_sessions',
214 route_name='admin_settings_sessions', request_method='GET',
223 route_name='admin_settings_sessions', request_method='GET',
215 renderer='rhodecode:templates/admin/settings/settings.mako')
224 renderer='rhodecode:templates/admin/settings/settings.mako')
216
225
217 config.add_route(
226 config.add_route(
218 name='admin_settings_sessions_cleanup',
227 name='admin_settings_sessions_cleanup',
219 pattern='/settings/sessions/cleanup')
228 pattern='/settings/sessions/cleanup')
220 config.add_view(
229 config.add_view(
221 AdminSessionSettingsView,
230 AdminSessionSettingsView,
222 attr='settings_sessions_cleanup',
231 attr='settings_sessions_cleanup',
223 route_name='admin_settings_sessions_cleanup', request_method='POST')
232 route_name='admin_settings_sessions_cleanup', request_method='POST')
224
233
225 config.add_route(
234 config.add_route(
226 name='admin_settings_process_management',
235 name='admin_settings_process_management',
227 pattern='/settings/process_management')
236 pattern='/settings/process_management')
228 config.add_view(
237 config.add_view(
229 AdminProcessManagementView,
238 AdminProcessManagementView,
230 attr='process_management',
239 attr='process_management',
231 route_name='admin_settings_process_management', request_method='GET',
240 route_name='admin_settings_process_management', request_method='GET',
232 renderer='rhodecode:templates/admin/settings/settings.mako')
241 renderer='rhodecode:templates/admin/settings/settings.mako')
233
242
234 config.add_route(
243 config.add_route(
235 name='admin_settings_process_management_data',
244 name='admin_settings_process_management_data',
236 pattern='/settings/process_management/data')
245 pattern='/settings/process_management/data')
237 config.add_view(
246 config.add_view(
238 AdminProcessManagementView,
247 AdminProcessManagementView,
239 attr='process_management_data',
248 attr='process_management_data',
240 route_name='admin_settings_process_management_data', request_method='GET',
249 route_name='admin_settings_process_management_data', request_method='GET',
241 renderer='rhodecode:templates/admin/settings/settings_process_management_data.mako')
250 renderer='rhodecode:templates/admin/settings/settings_process_management_data.mako')
242
251
243 config.add_route(
252 config.add_route(
244 name='admin_settings_process_management_signal',
253 name='admin_settings_process_management_signal',
245 pattern='/settings/process_management/signal')
254 pattern='/settings/process_management/signal')
246 config.add_view(
255 config.add_view(
247 AdminProcessManagementView,
256 AdminProcessManagementView,
248 attr='process_management_signal',
257 attr='process_management_signal',
249 route_name='admin_settings_process_management_signal',
258 route_name='admin_settings_process_management_signal',
250 request_method='POST', renderer='json_ext')
259 request_method='POST', renderer='json_ext')
251
260
252 config.add_route(
261 config.add_route(
253 name='admin_settings_process_management_master_signal',
262 name='admin_settings_process_management_master_signal',
254 pattern='/settings/process_management/master_signal')
263 pattern='/settings/process_management/master_signal')
255 config.add_view(
264 config.add_view(
256 AdminProcessManagementView,
265 AdminProcessManagementView,
257 attr='process_management_master_signal',
266 attr='process_management_master_signal',
258 route_name='admin_settings_process_management_master_signal',
267 route_name='admin_settings_process_management_master_signal',
259 request_method='POST', renderer='json_ext')
268 request_method='POST', renderer='json_ext')
260
269
261 # default settings
270 # default settings
262 config.add_route(
271 config.add_route(
263 name='admin_defaults_repositories',
272 name='admin_defaults_repositories',
264 pattern='/defaults/repositories')
273 pattern='/defaults/repositories')
265 config.add_view(
274 config.add_view(
266 AdminDefaultSettingsView,
275 AdminDefaultSettingsView,
267 attr='defaults_repository_show',
276 attr='defaults_repository_show',
268 route_name='admin_defaults_repositories', request_method='GET',
277 route_name='admin_defaults_repositories', request_method='GET',
269 renderer='rhodecode:templates/admin/defaults/defaults.mako')
278 renderer='rhodecode:templates/admin/defaults/defaults.mako')
270
279
271 config.add_route(
280 config.add_route(
272 name='admin_defaults_repositories_update',
281 name='admin_defaults_repositories_update',
273 pattern='/defaults/repositories/update')
282 pattern='/defaults/repositories/update')
274 config.add_view(
283 config.add_view(
275 AdminDefaultSettingsView,
284 AdminDefaultSettingsView,
276 attr='defaults_repository_update',
285 attr='defaults_repository_update',
277 route_name='admin_defaults_repositories_update', request_method='POST',
286 route_name='admin_defaults_repositories_update', request_method='POST',
278 renderer='rhodecode:templates/admin/defaults/defaults.mako')
287 renderer='rhodecode:templates/admin/defaults/defaults.mako')
279
288
280 # admin settings
289 # admin settings
281
290
282 config.add_route(
291 config.add_route(
283 name='admin_settings',
292 name='admin_settings',
284 pattern='/settings')
293 pattern='/settings')
285 config.add_view(
294 config.add_view(
286 AdminSettingsView,
295 AdminSettingsView,
287 attr='settings_global',
296 attr='settings_global',
288 route_name='admin_settings', request_method='GET',
297 route_name='admin_settings', request_method='GET',
289 renderer='rhodecode:templates/admin/settings/settings.mako')
298 renderer='rhodecode:templates/admin/settings/settings.mako')
290
299
291 config.add_route(
300 config.add_route(
292 name='admin_settings_update',
301 name='admin_settings_update',
293 pattern='/settings/update')
302 pattern='/settings/update')
294 config.add_view(
303 config.add_view(
295 AdminSettingsView,
304 AdminSettingsView,
296 attr='settings_global_update',
305 attr='settings_global_update',
297 route_name='admin_settings_update', request_method='POST',
306 route_name='admin_settings_update', request_method='POST',
298 renderer='rhodecode:templates/admin/settings/settings.mako')
307 renderer='rhodecode:templates/admin/settings/settings.mako')
299
308
300 config.add_route(
309 config.add_route(
301 name='admin_settings_global',
310 name='admin_settings_global',
302 pattern='/settings/global')
311 pattern='/settings/global')
303 config.add_view(
312 config.add_view(
304 AdminSettingsView,
313 AdminSettingsView,
305 attr='settings_global',
314 attr='settings_global',
306 route_name='admin_settings_global', request_method='GET',
315 route_name='admin_settings_global', request_method='GET',
307 renderer='rhodecode:templates/admin/settings/settings.mako')
316 renderer='rhodecode:templates/admin/settings/settings.mako')
308
317
309 config.add_route(
318 config.add_route(
310 name='admin_settings_global_update',
319 name='admin_settings_global_update',
311 pattern='/settings/global/update')
320 pattern='/settings/global/update')
312 config.add_view(
321 config.add_view(
313 AdminSettingsView,
322 AdminSettingsView,
314 attr='settings_global_update',
323 attr='settings_global_update',
315 route_name='admin_settings_global_update', request_method='POST',
324 route_name='admin_settings_global_update', request_method='POST',
316 renderer='rhodecode:templates/admin/settings/settings.mako')
325 renderer='rhodecode:templates/admin/settings/settings.mako')
317
326
318 config.add_route(
327 config.add_route(
319 name='admin_settings_vcs',
328 name='admin_settings_vcs',
320 pattern='/settings/vcs')
329 pattern='/settings/vcs')
321 config.add_view(
330 config.add_view(
322 AdminSettingsView,
331 AdminSettingsView,
323 attr='settings_vcs',
332 attr='settings_vcs',
324 route_name='admin_settings_vcs', request_method='GET',
333 route_name='admin_settings_vcs', request_method='GET',
325 renderer='rhodecode:templates/admin/settings/settings.mako')
334 renderer='rhodecode:templates/admin/settings/settings.mako')
326
335
327 config.add_route(
336 config.add_route(
328 name='admin_settings_vcs_update',
337 name='admin_settings_vcs_update',
329 pattern='/settings/vcs/update')
338 pattern='/settings/vcs/update')
330 config.add_view(
339 config.add_view(
331 AdminSettingsView,
340 AdminSettingsView,
332 attr='settings_vcs_update',
341 attr='settings_vcs_update',
333 route_name='admin_settings_vcs_update', request_method='POST',
342 route_name='admin_settings_vcs_update', request_method='POST',
334 renderer='rhodecode:templates/admin/settings/settings.mako')
343 renderer='rhodecode:templates/admin/settings/settings.mako')
335
344
336 config.add_route(
345 config.add_route(
337 name='admin_settings_vcs_svn_pattern_delete',
346 name='admin_settings_vcs_svn_pattern_delete',
338 pattern='/settings/vcs/svn_pattern_delete')
347 pattern='/settings/vcs/svn_pattern_delete')
339 config.add_view(
348 config.add_view(
340 AdminSettingsView,
349 AdminSettingsView,
341 attr='settings_vcs_delete_svn_pattern',
350 attr='settings_vcs_delete_svn_pattern',
342 route_name='admin_settings_vcs_svn_pattern_delete', request_method='POST',
351 route_name='admin_settings_vcs_svn_pattern_delete', request_method='POST',
343 renderer='json_ext', xhr=True)
352 renderer='json_ext', xhr=True)
344
353
345 config.add_route(
354 config.add_route(
346 name='admin_settings_mapping',
355 name='admin_settings_mapping',
347 pattern='/settings/mapping')
356 pattern='/settings/mapping')
348 config.add_view(
357 config.add_view(
349 AdminSettingsView,
358 AdminSettingsView,
350 attr='settings_mapping',
359 attr='settings_mapping',
351 route_name='admin_settings_mapping', request_method='GET',
360 route_name='admin_settings_mapping', request_method='GET',
352 renderer='rhodecode:templates/admin/settings/settings.mako')
361 renderer='rhodecode:templates/admin/settings/settings.mako')
353
362
354 config.add_route(
363 config.add_route(
355 name='admin_settings_mapping_update',
364 name='admin_settings_mapping_update',
356 pattern='/settings/mapping/update')
365 pattern='/settings/mapping/update')
357 config.add_view(
366 config.add_view(
358 AdminSettingsView,
367 AdminSettingsView,
359 attr='settings_mapping_update',
368 attr='settings_mapping_update',
360 route_name='admin_settings_mapping_update', request_method='POST',
369 route_name='admin_settings_mapping_update', request_method='POST',
361 renderer='rhodecode:templates/admin/settings/settings.mako')
370 renderer='rhodecode:templates/admin/settings/settings.mako')
362
371
363 config.add_route(
372 config.add_route(
364 name='admin_settings_visual',
373 name='admin_settings_visual',
365 pattern='/settings/visual')
374 pattern='/settings/visual')
366 config.add_view(
375 config.add_view(
367 AdminSettingsView,
376 AdminSettingsView,
368 attr='settings_visual',
377 attr='settings_visual',
369 route_name='admin_settings_visual', request_method='GET',
378 route_name='admin_settings_visual', request_method='GET',
370 renderer='rhodecode:templates/admin/settings/settings.mako')
379 renderer='rhodecode:templates/admin/settings/settings.mako')
371
380
372 config.add_route(
381 config.add_route(
373 name='admin_settings_visual_update',
382 name='admin_settings_visual_update',
374 pattern='/settings/visual/update')
383 pattern='/settings/visual/update')
375 config.add_view(
384 config.add_view(
376 AdminSettingsView,
385 AdminSettingsView,
377 attr='settings_visual_update',
386 attr='settings_visual_update',
378 route_name='admin_settings_visual_update', request_method='POST',
387 route_name='admin_settings_visual_update', request_method='POST',
379 renderer='rhodecode:templates/admin/settings/settings.mako')
388 renderer='rhodecode:templates/admin/settings/settings.mako')
380
389
381 config.add_route(
390 config.add_route(
382 name='admin_settings_issuetracker',
391 name='admin_settings_issuetracker',
383 pattern='/settings/issue-tracker')
392 pattern='/settings/issue-tracker')
384 config.add_view(
393 config.add_view(
385 AdminSettingsView,
394 AdminSettingsView,
386 attr='settings_issuetracker',
395 attr='settings_issuetracker',
387 route_name='admin_settings_issuetracker', request_method='GET',
396 route_name='admin_settings_issuetracker', request_method='GET',
388 renderer='rhodecode:templates/admin/settings/settings.mako')
397 renderer='rhodecode:templates/admin/settings/settings.mako')
389
398
390 config.add_route(
399 config.add_route(
391 name='admin_settings_issuetracker_update',
400 name='admin_settings_issuetracker_update',
392 pattern='/settings/issue-tracker/update')
401 pattern='/settings/issue-tracker/update')
393 config.add_view(
402 config.add_view(
394 AdminSettingsView,
403 AdminSettingsView,
395 attr='settings_issuetracker_update',
404 attr='settings_issuetracker_update',
396 route_name='admin_settings_issuetracker_update', request_method='POST',
405 route_name='admin_settings_issuetracker_update', request_method='POST',
397 renderer='rhodecode:templates/admin/settings/settings.mako')
406 renderer='rhodecode:templates/admin/settings/settings.mako')
398
407
399 config.add_route(
408 config.add_route(
400 name='admin_settings_issuetracker_test',
409 name='admin_settings_issuetracker_test',
401 pattern='/settings/issue-tracker/test')
410 pattern='/settings/issue-tracker/test')
402 config.add_view(
411 config.add_view(
403 AdminSettingsView,
412 AdminSettingsView,
404 attr='settings_issuetracker_test',
413 attr='settings_issuetracker_test',
405 route_name='admin_settings_issuetracker_test', request_method='POST',
414 route_name='admin_settings_issuetracker_test', request_method='POST',
406 renderer='string', xhr=True)
415 renderer='string', xhr=True)
407
416
408 config.add_route(
417 config.add_route(
409 name='admin_settings_issuetracker_delete',
418 name='admin_settings_issuetracker_delete',
410 pattern='/settings/issue-tracker/delete')
419 pattern='/settings/issue-tracker/delete')
411 config.add_view(
420 config.add_view(
412 AdminSettingsView,
421 AdminSettingsView,
413 attr='settings_issuetracker_delete',
422 attr='settings_issuetracker_delete',
414 route_name='admin_settings_issuetracker_delete', request_method='POST',
423 route_name='admin_settings_issuetracker_delete', request_method='POST',
415 renderer='json_ext', xhr=True)
424 renderer='json_ext', xhr=True)
416
425
417 config.add_route(
426 config.add_route(
418 name='admin_settings_email',
427 name='admin_settings_email',
419 pattern='/settings/email')
428 pattern='/settings/email')
420 config.add_view(
429 config.add_view(
421 AdminSettingsView,
430 AdminSettingsView,
422 attr='settings_email',
431 attr='settings_email',
423 route_name='admin_settings_email', request_method='GET',
432 route_name='admin_settings_email', request_method='GET',
424 renderer='rhodecode:templates/admin/settings/settings.mako')
433 renderer='rhodecode:templates/admin/settings/settings.mako')
425
434
426 config.add_route(
435 config.add_route(
427 name='admin_settings_email_update',
436 name='admin_settings_email_update',
428 pattern='/settings/email/update')
437 pattern='/settings/email/update')
429 config.add_view(
438 config.add_view(
430 AdminSettingsView,
439 AdminSettingsView,
431 attr='settings_email_update',
440 attr='settings_email_update',
432 route_name='admin_settings_email_update', request_method='POST',
441 route_name='admin_settings_email_update', request_method='POST',
433 renderer='rhodecode:templates/admin/settings/settings.mako')
442 renderer='rhodecode:templates/admin/settings/settings.mako')
434
443
435 config.add_route(
444 config.add_route(
436 name='admin_settings_hooks',
445 name='admin_settings_hooks',
437 pattern='/settings/hooks')
446 pattern='/settings/hooks')
438 config.add_view(
447 config.add_view(
439 AdminSettingsView,
448 AdminSettingsView,
440 attr='settings_hooks',
449 attr='settings_hooks',
441 route_name='admin_settings_hooks', request_method='GET',
450 route_name='admin_settings_hooks', request_method='GET',
442 renderer='rhodecode:templates/admin/settings/settings.mako')
451 renderer='rhodecode:templates/admin/settings/settings.mako')
443
452
444 config.add_route(
453 config.add_route(
445 name='admin_settings_hooks_update',
454 name='admin_settings_hooks_update',
446 pattern='/settings/hooks/update')
455 pattern='/settings/hooks/update')
447 config.add_view(
456 config.add_view(
448 AdminSettingsView,
457 AdminSettingsView,
449 attr='settings_hooks_update',
458 attr='settings_hooks_update',
450 route_name='admin_settings_hooks_update', request_method='POST',
459 route_name='admin_settings_hooks_update', request_method='POST',
451 renderer='rhodecode:templates/admin/settings/settings.mako')
460 renderer='rhodecode:templates/admin/settings/settings.mako')
452
461
453 config.add_route(
462 config.add_route(
454 name='admin_settings_hooks_delete',
463 name='admin_settings_hooks_delete',
455 pattern='/settings/hooks/delete')
464 pattern='/settings/hooks/delete')
456 config.add_view(
465 config.add_view(
457 AdminSettingsView,
466 AdminSettingsView,
458 attr='settings_hooks_update',
467 attr='settings_hooks_update',
459 route_name='admin_settings_hooks_delete', request_method='POST',
468 route_name='admin_settings_hooks_delete', request_method='POST',
460 renderer='rhodecode:templates/admin/settings/settings.mako')
469 renderer='rhodecode:templates/admin/settings/settings.mako')
461
470
462 config.add_route(
471 config.add_route(
463 name='admin_settings_search',
472 name='admin_settings_search',
464 pattern='/settings/search')
473 pattern='/settings/search')
465 config.add_view(
474 config.add_view(
466 AdminSettingsView,
475 AdminSettingsView,
467 attr='settings_search',
476 attr='settings_search',
468 route_name='admin_settings_search', request_method='GET',
477 route_name='admin_settings_search', request_method='GET',
469 renderer='rhodecode:templates/admin/settings/settings.mako')
478 renderer='rhodecode:templates/admin/settings/settings.mako')
470
479
471 config.add_route(
480 config.add_route(
472 name='admin_settings_labs',
481 name='admin_settings_labs',
473 pattern='/settings/labs')
482 pattern='/settings/labs')
474 config.add_view(
483 config.add_view(
475 AdminSettingsView,
484 AdminSettingsView,
476 attr='settings_labs',
485 attr='settings_labs',
477 route_name='admin_settings_labs', request_method='GET',
486 route_name='admin_settings_labs', request_method='GET',
478 renderer='rhodecode:templates/admin/settings/settings.mako')
487 renderer='rhodecode:templates/admin/settings/settings.mako')
479
488
480 config.add_route(
489 config.add_route(
481 name='admin_settings_labs_update',
490 name='admin_settings_labs_update',
482 pattern='/settings/labs/update')
491 pattern='/settings/labs/update')
483 config.add_view(
492 config.add_view(
484 AdminSettingsView,
493 AdminSettingsView,
485 attr='settings_labs_update',
494 attr='settings_labs_update',
486 route_name='admin_settings_labs_update', request_method='POST',
495 route_name='admin_settings_labs_update', request_method='POST',
487 renderer='rhodecode:templates/admin/settings/settings.mako')
496 renderer='rhodecode:templates/admin/settings/settings.mako')
488
497
489 # global permissions
498 # global permissions
490
499
491 config.add_route(
500 config.add_route(
492 name='admin_permissions_application',
501 name='admin_permissions_application',
493 pattern='/permissions/application')
502 pattern='/permissions/application')
494 config.add_view(
503 config.add_view(
495 AdminPermissionsView,
504 AdminPermissionsView,
496 attr='permissions_application',
505 attr='permissions_application',
497 route_name='admin_permissions_application', request_method='GET',
506 route_name='admin_permissions_application', request_method='GET',
498 renderer='rhodecode:templates/admin/permissions/permissions.mako')
507 renderer='rhodecode:templates/admin/permissions/permissions.mako')
499
508
500 config.add_route(
509 config.add_route(
501 name='admin_permissions_application_update',
510 name='admin_permissions_application_update',
502 pattern='/permissions/application/update')
511 pattern='/permissions/application/update')
503 config.add_view(
512 config.add_view(
504 AdminPermissionsView,
513 AdminPermissionsView,
505 attr='permissions_application_update',
514 attr='permissions_application_update',
506 route_name='admin_permissions_application_update', request_method='POST',
515 route_name='admin_permissions_application_update', request_method='POST',
507 renderer='rhodecode:templates/admin/permissions/permissions.mako')
516 renderer='rhodecode:templates/admin/permissions/permissions.mako')
508
517
509 config.add_route(
518 config.add_route(
510 name='admin_permissions_global',
519 name='admin_permissions_global',
511 pattern='/permissions/global')
520 pattern='/permissions/global')
512 config.add_view(
521 config.add_view(
513 AdminPermissionsView,
522 AdminPermissionsView,
514 attr='permissions_global',
523 attr='permissions_global',
515 route_name='admin_permissions_global', request_method='GET',
524 route_name='admin_permissions_global', request_method='GET',
516 renderer='rhodecode:templates/admin/permissions/permissions.mako')
525 renderer='rhodecode:templates/admin/permissions/permissions.mako')
517
526
518 config.add_route(
527 config.add_route(
519 name='admin_permissions_global_update',
528 name='admin_permissions_global_update',
520 pattern='/permissions/global/update')
529 pattern='/permissions/global/update')
521 config.add_view(
530 config.add_view(
522 AdminPermissionsView,
531 AdminPermissionsView,
523 attr='permissions_global_update',
532 attr='permissions_global_update',
524 route_name='admin_permissions_global_update', request_method='POST',
533 route_name='admin_permissions_global_update', request_method='POST',
525 renderer='rhodecode:templates/admin/permissions/permissions.mako')
534 renderer='rhodecode:templates/admin/permissions/permissions.mako')
526
535
527 config.add_route(
536 config.add_route(
528 name='admin_permissions_object',
537 name='admin_permissions_object',
529 pattern='/permissions/object')
538 pattern='/permissions/object')
530 config.add_view(
539 config.add_view(
531 AdminPermissionsView,
540 AdminPermissionsView,
532 attr='permissions_objects',
541 attr='permissions_objects',
533 route_name='admin_permissions_object', request_method='GET',
542 route_name='admin_permissions_object', request_method='GET',
534 renderer='rhodecode:templates/admin/permissions/permissions.mako')
543 renderer='rhodecode:templates/admin/permissions/permissions.mako')
535
544
536 config.add_route(
545 config.add_route(
537 name='admin_permissions_object_update',
546 name='admin_permissions_object_update',
538 pattern='/permissions/object/update')
547 pattern='/permissions/object/update')
539 config.add_view(
548 config.add_view(
540 AdminPermissionsView,
549 AdminPermissionsView,
541 attr='permissions_objects_update',
550 attr='permissions_objects_update',
542 route_name='admin_permissions_object_update', request_method='POST',
551 route_name='admin_permissions_object_update', request_method='POST',
543 renderer='rhodecode:templates/admin/permissions/permissions.mako')
552 renderer='rhodecode:templates/admin/permissions/permissions.mako')
544
553
545 # Branch perms EE feature
554 # Branch perms EE feature
546 config.add_route(
555 config.add_route(
547 name='admin_permissions_branch',
556 name='admin_permissions_branch',
548 pattern='/permissions/branch')
557 pattern='/permissions/branch')
549 config.add_view(
558 config.add_view(
550 AdminPermissionsView,
559 AdminPermissionsView,
551 attr='permissions_branch',
560 attr='permissions_branch',
552 route_name='admin_permissions_branch', request_method='GET',
561 route_name='admin_permissions_branch', request_method='GET',
553 renderer='rhodecode:templates/admin/permissions/permissions.mako')
562 renderer='rhodecode:templates/admin/permissions/permissions.mako')
554
563
555 config.add_route(
564 config.add_route(
556 name='admin_permissions_ips',
565 name='admin_permissions_ips',
557 pattern='/permissions/ips')
566 pattern='/permissions/ips')
558 config.add_view(
567 config.add_view(
559 AdminPermissionsView,
568 AdminPermissionsView,
560 attr='permissions_ips',
569 attr='permissions_ips',
561 route_name='admin_permissions_ips', request_method='GET',
570 route_name='admin_permissions_ips', request_method='GET',
562 renderer='rhodecode:templates/admin/permissions/permissions.mako')
571 renderer='rhodecode:templates/admin/permissions/permissions.mako')
563
572
564 config.add_route(
573 config.add_route(
565 name='admin_permissions_overview',
574 name='admin_permissions_overview',
566 pattern='/permissions/overview')
575 pattern='/permissions/overview')
567 config.add_view(
576 config.add_view(
568 AdminPermissionsView,
577 AdminPermissionsView,
569 attr='permissions_overview',
578 attr='permissions_overview',
570 route_name='admin_permissions_overview', request_method='GET',
579 route_name='admin_permissions_overview', request_method='GET',
571 renderer='rhodecode:templates/admin/permissions/permissions.mako')
580 renderer='rhodecode:templates/admin/permissions/permissions.mako')
572
581
573 config.add_route(
582 config.add_route(
574 name='admin_permissions_auth_token_access',
583 name='admin_permissions_auth_token_access',
575 pattern='/permissions/auth_token_access')
584 pattern='/permissions/auth_token_access')
576 config.add_view(
585 config.add_view(
577 AdminPermissionsView,
586 AdminPermissionsView,
578 attr='auth_token_access',
587 attr='auth_token_access',
579 route_name='admin_permissions_auth_token_access', request_method='GET',
588 route_name='admin_permissions_auth_token_access', request_method='GET',
580 renderer='rhodecode:templates/admin/permissions/permissions.mako')
589 renderer='rhodecode:templates/admin/permissions/permissions.mako')
581
590
582 config.add_route(
591 config.add_route(
583 name='admin_permissions_ssh_keys',
592 name='admin_permissions_ssh_keys',
584 pattern='/permissions/ssh_keys')
593 pattern='/permissions/ssh_keys')
585 config.add_view(
594 config.add_view(
586 AdminPermissionsView,
595 AdminPermissionsView,
587 attr='ssh_keys',
596 attr='ssh_keys',
588 route_name='admin_permissions_ssh_keys', request_method='GET',
597 route_name='admin_permissions_ssh_keys', request_method='GET',
589 renderer='rhodecode:templates/admin/permissions/permissions.mako')
598 renderer='rhodecode:templates/admin/permissions/permissions.mako')
590
599
591 config.add_route(
600 config.add_route(
592 name='admin_permissions_ssh_keys_data',
601 name='admin_permissions_ssh_keys_data',
593 pattern='/permissions/ssh_keys/data')
602 pattern='/permissions/ssh_keys/data')
594 config.add_view(
603 config.add_view(
595 AdminPermissionsView,
604 AdminPermissionsView,
596 attr='ssh_keys_data',
605 attr='ssh_keys_data',
597 route_name='admin_permissions_ssh_keys_data', request_method='GET',
606 route_name='admin_permissions_ssh_keys_data', request_method='GET',
598 renderer='json_ext', xhr=True)
607 renderer='json_ext', xhr=True)
599
608
600 config.add_route(
609 config.add_route(
601 name='admin_permissions_ssh_keys_update',
610 name='admin_permissions_ssh_keys_update',
602 pattern='/permissions/ssh_keys/update')
611 pattern='/permissions/ssh_keys/update')
603 config.add_view(
612 config.add_view(
604 AdminPermissionsView,
613 AdminPermissionsView,
605 attr='ssh_keys_update',
614 attr='ssh_keys_update',
606 route_name='admin_permissions_ssh_keys_update', request_method='POST',
615 route_name='admin_permissions_ssh_keys_update', request_method='POST',
607 renderer='rhodecode:templates/admin/permissions/permissions.mako')
616 renderer='rhodecode:templates/admin/permissions/permissions.mako')
608
617
609 # users admin
618 # users admin
610 config.add_route(
619 config.add_route(
611 name='users',
620 name='users',
612 pattern='/users')
621 pattern='/users')
613 config.add_view(
622 config.add_view(
614 AdminUsersView,
623 AdminUsersView,
615 attr='users_list',
624 attr='users_list',
616 route_name='users', request_method='GET',
625 route_name='users', request_method='GET',
617 renderer='rhodecode:templates/admin/users/users.mako')
626 renderer='rhodecode:templates/admin/users/users.mako')
618
627
619 config.add_route(
628 config.add_route(
620 name='users_data',
629 name='users_data',
621 pattern='/users_data')
630 pattern='/users_data')
622 config.add_view(
631 config.add_view(
623 AdminUsersView,
632 AdminUsersView,
624 attr='users_list_data',
633 attr='users_list_data',
625 # renderer defined below
634 # renderer defined below
626 route_name='users_data', request_method='GET',
635 route_name='users_data', request_method='GET',
627 renderer='json_ext', xhr=True)
636 renderer='json_ext', xhr=True)
628
637
629 config.add_route(
638 config.add_route(
630 name='users_create',
639 name='users_create',
631 pattern='/users/create')
640 pattern='/users/create')
632 config.add_view(
641 config.add_view(
633 AdminUsersView,
642 AdminUsersView,
634 attr='users_create',
643 attr='users_create',
635 route_name='users_create', request_method='POST',
644 route_name='users_create', request_method='POST',
636 renderer='rhodecode:templates/admin/users/user_add.mako')
645 renderer='rhodecode:templates/admin/users/user_add.mako')
637
646
638 config.add_route(
647 config.add_route(
639 name='users_new',
648 name='users_new',
640 pattern='/users/new')
649 pattern='/users/new')
641 config.add_view(
650 config.add_view(
642 AdminUsersView,
651 AdminUsersView,
643 attr='users_new',
652 attr='users_new',
644 route_name='users_new', request_method='GET',
653 route_name='users_new', request_method='GET',
645 renderer='rhodecode:templates/admin/users/user_add.mako')
654 renderer='rhodecode:templates/admin/users/user_add.mako')
646
655
647 # user management
656 # user management
648 config.add_route(
657 config.add_route(
649 name='user_edit',
658 name='user_edit',
650 pattern=r'/users/{user_id:\d+}/edit',
659 pattern=r'/users/{user_id:\d+}/edit',
651 user_route=True)
660 user_route=True)
652 config.add_view(
661 config.add_view(
653 UsersView,
662 UsersView,
654 attr='user_edit',
663 attr='user_edit',
655 route_name='user_edit', request_method='GET',
664 route_name='user_edit', request_method='GET',
656 renderer='rhodecode:templates/admin/users/user_edit.mako')
665 renderer='rhodecode:templates/admin/users/user_edit.mako')
657
666
658 config.add_route(
667 config.add_route(
659 name='user_edit_advanced',
668 name='user_edit_advanced',
660 pattern=r'/users/{user_id:\d+}/edit/advanced',
669 pattern=r'/users/{user_id:\d+}/edit/advanced',
661 user_route=True)
670 user_route=True)
662 config.add_view(
671 config.add_view(
663 UsersView,
672 UsersView,
664 attr='user_edit_advanced',
673 attr='user_edit_advanced',
665 route_name='user_edit_advanced', request_method='GET',
674 route_name='user_edit_advanced', request_method='GET',
666 renderer='rhodecode:templates/admin/users/user_edit.mako')
675 renderer='rhodecode:templates/admin/users/user_edit.mako')
667
676
668 config.add_route(
677 config.add_route(
669 name='user_edit_global_perms',
678 name='user_edit_global_perms',
670 pattern=r'/users/{user_id:\d+}/edit/global_permissions',
679 pattern=r'/users/{user_id:\d+}/edit/global_permissions',
671 user_route=True)
680 user_route=True)
672 config.add_view(
681 config.add_view(
673 UsersView,
682 UsersView,
674 attr='user_edit_global_perms',
683 attr='user_edit_global_perms',
675 route_name='user_edit_global_perms', request_method='GET',
684 route_name='user_edit_global_perms', request_method='GET',
676 renderer='rhodecode:templates/admin/users/user_edit.mako')
685 renderer='rhodecode:templates/admin/users/user_edit.mako')
677
686
678 config.add_route(
687 config.add_route(
679 name='user_edit_global_perms_update',
688 name='user_edit_global_perms_update',
680 pattern=r'/users/{user_id:\d+}/edit/global_permissions/update',
689 pattern=r'/users/{user_id:\d+}/edit/global_permissions/update',
681 user_route=True)
690 user_route=True)
682 config.add_view(
691 config.add_view(
683 UsersView,
692 UsersView,
684 attr='user_edit_global_perms_update',
693 attr='user_edit_global_perms_update',
685 route_name='user_edit_global_perms_update', request_method='POST',
694 route_name='user_edit_global_perms_update', request_method='POST',
686 renderer='rhodecode:templates/admin/users/user_edit.mako')
695 renderer='rhodecode:templates/admin/users/user_edit.mako')
687
696
688 config.add_route(
697 config.add_route(
689 name='user_update',
698 name='user_update',
690 pattern=r'/users/{user_id:\d+}/update',
699 pattern=r'/users/{user_id:\d+}/update',
691 user_route=True)
700 user_route=True)
692 config.add_view(
701 config.add_view(
693 UsersView,
702 UsersView,
694 attr='user_update',
703 attr='user_update',
695 route_name='user_update', request_method='POST',
704 route_name='user_update', request_method='POST',
696 renderer='rhodecode:templates/admin/users/user_edit.mako')
705 renderer='rhodecode:templates/admin/users/user_edit.mako')
697
706
698 config.add_route(
707 config.add_route(
699 name='user_delete',
708 name='user_delete',
700 pattern=r'/users/{user_id:\d+}/delete',
709 pattern=r'/users/{user_id:\d+}/delete',
701 user_route=True)
710 user_route=True)
702 config.add_view(
711 config.add_view(
703 UsersView,
712 UsersView,
704 attr='user_delete',
713 attr='user_delete',
705 route_name='user_delete', request_method='POST',
714 route_name='user_delete', request_method='POST',
706 renderer='rhodecode:templates/admin/users/user_edit.mako')
715 renderer='rhodecode:templates/admin/users/user_edit.mako')
707
716
708 config.add_route(
717 config.add_route(
709 name='user_enable_force_password_reset',
718 name='user_enable_force_password_reset',
710 pattern=r'/users/{user_id:\d+}/password_reset_enable',
719 pattern=r'/users/{user_id:\d+}/password_reset_enable',
711 user_route=True)
720 user_route=True)
712 config.add_view(
721 config.add_view(
713 UsersView,
722 UsersView,
714 attr='user_enable_force_password_reset',
723 attr='user_enable_force_password_reset',
715 route_name='user_enable_force_password_reset', request_method='POST',
724 route_name='user_enable_force_password_reset', request_method='POST',
716 renderer='rhodecode:templates/admin/users/user_edit.mako')
725 renderer='rhodecode:templates/admin/users/user_edit.mako')
717
726
718 config.add_route(
727 config.add_route(
719 name='user_disable_force_password_reset',
728 name='user_disable_force_password_reset',
720 pattern=r'/users/{user_id:\d+}/password_reset_disable',
729 pattern=r'/users/{user_id:\d+}/password_reset_disable',
721 user_route=True)
730 user_route=True)
722 config.add_view(
731 config.add_view(
723 UsersView,
732 UsersView,
724 attr='user_disable_force_password_reset',
733 attr='user_disable_force_password_reset',
725 route_name='user_disable_force_password_reset', request_method='POST',
734 route_name='user_disable_force_password_reset', request_method='POST',
726 renderer='rhodecode:templates/admin/users/user_edit.mako')
735 renderer='rhodecode:templates/admin/users/user_edit.mako')
727
736
728 config.add_route(
737 config.add_route(
729 name='user_create_personal_repo_group',
738 name='user_create_personal_repo_group',
730 pattern=r'/users/{user_id:\d+}/create_repo_group',
739 pattern=r'/users/{user_id:\d+}/create_repo_group',
731 user_route=True)
740 user_route=True)
732 config.add_view(
741 config.add_view(
733 UsersView,
742 UsersView,
734 attr='user_create_personal_repo_group',
743 attr='user_create_personal_repo_group',
735 route_name='user_create_personal_repo_group', request_method='POST',
744 route_name='user_create_personal_repo_group', request_method='POST',
736 renderer='rhodecode:templates/admin/users/user_edit.mako')
745 renderer='rhodecode:templates/admin/users/user_edit.mako')
737
746
738 # user notice
747 # user notice
739 config.add_route(
748 config.add_route(
740 name='user_notice_dismiss',
749 name='user_notice_dismiss',
741 pattern=r'/users/{user_id:\d+}/notice_dismiss',
750 pattern=r'/users/{user_id:\d+}/notice_dismiss',
742 user_route=True)
751 user_route=True)
743 config.add_view(
752 config.add_view(
744 UsersView,
753 UsersView,
745 attr='user_notice_dismiss',
754 attr='user_notice_dismiss',
746 route_name='user_notice_dismiss', request_method='POST',
755 route_name='user_notice_dismiss', request_method='POST',
747 renderer='json_ext', xhr=True)
756 renderer='json_ext', xhr=True)
748
757
749 # user auth tokens
758 # user auth tokens
750 config.add_route(
759 config.add_route(
751 name='edit_user_auth_tokens',
760 name='edit_user_auth_tokens',
752 pattern=r'/users/{user_id:\d+}/edit/auth_tokens',
761 pattern=r'/users/{user_id:\d+}/edit/auth_tokens',
753 user_route=True)
762 user_route=True)
754 config.add_view(
763 config.add_view(
755 UsersView,
764 UsersView,
756 attr='auth_tokens',
765 attr='auth_tokens',
757 route_name='edit_user_auth_tokens', request_method='GET',
766 route_name='edit_user_auth_tokens', request_method='GET',
758 renderer='rhodecode:templates/admin/users/user_edit.mako')
767 renderer='rhodecode:templates/admin/users/user_edit.mako')
759
768
760 config.add_route(
769 config.add_route(
761 name='edit_user_auth_tokens_view',
770 name='edit_user_auth_tokens_view',
762 pattern=r'/users/{user_id:\d+}/edit/auth_tokens/view',
771 pattern=r'/users/{user_id:\d+}/edit/auth_tokens/view',
763 user_route=True)
772 user_route=True)
764 config.add_view(
773 config.add_view(
765 UsersView,
774 UsersView,
766 attr='auth_tokens_view',
775 attr='auth_tokens_view',
767 route_name='edit_user_auth_tokens_view', request_method='POST',
776 route_name='edit_user_auth_tokens_view', request_method='POST',
768 renderer='json_ext', xhr=True)
777 renderer='json_ext', xhr=True)
769
778
770 config.add_route(
779 config.add_route(
771 name='edit_user_auth_tokens_add',
780 name='edit_user_auth_tokens_add',
772 pattern=r'/users/{user_id:\d+}/edit/auth_tokens/new',
781 pattern=r'/users/{user_id:\d+}/edit/auth_tokens/new',
773 user_route=True)
782 user_route=True)
774 config.add_view(
783 config.add_view(
775 UsersView,
784 UsersView,
776 attr='auth_tokens_add',
785 attr='auth_tokens_add',
777 route_name='edit_user_auth_tokens_add', request_method='POST')
786 route_name='edit_user_auth_tokens_add', request_method='POST')
778
787
779 config.add_route(
788 config.add_route(
780 name='edit_user_auth_tokens_delete',
789 name='edit_user_auth_tokens_delete',
781 pattern=r'/users/{user_id:\d+}/edit/auth_tokens/delete',
790 pattern=r'/users/{user_id:\d+}/edit/auth_tokens/delete',
782 user_route=True)
791 user_route=True)
783 config.add_view(
792 config.add_view(
784 UsersView,
793 UsersView,
785 attr='auth_tokens_delete',
794 attr='auth_tokens_delete',
786 route_name='edit_user_auth_tokens_delete', request_method='POST')
795 route_name='edit_user_auth_tokens_delete', request_method='POST')
787
796
788 # user ssh keys
797 # user ssh keys
789 config.add_route(
798 config.add_route(
790 name='edit_user_ssh_keys',
799 name='edit_user_ssh_keys',
791 pattern=r'/users/{user_id:\d+}/edit/ssh_keys',
800 pattern=r'/users/{user_id:\d+}/edit/ssh_keys',
792 user_route=True)
801 user_route=True)
793 config.add_view(
802 config.add_view(
794 UsersView,
803 UsersView,
795 attr='ssh_keys',
804 attr='ssh_keys',
796 route_name='edit_user_ssh_keys', request_method='GET',
805 route_name='edit_user_ssh_keys', request_method='GET',
797 renderer='rhodecode:templates/admin/users/user_edit.mako')
806 renderer='rhodecode:templates/admin/users/user_edit.mako')
798
807
799 config.add_route(
808 config.add_route(
800 name='edit_user_ssh_keys_generate_keypair',
809 name='edit_user_ssh_keys_generate_keypair',
801 pattern=r'/users/{user_id:\d+}/edit/ssh_keys/generate',
810 pattern=r'/users/{user_id:\d+}/edit/ssh_keys/generate',
802 user_route=True)
811 user_route=True)
803 config.add_view(
812 config.add_view(
804 UsersView,
813 UsersView,
805 attr='ssh_keys_generate_keypair',
814 attr='ssh_keys_generate_keypair',
806 route_name='edit_user_ssh_keys_generate_keypair', request_method='GET',
815 route_name='edit_user_ssh_keys_generate_keypair', request_method='GET',
807 renderer='rhodecode:templates/admin/users/user_edit.mako')
816 renderer='rhodecode:templates/admin/users/user_edit.mako')
808
817
809 config.add_route(
818 config.add_route(
810 name='edit_user_ssh_keys_add',
819 name='edit_user_ssh_keys_add',
811 pattern=r'/users/{user_id:\d+}/edit/ssh_keys/new',
820 pattern=r'/users/{user_id:\d+}/edit/ssh_keys/new',
812 user_route=True)
821 user_route=True)
813 config.add_view(
822 config.add_view(
814 UsersView,
823 UsersView,
815 attr='ssh_keys_add',
824 attr='ssh_keys_add',
816 route_name='edit_user_ssh_keys_add', request_method='POST')
825 route_name='edit_user_ssh_keys_add', request_method='POST')
817
826
818 config.add_route(
827 config.add_route(
819 name='edit_user_ssh_keys_delete',
828 name='edit_user_ssh_keys_delete',
820 pattern=r'/users/{user_id:\d+}/edit/ssh_keys/delete',
829 pattern=r'/users/{user_id:\d+}/edit/ssh_keys/delete',
821 user_route=True)
830 user_route=True)
822 config.add_view(
831 config.add_view(
823 UsersView,
832 UsersView,
824 attr='ssh_keys_delete',
833 attr='ssh_keys_delete',
825 route_name='edit_user_ssh_keys_delete', request_method='POST')
834 route_name='edit_user_ssh_keys_delete', request_method='POST')
826
835
827 # user emails
836 # user emails
828 config.add_route(
837 config.add_route(
829 name='edit_user_emails',
838 name='edit_user_emails',
830 pattern=r'/users/{user_id:\d+}/edit/emails',
839 pattern=r'/users/{user_id:\d+}/edit/emails',
831 user_route=True)
840 user_route=True)
832 config.add_view(
841 config.add_view(
833 UsersView,
842 UsersView,
834 attr='emails',
843 attr='emails',
835 route_name='edit_user_emails', request_method='GET',
844 route_name='edit_user_emails', request_method='GET',
836 renderer='rhodecode:templates/admin/users/user_edit.mako')
845 renderer='rhodecode:templates/admin/users/user_edit.mako')
837
846
838 config.add_route(
847 config.add_route(
839 name='edit_user_emails_add',
848 name='edit_user_emails_add',
840 pattern=r'/users/{user_id:\d+}/edit/emails/new',
849 pattern=r'/users/{user_id:\d+}/edit/emails/new',
841 user_route=True)
850 user_route=True)
842 config.add_view(
851 config.add_view(
843 UsersView,
852 UsersView,
844 attr='emails_add',
853 attr='emails_add',
845 route_name='edit_user_emails_add', request_method='POST')
854 route_name='edit_user_emails_add', request_method='POST')
846
855
847 config.add_route(
856 config.add_route(
848 name='edit_user_emails_delete',
857 name='edit_user_emails_delete',
849 pattern=r'/users/{user_id:\d+}/edit/emails/delete',
858 pattern=r'/users/{user_id:\d+}/edit/emails/delete',
850 user_route=True)
859 user_route=True)
851 config.add_view(
860 config.add_view(
852 UsersView,
861 UsersView,
853 attr='emails_delete',
862 attr='emails_delete',
854 route_name='edit_user_emails_delete', request_method='POST')
863 route_name='edit_user_emails_delete', request_method='POST')
855
864
856 # user IPs
865 # user IPs
857 config.add_route(
866 config.add_route(
858 name='edit_user_ips',
867 name='edit_user_ips',
859 pattern=r'/users/{user_id:\d+}/edit/ips',
868 pattern=r'/users/{user_id:\d+}/edit/ips',
860 user_route=True)
869 user_route=True)
861 config.add_view(
870 config.add_view(
862 UsersView,
871 UsersView,
863 attr='ips',
872 attr='ips',
864 route_name='edit_user_ips', request_method='GET',
873 route_name='edit_user_ips', request_method='GET',
865 renderer='rhodecode:templates/admin/users/user_edit.mako')
874 renderer='rhodecode:templates/admin/users/user_edit.mako')
866
875
867 config.add_route(
876 config.add_route(
868 name='edit_user_ips_add',
877 name='edit_user_ips_add',
869 pattern=r'/users/{user_id:\d+}/edit/ips/new',
878 pattern=r'/users/{user_id:\d+}/edit/ips/new',
870 user_route_with_default=True) # enabled for default user too
879 user_route_with_default=True) # enabled for default user too
871 config.add_view(
880 config.add_view(
872 UsersView,
881 UsersView,
873 attr='ips_add',
882 attr='ips_add',
874 route_name='edit_user_ips_add', request_method='POST')
883 route_name='edit_user_ips_add', request_method='POST')
875
884
876 config.add_route(
885 config.add_route(
877 name='edit_user_ips_delete',
886 name='edit_user_ips_delete',
878 pattern=r'/users/{user_id:\d+}/edit/ips/delete',
887 pattern=r'/users/{user_id:\d+}/edit/ips/delete',
879 user_route_with_default=True) # enabled for default user too
888 user_route_with_default=True) # enabled for default user too
880 config.add_view(
889 config.add_view(
881 UsersView,
890 UsersView,
882 attr='ips_delete',
891 attr='ips_delete',
883 route_name='edit_user_ips_delete', request_method='POST')
892 route_name='edit_user_ips_delete', request_method='POST')
884
893
885 # user perms
894 # user perms
886 config.add_route(
895 config.add_route(
887 name='edit_user_perms_summary',
896 name='edit_user_perms_summary',
888 pattern=r'/users/{user_id:\d+}/edit/permissions_summary',
897 pattern=r'/users/{user_id:\d+}/edit/permissions_summary',
889 user_route=True)
898 user_route=True)
890 config.add_view(
899 config.add_view(
891 UsersView,
900 UsersView,
892 attr='user_perms_summary',
901 attr='user_perms_summary',
893 route_name='edit_user_perms_summary', request_method='GET',
902 route_name='edit_user_perms_summary', request_method='GET',
894 renderer='rhodecode:templates/admin/users/user_edit.mako')
903 renderer='rhodecode:templates/admin/users/user_edit.mako')
895
904
896 config.add_route(
905 config.add_route(
897 name='edit_user_perms_summary_json',
906 name='edit_user_perms_summary_json',
898 pattern=r'/users/{user_id:\d+}/edit/permissions_summary/json',
907 pattern=r'/users/{user_id:\d+}/edit/permissions_summary/json',
899 user_route=True)
908 user_route=True)
900 config.add_view(
909 config.add_view(
901 UsersView,
910 UsersView,
902 attr='user_perms_summary_json',
911 attr='user_perms_summary_json',
903 route_name='edit_user_perms_summary_json', request_method='GET',
912 route_name='edit_user_perms_summary_json', request_method='GET',
904 renderer='json_ext')
913 renderer='json_ext')
905
914
906 # user user groups management
915 # user user groups management
907 config.add_route(
916 config.add_route(
908 name='edit_user_groups_management',
917 name='edit_user_groups_management',
909 pattern=r'/users/{user_id:\d+}/edit/groups_management',
918 pattern=r'/users/{user_id:\d+}/edit/groups_management',
910 user_route=True)
919 user_route=True)
911 config.add_view(
920 config.add_view(
912 UsersView,
921 UsersView,
913 attr='groups_management',
922 attr='groups_management',
914 route_name='edit_user_groups_management', request_method='GET',
923 route_name='edit_user_groups_management', request_method='GET',
915 renderer='rhodecode:templates/admin/users/user_edit.mako')
924 renderer='rhodecode:templates/admin/users/user_edit.mako')
916
925
917 config.add_route(
926 config.add_route(
918 name='edit_user_groups_management_updates',
927 name='edit_user_groups_management_updates',
919 pattern=r'/users/{user_id:\d+}/edit/edit_user_groups_management/updates',
928 pattern=r'/users/{user_id:\d+}/edit/edit_user_groups_management/updates',
920 user_route=True)
929 user_route=True)
921 config.add_view(
930 config.add_view(
922 UsersView,
931 UsersView,
923 attr='groups_management_updates',
932 attr='groups_management_updates',
924 route_name='edit_user_groups_management_updates', request_method='POST')
933 route_name='edit_user_groups_management_updates', request_method='POST')
925
934
926 # user audit logs
935 # user audit logs
927 config.add_route(
936 config.add_route(
928 name='edit_user_audit_logs',
937 name='edit_user_audit_logs',
929 pattern=r'/users/{user_id:\d+}/edit/audit', user_route=True)
938 pattern=r'/users/{user_id:\d+}/edit/audit', user_route=True)
930 config.add_view(
939 config.add_view(
931 UsersView,
940 UsersView,
932 attr='user_audit_logs',
941 attr='user_audit_logs',
933 route_name='edit_user_audit_logs', request_method='GET',
942 route_name='edit_user_audit_logs', request_method='GET',
934 renderer='rhodecode:templates/admin/users/user_edit.mako')
943 renderer='rhodecode:templates/admin/users/user_edit.mako')
935
944
936 config.add_route(
945 config.add_route(
937 name='edit_user_audit_logs_download',
946 name='edit_user_audit_logs_download',
938 pattern=r'/users/{user_id:\d+}/edit/audit/download', user_route=True)
947 pattern=r'/users/{user_id:\d+}/edit/audit/download', user_route=True)
939 config.add_view(
948 config.add_view(
940 UsersView,
949 UsersView,
941 attr='user_audit_logs_download',
950 attr='user_audit_logs_download',
942 route_name='edit_user_audit_logs_download', request_method='GET',
951 route_name='edit_user_audit_logs_download', request_method='GET',
943 renderer='string')
952 renderer='string')
944
953
945 # user caches
954 # user caches
946 config.add_route(
955 config.add_route(
947 name='edit_user_caches',
956 name='edit_user_caches',
948 pattern=r'/users/{user_id:\d+}/edit/caches',
957 pattern=r'/users/{user_id:\d+}/edit/caches',
949 user_route=True)
958 user_route=True)
950 config.add_view(
959 config.add_view(
951 UsersView,
960 UsersView,
952 attr='user_caches',
961 attr='user_caches',
953 route_name='edit_user_caches', request_method='GET',
962 route_name='edit_user_caches', request_method='GET',
954 renderer='rhodecode:templates/admin/users/user_edit.mako')
963 renderer='rhodecode:templates/admin/users/user_edit.mako')
955
964
956 config.add_route(
965 config.add_route(
957 name='edit_user_caches_update',
966 name='edit_user_caches_update',
958 pattern=r'/users/{user_id:\d+}/edit/caches/update',
967 pattern=r'/users/{user_id:\d+}/edit/caches/update',
959 user_route=True)
968 user_route=True)
960 config.add_view(
969 config.add_view(
961 UsersView,
970 UsersView,
962 attr='user_caches_update',
971 attr='user_caches_update',
963 route_name='edit_user_caches_update', request_method='POST')
972 route_name='edit_user_caches_update', request_method='POST')
964
973
965 # user-groups admin
974 # user-groups admin
966 config.add_route(
975 config.add_route(
967 name='user_groups',
976 name='user_groups',
968 pattern='/user_groups')
977 pattern='/user_groups')
969 config.add_view(
978 config.add_view(
970 AdminUserGroupsView,
979 AdminUserGroupsView,
971 attr='user_groups_list',
980 attr='user_groups_list',
972 route_name='user_groups', request_method='GET',
981 route_name='user_groups', request_method='GET',
973 renderer='rhodecode:templates/admin/user_groups/user_groups.mako')
982 renderer='rhodecode:templates/admin/user_groups/user_groups.mako')
974
983
975 config.add_route(
984 config.add_route(
976 name='user_groups_data',
985 name='user_groups_data',
977 pattern='/user_groups_data')
986 pattern='/user_groups_data')
978 config.add_view(
987 config.add_view(
979 AdminUserGroupsView,
988 AdminUserGroupsView,
980 attr='user_groups_list_data',
989 attr='user_groups_list_data',
981 route_name='user_groups_data', request_method='GET',
990 route_name='user_groups_data', request_method='GET',
982 renderer='json_ext', xhr=True)
991 renderer='json_ext', xhr=True)
983
992
984 config.add_route(
993 config.add_route(
985 name='user_groups_new',
994 name='user_groups_new',
986 pattern='/user_groups/new')
995 pattern='/user_groups/new')
987 config.add_view(
996 config.add_view(
988 AdminUserGroupsView,
997 AdminUserGroupsView,
989 attr='user_groups_new',
998 attr='user_groups_new',
990 route_name='user_groups_new', request_method='GET',
999 route_name='user_groups_new', request_method='GET',
991 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
1000 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
992
1001
993 config.add_route(
1002 config.add_route(
994 name='user_groups_create',
1003 name='user_groups_create',
995 pattern='/user_groups/create')
1004 pattern='/user_groups/create')
996 config.add_view(
1005 config.add_view(
997 AdminUserGroupsView,
1006 AdminUserGroupsView,
998 attr='user_groups_create',
1007 attr='user_groups_create',
999 route_name='user_groups_create', request_method='POST',
1008 route_name='user_groups_create', request_method='POST',
1000 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
1009 renderer='rhodecode:templates/admin/user_groups/user_group_add.mako')
1001
1010
1002 # repos admin
1011 # repos admin
1003 config.add_route(
1012 config.add_route(
1004 name='repos',
1013 name='repos',
1005 pattern='/repos')
1014 pattern='/repos')
1006 config.add_view(
1015 config.add_view(
1007 AdminReposView,
1016 AdminReposView,
1008 attr='repository_list',
1017 attr='repository_list',
1009 route_name='repos', request_method='GET',
1018 route_name='repos', request_method='GET',
1010 renderer='rhodecode:templates/admin/repos/repos.mako')
1019 renderer='rhodecode:templates/admin/repos/repos.mako')
1011
1020
1012 config.add_route(
1021 config.add_route(
1013 name='repos_data',
1022 name='repos_data',
1014 pattern='/repos_data')
1023 pattern='/repos_data')
1015 config.add_view(
1024 config.add_view(
1016 AdminReposView,
1025 AdminReposView,
1017 attr='repository_list_data',
1026 attr='repository_list_data',
1018 route_name='repos_data', request_method='GET',
1027 route_name='repos_data', request_method='GET',
1019 renderer='json_ext', xhr=True)
1028 renderer='json_ext', xhr=True)
1020
1029
1021 config.add_route(
1030 config.add_route(
1022 name='repo_new',
1031 name='repo_new',
1023 pattern='/repos/new')
1032 pattern='/repos/new')
1024 config.add_view(
1033 config.add_view(
1025 AdminReposView,
1034 AdminReposView,
1026 attr='repository_new',
1035 attr='repository_new',
1027 route_name='repo_new', request_method='GET',
1036 route_name='repo_new', request_method='GET',
1028 renderer='rhodecode:templates/admin/repos/repo_add.mako')
1037 renderer='rhodecode:templates/admin/repos/repo_add.mako')
1029
1038
1030 config.add_route(
1039 config.add_route(
1031 name='repo_create',
1040 name='repo_create',
1032 pattern='/repos/create')
1041 pattern='/repos/create')
1033 config.add_view(
1042 config.add_view(
1034 AdminReposView,
1043 AdminReposView,
1035 attr='repository_create',
1044 attr='repository_create',
1036 route_name='repo_create', request_method='POST',
1045 route_name='repo_create', request_method='POST',
1037 renderer='rhodecode:templates/admin/repos/repos.mako')
1046 renderer='rhodecode:templates/admin/repos/repos.mako')
1038
1047
1039 # repo groups admin
1048 # repo groups admin
1040 config.add_route(
1049 config.add_route(
1041 name='repo_groups',
1050 name='repo_groups',
1042 pattern='/repo_groups')
1051 pattern='/repo_groups')
1043 config.add_view(
1052 config.add_view(
1044 AdminRepoGroupsView,
1053 AdminRepoGroupsView,
1045 attr='repo_group_list',
1054 attr='repo_group_list',
1046 route_name='repo_groups', request_method='GET',
1055 route_name='repo_groups', request_method='GET',
1047 renderer='rhodecode:templates/admin/repo_groups/repo_groups.mako')
1056 renderer='rhodecode:templates/admin/repo_groups/repo_groups.mako')
1048
1057
1049 config.add_route(
1058 config.add_route(
1050 name='repo_groups_data',
1059 name='repo_groups_data',
1051 pattern='/repo_groups_data')
1060 pattern='/repo_groups_data')
1052 config.add_view(
1061 config.add_view(
1053 AdminRepoGroupsView,
1062 AdminRepoGroupsView,
1054 attr='repo_group_list_data',
1063 attr='repo_group_list_data',
1055 route_name='repo_groups_data', request_method='GET',
1064 route_name='repo_groups_data', request_method='GET',
1056 renderer='json_ext', xhr=True)
1065 renderer='json_ext', xhr=True)
1057
1066
1058 config.add_route(
1067 config.add_route(
1059 name='repo_group_new',
1068 name='repo_group_new',
1060 pattern='/repo_group/new')
1069 pattern='/repo_group/new')
1061 config.add_view(
1070 config.add_view(
1062 AdminRepoGroupsView,
1071 AdminRepoGroupsView,
1063 attr='repo_group_new',
1072 attr='repo_group_new',
1064 route_name='repo_group_new', request_method='GET',
1073 route_name='repo_group_new', request_method='GET',
1065 renderer='rhodecode:templates/admin/repo_groups/repo_group_add.mako')
1074 renderer='rhodecode:templates/admin/repo_groups/repo_group_add.mako')
1066
1075
1067 config.add_route(
1076 config.add_route(
1068 name='repo_group_create',
1077 name='repo_group_create',
1069 pattern='/repo_group/create')
1078 pattern='/repo_group/create')
1070 config.add_view(
1079 config.add_view(
1071 AdminRepoGroupsView,
1080 AdminRepoGroupsView,
1072 attr='repo_group_create',
1081 attr='repo_group_create',
1073 route_name='repo_group_create', request_method='POST',
1082 route_name='repo_group_create', request_method='POST',
1074 renderer='rhodecode:templates/admin/repo_groups/repo_group_add.mako')
1083 renderer='rhodecode:templates/admin/repo_groups/repo_group_add.mako')
1075
1084
1076
1085
1077 def includeme(config):
1086 def includeme(config):
1078 # Create admin navigation registry and add it to the pyramid registry.
1087 # Create admin navigation registry and add it to the pyramid registry.
1079 nav_includeme(config)
1088 nav_includeme(config)
1080
1089
1081 # main admin routes
1090 # main admin routes
1082 config.add_route(
1091 config.add_route(
1083 name='admin_home', pattern=ADMIN_PREFIX)
1092 name='admin_home', pattern=ADMIN_PREFIX)
1084 config.add_view(
1093 config.add_view(
1085 AdminMainView,
1094 AdminMainView,
1086 attr='admin_main',
1095 attr='admin_main',
1087 route_name='admin_home', request_method='GET',
1096 route_name='admin_home', request_method='GET',
1088 renderer='rhodecode:templates/admin/main.mako')
1097 renderer='rhodecode:templates/admin/main.mako')
1089
1098
1090 # pr global redirect
1099 # pr global redirect
1091 config.add_route(
1100 config.add_route(
1092 name='pull_requests_global_0', # backward compat
1101 name='pull_requests_global_0', # backward compat
1093 pattern=ADMIN_PREFIX + r'/pull_requests/{pull_request_id:\d+}')
1102 pattern=ADMIN_PREFIX + r'/pull_requests/{pull_request_id:\d+}')
1094 config.add_view(
1103 config.add_view(
1095 AdminMainView,
1104 AdminMainView,
1096 attr='pull_requests',
1105 attr='pull_requests',
1097 route_name='pull_requests_global_0', request_method='GET')
1106 route_name='pull_requests_global_0', request_method='GET')
1098
1107
1099 config.add_route(
1108 config.add_route(
1100 name='pull_requests_global_1', # backward compat
1109 name='pull_requests_global_1', # backward compat
1101 pattern=ADMIN_PREFIX + r'/pull-requests/{pull_request_id:\d+}')
1110 pattern=ADMIN_PREFIX + r'/pull-requests/{pull_request_id:\d+}')
1102 config.add_view(
1111 config.add_view(
1103 AdminMainView,
1112 AdminMainView,
1104 attr='pull_requests',
1113 attr='pull_requests',
1105 route_name='pull_requests_global_1', request_method='GET')
1114 route_name='pull_requests_global_1', request_method='GET')
1106
1115
1107 config.add_route(
1116 config.add_route(
1108 name='pull_requests_global',
1117 name='pull_requests_global',
1109 pattern=ADMIN_PREFIX + r'/pull-request/{pull_request_id:\d+}')
1118 pattern=ADMIN_PREFIX + r'/pull-request/{pull_request_id:\d+}')
1110 config.add_view(
1119 config.add_view(
1111 AdminMainView,
1120 AdminMainView,
1112 attr='pull_requests',
1121 attr='pull_requests',
1113 route_name='pull_requests_global', request_method='GET')
1122 route_name='pull_requests_global', request_method='GET')
1114
1123
1115 config.include(admin_routes, route_prefix=ADMIN_PREFIX)
1124 config.include(admin_routes, route_prefix=ADMIN_PREFIX)
@@ -1,39 +1,72 b''
1 # Copyright (C) 2010-2024 RhodeCode GmbH
1 # Copyright (C) 2010-2024 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import logging
19 import logging
20 import formencode
20
21
22 from rhodecode import BACKENDS
21 from rhodecode.apps._base import BaseAppView
23 from rhodecode.apps._base import BaseAppView
24 from rhodecode.model.meta import Session
25 from rhodecode.model.settings import SettingsModel
26 from rhodecode.model.forms import WhitelistedVcsClientsForm
22 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
27 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
23
28
24 log = logging.getLogger(__name__)
29 log = logging.getLogger(__name__)
25
30
26
31
27 class AdminSecurityView(BaseAppView):
32 class AdminSecurityView(BaseAppView):
28
33
29 def load_default_context(self):
34 def load_default_context(self):
30 c = self._get_local_tmpl_context()
35 c = self._get_local_tmpl_context()
31 return c
36 return c
32
37
33 @LoginRequired()
38 @LoginRequired()
34 @HasPermissionAllDecorator('hg.admin')
39 @HasPermissionAllDecorator('hg.admin')
35 def security(self):
40 def security(self):
36 c = self.load_default_context()
41 c = self.load_default_context()
37 c.active = 'security'
42 c.active = 'security'
38 return self._get_template_context(c)
43 return self._get_template_context(c)
39
44
45 @LoginRequired()
46 @HasPermissionAllDecorator('hg.admin')
47 def vcs_whitelisted_client_versions_edit(self):
48 _ = self.request.translate
49 c = self.load_default_context()
50 render_ctx = {}
51 settings = SettingsModel()
52 form = WhitelistedVcsClientsForm(_, )()
53 if self.request.method == 'POST':
54 try:
55 result = form.to_python(self.request.POST)
56 for k, v in result.items():
57 if v:
58 setting = settings.create_or_update_setting(name=f'{k}_allowed_clients', val=v)
59 Session().add(setting)
60 Session().commit()
61
62 except formencode.Invalid as errors:
63 render_ctx.update({
64 'errors': errors.error_dict
65 })
66 for key in BACKENDS.keys():
67 verbose_name = f"initial_{key}"
68 if existing := settings.get_setting_by_name(name=f'{key}_allowed_clients'):
69 render_ctx[verbose_name] = existing.app_settings_value
70 else:
71 render_ctx[verbose_name] = '*'
72 return self._get_template_context(c, **render_ctx)
@@ -1,209 +1,214 b''
1 # Copyright (C) 2010-2023 RhodeCode GmbH
1 # Copyright (C) 2010-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 """
19 """
20 Set of custom exceptions used in RhodeCode
20 Set of custom exceptions used in RhodeCode
21 """
21 """
22
22
23 from webob.exc import HTTPClientError
23 from webob.exc import HTTPClientError
24 from pyramid.httpexceptions import HTTPBadGateway
24 from pyramid.httpexceptions import HTTPBadGateway
25
25
26
26
27 class LdapUsernameError(Exception):
27 class LdapUsernameError(Exception):
28 pass
28 pass
29
29
30
30
31 class LdapPasswordError(Exception):
31 class LdapPasswordError(Exception):
32 pass
32 pass
33
33
34
34
35 class LdapConnectionError(Exception):
35 class LdapConnectionError(Exception):
36 pass
36 pass
37
37
38
38
39 class LdapImportError(Exception):
39 class LdapImportError(Exception):
40 pass
40 pass
41
41
42
42
43 class DefaultUserException(Exception):
43 class DefaultUserException(Exception):
44 pass
44 pass
45
45
46
46
47 class UserOwnsReposException(Exception):
47 class UserOwnsReposException(Exception):
48 pass
48 pass
49
49
50
50
51 class UserOwnsRepoGroupsException(Exception):
51 class UserOwnsRepoGroupsException(Exception):
52 pass
52 pass
53
53
54
54
55 class UserOwnsUserGroupsException(Exception):
55 class UserOwnsUserGroupsException(Exception):
56 pass
56 pass
57
57
58
58
59 class UserOwnsPullRequestsException(Exception):
59 class UserOwnsPullRequestsException(Exception):
60 pass
60 pass
61
61
62
62
63 class UserOwnsArtifactsException(Exception):
63 class UserOwnsArtifactsException(Exception):
64 pass
64 pass
65
65
66
66
67 class UserGroupAssignedException(Exception):
67 class UserGroupAssignedException(Exception):
68 pass
68 pass
69
69
70
70
71 class StatusChangeOnClosedPullRequestError(Exception):
71 class StatusChangeOnClosedPullRequestError(Exception):
72 pass
72 pass
73
73
74
74
75 class AttachedForksError(Exception):
75 class AttachedForksError(Exception):
76 pass
76 pass
77
77
78
78
79 class AttachedPullRequestsError(Exception):
79 class AttachedPullRequestsError(Exception):
80 pass
80 pass
81
81
82
82
83 class AttachedArtifactsError(Exception):
83 class AttachedArtifactsError(Exception):
84 pass
84 pass
85
85
86
86
87 class RepoGroupAssignmentError(Exception):
87 class RepoGroupAssignmentError(Exception):
88 pass
88 pass
89
89
90
90
91 class NonRelativePathError(Exception):
91 class NonRelativePathError(Exception):
92 pass
92 pass
93
93
94
94
95 class HTTPRequirementError(HTTPClientError):
95 class HTTPRequirementError(HTTPClientError):
96 title = explanation = 'Repository Requirement Missing'
96 title = explanation = 'Repository Requirement Missing'
97 reason = None
97 reason = None
98
98
99 def __init__(self, message, *args, **kwargs):
99 def __init__(self, message, *args, **kwargs):
100 self.title = self.explanation = message
100 self.title = self.explanation = message
101 super().__init__(*args, **kwargs)
101 super().__init__(*args, **kwargs)
102 self.args = (message, )
102 self.args = (message, )
103
103
104
104
105 class ClientNotSupportedError(HTTPRequirementError):
106 title = explanation = 'Client Not Supported'
107 reason = None
108
109
105 class HTTPLockedRC(HTTPClientError):
110 class HTTPLockedRC(HTTPClientError):
106 """
111 """
107 Special Exception For locked Repos in RhodeCode, the return code can
112 Special Exception For locked Repos in RhodeCode, the return code can
108 be overwritten by _code keyword argument passed into constructors
113 be overwritten by _code keyword argument passed into constructors
109 """
114 """
110 code = 423
115 code = 423
111 title = explanation = 'Repository Locked'
116 title = explanation = 'Repository Locked'
112 reason = None
117 reason = None
113
118
114 def __init__(self, message, *args, **kwargs):
119 def __init__(self, message, *args, **kwargs):
115 import rhodecode
120 import rhodecode
116
121
117 self.code = rhodecode.ConfigGet().get_int('lock_ret_code', missing=self.code)
122 self.code = rhodecode.ConfigGet().get_int('lock_ret_code', missing=self.code)
118
123
119 self.title = self.explanation = message
124 self.title = self.explanation = message
120 super().__init__(*args, **kwargs)
125 super().__init__(*args, **kwargs)
121 self.args = (message, )
126 self.args = (message, )
122
127
123
128
124 class HTTPBranchProtected(HTTPClientError):
129 class HTTPBranchProtected(HTTPClientError):
125 """
130 """
126 Special Exception For Indicating that branch is protected in RhodeCode, the
131 Special Exception For Indicating that branch is protected in RhodeCode, the
127 return code can be overwritten by _code keyword argument passed into constructors
132 return code can be overwritten by _code keyword argument passed into constructors
128 """
133 """
129 code = 403
134 code = 403
130 title = explanation = 'Branch Protected'
135 title = explanation = 'Branch Protected'
131 reason = None
136 reason = None
132
137
133 def __init__(self, message, *args, **kwargs):
138 def __init__(self, message, *args, **kwargs):
134 self.title = self.explanation = message
139 self.title = self.explanation = message
135 super().__init__(*args, **kwargs)
140 super().__init__(*args, **kwargs)
136 self.args = (message, )
141 self.args = (message, )
137
142
138
143
139 class IMCCommitError(Exception):
144 class IMCCommitError(Exception):
140 pass
145 pass
141
146
142
147
143 class UserCreationError(Exception):
148 class UserCreationError(Exception):
144 pass
149 pass
145
150
146
151
147 class NotAllowedToCreateUserError(Exception):
152 class NotAllowedToCreateUserError(Exception):
148 pass
153 pass
149
154
150
155
151 class DuplicateUpdateUserError(Exception):
156 class DuplicateUpdateUserError(Exception):
152 pass
157 pass
153
158
154
159
155 class RepositoryCreationError(Exception):
160 class RepositoryCreationError(Exception):
156 pass
161 pass
157
162
158
163
159 class VCSServerUnavailable(HTTPBadGateway):
164 class VCSServerUnavailable(HTTPBadGateway):
160 """ HTTP Exception class for VCS Server errors """
165 """ HTTP Exception class for VCS Server errors """
161 code = 502
166 code = 502
162 title = 'VCS Server Error'
167 title = 'VCS Server Error'
163 causes = [
168 causes = [
164 'VCS Server is not running',
169 'VCS Server is not running',
165 'Incorrect vcs.server=host:port',
170 'Incorrect vcs.server=host:port',
166 'Incorrect vcs.server.protocol',
171 'Incorrect vcs.server.protocol',
167 ]
172 ]
168
173
169 def __init__(self, message=''):
174 def __init__(self, message=''):
170 self.explanation = 'Could not connect to VCS Server'
175 self.explanation = 'Could not connect to VCS Server'
171 if message:
176 if message:
172 self.explanation += ': ' + message
177 self.explanation += ': ' + message
173 super().__init__()
178 super().__init__()
174
179
175
180
176 class ArtifactMetadataDuplicate(ValueError):
181 class ArtifactMetadataDuplicate(ValueError):
177
182
178 def __init__(self, *args, **kwargs):
183 def __init__(self, *args, **kwargs):
179 self.err_section = kwargs.pop('err_section', None)
184 self.err_section = kwargs.pop('err_section', None)
180 self.err_key = kwargs.pop('err_key', None)
185 self.err_key = kwargs.pop('err_key', None)
181 super().__init__(*args, **kwargs)
186 super().__init__(*args, **kwargs)
182
187
183
188
184 class ArtifactMetadataBadValueType(ValueError):
189 class ArtifactMetadataBadValueType(ValueError):
185 pass
190 pass
186
191
187
192
188 class CommentVersionMismatch(ValueError):
193 class CommentVersionMismatch(ValueError):
189 pass
194 pass
190
195
191
196
192 class SignatureVerificationError(ValueError):
197 class SignatureVerificationError(ValueError):
193 pass
198 pass
194
199
195
200
196 def signature_verification_error(msg):
201 def signature_verification_error(msg):
197 details = """
202 details = """
198 Encryption signature verification failed.
203 Encryption signature verification failed.
199 Please check your value of secret key, and/or encrypted value stored.
204 Please check your value of secret key, and/or encrypted value stored.
200 Secret key stored inside .ini file:
205 Secret key stored inside .ini file:
201 `rhodecode.encrypted_values.secret` or defaults to
206 `rhodecode.encrypted_values.secret` or defaults to
202 `beaker.session.secret`
207 `beaker.session.secret`
203
208
204 Probably the stored values were encrypted using a different secret then currently set in .ini file
209 Probably the stored values were encrypted using a different secret then currently set in .ini file
205 """
210 """
206
211
207 final_msg = f'{msg}\n{details}'
212 final_msg = f'{msg}\n{details}'
208 return SignatureVerificationError(final_msg)
213 return SignatureVerificationError(final_msg)
209
214
@@ -1,534 +1,548 b''
1 # Copyright (C) 2013-2023 RhodeCode GmbH
1 # Copyright (C) 2013-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19
19
20 """
20 """
21 Set of hooks run by RhodeCode Enterprise
21 Set of hooks run by RhodeCode Enterprise
22 """
22 """
23
23
24 import os
24 import os
25 import logging
25 import logging
26
26
27 import rhodecode
27 import rhodecode
28 from rhodecode import events
28 from rhodecode import events
29 from rhodecode.lib import helpers as h
29 from rhodecode.lib import helpers as h
30 from rhodecode.lib import audit_logger
30 from rhodecode.lib import audit_logger
31 from rhodecode.lib.utils2 import safe_str, user_agent_normalizer
31 from rhodecode.lib.utils2 import safe_str, user_agent_normalizer
32 from rhodecode.lib.exceptions import (
32 from rhodecode.lib.exceptions import (
33 HTTPLockedRC, HTTPBranchProtected, UserCreationError)
33 HTTPLockedRC, HTTPBranchProtected, UserCreationError, ClientNotSupportedError)
34 from rhodecode.model.db import Repository, User
34 from rhodecode.model.db import Repository, User
35 from rhodecode.lib.statsd_client import StatsdClient
35 from rhodecode.lib.statsd_client import StatsdClient
36
36
37 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
38
38
39
39
40 class HookResponse(object):
40 class HookResponse(object):
41 def __init__(self, status, output):
41 def __init__(self, status, output):
42 self.status = status
42 self.status = status
43 self.output = output
43 self.output = output
44
44
45 def __add__(self, other):
45 def __add__(self, other):
46 other_status = getattr(other, 'status', 0)
46 other_status = getattr(other, 'status', 0)
47 new_status = max(self.status, other_status)
47 new_status = max(self.status, other_status)
48 other_output = getattr(other, 'output', '')
48 other_output = getattr(other, 'output', '')
49 new_output = self.output + other_output
49 new_output = self.output + other_output
50
50
51 return HookResponse(new_status, new_output)
51 return HookResponse(new_status, new_output)
52
52
53 def __bool__(self):
53 def __bool__(self):
54 return self.status == 0
54 return self.status == 0
55
55
56 def to_json(self):
56 def to_json(self):
57 return {'status': self.status, 'output': self.output}
57 return {'status': self.status, 'output': self.output}
58
58
59
59
60 def is_shadow_repo(extras):
60 def is_shadow_repo(extras):
61 """
61 """
62 Returns ``True`` if this is an action executed against a shadow repository.
62 Returns ``True`` if this is an action executed against a shadow repository.
63 """
63 """
64 return extras['is_shadow_repo']
64 return extras['is_shadow_repo']
65
65
66
66
67 def check_vcs_client(extras):
68 """
69 Checks if vcs client is allowed (Only works in enterprise edition)
70 """
71 try:
72 from rc_ee.lib.security.utils import is_vcs_client_whitelisted
73 except ModuleNotFoundError:
74 is_vcs_client_whitelisted = lambda *x: True
75 backend = extras.get('scm')
76 if not is_vcs_client_whitelisted(extras.get('user_agent'), backend):
77 raise ClientNotSupportedError(f"Your {backend} client is forbidden")
78
67 def _get_scm_size(alias, root_path):
79 def _get_scm_size(alias, root_path):
68
80
69 if not alias.startswith('.'):
81 if not alias.startswith('.'):
70 alias += '.'
82 alias += '.'
71
83
72 size_scm, size_root = 0, 0
84 size_scm, size_root = 0, 0
73 for path, unused_dirs, files in os.walk(safe_str(root_path)):
85 for path, unused_dirs, files in os.walk(safe_str(root_path)):
74 if path.find(alias) != -1:
86 if path.find(alias) != -1:
75 for f in files:
87 for f in files:
76 try:
88 try:
77 size_scm += os.path.getsize(os.path.join(path, f))
89 size_scm += os.path.getsize(os.path.join(path, f))
78 except OSError:
90 except OSError:
79 pass
91 pass
80 else:
92 else:
81 for f in files:
93 for f in files:
82 try:
94 try:
83 size_root += os.path.getsize(os.path.join(path, f))
95 size_root += os.path.getsize(os.path.join(path, f))
84 except OSError:
96 except OSError:
85 pass
97 pass
86
98
87 size_scm_f = h.format_byte_size_binary(size_scm)
99 size_scm_f = h.format_byte_size_binary(size_scm)
88 size_root_f = h.format_byte_size_binary(size_root)
100 size_root_f = h.format_byte_size_binary(size_root)
89 size_total_f = h.format_byte_size_binary(size_root + size_scm)
101 size_total_f = h.format_byte_size_binary(size_root + size_scm)
90
102
91 return size_scm_f, size_root_f, size_total_f
103 return size_scm_f, size_root_f, size_total_f
92
104
93
105
94 # actual hooks called by Mercurial internally, and GIT by our Python Hooks
106 # actual hooks called by Mercurial internally, and GIT by our Python Hooks
95 def repo_size(extras):
107 def repo_size(extras):
96 """Present size of repository after push."""
108 """Present size of repository after push."""
97 repo = Repository.get_by_repo_name(extras.repository)
109 repo = Repository.get_by_repo_name(extras.repository)
98 vcs_part = f'.{repo.repo_type}'
110 vcs_part = f'.{repo.repo_type}'
99 size_vcs, size_root, size_total = _get_scm_size(vcs_part, repo.repo_full_path)
111 size_vcs, size_root, size_total = _get_scm_size(vcs_part, repo.repo_full_path)
100 msg = (f'RhodeCode: `{repo.repo_name}` size summary {vcs_part}:{size_vcs} repo:{size_root} total:{size_total}\n')
112 msg = (f'RhodeCode: `{repo.repo_name}` size summary {vcs_part}:{size_vcs} repo:{size_root} total:{size_total}\n')
101 return HookResponse(0, msg)
113 return HookResponse(0, msg)
102
114
103
115
104 def pre_push(extras):
116 def pre_push(extras):
105 """
117 """
106 Hook executed before pushing code.
118 Hook executed before pushing code.
107
119
108 It bans pushing when the repository is locked.
120 It bans pushing when the repository is locked.
109 """
121 """
110
122
123 check_vcs_client(extras)
111 user = User.get_by_username(extras.username)
124 user = User.get_by_username(extras.username)
112 output = ''
125 output = ''
113 if extras.locked_by[0] and user.user_id != int(extras.locked_by[0]):
126 if extras.locked_by[0] and user.user_id != int(extras.locked_by[0]):
114 locked_by = User.get(extras.locked_by[0]).username
127 locked_by = User.get(extras.locked_by[0]).username
115 reason = extras.locked_by[2]
128 reason = extras.locked_by[2]
116 # this exception is interpreted in git/hg middlewares and based
129 # this exception is interpreted in git/hg middlewares and based
117 # on that proper return code is server to client
130 # on that proper return code is server to client
118 _http_ret = HTTPLockedRC(
131 _http_ret = HTTPLockedRC(
119 _locked_by_explanation(extras.repository, locked_by, reason))
132 _locked_by_explanation(extras.repository, locked_by, reason))
120 if str(_http_ret.code).startswith('2'):
133 if str(_http_ret.code).startswith('2'):
121 # 2xx Codes don't raise exceptions
134 # 2xx Codes don't raise exceptions
122 output = _http_ret.title
135 output = _http_ret.title
123 else:
136 else:
124 raise _http_ret
137 raise _http_ret
125
138
126 hook_response = ''
139 hook_response = ''
127 if not is_shadow_repo(extras):
140 if not is_shadow_repo(extras):
128
141
129 if extras.commit_ids and extras.check_branch_perms:
142 if extras.commit_ids and extras.check_branch_perms:
130 auth_user = user.AuthUser()
143 auth_user = user.AuthUser()
131 repo = Repository.get_by_repo_name(extras.repository)
144 repo = Repository.get_by_repo_name(extras.repository)
132 affected_branches = []
145 affected_branches = []
133 if repo.repo_type == 'hg':
146 if repo.repo_type == 'hg':
134 for entry in extras.commit_ids:
147 for entry in extras.commit_ids:
135 if entry['type'] == 'branch':
148 if entry['type'] == 'branch':
136 is_forced = bool(entry['multiple_heads'])
149 is_forced = bool(entry['multiple_heads'])
137 affected_branches.append([entry['name'], is_forced])
150 affected_branches.append([entry['name'], is_forced])
138 elif repo.repo_type == 'git':
151 elif repo.repo_type == 'git':
139 for entry in extras.commit_ids:
152 for entry in extras.commit_ids:
140 if entry['type'] == 'heads':
153 if entry['type'] == 'heads':
141 is_forced = bool(entry['pruned_sha'])
154 is_forced = bool(entry['pruned_sha'])
142 affected_branches.append([entry['name'], is_forced])
155 affected_branches.append([entry['name'], is_forced])
143
156
144 for branch_name, is_forced in affected_branches:
157 for branch_name, is_forced in affected_branches:
145
158
146 rule, branch_perm = auth_user.get_rule_and_branch_permission(
159 rule, branch_perm = auth_user.get_rule_and_branch_permission(
147 extras.repository, branch_name)
160 extras.repository, branch_name)
148 if not branch_perm:
161 if not branch_perm:
149 # no branch permission found for this branch, just keep checking
162 # no branch permission found for this branch, just keep checking
150 continue
163 continue
151
164
152 if branch_perm == 'branch.push_force':
165 if branch_perm == 'branch.push_force':
153 continue
166 continue
154 elif branch_perm == 'branch.push' and is_forced is False:
167 elif branch_perm == 'branch.push' and is_forced is False:
155 continue
168 continue
156 elif branch_perm == 'branch.push' and is_forced is True:
169 elif branch_perm == 'branch.push' and is_forced is True:
157 halt_message = f'Branch `{branch_name}` changes rejected by rule {rule}. ' \
170 halt_message = f'Branch `{branch_name}` changes rejected by rule {rule}. ' \
158 f'FORCE PUSH FORBIDDEN.'
171 f'FORCE PUSH FORBIDDEN.'
159 else:
172 else:
160 halt_message = f'Branch `{branch_name}` changes rejected by rule {rule}.'
173 halt_message = f'Branch `{branch_name}` changes rejected by rule {rule}.'
161
174
162 if halt_message:
175 if halt_message:
163 _http_ret = HTTPBranchProtected(halt_message)
176 _http_ret = HTTPBranchProtected(halt_message)
164 raise _http_ret
177 raise _http_ret
165
178
166 # Propagate to external components. This is done after checking the
179 # Propagate to external components. This is done after checking the
167 # lock, for consistent behavior.
180 # lock, for consistent behavior.
168 hook_response = pre_push_extension(
181 hook_response = pre_push_extension(
169 repo_store_path=Repository.base_path(), **extras)
182 repo_store_path=Repository.base_path(), **extras)
170 events.trigger(events.RepoPrePushEvent(
183 events.trigger(events.RepoPrePushEvent(
171 repo_name=extras.repository, extras=extras))
184 repo_name=extras.repository, extras=extras))
172
185
173 return HookResponse(0, output) + hook_response
186 return HookResponse(0, output) + hook_response
174
187
175
188
176 def pre_pull(extras):
189 def pre_pull(extras):
177 """
190 """
178 Hook executed before pulling the code.
191 Hook executed before pulling the code.
179
192
180 It bans pulling when the repository is locked.
193 It bans pulling when the repository is locked.
181 """
194 """
182
195
196 check_vcs_client(extras)
183 output = ''
197 output = ''
184 if extras.locked_by[0]:
198 if extras.locked_by[0]:
185 locked_by = User.get(extras.locked_by[0]).username
199 locked_by = User.get(extras.locked_by[0]).username
186 reason = extras.locked_by[2]
200 reason = extras.locked_by[2]
187 # this exception is interpreted in git/hg middlewares and based
201 # this exception is interpreted in git/hg middlewares and based
188 # on that proper return code is server to client
202 # on that proper return code is server to client
189 _http_ret = HTTPLockedRC(
203 _http_ret = HTTPLockedRC(
190 _locked_by_explanation(extras.repository, locked_by, reason))
204 _locked_by_explanation(extras.repository, locked_by, reason))
191 if str(_http_ret.code).startswith('2'):
205 if str(_http_ret.code).startswith('2'):
192 # 2xx Codes don't raise exceptions
206 # 2xx Codes don't raise exceptions
193 output = _http_ret.title
207 output = _http_ret.title
194 else:
208 else:
195 raise _http_ret
209 raise _http_ret
196
210
197 # Propagate to external components. This is done after checking the
211 # Propagate to external components. This is done after checking the
198 # lock, for consistent behavior.
212 # lock, for consistent behavior.
199 hook_response = ''
213 hook_response = ''
200 if not is_shadow_repo(extras):
214 if not is_shadow_repo(extras):
201 extras.hook_type = extras.hook_type or 'pre_pull'
215 extras.hook_type = extras.hook_type or 'pre_pull'
202 hook_response = pre_pull_extension(
216 hook_response = pre_pull_extension(
203 repo_store_path=Repository.base_path(), **extras)
217 repo_store_path=Repository.base_path(), **extras)
204 events.trigger(events.RepoPrePullEvent(
218 events.trigger(events.RepoPrePullEvent(
205 repo_name=extras.repository, extras=extras))
219 repo_name=extras.repository, extras=extras))
206
220
207 return HookResponse(0, output) + hook_response
221 return HookResponse(0, output) + hook_response
208
222
209
223
210 def post_pull(extras):
224 def post_pull(extras):
211 """Hook executed after client pulls the code."""
225 """Hook executed after client pulls the code."""
212
226
213 audit_user = audit_logger.UserWrap(
227 audit_user = audit_logger.UserWrap(
214 username=extras.username,
228 username=extras.username,
215 ip_addr=extras.ip)
229 ip_addr=extras.ip)
216 repo = audit_logger.RepoWrap(repo_name=extras.repository)
230 repo = audit_logger.RepoWrap(repo_name=extras.repository)
217 audit_logger.store(
231 audit_logger.store(
218 'user.pull', action_data={'user_agent': extras.user_agent},
232 'user.pull', action_data={'user_agent': extras.user_agent},
219 user=audit_user, repo=repo, commit=True)
233 user=audit_user, repo=repo, commit=True)
220
234
221 statsd = StatsdClient.statsd
235 statsd = StatsdClient.statsd
222 if statsd:
236 if statsd:
223 statsd.incr('rhodecode_pull_total', tags=[
237 statsd.incr('rhodecode_pull_total', tags=[
224 f'user-agent:{user_agent_normalizer(extras.user_agent)}',
238 f'user-agent:{user_agent_normalizer(extras.user_agent)}',
225 ])
239 ])
226 output = ''
240 output = ''
227 # make lock is a tri state False, True, None. We only make lock on True
241 # make lock is a tri state False, True, None. We only make lock on True
228 if extras.make_lock is True and not is_shadow_repo(extras):
242 if extras.make_lock is True and not is_shadow_repo(extras):
229 user = User.get_by_username(extras.username)
243 user = User.get_by_username(extras.username)
230 Repository.lock(Repository.get_by_repo_name(extras.repository),
244 Repository.lock(Repository.get_by_repo_name(extras.repository),
231 user.user_id,
245 user.user_id,
232 lock_reason=Repository.LOCK_PULL)
246 lock_reason=Repository.LOCK_PULL)
233 msg = 'Made lock on repo `{}`'.format(extras.repository)
247 msg = 'Made lock on repo `{}`'.format(extras.repository)
234 output += msg
248 output += msg
235
249
236 if extras.locked_by[0]:
250 if extras.locked_by[0]:
237 locked_by = User.get(extras.locked_by[0]).username
251 locked_by = User.get(extras.locked_by[0]).username
238 reason = extras.locked_by[2]
252 reason = extras.locked_by[2]
239 _http_ret = HTTPLockedRC(
253 _http_ret = HTTPLockedRC(
240 _locked_by_explanation(extras.repository, locked_by, reason))
254 _locked_by_explanation(extras.repository, locked_by, reason))
241 if str(_http_ret.code).startswith('2'):
255 if str(_http_ret.code).startswith('2'):
242 # 2xx Codes don't raise exceptions
256 # 2xx Codes don't raise exceptions
243 output += _http_ret.title
257 output += _http_ret.title
244
258
245 # Propagate to external components.
259 # Propagate to external components.
246 hook_response = ''
260 hook_response = ''
247 if not is_shadow_repo(extras):
261 if not is_shadow_repo(extras):
248 extras.hook_type = extras.hook_type or 'post_pull'
262 extras.hook_type = extras.hook_type or 'post_pull'
249 hook_response = post_pull_extension(
263 hook_response = post_pull_extension(
250 repo_store_path=Repository.base_path(), **extras)
264 repo_store_path=Repository.base_path(), **extras)
251 events.trigger(events.RepoPullEvent(
265 events.trigger(events.RepoPullEvent(
252 repo_name=extras.repository, extras=extras))
266 repo_name=extras.repository, extras=extras))
253
267
254 return HookResponse(0, output) + hook_response
268 return HookResponse(0, output) + hook_response
255
269
256
270
257 def post_push(extras):
271 def post_push(extras):
258 """Hook executed after user pushes to the repository."""
272 """Hook executed after user pushes to the repository."""
259 commit_ids = extras.commit_ids
273 commit_ids = extras.commit_ids
260
274
261 # log the push call
275 # log the push call
262 audit_user = audit_logger.UserWrap(
276 audit_user = audit_logger.UserWrap(
263 username=extras.username, ip_addr=extras.ip)
277 username=extras.username, ip_addr=extras.ip)
264 repo = audit_logger.RepoWrap(repo_name=extras.repository)
278 repo = audit_logger.RepoWrap(repo_name=extras.repository)
265 audit_logger.store(
279 audit_logger.store(
266 'user.push', action_data={
280 'user.push', action_data={
267 'user_agent': extras.user_agent,
281 'user_agent': extras.user_agent,
268 'commit_ids': commit_ids[:400]},
282 'commit_ids': commit_ids[:400]},
269 user=audit_user, repo=repo, commit=True)
283 user=audit_user, repo=repo, commit=True)
270
284
271 statsd = StatsdClient.statsd
285 statsd = StatsdClient.statsd
272 if statsd:
286 if statsd:
273 statsd.incr('rhodecode_push_total', tags=[
287 statsd.incr('rhodecode_push_total', tags=[
274 f'user-agent:{user_agent_normalizer(extras.user_agent)}',
288 f'user-agent:{user_agent_normalizer(extras.user_agent)}',
275 ])
289 ])
276
290
277 # Propagate to external components.
291 # Propagate to external components.
278 output = ''
292 output = ''
279 # make lock is a tri state False, True, None. We only release lock on False
293 # make lock is a tri state False, True, None. We only release lock on False
280 if extras.make_lock is False and not is_shadow_repo(extras):
294 if extras.make_lock is False and not is_shadow_repo(extras):
281 Repository.unlock(Repository.get_by_repo_name(extras.repository))
295 Repository.unlock(Repository.get_by_repo_name(extras.repository))
282 msg = f'Released lock on repo `{extras.repository}`\n'
296 msg = f'Released lock on repo `{extras.repository}`\n'
283 output += msg
297 output += msg
284
298
285 if extras.locked_by[0]:
299 if extras.locked_by[0]:
286 locked_by = User.get(extras.locked_by[0]).username
300 locked_by = User.get(extras.locked_by[0]).username
287 reason = extras.locked_by[2]
301 reason = extras.locked_by[2]
288 _http_ret = HTTPLockedRC(
302 _http_ret = HTTPLockedRC(
289 _locked_by_explanation(extras.repository, locked_by, reason))
303 _locked_by_explanation(extras.repository, locked_by, reason))
290 # TODO: johbo: if not?
304 # TODO: johbo: if not?
291 if str(_http_ret.code).startswith('2'):
305 if str(_http_ret.code).startswith('2'):
292 # 2xx Codes don't raise exceptions
306 # 2xx Codes don't raise exceptions
293 output += _http_ret.title
307 output += _http_ret.title
294
308
295 if extras.new_refs:
309 if extras.new_refs:
296 tmpl = '{}/{}/pull-request/new?{{ref_type}}={{ref_name}}'.format(
310 tmpl = '{}/{}/pull-request/new?{{ref_type}}={{ref_name}}'.format(
297 safe_str(extras.server_url), safe_str(extras.repository))
311 safe_str(extras.server_url), safe_str(extras.repository))
298
312
299 for branch_name in extras.new_refs['branches']:
313 for branch_name in extras.new_refs['branches']:
300 pr_link = tmpl.format(ref_type='branch', ref_name=safe_str(branch_name))
314 pr_link = tmpl.format(ref_type='branch', ref_name=safe_str(branch_name))
301 output += f'RhodeCode: open pull request link: {pr_link}\n'
315 output += f'RhodeCode: open pull request link: {pr_link}\n'
302
316
303 for book_name in extras.new_refs['bookmarks']:
317 for book_name in extras.new_refs['bookmarks']:
304 pr_link = tmpl.format(ref_type='bookmark', ref_name=safe_str(book_name))
318 pr_link = tmpl.format(ref_type='bookmark', ref_name=safe_str(book_name))
305 output += f'RhodeCode: open pull request link: {pr_link}\n'
319 output += f'RhodeCode: open pull request link: {pr_link}\n'
306
320
307 hook_response = ''
321 hook_response = ''
308 if not is_shadow_repo(extras):
322 if not is_shadow_repo(extras):
309 hook_response = post_push_extension(
323 hook_response = post_push_extension(
310 repo_store_path=Repository.base_path(),
324 repo_store_path=Repository.base_path(),
311 **extras)
325 **extras)
312 events.trigger(events.RepoPushEvent(
326 events.trigger(events.RepoPushEvent(
313 repo_name=extras.repository, pushed_commit_ids=commit_ids, extras=extras))
327 repo_name=extras.repository, pushed_commit_ids=commit_ids, extras=extras))
314
328
315 output += 'RhodeCode: push completed\n'
329 output += 'RhodeCode: push completed\n'
316 return HookResponse(0, output) + hook_response
330 return HookResponse(0, output) + hook_response
317
331
318
332
319 def _locked_by_explanation(repo_name, user_name, reason):
333 def _locked_by_explanation(repo_name, user_name, reason):
320 message = f'Repository `{repo_name}` locked by user `{user_name}`. Reason:`{reason}`'
334 message = f'Repository `{repo_name}` locked by user `{user_name}`. Reason:`{reason}`'
321 return message
335 return message
322
336
323
337
324 def check_allowed_create_user(user_dict, created_by, **kwargs):
338 def check_allowed_create_user(user_dict, created_by, **kwargs):
325 # pre create hooks
339 # pre create hooks
326 if pre_create_user.is_active():
340 if pre_create_user.is_active():
327 hook_result = pre_create_user(created_by=created_by, **user_dict)
341 hook_result = pre_create_user(created_by=created_by, **user_dict)
328 allowed = hook_result.status == 0
342 allowed = hook_result.status == 0
329 if not allowed:
343 if not allowed:
330 reason = hook_result.output
344 reason = hook_result.output
331 raise UserCreationError(reason)
345 raise UserCreationError(reason)
332
346
333
347
334 class ExtensionCallback(object):
348 class ExtensionCallback(object):
335 """
349 """
336 Forwards a given call to rcextensions, sanitizes keyword arguments.
350 Forwards a given call to rcextensions, sanitizes keyword arguments.
337
351
338 Does check if there is an extension active for that hook. If it is
352 Does check if there is an extension active for that hook. If it is
339 there, it will forward all `kwargs_keys` keyword arguments to the
353 there, it will forward all `kwargs_keys` keyword arguments to the
340 extension callback.
354 extension callback.
341 """
355 """
342
356
343 def __init__(self, hook_name, kwargs_keys):
357 def __init__(self, hook_name, kwargs_keys):
344 self._hook_name = hook_name
358 self._hook_name = hook_name
345 self._kwargs_keys = set(kwargs_keys)
359 self._kwargs_keys = set(kwargs_keys)
346
360
347 def __call__(self, *args, **kwargs):
361 def __call__(self, *args, **kwargs):
348 log.debug('Calling extension callback for `%s`', self._hook_name)
362 log.debug('Calling extension callback for `%s`', self._hook_name)
349 callback = self._get_callback()
363 callback = self._get_callback()
350 if not callback:
364 if not callback:
351 log.debug('extension callback `%s` not found, skipping...', self._hook_name)
365 log.debug('extension callback `%s` not found, skipping...', self._hook_name)
352 return
366 return
353
367
354 kwargs_to_pass = {}
368 kwargs_to_pass = {}
355 for key in self._kwargs_keys:
369 for key in self._kwargs_keys:
356 try:
370 try:
357 kwargs_to_pass[key] = kwargs[key]
371 kwargs_to_pass[key] = kwargs[key]
358 except KeyError:
372 except KeyError:
359 log.error('Failed to fetch %s key from given kwargs. '
373 log.error('Failed to fetch %s key from given kwargs. '
360 'Expected keys: %s', key, self._kwargs_keys)
374 'Expected keys: %s', key, self._kwargs_keys)
361 raise
375 raise
362
376
363 # backward compat for removed api_key for old hooks. This was it works
377 # backward compat for removed api_key for old hooks. This was it works
364 # with older rcextensions that require api_key present
378 # with older rcextensions that require api_key present
365 if self._hook_name in ['CREATE_USER_HOOK', 'DELETE_USER_HOOK']:
379 if self._hook_name in ['CREATE_USER_HOOK', 'DELETE_USER_HOOK']:
366 kwargs_to_pass['api_key'] = '_DEPRECATED_'
380 kwargs_to_pass['api_key'] = '_DEPRECATED_'
367 return callback(**kwargs_to_pass)
381 return callback(**kwargs_to_pass)
368
382
369 def is_active(self):
383 def is_active(self):
370 return hasattr(rhodecode.EXTENSIONS, self._hook_name)
384 return hasattr(rhodecode.EXTENSIONS, self._hook_name)
371
385
372 def _get_callback(self):
386 def _get_callback(self):
373 return getattr(rhodecode.EXTENSIONS, self._hook_name, None)
387 return getattr(rhodecode.EXTENSIONS, self._hook_name, None)
374
388
375
389
376 pre_pull_extension = ExtensionCallback(
390 pre_pull_extension = ExtensionCallback(
377 hook_name='PRE_PULL_HOOK',
391 hook_name='PRE_PULL_HOOK',
378 kwargs_keys=(
392 kwargs_keys=(
379 'server_url', 'config', 'scm', 'username', 'ip', 'action',
393 'server_url', 'config', 'scm', 'username', 'ip', 'action',
380 'repository', 'hook_type', 'user_agent', 'repo_store_path',))
394 'repository', 'hook_type', 'user_agent', 'repo_store_path',))
381
395
382
396
383 post_pull_extension = ExtensionCallback(
397 post_pull_extension = ExtensionCallback(
384 hook_name='PULL_HOOK',
398 hook_name='PULL_HOOK',
385 kwargs_keys=(
399 kwargs_keys=(
386 'server_url', 'config', 'scm', 'username', 'ip', 'action',
400 'server_url', 'config', 'scm', 'username', 'ip', 'action',
387 'repository', 'hook_type', 'user_agent', 'repo_store_path',))
401 'repository', 'hook_type', 'user_agent', 'repo_store_path',))
388
402
389
403
390 pre_push_extension = ExtensionCallback(
404 pre_push_extension = ExtensionCallback(
391 hook_name='PRE_PUSH_HOOK',
405 hook_name='PRE_PUSH_HOOK',
392 kwargs_keys=(
406 kwargs_keys=(
393 'server_url', 'config', 'scm', 'username', 'ip', 'action',
407 'server_url', 'config', 'scm', 'username', 'ip', 'action',
394 'repository', 'repo_store_path', 'commit_ids', 'hook_type', 'user_agent',))
408 'repository', 'repo_store_path', 'commit_ids', 'hook_type', 'user_agent',))
395
409
396
410
397 post_push_extension = ExtensionCallback(
411 post_push_extension = ExtensionCallback(
398 hook_name='PUSH_HOOK',
412 hook_name='PUSH_HOOK',
399 kwargs_keys=(
413 kwargs_keys=(
400 'server_url', 'config', 'scm', 'username', 'ip', 'action',
414 'server_url', 'config', 'scm', 'username', 'ip', 'action',
401 'repository', 'repo_store_path', 'commit_ids', 'hook_type', 'user_agent',))
415 'repository', 'repo_store_path', 'commit_ids', 'hook_type', 'user_agent',))
402
416
403
417
404 pre_create_user = ExtensionCallback(
418 pre_create_user = ExtensionCallback(
405 hook_name='PRE_CREATE_USER_HOOK',
419 hook_name='PRE_CREATE_USER_HOOK',
406 kwargs_keys=(
420 kwargs_keys=(
407 'username', 'password', 'email', 'firstname', 'lastname', 'active',
421 'username', 'password', 'email', 'firstname', 'lastname', 'active',
408 'admin', 'created_by'))
422 'admin', 'created_by'))
409
423
410
424
411 create_pull_request = ExtensionCallback(
425 create_pull_request = ExtensionCallback(
412 hook_name='CREATE_PULL_REQUEST',
426 hook_name='CREATE_PULL_REQUEST',
413 kwargs_keys=(
427 kwargs_keys=(
414 'server_url', 'config', 'scm', 'username', 'ip', 'action',
428 'server_url', 'config', 'scm', 'username', 'ip', 'action',
415 'repository', 'pull_request_id', 'url', 'title', 'description',
429 'repository', 'pull_request_id', 'url', 'title', 'description',
416 'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
430 'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
417 'mergeable', 'source', 'target', 'author', 'reviewers'))
431 'mergeable', 'source', 'target', 'author', 'reviewers'))
418
432
419
433
420 merge_pull_request = ExtensionCallback(
434 merge_pull_request = ExtensionCallback(
421 hook_name='MERGE_PULL_REQUEST',
435 hook_name='MERGE_PULL_REQUEST',
422 kwargs_keys=(
436 kwargs_keys=(
423 'server_url', 'config', 'scm', 'username', 'ip', 'action',
437 'server_url', 'config', 'scm', 'username', 'ip', 'action',
424 'repository', 'pull_request_id', 'url', 'title', 'description',
438 'repository', 'pull_request_id', 'url', 'title', 'description',
425 'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
439 'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
426 'mergeable', 'source', 'target', 'author', 'reviewers'))
440 'mergeable', 'source', 'target', 'author', 'reviewers'))
427
441
428
442
429 close_pull_request = ExtensionCallback(
443 close_pull_request = ExtensionCallback(
430 hook_name='CLOSE_PULL_REQUEST',
444 hook_name='CLOSE_PULL_REQUEST',
431 kwargs_keys=(
445 kwargs_keys=(
432 'server_url', 'config', 'scm', 'username', 'ip', 'action',
446 'server_url', 'config', 'scm', 'username', 'ip', 'action',
433 'repository', 'pull_request_id', 'url', 'title', 'description',
447 'repository', 'pull_request_id', 'url', 'title', 'description',
434 'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
448 'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
435 'mergeable', 'source', 'target', 'author', 'reviewers'))
449 'mergeable', 'source', 'target', 'author', 'reviewers'))
436
450
437
451
438 review_pull_request = ExtensionCallback(
452 review_pull_request = ExtensionCallback(
439 hook_name='REVIEW_PULL_REQUEST',
453 hook_name='REVIEW_PULL_REQUEST',
440 kwargs_keys=(
454 kwargs_keys=(
441 'server_url', 'config', 'scm', 'username', 'ip', 'action',
455 'server_url', 'config', 'scm', 'username', 'ip', 'action',
442 'repository', 'pull_request_id', 'url', 'title', 'description',
456 'repository', 'pull_request_id', 'url', 'title', 'description',
443 'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
457 'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
444 'mergeable', 'source', 'target', 'author', 'reviewers'))
458 'mergeable', 'source', 'target', 'author', 'reviewers'))
445
459
446
460
447 comment_pull_request = ExtensionCallback(
461 comment_pull_request = ExtensionCallback(
448 hook_name='COMMENT_PULL_REQUEST',
462 hook_name='COMMENT_PULL_REQUEST',
449 kwargs_keys=(
463 kwargs_keys=(
450 'server_url', 'config', 'scm', 'username', 'ip', 'action',
464 'server_url', 'config', 'scm', 'username', 'ip', 'action',
451 'repository', 'pull_request_id', 'url', 'title', 'description',
465 'repository', 'pull_request_id', 'url', 'title', 'description',
452 'status', 'comment', 'created_on', 'updated_on', 'commit_ids', 'review_status',
466 'status', 'comment', 'created_on', 'updated_on', 'commit_ids', 'review_status',
453 'mergeable', 'source', 'target', 'author', 'reviewers'))
467 'mergeable', 'source', 'target', 'author', 'reviewers'))
454
468
455
469
456 comment_edit_pull_request = ExtensionCallback(
470 comment_edit_pull_request = ExtensionCallback(
457 hook_name='COMMENT_EDIT_PULL_REQUEST',
471 hook_name='COMMENT_EDIT_PULL_REQUEST',
458 kwargs_keys=(
472 kwargs_keys=(
459 'server_url', 'config', 'scm', 'username', 'ip', 'action',
473 'server_url', 'config', 'scm', 'username', 'ip', 'action',
460 'repository', 'pull_request_id', 'url', 'title', 'description',
474 'repository', 'pull_request_id', 'url', 'title', 'description',
461 'status', 'comment', 'created_on', 'updated_on', 'commit_ids', 'review_status',
475 'status', 'comment', 'created_on', 'updated_on', 'commit_ids', 'review_status',
462 'mergeable', 'source', 'target', 'author', 'reviewers'))
476 'mergeable', 'source', 'target', 'author', 'reviewers'))
463
477
464
478
465 update_pull_request = ExtensionCallback(
479 update_pull_request = ExtensionCallback(
466 hook_name='UPDATE_PULL_REQUEST',
480 hook_name='UPDATE_PULL_REQUEST',
467 kwargs_keys=(
481 kwargs_keys=(
468 'server_url', 'config', 'scm', 'username', 'ip', 'action',
482 'server_url', 'config', 'scm', 'username', 'ip', 'action',
469 'repository', 'pull_request_id', 'url', 'title', 'description',
483 'repository', 'pull_request_id', 'url', 'title', 'description',
470 'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
484 'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
471 'mergeable', 'source', 'target', 'author', 'reviewers'))
485 'mergeable', 'source', 'target', 'author', 'reviewers'))
472
486
473
487
474 create_user = ExtensionCallback(
488 create_user = ExtensionCallback(
475 hook_name='CREATE_USER_HOOK',
489 hook_name='CREATE_USER_HOOK',
476 kwargs_keys=(
490 kwargs_keys=(
477 'username', 'full_name_or_username', 'full_contact', 'user_id',
491 'username', 'full_name_or_username', 'full_contact', 'user_id',
478 'name', 'firstname', 'short_contact', 'admin', 'lastname',
492 'name', 'firstname', 'short_contact', 'admin', 'lastname',
479 'ip_addresses', 'extern_type', 'extern_name',
493 'ip_addresses', 'extern_type', 'extern_name',
480 'email', 'api_keys', 'last_login',
494 'email', 'api_keys', 'last_login',
481 'full_name', 'active', 'password', 'emails',
495 'full_name', 'active', 'password', 'emails',
482 'inherit_default_permissions', 'created_by', 'created_on'))
496 'inherit_default_permissions', 'created_by', 'created_on'))
483
497
484
498
485 delete_user = ExtensionCallback(
499 delete_user = ExtensionCallback(
486 hook_name='DELETE_USER_HOOK',
500 hook_name='DELETE_USER_HOOK',
487 kwargs_keys=(
501 kwargs_keys=(
488 'username', 'full_name_or_username', 'full_contact', 'user_id',
502 'username', 'full_name_or_username', 'full_contact', 'user_id',
489 'name', 'firstname', 'short_contact', 'admin', 'lastname',
503 'name', 'firstname', 'short_contact', 'admin', 'lastname',
490 'ip_addresses',
504 'ip_addresses',
491 'email', 'last_login',
505 'email', 'last_login',
492 'full_name', 'active', 'password', 'emails',
506 'full_name', 'active', 'password', 'emails',
493 'inherit_default_permissions', 'deleted_by'))
507 'inherit_default_permissions', 'deleted_by'))
494
508
495
509
496 create_repository = ExtensionCallback(
510 create_repository = ExtensionCallback(
497 hook_name='CREATE_REPO_HOOK',
511 hook_name='CREATE_REPO_HOOK',
498 kwargs_keys=(
512 kwargs_keys=(
499 'repo_name', 'repo_type', 'description', 'private', 'created_on',
513 'repo_name', 'repo_type', 'description', 'private', 'created_on',
500 'enable_downloads', 'repo_id', 'user_id', 'enable_statistics',
514 'enable_downloads', 'repo_id', 'user_id', 'enable_statistics',
501 'clone_uri', 'fork_id', 'group_id', 'created_by'))
515 'clone_uri', 'fork_id', 'group_id', 'created_by'))
502
516
503
517
504 delete_repository = ExtensionCallback(
518 delete_repository = ExtensionCallback(
505 hook_name='DELETE_REPO_HOOK',
519 hook_name='DELETE_REPO_HOOK',
506 kwargs_keys=(
520 kwargs_keys=(
507 'repo_name', 'repo_type', 'description', 'private', 'created_on',
521 'repo_name', 'repo_type', 'description', 'private', 'created_on',
508 'enable_downloads', 'repo_id', 'user_id', 'enable_statistics',
522 'enable_downloads', 'repo_id', 'user_id', 'enable_statistics',
509 'clone_uri', 'fork_id', 'group_id', 'deleted_by', 'deleted_on'))
523 'clone_uri', 'fork_id', 'group_id', 'deleted_by', 'deleted_on'))
510
524
511
525
512 comment_commit_repository = ExtensionCallback(
526 comment_commit_repository = ExtensionCallback(
513 hook_name='COMMENT_COMMIT_REPO_HOOK',
527 hook_name='COMMENT_COMMIT_REPO_HOOK',
514 kwargs_keys=(
528 kwargs_keys=(
515 'repo_name', 'repo_type', 'description', 'private', 'created_on',
529 'repo_name', 'repo_type', 'description', 'private', 'created_on',
516 'enable_downloads', 'repo_id', 'user_id', 'enable_statistics',
530 'enable_downloads', 'repo_id', 'user_id', 'enable_statistics',
517 'clone_uri', 'fork_id', 'group_id',
531 'clone_uri', 'fork_id', 'group_id',
518 'repository', 'created_by', 'comment', 'commit'))
532 'repository', 'created_by', 'comment', 'commit'))
519
533
520 comment_edit_commit_repository = ExtensionCallback(
534 comment_edit_commit_repository = ExtensionCallback(
521 hook_name='COMMENT_EDIT_COMMIT_REPO_HOOK',
535 hook_name='COMMENT_EDIT_COMMIT_REPO_HOOK',
522 kwargs_keys=(
536 kwargs_keys=(
523 'repo_name', 'repo_type', 'description', 'private', 'created_on',
537 'repo_name', 'repo_type', 'description', 'private', 'created_on',
524 'enable_downloads', 'repo_id', 'user_id', 'enable_statistics',
538 'enable_downloads', 'repo_id', 'user_id', 'enable_statistics',
525 'clone_uri', 'fork_id', 'group_id',
539 'clone_uri', 'fork_id', 'group_id',
526 'repository', 'created_by', 'comment', 'commit'))
540 'repository', 'created_by', 'comment', 'commit'))
527
541
528
542
529 create_repository_group = ExtensionCallback(
543 create_repository_group = ExtensionCallback(
530 hook_name='CREATE_REPO_GROUP_HOOK',
544 hook_name='CREATE_REPO_GROUP_HOOK',
531 kwargs_keys=(
545 kwargs_keys=(
532 'group_name', 'group_parent_id', 'group_description',
546 'group_name', 'group_parent_id', 'group_description',
533 'group_id', 'user_id', 'created_by', 'created_on',
547 'group_id', 'user_id', 'created_by', 'created_on',
534 'enable_locking'))
548 'enable_locking'))
@@ -1,824 +1,827 b''
1 # Copyright (C) 2010-2023 RhodeCode GmbH
1 # Copyright (C) 2010-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 """
19 """
20 Utilities library for RhodeCode
20 Utilities library for RhodeCode
21 """
21 """
22
22
23 import datetime
23 import datetime
24
24
25 import decorator
25 import decorator
26 import logging
26 import logging
27 import os
27 import os
28 import re
28 import re
29 import sys
29 import sys
30 import shutil
30 import shutil
31 import socket
31 import socket
32 import tempfile
32 import tempfile
33 import traceback
33 import traceback
34 import tarfile
34 import tarfile
35
35
36 from functools import wraps
36 from functools import wraps
37 from os.path import join as jn
37 from os.path import join as jn
38
38
39 import paste
39 import paste
40 import pkg_resources
40 import pkg_resources
41 from webhelpers2.text import collapse, strip_tags, convert_accented_entities, convert_misc_entities
41 from webhelpers2.text import collapse, strip_tags, convert_accented_entities, convert_misc_entities
42
42
43 from mako import exceptions
43 from mako import exceptions
44
44
45 from rhodecode.lib.hash_utils import sha256_safe, md5, sha1
45 from rhodecode.lib.hash_utils import sha256_safe, md5, sha1
46 from rhodecode.lib.type_utils import AttributeDict
46 from rhodecode.lib.type_utils import AttributeDict
47 from rhodecode.lib.str_utils import safe_bytes, safe_str
47 from rhodecode.lib.str_utils import safe_bytes, safe_str
48 from rhodecode.lib.vcs.backends.base import Config
48 from rhodecode.lib.vcs.backends.base import Config
49 from rhodecode.lib.vcs.exceptions import VCSError
49 from rhodecode.lib.vcs.exceptions import VCSError
50 from rhodecode.lib.vcs.utils.helpers import get_scm, get_scm_backend
50 from rhodecode.lib.vcs.utils.helpers import get_scm, get_scm_backend
51 from rhodecode.lib.ext_json import sjson as json
51 from rhodecode.lib.ext_json import sjson as json
52 from rhodecode.model import meta
52 from rhodecode.model import meta
53 from rhodecode.model.db import (
53 from rhodecode.model.db import (
54 Repository, User, RhodeCodeUi, UserLog, RepoGroup, UserGroup)
54 Repository, User, RhodeCodeUi, UserLog, RepoGroup, UserGroup)
55 from rhodecode.model.meta import Session
55 from rhodecode.model.meta import Session
56
56
57
57
58 log = logging.getLogger(__name__)
58 log = logging.getLogger(__name__)
59
59
60 REMOVED_REPO_PAT = re.compile(r'rm__\d{8}_\d{6}_\d{6}__.*')
60 REMOVED_REPO_PAT = re.compile(r'rm__\d{8}_\d{6}_\d{6}__.*')
61
61
62 # String which contains characters that are not allowed in slug names for
62 # String which contains characters that are not allowed in slug names for
63 # repositories or repository groups. It is properly escaped to use it in
63 # repositories or repository groups. It is properly escaped to use it in
64 # regular expressions.
64 # regular expressions.
65 SLUG_BAD_CHARS = re.escape(r'`?=[]\;\'"<>,/~!@#$%^&*()+{}|:')
65 SLUG_BAD_CHARS = re.escape(r'`?=[]\;\'"<>,/~!@#$%^&*()+{}|:')
66
66
67 # Regex that matches forbidden characters in repo/group slugs.
67 # Regex that matches forbidden characters in repo/group slugs.
68 SLUG_BAD_CHAR_RE = re.compile(r'[{}\x00-\x08\x0b-\x0c\x0e-\x1f]'.format(SLUG_BAD_CHARS))
68 SLUG_BAD_CHAR_RE = re.compile(r'[{}\x00-\x08\x0b-\x0c\x0e-\x1f]'.format(SLUG_BAD_CHARS))
69
69
70 # Regex that matches allowed characters in repo/group slugs.
70 # Regex that matches allowed characters in repo/group slugs.
71 SLUG_GOOD_CHAR_RE = re.compile(r'[^{}]'.format(SLUG_BAD_CHARS))
71 SLUG_GOOD_CHAR_RE = re.compile(r'[^{}]'.format(SLUG_BAD_CHARS))
72
72
73 # Regex that matches whole repo/group slugs.
73 # Regex that matches whole repo/group slugs.
74 SLUG_RE = re.compile(r'[^{}]+'.format(SLUG_BAD_CHARS))
74 SLUG_RE = re.compile(r'[^{}]+'.format(SLUG_BAD_CHARS))
75
75
76 _license_cache = None
76 _license_cache = None
77
77
78
78
79 def adopt_for_celery(func):
79 def adopt_for_celery(func):
80 """
80 """
81 Decorator designed to adopt hooks (from rhodecode.lib.hooks_base)
81 Decorator designed to adopt hooks (from rhodecode.lib.hooks_base)
82 for further usage as a celery tasks.
82 for further usage as a celery tasks.
83 """
83 """
84 @wraps(func)
84 @wraps(func)
85 def wrapper(extras):
85 def wrapper(extras):
86 extras = AttributeDict(extras)
86 extras = AttributeDict(extras)
87 # HooksResponse implements to_json method which must be used there.
87 try:
88 return func(extras).to_json()
88 # HooksResponse implements to_json method which must be used there.
89 return func(extras).to_json()
90 except Exception as e:
91 return {'status': 128, 'exception': type(e).__name__, 'exception_args': e.args}
89 return wrapper
92 return wrapper
90
93
91
94
92 def repo_name_slug(value):
95 def repo_name_slug(value):
93 """
96 """
94 Return slug of name of repository
97 Return slug of name of repository
95 This function is called on each creation/modification
98 This function is called on each creation/modification
96 of repository to prevent bad names in repo
99 of repository to prevent bad names in repo
97 """
100 """
98
101
99 replacement_char = '-'
102 replacement_char = '-'
100
103
101 slug = strip_tags(value)
104 slug = strip_tags(value)
102 slug = convert_accented_entities(slug)
105 slug = convert_accented_entities(slug)
103 slug = convert_misc_entities(slug)
106 slug = convert_misc_entities(slug)
104
107
105 slug = SLUG_BAD_CHAR_RE.sub('', slug)
108 slug = SLUG_BAD_CHAR_RE.sub('', slug)
106 slug = re.sub(r'[\s]+', '-', slug)
109 slug = re.sub(r'[\s]+', '-', slug)
107 slug = collapse(slug, replacement_char)
110 slug = collapse(slug, replacement_char)
108
111
109 return slug
112 return slug
110
113
111
114
112 #==============================================================================
115 #==============================================================================
113 # PERM DECORATOR HELPERS FOR EXTRACTING NAMES FOR PERM CHECKS
116 # PERM DECORATOR HELPERS FOR EXTRACTING NAMES FOR PERM CHECKS
114 #==============================================================================
117 #==============================================================================
115 def get_repo_slug(request):
118 def get_repo_slug(request):
116 _repo = ''
119 _repo = ''
117
120
118 if hasattr(request, 'db_repo_name'):
121 if hasattr(request, 'db_repo_name'):
119 # if our requests has set db reference use it for name, this
122 # if our requests has set db reference use it for name, this
120 # translates the example.com/_<id> into proper repo names
123 # translates the example.com/_<id> into proper repo names
121 _repo = request.db_repo_name
124 _repo = request.db_repo_name
122 elif getattr(request, 'matchdict', None):
125 elif getattr(request, 'matchdict', None):
123 # pyramid
126 # pyramid
124 _repo = request.matchdict.get('repo_name')
127 _repo = request.matchdict.get('repo_name')
125
128
126 if _repo:
129 if _repo:
127 _repo = _repo.rstrip('/')
130 _repo = _repo.rstrip('/')
128 return _repo
131 return _repo
129
132
130
133
131 def get_repo_group_slug(request):
134 def get_repo_group_slug(request):
132 _group = ''
135 _group = ''
133 if hasattr(request, 'db_repo_group'):
136 if hasattr(request, 'db_repo_group'):
134 # if our requests has set db reference use it for name, this
137 # if our requests has set db reference use it for name, this
135 # translates the example.com/_<id> into proper repo group names
138 # translates the example.com/_<id> into proper repo group names
136 _group = request.db_repo_group.group_name
139 _group = request.db_repo_group.group_name
137 elif getattr(request, 'matchdict', None):
140 elif getattr(request, 'matchdict', None):
138 # pyramid
141 # pyramid
139 _group = request.matchdict.get('repo_group_name')
142 _group = request.matchdict.get('repo_group_name')
140
143
141 if _group:
144 if _group:
142 _group = _group.rstrip('/')
145 _group = _group.rstrip('/')
143 return _group
146 return _group
144
147
145
148
146 def get_user_group_slug(request):
149 def get_user_group_slug(request):
147 _user_group = ''
150 _user_group = ''
148
151
149 if hasattr(request, 'db_user_group'):
152 if hasattr(request, 'db_user_group'):
150 _user_group = request.db_user_group.users_group_name
153 _user_group = request.db_user_group.users_group_name
151 elif getattr(request, 'matchdict', None):
154 elif getattr(request, 'matchdict', None):
152 # pyramid
155 # pyramid
153 _user_group = request.matchdict.get('user_group_id')
156 _user_group = request.matchdict.get('user_group_id')
154 _user_group_name = request.matchdict.get('user_group_name')
157 _user_group_name = request.matchdict.get('user_group_name')
155 try:
158 try:
156 if _user_group:
159 if _user_group:
157 _user_group = UserGroup.get(_user_group)
160 _user_group = UserGroup.get(_user_group)
158 elif _user_group_name:
161 elif _user_group_name:
159 _user_group = UserGroup.get_by_group_name(_user_group_name)
162 _user_group = UserGroup.get_by_group_name(_user_group_name)
160
163
161 if _user_group:
164 if _user_group:
162 _user_group = _user_group.users_group_name
165 _user_group = _user_group.users_group_name
163 except Exception:
166 except Exception:
164 log.exception('Failed to get user group by id and name')
167 log.exception('Failed to get user group by id and name')
165 # catch all failures here
168 # catch all failures here
166 return None
169 return None
167
170
168 return _user_group
171 return _user_group
169
172
170
173
171 def get_filesystem_repos(path, recursive=False, skip_removed_repos=True):
174 def get_filesystem_repos(path, recursive=False, skip_removed_repos=True):
172 """
175 """
173 Scans given path for repos and return (name,(type,path)) tuple
176 Scans given path for repos and return (name,(type,path)) tuple
174
177
175 :param path: path to scan for repositories
178 :param path: path to scan for repositories
176 :param recursive: recursive search and return names with subdirs in front
179 :param recursive: recursive search and return names with subdirs in front
177 """
180 """
178
181
179 # remove ending slash for better results
182 # remove ending slash for better results
180 path = path.rstrip(os.sep)
183 path = path.rstrip(os.sep)
181 log.debug('now scanning in %s location recursive:%s...', path, recursive)
184 log.debug('now scanning in %s location recursive:%s...', path, recursive)
182
185
183 def _get_repos(p):
186 def _get_repos(p):
184 dirpaths = get_dirpaths(p)
187 dirpaths = get_dirpaths(p)
185 if not _is_dir_writable(p):
188 if not _is_dir_writable(p):
186 log.warning('repo path without write access: %s', p)
189 log.warning('repo path without write access: %s', p)
187
190
188 for dirpath in dirpaths:
191 for dirpath in dirpaths:
189 if os.path.isfile(os.path.join(p, dirpath)):
192 if os.path.isfile(os.path.join(p, dirpath)):
190 continue
193 continue
191 cur_path = os.path.join(p, dirpath)
194 cur_path = os.path.join(p, dirpath)
192
195
193 # skip removed repos
196 # skip removed repos
194 if skip_removed_repos and REMOVED_REPO_PAT.match(dirpath):
197 if skip_removed_repos and REMOVED_REPO_PAT.match(dirpath):
195 continue
198 continue
196
199
197 #skip .<somethin> dirs
200 #skip .<somethin> dirs
198 if dirpath.startswith('.'):
201 if dirpath.startswith('.'):
199 continue
202 continue
200
203
201 try:
204 try:
202 scm_info = get_scm(cur_path)
205 scm_info = get_scm(cur_path)
203 yield scm_info[1].split(path, 1)[-1].lstrip(os.sep), scm_info
206 yield scm_info[1].split(path, 1)[-1].lstrip(os.sep), scm_info
204 except VCSError:
207 except VCSError:
205 if not recursive:
208 if not recursive:
206 continue
209 continue
207 #check if this dir containts other repos for recursive scan
210 #check if this dir containts other repos for recursive scan
208 rec_path = os.path.join(p, dirpath)
211 rec_path = os.path.join(p, dirpath)
209 if os.path.isdir(rec_path):
212 if os.path.isdir(rec_path):
210 yield from _get_repos(rec_path)
213 yield from _get_repos(rec_path)
211
214
212 return _get_repos(path)
215 return _get_repos(path)
213
216
214
217
215 def get_dirpaths(p: str) -> list:
218 def get_dirpaths(p: str) -> list:
216 try:
219 try:
217 # OS-independable way of checking if we have at least read-only
220 # OS-independable way of checking if we have at least read-only
218 # access or not.
221 # access or not.
219 dirpaths = os.listdir(p)
222 dirpaths = os.listdir(p)
220 except OSError:
223 except OSError:
221 log.warning('ignoring repo path without read access: %s', p)
224 log.warning('ignoring repo path without read access: %s', p)
222 return []
225 return []
223
226
224 # os.listpath has a tweak: If a unicode is passed into it, then it tries to
227 # os.listpath has a tweak: If a unicode is passed into it, then it tries to
225 # decode paths and suddenly returns unicode objects itself. The items it
228 # decode paths and suddenly returns unicode objects itself. The items it
226 # cannot decode are returned as strings and cause issues.
229 # cannot decode are returned as strings and cause issues.
227 #
230 #
228 # Those paths are ignored here until a solid solution for path handling has
231 # Those paths are ignored here until a solid solution for path handling has
229 # been built.
232 # been built.
230 expected_type = type(p)
233 expected_type = type(p)
231
234
232 def _has_correct_type(item):
235 def _has_correct_type(item):
233 if type(item) is not expected_type:
236 if type(item) is not expected_type:
234 log.error(
237 log.error(
235 "Ignoring path %s since it cannot be decoded into str.",
238 "Ignoring path %s since it cannot be decoded into str.",
236 # Using "repr" to make sure that we see the byte value in case
239 # Using "repr" to make sure that we see the byte value in case
237 # of support.
240 # of support.
238 repr(item))
241 repr(item))
239 return False
242 return False
240 return True
243 return True
241
244
242 dirpaths = [item for item in dirpaths if _has_correct_type(item)]
245 dirpaths = [item for item in dirpaths if _has_correct_type(item)]
243
246
244 return dirpaths
247 return dirpaths
245
248
246
249
247 def _is_dir_writable(path):
250 def _is_dir_writable(path):
248 """
251 """
249 Probe if `path` is writable.
252 Probe if `path` is writable.
250
253
251 Due to trouble on Cygwin / Windows, this is actually probing if it is
254 Due to trouble on Cygwin / Windows, this is actually probing if it is
252 possible to create a file inside of `path`, stat does not produce reliable
255 possible to create a file inside of `path`, stat does not produce reliable
253 results in this case.
256 results in this case.
254 """
257 """
255 try:
258 try:
256 with tempfile.TemporaryFile(dir=path):
259 with tempfile.TemporaryFile(dir=path):
257 pass
260 pass
258 except OSError:
261 except OSError:
259 return False
262 return False
260 return True
263 return True
261
264
262
265
263 def is_valid_repo(repo_name, base_path, expect_scm=None, explicit_scm=None, config=None):
266 def is_valid_repo(repo_name, base_path, expect_scm=None, explicit_scm=None, config=None):
264 """
267 """
265 Returns True if given path is a valid repository False otherwise.
268 Returns True if given path is a valid repository False otherwise.
266 If expect_scm param is given also, compare if given scm is the same
269 If expect_scm param is given also, compare if given scm is the same
267 as expected from scm parameter. If explicit_scm is given don't try to
270 as expected from scm parameter. If explicit_scm is given don't try to
268 detect the scm, just use the given one to check if repo is valid
271 detect the scm, just use the given one to check if repo is valid
269
272
270 :param repo_name:
273 :param repo_name:
271 :param base_path:
274 :param base_path:
272 :param expect_scm:
275 :param expect_scm:
273 :param explicit_scm:
276 :param explicit_scm:
274 :param config:
277 :param config:
275
278
276 :return True: if given path is a valid repository
279 :return True: if given path is a valid repository
277 """
280 """
278 full_path = os.path.join(safe_str(base_path), safe_str(repo_name))
281 full_path = os.path.join(safe_str(base_path), safe_str(repo_name))
279 log.debug('Checking if `%s` is a valid path for repository. '
282 log.debug('Checking if `%s` is a valid path for repository. '
280 'Explicit type: %s', repo_name, explicit_scm)
283 'Explicit type: %s', repo_name, explicit_scm)
281
284
282 try:
285 try:
283 if explicit_scm:
286 if explicit_scm:
284 detected_scms = [get_scm_backend(explicit_scm)(
287 detected_scms = [get_scm_backend(explicit_scm)(
285 full_path, config=config).alias]
288 full_path, config=config).alias]
286 else:
289 else:
287 detected_scms = get_scm(full_path)
290 detected_scms = get_scm(full_path)
288
291
289 if expect_scm:
292 if expect_scm:
290 return detected_scms[0] == expect_scm
293 return detected_scms[0] == expect_scm
291 log.debug('path: %s is an vcs object:%s', full_path, detected_scms)
294 log.debug('path: %s is an vcs object:%s', full_path, detected_scms)
292 return True
295 return True
293 except VCSError:
296 except VCSError:
294 log.debug('path: %s is not a valid repo !', full_path)
297 log.debug('path: %s is not a valid repo !', full_path)
295 return False
298 return False
296
299
297
300
298 def is_valid_repo_group(repo_group_name, base_path, skip_path_check=False):
301 def is_valid_repo_group(repo_group_name, base_path, skip_path_check=False):
299 """
302 """
300 Returns True if a given path is a repository group, False otherwise
303 Returns True if a given path is a repository group, False otherwise
301
304
302 :param repo_group_name:
305 :param repo_group_name:
303 :param base_path:
306 :param base_path:
304 """
307 """
305 full_path = os.path.join(safe_str(base_path), safe_str(repo_group_name))
308 full_path = os.path.join(safe_str(base_path), safe_str(repo_group_name))
306 log.debug('Checking if `%s` is a valid path for repository group',
309 log.debug('Checking if `%s` is a valid path for repository group',
307 repo_group_name)
310 repo_group_name)
308
311
309 # check if it's not a repo
312 # check if it's not a repo
310 if is_valid_repo(repo_group_name, base_path):
313 if is_valid_repo(repo_group_name, base_path):
311 log.debug('Repo called %s exist, it is not a valid repo group', repo_group_name)
314 log.debug('Repo called %s exist, it is not a valid repo group', repo_group_name)
312 return False
315 return False
313
316
314 try:
317 try:
315 # we need to check bare git repos at higher level
318 # we need to check bare git repos at higher level
316 # since we might match branches/hooks/info/objects or possible
319 # since we might match branches/hooks/info/objects or possible
317 # other things inside bare git repo
320 # other things inside bare git repo
318 maybe_repo = os.path.dirname(full_path)
321 maybe_repo = os.path.dirname(full_path)
319 if maybe_repo == base_path:
322 if maybe_repo == base_path:
320 # skip root level repo check; we know root location CANNOT BE a repo group
323 # skip root level repo check; we know root location CANNOT BE a repo group
321 return False
324 return False
322
325
323 scm_ = get_scm(maybe_repo)
326 scm_ = get_scm(maybe_repo)
324 log.debug('path: %s is a vcs object:%s, not valid repo group', full_path, scm_)
327 log.debug('path: %s is a vcs object:%s, not valid repo group', full_path, scm_)
325 return False
328 return False
326 except VCSError:
329 except VCSError:
327 pass
330 pass
328
331
329 # check if it's a valid path
332 # check if it's a valid path
330 if skip_path_check or os.path.isdir(full_path):
333 if skip_path_check or os.path.isdir(full_path):
331 log.debug('path: %s is a valid repo group !', full_path)
334 log.debug('path: %s is a valid repo group !', full_path)
332 return True
335 return True
333
336
334 log.debug('path: %s is not a valid repo group !', full_path)
337 log.debug('path: %s is not a valid repo group !', full_path)
335 return False
338 return False
336
339
337
340
338 def ask_ok(prompt, retries=4, complaint='[y]es or [n]o please!'):
341 def ask_ok(prompt, retries=4, complaint='[y]es or [n]o please!'):
339 while True:
342 while True:
340 ok = input(prompt)
343 ok = input(prompt)
341 if ok.lower() in ('y', 'ye', 'yes'):
344 if ok.lower() in ('y', 'ye', 'yes'):
342 return True
345 return True
343 if ok.lower() in ('n', 'no', 'nop', 'nope'):
346 if ok.lower() in ('n', 'no', 'nop', 'nope'):
344 return False
347 return False
345 retries = retries - 1
348 retries = retries - 1
346 if retries < 0:
349 if retries < 0:
347 raise OSError
350 raise OSError
348 print(complaint)
351 print(complaint)
349
352
350 # propagated from mercurial documentation
353 # propagated from mercurial documentation
351 ui_sections = [
354 ui_sections = [
352 'alias', 'auth',
355 'alias', 'auth',
353 'decode/encode', 'defaults',
356 'decode/encode', 'defaults',
354 'diff', 'email',
357 'diff', 'email',
355 'extensions', 'format',
358 'extensions', 'format',
356 'merge-patterns', 'merge-tools',
359 'merge-patterns', 'merge-tools',
357 'hooks', 'http_proxy',
360 'hooks', 'http_proxy',
358 'smtp', 'patch',
361 'smtp', 'patch',
359 'paths', 'profiling',
362 'paths', 'profiling',
360 'server', 'trusted',
363 'server', 'trusted',
361 'ui', 'web', ]
364 'ui', 'web', ]
362
365
363
366
364 def config_data_from_db(clear_session=True, repo=None):
367 def config_data_from_db(clear_session=True, repo=None):
365 """
368 """
366 Read the configuration data from the database and return configuration
369 Read the configuration data from the database and return configuration
367 tuples.
370 tuples.
368 """
371 """
369 from rhodecode.model.settings import VcsSettingsModel
372 from rhodecode.model.settings import VcsSettingsModel
370
373
371 config = []
374 config = []
372
375
373 sa = meta.Session()
376 sa = meta.Session()
374 settings_model = VcsSettingsModel(repo=repo, sa=sa)
377 settings_model = VcsSettingsModel(repo=repo, sa=sa)
375
378
376 ui_settings = settings_model.get_ui_settings()
379 ui_settings = settings_model.get_ui_settings()
377
380
378 ui_data = []
381 ui_data = []
379 for setting in ui_settings:
382 for setting in ui_settings:
380 if setting.active:
383 if setting.active:
381 ui_data.append((setting.section, setting.key, setting.value))
384 ui_data.append((setting.section, setting.key, setting.value))
382 config.append((
385 config.append((
383 safe_str(setting.section), safe_str(setting.key),
386 safe_str(setting.section), safe_str(setting.key),
384 safe_str(setting.value)))
387 safe_str(setting.value)))
385 if setting.key == 'push_ssl':
388 if setting.key == 'push_ssl':
386 # force set push_ssl requirement to False, rhodecode
389 # force set push_ssl requirement to False, rhodecode
387 # handles that
390 # handles that
388 config.append((
391 config.append((
389 safe_str(setting.section), safe_str(setting.key), False))
392 safe_str(setting.section), safe_str(setting.key), False))
390 log.debug(
393 log.debug(
391 'settings ui from db@repo[%s]: %s',
394 'settings ui from db@repo[%s]: %s',
392 repo,
395 repo,
393 ','.join(['[{}] {}={}'.format(*s) for s in ui_data]))
396 ','.join(['[{}] {}={}'.format(*s) for s in ui_data]))
394 if clear_session:
397 if clear_session:
395 meta.Session.remove()
398 meta.Session.remove()
396
399
397 # TODO: mikhail: probably it makes no sense to re-read hooks information.
400 # TODO: mikhail: probably it makes no sense to re-read hooks information.
398 # It's already there and activated/deactivated
401 # It's already there and activated/deactivated
399 skip_entries = []
402 skip_entries = []
400 enabled_hook_classes = get_enabled_hook_classes(ui_settings)
403 enabled_hook_classes = get_enabled_hook_classes(ui_settings)
401 if 'pull' not in enabled_hook_classes:
404 if 'pull' not in enabled_hook_classes:
402 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRE_PULL))
405 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRE_PULL))
403 if 'push' not in enabled_hook_classes:
406 if 'push' not in enabled_hook_classes:
404 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRE_PUSH))
407 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRE_PUSH))
405 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRETX_PUSH))
408 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRETX_PUSH))
406 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PUSH_KEY))
409 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PUSH_KEY))
407
410
408 config = [entry for entry in config if entry[:2] not in skip_entries]
411 config = [entry for entry in config if entry[:2] not in skip_entries]
409
412
410 return config
413 return config
411
414
412
415
413 def make_db_config(clear_session=True, repo=None):
416 def make_db_config(clear_session=True, repo=None):
414 """
417 """
415 Create a :class:`Config` instance based on the values in the database.
418 Create a :class:`Config` instance based on the values in the database.
416 """
419 """
417 config = Config()
420 config = Config()
418 config_data = config_data_from_db(clear_session=clear_session, repo=repo)
421 config_data = config_data_from_db(clear_session=clear_session, repo=repo)
419 for section, option, value in config_data:
422 for section, option, value in config_data:
420 config.set(section, option, value)
423 config.set(section, option, value)
421 return config
424 return config
422
425
423
426
424 def get_enabled_hook_classes(ui_settings):
427 def get_enabled_hook_classes(ui_settings):
425 """
428 """
426 Return the enabled hook classes.
429 Return the enabled hook classes.
427
430
428 :param ui_settings: List of ui_settings as returned
431 :param ui_settings: List of ui_settings as returned
429 by :meth:`VcsSettingsModel.get_ui_settings`
432 by :meth:`VcsSettingsModel.get_ui_settings`
430
433
431 :return: a list with the enabled hook classes. The order is not guaranteed.
434 :return: a list with the enabled hook classes. The order is not guaranteed.
432 :rtype: list
435 :rtype: list
433 """
436 """
434 enabled_hooks = []
437 enabled_hooks = []
435 active_hook_keys = [
438 active_hook_keys = [
436 key for section, key, value, active in ui_settings
439 key for section, key, value, active in ui_settings
437 if section == 'hooks' and active]
440 if section == 'hooks' and active]
438
441
439 hook_names = {
442 hook_names = {
440 RhodeCodeUi.HOOK_PUSH: 'push',
443 RhodeCodeUi.HOOK_PUSH: 'push',
441 RhodeCodeUi.HOOK_PULL: 'pull',
444 RhodeCodeUi.HOOK_PULL: 'pull',
442 RhodeCodeUi.HOOK_REPO_SIZE: 'repo_size'
445 RhodeCodeUi.HOOK_REPO_SIZE: 'repo_size'
443 }
446 }
444
447
445 for key in active_hook_keys:
448 for key in active_hook_keys:
446 hook = hook_names.get(key)
449 hook = hook_names.get(key)
447 if hook:
450 if hook:
448 enabled_hooks.append(hook)
451 enabled_hooks.append(hook)
449
452
450 return enabled_hooks
453 return enabled_hooks
451
454
452
455
453 def set_rhodecode_config(config):
456 def set_rhodecode_config(config):
454 """
457 """
455 Updates pyramid config with new settings from database
458 Updates pyramid config with new settings from database
456
459
457 :param config:
460 :param config:
458 """
461 """
459 from rhodecode.model.settings import SettingsModel
462 from rhodecode.model.settings import SettingsModel
460 app_settings = SettingsModel().get_all_settings()
463 app_settings = SettingsModel().get_all_settings()
461
464
462 for k, v in list(app_settings.items()):
465 for k, v in list(app_settings.items()):
463 config[k] = v
466 config[k] = v
464
467
465
468
466 def get_rhodecode_realm():
469 def get_rhodecode_realm():
467 """
470 """
468 Return the rhodecode realm from database.
471 Return the rhodecode realm from database.
469 """
472 """
470 from rhodecode.model.settings import SettingsModel
473 from rhodecode.model.settings import SettingsModel
471 realm = SettingsModel().get_setting_by_name('realm')
474 realm = SettingsModel().get_setting_by_name('realm')
472 return safe_str(realm.app_settings_value)
475 return safe_str(realm.app_settings_value)
473
476
474
477
475 def get_rhodecode_repo_store_path():
478 def get_rhodecode_repo_store_path():
476 """
479 """
477 Returns the base path. The base path is the filesystem path which points
480 Returns the base path. The base path is the filesystem path which points
478 to the repository store.
481 to the repository store.
479 """
482 """
480
483
481 import rhodecode
484 import rhodecode
482 return rhodecode.CONFIG['repo_store.path']
485 return rhodecode.CONFIG['repo_store.path']
483
486
484
487
485 def map_groups(path):
488 def map_groups(path):
486 """
489 """
487 Given a full path to a repository, create all nested groups that this
490 Given a full path to a repository, create all nested groups that this
488 repo is inside. This function creates parent-child relationships between
491 repo is inside. This function creates parent-child relationships between
489 groups and creates default perms for all new groups.
492 groups and creates default perms for all new groups.
490
493
491 :param paths: full path to repository
494 :param paths: full path to repository
492 """
495 """
493 from rhodecode.model.repo_group import RepoGroupModel
496 from rhodecode.model.repo_group import RepoGroupModel
494 sa = meta.Session()
497 sa = meta.Session()
495 groups = path.split(Repository.NAME_SEP)
498 groups = path.split(Repository.NAME_SEP)
496 parent = None
499 parent = None
497 group = None
500 group = None
498
501
499 # last element is repo in nested groups structure
502 # last element is repo in nested groups structure
500 groups = groups[:-1]
503 groups = groups[:-1]
501 rgm = RepoGroupModel(sa)
504 rgm = RepoGroupModel(sa)
502 owner = User.get_first_super_admin()
505 owner = User.get_first_super_admin()
503 for lvl, group_name in enumerate(groups):
506 for lvl, group_name in enumerate(groups):
504 group_name = '/'.join(groups[:lvl] + [group_name])
507 group_name = '/'.join(groups[:lvl] + [group_name])
505 group = RepoGroup.get_by_group_name(group_name)
508 group = RepoGroup.get_by_group_name(group_name)
506 desc = '%s group' % group_name
509 desc = '%s group' % group_name
507
510
508 # skip folders that are now removed repos
511 # skip folders that are now removed repos
509 if REMOVED_REPO_PAT.match(group_name):
512 if REMOVED_REPO_PAT.match(group_name):
510 break
513 break
511
514
512 if group is None:
515 if group is None:
513 log.debug('creating group level: %s group_name: %s',
516 log.debug('creating group level: %s group_name: %s',
514 lvl, group_name)
517 lvl, group_name)
515 group = RepoGroup(group_name, parent)
518 group = RepoGroup(group_name, parent)
516 group.group_description = desc
519 group.group_description = desc
517 group.user = owner
520 group.user = owner
518 sa.add(group)
521 sa.add(group)
519 perm_obj = rgm._create_default_perms(group)
522 perm_obj = rgm._create_default_perms(group)
520 sa.add(perm_obj)
523 sa.add(perm_obj)
521 sa.flush()
524 sa.flush()
522
525
523 parent = group
526 parent = group
524 return group
527 return group
525
528
526
529
527 def repo2db_mapper(initial_repo_list, remove_obsolete=False, force_hooks_rebuild=False):
530 def repo2db_mapper(initial_repo_list, remove_obsolete=False, force_hooks_rebuild=False):
528 """
531 """
529 maps all repos given in initial_repo_list, non existing repositories
532 maps all repos given in initial_repo_list, non existing repositories
530 are created, if remove_obsolete is True it also checks for db entries
533 are created, if remove_obsolete is True it also checks for db entries
531 that are not in initial_repo_list and removes them.
534 that are not in initial_repo_list and removes them.
532
535
533 :param initial_repo_list: list of repositories found by scanning methods
536 :param initial_repo_list: list of repositories found by scanning methods
534 :param remove_obsolete: check for obsolete entries in database
537 :param remove_obsolete: check for obsolete entries in database
535 """
538 """
536 from rhodecode.model.repo import RepoModel
539 from rhodecode.model.repo import RepoModel
537 from rhodecode.model.repo_group import RepoGroupModel
540 from rhodecode.model.repo_group import RepoGroupModel
538 from rhodecode.model.settings import SettingsModel
541 from rhodecode.model.settings import SettingsModel
539
542
540 sa = meta.Session()
543 sa = meta.Session()
541 repo_model = RepoModel()
544 repo_model = RepoModel()
542 user = User.get_first_super_admin()
545 user = User.get_first_super_admin()
543 added = []
546 added = []
544
547
545 # creation defaults
548 # creation defaults
546 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
549 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
547 enable_statistics = defs.get('repo_enable_statistics')
550 enable_statistics = defs.get('repo_enable_statistics')
548 enable_locking = defs.get('repo_enable_locking')
551 enable_locking = defs.get('repo_enable_locking')
549 enable_downloads = defs.get('repo_enable_downloads')
552 enable_downloads = defs.get('repo_enable_downloads')
550 private = defs.get('repo_private')
553 private = defs.get('repo_private')
551
554
552 for name, repo in list(initial_repo_list.items()):
555 for name, repo in list(initial_repo_list.items()):
553 group = map_groups(name)
556 group = map_groups(name)
554 str_name = safe_str(name)
557 str_name = safe_str(name)
555 db_repo = repo_model.get_by_repo_name(str_name)
558 db_repo = repo_model.get_by_repo_name(str_name)
556
559
557 # found repo that is on filesystem not in RhodeCode database
560 # found repo that is on filesystem not in RhodeCode database
558 if not db_repo:
561 if not db_repo:
559 log.info('repository `%s` not found in the database, creating now', name)
562 log.info('repository `%s` not found in the database, creating now', name)
560 added.append(name)
563 added.append(name)
561 desc = (repo.description
564 desc = (repo.description
562 if repo.description != 'unknown'
565 if repo.description != 'unknown'
563 else '%s repository' % name)
566 else '%s repository' % name)
564
567
565 db_repo = repo_model._create_repo(
568 db_repo = repo_model._create_repo(
566 repo_name=name,
569 repo_name=name,
567 repo_type=repo.alias,
570 repo_type=repo.alias,
568 description=desc,
571 description=desc,
569 repo_group=getattr(group, 'group_id', None),
572 repo_group=getattr(group, 'group_id', None),
570 owner=user,
573 owner=user,
571 enable_locking=enable_locking,
574 enable_locking=enable_locking,
572 enable_downloads=enable_downloads,
575 enable_downloads=enable_downloads,
573 enable_statistics=enable_statistics,
576 enable_statistics=enable_statistics,
574 private=private,
577 private=private,
575 state=Repository.STATE_CREATED
578 state=Repository.STATE_CREATED
576 )
579 )
577 sa.commit()
580 sa.commit()
578 # we added that repo just now, and make sure we updated server info
581 # we added that repo just now, and make sure we updated server info
579 if db_repo.repo_type == 'git':
582 if db_repo.repo_type == 'git':
580 git_repo = db_repo.scm_instance()
583 git_repo = db_repo.scm_instance()
581 # update repository server-info
584 # update repository server-info
582 log.debug('Running update server info')
585 log.debug('Running update server info')
583 git_repo._update_server_info(force=True)
586 git_repo._update_server_info(force=True)
584
587
585 db_repo.update_commit_cache(recursive=False)
588 db_repo.update_commit_cache(recursive=False)
586
589
587 config = db_repo._config
590 config = db_repo._config
588 config.set('extensions', 'largefiles', '')
591 config.set('extensions', 'largefiles', '')
589 repo = db_repo.scm_instance(config=config)
592 repo = db_repo.scm_instance(config=config)
590 repo.install_hooks(force=force_hooks_rebuild)
593 repo.install_hooks(force=force_hooks_rebuild)
591
594
592 removed = []
595 removed = []
593 if remove_obsolete:
596 if remove_obsolete:
594 # remove from database those repositories that are not in the filesystem
597 # remove from database those repositories that are not in the filesystem
595 for repo in sa.query(Repository).all():
598 for repo in sa.query(Repository).all():
596 if repo.repo_name not in list(initial_repo_list.keys()):
599 if repo.repo_name not in list(initial_repo_list.keys()):
597 log.debug("Removing non-existing repository found in db `%s`",
600 log.debug("Removing non-existing repository found in db `%s`",
598 repo.repo_name)
601 repo.repo_name)
599 try:
602 try:
600 RepoModel(sa).delete(repo, forks='detach', fs_remove=False)
603 RepoModel(sa).delete(repo, forks='detach', fs_remove=False)
601 sa.commit()
604 sa.commit()
602 removed.append(repo.repo_name)
605 removed.append(repo.repo_name)
603 except Exception:
606 except Exception:
604 # don't hold further removals on error
607 # don't hold further removals on error
605 log.error(traceback.format_exc())
608 log.error(traceback.format_exc())
606 sa.rollback()
609 sa.rollback()
607
610
608 def splitter(full_repo_name):
611 def splitter(full_repo_name):
609 _parts = full_repo_name.rsplit(RepoGroup.url_sep(), 1)
612 _parts = full_repo_name.rsplit(RepoGroup.url_sep(), 1)
610 gr_name = None
613 gr_name = None
611 if len(_parts) == 2:
614 if len(_parts) == 2:
612 gr_name = _parts[0]
615 gr_name = _parts[0]
613 return gr_name
616 return gr_name
614
617
615 initial_repo_group_list = [splitter(x) for x in
618 initial_repo_group_list = [splitter(x) for x in
616 list(initial_repo_list.keys()) if splitter(x)]
619 list(initial_repo_list.keys()) if splitter(x)]
617
620
618 # remove from database those repository groups that are not in the
621 # remove from database those repository groups that are not in the
619 # filesystem due to parent child relationships we need to delete them
622 # filesystem due to parent child relationships we need to delete them
620 # in a specific order of most nested first
623 # in a specific order of most nested first
621 all_groups = [x.group_name for x in sa.query(RepoGroup).all()]
624 all_groups = [x.group_name for x in sa.query(RepoGroup).all()]
622 def nested_sort(gr):
625 def nested_sort(gr):
623 return len(gr.split('/'))
626 return len(gr.split('/'))
624 for group_name in sorted(all_groups, key=nested_sort, reverse=True):
627 for group_name in sorted(all_groups, key=nested_sort, reverse=True):
625 if group_name not in initial_repo_group_list:
628 if group_name not in initial_repo_group_list:
626 repo_group = RepoGroup.get_by_group_name(group_name)
629 repo_group = RepoGroup.get_by_group_name(group_name)
627 if (repo_group.children.all() or
630 if (repo_group.children.all() or
628 not RepoGroupModel().check_exist_filesystem(
631 not RepoGroupModel().check_exist_filesystem(
629 group_name=group_name, exc_on_failure=False)):
632 group_name=group_name, exc_on_failure=False)):
630 continue
633 continue
631
634
632 log.info(
635 log.info(
633 'Removing non-existing repository group found in db `%s`',
636 'Removing non-existing repository group found in db `%s`',
634 group_name)
637 group_name)
635 try:
638 try:
636 RepoGroupModel(sa).delete(group_name, fs_remove=False)
639 RepoGroupModel(sa).delete(group_name, fs_remove=False)
637 sa.commit()
640 sa.commit()
638 removed.append(group_name)
641 removed.append(group_name)
639 except Exception:
642 except Exception:
640 # don't hold further removals on error
643 # don't hold further removals on error
641 log.exception(
644 log.exception(
642 'Unable to remove repository group `%s`',
645 'Unable to remove repository group `%s`',
643 group_name)
646 group_name)
644 sa.rollback()
647 sa.rollback()
645 raise
648 raise
646
649
647 return added, removed
650 return added, removed
648
651
649
652
650 def load_rcextensions(root_path):
653 def load_rcextensions(root_path):
651 import rhodecode
654 import rhodecode
652 from rhodecode.config import conf
655 from rhodecode.config import conf
653
656
654 path = os.path.join(root_path)
657 path = os.path.join(root_path)
655 sys.path.append(path)
658 sys.path.append(path)
656
659
657 try:
660 try:
658 rcextensions = __import__('rcextensions')
661 rcextensions = __import__('rcextensions')
659 except ImportError:
662 except ImportError:
660 if os.path.isdir(os.path.join(path, 'rcextensions')):
663 if os.path.isdir(os.path.join(path, 'rcextensions')):
661 log.warning('Unable to load rcextensions from %s', path)
664 log.warning('Unable to load rcextensions from %s', path)
662 rcextensions = None
665 rcextensions = None
663
666
664 if rcextensions:
667 if rcextensions:
665 log.info('Loaded rcextensions from %s...', rcextensions)
668 log.info('Loaded rcextensions from %s...', rcextensions)
666 rhodecode.EXTENSIONS = rcextensions
669 rhodecode.EXTENSIONS = rcextensions
667
670
668 # Additional mappings that are not present in the pygments lexers
671 # Additional mappings that are not present in the pygments lexers
669 conf.LANGUAGES_EXTENSIONS_MAP.update(
672 conf.LANGUAGES_EXTENSIONS_MAP.update(
670 getattr(rhodecode.EXTENSIONS, 'EXTRA_MAPPINGS', {}))
673 getattr(rhodecode.EXTENSIONS, 'EXTRA_MAPPINGS', {}))
671
674
672
675
673 def get_custom_lexer(extension):
676 def get_custom_lexer(extension):
674 """
677 """
675 returns a custom lexer if it is defined in rcextensions module, or None
678 returns a custom lexer if it is defined in rcextensions module, or None
676 if there's no custom lexer defined
679 if there's no custom lexer defined
677 """
680 """
678 import rhodecode
681 import rhodecode
679 from pygments import lexers
682 from pygments import lexers
680
683
681 # custom override made by RhodeCode
684 # custom override made by RhodeCode
682 if extension in ['mako']:
685 if extension in ['mako']:
683 return lexers.get_lexer_by_name('html+mako')
686 return lexers.get_lexer_by_name('html+mako')
684
687
685 # check if we didn't define this extension as other lexer
688 # check if we didn't define this extension as other lexer
686 extensions = rhodecode.EXTENSIONS and getattr(rhodecode.EXTENSIONS, 'EXTRA_LEXERS', None)
689 extensions = rhodecode.EXTENSIONS and getattr(rhodecode.EXTENSIONS, 'EXTRA_LEXERS', None)
687 if extensions and extension in rhodecode.EXTENSIONS.EXTRA_LEXERS:
690 if extensions and extension in rhodecode.EXTENSIONS.EXTRA_LEXERS:
688 _lexer_name = rhodecode.EXTENSIONS.EXTRA_LEXERS[extension]
691 _lexer_name = rhodecode.EXTENSIONS.EXTRA_LEXERS[extension]
689 return lexers.get_lexer_by_name(_lexer_name)
692 return lexers.get_lexer_by_name(_lexer_name)
690
693
691
694
692 #==============================================================================
695 #==============================================================================
693 # TEST FUNCTIONS AND CREATORS
696 # TEST FUNCTIONS AND CREATORS
694 #==============================================================================
697 #==============================================================================
695 def create_test_index(repo_location, config):
698 def create_test_index(repo_location, config):
696 """
699 """
697 Makes default test index.
700 Makes default test index.
698 """
701 """
699 try:
702 try:
700 import rc_testdata
703 import rc_testdata
701 except ImportError:
704 except ImportError:
702 raise ImportError('Failed to import rc_testdata, '
705 raise ImportError('Failed to import rc_testdata, '
703 'please make sure this package is installed from requirements_test.txt')
706 'please make sure this package is installed from requirements_test.txt')
704 rc_testdata.extract_search_index(
707 rc_testdata.extract_search_index(
705 'vcs_search_index', os.path.dirname(config['search.location']))
708 'vcs_search_index', os.path.dirname(config['search.location']))
706
709
707
710
708 def create_test_directory(test_path):
711 def create_test_directory(test_path):
709 """
712 """
710 Create test directory if it doesn't exist.
713 Create test directory if it doesn't exist.
711 """
714 """
712 if not os.path.isdir(test_path):
715 if not os.path.isdir(test_path):
713 log.debug('Creating testdir %s', test_path)
716 log.debug('Creating testdir %s', test_path)
714 os.makedirs(test_path)
717 os.makedirs(test_path)
715
718
716
719
717 def create_test_database(test_path, config):
720 def create_test_database(test_path, config):
718 """
721 """
719 Makes a fresh database.
722 Makes a fresh database.
720 """
723 """
721 from rhodecode.lib.db_manage import DbManage
724 from rhodecode.lib.db_manage import DbManage
722 from rhodecode.lib.utils2 import get_encryption_key
725 from rhodecode.lib.utils2 import get_encryption_key
723
726
724 # PART ONE create db
727 # PART ONE create db
725 dbconf = config['sqlalchemy.db1.url']
728 dbconf = config['sqlalchemy.db1.url']
726 enc_key = get_encryption_key(config)
729 enc_key = get_encryption_key(config)
727
730
728 log.debug('making test db %s', dbconf)
731 log.debug('making test db %s', dbconf)
729
732
730 dbmanage = DbManage(log_sql=False, dbconf=dbconf, root=config['here'],
733 dbmanage = DbManage(log_sql=False, dbconf=dbconf, root=config['here'],
731 tests=True, cli_args={'force_ask': True}, enc_key=enc_key)
734 tests=True, cli_args={'force_ask': True}, enc_key=enc_key)
732 dbmanage.create_tables(override=True)
735 dbmanage.create_tables(override=True)
733 dbmanage.set_db_version()
736 dbmanage.set_db_version()
734 # for tests dynamically set new root paths based on generated content
737 # for tests dynamically set new root paths based on generated content
735 dbmanage.create_settings(dbmanage.config_prompt(test_path))
738 dbmanage.create_settings(dbmanage.config_prompt(test_path))
736 dbmanage.create_default_user()
739 dbmanage.create_default_user()
737 dbmanage.create_test_admin_and_users()
740 dbmanage.create_test_admin_and_users()
738 dbmanage.create_permissions()
741 dbmanage.create_permissions()
739 dbmanage.populate_default_permissions()
742 dbmanage.populate_default_permissions()
740 Session().commit()
743 Session().commit()
741
744
742
745
743 def create_test_repositories(test_path, config):
746 def create_test_repositories(test_path, config):
744 """
747 """
745 Creates test repositories in the temporary directory. Repositories are
748 Creates test repositories in the temporary directory. Repositories are
746 extracted from archives within the rc_testdata package.
749 extracted from archives within the rc_testdata package.
747 """
750 """
748 import rc_testdata
751 import rc_testdata
749 from rhodecode.tests import HG_REPO, GIT_REPO, SVN_REPO
752 from rhodecode.tests import HG_REPO, GIT_REPO, SVN_REPO
750
753
751 log.debug('making test vcs repositories')
754 log.debug('making test vcs repositories')
752
755
753 idx_path = config['search.location']
756 idx_path = config['search.location']
754 data_path = config['cache_dir']
757 data_path = config['cache_dir']
755
758
756 # clean index and data
759 # clean index and data
757 if idx_path and os.path.exists(idx_path):
760 if idx_path and os.path.exists(idx_path):
758 log.debug('remove %s', idx_path)
761 log.debug('remove %s', idx_path)
759 shutil.rmtree(idx_path)
762 shutil.rmtree(idx_path)
760
763
761 if data_path and os.path.exists(data_path):
764 if data_path and os.path.exists(data_path):
762 log.debug('remove %s', data_path)
765 log.debug('remove %s', data_path)
763 shutil.rmtree(data_path)
766 shutil.rmtree(data_path)
764
767
765 rc_testdata.extract_hg_dump('vcs_test_hg', jn(test_path, HG_REPO))
768 rc_testdata.extract_hg_dump('vcs_test_hg', jn(test_path, HG_REPO))
766 rc_testdata.extract_git_dump('vcs_test_git', jn(test_path, GIT_REPO))
769 rc_testdata.extract_git_dump('vcs_test_git', jn(test_path, GIT_REPO))
767
770
768 # Note: Subversion is in the process of being integrated with the system,
771 # Note: Subversion is in the process of being integrated with the system,
769 # until we have a properly packed version of the test svn repository, this
772 # until we have a properly packed version of the test svn repository, this
770 # tries to copy over the repo from a package "rc_testdata"
773 # tries to copy over the repo from a package "rc_testdata"
771 svn_repo_path = rc_testdata.get_svn_repo_archive()
774 svn_repo_path = rc_testdata.get_svn_repo_archive()
772 with tarfile.open(svn_repo_path) as tar:
775 with tarfile.open(svn_repo_path) as tar:
773 tar.extractall(jn(test_path, SVN_REPO))
776 tar.extractall(jn(test_path, SVN_REPO))
774
777
775
778
776 def password_changed(auth_user, session):
779 def password_changed(auth_user, session):
777 # Never report password change in case of default user or anonymous user.
780 # Never report password change in case of default user or anonymous user.
778 if auth_user.username == User.DEFAULT_USER or auth_user.user_id is None:
781 if auth_user.username == User.DEFAULT_USER or auth_user.user_id is None:
779 return False
782 return False
780
783
781 password_hash = md5(safe_bytes(auth_user.password)) if auth_user.password else None
784 password_hash = md5(safe_bytes(auth_user.password)) if auth_user.password else None
782 rhodecode_user = session.get('rhodecode_user', {})
785 rhodecode_user = session.get('rhodecode_user', {})
783 session_password_hash = rhodecode_user.get('password', '')
786 session_password_hash = rhodecode_user.get('password', '')
784 return password_hash != session_password_hash
787 return password_hash != session_password_hash
785
788
786
789
787 def read_opensource_licenses():
790 def read_opensource_licenses():
788 global _license_cache
791 global _license_cache
789
792
790 if not _license_cache:
793 if not _license_cache:
791 licenses = pkg_resources.resource_string(
794 licenses = pkg_resources.resource_string(
792 'rhodecode', 'config/licenses.json')
795 'rhodecode', 'config/licenses.json')
793 _license_cache = json.loads(licenses)
796 _license_cache = json.loads(licenses)
794
797
795 return _license_cache
798 return _license_cache
796
799
797
800
798 def generate_platform_uuid():
801 def generate_platform_uuid():
799 """
802 """
800 Generates platform UUID based on it's name
803 Generates platform UUID based on it's name
801 """
804 """
802 import platform
805 import platform
803
806
804 try:
807 try:
805 uuid_list = [platform.platform()]
808 uuid_list = [platform.platform()]
806 return sha256_safe(':'.join(uuid_list))
809 return sha256_safe(':'.join(uuid_list))
807 except Exception as e:
810 except Exception as e:
808 log.error('Failed to generate host uuid: %s', e)
811 log.error('Failed to generate host uuid: %s', e)
809 return 'UNDEFINED'
812 return 'UNDEFINED'
810
813
811
814
812 def send_test_email(recipients, email_body='TEST EMAIL'):
815 def send_test_email(recipients, email_body='TEST EMAIL'):
813 """
816 """
814 Simple code for generating test emails.
817 Simple code for generating test emails.
815 Usage::
818 Usage::
816
819
817 from rhodecode.lib import utils
820 from rhodecode.lib import utils
818 utils.send_test_email()
821 utils.send_test_email()
819 """
822 """
820 from rhodecode.lib.celerylib import tasks, run_task
823 from rhodecode.lib.celerylib import tasks, run_task
821
824
822 email_body = email_body_plaintext = email_body
825 email_body = email_body_plaintext = email_body
823 subject = f'SUBJECT FROM: {socket.gethostname()}'
826 subject = f'SUBJECT FROM: {socket.gethostname()}'
824 tasks.send_email(recipients, subject, email_body_plaintext, email_body)
827 tasks.send_email(recipients, subject, email_body_plaintext, email_body)
@@ -1,655 +1,669 b''
1 # Copyright (C) 2010-2023 RhodeCode GmbH
1 # Copyright (C) 2010-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 """
19 """
20 this is forms validation classes
20 this is forms validation classes
21 http://formencode.org/module-formencode.validators.html
21 http://formencode.org/module-formencode.validators.html
22 for list off all availible validators
22 for list off all availible validators
23
23
24 we can create our own validators
24 we can create our own validators
25
25
26 The table below outlines the options which can be used in a schema in addition to the validators themselves
26 The table below outlines the options which can be used in a schema in addition to the validators themselves
27 pre_validators [] These validators will be applied before the schema
27 pre_validators [] These validators will be applied before the schema
28 chained_validators [] These validators will be applied after the schema
28 chained_validators [] These validators will be applied after the schema
29 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
29 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
30 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
30 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
31 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
31 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
32 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
32 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
33
33
34
34
35 <name> = formencode.validators.<name of validator>
35 <name> = formencode.validators.<name of validator>
36 <name> must equal form name
36 <name> must equal form name
37 list=[1,2,3,4,5]
37 list=[1,2,3,4,5]
38 for SELECT use formencode.All(OneOf(list), Int())
38 for SELECT use formencode.All(OneOf(list), Int())
39
39
40 """
40 """
41
41
42 import deform
42 import deform
43 import logging
43 import logging
44 import formencode
44 import formencode
45
45
46 from pkg_resources import resource_filename
46 from pkg_resources import resource_filename
47 from formencode import All, Pipe
47 from formencode import All, Pipe
48
48
49 from pyramid.threadlocal import get_current_request
49 from pyramid.threadlocal import get_current_request
50
50
51 from rhodecode import BACKENDS
51 from rhodecode import BACKENDS
52 from rhodecode.lib import helpers
52 from rhodecode.lib import helpers
53 from rhodecode.model import validators as v
53 from rhodecode.model import validators as v
54
54
55 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
56
56
57
57
58 deform_templates = resource_filename('deform', 'templates')
58 deform_templates = resource_filename('deform', 'templates')
59 rhodecode_templates = resource_filename('rhodecode', 'templates/forms')
59 rhodecode_templates = resource_filename('rhodecode', 'templates/forms')
60 search_path = (rhodecode_templates, deform_templates)
60 search_path = (rhodecode_templates, deform_templates)
61
61
62
62
63 class RhodecodeFormZPTRendererFactory(deform.ZPTRendererFactory):
63 class RhodecodeFormZPTRendererFactory(deform.ZPTRendererFactory):
64 """ Subclass of ZPTRendererFactory to add rhodecode context variables """
64 """ Subclass of ZPTRendererFactory to add rhodecode context variables """
65 def __call__(self, template_name, **kw):
65 def __call__(self, template_name, **kw):
66 kw['h'] = helpers
66 kw['h'] = helpers
67 kw['request'] = get_current_request()
67 kw['request'] = get_current_request()
68 return self.load(template_name)(**kw)
68 return self.load(template_name)(**kw)
69
69
70
70
71 form_renderer = RhodecodeFormZPTRendererFactory(search_path)
71 form_renderer = RhodecodeFormZPTRendererFactory(search_path)
72 deform.Form.set_default_renderer(form_renderer)
72 deform.Form.set_default_renderer(form_renderer)
73
73
74
74
75 def LoginForm(localizer):
75 def LoginForm(localizer):
76 _ = localizer
76 _ = localizer
77
77
78 class _LoginForm(formencode.Schema):
78 class _LoginForm(formencode.Schema):
79 allow_extra_fields = True
79 allow_extra_fields = True
80 filter_extra_fields = True
80 filter_extra_fields = True
81 username = v.UnicodeString(
81 username = v.UnicodeString(
82 strip=True,
82 strip=True,
83 min=1,
83 min=1,
84 not_empty=True,
84 not_empty=True,
85 messages={
85 messages={
86 'empty': _('Please enter a login'),
86 'empty': _('Please enter a login'),
87 'tooShort': _('Enter a value %(min)i characters long or more')
87 'tooShort': _('Enter a value %(min)i characters long or more')
88 }
88 }
89 )
89 )
90
90
91 password = v.UnicodeString(
91 password = v.UnicodeString(
92 strip=False,
92 strip=False,
93 min=3,
93 min=3,
94 max=72,
94 max=72,
95 not_empty=True,
95 not_empty=True,
96 messages={
96 messages={
97 'empty': _('Please enter a password'),
97 'empty': _('Please enter a password'),
98 'tooShort': _('Enter %(min)i characters or more')}
98 'tooShort': _('Enter %(min)i characters or more')}
99 )
99 )
100
100
101 remember = v.StringBoolean(if_missing=False)
101 remember = v.StringBoolean(if_missing=False)
102
102
103 chained_validators = [v.ValidAuth(localizer)]
103 chained_validators = [v.ValidAuth(localizer)]
104 return _LoginForm
104 return _LoginForm
105
105
106
106
107 def TOTPForm(localizer, user, allow_recovery_code_use=False):
107 def TOTPForm(localizer, user, allow_recovery_code_use=False):
108 _ = localizer
108 _ = localizer
109
109
110 class _TOTPForm(formencode.Schema):
110 class _TOTPForm(formencode.Schema):
111 allow_extra_fields = True
111 allow_extra_fields = True
112 filter_extra_fields = False
112 filter_extra_fields = False
113 totp = v.Regex(r'^(?:\d{6}|[A-Z0-9]{32})$')
113 totp = v.Regex(r'^(?:\d{6}|[A-Z0-9]{32})$')
114 secret_totp = v.String()
114 secret_totp = v.String()
115
115
116 def to_python(self, value, state=None):
116 def to_python(self, value, state=None):
117 validation_checks = [user.is_totp_valid]
117 validation_checks = [user.is_totp_valid]
118 if allow_recovery_code_use:
118 if allow_recovery_code_use:
119 validation_checks.append(user.is_2fa_recovery_code_valid)
119 validation_checks.append(user.is_2fa_recovery_code_valid)
120 form_data = super().to_python(value, state)
120 form_data = super().to_python(value, state)
121 received_code = form_data['totp']
121 received_code = form_data['totp']
122 secret = form_data.get('secret_totp')
122 secret = form_data.get('secret_totp')
123
123
124 if not any(map(lambda func: func(received_code, secret), validation_checks)):
124 if not any(map(lambda func: func(received_code, secret), validation_checks)):
125 error_msg = _('Code is invalid. Try again!')
125 error_msg = _('Code is invalid. Try again!')
126 raise formencode.Invalid(error_msg, v, state, error_dict={'totp': error_msg})
126 raise formencode.Invalid(error_msg, v, state, error_dict={'totp': error_msg})
127 return form_data
127 return form_data
128
128
129 return _TOTPForm
129 return _TOTPForm
130
130
131
131
132 def WhitelistedVcsClientsForm(localizer):
133 _ = localizer
134
135 class _WhitelistedVcsClientsForm(formencode.Schema):
136 regexp = r'^(?:\s*[<>=~^!]*\s*\d{1,2}\.\d{1,2}(?:\.\d{1,2})?\s*|\*)\s*(?:,\s*[<>=~^!]*\s*\d{1,2}\.\d{1,2}(?:\.\d{1,2})?\s*|\s*\*\s*)*$'
137 allow_extra_fields = True
138 filter_extra_fields = True
139 git = v.Regex(regexp)
140 hg = v.Regex(regexp)
141 svn = v.Regex(regexp)
142
143 return _WhitelistedVcsClientsForm
144
145
132 def UserForm(localizer, edit=False, available_languages=None, old_data=None):
146 def UserForm(localizer, edit=False, available_languages=None, old_data=None):
133 old_data = old_data or {}
147 old_data = old_data or {}
134 available_languages = available_languages or []
148 available_languages = available_languages or []
135 _ = localizer
149 _ = localizer
136
150
137 class _UserForm(formencode.Schema):
151 class _UserForm(formencode.Schema):
138 allow_extra_fields = True
152 allow_extra_fields = True
139 filter_extra_fields = True
153 filter_extra_fields = True
140 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
154 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
141 v.ValidUsername(localizer, edit, old_data))
155 v.ValidUsername(localizer, edit, old_data))
142 if edit:
156 if edit:
143 new_password = All(
157 new_password = All(
144 v.ValidPassword(localizer),
158 v.ValidPassword(localizer),
145 v.UnicodeString(strip=False, min=6, max=72, not_empty=False)
159 v.UnicodeString(strip=False, min=6, max=72, not_empty=False)
146 )
160 )
147 password_confirmation = All(
161 password_confirmation = All(
148 v.ValidPassword(localizer),
162 v.ValidPassword(localizer),
149 v.UnicodeString(strip=False, min=6, max=72, not_empty=False),
163 v.UnicodeString(strip=False, min=6, max=72, not_empty=False),
150 )
164 )
151 admin = v.StringBoolean(if_missing=False)
165 admin = v.StringBoolean(if_missing=False)
152 else:
166 else:
153 password = All(
167 password = All(
154 v.ValidPassword(localizer),
168 v.ValidPassword(localizer),
155 v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
169 v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
156 )
170 )
157 password_confirmation = All(
171 password_confirmation = All(
158 v.ValidPassword(localizer),
172 v.ValidPassword(localizer),
159 v.UnicodeString(strip=False, min=6, max=72, not_empty=False)
173 v.UnicodeString(strip=False, min=6, max=72, not_empty=False)
160 )
174 )
161
175
162 password_change = v.StringBoolean(if_missing=False)
176 password_change = v.StringBoolean(if_missing=False)
163 create_repo_group = v.StringBoolean(if_missing=False)
177 create_repo_group = v.StringBoolean(if_missing=False)
164
178
165 active = v.StringBoolean(if_missing=False)
179 active = v.StringBoolean(if_missing=False)
166 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
180 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
167 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
181 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
168 email = All(v.UniqSystemEmail(localizer, old_data), v.Email(not_empty=True))
182 email = All(v.UniqSystemEmail(localizer, old_data), v.Email(not_empty=True))
169 description = v.UnicodeString(strip=True, min=1, max=250, not_empty=False,
183 description = v.UnicodeString(strip=True, min=1, max=250, not_empty=False,
170 if_missing='')
184 if_missing='')
171 extern_name = v.UnicodeString(strip=True)
185 extern_name = v.UnicodeString(strip=True)
172 extern_type = v.UnicodeString(strip=True)
186 extern_type = v.UnicodeString(strip=True)
173 language = v.OneOf(available_languages, hideList=False,
187 language = v.OneOf(available_languages, hideList=False,
174 testValueList=True, if_missing=None)
188 testValueList=True, if_missing=None)
175 chained_validators = [v.ValidPasswordsMatch(localizer)]
189 chained_validators = [v.ValidPasswordsMatch(localizer)]
176 return _UserForm
190 return _UserForm
177
191
178
192
179 def UserGroupForm(localizer, edit=False, old_data=None, allow_disabled=False):
193 def UserGroupForm(localizer, edit=False, old_data=None, allow_disabled=False):
180 old_data = old_data or {}
194 old_data = old_data or {}
181 _ = localizer
195 _ = localizer
182
196
183 class _UserGroupForm(formencode.Schema):
197 class _UserGroupForm(formencode.Schema):
184 allow_extra_fields = True
198 allow_extra_fields = True
185 filter_extra_fields = True
199 filter_extra_fields = True
186
200
187 users_group_name = All(
201 users_group_name = All(
188 v.UnicodeString(strip=True, min=1, not_empty=True),
202 v.UnicodeString(strip=True, min=1, not_empty=True),
189 v.ValidUserGroup(localizer, edit, old_data)
203 v.ValidUserGroup(localizer, edit, old_data)
190 )
204 )
191 user_group_description = v.UnicodeString(strip=True, min=1,
205 user_group_description = v.UnicodeString(strip=True, min=1,
192 not_empty=False)
206 not_empty=False)
193
207
194 users_group_active = v.StringBoolean(if_missing=False)
208 users_group_active = v.StringBoolean(if_missing=False)
195
209
196 if edit:
210 if edit:
197 # this is user group owner
211 # this is user group owner
198 user = All(
212 user = All(
199 v.UnicodeString(not_empty=True),
213 v.UnicodeString(not_empty=True),
200 v.ValidRepoUser(localizer, allow_disabled))
214 v.ValidRepoUser(localizer, allow_disabled))
201 return _UserGroupForm
215 return _UserGroupForm
202
216
203
217
204 def RepoGroupForm(localizer, edit=False, old_data=None, available_groups=None,
218 def RepoGroupForm(localizer, edit=False, old_data=None, available_groups=None,
205 can_create_in_root=False, allow_disabled=False):
219 can_create_in_root=False, allow_disabled=False):
206 _ = localizer
220 _ = localizer
207 old_data = old_data or {}
221 old_data = old_data or {}
208 available_groups = available_groups or []
222 available_groups = available_groups or []
209
223
210 class _RepoGroupForm(formencode.Schema):
224 class _RepoGroupForm(formencode.Schema):
211 allow_extra_fields = True
225 allow_extra_fields = True
212 filter_extra_fields = False
226 filter_extra_fields = False
213
227
214 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
228 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
215 v.SlugifyName(localizer),)
229 v.SlugifyName(localizer),)
216 group_description = v.UnicodeString(strip=True, min=1,
230 group_description = v.UnicodeString(strip=True, min=1,
217 not_empty=False)
231 not_empty=False)
218 group_copy_permissions = v.StringBoolean(if_missing=False)
232 group_copy_permissions = v.StringBoolean(if_missing=False)
219
233
220 group_parent_id = v.OneOf(available_groups, hideList=False,
234 group_parent_id = v.OneOf(available_groups, hideList=False,
221 testValueList=True, not_empty=True)
235 testValueList=True, not_empty=True)
222 enable_locking = v.StringBoolean(if_missing=False)
236 enable_locking = v.StringBoolean(if_missing=False)
223 chained_validators = [
237 chained_validators = [
224 v.ValidRepoGroup(localizer, edit, old_data, can_create_in_root)]
238 v.ValidRepoGroup(localizer, edit, old_data, can_create_in_root)]
225
239
226 if edit:
240 if edit:
227 # this is repo group owner
241 # this is repo group owner
228 user = All(
242 user = All(
229 v.UnicodeString(not_empty=True),
243 v.UnicodeString(not_empty=True),
230 v.ValidRepoUser(localizer, allow_disabled))
244 v.ValidRepoUser(localizer, allow_disabled))
231 return _RepoGroupForm
245 return _RepoGroupForm
232
246
233
247
234 def RegisterForm(localizer, edit=False, old_data=None):
248 def RegisterForm(localizer, edit=False, old_data=None):
235 _ = localizer
249 _ = localizer
236 old_data = old_data or {}
250 old_data = old_data or {}
237
251
238 class _RegisterForm(formencode.Schema):
252 class _RegisterForm(formencode.Schema):
239 allow_extra_fields = True
253 allow_extra_fields = True
240 filter_extra_fields = True
254 filter_extra_fields = True
241 username = All(
255 username = All(
242 v.ValidUsername(localizer, edit, old_data),
256 v.ValidUsername(localizer, edit, old_data),
243 v.UnicodeString(strip=True, min=1, not_empty=True)
257 v.UnicodeString(strip=True, min=1, not_empty=True)
244 )
258 )
245 password = All(
259 password = All(
246 v.ValidPassword(localizer),
260 v.ValidPassword(localizer),
247 v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
261 v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
248 )
262 )
249 password_confirmation = All(
263 password_confirmation = All(
250 v.ValidPassword(localizer),
264 v.ValidPassword(localizer),
251 v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
265 v.UnicodeString(strip=False, min=6, max=72, not_empty=True)
252 )
266 )
253 active = v.StringBoolean(if_missing=False)
267 active = v.StringBoolean(if_missing=False)
254 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
268 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
255 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
269 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
256 email = All(v.UniqSystemEmail(localizer, old_data), v.Email(not_empty=True))
270 email = All(v.UniqSystemEmail(localizer, old_data), v.Email(not_empty=True))
257
271
258 chained_validators = [v.ValidPasswordsMatch(localizer)]
272 chained_validators = [v.ValidPasswordsMatch(localizer)]
259 return _RegisterForm
273 return _RegisterForm
260
274
261
275
262 def PasswordResetForm(localizer):
276 def PasswordResetForm(localizer):
263 _ = localizer
277 _ = localizer
264
278
265 class _PasswordResetForm(formencode.Schema):
279 class _PasswordResetForm(formencode.Schema):
266 allow_extra_fields = True
280 allow_extra_fields = True
267 filter_extra_fields = True
281 filter_extra_fields = True
268 email = All(v.ValidSystemEmail(localizer), v.Email(not_empty=True))
282 email = All(v.ValidSystemEmail(localizer), v.Email(not_empty=True))
269 return _PasswordResetForm
283 return _PasswordResetForm
270
284
271
285
272 def RepoForm(localizer, edit=False, old_data=None, repo_groups=None, allow_disabled=False):
286 def RepoForm(localizer, edit=False, old_data=None, repo_groups=None, allow_disabled=False):
273 _ = localizer
287 _ = localizer
274 old_data = old_data or {}
288 old_data = old_data or {}
275 repo_groups = repo_groups or []
289 repo_groups = repo_groups or []
276 supported_backends = BACKENDS.keys()
290 supported_backends = BACKENDS.keys()
277
291
278 class _RepoForm(formencode.Schema):
292 class _RepoForm(formencode.Schema):
279 allow_extra_fields = True
293 allow_extra_fields = True
280 filter_extra_fields = False
294 filter_extra_fields = False
281 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
295 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
282 v.SlugifyName(localizer), v.CannotHaveGitSuffix(localizer))
296 v.SlugifyName(localizer), v.CannotHaveGitSuffix(localizer))
283 repo_group = All(v.CanWriteGroup(localizer, old_data),
297 repo_group = All(v.CanWriteGroup(localizer, old_data),
284 v.OneOf(repo_groups, hideList=True))
298 v.OneOf(repo_groups, hideList=True))
285 repo_type = v.OneOf(supported_backends, required=False,
299 repo_type = v.OneOf(supported_backends, required=False,
286 if_missing=old_data.get('repo_type'))
300 if_missing=old_data.get('repo_type'))
287 repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
301 repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
288 repo_private = v.StringBoolean(if_missing=False)
302 repo_private = v.StringBoolean(if_missing=False)
289 repo_copy_permissions = v.StringBoolean(if_missing=False)
303 repo_copy_permissions = v.StringBoolean(if_missing=False)
290 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
304 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
291
305
292 repo_enable_statistics = v.StringBoolean(if_missing=False)
306 repo_enable_statistics = v.StringBoolean(if_missing=False)
293 repo_enable_downloads = v.StringBoolean(if_missing=False)
307 repo_enable_downloads = v.StringBoolean(if_missing=False)
294 repo_enable_locking = v.StringBoolean(if_missing=False)
308 repo_enable_locking = v.StringBoolean(if_missing=False)
295
309
296 if edit:
310 if edit:
297 # this is repo owner
311 # this is repo owner
298 user = All(
312 user = All(
299 v.UnicodeString(not_empty=True),
313 v.UnicodeString(not_empty=True),
300 v.ValidRepoUser(localizer, allow_disabled))
314 v.ValidRepoUser(localizer, allow_disabled))
301 clone_uri_change = v.UnicodeString(
315 clone_uri_change = v.UnicodeString(
302 not_empty=False, if_missing=v.Missing)
316 not_empty=False, if_missing=v.Missing)
303
317
304 chained_validators = [v.ValidCloneUri(localizer),
318 chained_validators = [v.ValidCloneUri(localizer),
305 v.ValidRepoName(localizer, edit, old_data)]
319 v.ValidRepoName(localizer, edit, old_data)]
306 return _RepoForm
320 return _RepoForm
307
321
308
322
309 def RepoPermsForm(localizer):
323 def RepoPermsForm(localizer):
310 _ = localizer
324 _ = localizer
311
325
312 class _RepoPermsForm(formencode.Schema):
326 class _RepoPermsForm(formencode.Schema):
313 allow_extra_fields = True
327 allow_extra_fields = True
314 filter_extra_fields = False
328 filter_extra_fields = False
315 chained_validators = [v.ValidPerms(localizer, type_='repo')]
329 chained_validators = [v.ValidPerms(localizer, type_='repo')]
316 return _RepoPermsForm
330 return _RepoPermsForm
317
331
318
332
319 def RepoGroupPermsForm(localizer, valid_recursive_choices):
333 def RepoGroupPermsForm(localizer, valid_recursive_choices):
320 _ = localizer
334 _ = localizer
321
335
322 class _RepoGroupPermsForm(formencode.Schema):
336 class _RepoGroupPermsForm(formencode.Schema):
323 allow_extra_fields = True
337 allow_extra_fields = True
324 filter_extra_fields = False
338 filter_extra_fields = False
325 recursive = v.OneOf(valid_recursive_choices)
339 recursive = v.OneOf(valid_recursive_choices)
326 chained_validators = [v.ValidPerms(localizer, type_='repo_group')]
340 chained_validators = [v.ValidPerms(localizer, type_='repo_group')]
327 return _RepoGroupPermsForm
341 return _RepoGroupPermsForm
328
342
329
343
330 def UserGroupPermsForm(localizer):
344 def UserGroupPermsForm(localizer):
331 _ = localizer
345 _ = localizer
332
346
333 class _UserPermsForm(formencode.Schema):
347 class _UserPermsForm(formencode.Schema):
334 allow_extra_fields = True
348 allow_extra_fields = True
335 filter_extra_fields = False
349 filter_extra_fields = False
336 chained_validators = [v.ValidPerms(localizer, type_='user_group')]
350 chained_validators = [v.ValidPerms(localizer, type_='user_group')]
337 return _UserPermsForm
351 return _UserPermsForm
338
352
339
353
340 def RepoFieldForm(localizer):
354 def RepoFieldForm(localizer):
341 _ = localizer
355 _ = localizer
342
356
343 class _RepoFieldForm(formencode.Schema):
357 class _RepoFieldForm(formencode.Schema):
344 filter_extra_fields = True
358 filter_extra_fields = True
345 allow_extra_fields = True
359 allow_extra_fields = True
346
360
347 new_field_key = All(v.FieldKey(localizer),
361 new_field_key = All(v.FieldKey(localizer),
348 v.UnicodeString(strip=True, min=3, not_empty=True))
362 v.UnicodeString(strip=True, min=3, not_empty=True))
349 new_field_value = v.UnicodeString(not_empty=False, if_missing='')
363 new_field_value = v.UnicodeString(not_empty=False, if_missing='')
350 new_field_type = v.OneOf(['str', 'unicode', 'list', 'tuple'],
364 new_field_type = v.OneOf(['str', 'unicode', 'list', 'tuple'],
351 if_missing='str')
365 if_missing='str')
352 new_field_label = v.UnicodeString(not_empty=False)
366 new_field_label = v.UnicodeString(not_empty=False)
353 new_field_desc = v.UnicodeString(not_empty=False)
367 new_field_desc = v.UnicodeString(not_empty=False)
354 return _RepoFieldForm
368 return _RepoFieldForm
355
369
356
370
357 def RepoForkForm(localizer, edit=False, old_data=None,
371 def RepoForkForm(localizer, edit=False, old_data=None,
358 supported_backends=BACKENDS.keys(), repo_groups=None):
372 supported_backends=BACKENDS.keys(), repo_groups=None):
359 _ = localizer
373 _ = localizer
360 old_data = old_data or {}
374 old_data = old_data or {}
361 repo_groups = repo_groups or []
375 repo_groups = repo_groups or []
362
376
363 class _RepoForkForm(formencode.Schema):
377 class _RepoForkForm(formencode.Schema):
364 allow_extra_fields = True
378 allow_extra_fields = True
365 filter_extra_fields = False
379 filter_extra_fields = False
366 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
380 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
367 v.SlugifyName(localizer))
381 v.SlugifyName(localizer))
368 repo_group = All(v.CanWriteGroup(localizer, ),
382 repo_group = All(v.CanWriteGroup(localizer, ),
369 v.OneOf(repo_groups, hideList=True))
383 v.OneOf(repo_groups, hideList=True))
370 repo_type = All(v.ValidForkType(localizer, old_data), v.OneOf(supported_backends))
384 repo_type = All(v.ValidForkType(localizer, old_data), v.OneOf(supported_backends))
371 description = v.UnicodeString(strip=True, min=1, not_empty=True)
385 description = v.UnicodeString(strip=True, min=1, not_empty=True)
372 private = v.StringBoolean(if_missing=False)
386 private = v.StringBoolean(if_missing=False)
373 copy_permissions = v.StringBoolean(if_missing=False)
387 copy_permissions = v.StringBoolean(if_missing=False)
374 fork_parent_id = v.UnicodeString()
388 fork_parent_id = v.UnicodeString()
375 chained_validators = [v.ValidForkName(localizer, edit, old_data)]
389 chained_validators = [v.ValidForkName(localizer, edit, old_data)]
376 return _RepoForkForm
390 return _RepoForkForm
377
391
378
392
379 def ApplicationSettingsForm(localizer):
393 def ApplicationSettingsForm(localizer):
380 _ = localizer
394 _ = localizer
381
395
382 class _ApplicationSettingsForm(formencode.Schema):
396 class _ApplicationSettingsForm(formencode.Schema):
383 allow_extra_fields = True
397 allow_extra_fields = True
384 filter_extra_fields = False
398 filter_extra_fields = False
385 rhodecode_title = v.UnicodeString(strip=True, max=40, not_empty=False)
399 rhodecode_title = v.UnicodeString(strip=True, max=40, not_empty=False)
386 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
400 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
387 rhodecode_pre_code = v.UnicodeString(strip=True, min=1, not_empty=False)
401 rhodecode_pre_code = v.UnicodeString(strip=True, min=1, not_empty=False)
388 rhodecode_post_code = v.UnicodeString(strip=True, min=1, not_empty=False)
402 rhodecode_post_code = v.UnicodeString(strip=True, min=1, not_empty=False)
389 rhodecode_captcha_public_key = v.UnicodeString(strip=True, min=1, not_empty=False)
403 rhodecode_captcha_public_key = v.UnicodeString(strip=True, min=1, not_empty=False)
390 rhodecode_captcha_private_key = v.UnicodeString(strip=True, min=1, not_empty=False)
404 rhodecode_captcha_private_key = v.UnicodeString(strip=True, min=1, not_empty=False)
391 rhodecode_create_personal_repo_group = v.StringBoolean(if_missing=False)
405 rhodecode_create_personal_repo_group = v.StringBoolean(if_missing=False)
392 rhodecode_personal_repo_group_pattern = v.UnicodeString(strip=True, min=1, not_empty=False)
406 rhodecode_personal_repo_group_pattern = v.UnicodeString(strip=True, min=1, not_empty=False)
393 return _ApplicationSettingsForm
407 return _ApplicationSettingsForm
394
408
395
409
396 def ApplicationVisualisationForm(localizer):
410 def ApplicationVisualisationForm(localizer):
397 from rhodecode.model.db import Repository
411 from rhodecode.model.db import Repository
398 _ = localizer
412 _ = localizer
399
413
400 class _ApplicationVisualisationForm(formencode.Schema):
414 class _ApplicationVisualisationForm(formencode.Schema):
401 allow_extra_fields = True
415 allow_extra_fields = True
402 filter_extra_fields = False
416 filter_extra_fields = False
403 rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
417 rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
404 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
418 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
405 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
419 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
406
420
407 rhodecode_repository_fields = v.StringBoolean(if_missing=False)
421 rhodecode_repository_fields = v.StringBoolean(if_missing=False)
408 rhodecode_lightweight_journal = v.StringBoolean(if_missing=False)
422 rhodecode_lightweight_journal = v.StringBoolean(if_missing=False)
409 rhodecode_dashboard_items = v.Int(min=5, not_empty=True)
423 rhodecode_dashboard_items = v.Int(min=5, not_empty=True)
410 rhodecode_admin_grid_items = v.Int(min=5, not_empty=True)
424 rhodecode_admin_grid_items = v.Int(min=5, not_empty=True)
411 rhodecode_show_version = v.StringBoolean(if_missing=False)
425 rhodecode_show_version = v.StringBoolean(if_missing=False)
412 rhodecode_use_gravatar = v.StringBoolean(if_missing=False)
426 rhodecode_use_gravatar = v.StringBoolean(if_missing=False)
413 rhodecode_markup_renderer = v.OneOf(['markdown', 'rst'])
427 rhodecode_markup_renderer = v.OneOf(['markdown', 'rst'])
414 rhodecode_gravatar_url = v.UnicodeString(min=3)
428 rhodecode_gravatar_url = v.UnicodeString(min=3)
415 rhodecode_clone_uri_tmpl = v.UnicodeString(not_empty=False, if_empty=Repository.DEFAULT_CLONE_URI)
429 rhodecode_clone_uri_tmpl = v.UnicodeString(not_empty=False, if_empty=Repository.DEFAULT_CLONE_URI)
416 rhodecode_clone_uri_id_tmpl = v.UnicodeString(not_empty=False, if_empty=Repository.DEFAULT_CLONE_URI_ID)
430 rhodecode_clone_uri_id_tmpl = v.UnicodeString(not_empty=False, if_empty=Repository.DEFAULT_CLONE_URI_ID)
417 rhodecode_clone_uri_ssh_tmpl = v.UnicodeString(not_empty=False, if_empty=Repository.DEFAULT_CLONE_URI_SSH)
431 rhodecode_clone_uri_ssh_tmpl = v.UnicodeString(not_empty=False, if_empty=Repository.DEFAULT_CLONE_URI_SSH)
418 rhodecode_support_url = v.UnicodeString()
432 rhodecode_support_url = v.UnicodeString()
419 rhodecode_show_revision_number = v.StringBoolean(if_missing=False)
433 rhodecode_show_revision_number = v.StringBoolean(if_missing=False)
420 rhodecode_show_sha_length = v.Int(min=4, not_empty=True)
434 rhodecode_show_sha_length = v.Int(min=4, not_empty=True)
421 return _ApplicationVisualisationForm
435 return _ApplicationVisualisationForm
422
436
423
437
424 class _BaseVcsSettingsForm(formencode.Schema):
438 class _BaseVcsSettingsForm(formencode.Schema):
425
439
426 allow_extra_fields = True
440 allow_extra_fields = True
427 filter_extra_fields = False
441 filter_extra_fields = False
428 hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
442 hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
429 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
443 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
430 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
444 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
431
445
432 # PR/Code-review
446 # PR/Code-review
433 rhodecode_pr_merge_enabled = v.StringBoolean(if_missing=False)
447 rhodecode_pr_merge_enabled = v.StringBoolean(if_missing=False)
434 rhodecode_use_outdated_comments = v.StringBoolean(if_missing=False)
448 rhodecode_use_outdated_comments = v.StringBoolean(if_missing=False)
435
449
436 # hg
450 # hg
437 extensions_largefiles = v.StringBoolean(if_missing=False)
451 extensions_largefiles = v.StringBoolean(if_missing=False)
438 extensions_evolve = v.StringBoolean(if_missing=False)
452 extensions_evolve = v.StringBoolean(if_missing=False)
439 phases_publish = v.StringBoolean(if_missing=False)
453 phases_publish = v.StringBoolean(if_missing=False)
440
454
441 rhodecode_hg_use_rebase_for_merging = v.StringBoolean(if_missing=False)
455 rhodecode_hg_use_rebase_for_merging = v.StringBoolean(if_missing=False)
442 rhodecode_hg_close_branch_before_merging = v.StringBoolean(if_missing=False)
456 rhodecode_hg_close_branch_before_merging = v.StringBoolean(if_missing=False)
443
457
444 # git
458 # git
445 vcs_git_lfs_enabled = v.StringBoolean(if_missing=False)
459 vcs_git_lfs_enabled = v.StringBoolean(if_missing=False)
446 rhodecode_git_use_rebase_for_merging = v.StringBoolean(if_missing=False)
460 rhodecode_git_use_rebase_for_merging = v.StringBoolean(if_missing=False)
447 rhodecode_git_close_branch_before_merging = v.StringBoolean(if_missing=False)
461 rhodecode_git_close_branch_before_merging = v.StringBoolean(if_missing=False)
448
462
449 # cache
463 # cache
450 rhodecode_diff_cache = v.StringBoolean(if_missing=False)
464 rhodecode_diff_cache = v.StringBoolean(if_missing=False)
451
465
452
466
453 def ApplicationUiSettingsForm(localizer):
467 def ApplicationUiSettingsForm(localizer):
454 _ = localizer
468 _ = localizer
455
469
456 class _ApplicationUiSettingsForm(_BaseVcsSettingsForm):
470 class _ApplicationUiSettingsForm(_BaseVcsSettingsForm):
457 web_push_ssl = v.StringBoolean(if_missing=False)
471 web_push_ssl = v.StringBoolean(if_missing=False)
458 largefiles_usercache = All(
472 largefiles_usercache = All(
459 v.ValidPath(localizer),
473 v.ValidPath(localizer),
460 v.UnicodeString(strip=True, min=2, not_empty=True))
474 v.UnicodeString(strip=True, min=2, not_empty=True))
461 vcs_git_lfs_store_location = All(
475 vcs_git_lfs_store_location = All(
462 v.ValidPath(localizer),
476 v.ValidPath(localizer),
463 v.UnicodeString(strip=True, min=2, not_empty=True))
477 v.UnicodeString(strip=True, min=2, not_empty=True))
464 extensions_hggit = v.StringBoolean(if_missing=False)
478 extensions_hggit = v.StringBoolean(if_missing=False)
465 new_svn_branch = v.ValidSvnPattern(localizer, section='vcs_svn_branch')
479 new_svn_branch = v.ValidSvnPattern(localizer, section='vcs_svn_branch')
466 new_svn_tag = v.ValidSvnPattern(localizer, section='vcs_svn_tag')
480 new_svn_tag = v.ValidSvnPattern(localizer, section='vcs_svn_tag')
467 return _ApplicationUiSettingsForm
481 return _ApplicationUiSettingsForm
468
482
469
483
470 def RepoVcsSettingsForm(localizer, repo_name):
484 def RepoVcsSettingsForm(localizer, repo_name):
471 _ = localizer
485 _ = localizer
472
486
473 class _RepoVcsSettingsForm(_BaseVcsSettingsForm):
487 class _RepoVcsSettingsForm(_BaseVcsSettingsForm):
474 inherit_global_settings = v.StringBoolean(if_missing=False)
488 inherit_global_settings = v.StringBoolean(if_missing=False)
475 new_svn_branch = v.ValidSvnPattern(localizer,
489 new_svn_branch = v.ValidSvnPattern(localizer,
476 section='vcs_svn_branch', repo_name=repo_name)
490 section='vcs_svn_branch', repo_name=repo_name)
477 new_svn_tag = v.ValidSvnPattern(localizer,
491 new_svn_tag = v.ValidSvnPattern(localizer,
478 section='vcs_svn_tag', repo_name=repo_name)
492 section='vcs_svn_tag', repo_name=repo_name)
479 return _RepoVcsSettingsForm
493 return _RepoVcsSettingsForm
480
494
481
495
482 def LabsSettingsForm(localizer):
496 def LabsSettingsForm(localizer):
483 _ = localizer
497 _ = localizer
484
498
485 class _LabSettingsForm(formencode.Schema):
499 class _LabSettingsForm(formencode.Schema):
486 allow_extra_fields = True
500 allow_extra_fields = True
487 filter_extra_fields = False
501 filter_extra_fields = False
488 return _LabSettingsForm
502 return _LabSettingsForm
489
503
490
504
491 def ApplicationPermissionsForm(
505 def ApplicationPermissionsForm(
492 localizer, register_choices, password_reset_choices,
506 localizer, register_choices, password_reset_choices,
493 extern_activate_choices):
507 extern_activate_choices):
494 _ = localizer
508 _ = localizer
495
509
496 class _DefaultPermissionsForm(formencode.Schema):
510 class _DefaultPermissionsForm(formencode.Schema):
497 allow_extra_fields = True
511 allow_extra_fields = True
498 filter_extra_fields = True
512 filter_extra_fields = True
499
513
500 anonymous = v.StringBoolean(if_missing=False)
514 anonymous = v.StringBoolean(if_missing=False)
501 default_register = v.OneOf(register_choices)
515 default_register = v.OneOf(register_choices)
502 default_register_message = v.UnicodeString()
516 default_register_message = v.UnicodeString()
503 default_password_reset = v.OneOf(password_reset_choices)
517 default_password_reset = v.OneOf(password_reset_choices)
504 default_extern_activate = v.OneOf(extern_activate_choices)
518 default_extern_activate = v.OneOf(extern_activate_choices)
505 return _DefaultPermissionsForm
519 return _DefaultPermissionsForm
506
520
507
521
508 def ObjectPermissionsForm(localizer, repo_perms_choices, group_perms_choices,
522 def ObjectPermissionsForm(localizer, repo_perms_choices, group_perms_choices,
509 user_group_perms_choices):
523 user_group_perms_choices):
510 _ = localizer
524 _ = localizer
511
525
512 class _ObjectPermissionsForm(formencode.Schema):
526 class _ObjectPermissionsForm(formencode.Schema):
513 allow_extra_fields = True
527 allow_extra_fields = True
514 filter_extra_fields = True
528 filter_extra_fields = True
515 overwrite_default_repo = v.StringBoolean(if_missing=False)
529 overwrite_default_repo = v.StringBoolean(if_missing=False)
516 overwrite_default_group = v.StringBoolean(if_missing=False)
530 overwrite_default_group = v.StringBoolean(if_missing=False)
517 overwrite_default_user_group = v.StringBoolean(if_missing=False)
531 overwrite_default_user_group = v.StringBoolean(if_missing=False)
518
532
519 default_repo_perm = v.OneOf(repo_perms_choices)
533 default_repo_perm = v.OneOf(repo_perms_choices)
520 default_group_perm = v.OneOf(group_perms_choices)
534 default_group_perm = v.OneOf(group_perms_choices)
521 default_user_group_perm = v.OneOf(user_group_perms_choices)
535 default_user_group_perm = v.OneOf(user_group_perms_choices)
522
536
523 return _ObjectPermissionsForm
537 return _ObjectPermissionsForm
524
538
525
539
526 def BranchPermissionsForm(localizer, branch_perms_choices):
540 def BranchPermissionsForm(localizer, branch_perms_choices):
527 _ = localizer
541 _ = localizer
528
542
529 class _BranchPermissionsForm(formencode.Schema):
543 class _BranchPermissionsForm(formencode.Schema):
530 allow_extra_fields = True
544 allow_extra_fields = True
531 filter_extra_fields = True
545 filter_extra_fields = True
532 overwrite_default_branch = v.StringBoolean(if_missing=False)
546 overwrite_default_branch = v.StringBoolean(if_missing=False)
533 default_branch_perm = v.OneOf(branch_perms_choices)
547 default_branch_perm = v.OneOf(branch_perms_choices)
534
548
535 return _BranchPermissionsForm
549 return _BranchPermissionsForm
536
550
537
551
538 def UserPermissionsForm(localizer, create_choices, create_on_write_choices,
552 def UserPermissionsForm(localizer, create_choices, create_on_write_choices,
539 repo_group_create_choices, user_group_create_choices,
553 repo_group_create_choices, user_group_create_choices,
540 fork_choices, inherit_default_permissions_choices):
554 fork_choices, inherit_default_permissions_choices):
541 _ = localizer
555 _ = localizer
542
556
543 class _DefaultPermissionsForm(formencode.Schema):
557 class _DefaultPermissionsForm(formencode.Schema):
544 allow_extra_fields = True
558 allow_extra_fields = True
545 filter_extra_fields = True
559 filter_extra_fields = True
546
560
547 anonymous = v.StringBoolean(if_missing=False)
561 anonymous = v.StringBoolean(if_missing=False)
548
562
549 default_repo_create = v.OneOf(create_choices)
563 default_repo_create = v.OneOf(create_choices)
550 default_repo_create_on_write = v.OneOf(create_on_write_choices)
564 default_repo_create_on_write = v.OneOf(create_on_write_choices)
551 default_user_group_create = v.OneOf(user_group_create_choices)
565 default_user_group_create = v.OneOf(user_group_create_choices)
552 default_repo_group_create = v.OneOf(repo_group_create_choices)
566 default_repo_group_create = v.OneOf(repo_group_create_choices)
553 default_fork_create = v.OneOf(fork_choices)
567 default_fork_create = v.OneOf(fork_choices)
554 default_inherit_default_permissions = v.OneOf(inherit_default_permissions_choices)
568 default_inherit_default_permissions = v.OneOf(inherit_default_permissions_choices)
555 return _DefaultPermissionsForm
569 return _DefaultPermissionsForm
556
570
557
571
558 def UserIndividualPermissionsForm(localizer):
572 def UserIndividualPermissionsForm(localizer):
559 _ = localizer
573 _ = localizer
560
574
561 class _DefaultPermissionsForm(formencode.Schema):
575 class _DefaultPermissionsForm(formencode.Schema):
562 allow_extra_fields = True
576 allow_extra_fields = True
563 filter_extra_fields = True
577 filter_extra_fields = True
564
578
565 inherit_default_permissions = v.StringBoolean(if_missing=False)
579 inherit_default_permissions = v.StringBoolean(if_missing=False)
566 return _DefaultPermissionsForm
580 return _DefaultPermissionsForm
567
581
568
582
569 def DefaultsForm(localizer, edit=False, old_data=None, supported_backends=BACKENDS.keys()):
583 def DefaultsForm(localizer, edit=False, old_data=None, supported_backends=BACKENDS.keys()):
570 _ = localizer
584 _ = localizer
571 old_data = old_data or {}
585 old_data = old_data or {}
572
586
573 class _DefaultsForm(formencode.Schema):
587 class _DefaultsForm(formencode.Schema):
574 allow_extra_fields = True
588 allow_extra_fields = True
575 filter_extra_fields = True
589 filter_extra_fields = True
576 default_repo_type = v.OneOf(supported_backends)
590 default_repo_type = v.OneOf(supported_backends)
577 default_repo_private = v.StringBoolean(if_missing=False)
591 default_repo_private = v.StringBoolean(if_missing=False)
578 default_repo_enable_statistics = v.StringBoolean(if_missing=False)
592 default_repo_enable_statistics = v.StringBoolean(if_missing=False)
579 default_repo_enable_downloads = v.StringBoolean(if_missing=False)
593 default_repo_enable_downloads = v.StringBoolean(if_missing=False)
580 default_repo_enable_locking = v.StringBoolean(if_missing=False)
594 default_repo_enable_locking = v.StringBoolean(if_missing=False)
581 return _DefaultsForm
595 return _DefaultsForm
582
596
583
597
584 def AuthSettingsForm(localizer):
598 def AuthSettingsForm(localizer):
585 _ = localizer
599 _ = localizer
586
600
587 class _AuthSettingsForm(formencode.Schema):
601 class _AuthSettingsForm(formencode.Schema):
588 allow_extra_fields = True
602 allow_extra_fields = True
589 filter_extra_fields = True
603 filter_extra_fields = True
590 auth_plugins = All(v.ValidAuthPlugins(localizer),
604 auth_plugins = All(v.ValidAuthPlugins(localizer),
591 v.UniqueListFromString(localizer)(not_empty=True))
605 v.UniqueListFromString(localizer)(not_empty=True))
592 return _AuthSettingsForm
606 return _AuthSettingsForm
593
607
594
608
595 def UserExtraEmailForm(localizer):
609 def UserExtraEmailForm(localizer):
596 _ = localizer
610 _ = localizer
597
611
598 class _UserExtraEmailForm(formencode.Schema):
612 class _UserExtraEmailForm(formencode.Schema):
599 email = All(v.UniqSystemEmail(localizer), v.Email(not_empty=True))
613 email = All(v.UniqSystemEmail(localizer), v.Email(not_empty=True))
600 return _UserExtraEmailForm
614 return _UserExtraEmailForm
601
615
602
616
603 def UserExtraIpForm(localizer):
617 def UserExtraIpForm(localizer):
604 _ = localizer
618 _ = localizer
605
619
606 class _UserExtraIpForm(formencode.Schema):
620 class _UserExtraIpForm(formencode.Schema):
607 ip = v.ValidIp(localizer)(not_empty=True)
621 ip = v.ValidIp(localizer)(not_empty=True)
608 return _UserExtraIpForm
622 return _UserExtraIpForm
609
623
610
624
611 def PullRequestForm(localizer, repo_id):
625 def PullRequestForm(localizer, repo_id):
612 _ = localizer
626 _ = localizer
613
627
614 class ReviewerForm(formencode.Schema):
628 class ReviewerForm(formencode.Schema):
615 user_id = v.Int(not_empty=True)
629 user_id = v.Int(not_empty=True)
616 reasons = All()
630 reasons = All()
617 rules = All(v.UniqueList(localizer, convert=int)())
631 rules = All(v.UniqueList(localizer, convert=int)())
618 mandatory = v.StringBoolean()
632 mandatory = v.StringBoolean()
619 role = v.String(if_missing='reviewer')
633 role = v.String(if_missing='reviewer')
620
634
621 class ObserverForm(formencode.Schema):
635 class ObserverForm(formencode.Schema):
622 user_id = v.Int(not_empty=True)
636 user_id = v.Int(not_empty=True)
623 reasons = All()
637 reasons = All()
624 rules = All(v.UniqueList(localizer, convert=int)())
638 rules = All(v.UniqueList(localizer, convert=int)())
625 mandatory = v.StringBoolean()
639 mandatory = v.StringBoolean()
626 role = v.String(if_missing='observer')
640 role = v.String(if_missing='observer')
627
641
628 class _PullRequestForm(formencode.Schema):
642 class _PullRequestForm(formencode.Schema):
629 allow_extra_fields = True
643 allow_extra_fields = True
630 filter_extra_fields = True
644 filter_extra_fields = True
631
645
632 common_ancestor = v.UnicodeString(strip=True, required=True)
646 common_ancestor = v.UnicodeString(strip=True, required=True)
633 source_repo = v.UnicodeString(strip=True, required=True)
647 source_repo = v.UnicodeString(strip=True, required=True)
634 source_ref = v.UnicodeString(strip=True, required=True)
648 source_ref = v.UnicodeString(strip=True, required=True)
635 target_repo = v.UnicodeString(strip=True, required=True)
649 target_repo = v.UnicodeString(strip=True, required=True)
636 target_ref = v.UnicodeString(strip=True, required=True)
650 target_ref = v.UnicodeString(strip=True, required=True)
637 revisions = All(#v.NotReviewedRevisions(localizer, repo_id)(),
651 revisions = All(#v.NotReviewedRevisions(localizer, repo_id)(),
638 v.UniqueList(localizer)(not_empty=True))
652 v.UniqueList(localizer)(not_empty=True))
639 review_members = formencode.ForEach(ReviewerForm())
653 review_members = formencode.ForEach(ReviewerForm())
640 observer_members = formencode.ForEach(ObserverForm())
654 observer_members = formencode.ForEach(ObserverForm())
641 pullrequest_title = v.UnicodeString(strip=True, required=True, min=1, max=255)
655 pullrequest_title = v.UnicodeString(strip=True, required=True, min=1, max=255)
642 pullrequest_desc = v.UnicodeString(strip=True, required=False)
656 pullrequest_desc = v.UnicodeString(strip=True, required=False)
643 description_renderer = v.UnicodeString(strip=True, required=False)
657 description_renderer = v.UnicodeString(strip=True, required=False)
644
658
645 return _PullRequestForm
659 return _PullRequestForm
646
660
647
661
648 def IssueTrackerPatternsForm(localizer):
662 def IssueTrackerPatternsForm(localizer):
649 _ = localizer
663 _ = localizer
650
664
651 class _IssueTrackerPatternsForm(formencode.Schema):
665 class _IssueTrackerPatternsForm(formencode.Schema):
652 allow_extra_fields = True
666 allow_extra_fields = True
653 filter_extra_fields = False
667 filter_extra_fields = False
654 chained_validators = [v.ValidPattern(localizer)]
668 chained_validators = [v.ValidPattern(localizer)]
655 return _IssueTrackerPatternsForm
669 return _IssueTrackerPatternsForm
@@ -1,421 +1,422 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('admin_artifacts', '/_admin/artifacts', []);
15 pyroutes.register('admin_artifacts', '/_admin/artifacts', []);
16 pyroutes.register('admin_artifacts_data', '/_admin/artifacts-data', []);
16 pyroutes.register('admin_artifacts_data', '/_admin/artifacts-data', []);
17 pyroutes.register('admin_artifacts_delete', '/_admin/artifacts/%(uid)s/delete', ['uid']);
17 pyroutes.register('admin_artifacts_delete', '/_admin/artifacts/%(uid)s/delete', ['uid']);
18 pyroutes.register('admin_artifacts_show_all', '/_admin/artifacts', []);
18 pyroutes.register('admin_artifacts_show_all', '/_admin/artifacts', []);
19 pyroutes.register('admin_artifacts_show_info', '/_admin/artifacts/%(uid)s', ['uid']);
19 pyroutes.register('admin_artifacts_show_info', '/_admin/artifacts/%(uid)s', ['uid']);
20 pyroutes.register('admin_artifacts_update', '/_admin/artifacts/%(uid)s/update', ['uid']);
20 pyroutes.register('admin_artifacts_update', '/_admin/artifacts/%(uid)s/update', ['uid']);
21 pyroutes.register('admin_audit_log_entry', '/_admin/audit_logs/%(audit_log_id)s', ['audit_log_id']);
21 pyroutes.register('admin_audit_log_entry', '/_admin/audit_logs/%(audit_log_id)s', ['audit_log_id']);
22 pyroutes.register('admin_audit_logs', '/_admin/audit_logs', []);
22 pyroutes.register('admin_audit_logs', '/_admin/audit_logs', []);
23 pyroutes.register('admin_automation', '/_admin/automation', []);
23 pyroutes.register('admin_automation', '/_admin/automation', []);
24 pyroutes.register('admin_automation_update', '/_admin/automation/%(entry_id)s/update', ['entry_id']);
24 pyroutes.register('admin_automation_update', '/_admin/automation/%(entry_id)s/update', ['entry_id']);
25 pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []);
25 pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []);
26 pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []);
26 pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []);
27 pyroutes.register('admin_home', '/_admin', []);
27 pyroutes.register('admin_home', '/_admin', []);
28 pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []);
28 pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []);
29 pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []);
29 pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []);
30 pyroutes.register('admin_permissions_auth_token_access', '/_admin/permissions/auth_token_access', []);
30 pyroutes.register('admin_permissions_auth_token_access', '/_admin/permissions/auth_token_access', []);
31 pyroutes.register('admin_permissions_branch', '/_admin/permissions/branch', []);
31 pyroutes.register('admin_permissions_branch', '/_admin/permissions/branch', []);
32 pyroutes.register('admin_permissions_branch_update', '/_admin/permissions/branch/update', []);
32 pyroutes.register('admin_permissions_branch_update', '/_admin/permissions/branch/update', []);
33 pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []);
33 pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []);
34 pyroutes.register('admin_permissions_global_update', '/_admin/permissions/global/update', []);
34 pyroutes.register('admin_permissions_global_update', '/_admin/permissions/global/update', []);
35 pyroutes.register('admin_permissions_ips', '/_admin/permissions/ips', []);
35 pyroutes.register('admin_permissions_ips', '/_admin/permissions/ips', []);
36 pyroutes.register('admin_permissions_object', '/_admin/permissions/object', []);
36 pyroutes.register('admin_permissions_object', '/_admin/permissions/object', []);
37 pyroutes.register('admin_permissions_object_update', '/_admin/permissions/object/update', []);
37 pyroutes.register('admin_permissions_object_update', '/_admin/permissions/object/update', []);
38 pyroutes.register('admin_permissions_overview', '/_admin/permissions/overview', []);
38 pyroutes.register('admin_permissions_overview', '/_admin/permissions/overview', []);
39 pyroutes.register('admin_permissions_ssh_keys', '/_admin/permissions/ssh_keys', []);
39 pyroutes.register('admin_permissions_ssh_keys', '/_admin/permissions/ssh_keys', []);
40 pyroutes.register('admin_permissions_ssh_keys_data', '/_admin/permissions/ssh_keys/data', []);
40 pyroutes.register('admin_permissions_ssh_keys_data', '/_admin/permissions/ssh_keys/data', []);
41 pyroutes.register('admin_permissions_ssh_keys_update', '/_admin/permissions/ssh_keys/update', []);
41 pyroutes.register('admin_permissions_ssh_keys_update', '/_admin/permissions/ssh_keys/update', []);
42 pyroutes.register('admin_scheduler', '/_admin/scheduler', []);
42 pyroutes.register('admin_scheduler', '/_admin/scheduler', []);
43 pyroutes.register('admin_scheduler_show_tasks', '/_admin/scheduler/_tasks', []);
43 pyroutes.register('admin_scheduler_show_tasks', '/_admin/scheduler/_tasks', []);
44 pyroutes.register('admin_settings', '/_admin/settings', []);
44 pyroutes.register('admin_settings', '/_admin/settings', []);
45 pyroutes.register('admin_settings_email', '/_admin/settings/email', []);
45 pyroutes.register('admin_settings_email', '/_admin/settings/email', []);
46 pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []);
46 pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []);
47 pyroutes.register('admin_settings_exception_tracker', '/_admin/settings/exceptions', []);
47 pyroutes.register('admin_settings_exception_tracker', '/_admin/settings/exceptions', []);
48 pyroutes.register('admin_settings_exception_tracker_delete', '/_admin/settings/exceptions/%(exception_id)s/delete', ['exception_id']);
48 pyroutes.register('admin_settings_exception_tracker_delete', '/_admin/settings/exceptions/%(exception_id)s/delete', ['exception_id']);
49 pyroutes.register('admin_settings_exception_tracker_delete_all', '/_admin/settings/exceptions_delete_all', []);
49 pyroutes.register('admin_settings_exception_tracker_delete_all', '/_admin/settings/exceptions_delete_all', []);
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_global', '/_admin/settings/global', []);
51 pyroutes.register('admin_settings_global', '/_admin/settings/global', []);
52 pyroutes.register('admin_settings_global_update', '/_admin/settings/global/update', []);
52 pyroutes.register('admin_settings_global_update', '/_admin/settings/global/update', []);
53 pyroutes.register('admin_settings_hooks', '/_admin/settings/hooks', []);
53 pyroutes.register('admin_settings_hooks', '/_admin/settings/hooks', []);
54 pyroutes.register('admin_settings_hooks_delete', '/_admin/settings/hooks/delete', []);
54 pyroutes.register('admin_settings_hooks_delete', '/_admin/settings/hooks/delete', []);
55 pyroutes.register('admin_settings_hooks_update', '/_admin/settings/hooks/update', []);
55 pyroutes.register('admin_settings_hooks_update', '/_admin/settings/hooks/update', []);
56 pyroutes.register('admin_settings_issuetracker', '/_admin/settings/issue-tracker', []);
56 pyroutes.register('admin_settings_issuetracker', '/_admin/settings/issue-tracker', []);
57 pyroutes.register('admin_settings_issuetracker_delete', '/_admin/settings/issue-tracker/delete', []);
57 pyroutes.register('admin_settings_issuetracker_delete', '/_admin/settings/issue-tracker/delete', []);
58 pyroutes.register('admin_settings_issuetracker_test', '/_admin/settings/issue-tracker/test', []);
58 pyroutes.register('admin_settings_issuetracker_test', '/_admin/settings/issue-tracker/test', []);
59 pyroutes.register('admin_settings_issuetracker_update', '/_admin/settings/issue-tracker/update', []);
59 pyroutes.register('admin_settings_issuetracker_update', '/_admin/settings/issue-tracker/update', []);
60 pyroutes.register('admin_settings_labs', '/_admin/settings/labs', []);
60 pyroutes.register('admin_settings_labs', '/_admin/settings/labs', []);
61 pyroutes.register('admin_settings_labs_update', '/_admin/settings/labs/update', []);
61 pyroutes.register('admin_settings_labs_update', '/_admin/settings/labs/update', []);
62 pyroutes.register('admin_settings_license', '/_admin/settings/license', []);
62 pyroutes.register('admin_settings_license', '/_admin/settings/license', []);
63 pyroutes.register('admin_settings_license_unlock', '/_admin/settings/license_unlock', []);
63 pyroutes.register('admin_settings_license_unlock', '/_admin/settings/license_unlock', []);
64 pyroutes.register('admin_settings_mapping', '/_admin/settings/mapping', []);
64 pyroutes.register('admin_settings_mapping', '/_admin/settings/mapping', []);
65 pyroutes.register('admin_settings_mapping_update', '/_admin/settings/mapping/update', []);
65 pyroutes.register('admin_settings_mapping_update', '/_admin/settings/mapping/update', []);
66 pyroutes.register('admin_settings_open_source', '/_admin/settings/open_source', []);
66 pyroutes.register('admin_settings_open_source', '/_admin/settings/open_source', []);
67 pyroutes.register('admin_settings_process_management', '/_admin/settings/process_management', []);
67 pyroutes.register('admin_settings_process_management', '/_admin/settings/process_management', []);
68 pyroutes.register('admin_settings_process_management_data', '/_admin/settings/process_management/data', []);
68 pyroutes.register('admin_settings_process_management_data', '/_admin/settings/process_management/data', []);
69 pyroutes.register('admin_settings_process_management_master_signal', '/_admin/settings/process_management/master_signal', []);
69 pyroutes.register('admin_settings_process_management_master_signal', '/_admin/settings/process_management/master_signal', []);
70 pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []);
70 pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []);
71 pyroutes.register('admin_settings_scheduler_create', '/_admin/scheduler/create', []);
71 pyroutes.register('admin_settings_scheduler_create', '/_admin/scheduler/create', []);
72 pyroutes.register('admin_settings_scheduler_delete', '/_admin/scheduler/%(schedule_id)s/delete', ['schedule_id']);
72 pyroutes.register('admin_settings_scheduler_delete', '/_admin/scheduler/%(schedule_id)s/delete', ['schedule_id']);
73 pyroutes.register('admin_settings_scheduler_edit', '/_admin/scheduler/%(schedule_id)s', ['schedule_id']);
73 pyroutes.register('admin_settings_scheduler_edit', '/_admin/scheduler/%(schedule_id)s', ['schedule_id']);
74 pyroutes.register('admin_settings_scheduler_execute', '/_admin/scheduler/%(schedule_id)s/execute', ['schedule_id']);
74 pyroutes.register('admin_settings_scheduler_execute', '/_admin/scheduler/%(schedule_id)s/execute', ['schedule_id']);
75 pyroutes.register('admin_settings_scheduler_new', '/_admin/scheduler/new', []);
75 pyroutes.register('admin_settings_scheduler_new', '/_admin/scheduler/new', []);
76 pyroutes.register('admin_settings_scheduler_update', '/_admin/scheduler/%(schedule_id)s/update', ['schedule_id']);
76 pyroutes.register('admin_settings_scheduler_update', '/_admin/scheduler/%(schedule_id)s/update', ['schedule_id']);
77 pyroutes.register('admin_settings_search', '/_admin/settings/search', []);
77 pyroutes.register('admin_settings_search', '/_admin/settings/search', []);
78 pyroutes.register('admin_settings_sessions', '/_admin/settings/sessions', []);
78 pyroutes.register('admin_settings_sessions', '/_admin/settings/sessions', []);
79 pyroutes.register('admin_settings_sessions_cleanup', '/_admin/settings/sessions/cleanup', []);
79 pyroutes.register('admin_settings_sessions_cleanup', '/_admin/settings/sessions/cleanup', []);
80 pyroutes.register('admin_settings_system', '/_admin/settings/system', []);
80 pyroutes.register('admin_settings_system', '/_admin/settings/system', []);
81 pyroutes.register('admin_settings_system_update', '/_admin/settings/system/updates', []);
81 pyroutes.register('admin_settings_system_update', '/_admin/settings/system/updates', []);
82 pyroutes.register('admin_settings_update', '/_admin/settings/update', []);
82 pyroutes.register('admin_settings_update', '/_admin/settings/update', []);
83 pyroutes.register('admin_settings_vcs', '/_admin/settings/vcs', []);
83 pyroutes.register('admin_settings_vcs', '/_admin/settings/vcs', []);
84 pyroutes.register('admin_settings_vcs_svn_generate_cfg', '/_admin/settings/vcs/svn_generate_cfg', []);
84 pyroutes.register('admin_settings_vcs_svn_generate_cfg', '/_admin/settings/vcs/svn_generate_cfg', []);
85 pyroutes.register('admin_settings_vcs_svn_pattern_delete', '/_admin/settings/vcs/svn_pattern_delete', []);
85 pyroutes.register('admin_settings_vcs_svn_pattern_delete', '/_admin/settings/vcs/svn_pattern_delete', []);
86 pyroutes.register('admin_settings_vcs_update', '/_admin/settings/vcs/update', []);
86 pyroutes.register('admin_settings_vcs_update', '/_admin/settings/vcs/update', []);
87 pyroutes.register('admin_settings_visual', '/_admin/settings/visual', []);
87 pyroutes.register('admin_settings_visual', '/_admin/settings/visual', []);
88 pyroutes.register('admin_settings_visual_update', '/_admin/settings/visual/update', []);
88 pyroutes.register('admin_settings_visual_update', '/_admin/settings/visual/update', []);
89 pyroutes.register('admin_security_modify_allowed_vcs_client_versions', '/_admin/security/modify/allowed_vcs_client_versions', []);
89 pyroutes.register('apiv2', '/_admin/api', []);
90 pyroutes.register('apiv2', '/_admin/api', []);
90 pyroutes.register('atom_feed_home', '/%(repo_name)s/feed-atom', ['repo_name']);
91 pyroutes.register('atom_feed_home', '/%(repo_name)s/feed-atom', ['repo_name']);
91 pyroutes.register('atom_feed_home_old', '/%(repo_name)s/feed/atom', ['repo_name']);
92 pyroutes.register('atom_feed_home_old', '/%(repo_name)s/feed/atom', ['repo_name']);
92 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
93 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
93 pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']);
94 pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']);
94 pyroutes.register('branch_remove', '/%(repo_name)s/branches/%(branch_name)s/remove', ['repo_name', 'branch_name']);
95 pyroutes.register('branch_remove', '/%(repo_name)s/branches/%(branch_name)s/remove', ['repo_name', 'branch_name']);
95 pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']);
96 pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']);
96 pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []);
97 pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []);
97 pyroutes.register('channelstream_proxy', '/_channelstream', []);
98 pyroutes.register('channelstream_proxy', '/_channelstream', []);
98 pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []);
99 pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []);
99 pyroutes.register('check_2fa', '/_admin/check_2fa', []);
100 pyroutes.register('check_2fa', '/_admin/check_2fa', []);
100 pyroutes.register('commit_draft_comments_submit', '/%(repo_name)s/changeset/%(commit_id)s/draft_comments_submit', ['repo_name', 'commit_id']);
101 pyroutes.register('commit_draft_comments_submit', '/%(repo_name)s/changeset/%(commit_id)s/draft_comments_submit', ['repo_name', 'commit_id']);
101 pyroutes.register('debug_style_email', '/_admin/debug_style/email/%(email_id)s', ['email_id']);
102 pyroutes.register('debug_style_email', '/_admin/debug_style/email/%(email_id)s', ['email_id']);
102 pyroutes.register('debug_style_email_plain_rendered', '/_admin/debug_style/email-rendered/%(email_id)s', ['email_id']);
103 pyroutes.register('debug_style_email_plain_rendered', '/_admin/debug_style/email-rendered/%(email_id)s', ['email_id']);
103 pyroutes.register('debug_style_home', '/_admin/debug_style', []);
104 pyroutes.register('debug_style_home', '/_admin/debug_style', []);
104 pyroutes.register('debug_style_template', '/_admin/debug_style/t/%(t_path)s', ['t_path']);
105 pyroutes.register('debug_style_template', '/_admin/debug_style/t/%(t_path)s', ['t_path']);
105 pyroutes.register('download_file', '/_file_store/download/%(fid)s', ['fid']);
106 pyroutes.register('download_file', '/_file_store/download/%(fid)s', ['fid']);
106 pyroutes.register('download_file_by_token', '/_file_store/token-download/%(_auth_token)s/%(fid)s', ['_auth_token', 'fid']);
107 pyroutes.register('download_file_by_token', '/_file_store/token-download/%(_auth_token)s/%(fid)s', ['_auth_token', 'fid']);
107 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
108 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
108 pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']);
109 pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']);
109 pyroutes.register('edit_repo_advanced_archive', '/%(repo_name)s/settings/advanced/archive', ['repo_name']);
110 pyroutes.register('edit_repo_advanced_archive', '/%(repo_name)s/settings/advanced/archive', ['repo_name']);
110 pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']);
111 pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']);
111 pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']);
112 pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']);
112 pyroutes.register('edit_repo_advanced_hooks', '/%(repo_name)s/settings/advanced/hooks', ['repo_name']);
113 pyroutes.register('edit_repo_advanced_hooks', '/%(repo_name)s/settings/advanced/hooks', ['repo_name']);
113 pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']);
114 pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']);
114 pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']);
115 pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']);
115 pyroutes.register('edit_repo_audit_logs', '/%(repo_name)s/settings/audit_logs', ['repo_name']);
116 pyroutes.register('edit_repo_audit_logs', '/%(repo_name)s/settings/audit_logs', ['repo_name']);
116 pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
117 pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
117 pyroutes.register('edit_repo_fields', '/%(repo_name)s/settings/fields', ['repo_name']);
118 pyroutes.register('edit_repo_fields', '/%(repo_name)s/settings/fields', ['repo_name']);
118 pyroutes.register('edit_repo_fields_create', '/%(repo_name)s/settings/fields/create', ['repo_name']);
119 pyroutes.register('edit_repo_fields_create', '/%(repo_name)s/settings/fields/create', ['repo_name']);
119 pyroutes.register('edit_repo_fields_delete', '/%(repo_name)s/settings/fields/%(field_id)s/delete', ['repo_name', 'field_id']);
120 pyroutes.register('edit_repo_fields_delete', '/%(repo_name)s/settings/fields/%(field_id)s/delete', ['repo_name', 'field_id']);
120 pyroutes.register('edit_repo_group', '/%(repo_group_name)s/_edit', ['repo_group_name']);
121 pyroutes.register('edit_repo_group', '/%(repo_group_name)s/_edit', ['repo_group_name']);
121 pyroutes.register('edit_repo_group_advanced', '/%(repo_group_name)s/_settings/advanced', ['repo_group_name']);
122 pyroutes.register('edit_repo_group_advanced', '/%(repo_group_name)s/_settings/advanced', ['repo_group_name']);
122 pyroutes.register('edit_repo_group_advanced_delete', '/%(repo_group_name)s/_settings/advanced/delete', ['repo_group_name']);
123 pyroutes.register('edit_repo_group_advanced_delete', '/%(repo_group_name)s/_settings/advanced/delete', ['repo_group_name']);
123 pyroutes.register('edit_repo_group_perms', '/%(repo_group_name)s/_settings/permissions', ['repo_group_name']);
124 pyroutes.register('edit_repo_group_perms', '/%(repo_group_name)s/_settings/permissions', ['repo_group_name']);
124 pyroutes.register('edit_repo_group_perms_update', '/%(repo_group_name)s/_settings/permissions/update', ['repo_group_name']);
125 pyroutes.register('edit_repo_group_perms_update', '/%(repo_group_name)s/_settings/permissions/update', ['repo_group_name']);
125 pyroutes.register('edit_repo_issuetracker', '/%(repo_name)s/settings/issue_trackers', ['repo_name']);
126 pyroutes.register('edit_repo_issuetracker', '/%(repo_name)s/settings/issue_trackers', ['repo_name']);
126 pyroutes.register('edit_repo_issuetracker_delete', '/%(repo_name)s/settings/issue_trackers/delete', ['repo_name']);
127 pyroutes.register('edit_repo_issuetracker_delete', '/%(repo_name)s/settings/issue_trackers/delete', ['repo_name']);
127 pyroutes.register('edit_repo_issuetracker_test', '/%(repo_name)s/settings/issue_trackers/test', ['repo_name']);
128 pyroutes.register('edit_repo_issuetracker_test', '/%(repo_name)s/settings/issue_trackers/test', ['repo_name']);
128 pyroutes.register('edit_repo_issuetracker_update', '/%(repo_name)s/settings/issue_trackers/update', ['repo_name']);
129 pyroutes.register('edit_repo_issuetracker_update', '/%(repo_name)s/settings/issue_trackers/update', ['repo_name']);
129 pyroutes.register('edit_repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']);
130 pyroutes.register('edit_repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']);
130 pyroutes.register('edit_repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']);
131 pyroutes.register('edit_repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']);
131 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
132 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
132 pyroutes.register('edit_repo_perms_branch', '/%(repo_name)s/settings/branch_permissions', ['repo_name']);
133 pyroutes.register('edit_repo_perms_branch', '/%(repo_name)s/settings/branch_permissions', ['repo_name']);
133 pyroutes.register('edit_repo_perms_branch_delete', '/%(repo_name)s/settings/branch_permissions/%(rule_id)s/delete', ['repo_name', 'rule_id']);
134 pyroutes.register('edit_repo_perms_branch_delete', '/%(repo_name)s/settings/branch_permissions/%(rule_id)s/delete', ['repo_name', 'rule_id']);
134 pyroutes.register('edit_repo_perms_set_private', '/%(repo_name)s/settings/permissions/set_private', ['repo_name']);
135 pyroutes.register('edit_repo_perms_set_private', '/%(repo_name)s/settings/permissions/set_private', ['repo_name']);
135 pyroutes.register('edit_repo_remote', '/%(repo_name)s/settings/remote', ['repo_name']);
136 pyroutes.register('edit_repo_remote', '/%(repo_name)s/settings/remote', ['repo_name']);
136 pyroutes.register('edit_repo_remote_pull', '/%(repo_name)s/settings/remote/pull', ['repo_name']);
137 pyroutes.register('edit_repo_remote_pull', '/%(repo_name)s/settings/remote/pull', ['repo_name']);
137 pyroutes.register('edit_repo_remote_push', '/%(repo_name)s/settings/remote/push', ['repo_name']);
138 pyroutes.register('edit_repo_remote_push', '/%(repo_name)s/settings/remote/push', ['repo_name']);
138 pyroutes.register('edit_repo_statistics', '/%(repo_name)s/settings/statistics', ['repo_name']);
139 pyroutes.register('edit_repo_statistics', '/%(repo_name)s/settings/statistics', ['repo_name']);
139 pyroutes.register('edit_repo_statistics_reset', '/%(repo_name)s/settings/statistics/update', ['repo_name']);
140 pyroutes.register('edit_repo_statistics_reset', '/%(repo_name)s/settings/statistics/update', ['repo_name']);
140 pyroutes.register('edit_repo_strip', '/%(repo_name)s/settings/strip', ['repo_name']);
141 pyroutes.register('edit_repo_strip', '/%(repo_name)s/settings/strip', ['repo_name']);
141 pyroutes.register('edit_repo_vcs', '/%(repo_name)s/settings/vcs', ['repo_name']);
142 pyroutes.register('edit_repo_vcs', '/%(repo_name)s/settings/vcs', ['repo_name']);
142 pyroutes.register('edit_repo_vcs_svn_pattern_delete', '/%(repo_name)s/settings/vcs/svn_pattern/delete', ['repo_name']);
143 pyroutes.register('edit_repo_vcs_svn_pattern_delete', '/%(repo_name)s/settings/vcs/svn_pattern/delete', ['repo_name']);
143 pyroutes.register('edit_repo_vcs_update', '/%(repo_name)s/settings/vcs/update', ['repo_name']);
144 pyroutes.register('edit_repo_vcs_update', '/%(repo_name)s/settings/vcs/update', ['repo_name']);
144 pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']);
145 pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']);
145 pyroutes.register('edit_user_audit_logs_download', '/_admin/users/%(user_id)s/edit/audit/download', ['user_id']);
146 pyroutes.register('edit_user_audit_logs_download', '/_admin/users/%(user_id)s/edit/audit/download', ['user_id']);
146 pyroutes.register('edit_user_auth_tokens', '/_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']);
147 pyroutes.register('edit_user_auth_tokens', '/_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']);
147 pyroutes.register('edit_user_auth_tokens_add', '/_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']);
148 pyroutes.register('edit_user_auth_tokens_add', '/_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']);
148 pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
149 pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
149 pyroutes.register('edit_user_auth_tokens_view', '/_admin/users/%(user_id)s/edit/auth_tokens/view', ['user_id']);
150 pyroutes.register('edit_user_auth_tokens_view', '/_admin/users/%(user_id)s/edit/auth_tokens/view', ['user_id']);
150 pyroutes.register('edit_user_caches', '/_admin/users/%(user_id)s/edit/caches', ['user_id']);
151 pyroutes.register('edit_user_caches', '/_admin/users/%(user_id)s/edit/caches', ['user_id']);
151 pyroutes.register('edit_user_caches_update', '/_admin/users/%(user_id)s/edit/caches/update', ['user_id']);
152 pyroutes.register('edit_user_caches_update', '/_admin/users/%(user_id)s/edit/caches/update', ['user_id']);
152 pyroutes.register('edit_user_emails', '/_admin/users/%(user_id)s/edit/emails', ['user_id']);
153 pyroutes.register('edit_user_emails', '/_admin/users/%(user_id)s/edit/emails', ['user_id']);
153 pyroutes.register('edit_user_emails_add', '/_admin/users/%(user_id)s/edit/emails/new', ['user_id']);
154 pyroutes.register('edit_user_emails_add', '/_admin/users/%(user_id)s/edit/emails/new', ['user_id']);
154 pyroutes.register('edit_user_emails_delete', '/_admin/users/%(user_id)s/edit/emails/delete', ['user_id']);
155 pyroutes.register('edit_user_emails_delete', '/_admin/users/%(user_id)s/edit/emails/delete', ['user_id']);
155 pyroutes.register('edit_user_group', '/_admin/user_groups/%(user_group_id)s/edit', ['user_group_id']);
156 pyroutes.register('edit_user_group', '/_admin/user_groups/%(user_group_id)s/edit', ['user_group_id']);
156 pyroutes.register('edit_user_group_advanced', '/_admin/user_groups/%(user_group_id)s/edit/advanced', ['user_group_id']);
157 pyroutes.register('edit_user_group_advanced', '/_admin/user_groups/%(user_group_id)s/edit/advanced', ['user_group_id']);
157 pyroutes.register('edit_user_group_advanced_sync', '/_admin/user_groups/%(user_group_id)s/edit/advanced/sync', ['user_group_id']);
158 pyroutes.register('edit_user_group_advanced_sync', '/_admin/user_groups/%(user_group_id)s/edit/advanced/sync', ['user_group_id']);
158 pyroutes.register('edit_user_group_global_perms', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions', ['user_group_id']);
159 pyroutes.register('edit_user_group_global_perms', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions', ['user_group_id']);
159 pyroutes.register('edit_user_group_global_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions/update', ['user_group_id']);
160 pyroutes.register('edit_user_group_global_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions/update', ['user_group_id']);
160 pyroutes.register('edit_user_group_perms', '/_admin/user_groups/%(user_group_id)s/edit/permissions', ['user_group_id']);
161 pyroutes.register('edit_user_group_perms', '/_admin/user_groups/%(user_group_id)s/edit/permissions', ['user_group_id']);
161 pyroutes.register('edit_user_group_perms_summary', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary', ['user_group_id']);
162 pyroutes.register('edit_user_group_perms_summary', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary', ['user_group_id']);
162 pyroutes.register('edit_user_group_perms_summary_json', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary/json', ['user_group_id']);
163 pyroutes.register('edit_user_group_perms_summary_json', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary/json', ['user_group_id']);
163 pyroutes.register('edit_user_group_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/permissions/update', ['user_group_id']);
164 pyroutes.register('edit_user_group_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/permissions/update', ['user_group_id']);
164 pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']);
165 pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']);
165 pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']);
166 pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']);
166 pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']);
167 pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']);
167 pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']);
168 pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']);
168 pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']);
169 pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']);
169 pyroutes.register('edit_user_perms_summary', '/_admin/users/%(user_id)s/edit/permissions_summary', ['user_id']);
170 pyroutes.register('edit_user_perms_summary', '/_admin/users/%(user_id)s/edit/permissions_summary', ['user_id']);
170 pyroutes.register('edit_user_perms_summary_json', '/_admin/users/%(user_id)s/edit/permissions_summary/json', ['user_id']);
171 pyroutes.register('edit_user_perms_summary_json', '/_admin/users/%(user_id)s/edit/permissions_summary/json', ['user_id']);
171 pyroutes.register('edit_user_ssh_keys', '/_admin/users/%(user_id)s/edit/ssh_keys', ['user_id']);
172 pyroutes.register('edit_user_ssh_keys', '/_admin/users/%(user_id)s/edit/ssh_keys', ['user_id']);
172 pyroutes.register('edit_user_ssh_keys_add', '/_admin/users/%(user_id)s/edit/ssh_keys/new', ['user_id']);
173 pyroutes.register('edit_user_ssh_keys_add', '/_admin/users/%(user_id)s/edit/ssh_keys/new', ['user_id']);
173 pyroutes.register('edit_user_ssh_keys_delete', '/_admin/users/%(user_id)s/edit/ssh_keys/delete', ['user_id']);
174 pyroutes.register('edit_user_ssh_keys_delete', '/_admin/users/%(user_id)s/edit/ssh_keys/delete', ['user_id']);
174 pyroutes.register('edit_user_ssh_keys_generate_keypair', '/_admin/users/%(user_id)s/edit/ssh_keys/generate', ['user_id']);
175 pyroutes.register('edit_user_ssh_keys_generate_keypair', '/_admin/users/%(user_id)s/edit/ssh_keys/generate', ['user_id']);
175 pyroutes.register('favicon', '/favicon.ico', []);
176 pyroutes.register('favicon', '/favicon.ico', []);
176 pyroutes.register('file_preview', '/_file_preview', []);
177 pyroutes.register('file_preview', '/_file_preview', []);
177 pyroutes.register('gist_delete', '/_admin/gists/%(gist_id)s/delete', ['gist_id']);
178 pyroutes.register('gist_delete', '/_admin/gists/%(gist_id)s/delete', ['gist_id']);
178 pyroutes.register('gist_edit', '/_admin/gists/%(gist_id)s/edit', ['gist_id']);
179 pyroutes.register('gist_edit', '/_admin/gists/%(gist_id)s/edit', ['gist_id']);
179 pyroutes.register('gist_edit_check_revision', '/_admin/gists/%(gist_id)s/edit/check_revision', ['gist_id']);
180 pyroutes.register('gist_edit_check_revision', '/_admin/gists/%(gist_id)s/edit/check_revision', ['gist_id']);
180 pyroutes.register('gist_show', '/_admin/gists/%(gist_id)s', ['gist_id']);
181 pyroutes.register('gist_show', '/_admin/gists/%(gist_id)s', ['gist_id']);
181 pyroutes.register('gist_show_formatted', '/_admin/gists/%(gist_id)s/rev/%(revision)s/%(format)s', ['gist_id', 'revision', 'format']);
182 pyroutes.register('gist_show_formatted', '/_admin/gists/%(gist_id)s/rev/%(revision)s/%(format)s', ['gist_id', 'revision', 'format']);
182 pyroutes.register('gist_show_formatted_path', '/_admin/gists/%(gist_id)s/rev/%(revision)s/%(format)s/%(f_path)s', ['gist_id', 'revision', 'format', 'f_path']);
183 pyroutes.register('gist_show_formatted_path', '/_admin/gists/%(gist_id)s/rev/%(revision)s/%(format)s/%(f_path)s', ['gist_id', 'revision', 'format', 'f_path']);
183 pyroutes.register('gist_show_rev', '/_admin/gists/%(gist_id)s/rev/%(revision)s', ['gist_id', 'revision']);
184 pyroutes.register('gist_show_rev', '/_admin/gists/%(gist_id)s/rev/%(revision)s', ['gist_id', 'revision']);
184 pyroutes.register('gist_update', '/_admin/gists/%(gist_id)s/update', ['gist_id']);
185 pyroutes.register('gist_update', '/_admin/gists/%(gist_id)s/update', ['gist_id']);
185 pyroutes.register('gists_create', '/_admin/gists/create', []);
186 pyroutes.register('gists_create', '/_admin/gists/create', []);
186 pyroutes.register('gists_new', '/_admin/gists/new', []);
187 pyroutes.register('gists_new', '/_admin/gists/new', []);
187 pyroutes.register('gists_show', '/_admin/gists', []);
188 pyroutes.register('gists_show', '/_admin/gists', []);
188 pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
189 pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
189 pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
190 pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
190 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
191 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
191 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
192 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
192 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
193 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
193 pyroutes.register('goto_switcher_data', '/_goto_data', []);
194 pyroutes.register('goto_switcher_data', '/_goto_data', []);
194 pyroutes.register('home', '/', []);
195 pyroutes.register('home', '/', []);
195 pyroutes.register('hovercard_pull_request', '/_hovercard/pull_request/%(pull_request_id)s', ['pull_request_id']);
196 pyroutes.register('hovercard_pull_request', '/_hovercard/pull_request/%(pull_request_id)s', ['pull_request_id']);
196 pyroutes.register('hovercard_repo_commit', '/_hovercard/commit/%(repo_name)s/%(commit_id)s', ['repo_name', 'commit_id']);
197 pyroutes.register('hovercard_repo_commit', '/_hovercard/commit/%(repo_name)s/%(commit_id)s', ['repo_name', 'commit_id']);
197 pyroutes.register('hovercard_user', '/_hovercard/user/%(user_id)s', ['user_id']);
198 pyroutes.register('hovercard_user', '/_hovercard/user/%(user_id)s', ['user_id']);
198 pyroutes.register('hovercard_user_group', '/_hovercard/user_group/%(user_group_id)s', ['user_group_id']);
199 pyroutes.register('hovercard_user_group', '/_hovercard/user_group/%(user_group_id)s', ['user_group_id']);
199 pyroutes.register('hovercard_username', '/_hovercard/username/%(username)s', ['username']);
200 pyroutes.register('hovercard_username', '/_hovercard/username/%(username)s', ['username']);
200 pyroutes.register('journal', '/_admin/journal', []);
201 pyroutes.register('journal', '/_admin/journal', []);
201 pyroutes.register('journal_atom', '/_admin/journal/atom', []);
202 pyroutes.register('journal_atom', '/_admin/journal/atom', []);
202 pyroutes.register('journal_public', '/_admin/public_journal', []);
203 pyroutes.register('journal_public', '/_admin/public_journal', []);
203 pyroutes.register('journal_public_atom', '/_admin/public_journal/atom', []);
204 pyroutes.register('journal_public_atom', '/_admin/public_journal/atom', []);
204 pyroutes.register('journal_public_atom_old', '/_admin/public_journal_atom', []);
205 pyroutes.register('journal_public_atom_old', '/_admin/public_journal_atom', []);
205 pyroutes.register('journal_public_rss', '/_admin/public_journal/rss', []);
206 pyroutes.register('journal_public_rss', '/_admin/public_journal/rss', []);
206 pyroutes.register('journal_public_rss_old', '/_admin/public_journal_rss', []);
207 pyroutes.register('journal_public_rss_old', '/_admin/public_journal_rss', []);
207 pyroutes.register('journal_rss', '/_admin/journal/rss', []);
208 pyroutes.register('journal_rss', '/_admin/journal/rss', []);
208 pyroutes.register('login', '/_admin/login', []);
209 pyroutes.register('login', '/_admin/login', []);
209 pyroutes.register('logout', '/_admin/logout', []);
210 pyroutes.register('logout', '/_admin/logout', []);
210 pyroutes.register('main_page_repo_groups_data', '/_home_repo_groups', []);
211 pyroutes.register('main_page_repo_groups_data', '/_home_repo_groups', []);
211 pyroutes.register('main_page_repos_data', '/_home_repos', []);
212 pyroutes.register('main_page_repos_data', '/_home_repos', []);
212 pyroutes.register('markup_preview', '/_markup_preview', []);
213 pyroutes.register('markup_preview', '/_markup_preview', []);
213 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
214 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
214 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
215 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
215 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
216 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
216 pyroutes.register('my_account_auth_tokens_view', '/_admin/my_account/auth_tokens/view', []);
217 pyroutes.register('my_account_auth_tokens_view', '/_admin/my_account/auth_tokens/view', []);
217 pyroutes.register('my_account_bookmarks', '/_admin/my_account/bookmarks', []);
218 pyroutes.register('my_account_bookmarks', '/_admin/my_account/bookmarks', []);
218 pyroutes.register('my_account_bookmarks_update', '/_admin/my_account/bookmarks/update', []);
219 pyroutes.register('my_account_bookmarks_update', '/_admin/my_account/bookmarks/update', []);
219 pyroutes.register('my_account_configure_2fa', '/_admin/my_account/configure_2fa', []);
220 pyroutes.register('my_account_configure_2fa', '/_admin/my_account/configure_2fa', []);
220 pyroutes.register('my_account_configure_2fa_update', '/_admin/my_account/configure_2fa_update', []);
221 pyroutes.register('my_account_configure_2fa_update', '/_admin/my_account/configure_2fa_update', []);
221 pyroutes.register('my_account_edit', '/_admin/my_account/edit', []);
222 pyroutes.register('my_account_edit', '/_admin/my_account/edit', []);
222 pyroutes.register('my_account_emails', '/_admin/my_account/emails', []);
223 pyroutes.register('my_account_emails', '/_admin/my_account/emails', []);
223 pyroutes.register('my_account_emails_add', '/_admin/my_account/emails/new', []);
224 pyroutes.register('my_account_emails_add', '/_admin/my_account/emails/new', []);
224 pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []);
225 pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []);
225 pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []);
226 pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []);
226 pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []);
227 pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []);
227 pyroutes.register('my_account_goto_bookmark', '/_admin/my_account/bookmark/%(bookmark_id)s', ['bookmark_id']);
228 pyroutes.register('my_account_goto_bookmark', '/_admin/my_account/bookmark/%(bookmark_id)s', ['bookmark_id']);
228 pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []);
229 pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []);
229 pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []);
230 pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []);
230 pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []);
231 pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []);
231 pyroutes.register('my_account_password', '/_admin/my_account/password', []);
232 pyroutes.register('my_account_password', '/_admin/my_account/password', []);
232 pyroutes.register('my_account_password_update', '/_admin/my_account/password/update', []);
233 pyroutes.register('my_account_password_update', '/_admin/my_account/password/update', []);
233 pyroutes.register('my_account_perms', '/_admin/my_account/perms', []);
234 pyroutes.register('my_account_perms', '/_admin/my_account/perms', []);
234 pyroutes.register('my_account_profile', '/_admin/my_account/profile', []);
235 pyroutes.register('my_account_profile', '/_admin/my_account/profile', []);
235 pyroutes.register('my_account_pullrequests', '/_admin/my_account/pull_requests', []);
236 pyroutes.register('my_account_pullrequests', '/_admin/my_account/pull_requests', []);
236 pyroutes.register('my_account_pullrequests_data', '/_admin/my_account/pull_requests/data', []);
237 pyroutes.register('my_account_pullrequests_data', '/_admin/my_account/pull_requests/data', []);
237 pyroutes.register('my_account_regenerate_2fa_recovery_codes', '/_admin/my_account/regenerate_recovery_codes', []);
238 pyroutes.register('my_account_regenerate_2fa_recovery_codes', '/_admin/my_account/regenerate_recovery_codes', []);
238 pyroutes.register('my_account_repos', '/_admin/my_account/repos', []);
239 pyroutes.register('my_account_repos', '/_admin/my_account/repos', []);
239 pyroutes.register('my_account_show_2fa_recovery_codes', '/_admin/my_account/recovery_codes', []);
240 pyroutes.register('my_account_show_2fa_recovery_codes', '/_admin/my_account/recovery_codes', []);
240 pyroutes.register('my_account_ssh_keys', '/_admin/my_account/ssh_keys', []);
241 pyroutes.register('my_account_ssh_keys', '/_admin/my_account/ssh_keys', []);
241 pyroutes.register('my_account_ssh_keys_add', '/_admin/my_account/ssh_keys/new', []);
242 pyroutes.register('my_account_ssh_keys_add', '/_admin/my_account/ssh_keys/new', []);
242 pyroutes.register('my_account_ssh_keys_delete', '/_admin/my_account/ssh_keys/delete', []);
243 pyroutes.register('my_account_ssh_keys_delete', '/_admin/my_account/ssh_keys/delete', []);
243 pyroutes.register('my_account_ssh_keys_generate', '/_admin/my_account/ssh_keys/generate', []);
244 pyroutes.register('my_account_ssh_keys_generate', '/_admin/my_account/ssh_keys/generate', []);
244 pyroutes.register('my_account_update', '/_admin/my_account/update', []);
245 pyroutes.register('my_account_update', '/_admin/my_account/update', []);
245 pyroutes.register('my_account_user_group_membership', '/_admin/my_account/user_group_membership', []);
246 pyroutes.register('my_account_user_group_membership', '/_admin/my_account/user_group_membership', []);
246 pyroutes.register('my_account_watched', '/_admin/my_account/watched', []);
247 pyroutes.register('my_account_watched', '/_admin/my_account/watched', []);
247 pyroutes.register('notifications_delete', '/_admin/notifications/%(notification_id)s/delete', ['notification_id']);
248 pyroutes.register('notifications_delete', '/_admin/notifications/%(notification_id)s/delete', ['notification_id']);
248 pyroutes.register('notifications_mark_all_read', '/_admin/notifications_mark_all_read', []);
249 pyroutes.register('notifications_mark_all_read', '/_admin/notifications_mark_all_read', []);
249 pyroutes.register('notifications_show', '/_admin/notifications/%(notification_id)s', ['notification_id']);
250 pyroutes.register('notifications_show', '/_admin/notifications/%(notification_id)s', ['notification_id']);
250 pyroutes.register('notifications_show_all', '/_admin/notifications', []);
251 pyroutes.register('notifications_show_all', '/_admin/notifications', []);
251 pyroutes.register('notifications_update', '/_admin/notifications/%(notification_id)s/update', ['notification_id']);
252 pyroutes.register('notifications_update', '/_admin/notifications/%(notification_id)s/update', ['notification_id']);
252 pyroutes.register('ops_celery_error_test', '/_admin/ops/error-celery', []);
253 pyroutes.register('ops_celery_error_test', '/_admin/ops/error-celery', []);
253 pyroutes.register('ops_error_test', '/_admin/ops/error', []);
254 pyroutes.register('ops_error_test', '/_admin/ops/error', []);
254 pyroutes.register('ops_healthcheck', '/_admin/ops/status', []);
255 pyroutes.register('ops_healthcheck', '/_admin/ops/status', []);
255 pyroutes.register('ops_ping', '/_admin/ops/ping', []);
256 pyroutes.register('ops_ping', '/_admin/ops/ping', []);
256 pyroutes.register('ops_redirect_test', '/_admin/ops/redirect', []);
257 pyroutes.register('ops_redirect_test', '/_admin/ops/redirect', []);
257 pyroutes.register('plugin_admin_chat', '/_admin/plugin_admin_chat/%(action)s', ['action']);
258 pyroutes.register('plugin_admin_chat', '/_admin/plugin_admin_chat/%(action)s', ['action']);
258 pyroutes.register('pull_requests_global', '/_admin/pull-request/%(pull_request_id)s', ['pull_request_id']);
259 pyroutes.register('pull_requests_global', '/_admin/pull-request/%(pull_request_id)s', ['pull_request_id']);
259 pyroutes.register('pull_requests_global_0', '/_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']);
260 pyroutes.register('pull_requests_global_0', '/_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']);
260 pyroutes.register('pull_requests_global_1', '/_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']);
261 pyroutes.register('pull_requests_global_1', '/_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']);
261 pyroutes.register('pullrequest_comment_create', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment', ['repo_name', 'pull_request_id']);
262 pyroutes.register('pullrequest_comment_create', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment', ['repo_name', 'pull_request_id']);
262 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']);
263 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']);
263 pyroutes.register('pullrequest_comment_edit', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/edit', ['repo_name', 'pull_request_id', 'comment_id']);
264 pyroutes.register('pullrequest_comment_edit', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/edit', ['repo_name', 'pull_request_id', 'comment_id']);
264 pyroutes.register('pullrequest_comments', '/%(repo_name)s/pull-request/%(pull_request_id)s/comments', ['repo_name', 'pull_request_id']);
265 pyroutes.register('pullrequest_comments', '/%(repo_name)s/pull-request/%(pull_request_id)s/comments', ['repo_name', 'pull_request_id']);
265 pyroutes.register('pullrequest_create', '/%(repo_name)s/pull-request/create', ['repo_name']);
266 pyroutes.register('pullrequest_create', '/%(repo_name)s/pull-request/create', ['repo_name']);
266 pyroutes.register('pullrequest_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/delete', ['repo_name', 'pull_request_id']);
267 pyroutes.register('pullrequest_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/delete', ['repo_name', 'pull_request_id']);
267 pyroutes.register('pullrequest_draft_comments_submit', '/%(repo_name)s/pull-request/%(pull_request_id)s/draft_comments_submit', ['repo_name', 'pull_request_id']);
268 pyroutes.register('pullrequest_draft_comments_submit', '/%(repo_name)s/pull-request/%(pull_request_id)s/draft_comments_submit', ['repo_name', 'pull_request_id']);
268 pyroutes.register('pullrequest_drafts', '/%(repo_name)s/pull-request/%(pull_request_id)s/drafts', ['repo_name', 'pull_request_id']);
269 pyroutes.register('pullrequest_drafts', '/%(repo_name)s/pull-request/%(pull_request_id)s/drafts', ['repo_name', 'pull_request_id']);
269 pyroutes.register('pullrequest_merge', '/%(repo_name)s/pull-request/%(pull_request_id)s/merge', ['repo_name', 'pull_request_id']);
270 pyroutes.register('pullrequest_merge', '/%(repo_name)s/pull-request/%(pull_request_id)s/merge', ['repo_name', 'pull_request_id']);
270 pyroutes.register('pullrequest_new', '/%(repo_name)s/pull-request/new', ['repo_name']);
271 pyroutes.register('pullrequest_new', '/%(repo_name)s/pull-request/new', ['repo_name']);
271 pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
272 pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
272 pyroutes.register('pullrequest_repo_targets', '/%(repo_name)s/pull-request/repo-targets', ['repo_name']);
273 pyroutes.register('pullrequest_repo_targets', '/%(repo_name)s/pull-request/repo-targets', ['repo_name']);
273 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
274 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
274 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
275 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
275 pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
276 pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
276 pyroutes.register('pullrequest_todos', '/%(repo_name)s/pull-request/%(pull_request_id)s/todos', ['repo_name', 'pull_request_id']);
277 pyroutes.register('pullrequest_todos', '/%(repo_name)s/pull-request/%(pull_request_id)s/todos', ['repo_name', 'pull_request_id']);
277 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s/update', ['repo_name', 'pull_request_id']);
278 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s/update', ['repo_name', 'pull_request_id']);
278 pyroutes.register('register', '/_admin/register', []);
279 pyroutes.register('register', '/_admin/register', []);
279 pyroutes.register('repo_archivefile', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
280 pyroutes.register('repo_archivefile', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
280 pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']);
281 pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']);
281 pyroutes.register('repo_artifacts_delete', '/%(repo_name)s/artifacts/delete/%(uid)s', ['repo_name', 'uid']);
282 pyroutes.register('repo_artifacts_delete', '/%(repo_name)s/artifacts/delete/%(uid)s', ['repo_name', 'uid']);
282 pyroutes.register('repo_artifacts_get', '/%(repo_name)s/artifacts/download/%(uid)s', ['repo_name', 'uid']);
283 pyroutes.register('repo_artifacts_get', '/%(repo_name)s/artifacts/download/%(uid)s', ['repo_name', 'uid']);
283 pyroutes.register('repo_artifacts_info', '/%(repo_name)s/artifacts/info/%(uid)s', ['repo_name', 'uid']);
284 pyroutes.register('repo_artifacts_info', '/%(repo_name)s/artifacts/info/%(uid)s', ['repo_name', 'uid']);
284 pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']);
285 pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']);
285 pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']);
286 pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']);
286 pyroutes.register('repo_artifacts_store', '/%(repo_name)s/artifacts/store', ['repo_name']);
287 pyroutes.register('repo_artifacts_store', '/%(repo_name)s/artifacts/store', ['repo_name']);
287 pyroutes.register('repo_artifacts_stream_script', '/_file_store/stream-upload-script', []);
288 pyroutes.register('repo_artifacts_stream_script', '/_file_store/stream-upload-script', []);
288 pyroutes.register('repo_artifacts_stream_store', '/_file_store/stream-upload', []);
289 pyroutes.register('repo_artifacts_stream_store', '/_file_store/stream-upload', []);
289 pyroutes.register('repo_artifacts_update', '/%(repo_name)s/artifacts/update/%(uid)s', ['repo_name', 'uid']);
290 pyroutes.register('repo_artifacts_update', '/%(repo_name)s/artifacts/update/%(uid)s', ['repo_name', 'uid']);
290 pyroutes.register('repo_automation', '/%(repo_name)s/settings/automation', ['repo_name']);
291 pyroutes.register('repo_automation', '/%(repo_name)s/settings/automation', ['repo_name']);
291 pyroutes.register('repo_automation_update', '/%(repo_name)s/settings/automation/%(entry_id)s/update', ['repo_name', 'entry_id']);
292 pyroutes.register('repo_automation_update', '/%(repo_name)s/settings/automation/%(entry_id)s/update', ['repo_name', 'entry_id']);
292 pyroutes.register('repo_changelog', '/%(repo_name)s/changelog', ['repo_name']);
293 pyroutes.register('repo_changelog', '/%(repo_name)s/changelog', ['repo_name']);
293 pyroutes.register('repo_changelog_file', '/%(repo_name)s/changelog/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
294 pyroutes.register('repo_changelog_file', '/%(repo_name)s/changelog/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
294 pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
295 pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
295 pyroutes.register('repo_commit_children', '/%(repo_name)s/changeset_children/%(commit_id)s', ['repo_name', 'commit_id']);
296 pyroutes.register('repo_commit_children', '/%(repo_name)s/changeset_children/%(commit_id)s', ['repo_name', 'commit_id']);
296 pyroutes.register('repo_commit_comment_attachment_upload', '/%(repo_name)s/changeset/%(commit_id)s/comment/attachment_upload', ['repo_name', 'commit_id']);
297 pyroutes.register('repo_commit_comment_attachment_upload', '/%(repo_name)s/changeset/%(commit_id)s/comment/attachment_upload', ['repo_name', 'commit_id']);
297 pyroutes.register('repo_commit_comment_create', '/%(repo_name)s/changeset/%(commit_id)s/comment/create', ['repo_name', 'commit_id']);
298 pyroutes.register('repo_commit_comment_create', '/%(repo_name)s/changeset/%(commit_id)s/comment/create', ['repo_name', 'commit_id']);
298 pyroutes.register('repo_commit_comment_delete', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/delete', ['repo_name', 'commit_id', 'comment_id']);
299 pyroutes.register('repo_commit_comment_delete', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/delete', ['repo_name', 'commit_id', 'comment_id']);
299 pyroutes.register('repo_commit_comment_edit', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/edit', ['repo_name', 'commit_id', 'comment_id']);
300 pyroutes.register('repo_commit_comment_edit', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/edit', ['repo_name', 'commit_id', 'comment_id']);
300 pyroutes.register('repo_commit_comment_history_view', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/history_view/%(comment_history_id)s', ['repo_name', 'commit_id', 'comment_id', 'comment_history_id']);
301 pyroutes.register('repo_commit_comment_history_view', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/history_view/%(comment_history_id)s', ['repo_name', 'commit_id', 'comment_id', 'comment_history_id']);
301 pyroutes.register('repo_commit_comment_preview', '/%(repo_name)s/changeset/%(commit_id)s/comment/preview', ['repo_name', 'commit_id']);
302 pyroutes.register('repo_commit_comment_preview', '/%(repo_name)s/changeset/%(commit_id)s/comment/preview', ['repo_name', 'commit_id']);
302 pyroutes.register('repo_commit_data', '/%(repo_name)s/changeset-data/%(commit_id)s', ['repo_name', 'commit_id']);
303 pyroutes.register('repo_commit_data', '/%(repo_name)s/changeset-data/%(commit_id)s', ['repo_name', 'commit_id']);
303 pyroutes.register('repo_commit_download', '/%(repo_name)s/changeset-download/%(commit_id)s', ['repo_name', 'commit_id']);
304 pyroutes.register('repo_commit_download', '/%(repo_name)s/changeset-download/%(commit_id)s', ['repo_name', 'commit_id']);
304 pyroutes.register('repo_commit_parents', '/%(repo_name)s/changeset_parents/%(commit_id)s', ['repo_name', 'commit_id']);
305 pyroutes.register('repo_commit_parents', '/%(repo_name)s/changeset_parents/%(commit_id)s', ['repo_name', 'commit_id']);
305 pyroutes.register('repo_commit_patch', '/%(repo_name)s/changeset-patch/%(commit_id)s', ['repo_name', 'commit_id']);
306 pyroutes.register('repo_commit_patch', '/%(repo_name)s/changeset-patch/%(commit_id)s', ['repo_name', 'commit_id']);
306 pyroutes.register('repo_commit_raw', '/%(repo_name)s/changeset-diff/%(commit_id)s', ['repo_name', 'commit_id']);
307 pyroutes.register('repo_commit_raw', '/%(repo_name)s/changeset-diff/%(commit_id)s', ['repo_name', 'commit_id']);
307 pyroutes.register('repo_commit_raw_deprecated', '/%(repo_name)s/raw-changeset/%(commit_id)s', ['repo_name', 'commit_id']);
308 pyroutes.register('repo_commit_raw_deprecated', '/%(repo_name)s/raw-changeset/%(commit_id)s', ['repo_name', 'commit_id']);
308 pyroutes.register('repo_commits', '/%(repo_name)s/commits', ['repo_name']);
309 pyroutes.register('repo_commits', '/%(repo_name)s/commits', ['repo_name']);
309 pyroutes.register('repo_commits_elements', '/%(repo_name)s/commits_elements', ['repo_name']);
310 pyroutes.register('repo_commits_elements', '/%(repo_name)s/commits_elements', ['repo_name']);
310 pyroutes.register('repo_commits_elements_file', '/%(repo_name)s/commits_elements/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
311 pyroutes.register('repo_commits_elements_file', '/%(repo_name)s/commits_elements/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
311 pyroutes.register('repo_commits_file', '/%(repo_name)s/commits/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
312 pyroutes.register('repo_commits_file', '/%(repo_name)s/commits/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
312 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']);
313 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']);
313 pyroutes.register('repo_compare_select', '/%(repo_name)s/compare', ['repo_name']);
314 pyroutes.register('repo_compare_select', '/%(repo_name)s/compare', ['repo_name']);
314 pyroutes.register('repo_create', '/_admin/repos/create', []);
315 pyroutes.register('repo_create', '/_admin/repos/create', []);
315 pyroutes.register('repo_creating', '/%(repo_name)s/repo_creating', ['repo_name']);
316 pyroutes.register('repo_creating', '/%(repo_name)s/repo_creating', ['repo_name']);
316 pyroutes.register('repo_creating_check', '/%(repo_name)s/repo_creating_check', ['repo_name']);
317 pyroutes.register('repo_creating_check', '/%(repo_name)s/repo_creating_check', ['repo_name']);
317 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/settings/review/default-reviewers', ['repo_name']);
318 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/settings/review/default-reviewers', ['repo_name']);
318 pyroutes.register('repo_file_authors', '/%(repo_name)s/authors/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
319 pyroutes.register('repo_file_authors', '/%(repo_name)s/authors/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
319 pyroutes.register('repo_file_download', '/%(repo_name)s/download/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
320 pyroutes.register('repo_file_download', '/%(repo_name)s/download/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
320 pyroutes.register('repo_file_download:legacy', '/%(repo_name)s/rawfile/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
321 pyroutes.register('repo_file_download:legacy', '/%(repo_name)s/rawfile/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
321 pyroutes.register('repo_file_history', '/%(repo_name)s/history/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
322 pyroutes.register('repo_file_history', '/%(repo_name)s/history/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
322 pyroutes.register('repo_file_raw', '/%(repo_name)s/raw/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
323 pyroutes.register('repo_file_raw', '/%(repo_name)s/raw/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
323 pyroutes.register('repo_files', '/%(repo_name)s/files/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
324 pyroutes.register('repo_files', '/%(repo_name)s/files/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
324 pyroutes.register('repo_files:annotated', '/%(repo_name)s/annotate/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
325 pyroutes.register('repo_files:annotated', '/%(repo_name)s/annotate/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
325 pyroutes.register('repo_files:annotated_previous', '/%(repo_name)s/annotate-previous/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
326 pyroutes.register('repo_files:annotated_previous', '/%(repo_name)s/annotate-previous/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
326 pyroutes.register('repo_files:default_commit', '/%(repo_name)s/files', ['repo_name']);
327 pyroutes.register('repo_files:default_commit', '/%(repo_name)s/files', ['repo_name']);
327 pyroutes.register('repo_files:default_path', '/%(repo_name)s/files/%(commit_id)s/', ['repo_name', 'commit_id']);
328 pyroutes.register('repo_files:default_path', '/%(repo_name)s/files/%(commit_id)s/', ['repo_name', 'commit_id']);
328 pyroutes.register('repo_files:rendered', '/%(repo_name)s/render/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
329 pyroutes.register('repo_files:rendered', '/%(repo_name)s/render/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
329 pyroutes.register('repo_files_add_file', '/%(repo_name)s/add_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
330 pyroutes.register('repo_files_add_file', '/%(repo_name)s/add_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
330 pyroutes.register('repo_files_check_head', '/%(repo_name)s/check_head/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
331 pyroutes.register('repo_files_check_head', '/%(repo_name)s/check_head/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
331 pyroutes.register('repo_files_create_file', '/%(repo_name)s/create_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
332 pyroutes.register('repo_files_create_file', '/%(repo_name)s/create_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
332 pyroutes.register('repo_files_delete_file', '/%(repo_name)s/delete_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
333 pyroutes.register('repo_files_delete_file', '/%(repo_name)s/delete_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
333 pyroutes.register('repo_files_diff', '/%(repo_name)s/diff/%(f_path)s', ['repo_name', 'f_path']);
334 pyroutes.register('repo_files_diff', '/%(repo_name)s/diff/%(f_path)s', ['repo_name', 'f_path']);
334 pyroutes.register('repo_files_diff_2way_redirect', '/%(repo_name)s/diff-2way/%(f_path)s', ['repo_name', 'f_path']);
335 pyroutes.register('repo_files_diff_2way_redirect', '/%(repo_name)s/diff-2way/%(f_path)s', ['repo_name', 'f_path']);
335 pyroutes.register('repo_files_edit_file', '/%(repo_name)s/edit_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
336 pyroutes.register('repo_files_edit_file', '/%(repo_name)s/edit_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
336 pyroutes.register('repo_files_nodelist', '/%(repo_name)s/nodelist/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
337 pyroutes.register('repo_files_nodelist', '/%(repo_name)s/nodelist/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
337 pyroutes.register('repo_files_remove_file', '/%(repo_name)s/remove_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
338 pyroutes.register('repo_files_remove_file', '/%(repo_name)s/remove_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
338 pyroutes.register('repo_files_replace_binary', '/%(repo_name)s/replace_binary/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
339 pyroutes.register('repo_files_replace_binary', '/%(repo_name)s/replace_binary/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
339 pyroutes.register('repo_files_update_file', '/%(repo_name)s/update_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
340 pyroutes.register('repo_files_update_file', '/%(repo_name)s/update_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
340 pyroutes.register('repo_files_upload_file', '/%(repo_name)s/upload_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
341 pyroutes.register('repo_files_upload_file', '/%(repo_name)s/upload_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
341 pyroutes.register('repo_fork_create', '/%(repo_name)s/fork/create', ['repo_name']);
342 pyroutes.register('repo_fork_create', '/%(repo_name)s/fork/create', ['repo_name']);
342 pyroutes.register('repo_fork_new', '/%(repo_name)s/fork', ['repo_name']);
343 pyroutes.register('repo_fork_new', '/%(repo_name)s/fork', ['repo_name']);
343 pyroutes.register('repo_forks_data', '/%(repo_name)s/forks/data', ['repo_name']);
344 pyroutes.register('repo_forks_data', '/%(repo_name)s/forks/data', ['repo_name']);
344 pyroutes.register('repo_forks_show_all', '/%(repo_name)s/forks', ['repo_name']);
345 pyroutes.register('repo_forks_show_all', '/%(repo_name)s/forks', ['repo_name']);
345 pyroutes.register('repo_group_create', '/_admin/repo_group/create', []);
346 pyroutes.register('repo_group_create', '/_admin/repo_group/create', []);
346 pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']);
347 pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']);
347 pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']);
348 pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']);
348 pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/_settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
349 pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/_settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
349 pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/_settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
350 pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/_settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
350 pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/_settings/integrations', ['repo_group_name']);
351 pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/_settings/integrations', ['repo_group_name']);
351 pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/_settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
352 pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/_settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
352 pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/_settings/integrations/new', ['repo_group_name']);
353 pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/_settings/integrations/new', ['repo_group_name']);
353 pyroutes.register('repo_group_list_data', '/_repo_groups', []);
354 pyroutes.register('repo_group_list_data', '/_repo_groups', []);
354 pyroutes.register('repo_group_new', '/_admin/repo_group/new', []);
355 pyroutes.register('repo_group_new', '/_admin/repo_group/new', []);
355 pyroutes.register('repo_groups', '/_admin/repo_groups', []);
356 pyroutes.register('repo_groups', '/_admin/repo_groups', []);
356 pyroutes.register('repo_groups_data', '/_admin/repo_groups_data', []);
357 pyroutes.register('repo_groups_data', '/_admin/repo_groups_data', []);
357 pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
358 pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
358 pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
359 pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
359 pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']);
360 pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']);
360 pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
361 pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
361 pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']);
362 pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']);
362 pyroutes.register('repo_list_data', '/_repos', []);
363 pyroutes.register('repo_list_data', '/_repos', []);
363 pyroutes.register('repo_new', '/_admin/repos/new', []);
364 pyroutes.register('repo_new', '/_admin/repos/new', []);
364 pyroutes.register('repo_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
365 pyroutes.register('repo_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
365 pyroutes.register('repo_nodetree_full:default_path', '/%(repo_name)s/nodetree_full/%(commit_id)s/', ['repo_name', 'commit_id']);
366 pyroutes.register('repo_nodetree_full:default_path', '/%(repo_name)s/nodetree_full/%(commit_id)s/', ['repo_name', 'commit_id']);
366 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
367 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
367 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
368 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
368 pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']);
369 pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']);
369 pyroutes.register('repo_reviewers_review_rule_delete', '/%(repo_name)s/settings/review/rules/%(rule_id)s/delete', ['repo_name', 'rule_id']);
370 pyroutes.register('repo_reviewers_review_rule_delete', '/%(repo_name)s/settings/review/rules/%(rule_id)s/delete', ['repo_name', 'rule_id']);
370 pyroutes.register('repo_reviewers_review_rule_edit', '/%(repo_name)s/settings/review/rules/%(rule_id)s', ['repo_name', 'rule_id']);
371 pyroutes.register('repo_reviewers_review_rule_edit', '/%(repo_name)s/settings/review/rules/%(rule_id)s', ['repo_name', 'rule_id']);
371 pyroutes.register('repo_reviewers_review_rule_new', '/%(repo_name)s/settings/review/rules/new', ['repo_name']);
372 pyroutes.register('repo_reviewers_review_rule_new', '/%(repo_name)s/settings/review/rules/new', ['repo_name']);
372 pyroutes.register('repo_settings_quick_actions', '/%(repo_name)s/settings/quick-action', ['repo_name']);
373 pyroutes.register('repo_settings_quick_actions', '/%(repo_name)s/settings/quick-action', ['repo_name']);
373 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
374 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
374 pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']);
375 pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']);
375 pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
376 pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
376 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
377 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
377 pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']);
378 pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']);
378 pyroutes.register('repos', '/_admin/repos', []);
379 pyroutes.register('repos', '/_admin/repos', []);
379 pyroutes.register('repos_data', '/_admin/repos_data', []);
380 pyroutes.register('repos_data', '/_admin/repos_data', []);
380 pyroutes.register('reset_password', '/_admin/password_reset', []);
381 pyroutes.register('reset_password', '/_admin/password_reset', []);
381 pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []);
382 pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []);
382 pyroutes.register('robots', '/robots.txt', []);
383 pyroutes.register('robots', '/robots.txt', []);
383 pyroutes.register('rss_feed_home', '/%(repo_name)s/feed-rss', ['repo_name']);
384 pyroutes.register('rss_feed_home', '/%(repo_name)s/feed-rss', ['repo_name']);
384 pyroutes.register('rss_feed_home_old', '/%(repo_name)s/feed/rss', ['repo_name']);
385 pyroutes.register('rss_feed_home_old', '/%(repo_name)s/feed/rss', ['repo_name']);
385 pyroutes.register('search', '/_admin/search', []);
386 pyroutes.register('search', '/_admin/search', []);
386 pyroutes.register('search_repo', '/%(repo_name)s/_search', ['repo_name']);
387 pyroutes.register('search_repo', '/%(repo_name)s/_search', ['repo_name']);
387 pyroutes.register('search_repo_alt', '/%(repo_name)s/search', ['repo_name']);
388 pyroutes.register('search_repo_alt', '/%(repo_name)s/search', ['repo_name']);
388 pyroutes.register('search_repo_group', '/%(repo_group_name)s/_search', ['repo_group_name']);
389 pyroutes.register('search_repo_group', '/%(repo_group_name)s/_search', ['repo_group_name']);
389 pyroutes.register('setup_2fa', '/_admin/setup_2fa', []);
390 pyroutes.register('setup_2fa', '/_admin/setup_2fa', []);
390 pyroutes.register('store_user_session_value', '/_store_session_attr', []);
391 pyroutes.register('store_user_session_value', '/_store_session_attr', []);
391 pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']);
392 pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']);
392 pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']);
393 pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']);
393 pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']);
394 pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']);
394 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
395 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
395 pyroutes.register('upload_file', '/_file_store/upload', []);
396 pyroutes.register('upload_file', '/_file_store/upload', []);
396 pyroutes.register('user_autocomplete_data', '/_users', []);
397 pyroutes.register('user_autocomplete_data', '/_users', []);
397 pyroutes.register('user_create_personal_repo_group', '/_admin/users/%(user_id)s/create_repo_group', ['user_id']);
398 pyroutes.register('user_create_personal_repo_group', '/_admin/users/%(user_id)s/create_repo_group', ['user_id']);
398 pyroutes.register('user_delete', '/_admin/users/%(user_id)s/delete', ['user_id']);
399 pyroutes.register('user_delete', '/_admin/users/%(user_id)s/delete', ['user_id']);
399 pyroutes.register('user_disable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_disable', ['user_id']);
400 pyroutes.register('user_disable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_disable', ['user_id']);
400 pyroutes.register('user_edit', '/_admin/users/%(user_id)s/edit', ['user_id']);
401 pyroutes.register('user_edit', '/_admin/users/%(user_id)s/edit', ['user_id']);
401 pyroutes.register('user_edit_advanced', '/_admin/users/%(user_id)s/edit/advanced', ['user_id']);
402 pyroutes.register('user_edit_advanced', '/_admin/users/%(user_id)s/edit/advanced', ['user_id']);
402 pyroutes.register('user_edit_global_perms', '/_admin/users/%(user_id)s/edit/global_permissions', ['user_id']);
403 pyroutes.register('user_edit_global_perms', '/_admin/users/%(user_id)s/edit/global_permissions', ['user_id']);
403 pyroutes.register('user_edit_global_perms_update', '/_admin/users/%(user_id)s/edit/global_permissions/update', ['user_id']);
404 pyroutes.register('user_edit_global_perms_update', '/_admin/users/%(user_id)s/edit/global_permissions/update', ['user_id']);
404 pyroutes.register('user_enable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_enable', ['user_id']);
405 pyroutes.register('user_enable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_enable', ['user_id']);
405 pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
406 pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
406 pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']);
407 pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']);
407 pyroutes.register('user_group_profile', '/_profile_user_group/%(user_group_name)s', ['user_group_name']);
408 pyroutes.register('user_group_profile', '/_profile_user_group/%(user_group_name)s', ['user_group_name']);
408 pyroutes.register('user_groups', '/_admin/user_groups', []);
409 pyroutes.register('user_groups', '/_admin/user_groups', []);
409 pyroutes.register('user_groups_create', '/_admin/user_groups/create', []);
410 pyroutes.register('user_groups_create', '/_admin/user_groups/create', []);
410 pyroutes.register('user_groups_data', '/_admin/user_groups_data', []);
411 pyroutes.register('user_groups_data', '/_admin/user_groups_data', []);
411 pyroutes.register('user_groups_delete', '/_admin/user_groups/%(user_group_id)s/delete', ['user_group_id']);
412 pyroutes.register('user_groups_delete', '/_admin/user_groups/%(user_group_id)s/delete', ['user_group_id']);
412 pyroutes.register('user_groups_new', '/_admin/user_groups/new', []);
413 pyroutes.register('user_groups_new', '/_admin/user_groups/new', []);
413 pyroutes.register('user_groups_update', '/_admin/user_groups/%(user_group_id)s/update', ['user_group_id']);
414 pyroutes.register('user_groups_update', '/_admin/user_groups/%(user_group_id)s/update', ['user_group_id']);
414 pyroutes.register('user_notice_dismiss', '/_admin/users/%(user_id)s/notice_dismiss', ['user_id']);
415 pyroutes.register('user_notice_dismiss', '/_admin/users/%(user_id)s/notice_dismiss', ['user_id']);
415 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
416 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
416 pyroutes.register('user_update', '/_admin/users/%(user_id)s/update', ['user_id']);
417 pyroutes.register('user_update', '/_admin/users/%(user_id)s/update', ['user_id']);
417 pyroutes.register('users', '/_admin/users', []);
418 pyroutes.register('users', '/_admin/users', []);
418 pyroutes.register('users_create', '/_admin/users/create', []);
419 pyroutes.register('users_create', '/_admin/users/create', []);
419 pyroutes.register('users_data', '/_admin/users_data', []);
420 pyroutes.register('users_data', '/_admin/users_data', []);
420 pyroutes.register('users_new', '/_admin/users/new', []);
421 pyroutes.register('users_new', '/_admin/users/new', []);
421 }
422 }
@@ -1,40 +1,79 b''
1 <%inherit file="/base/base.mako"/>
1 <%inherit file="/base/base.mako"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${_('Security Admin')}
4 ${_('Security Admin')}
5 %if c.rhodecode_name:
5 %if c.rhodecode_name:
6 &middot; ${h.branding(c.rhodecode_name)}
6 &middot; ${h.branding(c.rhodecode_name)}
7 %endif
7 %endif
8 </%def>
8 </%def>
9
9
10 <%def name="breadcrumbs_links()"></%def>
10 <%def name="breadcrumbs_links()"></%def>
11
11
12 <%def name="menu_bar_nav()">
12 <%def name="menu_bar_nav()">
13 ${self.menu_items(active='admin')}
13 ${self.menu_items(active='admin')}
14 </%def>
14 </%def>
15
15
16 <%def name="menu_bar_subnav()">
16 <%def name="menu_bar_subnav()">
17 ${self.admin_menu(active='security')}
17 ${self.admin_menu(active='security')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21
21
22 <div class="box">
22 <div class="box">
23
23
24 <div class="panel panel-default">
24 <div class="panel panel-default">
25 <div class="panel-heading">
25 <div class="panel-heading">
26 <h3 class="panel-title">${_('Security Audit')}</h3>
26 <h3 class="panel-title">${_('Security Audit')}</h3>
27 </div>
27 </div>
28 <div class="panel-body">
28 <div class="panel-body">
29 <h4>${_('This feature is available in RhodeCode EE edition only. Contact {sales_email} to obtain a trial license.').format(sales_email='<a href="mailto:sales@rhodecode.com">sales@rhodecode.com</a>')|n}</h4>
29 <h4>${_('This feature is available in RhodeCode EE edition only. Contact {sales_email} to obtain a trial license.').format(sales_email='<a href="mailto:sales@rhodecode.com">sales@rhodecode.com</a>')|n}</h4>
30 <p>
30 <p>
31 You can scan your repositories for exposed secrets, passwords, etc
31 ${_('You can scan your repositories for exposed secrets, passwords, etc')}
32 </p>
32 </p>
33 </div>
33 </div>
34 </div>
34 </div>
35
35
36 <div class="panel panel-default">
37 <div class="panel-heading">
38 <h3 class="panel-title">${_('Allowed client versions')}</h3>
39 </div>
40 <div class="panel-body">
41 %if c.rhodecode_edition_id != 'EE':
42 <h4>${_('This feature is available in RhodeCode EE edition only. Contact {sales_email} to obtain a trial license.').format(sales_email='<a href="mailto:sales@rhodecode.com">sales@rhodecode.com</a>')|n}</h4>
43 <p>
44 ${_('Some outdated client versions may have security vulnerabilities. This section have rules for whitelisting versions of clients for Git, Mercurial and SVN.')}
45 </p>
46 %else:
47 <div class="inner form" id="container">
48 </div>
49 %endif
50 </div>
51
36 </div>
52 </div>
37
53
54 <script>
55 $(document).ready(function() {
56 $.ajax({
57 url: pyroutes.url('admin_security_modify_allowed_vcs_client_versions'),
58 type: 'GET',
59 success: function(response) {
60 $('#container').html(response);
61 },
62 });
63 $(document).on('submit', '#allowed_clients_form', function(event) {
64 event.preventDefault();
65 var formData = $(this).serialize();
66
67 $.ajax({
68 url: pyroutes.url('admin_security_modify_allowed_vcs_client_versions'),
69 type: 'POST',
70 data: formData,
71 success: function(response) {
72 $('#container').html(response);
73 },
74 });
75 });
76 });
77 </script>
38
78
39 </%def>
79 </%def>
40
General Comments 0
You need to be logged in to leave comments. Login now