##// END OF EJS Templates
core: make pylons global be used in obsolete parts of the code....
marcink -
r1895:002c3bcf default
parent child Browse files
Show More
@@ -1,357 +1,358 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import time
21 import time
22 import logging
22 import logging
23 from pylons import tmpl_context as c
23
24 from pyramid.httpexceptions import HTTPFound
24 from pyramid.httpexceptions import HTTPFound
25
25
26 from rhodecode.lib import helpers as h
26 from rhodecode.lib import helpers as h
27 from rhodecode.lib.utils import PartialRenderer
27 from rhodecode.lib.utils import PartialRenderer
28 from rhodecode.lib.utils2 import StrictAttributeDict, safe_int, datetime_to_time
28 from rhodecode.lib.utils2 import StrictAttributeDict, safe_int, datetime_to_time
29 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
29 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
30 from rhodecode.lib.ext_json import json
30 from rhodecode.lib.ext_json import json
31 from rhodecode.model import repo
31 from rhodecode.model import repo
32 from rhodecode.model import repo_group
32 from rhodecode.model import repo_group
33 from rhodecode.model.db import User
33 from rhodecode.model.db import User
34 from rhodecode.model.scm import ScmModel
34 from rhodecode.model.scm import ScmModel
35
35
36 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
37
37
38
38
39 ADMIN_PREFIX = '/_admin'
39 ADMIN_PREFIX = '/_admin'
40 STATIC_FILE_PREFIX = '/_static'
40 STATIC_FILE_PREFIX = '/_static'
41
41
42
42
43 def add_route_with_slash(config,name, pattern, **kw):
43 def add_route_with_slash(config,name, pattern, **kw):
44 config.add_route(name, pattern, **kw)
44 config.add_route(name, pattern, **kw)
45 if not pattern.endswith('/'):
45 if not pattern.endswith('/'):
46 config.add_route(name + '_slash', pattern + '/', **kw)
46 config.add_route(name + '_slash', pattern + '/', **kw)
47
47
48
48
49 def get_format_ref_id(repo):
49 def get_format_ref_id(repo):
50 """Returns a `repo` specific reference formatter function"""
50 """Returns a `repo` specific reference formatter function"""
51 if h.is_svn(repo):
51 if h.is_svn(repo):
52 return _format_ref_id_svn
52 return _format_ref_id_svn
53 else:
53 else:
54 return _format_ref_id
54 return _format_ref_id
55
55
56
56
57 def _format_ref_id(name, raw_id):
57 def _format_ref_id(name, raw_id):
58 """Default formatting of a given reference `name`"""
58 """Default formatting of a given reference `name`"""
59 return name
59 return name
60
60
61
61
62 def _format_ref_id_svn(name, raw_id):
62 def _format_ref_id_svn(name, raw_id):
63 """Special way of formatting a reference for Subversion including path"""
63 """Special way of formatting a reference for Subversion including path"""
64 return '%s@%s' % (name, raw_id)
64 return '%s@%s' % (name, raw_id)
65
65
66
66
67 class TemplateArgs(StrictAttributeDict):
67 class TemplateArgs(StrictAttributeDict):
68 pass
68 pass
69
69
70
70
71 class BaseAppView(object):
71 class BaseAppView(object):
72
72
73 def __init__(self, context, request):
73 def __init__(self, context, request):
74 self.request = request
74 self.request = request
75 self.context = context
75 self.context = context
76 self.session = request.session
76 self.session = request.session
77 self._rhodecode_user = request.user # auth user
77 self._rhodecode_user = request.user # auth user
78 self._rhodecode_db_user = self._rhodecode_user.get_instance()
78 self._rhodecode_db_user = self._rhodecode_user.get_instance()
79 self._maybe_needs_password_change(
79 self._maybe_needs_password_change(
80 request.matched_route.name, self._rhodecode_db_user)
80 request.matched_route.name, self._rhodecode_db_user)
81
81
82 def _maybe_needs_password_change(self, view_name, user_obj):
82 def _maybe_needs_password_change(self, view_name, user_obj):
83 log.debug('Checking if user %s needs password change on view %s',
83 log.debug('Checking if user %s needs password change on view %s',
84 user_obj, view_name)
84 user_obj, view_name)
85 skip_user_views = [
85 skip_user_views = [
86 'logout', 'login',
86 'logout', 'login',
87 'my_account_password', 'my_account_password_update'
87 'my_account_password', 'my_account_password_update'
88 ]
88 ]
89
89
90 if not user_obj:
90 if not user_obj:
91 return
91 return
92
92
93 if user_obj.username == User.DEFAULT_USER:
93 if user_obj.username == User.DEFAULT_USER:
94 return
94 return
95
95
96 now = time.time()
96 now = time.time()
97 should_change = user_obj.user_data.get('force_password_change')
97 should_change = user_obj.user_data.get('force_password_change')
98 change_after = safe_int(should_change) or 0
98 change_after = safe_int(should_change) or 0
99 if should_change and now > change_after:
99 if should_change and now > change_after:
100 log.debug('User %s requires password change', user_obj)
100 log.debug('User %s requires password change', user_obj)
101 h.flash('You are required to change your password', 'warning',
101 h.flash('You are required to change your password', 'warning',
102 ignore_duplicate=True)
102 ignore_duplicate=True)
103
103
104 if view_name not in skip_user_views:
104 if view_name not in skip_user_views:
105 raise HTTPFound(
105 raise HTTPFound(
106 self.request.route_path('my_account_password'))
106 self.request.route_path('my_account_password'))
107
107
108 def _get_local_tmpl_context(self, include_app_defaults=False):
108 def _get_local_tmpl_context(self, include_app_defaults=False):
109 c = TemplateArgs()
109 c = TemplateArgs()
110 c.auth_user = self.request.user
110 c.auth_user = self.request.user
111 if include_app_defaults:
111 if include_app_defaults:
112 # NOTE(marcink): after full pyramid migration include_app_defaults
112 # NOTE(marcink): after full pyramid migration include_app_defaults
113 # should be turned on by default
113 # should be turned on by default
114 from rhodecode.lib.base import attach_context_attributes
114 from rhodecode.lib.base import attach_context_attributes
115 attach_context_attributes(c, self.request, self.request.user.user_id)
115 attach_context_attributes(c, self.request, self.request.user.user_id)
116 return c
116 return c
117
117
118 def _register_global_c(self, tmpl_args):
118 def _register_global_c(self, tmpl_args):
119 """
119 """
120 Registers attributes to pylons global `c`
120 Registers attributes to pylons global `c`
121 """
121 """
122 # TODO(marcink): remove once pyramid migration is finished
122 # TODO(marcink): remove once pyramid migration is finished
123 from pylons import tmpl_context as c
123 for k, v in tmpl_args.items():
124 for k, v in tmpl_args.items():
124 setattr(c, k, v)
125 setattr(c, k, v)
125
126
126 def _get_template_context(self, tmpl_args):
127 def _get_template_context(self, tmpl_args):
127 self._register_global_c(tmpl_args)
128 self._register_global_c(tmpl_args)
128
129
129 local_tmpl_args = {
130 local_tmpl_args = {
130 'defaults': {},
131 'defaults': {},
131 'errors': {},
132 'errors': {},
132 }
133 }
133 local_tmpl_args.update(tmpl_args)
134 local_tmpl_args.update(tmpl_args)
134 return local_tmpl_args
135 return local_tmpl_args
135
136
136 def load_default_context(self):
137 def load_default_context(self):
137 """
138 """
138 example:
139 example:
139
140
140 def load_default_context(self):
141 def load_default_context(self):
141 c = self._get_local_tmpl_context()
142 c = self._get_local_tmpl_context()
142 c.custom_var = 'foobar'
143 c.custom_var = 'foobar'
143 self._register_global_c(c)
144 self._register_global_c(c)
144 return c
145 return c
145 """
146 """
146 raise NotImplementedError('Needs implementation in view class')
147 raise NotImplementedError('Needs implementation in view class')
147
148
148
149
149 class RepoAppView(BaseAppView):
150 class RepoAppView(BaseAppView):
150
151
151 def __init__(self, context, request):
152 def __init__(self, context, request):
152 super(RepoAppView, self).__init__(context, request)
153 super(RepoAppView, self).__init__(context, request)
153 self.db_repo = request.db_repo
154 self.db_repo = request.db_repo
154 self.db_repo_name = self.db_repo.repo_name
155 self.db_repo_name = self.db_repo.repo_name
155 self.db_repo_pull_requests = ScmModel().get_pull_requests(self.db_repo)
156 self.db_repo_pull_requests = ScmModel().get_pull_requests(self.db_repo)
156
157
157 def _handle_missing_requirements(self, error):
158 def _handle_missing_requirements(self, error):
158 log.error(
159 log.error(
159 'Requirements are missing for repository %s: %s',
160 'Requirements are missing for repository %s: %s',
160 self.db_repo_name, error.message)
161 self.db_repo_name, error.message)
161
162
162 def _get_local_tmpl_context(self, include_app_defaults=False):
163 def _get_local_tmpl_context(self, include_app_defaults=False):
163 c = super(RepoAppView, self)._get_local_tmpl_context(
164 c = super(RepoAppView, self)._get_local_tmpl_context(
164 include_app_defaults=include_app_defaults)
165 include_app_defaults=include_app_defaults)
165
166
166 # register common vars for this type of view
167 # register common vars for this type of view
167 c.rhodecode_db_repo = self.db_repo
168 c.rhodecode_db_repo = self.db_repo
168 c.repo_name = self.db_repo_name
169 c.repo_name = self.db_repo_name
169 c.repository_pull_requests = self.db_repo_pull_requests
170 c.repository_pull_requests = self.db_repo_pull_requests
170
171
171 c.repository_requirements_missing = False
172 c.repository_requirements_missing = False
172 try:
173 try:
173 self.rhodecode_vcs_repo = self.db_repo.scm_instance()
174 self.rhodecode_vcs_repo = self.db_repo.scm_instance()
174 except RepositoryRequirementError as e:
175 except RepositoryRequirementError as e:
175 c.repository_requirements_missing = True
176 c.repository_requirements_missing = True
176 self._handle_missing_requirements(e)
177 self._handle_missing_requirements(e)
177
178
178 return c
179 return c
179
180
180
181
181 class DataGridAppView(object):
182 class DataGridAppView(object):
182 """
183 """
183 Common class to have re-usable grid rendering components
184 Common class to have re-usable grid rendering components
184 """
185 """
185
186
186 def _extract_ordering(self, request, column_map=None):
187 def _extract_ordering(self, request, column_map=None):
187 column_map = column_map or {}
188 column_map = column_map or {}
188 column_index = safe_int(request.GET.get('order[0][column]'))
189 column_index = safe_int(request.GET.get('order[0][column]'))
189 order_dir = request.GET.get(
190 order_dir = request.GET.get(
190 'order[0][dir]', 'desc')
191 'order[0][dir]', 'desc')
191 order_by = request.GET.get(
192 order_by = request.GET.get(
192 'columns[%s][data][sort]' % column_index, 'name_raw')
193 'columns[%s][data][sort]' % column_index, 'name_raw')
193
194
194 # translate datatable to DB columns
195 # translate datatable to DB columns
195 order_by = column_map.get(order_by) or order_by
196 order_by = column_map.get(order_by) or order_by
196
197
197 search_q = request.GET.get('search[value]')
198 search_q = request.GET.get('search[value]')
198 return search_q, order_by, order_dir
199 return search_q, order_by, order_dir
199
200
200 def _extract_chunk(self, request):
201 def _extract_chunk(self, request):
201 start = safe_int(request.GET.get('start'), 0)
202 start = safe_int(request.GET.get('start'), 0)
202 length = safe_int(request.GET.get('length'), 25)
203 length = safe_int(request.GET.get('length'), 25)
203 draw = safe_int(request.GET.get('draw'))
204 draw = safe_int(request.GET.get('draw'))
204 return draw, start, length
205 return draw, start, length
205
206
206
207
207 class BaseReferencesView(RepoAppView):
208 class BaseReferencesView(RepoAppView):
208 """
209 """
209 Base for reference view for branches, tags and bookmarks.
210 Base for reference view for branches, tags and bookmarks.
210 """
211 """
211 def load_default_context(self):
212 def load_default_context(self):
212 c = self._get_local_tmpl_context()
213 c = self._get_local_tmpl_context()
213
214
214 # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
215 # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
215 c.repo_info = self.db_repo
216 c.repo_info = self.db_repo
216
217
217 self._register_global_c(c)
218 self._register_global_c(c)
218 return c
219 return c
219
220
220 def load_refs_context(self, ref_items, partials_template):
221 def load_refs_context(self, ref_items, partials_template):
221 _render = PartialRenderer(partials_template)
222 _render = PartialRenderer(partials_template)
222 _data = []
223 _data = []
223 pre_load = ["author", "date", "message"]
224 pre_load = ["author", "date", "message"]
224
225
225 is_svn = h.is_svn(self.rhodecode_vcs_repo)
226 is_svn = h.is_svn(self.rhodecode_vcs_repo)
226 format_ref_id = get_format_ref_id(self.rhodecode_vcs_repo)
227 format_ref_id = get_format_ref_id(self.rhodecode_vcs_repo)
227
228
228 for ref_name, commit_id in ref_items:
229 for ref_name, commit_id in ref_items:
229 commit = self.rhodecode_vcs_repo.get_commit(
230 commit = self.rhodecode_vcs_repo.get_commit(
230 commit_id=commit_id, pre_load=pre_load)
231 commit_id=commit_id, pre_load=pre_load)
231
232
232 # TODO: johbo: Unify generation of reference links
233 # TODO: johbo: Unify generation of reference links
233 use_commit_id = '/' in ref_name or is_svn
234 use_commit_id = '/' in ref_name or is_svn
234 files_url = h.url(
235 files_url = h.url(
235 'files_home',
236 'files_home',
236 repo_name=c.repo_name,
237 repo_name=c.repo_name,
237 f_path=ref_name if is_svn else '',
238 f_path=ref_name if is_svn else '',
238 revision=commit_id if use_commit_id else ref_name,
239 revision=commit_id if use_commit_id else ref_name,
239 at=ref_name)
240 at=ref_name)
240
241
241 _data.append({
242 _data.append({
242 "name": _render('name', ref_name, files_url),
243 "name": _render('name', ref_name, files_url),
243 "name_raw": ref_name,
244 "name_raw": ref_name,
244 "date": _render('date', commit.date),
245 "date": _render('date', commit.date),
245 "date_raw": datetime_to_time(commit.date),
246 "date_raw": datetime_to_time(commit.date),
246 "author": _render('author', commit.author),
247 "author": _render('author', commit.author),
247 "commit": _render(
248 "commit": _render(
248 'commit', commit.message, commit.raw_id, commit.idx),
249 'commit', commit.message, commit.raw_id, commit.idx),
249 "commit_raw": commit.idx,
250 "commit_raw": commit.idx,
250 "compare": _render(
251 "compare": _render(
251 'compare', format_ref_id(ref_name, commit.raw_id)),
252 'compare', format_ref_id(ref_name, commit.raw_id)),
252 })
253 })
253 c.has_references = bool(_data)
254 c.has_references = bool(_data)
254 c.data = json.dumps(_data)
255 c.data = json.dumps(_data)
255
256
256
257
257 class RepoRoutePredicate(object):
258 class RepoRoutePredicate(object):
258 def __init__(self, val, config):
259 def __init__(self, val, config):
259 self.val = val
260 self.val = val
260
261
261 def text(self):
262 def text(self):
262 return 'repo_route = %s' % self.val
263 return 'repo_route = %s' % self.val
263
264
264 phash = text
265 phash = text
265
266
266 def __call__(self, info, request):
267 def __call__(self, info, request):
267
268
268 if hasattr(request, 'vcs_call'):
269 if hasattr(request, 'vcs_call'):
269 # skip vcs calls
270 # skip vcs calls
270 return
271 return
271
272
272 repo_name = info['match']['repo_name']
273 repo_name = info['match']['repo_name']
273 repo_model = repo.RepoModel()
274 repo_model = repo.RepoModel()
274 by_name_match = repo_model.get_by_repo_name(repo_name, cache=True)
275 by_name_match = repo_model.get_by_repo_name(repo_name, cache=True)
275
276
276 if by_name_match:
277 if by_name_match:
277 # register this as request object we can re-use later
278 # register this as request object we can re-use later
278 request.db_repo = by_name_match
279 request.db_repo = by_name_match
279 return True
280 return True
280
281
281 by_id_match = repo_model.get_repo_by_id(repo_name)
282 by_id_match = repo_model.get_repo_by_id(repo_name)
282 if by_id_match:
283 if by_id_match:
283 request.db_repo = by_id_match
284 request.db_repo = by_id_match
284 return True
285 return True
285
286
286 return False
287 return False
287
288
288
289
289 class RepoTypeRoutePredicate(object):
290 class RepoTypeRoutePredicate(object):
290 def __init__(self, val, config):
291 def __init__(self, val, config):
291 self.val = val or ['hg', 'git', 'svn']
292 self.val = val or ['hg', 'git', 'svn']
292
293
293 def text(self):
294 def text(self):
294 return 'repo_accepted_type = %s' % self.val
295 return 'repo_accepted_type = %s' % self.val
295
296
296 phash = text
297 phash = text
297
298
298 def __call__(self, info, request):
299 def __call__(self, info, request):
299 if hasattr(request, 'vcs_call'):
300 if hasattr(request, 'vcs_call'):
300 # skip vcs calls
301 # skip vcs calls
301 return
302 return
302
303
303 rhodecode_db_repo = request.db_repo
304 rhodecode_db_repo = request.db_repo
304
305
305 log.debug(
306 log.debug(
306 '%s checking repo type for %s in %s',
307 '%s checking repo type for %s in %s',
307 self.__class__.__name__, rhodecode_db_repo.repo_type, self.val)
308 self.__class__.__name__, rhodecode_db_repo.repo_type, self.val)
308
309
309 if rhodecode_db_repo.repo_type in self.val:
310 if rhodecode_db_repo.repo_type in self.val:
310 return True
311 return True
311 else:
312 else:
312 log.warning('Current view is not supported for repo type:%s',
313 log.warning('Current view is not supported for repo type:%s',
313 rhodecode_db_repo.repo_type)
314 rhodecode_db_repo.repo_type)
314 #
315 #
315 # h.flash(h.literal(
316 # h.flash(h.literal(
316 # _('Action not supported for %s.' % rhodecode_repo.alias)),
317 # _('Action not supported for %s.' % rhodecode_repo.alias)),
317 # category='warning')
318 # category='warning')
318 # return redirect(
319 # return redirect(
319 # route_path('repo_summary', repo_name=cls.rhodecode_db_repo.repo_name))
320 # route_path('repo_summary', repo_name=cls.rhodecode_db_repo.repo_name))
320
321
321 return False
322 return False
322
323
323
324
324 class RepoGroupRoutePredicate(object):
325 class RepoGroupRoutePredicate(object):
325 def __init__(self, val, config):
326 def __init__(self, val, config):
326 self.val = val
327 self.val = val
327
328
328 def text(self):
329 def text(self):
329 return 'repo_group_route = %s' % self.val
330 return 'repo_group_route = %s' % self.val
330
331
331 phash = text
332 phash = text
332
333
333 def __call__(self, info, request):
334 def __call__(self, info, request):
334 if hasattr(request, 'vcs_call'):
335 if hasattr(request, 'vcs_call'):
335 # skip vcs calls
336 # skip vcs calls
336 return
337 return
337
338
338 repo_group_name = info['match']['repo_group_name']
339 repo_group_name = info['match']['repo_group_name']
339 repo_group_model = repo_group.RepoGroupModel()
340 repo_group_model = repo_group.RepoGroupModel()
340 by_name_match = repo_group_model.get_by_group_name(
341 by_name_match = repo_group_model.get_by_group_name(
341 repo_group_name, cache=True)
342 repo_group_name, cache=True)
342
343
343 if by_name_match:
344 if by_name_match:
344 # register this as request object we can re-use later
345 # register this as request object we can re-use later
345 request.db_repo_group = by_name_match
346 request.db_repo_group = by_name_match
346 return True
347 return True
347
348
348 return False
349 return False
349
350
350
351
351 def includeme(config):
352 def includeme(config):
352 config.add_route_predicate(
353 config.add_route_predicate(
353 'repo_route', RepoRoutePredicate)
354 'repo_route', RepoRoutePredicate)
354 config.add_route_predicate(
355 config.add_route_predicate(
355 'repo_accepted_types', RepoTypeRoutePredicate)
356 'repo_accepted_types', RepoTypeRoutePredicate)
356 config.add_route_predicate(
357 config.add_route_predicate(
357 'repo_group_route', RepoGroupRoutePredicate)
358 'repo_group_route', RepoGroupRoutePredicate)
@@ -1,142 +1,142 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 import logging
22 import logging
23 import collections
23 import collections
24
24
25 from pylons import url
26 from zope.interface import implementer
25 from zope.interface import implementer
27
26
28 from rhodecode.apps.admin.interfaces import IAdminNavigationRegistry
27 from rhodecode.apps.admin.interfaces import IAdminNavigationRegistry
29 from rhodecode.lib.utils import get_registry
28 from rhodecode.lib.utils import get_registry
30 from rhodecode.translation import _
29 from rhodecode.translation import _
31
30
32
31
33 log = logging.getLogger(__name__)
32 log = logging.getLogger(__name__)
34
33
35 NavListEntry = collections.namedtuple('NavListEntry', ['key', 'name', 'url'])
34 NavListEntry = collections.namedtuple('NavListEntry', ['key', 'name', 'url'])
36
35
37
36
38 class NavEntry(object):
37 class NavEntry(object):
39 """
38 """
40 Represents an entry in the admin navigation.
39 Represents an entry in the admin navigation.
41
40
42 :param key: Unique identifier used to store reference in an OrderedDict.
41 :param key: Unique identifier used to store reference in an OrderedDict.
43 :param name: Display name, usually a translation string.
42 :param name: Display name, usually a translation string.
44 :param view_name: Name of the view, used generate the URL.
43 :param view_name: Name of the view, used generate the URL.
45 :param pyramid: Indicator to use pyramid for URL generation. This should
44 :param pyramid: Indicator to use pyramid for URL generation. This should
46 be removed as soon as we are fully migrated to pyramid.
45 be removed as soon as we are fully migrated to pyramid.
47 """
46 """
48
47
49 def __init__(self, key, name, view_name, pyramid=False):
48 def __init__(self, key, name, view_name, pyramid=False):
50 self.key = key
49 self.key = key
51 self.name = name
50 self.name = name
52 self.view_name = view_name
51 self.view_name = view_name
53 self.pyramid = pyramid
52 self.pyramid = pyramid
54
53
55 def generate_url(self, request):
54 def generate_url(self, request):
56 if self.pyramid:
55 if self.pyramid:
57 if hasattr(request, 'route_path'):
56 if hasattr(request, 'route_path'):
58 return request.route_path(self.view_name)
57 return request.route_path(self.view_name)
59 else:
58 else:
60 # TODO: johbo: Remove this after migrating to pyramid.
59 # TODO: johbo: Remove this after migrating to pyramid.
61 # We need the pyramid request here to generate URLs to pyramid
60 # We need the pyramid request here to generate URLs to pyramid
62 # views from within pylons views.
61 # views from within pylons views.
63 from pyramid.threadlocal import get_current_request
62 from pyramid.threadlocal import get_current_request
64 pyramid_request = get_current_request()
63 pyramid_request = get_current_request()
65 return pyramid_request.route_path(self.view_name)
64 return pyramid_request.route_path(self.view_name)
66 else:
65 else:
66 from pylons import url
67 return url(self.view_name)
67 return url(self.view_name)
68
68
69 def get_localized_name(self, request):
69 def get_localized_name(self, request):
70 if hasattr(request, 'translate'):
70 if hasattr(request, 'translate'):
71 return request.translate(self.name)
71 return request.translate(self.name)
72 else:
72 else:
73 # TODO(marcink): Remove this after migrating to pyramid
73 # TODO(marcink): Remove this after migrating to pyramid
74 from pyramid.threadlocal import get_current_request
74 from pyramid.threadlocal import get_current_request
75 pyramid_request = get_current_request()
75 pyramid_request = get_current_request()
76 return pyramid_request.translate(self.name)
76 return pyramid_request.translate(self.name)
77
77
78
78
79 @implementer(IAdminNavigationRegistry)
79 @implementer(IAdminNavigationRegistry)
80 class NavigationRegistry(object):
80 class NavigationRegistry(object):
81
81
82 _base_entries = [
82 _base_entries = [
83 NavEntry('global', _('Global'), 'admin_settings_global'),
83 NavEntry('global', _('Global'), 'admin_settings_global'),
84 NavEntry('vcs', _('VCS'), 'admin_settings_vcs'),
84 NavEntry('vcs', _('VCS'), 'admin_settings_vcs'),
85 NavEntry('visual', _('Visual'), 'admin_settings_visual'),
85 NavEntry('visual', _('Visual'), 'admin_settings_visual'),
86 NavEntry('mapping', _('Remap and Rescan'), 'admin_settings_mapping'),
86 NavEntry('mapping', _('Remap and Rescan'), 'admin_settings_mapping'),
87 NavEntry('issuetracker', _('Issue Tracker'),
87 NavEntry('issuetracker', _('Issue Tracker'),
88 'admin_settings_issuetracker'),
88 'admin_settings_issuetracker'),
89 NavEntry('email', _('Email'), 'admin_settings_email'),
89 NavEntry('email', _('Email'), 'admin_settings_email'),
90 NavEntry('hooks', _('Hooks'), 'admin_settings_hooks'),
90 NavEntry('hooks', _('Hooks'), 'admin_settings_hooks'),
91 NavEntry('search', _('Full Text Search'), 'admin_settings_search'),
91 NavEntry('search', _('Full Text Search'), 'admin_settings_search'),
92
92
93 NavEntry('integrations', _('Integrations'),
93 NavEntry('integrations', _('Integrations'),
94 'global_integrations_home', pyramid=True),
94 'global_integrations_home', pyramid=True),
95 NavEntry('system', _('System Info'),
95 NavEntry('system', _('System Info'),
96 'admin_settings_system', pyramid=True),
96 'admin_settings_system', pyramid=True),
97 NavEntry('process_management', _('Processes'),
97 NavEntry('process_management', _('Processes'),
98 'admin_settings_process_management', pyramid=True),
98 'admin_settings_process_management', pyramid=True),
99 NavEntry('sessions', _('User Sessions'),
99 NavEntry('sessions', _('User Sessions'),
100 'admin_settings_sessions', pyramid=True),
100 'admin_settings_sessions', pyramid=True),
101 NavEntry('open_source', _('Open Source Licenses'),
101 NavEntry('open_source', _('Open Source Licenses'),
102 'admin_settings_open_source', pyramid=True),
102 'admin_settings_open_source', pyramid=True),
103
103
104 # TODO: marcink: we disable supervisor now until the supervisor stats
104 # TODO: marcink: we disable supervisor now until the supervisor stats
105 # page is fixed in the nix configuration
105 # page is fixed in the nix configuration
106 # NavEntry('supervisor', _('Supervisor'), 'admin_settings_supervisor'),
106 # NavEntry('supervisor', _('Supervisor'), 'admin_settings_supervisor'),
107 ]
107 ]
108
108
109 _labs_entry = NavEntry('labs', _('Labs'), 'admin_settings_labs')
109 _labs_entry = NavEntry('labs', _('Labs'), 'admin_settings_labs')
110
110
111 def __init__(self, labs_active=False):
111 def __init__(self, labs_active=False):
112 self._registered_entries = collections.OrderedDict([
112 self._registered_entries = collections.OrderedDict([
113 (item.key, item) for item in self.__class__._base_entries
113 (item.key, item) for item in self.__class__._base_entries
114 ])
114 ])
115
115
116 if labs_active:
116 if labs_active:
117 self.add_entry(self._labs_entry)
117 self.add_entry(self._labs_entry)
118
118
119 def add_entry(self, entry):
119 def add_entry(self, entry):
120 self._registered_entries[entry.key] = entry
120 self._registered_entries[entry.key] = entry
121
121
122 def get_navlist(self, request):
122 def get_navlist(self, request):
123 navlist = [NavListEntry(i.key, i.get_localized_name(request),
123 navlist = [NavListEntry(i.key, i.get_localized_name(request),
124 i.generate_url(request))
124 i.generate_url(request))
125 for i in self._registered_entries.values()]
125 for i in self._registered_entries.values()]
126 return navlist
126 return navlist
127
127
128
128
129 def navigation_registry(request):
129 def navigation_registry(request):
130 """
130 """
131 Helper that returns the admin navigation registry.
131 Helper that returns the admin navigation registry.
132 """
132 """
133 pyramid_registry = get_registry(request)
133 pyramid_registry = get_registry(request)
134 nav_registry = pyramid_registry.queryUtility(IAdminNavigationRegistry)
134 nav_registry = pyramid_registry.queryUtility(IAdminNavigationRegistry)
135 return nav_registry
135 return nav_registry
136
136
137
137
138 def navigation_list(request):
138 def navigation_list(request):
139 """
139 """
140 Helper that returns the admin navigation as list of NavListEntry objects.
140 Helper that returns the admin navigation as list of NavListEntry objects.
141 """
141 """
142 return navigation_registry(request).get_navlist(request)
142 return navigation_registry(request).get_navlist(request)
General Comments 0
You need to be logged in to leave comments. Login now