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