##// END OF EJS Templates
update issue tracker and official site
marcink -
r4099:43b54436 default
parent child Browse files
Show More
@@ -1,709 +1,710 b''
1 """
1 """
2 Routes configuration
2 Routes configuration
3
3
4 The more specific and detailed routes should be defined first so they
4 The more specific and detailed routes should be defined first so they
5 may take precedent over the more generic routes. For more information
5 may take precedent over the more generic routes. For more information
6 refer to the routes manual at http://routes.groovie.org/docs/
6 refer to the routes manual at http://routes.groovie.org/docs/
7 """
7 """
8 from __future__ import with_statement
8 from __future__ import with_statement
9 from routes import Mapper
9 from routes import Mapper
10
10
11 # prefix for non repository related links needs to be prefixed with `/`
11 # prefix for non repository related links needs to be prefixed with `/`
12 ADMIN_PREFIX = '/_admin'
12 ADMIN_PREFIX = '/_admin'
13
13
14
14
15 def make_map(config):
15 def make_map(config):
16 """Create, configure and return the routes Mapper"""
16 """Create, configure and return the routes Mapper"""
17 rmap = Mapper(directory=config['pylons.paths']['controllers'],
17 rmap = Mapper(directory=config['pylons.paths']['controllers'],
18 always_scan=config['debug'])
18 always_scan=config['debug'])
19 rmap.minimization = False
19 rmap.minimization = False
20 rmap.explicit = False
20 rmap.explicit = False
21
21
22 from rhodecode.lib.utils import is_valid_repo
22 from rhodecode.lib.utils import is_valid_repo
23 from rhodecode.lib.utils import is_valid_repos_group
23 from rhodecode.lib.utils import is_valid_repos_group
24
24
25 def check_repo(environ, match_dict):
25 def check_repo(environ, match_dict):
26 """
26 """
27 check for valid repository for proper 404 handling
27 check for valid repository for proper 404 handling
28
28
29 :param environ:
29 :param environ:
30 :param match_dict:
30 :param match_dict:
31 """
31 """
32 from rhodecode.model.db import Repository
32 from rhodecode.model.db import Repository
33 repo_name = match_dict.get('repo_name')
33 repo_name = match_dict.get('repo_name')
34
34
35 if match_dict.get('f_path'):
35 if match_dict.get('f_path'):
36 #fix for multiple initial slashes that causes errors
36 #fix for multiple initial slashes that causes errors
37 match_dict['f_path'] = match_dict['f_path'].lstrip('/')
37 match_dict['f_path'] = match_dict['f_path'].lstrip('/')
38
38
39 try:
39 try:
40 by_id = repo_name.split('_')
40 by_id = repo_name.split('_')
41 if len(by_id) == 2 and by_id[1].isdigit() and by_id[0] == '':
41 if len(by_id) == 2 and by_id[1].isdigit() and by_id[0] == '':
42 repo_name = Repository.get(by_id[1]).repo_name
42 repo_name = Repository.get(by_id[1]).repo_name
43 match_dict['repo_name'] = repo_name
43 match_dict['repo_name'] = repo_name
44 except Exception:
44 except Exception:
45 pass
45 pass
46
46
47 return is_valid_repo(repo_name, config['base_path'])
47 return is_valid_repo(repo_name, config['base_path'])
48
48
49 def check_group(environ, match_dict):
49 def check_group(environ, match_dict):
50 """
50 """
51 check for valid repository group for proper 404 handling
51 check for valid repository group for proper 404 handling
52
52
53 :param environ:
53 :param environ:
54 :param match_dict:
54 :param match_dict:
55 """
55 """
56 repos_group_name = match_dict.get('group_name')
56 repos_group_name = match_dict.get('group_name')
57 return is_valid_repos_group(repos_group_name, config['base_path'])
57 return is_valid_repos_group(repos_group_name, config['base_path'])
58
58
59 def check_group_skip_path(environ, match_dict):
59 def check_group_skip_path(environ, match_dict):
60 """
60 """
61 check for valid repository group for proper 404 handling, but skips
61 check for valid repository group for proper 404 handling, but skips
62 verification of existing path
62 verification of existing path
63
63
64 :param environ:
64 :param environ:
65 :param match_dict:
65 :param match_dict:
66 """
66 """
67 repos_group_name = match_dict.get('group_name')
67 repos_group_name = match_dict.get('group_name')
68 return is_valid_repos_group(repos_group_name, config['base_path'],
68 return is_valid_repos_group(repos_group_name, config['base_path'],
69 skip_path_check=True)
69 skip_path_check=True)
70
70
71 def check_user_group(environ, match_dict):
71 def check_user_group(environ, match_dict):
72 """
72 """
73 check for valid user group for proper 404 handling
73 check for valid user group for proper 404 handling
74
74
75 :param environ:
75 :param environ:
76 :param match_dict:
76 :param match_dict:
77 """
77 """
78 return True
78 return True
79
79
80 def check_int(environ, match_dict):
80 def check_int(environ, match_dict):
81 return match_dict.get('id').isdigit()
81 return match_dict.get('id').isdigit()
82
82
83 # The ErrorController route (handles 404/500 error pages); it should
83 # The ErrorController route (handles 404/500 error pages); it should
84 # likely stay at the top, ensuring it can always be resolved
84 # likely stay at the top, ensuring it can always be resolved
85 rmap.connect('/error/{action}', controller='error')
85 rmap.connect('/error/{action}', controller='error')
86 rmap.connect('/error/{action}/{id}', controller='error')
86 rmap.connect('/error/{action}/{id}', controller='error')
87
87
88 #==========================================================================
88 #==========================================================================
89 # CUSTOM ROUTES HERE
89 # CUSTOM ROUTES HERE
90 #==========================================================================
90 #==========================================================================
91
91
92 #MAIN PAGE
92 #MAIN PAGE
93 rmap.connect('home', '/', controller='home', action='index')
93 rmap.connect('home', '/', controller='home', action='index')
94 rmap.connect('repo_switcher', '/repos', controller='home',
94 rmap.connect('repo_switcher', '/repos', controller='home',
95 action='repo_switcher')
95 action='repo_switcher')
96 rmap.connect('branch_tag_switcher', '/branches-tags/{repo_name:.*?}',
96 rmap.connect('branch_tag_switcher', '/branches-tags/{repo_name:.*?}',
97 controller='home', action='branch_tag_switcher')
97 controller='home', action='branch_tag_switcher')
98 rmap.connect('rst_help',
98 rmap.connect('rst_help',
99 "http://docutils.sourceforge.net/docs/user/rst/quickref.html",
99 "http://docutils.sourceforge.net/docs/user/rst/quickref.html",
100 _static=True)
100 _static=True)
101 rmap.connect('rhodecode_official', "http://rhodecode.org", _static=True)
101 rmap.connect('rhodecode_official', "https://rhodecode.com", _static=True)
102 rmap.connect('rc_issue_tracker', 'https://rhodecode.com/help/', _static=True)
102
103
103 #ADMIN REPOSITORY REST ROUTES
104 #ADMIN REPOSITORY REST ROUTES
104 with rmap.submapper(path_prefix=ADMIN_PREFIX,
105 with rmap.submapper(path_prefix=ADMIN_PREFIX,
105 controller='admin/repos') as m:
106 controller='admin/repos') as m:
106 m.connect("repos", "/repos",
107 m.connect("repos", "/repos",
107 action="create", conditions=dict(method=["POST"]))
108 action="create", conditions=dict(method=["POST"]))
108 m.connect("repos", "/repos",
109 m.connect("repos", "/repos",
109 action="index", conditions=dict(method=["GET"]))
110 action="index", conditions=dict(method=["GET"]))
110 m.connect("formatted_repos", "/repos.{format}",
111 m.connect("formatted_repos", "/repos.{format}",
111 action="index",
112 action="index",
112 conditions=dict(method=["GET"]))
113 conditions=dict(method=["GET"]))
113 m.connect("new_repo", "/create_repository",
114 m.connect("new_repo", "/create_repository",
114 action="create_repository", conditions=dict(method=["GET"]))
115 action="create_repository", conditions=dict(method=["GET"]))
115 m.connect("/repos/{repo_name:.*?}",
116 m.connect("/repos/{repo_name:.*?}",
116 action="update", conditions=dict(method=["PUT"],
117 action="update", conditions=dict(method=["PUT"],
117 function=check_repo))
118 function=check_repo))
118 m.connect("/repos/{repo_name:.*?}",
119 m.connect("/repos/{repo_name:.*?}",
119 action="delete", conditions=dict(method=["DELETE"],
120 action="delete", conditions=dict(method=["DELETE"],
120 function=check_repo))
121 function=check_repo))
121 m.connect("formatted_edit_repo", "/repos/{repo_name:.*?}.{format}/edit",
122 m.connect("formatted_edit_repo", "/repos/{repo_name:.*?}.{format}/edit",
122 action="edit", conditions=dict(method=["GET"],
123 action="edit", conditions=dict(method=["GET"],
123 function=check_repo))
124 function=check_repo))
124 m.connect("repo", "/repos/{repo_name:.*?}",
125 m.connect("repo", "/repos/{repo_name:.*?}",
125 action="show", conditions=dict(method=["GET"],
126 action="show", conditions=dict(method=["GET"],
126 function=check_repo))
127 function=check_repo))
127 m.connect("formatted_repo", "/repos/{repo_name:.*?}.{format}",
128 m.connect("formatted_repo", "/repos/{repo_name:.*?}.{format}",
128 action="show", conditions=dict(method=["GET"],
129 action="show", conditions=dict(method=["GET"],
129 function=check_repo))
130 function=check_repo))
130 #add repo perm member
131 #add repo perm member
131 m.connect('set_repo_perm_member',
132 m.connect('set_repo_perm_member',
132 "/repos/{repo_name:.*?}/grant_perm",
133 "/repos/{repo_name:.*?}/grant_perm",
133 action="set_repo_perm_member",
134 action="set_repo_perm_member",
134 conditions=dict(method=["POST"], function=check_repo))
135 conditions=dict(method=["POST"], function=check_repo))
135
136
136 #ajax delete repo perm user
137 #ajax delete repo perm user
137 m.connect('delete_repo_perm_member',
138 m.connect('delete_repo_perm_member',
138 "/repos/{repo_name:.*?}/revoke_perm",
139 "/repos/{repo_name:.*?}/revoke_perm",
139 action="delete_repo_perm_member",
140 action="delete_repo_perm_member",
140 conditions=dict(method=["DELETE"], function=check_repo))
141 conditions=dict(method=["DELETE"], function=check_repo))
141
142
142 #settings actions
143 #settings actions
143 m.connect('repo_stats', "/repos_stats/{repo_name:.*?}",
144 m.connect('repo_stats', "/repos_stats/{repo_name:.*?}",
144 action="repo_stats", conditions=dict(method=["DELETE"],
145 action="repo_stats", conditions=dict(method=["DELETE"],
145 function=check_repo))
146 function=check_repo))
146 m.connect('repo_cache', "/repos_cache/{repo_name:.*?}",
147 m.connect('repo_cache', "/repos_cache/{repo_name:.*?}",
147 action="repo_cache", conditions=dict(method=["DELETE"],
148 action="repo_cache", conditions=dict(method=["DELETE"],
148 function=check_repo))
149 function=check_repo))
149 m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*?}",
150 m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*?}",
150 action="repo_public_journal", conditions=dict(method=["PUT"],
151 action="repo_public_journal", conditions=dict(method=["PUT"],
151 function=check_repo))
152 function=check_repo))
152 m.connect('repo_pull', "/repo_pull/{repo_name:.*?}",
153 m.connect('repo_pull', "/repo_pull/{repo_name:.*?}",
153 action="repo_pull", conditions=dict(method=["PUT"],
154 action="repo_pull", conditions=dict(method=["PUT"],
154 function=check_repo))
155 function=check_repo))
155 m.connect('repo_as_fork', "/repo_as_fork/{repo_name:.*?}",
156 m.connect('repo_as_fork', "/repo_as_fork/{repo_name:.*?}",
156 action="repo_as_fork", conditions=dict(method=["PUT"],
157 action="repo_as_fork", conditions=dict(method=["PUT"],
157 function=check_repo))
158 function=check_repo))
158 m.connect('repo_locking', "/repo_locking/{repo_name:.*?}",
159 m.connect('repo_locking', "/repo_locking/{repo_name:.*?}",
159 action="repo_locking", conditions=dict(method=["PUT"],
160 action="repo_locking", conditions=dict(method=["PUT"],
160 function=check_repo))
161 function=check_repo))
161 m.connect('toggle_locking', "/locking_toggle/{repo_name:.*?}",
162 m.connect('toggle_locking', "/locking_toggle/{repo_name:.*?}",
162 action="toggle_locking", conditions=dict(method=["GET"],
163 action="toggle_locking", conditions=dict(method=["GET"],
163 function=check_repo))
164 function=check_repo))
164
165
165 #repo fields
166 #repo fields
166 m.connect('create_repo_fields', "/repo_fields/{repo_name:.*?}/new",
167 m.connect('create_repo_fields', "/repo_fields/{repo_name:.*?}/new",
167 action="create_repo_field", conditions=dict(method=["PUT"],
168 action="create_repo_field", conditions=dict(method=["PUT"],
168 function=check_repo))
169 function=check_repo))
169
170
170 m.connect('delete_repo_fields', "/repo_fields/{repo_name:.*?}/{field_id}",
171 m.connect('delete_repo_fields', "/repo_fields/{repo_name:.*?}/{field_id}",
171 action="delete_repo_field", conditions=dict(method=["DELETE"],
172 action="delete_repo_field", conditions=dict(method=["DELETE"],
172 function=check_repo))
173 function=check_repo))
173
174
174 with rmap.submapper(path_prefix=ADMIN_PREFIX,
175 with rmap.submapper(path_prefix=ADMIN_PREFIX,
175 controller='admin/repos_groups') as m:
176 controller='admin/repos_groups') as m:
176 m.connect("repos_groups", "/repos_groups",
177 m.connect("repos_groups", "/repos_groups",
177 action="create", conditions=dict(method=["POST"]))
178 action="create", conditions=dict(method=["POST"]))
178 m.connect("repos_groups", "/repos_groups",
179 m.connect("repos_groups", "/repos_groups",
179 action="index", conditions=dict(method=["GET"]))
180 action="index", conditions=dict(method=["GET"]))
180 m.connect("formatted_repos_groups", "/repos_groups.{format}",
181 m.connect("formatted_repos_groups", "/repos_groups.{format}",
181 action="index", conditions=dict(method=["GET"]))
182 action="index", conditions=dict(method=["GET"]))
182 m.connect("new_repos_group", "/repos_groups/new",
183 m.connect("new_repos_group", "/repos_groups/new",
183 action="new", conditions=dict(method=["GET"]))
184 action="new", conditions=dict(method=["GET"]))
184 m.connect("formatted_new_repos_group", "/repos_groups/new.{format}",
185 m.connect("formatted_new_repos_group", "/repos_groups/new.{format}",
185 action="new", conditions=dict(method=["GET"]))
186 action="new", conditions=dict(method=["GET"]))
186 m.connect("update_repos_group", "/repos_groups/{group_name:.*?}",
187 m.connect("update_repos_group", "/repos_groups/{group_name:.*?}",
187 action="update", conditions=dict(method=["PUT"],
188 action="update", conditions=dict(method=["PUT"],
188 function=check_group))
189 function=check_group))
189 #add repo group perm member
190 #add repo group perm member
190 m.connect('set_repo_group_perm_member',
191 m.connect('set_repo_group_perm_member',
191 "/repos_groups/{group_name:.*?}/grant_perm",
192 "/repos_groups/{group_name:.*?}/grant_perm",
192 action="set_repo_group_perm_member",
193 action="set_repo_group_perm_member",
193 conditions=dict(method=["POST"], function=check_group))
194 conditions=dict(method=["POST"], function=check_group))
194
195
195 #ajax delete repo group perm
196 #ajax delete repo group perm
196 m.connect('delete_repo_group_perm_member',
197 m.connect('delete_repo_group_perm_member',
197 "/repos_groups/{group_name:.*?}/revoke_perm",
198 "/repos_groups/{group_name:.*?}/revoke_perm",
198 action="delete_repo_group_perm_member",
199 action="delete_repo_group_perm_member",
199 conditions=dict(method=["DELETE"], function=check_group))
200 conditions=dict(method=["DELETE"], function=check_group))
200
201
201 m.connect("delete_repos_group", "/repos_groups/{group_name:.*?}",
202 m.connect("delete_repos_group", "/repos_groups/{group_name:.*?}",
202 action="delete", conditions=dict(method=["DELETE"],
203 action="delete", conditions=dict(method=["DELETE"],
203 function=check_group_skip_path))
204 function=check_group_skip_path))
204 m.connect("edit_repos_group", "/repos_groups/{group_name:.*?}/edit",
205 m.connect("edit_repos_group", "/repos_groups/{group_name:.*?}/edit",
205 action="edit", conditions=dict(method=["GET"],
206 action="edit", conditions=dict(method=["GET"],
206 function=check_group))
207 function=check_group))
207 m.connect("formatted_edit_repos_group",
208 m.connect("formatted_edit_repos_group",
208 "/repos_groups/{group_name:.*?}.{format}/edit",
209 "/repos_groups/{group_name:.*?}.{format}/edit",
209 action="edit", conditions=dict(method=["GET"],
210 action="edit", conditions=dict(method=["GET"],
210 function=check_group))
211 function=check_group))
211 m.connect("repos_group", "/repos_groups/{group_name:.*?}",
212 m.connect("repos_group", "/repos_groups/{group_name:.*?}",
212 action="show", conditions=dict(method=["GET"],
213 action="show", conditions=dict(method=["GET"],
213 function=check_group))
214 function=check_group))
214 m.connect("formatted_repos_group", "/repos_groups/{group_name:.*?}.{format}",
215 m.connect("formatted_repos_group", "/repos_groups/{group_name:.*?}.{format}",
215 action="show", conditions=dict(method=["GET"],
216 action="show", conditions=dict(method=["GET"],
216 function=check_group))
217 function=check_group))
217
218
218 #ADMIN USER REST ROUTES
219 #ADMIN USER REST ROUTES
219 with rmap.submapper(path_prefix=ADMIN_PREFIX,
220 with rmap.submapper(path_prefix=ADMIN_PREFIX,
220 controller='admin/users') as m:
221 controller='admin/users') as m:
221 m.connect("users", "/users",
222 m.connect("users", "/users",
222 action="create", conditions=dict(method=["POST"]))
223 action="create", conditions=dict(method=["POST"]))
223 m.connect("users", "/users",
224 m.connect("users", "/users",
224 action="index", conditions=dict(method=["GET"]))
225 action="index", conditions=dict(method=["GET"]))
225 m.connect("formatted_users", "/users.{format}",
226 m.connect("formatted_users", "/users.{format}",
226 action="index", conditions=dict(method=["GET"]))
227 action="index", conditions=dict(method=["GET"]))
227 m.connect("new_user", "/users/new",
228 m.connect("new_user", "/users/new",
228 action="new", conditions=dict(method=["GET"]))
229 action="new", conditions=dict(method=["GET"]))
229 m.connect("formatted_new_user", "/users/new.{format}",
230 m.connect("formatted_new_user", "/users/new.{format}",
230 action="new", conditions=dict(method=["GET"]))
231 action="new", conditions=dict(method=["GET"]))
231 m.connect("update_user", "/users/{id}",
232 m.connect("update_user", "/users/{id}",
232 action="update", conditions=dict(method=["PUT"]))
233 action="update", conditions=dict(method=["PUT"]))
233 m.connect("delete_user", "/users/{id}",
234 m.connect("delete_user", "/users/{id}",
234 action="delete", conditions=dict(method=["DELETE"]))
235 action="delete", conditions=dict(method=["DELETE"]))
235 m.connect("edit_user", "/users/{id}/edit",
236 m.connect("edit_user", "/users/{id}/edit",
236 action="edit", conditions=dict(method=["GET"]))
237 action="edit", conditions=dict(method=["GET"]))
237 m.connect("formatted_edit_user",
238 m.connect("formatted_edit_user",
238 "/users/{id}.{format}/edit",
239 "/users/{id}.{format}/edit",
239 action="edit", conditions=dict(method=["GET"]))
240 action="edit", conditions=dict(method=["GET"]))
240 m.connect("user", "/users/{id}",
241 m.connect("user", "/users/{id}",
241 action="show", conditions=dict(method=["GET"]))
242 action="show", conditions=dict(method=["GET"]))
242 m.connect("formatted_user", "/users/{id}.{format}",
243 m.connect("formatted_user", "/users/{id}.{format}",
243 action="show", conditions=dict(method=["GET"]))
244 action="show", conditions=dict(method=["GET"]))
244
245
245 #EXTRAS USER ROUTES
246 #EXTRAS USER ROUTES
246 m.connect("user_perm", "/users_perm/{id}",
247 m.connect("user_perm", "/users_perm/{id}",
247 action="update_perm", conditions=dict(method=["PUT"]))
248 action="update_perm", conditions=dict(method=["PUT"]))
248 m.connect("user_emails", "/users_emails/{id}",
249 m.connect("user_emails", "/users_emails/{id}",
249 action="add_email", conditions=dict(method=["PUT"]))
250 action="add_email", conditions=dict(method=["PUT"]))
250 m.connect("user_emails_delete", "/users_emails/{id}",
251 m.connect("user_emails_delete", "/users_emails/{id}",
251 action="delete_email", conditions=dict(method=["DELETE"]))
252 action="delete_email", conditions=dict(method=["DELETE"]))
252 m.connect("user_ips", "/users_ips/{id}",
253 m.connect("user_ips", "/users_ips/{id}",
253 action="add_ip", conditions=dict(method=["PUT"]))
254 action="add_ip", conditions=dict(method=["PUT"]))
254 m.connect("user_ips_delete", "/users_ips/{id}",
255 m.connect("user_ips_delete", "/users_ips/{id}",
255 action="delete_ip", conditions=dict(method=["DELETE"]))
256 action="delete_ip", conditions=dict(method=["DELETE"]))
256
257
257 #ADMIN USER GROUPS REST ROUTES
258 #ADMIN USER GROUPS REST ROUTES
258 with rmap.submapper(path_prefix=ADMIN_PREFIX,
259 with rmap.submapper(path_prefix=ADMIN_PREFIX,
259 controller='admin/users_groups') as m:
260 controller='admin/users_groups') as m:
260 m.connect("users_groups", "/users_groups",
261 m.connect("users_groups", "/users_groups",
261 action="create", conditions=dict(method=["POST"]))
262 action="create", conditions=dict(method=["POST"]))
262 m.connect("users_groups", "/users_groups",
263 m.connect("users_groups", "/users_groups",
263 action="index", conditions=dict(method=["GET"]))
264 action="index", conditions=dict(method=["GET"]))
264 m.connect("formatted_users_groups", "/users_groups.{format}",
265 m.connect("formatted_users_groups", "/users_groups.{format}",
265 action="index", conditions=dict(method=["GET"]))
266 action="index", conditions=dict(method=["GET"]))
266 m.connect("new_users_group", "/users_groups/new",
267 m.connect("new_users_group", "/users_groups/new",
267 action="new", conditions=dict(method=["GET"]))
268 action="new", conditions=dict(method=["GET"]))
268 m.connect("formatted_new_users_group", "/users_groups/new.{format}",
269 m.connect("formatted_new_users_group", "/users_groups/new.{format}",
269 action="new", conditions=dict(method=["GET"]))
270 action="new", conditions=dict(method=["GET"]))
270 m.connect("update_users_group", "/users_groups/{id}",
271 m.connect("update_users_group", "/users_groups/{id}",
271 action="update", conditions=dict(method=["PUT"]))
272 action="update", conditions=dict(method=["PUT"]))
272 m.connect("delete_users_group", "/users_groups/{id}",
273 m.connect("delete_users_group", "/users_groups/{id}",
273 action="delete", conditions=dict(method=["DELETE"]))
274 action="delete", conditions=dict(method=["DELETE"]))
274 m.connect("edit_users_group", "/users_groups/{id}/edit",
275 m.connect("edit_users_group", "/users_groups/{id}/edit",
275 action="edit", conditions=dict(method=["GET"]),
276 action="edit", conditions=dict(method=["GET"]),
276 function=check_user_group)
277 function=check_user_group)
277 m.connect("formatted_edit_users_group",
278 m.connect("formatted_edit_users_group",
278 "/users_groups/{id}.{format}/edit",
279 "/users_groups/{id}.{format}/edit",
279 action="edit", conditions=dict(method=["GET"]))
280 action="edit", conditions=dict(method=["GET"]))
280 m.connect("users_group", "/users_groups/{id}",
281 m.connect("users_group", "/users_groups/{id}",
281 action="show", conditions=dict(method=["GET"]))
282 action="show", conditions=dict(method=["GET"]))
282 m.connect("formatted_users_group", "/users_groups/{id}.{format}",
283 m.connect("formatted_users_group", "/users_groups/{id}.{format}",
283 action="show", conditions=dict(method=["GET"]))
284 action="show", conditions=dict(method=["GET"]))
284
285
285 #EXTRAS USER ROUTES
286 #EXTRAS USER ROUTES
286 # update
287 # update
287 m.connect("users_group_perm", "/users_groups/{id}/update_global_perm",
288 m.connect("users_group_perm", "/users_groups/{id}/update_global_perm",
288 action="update_perm", conditions=dict(method=["PUT"]))
289 action="update_perm", conditions=dict(method=["PUT"]))
289
290
290 #add user group perm member
291 #add user group perm member
291 m.connect('set_user_group_perm_member', "/users_groups/{id}/grant_perm",
292 m.connect('set_user_group_perm_member', "/users_groups/{id}/grant_perm",
292 action="set_user_group_perm_member",
293 action="set_user_group_perm_member",
293 conditions=dict(method=["POST"]))
294 conditions=dict(method=["POST"]))
294
295
295 #ajax delete user group perm
296 #ajax delete user group perm
296 m.connect('delete_user_group_perm_member', "/users_groups/{id}/revoke_perm",
297 m.connect('delete_user_group_perm_member', "/users_groups/{id}/revoke_perm",
297 action="delete_user_group_perm_member",
298 action="delete_user_group_perm_member",
298 conditions=dict(method=["DELETE"]))
299 conditions=dict(method=["DELETE"]))
299
300
300 #ADMIN GROUP REST ROUTES
301 #ADMIN GROUP REST ROUTES
301 rmap.resource('group', 'groups',
302 rmap.resource('group', 'groups',
302 controller='admin/groups', path_prefix=ADMIN_PREFIX)
303 controller='admin/groups', path_prefix=ADMIN_PREFIX)
303
304
304 #ADMIN PERMISSIONS REST ROUTES
305 #ADMIN PERMISSIONS REST ROUTES
305 rmap.resource('permission', 'permissions',
306 rmap.resource('permission', 'permissions',
306 controller='admin/permissions', path_prefix=ADMIN_PREFIX)
307 controller='admin/permissions', path_prefix=ADMIN_PREFIX)
307
308
308 #ADMIN DEFAULTS REST ROUTES
309 #ADMIN DEFAULTS REST ROUTES
309 rmap.resource('default', 'defaults',
310 rmap.resource('default', 'defaults',
310 controller='admin/defaults', path_prefix=ADMIN_PREFIX)
311 controller='admin/defaults', path_prefix=ADMIN_PREFIX)
311
312
312 ##ADMIN LDAP SETTINGS
313 ##ADMIN LDAP SETTINGS
313 rmap.connect('ldap_settings', '%s/ldap' % ADMIN_PREFIX,
314 rmap.connect('ldap_settings', '%s/ldap' % ADMIN_PREFIX,
314 controller='admin/ldap_settings', action='ldap_settings',
315 controller='admin/ldap_settings', action='ldap_settings',
315 conditions=dict(method=["POST"]))
316 conditions=dict(method=["POST"]))
316
317
317 rmap.connect('ldap_home', '%s/ldap' % ADMIN_PREFIX,
318 rmap.connect('ldap_home', '%s/ldap' % ADMIN_PREFIX,
318 controller='admin/ldap_settings')
319 controller='admin/ldap_settings')
319
320
320 #ADMIN SETTINGS REST ROUTES
321 #ADMIN SETTINGS REST ROUTES
321 with rmap.submapper(path_prefix=ADMIN_PREFIX,
322 with rmap.submapper(path_prefix=ADMIN_PREFIX,
322 controller='admin/settings') as m:
323 controller='admin/settings') as m:
323 m.connect("admin_settings", "/settings",
324 m.connect("admin_settings", "/settings",
324 action="create", conditions=dict(method=["POST"]))
325 action="create", conditions=dict(method=["POST"]))
325 m.connect("admin_settings", "/settings",
326 m.connect("admin_settings", "/settings",
326 action="index", conditions=dict(method=["GET"]))
327 action="index", conditions=dict(method=["GET"]))
327 m.connect("formatted_admin_settings", "/settings.{format}",
328 m.connect("formatted_admin_settings", "/settings.{format}",
328 action="index", conditions=dict(method=["GET"]))
329 action="index", conditions=dict(method=["GET"]))
329 m.connect("admin_new_setting", "/settings/new",
330 m.connect("admin_new_setting", "/settings/new",
330 action="new", conditions=dict(method=["GET"]))
331 action="new", conditions=dict(method=["GET"]))
331 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
332 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
332 action="new", conditions=dict(method=["GET"]))
333 action="new", conditions=dict(method=["GET"]))
333 m.connect("/settings/{setting_id}",
334 m.connect("/settings/{setting_id}",
334 action="update", conditions=dict(method=["PUT"]))
335 action="update", conditions=dict(method=["PUT"]))
335 m.connect("/settings/{setting_id}",
336 m.connect("/settings/{setting_id}",
336 action="delete", conditions=dict(method=["DELETE"]))
337 action="delete", conditions=dict(method=["DELETE"]))
337 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
338 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
338 action="edit", conditions=dict(method=["GET"]))
339 action="edit", conditions=dict(method=["GET"]))
339 m.connect("formatted_admin_edit_setting",
340 m.connect("formatted_admin_edit_setting",
340 "/settings/{setting_id}.{format}/edit",
341 "/settings/{setting_id}.{format}/edit",
341 action="edit", conditions=dict(method=["GET"]))
342 action="edit", conditions=dict(method=["GET"]))
342 m.connect("admin_setting", "/settings/{setting_id}",
343 m.connect("admin_setting", "/settings/{setting_id}",
343 action="show", conditions=dict(method=["GET"]))
344 action="show", conditions=dict(method=["GET"]))
344 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
345 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
345 action="show", conditions=dict(method=["GET"]))
346 action="show", conditions=dict(method=["GET"]))
346 m.connect("admin_settings_my_account", "/my_account",
347 m.connect("admin_settings_my_account", "/my_account",
347 action="my_account", conditions=dict(method=["GET"]))
348 action="my_account", conditions=dict(method=["GET"]))
348 m.connect("admin_settings_my_account_update", "/my_account_update",
349 m.connect("admin_settings_my_account_update", "/my_account_update",
349 action="my_account_update", conditions=dict(method=["PUT"]))
350 action="my_account_update", conditions=dict(method=["PUT"]))
350 m.connect("admin_settings_my_repos", "/my_account/repos",
351 m.connect("admin_settings_my_repos", "/my_account/repos",
351 action="my_account_my_repos", conditions=dict(method=["GET"]))
352 action="my_account_my_repos", conditions=dict(method=["GET"]))
352 m.connect("admin_settings_my_pullrequests", "/my_account/pull_requests",
353 m.connect("admin_settings_my_pullrequests", "/my_account/pull_requests",
353 action="my_account_my_pullrequests", conditions=dict(method=["GET"]))
354 action="my_account_my_pullrequests", conditions=dict(method=["GET"]))
354
355
355 #NOTIFICATION REST ROUTES
356 #NOTIFICATION REST ROUTES
356 with rmap.submapper(path_prefix=ADMIN_PREFIX,
357 with rmap.submapper(path_prefix=ADMIN_PREFIX,
357 controller='admin/notifications') as m:
358 controller='admin/notifications') as m:
358 m.connect("notifications", "/notifications",
359 m.connect("notifications", "/notifications",
359 action="create", conditions=dict(method=["POST"]))
360 action="create", conditions=dict(method=["POST"]))
360 m.connect("notifications", "/notifications",
361 m.connect("notifications", "/notifications",
361 action="index", conditions=dict(method=["GET"]))
362 action="index", conditions=dict(method=["GET"]))
362 m.connect("notifications_mark_all_read", "/notifications/mark_all_read",
363 m.connect("notifications_mark_all_read", "/notifications/mark_all_read",
363 action="mark_all_read", conditions=dict(method=["GET"]))
364 action="mark_all_read", conditions=dict(method=["GET"]))
364 m.connect("formatted_notifications", "/notifications.{format}",
365 m.connect("formatted_notifications", "/notifications.{format}",
365 action="index", conditions=dict(method=["GET"]))
366 action="index", conditions=dict(method=["GET"]))
366 m.connect("new_notification", "/notifications/new",
367 m.connect("new_notification", "/notifications/new",
367 action="new", conditions=dict(method=["GET"]))
368 action="new", conditions=dict(method=["GET"]))
368 m.connect("formatted_new_notification", "/notifications/new.{format}",
369 m.connect("formatted_new_notification", "/notifications/new.{format}",
369 action="new", conditions=dict(method=["GET"]))
370 action="new", conditions=dict(method=["GET"]))
370 m.connect("/notifications/{notification_id}",
371 m.connect("/notifications/{notification_id}",
371 action="update", conditions=dict(method=["PUT"]))
372 action="update", conditions=dict(method=["PUT"]))
372 m.connect("/notifications/{notification_id}",
373 m.connect("/notifications/{notification_id}",
373 action="delete", conditions=dict(method=["DELETE"]))
374 action="delete", conditions=dict(method=["DELETE"]))
374 m.connect("edit_notification", "/notifications/{notification_id}/edit",
375 m.connect("edit_notification", "/notifications/{notification_id}/edit",
375 action="edit", conditions=dict(method=["GET"]))
376 action="edit", conditions=dict(method=["GET"]))
376 m.connect("formatted_edit_notification",
377 m.connect("formatted_edit_notification",
377 "/notifications/{notification_id}.{format}/edit",
378 "/notifications/{notification_id}.{format}/edit",
378 action="edit", conditions=dict(method=["GET"]))
379 action="edit", conditions=dict(method=["GET"]))
379 m.connect("notification", "/notifications/{notification_id}",
380 m.connect("notification", "/notifications/{notification_id}",
380 action="show", conditions=dict(method=["GET"]))
381 action="show", conditions=dict(method=["GET"]))
381 m.connect("formatted_notification", "/notifications/{notification_id}.{format}",
382 m.connect("formatted_notification", "/notifications/{notification_id}.{format}",
382 action="show", conditions=dict(method=["GET"]))
383 action="show", conditions=dict(method=["GET"]))
383
384
384 #ADMIN GIST
385 #ADMIN GIST
385 with rmap.submapper(path_prefix=ADMIN_PREFIX,
386 with rmap.submapper(path_prefix=ADMIN_PREFIX,
386 controller='admin/gists') as m:
387 controller='admin/gists') as m:
387 m.connect("gists", "/gists",
388 m.connect("gists", "/gists",
388 action="create", conditions=dict(method=["POST"]))
389 action="create", conditions=dict(method=["POST"]))
389 m.connect("gists", "/gists",
390 m.connect("gists", "/gists",
390 action="index", conditions=dict(method=["GET"]))
391 action="index", conditions=dict(method=["GET"]))
391 m.connect("new_gist", "/gists/new",
392 m.connect("new_gist", "/gists/new",
392 action="new", conditions=dict(method=["GET"]))
393 action="new", conditions=dict(method=["GET"]))
393 m.connect("formatted_new_gist", "/gists/new.{format}",
394 m.connect("formatted_new_gist", "/gists/new.{format}",
394 action="new", conditions=dict(method=["GET"]))
395 action="new", conditions=dict(method=["GET"]))
395 m.connect("formatted_gists", "/gists.{format}",
396 m.connect("formatted_gists", "/gists.{format}",
396 action="index", conditions=dict(method=["GET"]))
397 action="index", conditions=dict(method=["GET"]))
397 m.connect("/gists/{gist_id}",
398 m.connect("/gists/{gist_id}",
398 action="update", conditions=dict(method=["PUT"]))
399 action="update", conditions=dict(method=["PUT"]))
399 m.connect("/gists/{gist_id}",
400 m.connect("/gists/{gist_id}",
400 action="delete", conditions=dict(method=["DELETE"]))
401 action="delete", conditions=dict(method=["DELETE"]))
401 m.connect("edit_gist", "/gists/{gist_id}/edit",
402 m.connect("edit_gist", "/gists/{gist_id}/edit",
402 action="edit", conditions=dict(method=["GET"]))
403 action="edit", conditions=dict(method=["GET"]))
403 m.connect("formatted_edit_gist",
404 m.connect("formatted_edit_gist",
404 "/gists/{gist_id}/{format}/edit",
405 "/gists/{gist_id}/{format}/edit",
405 action="edit", conditions=dict(method=["GET"]))
406 action="edit", conditions=dict(method=["GET"]))
406 m.connect("gist", "/gists/{gist_id}",
407 m.connect("gist", "/gists/{gist_id}",
407 action="show", conditions=dict(method=["GET"]))
408 action="show", conditions=dict(method=["GET"]))
408 m.connect("formatted_gist", "/gists/{gist_id}/{format}",
409 m.connect("formatted_gist", "/gists/{gist_id}/{format}",
409 action="show", conditions=dict(method=["GET"]))
410 action="show", conditions=dict(method=["GET"]))
410 m.connect("formatted_gist_file", "/gists/{gist_id}/{format}/{revision}/{f_path:.*}",
411 m.connect("formatted_gist_file", "/gists/{gist_id}/{format}/{revision}/{f_path:.*}",
411 action="show", conditions=dict(method=["GET"]))
412 action="show", conditions=dict(method=["GET"]))
412
413
413 #ADMIN MAIN PAGES
414 #ADMIN MAIN PAGES
414 with rmap.submapper(path_prefix=ADMIN_PREFIX,
415 with rmap.submapper(path_prefix=ADMIN_PREFIX,
415 controller='admin/admin') as m:
416 controller='admin/admin') as m:
416 m.connect('admin_home', '', action='index')
417 m.connect('admin_home', '', action='index')
417 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
418 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
418 action='add_repo')
419 action='add_repo')
419 #==========================================================================
420 #==========================================================================
420 # API V2
421 # API V2
421 #==========================================================================
422 #==========================================================================
422 with rmap.submapper(path_prefix=ADMIN_PREFIX,
423 with rmap.submapper(path_prefix=ADMIN_PREFIX,
423 controller='api/api') as m:
424 controller='api/api') as m:
424 m.connect('api', '/api')
425 m.connect('api', '/api')
425
426
426 #USER JOURNAL
427 #USER JOURNAL
427 rmap.connect('journal', '%s/journal' % ADMIN_PREFIX,
428 rmap.connect('journal', '%s/journal' % ADMIN_PREFIX,
428 controller='journal', action='index')
429 controller='journal', action='index')
429 rmap.connect('journal_rss', '%s/journal/rss' % ADMIN_PREFIX,
430 rmap.connect('journal_rss', '%s/journal/rss' % ADMIN_PREFIX,
430 controller='journal', action='journal_rss')
431 controller='journal', action='journal_rss')
431 rmap.connect('journal_atom', '%s/journal/atom' % ADMIN_PREFIX,
432 rmap.connect('journal_atom', '%s/journal/atom' % ADMIN_PREFIX,
432 controller='journal', action='journal_atom')
433 controller='journal', action='journal_atom')
433
434
434 rmap.connect('public_journal', '%s/public_journal' % ADMIN_PREFIX,
435 rmap.connect('public_journal', '%s/public_journal' % ADMIN_PREFIX,
435 controller='journal', action="public_journal")
436 controller='journal', action="public_journal")
436
437
437 rmap.connect('public_journal_rss', '%s/public_journal/rss' % ADMIN_PREFIX,
438 rmap.connect('public_journal_rss', '%s/public_journal/rss' % ADMIN_PREFIX,
438 controller='journal', action="public_journal_rss")
439 controller='journal', action="public_journal_rss")
439
440
440 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % ADMIN_PREFIX,
441 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % ADMIN_PREFIX,
441 controller='journal', action="public_journal_rss")
442 controller='journal', action="public_journal_rss")
442
443
443 rmap.connect('public_journal_atom',
444 rmap.connect('public_journal_atom',
444 '%s/public_journal/atom' % ADMIN_PREFIX, controller='journal',
445 '%s/public_journal/atom' % ADMIN_PREFIX, controller='journal',
445 action="public_journal_atom")
446 action="public_journal_atom")
446
447
447 rmap.connect('public_journal_atom_old',
448 rmap.connect('public_journal_atom_old',
448 '%s/public_journal_atom' % ADMIN_PREFIX, controller='journal',
449 '%s/public_journal_atom' % ADMIN_PREFIX, controller='journal',
449 action="public_journal_atom")
450 action="public_journal_atom")
450
451
451 rmap.connect('toggle_following', '%s/toggle_following' % ADMIN_PREFIX,
452 rmap.connect('toggle_following', '%s/toggle_following' % ADMIN_PREFIX,
452 controller='journal', action='toggle_following',
453 controller='journal', action='toggle_following',
453 conditions=dict(method=["POST"]))
454 conditions=dict(method=["POST"]))
454
455
455 #SEARCH
456 #SEARCH
456 rmap.connect('search', '%s/search' % ADMIN_PREFIX, controller='search',)
457 rmap.connect('search', '%s/search' % ADMIN_PREFIX, controller='search',)
457 rmap.connect('search_repo_admin', '%s/search/{repo_name:.*}' % ADMIN_PREFIX,
458 rmap.connect('search_repo_admin', '%s/search/{repo_name:.*}' % ADMIN_PREFIX,
458 controller='search',
459 controller='search',
459 conditions=dict(function=check_repo))
460 conditions=dict(function=check_repo))
460 rmap.connect('search_repo', '/{repo_name:.*?}/search',
461 rmap.connect('search_repo', '/{repo_name:.*?}/search',
461 controller='search',
462 controller='search',
462 conditions=dict(function=check_repo),
463 conditions=dict(function=check_repo),
463 )
464 )
464
465
465 #LOGIN/LOGOUT/REGISTER/SIGN IN
466 #LOGIN/LOGOUT/REGISTER/SIGN IN
466 rmap.connect('login_home', '%s/login' % ADMIN_PREFIX, controller='login')
467 rmap.connect('login_home', '%s/login' % ADMIN_PREFIX, controller='login')
467 rmap.connect('logout_home', '%s/logout' % ADMIN_PREFIX, controller='login',
468 rmap.connect('logout_home', '%s/logout' % ADMIN_PREFIX, controller='login',
468 action='logout')
469 action='logout')
469
470
470 rmap.connect('register', '%s/register' % ADMIN_PREFIX, controller='login',
471 rmap.connect('register', '%s/register' % ADMIN_PREFIX, controller='login',
471 action='register')
472 action='register')
472
473
473 rmap.connect('reset_password', '%s/password_reset' % ADMIN_PREFIX,
474 rmap.connect('reset_password', '%s/password_reset' % ADMIN_PREFIX,
474 controller='login', action='password_reset')
475 controller='login', action='password_reset')
475
476
476 rmap.connect('reset_password_confirmation',
477 rmap.connect('reset_password_confirmation',
477 '%s/password_reset_confirmation' % ADMIN_PREFIX,
478 '%s/password_reset_confirmation' % ADMIN_PREFIX,
478 controller='login', action='password_reset_confirmation')
479 controller='login', action='password_reset_confirmation')
479
480
480 #FEEDS
481 #FEEDS
481 rmap.connect('rss_feed_home', '/{repo_name:.*?}/feed/rss',
482 rmap.connect('rss_feed_home', '/{repo_name:.*?}/feed/rss',
482 controller='feed', action='rss',
483 controller='feed', action='rss',
483 conditions=dict(function=check_repo))
484 conditions=dict(function=check_repo))
484
485
485 rmap.connect('atom_feed_home', '/{repo_name:.*?}/feed/atom',
486 rmap.connect('atom_feed_home', '/{repo_name:.*?}/feed/atom',
486 controller='feed', action='atom',
487 controller='feed', action='atom',
487 conditions=dict(function=check_repo))
488 conditions=dict(function=check_repo))
488
489
489 #==========================================================================
490 #==========================================================================
490 # REPOSITORY ROUTES
491 # REPOSITORY ROUTES
491 #==========================================================================
492 #==========================================================================
492 rmap.connect('summary_home', '/{repo_name:.*?}',
493 rmap.connect('summary_home', '/{repo_name:.*?}',
493 controller='summary',
494 controller='summary',
494 conditions=dict(function=check_repo))
495 conditions=dict(function=check_repo))
495
496
496 rmap.connect('repo_size', '/{repo_name:.*?}/repo_size',
497 rmap.connect('repo_size', '/{repo_name:.*?}/repo_size',
497 controller='summary', action='repo_size',
498 controller='summary', action='repo_size',
498 conditions=dict(function=check_repo))
499 conditions=dict(function=check_repo))
499
500
500 rmap.connect('repos_group_home', '/{group_name:.*}',
501 rmap.connect('repos_group_home', '/{group_name:.*}',
501 controller='admin/repos_groups', action="show_by_name",
502 controller='admin/repos_groups', action="show_by_name",
502 conditions=dict(function=check_group))
503 conditions=dict(function=check_group))
503
504
504 rmap.connect('changeset_home', '/{repo_name:.*?}/changeset/{revision}',
505 rmap.connect('changeset_home', '/{repo_name:.*?}/changeset/{revision}',
505 controller='changeset', revision='tip',
506 controller='changeset', revision='tip',
506 conditions=dict(function=check_repo))
507 conditions=dict(function=check_repo))
507
508
508 # no longer user, but kept for routes to work
509 # no longer user, but kept for routes to work
509 rmap.connect("_edit_repo", "/{repo_name:.*?}/edit",
510 rmap.connect("_edit_repo", "/{repo_name:.*?}/edit",
510 controller='admin/repos', action="edit",
511 controller='admin/repos', action="edit",
511 conditions=dict(method=["GET"], function=check_repo)
512 conditions=dict(method=["GET"], function=check_repo)
512 )
513 )
513
514
514 rmap.connect("edit_repo", "/{repo_name:.*?}/settings",
515 rmap.connect("edit_repo", "/{repo_name:.*?}/settings",
515 controller='admin/repos', action="edit",
516 controller='admin/repos', action="edit",
516 conditions=dict(method=["GET"], function=check_repo)
517 conditions=dict(method=["GET"], function=check_repo)
517 )
518 )
518
519
519 #still working url for backward compat.
520 #still working url for backward compat.
520 rmap.connect('raw_changeset_home_depraced',
521 rmap.connect('raw_changeset_home_depraced',
521 '/{repo_name:.*?}/raw-changeset/{revision}',
522 '/{repo_name:.*?}/raw-changeset/{revision}',
522 controller='changeset', action='changeset_raw',
523 controller='changeset', action='changeset_raw',
523 revision='tip', conditions=dict(function=check_repo))
524 revision='tip', conditions=dict(function=check_repo))
524
525
525 ## new URLs
526 ## new URLs
526 rmap.connect('changeset_raw_home',
527 rmap.connect('changeset_raw_home',
527 '/{repo_name:.*?}/changeset-diff/{revision}',
528 '/{repo_name:.*?}/changeset-diff/{revision}',
528 controller='changeset', action='changeset_raw',
529 controller='changeset', action='changeset_raw',
529 revision='tip', conditions=dict(function=check_repo))
530 revision='tip', conditions=dict(function=check_repo))
530
531
531 rmap.connect('changeset_patch_home',
532 rmap.connect('changeset_patch_home',
532 '/{repo_name:.*?}/changeset-patch/{revision}',
533 '/{repo_name:.*?}/changeset-patch/{revision}',
533 controller='changeset', action='changeset_patch',
534 controller='changeset', action='changeset_patch',
534 revision='tip', conditions=dict(function=check_repo))
535 revision='tip', conditions=dict(function=check_repo))
535
536
536 rmap.connect('changeset_download_home',
537 rmap.connect('changeset_download_home',
537 '/{repo_name:.*?}/changeset-download/{revision}',
538 '/{repo_name:.*?}/changeset-download/{revision}',
538 controller='changeset', action='changeset_download',
539 controller='changeset', action='changeset_download',
539 revision='tip', conditions=dict(function=check_repo))
540 revision='tip', conditions=dict(function=check_repo))
540
541
541 rmap.connect('changeset_comment',
542 rmap.connect('changeset_comment',
542 '/{repo_name:.*?}/changeset/{revision}/comment',
543 '/{repo_name:.*?}/changeset/{revision}/comment',
543 controller='changeset', revision='tip', action='comment',
544 controller='changeset', revision='tip', action='comment',
544 conditions=dict(function=check_repo))
545 conditions=dict(function=check_repo))
545
546
546 rmap.connect('changeset_comment_preview',
547 rmap.connect('changeset_comment_preview',
547 '/{repo_name:.*?}/changeset/comment/preview',
548 '/{repo_name:.*?}/changeset/comment/preview',
548 controller='changeset', action='preview_comment',
549 controller='changeset', action='preview_comment',
549 conditions=dict(function=check_repo, method=["POST"]))
550 conditions=dict(function=check_repo, method=["POST"]))
550
551
551 rmap.connect('changeset_comment_delete',
552 rmap.connect('changeset_comment_delete',
552 '/{repo_name:.*?}/changeset/comment/{comment_id}/delete',
553 '/{repo_name:.*?}/changeset/comment/{comment_id}/delete',
553 controller='changeset', action='delete_comment',
554 controller='changeset', action='delete_comment',
554 conditions=dict(function=check_repo, method=["DELETE"]))
555 conditions=dict(function=check_repo, method=["DELETE"]))
555
556
556 rmap.connect('changeset_info', '/changeset_info/{repo_name:.*?}/{revision}',
557 rmap.connect('changeset_info', '/changeset_info/{repo_name:.*?}/{revision}',
557 controller='changeset', action='changeset_info')
558 controller='changeset', action='changeset_info')
558
559
559 rmap.connect('compare_url',
560 rmap.connect('compare_url',
560 '/{repo_name:.*?}/compare/{org_ref_type}@{org_ref:.*?}...{other_ref_type}@{other_ref:.*?}',
561 '/{repo_name:.*?}/compare/{org_ref_type}@{org_ref:.*?}...{other_ref_type}@{other_ref:.*?}',
561 controller='compare', action='index',
562 controller='compare', action='index',
562 conditions=dict(function=check_repo),
563 conditions=dict(function=check_repo),
563 requirements=dict(
564 requirements=dict(
564 org_ref_type='(branch|book|tag|rev|__other_ref_type__)',
565 org_ref_type='(branch|book|tag|rev|__other_ref_type__)',
565 other_ref_type='(branch|book|tag|rev|__org_ref_type__)')
566 other_ref_type='(branch|book|tag|rev|__org_ref_type__)')
566 )
567 )
567
568
568 rmap.connect('pullrequest_home',
569 rmap.connect('pullrequest_home',
569 '/{repo_name:.*?}/pull-request/new', controller='pullrequests',
570 '/{repo_name:.*?}/pull-request/new', controller='pullrequests',
570 action='index', conditions=dict(function=check_repo,
571 action='index', conditions=dict(function=check_repo,
571 method=["GET"]))
572 method=["GET"]))
572
573
573 rmap.connect('pullrequest',
574 rmap.connect('pullrequest',
574 '/{repo_name:.*?}/pull-request/new', controller='pullrequests',
575 '/{repo_name:.*?}/pull-request/new', controller='pullrequests',
575 action='create', conditions=dict(function=check_repo,
576 action='create', conditions=dict(function=check_repo,
576 method=["POST"]))
577 method=["POST"]))
577
578
578 rmap.connect('pullrequest_show',
579 rmap.connect('pullrequest_show',
579 '/{repo_name:.*?}/pull-request/{pull_request_id}',
580 '/{repo_name:.*?}/pull-request/{pull_request_id}',
580 controller='pullrequests',
581 controller='pullrequests',
581 action='show', conditions=dict(function=check_repo,
582 action='show', conditions=dict(function=check_repo,
582 method=["GET"]))
583 method=["GET"]))
583 rmap.connect('pullrequest_update',
584 rmap.connect('pullrequest_update',
584 '/{repo_name:.*?}/pull-request/{pull_request_id}',
585 '/{repo_name:.*?}/pull-request/{pull_request_id}',
585 controller='pullrequests',
586 controller='pullrequests',
586 action='update', conditions=dict(function=check_repo,
587 action='update', conditions=dict(function=check_repo,
587 method=["PUT"]))
588 method=["PUT"]))
588 rmap.connect('pullrequest_delete',
589 rmap.connect('pullrequest_delete',
589 '/{repo_name:.*?}/pull-request/{pull_request_id}',
590 '/{repo_name:.*?}/pull-request/{pull_request_id}',
590 controller='pullrequests',
591 controller='pullrequests',
591 action='delete', conditions=dict(function=check_repo,
592 action='delete', conditions=dict(function=check_repo,
592 method=["DELETE"]))
593 method=["DELETE"]))
593
594
594 rmap.connect('pullrequest_show_all',
595 rmap.connect('pullrequest_show_all',
595 '/{repo_name:.*?}/pull-request',
596 '/{repo_name:.*?}/pull-request',
596 controller='pullrequests',
597 controller='pullrequests',
597 action='show_all', conditions=dict(function=check_repo,
598 action='show_all', conditions=dict(function=check_repo,
598 method=["GET"]))
599 method=["GET"]))
599
600
600 rmap.connect('pullrequest_comment',
601 rmap.connect('pullrequest_comment',
601 '/{repo_name:.*?}/pull-request-comment/{pull_request_id}',
602 '/{repo_name:.*?}/pull-request-comment/{pull_request_id}',
602 controller='pullrequests',
603 controller='pullrequests',
603 action='comment', conditions=dict(function=check_repo,
604 action='comment', conditions=dict(function=check_repo,
604 method=["POST"]))
605 method=["POST"]))
605
606
606 rmap.connect('pullrequest_comment_delete',
607 rmap.connect('pullrequest_comment_delete',
607 '/{repo_name:.*?}/pull-request-comment/{comment_id}/delete',
608 '/{repo_name:.*?}/pull-request-comment/{comment_id}/delete',
608 controller='pullrequests', action='delete_comment',
609 controller='pullrequests', action='delete_comment',
609 conditions=dict(function=check_repo, method=["DELETE"]))
610 conditions=dict(function=check_repo, method=["DELETE"]))
610
611
611 rmap.connect('summary_home_summary', '/{repo_name:.*?}/summary',
612 rmap.connect('summary_home_summary', '/{repo_name:.*?}/summary',
612 controller='summary', conditions=dict(function=check_repo))
613 controller='summary', conditions=dict(function=check_repo))
613
614
614 rmap.connect('branches_home', '/{repo_name:.*?}/branches',
615 rmap.connect('branches_home', '/{repo_name:.*?}/branches',
615 controller='branches', conditions=dict(function=check_repo))
616 controller='branches', conditions=dict(function=check_repo))
616
617
617 rmap.connect('tags_home', '/{repo_name:.*?}/tags',
618 rmap.connect('tags_home', '/{repo_name:.*?}/tags',
618 controller='tags', conditions=dict(function=check_repo))
619 controller='tags', conditions=dict(function=check_repo))
619
620
620 rmap.connect('bookmarks_home', '/{repo_name:.*?}/bookmarks',
621 rmap.connect('bookmarks_home', '/{repo_name:.*?}/bookmarks',
621 controller='bookmarks', conditions=dict(function=check_repo))
622 controller='bookmarks', conditions=dict(function=check_repo))
622
623
623 rmap.connect('changelog_home', '/{repo_name:.*?}/changelog',
624 rmap.connect('changelog_home', '/{repo_name:.*?}/changelog',
624 controller='changelog', conditions=dict(function=check_repo))
625 controller='changelog', conditions=dict(function=check_repo))
625
626
626 rmap.connect('changelog_summary_home', '/{repo_name:.*?}/changelog_summary',
627 rmap.connect('changelog_summary_home', '/{repo_name:.*?}/changelog_summary',
627 controller='changelog', action='changelog_summary',
628 controller='changelog', action='changelog_summary',
628 conditions=dict(function=check_repo))
629 conditions=dict(function=check_repo))
629
630
630 rmap.connect('changelog_file_home', '/{repo_name:.*?}/changelog/{revision}/{f_path:.*}',
631 rmap.connect('changelog_file_home', '/{repo_name:.*?}/changelog/{revision}/{f_path:.*}',
631 controller='changelog', f_path=None,
632 controller='changelog', f_path=None,
632 conditions=dict(function=check_repo))
633 conditions=dict(function=check_repo))
633
634
634 rmap.connect('changelog_details', '/{repo_name:.*?}/changelog_details/{cs}',
635 rmap.connect('changelog_details', '/{repo_name:.*?}/changelog_details/{cs}',
635 controller='changelog', action='changelog_details',
636 controller='changelog', action='changelog_details',
636 conditions=dict(function=check_repo))
637 conditions=dict(function=check_repo))
637
638
638 rmap.connect('files_home', '/{repo_name:.*?}/files/{revision}/{f_path:.*}',
639 rmap.connect('files_home', '/{repo_name:.*?}/files/{revision}/{f_path:.*}',
639 controller='files', revision='tip', f_path='',
640 controller='files', revision='tip', f_path='',
640 conditions=dict(function=check_repo))
641 conditions=dict(function=check_repo))
641
642
642 rmap.connect('files_home_nopath', '/{repo_name:.*?}/files/{revision}',
643 rmap.connect('files_home_nopath', '/{repo_name:.*?}/files/{revision}',
643 controller='files', revision='tip', f_path='',
644 controller='files', revision='tip', f_path='',
644 conditions=dict(function=check_repo))
645 conditions=dict(function=check_repo))
645
646
646 rmap.connect('files_history_home',
647 rmap.connect('files_history_home',
647 '/{repo_name:.*?}/history/{revision}/{f_path:.*}',
648 '/{repo_name:.*?}/history/{revision}/{f_path:.*}',
648 controller='files', action='history', revision='tip', f_path='',
649 controller='files', action='history', revision='tip', f_path='',
649 conditions=dict(function=check_repo))
650 conditions=dict(function=check_repo))
650
651
651 rmap.connect('files_diff_home', '/{repo_name:.*?}/diff/{f_path:.*}',
652 rmap.connect('files_diff_home', '/{repo_name:.*?}/diff/{f_path:.*}',
652 controller='files', action='diff', revision='tip', f_path='',
653 controller='files', action='diff', revision='tip', f_path='',
653 conditions=dict(function=check_repo))
654 conditions=dict(function=check_repo))
654
655
655 rmap.connect('files_diff_2way_home', '/{repo_name:.*?}/diff-2way/{f_path:.*}',
656 rmap.connect('files_diff_2way_home', '/{repo_name:.*?}/diff-2way/{f_path:.*}',
656 controller='files', action='diff_2way', revision='tip', f_path='',
657 controller='files', action='diff_2way', revision='tip', f_path='',
657 conditions=dict(function=check_repo))
658 conditions=dict(function=check_repo))
658
659
659 rmap.connect('files_rawfile_home',
660 rmap.connect('files_rawfile_home',
660 '/{repo_name:.*?}/rawfile/{revision}/{f_path:.*}',
661 '/{repo_name:.*?}/rawfile/{revision}/{f_path:.*}',
661 controller='files', action='rawfile', revision='tip',
662 controller='files', action='rawfile', revision='tip',
662 f_path='', conditions=dict(function=check_repo))
663 f_path='', conditions=dict(function=check_repo))
663
664
664 rmap.connect('files_raw_home',
665 rmap.connect('files_raw_home',
665 '/{repo_name:.*?}/raw/{revision}/{f_path:.*}',
666 '/{repo_name:.*?}/raw/{revision}/{f_path:.*}',
666 controller='files', action='raw', revision='tip', f_path='',
667 controller='files', action='raw', revision='tip', f_path='',
667 conditions=dict(function=check_repo))
668 conditions=dict(function=check_repo))
668
669
669 rmap.connect('files_annotate_home',
670 rmap.connect('files_annotate_home',
670 '/{repo_name:.*?}/annotate/{revision}/{f_path:.*}',
671 '/{repo_name:.*?}/annotate/{revision}/{f_path:.*}',
671 controller='files', action='index', revision='tip',
672 controller='files', action='index', revision='tip',
672 f_path='', annotate=True, conditions=dict(function=check_repo))
673 f_path='', annotate=True, conditions=dict(function=check_repo))
673
674
674 rmap.connect('files_edit_home',
675 rmap.connect('files_edit_home',
675 '/{repo_name:.*?}/edit/{revision}/{f_path:.*}',
676 '/{repo_name:.*?}/edit/{revision}/{f_path:.*}',
676 controller='files', action='edit', revision='tip',
677 controller='files', action='edit', revision='tip',
677 f_path='', conditions=dict(function=check_repo))
678 f_path='', conditions=dict(function=check_repo))
678
679
679 rmap.connect('files_add_home',
680 rmap.connect('files_add_home',
680 '/{repo_name:.*?}/add/{revision}/{f_path:.*}',
681 '/{repo_name:.*?}/add/{revision}/{f_path:.*}',
681 controller='files', action='add', revision='tip',
682 controller='files', action='add', revision='tip',
682 f_path='', conditions=dict(function=check_repo))
683 f_path='', conditions=dict(function=check_repo))
683
684
684 rmap.connect('files_archive_home', '/{repo_name:.*?}/archive/{fname}',
685 rmap.connect('files_archive_home', '/{repo_name:.*?}/archive/{fname}',
685 controller='files', action='archivefile',
686 controller='files', action='archivefile',
686 conditions=dict(function=check_repo))
687 conditions=dict(function=check_repo))
687
688
688 rmap.connect('files_nodelist_home',
689 rmap.connect('files_nodelist_home',
689 '/{repo_name:.*?}/nodelist/{revision}/{f_path:.*}',
690 '/{repo_name:.*?}/nodelist/{revision}/{f_path:.*}',
690 controller='files', action='nodelist',
691 controller='files', action='nodelist',
691 conditions=dict(function=check_repo))
692 conditions=dict(function=check_repo))
692
693
693 rmap.connect('repo_fork_create_home', '/{repo_name:.*?}/fork',
694 rmap.connect('repo_fork_create_home', '/{repo_name:.*?}/fork',
694 controller='forks', action='fork_create',
695 controller='forks', action='fork_create',
695 conditions=dict(function=check_repo, method=["POST"]))
696 conditions=dict(function=check_repo, method=["POST"]))
696
697
697 rmap.connect('repo_fork_home', '/{repo_name:.*?}/fork',
698 rmap.connect('repo_fork_home', '/{repo_name:.*?}/fork',
698 controller='forks', action='fork',
699 controller='forks', action='fork',
699 conditions=dict(function=check_repo))
700 conditions=dict(function=check_repo))
700
701
701 rmap.connect('repo_forks_home', '/{repo_name:.*?}/forks',
702 rmap.connect('repo_forks_home', '/{repo_name:.*?}/forks',
702 controller='forks', action='forks',
703 controller='forks', action='forks',
703 conditions=dict(function=check_repo))
704 conditions=dict(function=check_repo))
704
705
705 rmap.connect('repo_followers_home', '/{repo_name:.*?}/followers',
706 rmap.connect('repo_followers_home', '/{repo_name:.*?}/followers',
706 controller='followers', action='followers',
707 controller='followers', action='followers',
707 conditions=dict(function=check_repo))
708 conditions=dict(function=check_repo))
708
709
709 return rmap
710 return rmap
@@ -1,361 +1,361 b''
1 """The base Controller API
1 """The base Controller API
2
2
3 Provides the BaseController class for subclassing.
3 Provides the BaseController class for subclassing.
4 """
4 """
5 import logging
5 import logging
6 import time
6 import time
7 import traceback
7 import traceback
8
8
9 from paste.auth.basic import AuthBasicAuthenticator
9 from paste.auth.basic import AuthBasicAuthenticator
10 from paste.httpexceptions import HTTPUnauthorized, HTTPForbidden
10 from paste.httpexceptions import HTTPUnauthorized, HTTPForbidden
11 from paste.httpheaders import WWW_AUTHENTICATE, AUTHORIZATION
11 from paste.httpheaders import WWW_AUTHENTICATE, AUTHORIZATION
12
12
13 from pylons import config, tmpl_context as c, request, session, url
13 from pylons import config, tmpl_context as c, request, session, url
14 from pylons.controllers import WSGIController
14 from pylons.controllers import WSGIController
15 from pylons.controllers.util import redirect
15 from pylons.controllers.util import redirect
16 from pylons.templating import render_mako as render
16 from pylons.templating import render_mako as render
17
17
18 from rhodecode import __version__, BACKENDS
18 from rhodecode import __version__, BACKENDS
19
19
20 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict,\
20 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict,\
21 safe_str, safe_int
21 safe_str, safe_int
22 from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\
22 from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\
23 HasPermissionAnyMiddleware, CookieStoreWrapper
23 HasPermissionAnyMiddleware, CookieStoreWrapper
24 from rhodecode.lib.utils import get_repo_slug
24 from rhodecode.lib.utils import get_repo_slug
25 from rhodecode.lib.exceptions import UserCreationError
25 from rhodecode.lib.exceptions import UserCreationError
26 from rhodecode.model import meta
26 from rhodecode.model import meta
27
27
28 from rhodecode.model.db import Repository, RhodeCodeUi, User, RhodeCodeSetting
28 from rhodecode.model.db import Repository, RhodeCodeUi, User, RhodeCodeSetting
29 from rhodecode.model.notification import NotificationModel
29 from rhodecode.model.notification import NotificationModel
30 from rhodecode.model.scm import ScmModel
30 from rhodecode.model.scm import ScmModel
31 from rhodecode.model.meta import Session
31 from rhodecode.model.meta import Session
32
32
33 log = logging.getLogger(__name__)
33 log = logging.getLogger(__name__)
34
34
35
35
36 def _filter_proxy(ip):
36 def _filter_proxy(ip):
37 """
37 """
38 HEADERS can have multiple ips inside the left-most being the original
38 HEADERS can have multiple ips inside the left-most being the original
39 client, and each successive proxy that passed the request adding the IP
39 client, and each successive proxy that passed the request adding the IP
40 address where it received the request from.
40 address where it received the request from.
41
41
42 :param ip:
42 :param ip:
43 """
43 """
44 if ',' in ip:
44 if ',' in ip:
45 _ips = ip.split(',')
45 _ips = ip.split(',')
46 _first_ip = _ips[0].strip()
46 _first_ip = _ips[0].strip()
47 log.debug('Got multiple IPs %s, using %s' % (','.join(_ips), _first_ip))
47 log.debug('Got multiple IPs %s, using %s' % (','.join(_ips), _first_ip))
48 return _first_ip
48 return _first_ip
49 return ip
49 return ip
50
50
51
51
52 def _get_ip_addr(environ):
52 def _get_ip_addr(environ):
53 proxy_key = 'HTTP_X_REAL_IP'
53 proxy_key = 'HTTP_X_REAL_IP'
54 proxy_key2 = 'HTTP_X_FORWARDED_FOR'
54 proxy_key2 = 'HTTP_X_FORWARDED_FOR'
55 def_key = 'REMOTE_ADDR'
55 def_key = 'REMOTE_ADDR'
56
56
57 ip = environ.get(proxy_key)
57 ip = environ.get(proxy_key)
58 if ip:
58 if ip:
59 return _filter_proxy(ip)
59 return _filter_proxy(ip)
60
60
61 ip = environ.get(proxy_key2)
61 ip = environ.get(proxy_key2)
62 if ip:
62 if ip:
63 return _filter_proxy(ip)
63 return _filter_proxy(ip)
64
64
65 ip = environ.get(def_key, '0.0.0.0')
65 ip = environ.get(def_key, '0.0.0.0')
66 return _filter_proxy(ip)
66 return _filter_proxy(ip)
67
67
68
68
69 def _get_access_path(environ):
69 def _get_access_path(environ):
70 path = environ.get('PATH_INFO')
70 path = environ.get('PATH_INFO')
71 org_req = environ.get('pylons.original_request')
71 org_req = environ.get('pylons.original_request')
72 if org_req:
72 if org_req:
73 path = org_req.environ.get('PATH_INFO')
73 path = org_req.environ.get('PATH_INFO')
74 return path
74 return path
75
75
76
76
77 class BasicAuth(AuthBasicAuthenticator):
77 class BasicAuth(AuthBasicAuthenticator):
78
78
79 def __init__(self, realm, authfunc, auth_http_code=None):
79 def __init__(self, realm, authfunc, auth_http_code=None):
80 self.realm = realm
80 self.realm = realm
81 self.authfunc = authfunc
81 self.authfunc = authfunc
82 self._rc_auth_http_code = auth_http_code
82 self._rc_auth_http_code = auth_http_code
83
83
84 def build_authentication(self):
84 def build_authentication(self):
85 head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
85 head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
86 if self._rc_auth_http_code and self._rc_auth_http_code == '403':
86 if self._rc_auth_http_code and self._rc_auth_http_code == '403':
87 # return 403 if alternative http return code is specified in
87 # return 403 if alternative http return code is specified in
88 # RhodeCode config
88 # RhodeCode config
89 return HTTPForbidden(headers=head)
89 return HTTPForbidden(headers=head)
90 return HTTPUnauthorized(headers=head)
90 return HTTPUnauthorized(headers=head)
91
91
92 def authenticate(self, environ):
92 def authenticate(self, environ):
93 authorization = AUTHORIZATION(environ)
93 authorization = AUTHORIZATION(environ)
94 if not authorization:
94 if not authorization:
95 return self.build_authentication()
95 return self.build_authentication()
96 (authmeth, auth) = authorization.split(' ', 1)
96 (authmeth, auth) = authorization.split(' ', 1)
97 if 'basic' != authmeth.lower():
97 if 'basic' != authmeth.lower():
98 return self.build_authentication()
98 return self.build_authentication()
99 auth = auth.strip().decode('base64')
99 auth = auth.strip().decode('base64')
100 _parts = auth.split(':', 1)
100 _parts = auth.split(':', 1)
101 if len(_parts) == 2:
101 if len(_parts) == 2:
102 username, password = _parts
102 username, password = _parts
103 if self.authfunc(environ, username, password):
103 if self.authfunc(environ, username, password):
104 return username
104 return username
105 return self.build_authentication()
105 return self.build_authentication()
106
106
107 __call__ = authenticate
107 __call__ = authenticate
108
108
109
109
110 class BaseVCSController(object):
110 class BaseVCSController(object):
111
111
112 def __init__(self, application, config):
112 def __init__(self, application, config):
113 self.application = application
113 self.application = application
114 self.config = config
114 self.config = config
115 # base path of repo locations
115 # base path of repo locations
116 self.basepath = self.config['base_path']
116 self.basepath = self.config['base_path']
117 #authenticate this mercurial request using authfunc
117 #authenticate this mercurial request using authfunc
118 self.authenticate = BasicAuth('', authfunc,
118 self.authenticate = BasicAuth('', authfunc,
119 config.get('auth_ret_code'))
119 config.get('auth_ret_code'))
120 self.ip_addr = '0.0.0.0'
120 self.ip_addr = '0.0.0.0'
121
121
122 def _handle_request(self, environ, start_response):
122 def _handle_request(self, environ, start_response):
123 raise NotImplementedError()
123 raise NotImplementedError()
124
124
125 def _get_by_id(self, repo_name):
125 def _get_by_id(self, repo_name):
126 """
126 """
127 Gets a special pattern _<ID> from clone url and tries to replace it
127 Gets a special pattern _<ID> from clone url and tries to replace it
128 with a repository_name for support of _<ID> non changable urls
128 with a repository_name for support of _<ID> non changable urls
129
129
130 :param repo_name:
130 :param repo_name:
131 """
131 """
132 try:
132 try:
133 data = repo_name.split('/')
133 data = repo_name.split('/')
134 if len(data) >= 2:
134 if len(data) >= 2:
135 by_id = data[1].split('_')
135 by_id = data[1].split('_')
136 if len(by_id) == 2 and by_id[1].isdigit():
136 if len(by_id) == 2 and by_id[1].isdigit():
137 _repo_name = Repository.get(by_id[1]).repo_name
137 _repo_name = Repository.get(by_id[1]).repo_name
138 data[1] = _repo_name
138 data[1] = _repo_name
139 except Exception:
139 except Exception:
140 log.debug('Failed to extract repo_name from id %s' % (
140 log.debug('Failed to extract repo_name from id %s' % (
141 traceback.format_exc()
141 traceback.format_exc()
142 )
142 )
143 )
143 )
144
144
145 return '/'.join(data)
145 return '/'.join(data)
146
146
147 def _invalidate_cache(self, repo_name):
147 def _invalidate_cache(self, repo_name):
148 """
148 """
149 Set's cache for this repository for invalidation on next access
149 Set's cache for this repository for invalidation on next access
150
150
151 :param repo_name: full repo name, also a cache key
151 :param repo_name: full repo name, also a cache key
152 """
152 """
153 ScmModel().mark_for_invalidation(repo_name)
153 ScmModel().mark_for_invalidation(repo_name)
154
154
155 def _check_permission(self, action, user, repo_name, ip_addr=None):
155 def _check_permission(self, action, user, repo_name, ip_addr=None):
156 """
156 """
157 Checks permissions using action (push/pull) user and repository
157 Checks permissions using action (push/pull) user and repository
158 name
158 name
159
159
160 :param action: push or pull action
160 :param action: push or pull action
161 :param user: user instance
161 :param user: user instance
162 :param repo_name: repository name
162 :param repo_name: repository name
163 """
163 """
164 #check IP
164 #check IP
165 authuser = AuthUser(user_id=user.user_id, ip_addr=ip_addr)
165 authuser = AuthUser(user_id=user.user_id, ip_addr=ip_addr)
166 if not authuser.ip_allowed:
166 if not authuser.ip_allowed:
167 return False
167 return False
168 else:
168 else:
169 log.info('Access for IP:%s allowed' % (ip_addr))
169 log.info('Access for IP:%s allowed' % (ip_addr))
170 if action == 'push':
170 if action == 'push':
171 if not HasPermissionAnyMiddleware('repository.write',
171 if not HasPermissionAnyMiddleware('repository.write',
172 'repository.admin')(user,
172 'repository.admin')(user,
173 repo_name):
173 repo_name):
174 return False
174 return False
175
175
176 else:
176 else:
177 #any other action need at least read permission
177 #any other action need at least read permission
178 if not HasPermissionAnyMiddleware('repository.read',
178 if not HasPermissionAnyMiddleware('repository.read',
179 'repository.write',
179 'repository.write',
180 'repository.admin')(user,
180 'repository.admin')(user,
181 repo_name):
181 repo_name):
182 return False
182 return False
183
183
184 return True
184 return True
185
185
186 def _get_ip_addr(self, environ):
186 def _get_ip_addr(self, environ):
187 return _get_ip_addr(environ)
187 return _get_ip_addr(environ)
188
188
189 def _check_ssl(self, environ, start_response):
189 def _check_ssl(self, environ, start_response):
190 """
190 """
191 Checks the SSL check flag and returns False if SSL is not present
191 Checks the SSL check flag and returns False if SSL is not present
192 and required True otherwise
192 and required True otherwise
193 """
193 """
194 org_proto = environ['wsgi._org_proto']
194 org_proto = environ['wsgi._org_proto']
195 #check if we have SSL required ! if not it's a bad request !
195 #check if we have SSL required ! if not it's a bad request !
196 require_ssl = str2bool(RhodeCodeUi.get_by_key('push_ssl').ui_value)
196 require_ssl = str2bool(RhodeCodeUi.get_by_key('push_ssl').ui_value)
197 if require_ssl and org_proto == 'http':
197 if require_ssl and org_proto == 'http':
198 log.debug('proto is %s and SSL is required BAD REQUEST !'
198 log.debug('proto is %s and SSL is required BAD REQUEST !'
199 % org_proto)
199 % org_proto)
200 return False
200 return False
201 return True
201 return True
202
202
203 def _check_locking_state(self, environ, action, repo, user_id):
203 def _check_locking_state(self, environ, action, repo, user_id):
204 """
204 """
205 Checks locking on this repository, if locking is enabled and lock is
205 Checks locking on this repository, if locking is enabled and lock is
206 present returns a tuple of make_lock, locked, locked_by.
206 present returns a tuple of make_lock, locked, locked_by.
207 make_lock can have 3 states None (do nothing) True, make lock
207 make_lock can have 3 states None (do nothing) True, make lock
208 False release lock, This value is later propagated to hooks, which
208 False release lock, This value is later propagated to hooks, which
209 do the locking. Think about this as signals passed to hooks what to do.
209 do the locking. Think about this as signals passed to hooks what to do.
210
210
211 """
211 """
212 locked = False # defines that locked error should be thrown to user
212 locked = False # defines that locked error should be thrown to user
213 make_lock = None
213 make_lock = None
214 repo = Repository.get_by_repo_name(repo)
214 repo = Repository.get_by_repo_name(repo)
215 user = User.get(user_id)
215 user = User.get(user_id)
216
216
217 # this is kind of hacky, but due to how mercurial handles client-server
217 # this is kind of hacky, but due to how mercurial handles client-server
218 # server see all operation on changeset; bookmarks, phases and
218 # server see all operation on changeset; bookmarks, phases and
219 # obsolescence marker in different transaction, we don't want to check
219 # obsolescence marker in different transaction, we don't want to check
220 # locking on those
220 # locking on those
221 obsolete_call = environ['QUERY_STRING'] in ['cmd=listkeys',]
221 obsolete_call = environ['QUERY_STRING'] in ['cmd=listkeys',]
222 locked_by = repo.locked
222 locked_by = repo.locked
223 if repo and repo.enable_locking and not obsolete_call:
223 if repo and repo.enable_locking and not obsolete_call:
224 if action == 'push':
224 if action == 'push':
225 #check if it's already locked !, if it is compare users
225 #check if it's already locked !, if it is compare users
226 user_id, _date = repo.locked
226 user_id, _date = repo.locked
227 if user.user_id == user_id:
227 if user.user_id == user_id:
228 log.debug('Got push from user %s, now unlocking' % (user))
228 log.debug('Got push from user %s, now unlocking' % (user))
229 # unlock if we have push from user who locked
229 # unlock if we have push from user who locked
230 make_lock = False
230 make_lock = False
231 else:
231 else:
232 # we're not the same user who locked, ban with 423 !
232 # we're not the same user who locked, ban with 423 !
233 locked = True
233 locked = True
234 if action == 'pull':
234 if action == 'pull':
235 if repo.locked[0] and repo.locked[1]:
235 if repo.locked[0] and repo.locked[1]:
236 locked = True
236 locked = True
237 else:
237 else:
238 log.debug('Setting lock on repo %s by %s' % (repo, user))
238 log.debug('Setting lock on repo %s by %s' % (repo, user))
239 make_lock = True
239 make_lock = True
240
240
241 else:
241 else:
242 log.debug('Repository %s do not have locking enabled' % (repo))
242 log.debug('Repository %s do not have locking enabled' % (repo))
243 log.debug('FINAL locking values make_lock:%s,locked:%s,locked_by:%s'
243 log.debug('FINAL locking values make_lock:%s,locked:%s,locked_by:%s'
244 % (make_lock, locked, locked_by))
244 % (make_lock, locked, locked_by))
245 return make_lock, locked, locked_by
245 return make_lock, locked, locked_by
246
246
247 def __call__(self, environ, start_response):
247 def __call__(self, environ, start_response):
248 start = time.time()
248 start = time.time()
249 try:
249 try:
250 return self._handle_request(environ, start_response)
250 return self._handle_request(environ, start_response)
251 finally:
251 finally:
252 log = logging.getLogger('rhodecode.' + self.__class__.__name__)
252 log = logging.getLogger('rhodecode.' + self.__class__.__name__)
253 log.debug('Request time: %.3fs' % (time.time() - start))
253 log.debug('Request time: %.3fs' % (time.time() - start))
254 meta.Session.remove()
254 meta.Session.remove()
255
255
256
256
257 class BaseController(WSGIController):
257 class BaseController(WSGIController):
258
258
259 def __before__(self):
259 def __before__(self):
260 """
260 """
261 __before__ is called before controller methods and after __call__
261 __before__ is called before controller methods and after __call__
262 """
262 """
263 c.rhodecode_version = __version__
263 c.rhodecode_version = __version__
264 c.rhodecode_instanceid = config.get('instance_id')
264 c.rhodecode_instanceid = config.get('instance_id')
265 c.rhodecode_name = config.get('rhodecode_title')
265 c.rhodecode_name = config.get('rhodecode_title')
266 c.rhodecode_bugtracker = config.get('bugtracker', 'http://bitbucket.org/marcinkuzminski/rhodecode/issues')
266 c.rhodecode_bugtracker = config.get('bugtracker', url('rc_issue_tracker'))
267 c.use_gravatar = str2bool(config.get('use_gravatar'))
267 c.use_gravatar = str2bool(config.get('use_gravatar'))
268 c.ga_code = config.get('rhodecode_ga_code')
268 c.ga_code = config.get('rhodecode_ga_code')
269 # Visual options
269 # Visual options
270 c.visual = AttributeDict({})
270 c.visual = AttributeDict({})
271 rc_config = RhodeCodeSetting.get_app_settings()
271 rc_config = RhodeCodeSetting.get_app_settings()
272 ## DB stored
272 ## DB stored
273 c.visual.show_public_icon = str2bool(rc_config.get('rhodecode_show_public_icon'))
273 c.visual.show_public_icon = str2bool(rc_config.get('rhodecode_show_public_icon'))
274 c.visual.show_private_icon = str2bool(rc_config.get('rhodecode_show_private_icon'))
274 c.visual.show_private_icon = str2bool(rc_config.get('rhodecode_show_private_icon'))
275 c.visual.stylify_metatags = str2bool(rc_config.get('rhodecode_stylify_metatags'))
275 c.visual.stylify_metatags = str2bool(rc_config.get('rhodecode_stylify_metatags'))
276 c.visual.dashboard_items = safe_int(rc_config.get('rhodecode_dashboard_items', 100))
276 c.visual.dashboard_items = safe_int(rc_config.get('rhodecode_dashboard_items', 100))
277 c.visual.repository_fields = str2bool(rc_config.get('rhodecode_repository_fields'))
277 c.visual.repository_fields = str2bool(rc_config.get('rhodecode_repository_fields'))
278 c.visual.show_version = str2bool(rc_config.get('rhodecode_show_version'))
278 c.visual.show_version = str2bool(rc_config.get('rhodecode_show_version'))
279
279
280 ## INI stored
280 ## INI stored
281 self.cut_off_limit = int(config.get('cut_off_limit'))
281 self.cut_off_limit = int(config.get('cut_off_limit'))
282 c.visual.allow_repo_location_change = str2bool(config.get('allow_repo_location_change', True))
282 c.visual.allow_repo_location_change = str2bool(config.get('allow_repo_location_change', True))
283 c.visual.allow_custom_hooks_settings = str2bool(config.get('allow_custom_hooks_settings', True))
283 c.visual.allow_custom_hooks_settings = str2bool(config.get('allow_custom_hooks_settings', True))
284
284
285 c.repo_name = get_repo_slug(request) # can be empty
285 c.repo_name = get_repo_slug(request) # can be empty
286 c.backends = BACKENDS.keys()
286 c.backends = BACKENDS.keys()
287 c.unread_notifications = NotificationModel()\
287 c.unread_notifications = NotificationModel()\
288 .get_unread_cnt_for_user(c.rhodecode_user.user_id)
288 .get_unread_cnt_for_user(c.rhodecode_user.user_id)
289 self.sa = meta.Session
289 self.sa = meta.Session
290 self.scm_model = ScmModel(self.sa)
290 self.scm_model = ScmModel(self.sa)
291
291
292 def __call__(self, environ, start_response):
292 def __call__(self, environ, start_response):
293 """Invoke the Controller"""
293 """Invoke the Controller"""
294 # WSGIController.__call__ dispatches to the Controller method
294 # WSGIController.__call__ dispatches to the Controller method
295 # the request is routed to. This routing information is
295 # the request is routed to. This routing information is
296 # available in environ['pylons.routes_dict']
296 # available in environ['pylons.routes_dict']
297 try:
297 try:
298 self.ip_addr = _get_ip_addr(environ)
298 self.ip_addr = _get_ip_addr(environ)
299 # make sure that we update permissions each time we call controller
299 # make sure that we update permissions each time we call controller
300 api_key = request.GET.get('api_key')
300 api_key = request.GET.get('api_key')
301 cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
301 cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
302 user_id = cookie_store.get('user_id', None)
302 user_id = cookie_store.get('user_id', None)
303 username = get_container_username(environ, config)
303 username = get_container_username(environ, config)
304 try:
304 try:
305 auth_user = AuthUser(user_id, api_key, username, self.ip_addr)
305 auth_user = AuthUser(user_id, api_key, username, self.ip_addr)
306 except UserCreationError, e:
306 except UserCreationError, e:
307 from rhodecode.lib import helpers as h
307 from rhodecode.lib import helpers as h
308 h.flash(e, 'error')
308 h.flash(e, 'error')
309 # container auth or other auth functions that create users on
309 # container auth or other auth functions that create users on
310 # the fly can throw this exception signaling that there's issue
310 # the fly can throw this exception signaling that there's issue
311 # with user creation, explanation should be provided in
311 # with user creation, explanation should be provided in
312 # Exception itself
312 # Exception itself
313 auth_user = AuthUser(ip_addr=self.ip_addr)
313 auth_user = AuthUser(ip_addr=self.ip_addr)
314
314
315 request.user = auth_user
315 request.user = auth_user
316 self.rhodecode_user = c.rhodecode_user = auth_user
316 self.rhodecode_user = c.rhodecode_user = auth_user
317 if not self.rhodecode_user.is_authenticated and \
317 if not self.rhodecode_user.is_authenticated and \
318 self.rhodecode_user.user_id is not None:
318 self.rhodecode_user.user_id is not None:
319 self.rhodecode_user.set_authenticated(
319 self.rhodecode_user.set_authenticated(
320 cookie_store.get('is_authenticated')
320 cookie_store.get('is_authenticated')
321 )
321 )
322 log.info('IP: %s User: %s accessed %s' % (
322 log.info('IP: %s User: %s accessed %s' % (
323 self.ip_addr, auth_user, safe_unicode(_get_access_path(environ)))
323 self.ip_addr, auth_user, safe_unicode(_get_access_path(environ)))
324 )
324 )
325 return WSGIController.__call__(self, environ, start_response)
325 return WSGIController.__call__(self, environ, start_response)
326 finally:
326 finally:
327 meta.Session.remove()
327 meta.Session.remove()
328
328
329
329
330 class BaseRepoController(BaseController):
330 class BaseRepoController(BaseController):
331 """
331 """
332 Base class for controllers responsible for loading all needed data for
332 Base class for controllers responsible for loading all needed data for
333 repository loaded items are
333 repository loaded items are
334
334
335 c.rhodecode_repo: instance of scm repository
335 c.rhodecode_repo: instance of scm repository
336 c.rhodecode_db_repo: instance of db
336 c.rhodecode_db_repo: instance of db
337 c.repository_followers: number of followers
337 c.repository_followers: number of followers
338 c.repository_forks: number of forks
338 c.repository_forks: number of forks
339 c.repository_following: weather the current user is following the current repo
339 c.repository_following: weather the current user is following the current repo
340 """
340 """
341
341
342 def __before__(self):
342 def __before__(self):
343 super(BaseRepoController, self).__before__()
343 super(BaseRepoController, self).__before__()
344 if c.repo_name:
344 if c.repo_name:
345
345
346 dbr = c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
346 dbr = c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
347 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
347 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
348 # update last change according to VCS data
348 # update last change according to VCS data
349 dbr.update_changeset_cache(dbr.get_changeset())
349 dbr.update_changeset_cache(dbr.get_changeset())
350 if c.rhodecode_repo is None:
350 if c.rhodecode_repo is None:
351 log.error('%s this repository is present in database but it '
351 log.error('%s this repository is present in database but it '
352 'cannot be created as an scm instance', c.repo_name)
352 'cannot be created as an scm instance', c.repo_name)
353
353
354 redirect(url('home'))
354 redirect(url('home'))
355
355
356 # some globals counter for menu
356 # some globals counter for menu
357 c.repository_followers = self.scm_model.get_followers(dbr)
357 c.repository_followers = self.scm_model.get_followers(dbr)
358 c.repository_forks = self.scm_model.get_forks(dbr)
358 c.repository_forks = self.scm_model.get_forks(dbr)
359 c.repository_pull_requests = self.scm_model.get_pull_requests(dbr)
359 c.repository_pull_requests = self.scm_model.get_pull_requests(dbr)
360 c.repository_following = self.scm_model.is_following_repo(c.repo_name,
360 c.repository_following = self.scm_model.is_following_repo(c.repo_name,
361 self.rhodecode_user.user_id)
361 self.rhodecode_user.user_id)
General Comments 0
You need to be logged in to leave comments. Login now