repo-commits: ported changeset code into pyramid views....
marcink -
r1951:965019b0 default
Not Reviewed
Show More
Add another comment
TODOs: 0 unresolved 0 Resolved
COMMENTS: 0 General 0 Inline
This diff has been collapsed as it changes many lines, (557 lines changed) Show them Hide them
@@ -0,0 +1,557
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import logging
23 import collections
24
25 from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest, HTTPFound
26 from pyramid.view import view_config
27 from pyramid.renderers import render
28 from pyramid.response import Response
29
30 from rhodecode.apps._base import RepoAppView
31
32 from rhodecode.lib import diffs, codeblocks
33 from rhodecode.lib.auth import (
34 LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous, CSRFRequired)
35
36 from rhodecode.lib.compat import OrderedDict
37 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
38 import rhodecode.lib.helpers as h
39 from rhodecode.lib.utils2 import safe_unicode, safe_int
40 from rhodecode.lib.vcs.backends.base import EmptyCommit
41 from rhodecode.lib.vcs.exceptions import (
42 RepositoryError, CommitDoesNotExistError, NodeDoesNotExistError)
43 from rhodecode.model.db import ChangesetComment, ChangesetStatus
44 from rhodecode.model.changeset_status import ChangesetStatusModel
45 from rhodecode.model.comment import CommentsModel
46 from rhodecode.model.meta import Session
47
48
49 log = logging.getLogger(__name__)
50
51
52 def _update_with_GET(params, request):
53 for k in ['diff1', 'diff2', 'diff']:
54 params[k] += request.GET.getall(k)
55
56
57 def get_ignore_ws(fid, request):
58 ig_ws_global = request.GET.get('ignorews')
59 ig_ws = filter(lambda k: k.startswith('WS'), request.GET.getall(fid))
60 if ig_ws:
61 try:
62 return int(ig_ws[0].split(':')[-1])
63 except Exception:
64 pass
65 return ig_ws_global
66
67
68 def _ignorews_url(request, fileid=None):
69 _ = request.translate
70 fileid = str(fileid) if fileid else None
71 params = collections.defaultdict(list)
72 _update_with_GET(params, request)
73 label = _('Show whitespace')
74 tooltiplbl = _('Show whitespace for all diffs')
75 ig_ws = get_ignore_ws(fileid, request)
76 ln_ctx = get_line_ctx(fileid, request)
77
78 if ig_ws is None:
79 params['ignorews'] += [1]
80 label = _('Ignore whitespace')
81 tooltiplbl = _('Ignore whitespace for all diffs')
82 ctx_key = 'context'
83 ctx_val = ln_ctx
84
85 # if we have passed in ln_ctx pass it along to our params
86 if ln_ctx:
87 params[ctx_key] += [ctx_val]
88
89 if fileid:
90 params['anchor'] = 'a_' + fileid
91 return h.link_to(label, request.current_route_path(_query=params),
92 title=tooltiplbl, class_='tooltip')
93
94
95 def get_line_ctx(fid, request):
96 ln_ctx_global = request.GET.get('context')
97 if fid:
98 ln_ctx = filter(lambda k: k.startswith('C'), request.GET.getall(fid))
99 else:
100 _ln_ctx = filter(lambda k: k.startswith('C'), request.GET)
101 ln_ctx = request.GET.get(_ln_ctx[0]) if _ln_ctx else ln_ctx_global
102 if ln_ctx:
103 ln_ctx = [ln_ctx]
104
105 if ln_ctx:
106 retval = ln_ctx[0].split(':')[-1]
107 else:
108 retval = ln_ctx_global
109
110 try:
111 return int(retval)
112 except Exception:
113 return 3
114
115
116 def _context_url(request, fileid=None):
117 """
118 Generates a url for context lines.
119
120 :param fileid:
121 """
122
123 _ = request.translate
124 fileid = str(fileid) if fileid else None
125 ig_ws = get_ignore_ws(fileid, request)
126 ln_ctx = (get_line_ctx(fileid, request) or 3) * 2
127
128 params = collections.defaultdict(list)
129 _update_with_GET(params, request)
130
131 if ln_ctx > 0:
132 params['context'] += [ln_ctx]
133
134 if ig_ws:
135 ig_ws_key = 'ignorews'
136 ig_ws_val = 1
137 params[ig_ws_key] += [ig_ws_val]
138
139 lbl = _('Increase context')
140 tooltiplbl = _('Increase context for all diffs')
141
142 if fileid:
143 params['anchor'] = 'a_' + fileid
144 return h.link_to(lbl, request.current_route_path(_query=params),
145 title=tooltiplbl, class_='tooltip')
146
147
148 class RepoCommitsView(RepoAppView):
149 def load_default_context(self):
150 c = self._get_local_tmpl_context(include_app_defaults=True)
151
152 # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
153 c.repo_info = self.db_repo
154 c.rhodecode_repo = self.rhodecode_vcs_repo
155
156 self._register_global_c(c)
157 return c
158
159 def _commit(self, commit_id_range, method):
160 _ = self.request.translate
161 c = self.load_default_context()
162 c.ignorews_url = _ignorews_url
163 c.context_url = _context_url
164 c.fulldiff = self.request.GET.get('fulldiff')
165
166 # fetch global flags of ignore ws or context lines
167 context_lcl = get_line_ctx('', self.request)
168 ign_whitespace_lcl = get_ignore_ws('', self.request)
169
170 # diff_limit will cut off the whole diff if the limit is applied
171 # otherwise it will just hide the big files from the front-end
172 diff_limit = c.visual.cut_off_limit_diff
173 file_limit = c.visual.cut_off_limit_file
174
175 # get ranges of commit ids if preset
176 commit_range = commit_id_range.split('...')[:2]
177
178 try:
179 pre_load = ['affected_files', 'author', 'branch', 'date',
180 'message', 'parents']
181
182 if len(commit_range) == 2:
183 commits = self.rhodecode_vcs_repo.get_commits(
184 start_id=commit_range[0], end_id=commit_range[1],
185 pre_load=pre_load)
186 commits = list(commits)
187 else:
188 commits = [self.rhodecode_vcs_repo.get_commit(
189 commit_id=commit_id_range, pre_load=pre_load)]
190
191 c.commit_ranges = commits
192 if not c.commit_ranges:
193 raise RepositoryError(
194 'The commit range returned an empty result')
195 except CommitDoesNotExistError:
196 msg = _('No such commit exists for this repository')
197 h.flash(msg, category='error')
198 raise HTTPNotFound()
199 except Exception:
200 log.exception("General failure")
201 raise HTTPNotFound()
202
203 c.changes = OrderedDict()
204 c.lines_added = 0
205 c.lines_deleted = 0
206
207 # auto collapse if we have more than limit
208 collapse_limit = diffs.DiffProcessor._collapse_commits_over
209 c.collapse_all_commits = len(c.commit_ranges) > collapse_limit
210
211 c.commit_statuses = ChangesetStatus.STATUSES
212 c.inline_comments = []
213 c.files = []
214
215 c.statuses = []
216 c.comments = []
217 c.unresolved_comments = []
218 if len(c.commit_ranges) == 1:
219 commit = c.commit_ranges[0]
220 c.comments = CommentsModel().get_comments(
221 self.db_repo.repo_id,
222 revision=commit.raw_id)
223 c.statuses.append(ChangesetStatusModel().get_status(
224 self.db_repo.repo_id, commit.raw_id))
225 # comments from PR
226 statuses = ChangesetStatusModel().get_statuses(
227 self.db_repo.repo_id, commit.raw_id,
228 with_revisions=True)
229 prs = set(st.pull_request for st in statuses
230 if st.pull_request is not None)
231 # from associated statuses, check the pull requests, and
232 # show comments from them
233 for pr in prs:
234 c.comments.extend(pr.comments)
235
236 c.unresolved_comments = CommentsModel()\
237 .get_commit_unresolved_todos(commit.raw_id)
238
239 diff = None
240 # Iterate over ranges (default commit view is always one commit)
241 for commit in c.commit_ranges:
242 c.changes[commit.raw_id] = []
243
244 commit2 = commit
245 commit1 = commit.parents[0] if commit.parents else EmptyCommit()
246
247 _diff = self.rhodecode_vcs_repo.get_diff(
248 commit1, commit2,
249 ignore_whitespace=ign_whitespace_lcl, context=context_lcl)
250 diff_processor = diffs.DiffProcessor(
251 _diff, format='newdiff', diff_limit=diff_limit,
252 file_limit=file_limit, show_full_diff=c.fulldiff)
253
254 commit_changes = OrderedDict()
255 if method == 'show':
256 _parsed = diff_processor.prepare()
257 c.limited_diff = isinstance(_parsed, diffs.LimitedDiffContainer)
258
259 _parsed = diff_processor.prepare()
260
261 def _node_getter(commit):
262 def get_node(fname):
263 try:
264 return commit.get_node(fname)
265 except NodeDoesNotExistError:
266 return None
267 return get_node
268
269 inline_comments = CommentsModel().get_inline_comments(
270 self.db_repo.repo_id, revision=commit.raw_id)
271 c.inline_cnt = CommentsModel().get_inline_comments_count(
272 inline_comments)
273
274 diffset = codeblocks.DiffSet(
275 repo_name=self.db_repo_name,
276 source_node_getter=_node_getter(commit1),
277 target_node_getter=_node_getter(commit2),
278 comments=inline_comments)
279 diffset = diffset.render_patchset(
280 _parsed, commit1.raw_id, commit2.raw_id)
281
282 c.changes[commit.raw_id] = diffset
283 else:
284 # downloads/raw we only need RAW diff nothing else
285 diff = diff_processor.as_raw()
286 c.changes[commit.raw_id] = [None, None, None, None, diff, None, None]
287
288 # sort comments by how they were generated
289 c.comments = sorted(c.comments, key=lambda x: x.comment_id)
290
291 if len(c.commit_ranges) == 1:
292 c.commit = c.commit_ranges[0]
293 c.parent_tmpl = ''.join(
294 '# Parent %s\n' % x.raw_id for x in c.commit.parents)
295
296 if method == 'download':
297 response = Response(diff)
298 response.content_type = 'text/plain'
299 response.content_disposition = (
300 'attachment; filename=%s.diff' % commit_id_range[:12])
301 return response
302 elif method == 'patch':
303 c.diff = safe_unicode(diff)
304 patch = render(
305 'rhodecode:templates/changeset/patch_changeset.mako',
306 self._get_template_context(c), self.request)
307 response = Response(patch)
308 response.content_type = 'text/plain'
309 return response
310 elif method == 'raw':
311 response = Response(diff)
312 response.content_type = 'text/plain'
313 return response
314 elif method == 'show':
315 if len(c.commit_ranges) == 1:
316 html = render(
317 'rhodecode:templates/changeset/changeset.mako',
318 self._get_template_context(c), self.request)
319 return Response(html)
320 else:
321 c.ancestor = None
322 c.target_repo = self.db_repo
323 html = render(
324 'rhodecode:templates/changeset/changeset_range.mako',
325 self._get_template_context(c), self.request)
326 return Response(html)
327
328 raise HTTPBadRequest()
329
330 @LoginRequired()
331 @HasRepoPermissionAnyDecorator(
332 'repository.read', 'repository.write', 'repository.admin')
333 @view_config(
334 route_name='repo_commit', request_method='GET',
335 renderer=None)
336 def repo_commit_show(self):
337 commit_id = self.request.matchdict['commit_id']
338 return self._commit(commit_id, method='show')
339
340 @LoginRequired()
341 @HasRepoPermissionAnyDecorator(
342 'repository.read', 'repository.write', 'repository.admin')
343 @view_config(
344 route_name='repo_commit_raw', request_method='GET',
345 renderer=None)
346 @view_config(
347 route_name='repo_commit_raw_deprecated', request_method='GET',
348 renderer=None)
349 def repo_commit_raw(self):
350 commit_id = self.request.matchdict['commit_id']
351 return self._commit(commit_id, method='raw')
352
353 @LoginRequired()
354 @HasRepoPermissionAnyDecorator(
355 'repository.read', 'repository.write', 'repository.admin')
356 @view_config(
357 route_name='repo_commit_patch', request_method='GET',
358 renderer=None)
359 def repo_commit_patch(self):
360 commit_id = self.request.matchdict['commit_id']
361 return self._commit(commit_id, method='patch')
362
363 @LoginRequired()
364 @HasRepoPermissionAnyDecorator(
365 'repository.read', 'repository.write', 'repository.admin')
366 @view_config(
367 route_name='repo_commit_download', request_method='GET',
368 renderer=None)
369 def repo_commit_download(self):
370 commit_id = self.request.matchdict['commit_id']
371 return self._commit(commit_id, method='download')
372
373 @LoginRequired()
374 @NotAnonymous()
375 @HasRepoPermissionAnyDecorator(
376 'repository.read', 'repository.write', 'repository.admin')
377 @CSRFRequired()
378 @view_config(
379 route_name='repo_commit_comment_create', request_method='POST',
380 renderer='json_ext')
381 def repo_commit_comment_create(self):
382 _ = self.request.translate
383 commit_id = self.request.matchdict['commit_id']
384
385 c = self.load_default_context()
386 status = self.request.POST.get('changeset_status', None)
387 text = self.request.POST.get('text')
388 comment_type = self.request.POST.get('comment_type')
389 resolves_comment_id = self.request.POST.get('resolves_comment_id', None)
390
391 if status:
392 text = text or (_('Status change %(transition_icon)s %(status)s')
393 % {'transition_icon': '>',
394 'status': ChangesetStatus.get_status_lbl(status)})
395
396 multi_commit_ids = []
397 for _commit_id in self.request.POST.get('commit_ids', '').split(','):
398 if _commit_id not in ['', None, EmptyCommit.raw_id]:
399 if _commit_id not in multi_commit_ids:
400 multi_commit_ids.append(_commit_id)
401
402 commit_ids = multi_commit_ids or [commit_id]
403
404 comment = None
405 for current_id in filter(None, commit_ids):
406 comment = CommentsModel().create(
407 text=text,
408 repo=self.db_repo.repo_id,
409 user=self._rhodecode_db_user.user_id,
410 commit_id=current_id,
411 f_path=self.request.POST.get('f_path'),
412 line_no=self.request.POST.get('line'),
413 status_change=(ChangesetStatus.get_status_lbl(status)
414 if status else None),
415 status_change_type=status,
416 comment_type=comment_type,
417 resolves_comment_id=resolves_comment_id
418 )
419
420 # get status if set !
421 if status:
422 # if latest status was from pull request and it's closed
423 # disallow changing status !
424 # dont_allow_on_closed_pull_request = True !
425
426 try:
427 ChangesetStatusModel().set_status(
428 self.db_repo.repo_id,
429 status,
430 self._rhodecode_db_user.user_id,
431 comment,
432 revision=current_id,
433 dont_allow_on_closed_pull_request=True
434 )
435 except StatusChangeOnClosedPullRequestError:
436 msg = _('Changing the status of a commit associated with '
437 'a closed pull request is not allowed')
438 log.exception(msg)
439 h.flash(msg, category='warning')
440 raise HTTPFound(h.route_path(
441 'repo_commit', repo_name=self.db_repo_name,
442 commit_id=current_id))
443
444 # finalize, commit and redirect
445 Session().commit()
446
447 data = {
448 'target_id': h.safeid(h.safe_unicode(
449 self.request.POST.get('f_path'))),
450 }
451 if comment:
452 c.co = comment
453 rendered_comment = render(
454 'rhodecode:templates/changeset/changeset_comment_block.mako',
455 self._get_template_context(c), self.request)
456
457 data.update(comment.get_dict())
458 data.update({'rendered_text': rendered_comment})
459
460 return data
461
462 @LoginRequired()
463 @NotAnonymous()
464 @HasRepoPermissionAnyDecorator(
465 'repository.read', 'repository.write', 'repository.admin')
466 @CSRFRequired()
467 @view_config(
468 route_name='repo_commit_comment_preview', request_method='POST',
469 renderer='string', xhr=True)
470 def repo_commit_comment_preview(self):
471 # Technically a CSRF token is not needed as no state changes with this
472 # call. However, as this is a POST is better to have it, so automated
473 # tools don't flag it as potential CSRF.
474 # Post is required because the payload could be bigger than the maximum
475 # allowed by GET.
476
477 text = self.request.POST.get('text')
478 renderer = self.request.POST.get('renderer') or 'rst'
479 if text:
480 return h.render(text, renderer=renderer, mentions=True)
481 return ''
482
483 @LoginRequired()
484 @NotAnonymous()
485 @HasRepoPermissionAnyDecorator(
486 'repository.read', 'repository.write', 'repository.admin')
487 @CSRFRequired()
488 @view_config(
489 route_name='repo_commit_comment_delete', request_method='POST',
490 renderer='json_ext')
491 def repo_commit_comment_delete(self):
492 commit_id = self.request.matchdict['commit_id']
493 comment_id = self.request.matchdict['comment_id']
494
495 comment = ChangesetComment.get_or_404(safe_int(comment_id))
496 if not comment:
497 log.debug('Comment with id:%s not found, skipping', comment_id)
498 # comment already deleted in another call probably
499 return True
500
501 is_repo_admin = h.HasRepoPermissionAny('repository.admin')(self.db_repo_name)
502 super_admin = h.HasPermissionAny('hg.admin')()
503 comment_owner = (comment.author.user_id == self._rhodecode_db_user.user_id)
504 is_repo_comment = comment.repo.repo_name == self.db_repo_name
505 comment_repo_admin = is_repo_admin and is_repo_comment
506
507 if super_admin or comment_owner or comment_repo_admin:
508 CommentsModel().delete(comment=comment, user=self._rhodecode_db_user)
509 Session().commit()
510 return True
511 else:
512 log.warning('No permissions for user %s to delete comment_id: %s',
513 self._rhodecode_db_user, comment_id)
514 raise HTTPNotFound()
515
516 @LoginRequired()
517 @HasRepoPermissionAnyDecorator(
518 'repository.read', 'repository.write', 'repository.admin')
519 @view_config(
520 route_name='repo_commit_data', request_method='GET',
521 renderer='json_ext', xhr=True)
522 def repo_commit_data(self):
523 commit_id = self.request.matchdict['commit_id']
524 self.load_default_context()
525
526 try:
527 return self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
528 except CommitDoesNotExistError as e:
529 return EmptyCommit(message=str(e))
530
531 @LoginRequired()
532 @HasRepoPermissionAnyDecorator(
533 'repository.read', 'repository.write', 'repository.admin')
534 @view_config(
535 route_name='repo_commit_children', request_method='GET',
536 renderer='json_ext', xhr=True)
537 def repo_commit_children(self):
538 commit_id = self.request.matchdict['commit_id']
539 self.load_default_context()
540
541 commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
542 result = {"results": commit.children}
543 return result
544
545 @LoginRequired()
546 @HasRepoPermissionAnyDecorator(
547 'repository.read', 'repository.write', 'repository.admin')
548 @view_config(
549 route_name='repo_commit_parents', request_method='GET',
550 renderer='json_ext')
551 def repo_commit_parents(self):
552 commit_id = self.request.matchdict['commit_id']
553 self.load_default_context()
554
555 commit = self.rhodecode_vcs_repo.get_commit(commit_id=commit_id)
556 result = {"results": commit.parents}
557 return result
@@ -210,11 +210,12
210 ## The list should be "," separated and on a single line.
210 ## The list should be "," separated and on a single line.
211 ##
211 ##
212 ## Most common views to enable:
212 ## Most common views to enable:
213 # ChangesetController:changeset_patch
213 # RepoCommitsView:repo_commit_download
214 # ChangesetController:changeset_raw
214 # RepoCommitsView:repo_commit_patch
215 # RepoFilesView.repo_files_diff
215 # RepoCommitsView:repo_commit_raw
216 # RepoFilesView.repo_archivefile
216 # RepoFilesView:repo_files_diff
217 # RepoFilesView.repo_file_raw
217 # RepoFilesView:repo_archivefile
218 # RepoFilesView:repo_file_raw
218 # GistView:*
219 # GistView:*
219 api_access_controllers_whitelist =
220 api_access_controllers_whitelist =
220
221
@@ -184,11 +184,12
184 ## The list should be "," separated and on a single line.
184 ## The list should be "," separated and on a single line.
185 ##
185 ##
186 ## Most common views to enable:
186 ## Most common views to enable:
187 # ChangesetController:changeset_patch
187 # RepoCommitsView:repo_commit_download
188 # ChangesetController:changeset_raw
188 # RepoCommitsView:repo_commit_patch
189 # RepoFilesView.repo_files_diff
189 # RepoCommitsView:repo_commit_raw
190 # RepoFilesView.repo_archivefile
190 # RepoFilesView:repo_files_diff
191 # RepoFilesView.repo_file_raw
191 # RepoFilesView:repo_archivefile
192 # RepoFilesView:repo_file_raw
192 # GistView:*
193 # GistView:*
193 api_access_controllers_whitelist =
194 api_access_controllers_whitelist =
194
195
@@ -42,7 +42,7
42 ## Syntax is <ControllerClass>:<function_pattern>.
42 ## Syntax is <ControllerClass>:<function_pattern>.
43 ## The list should be "," separated and on a single line.
43 ## The list should be "," separated and on a single line.
44 ##
44 ##
45 api_access_controllers_whitelist = ChangesetController:changeset_patch,ChangesetController:changeset_raw,ilesController:raw,FilesController:archivefile,
45 api_access_controllers_whitelist = RepoCommitsView:repo_commit_raw,RepoCommitsView:repo_commit_patch,RepoCommitsView:repo_commit_download
46
46
47 After this change, a |RCE| view can be accessed without login by adding a
47 After this change, a |RCE| view can be accessed without login by adding a
48 GET parameter ``?auth_token=<auth_token>`` to a url. For example to
48 GET parameter ``?auth_token=<auth_token>`` to a url. For example to
@@ -172,9 +172,9
172 'text': entry['commit_id'],
172 'text': entry['commit_id'],
173 'type': 'commit',
173 'type': 'commit',
174 'obj': {'repo': entry['repository']},
174 'obj': {'repo': entry['repository']},
175 'url': h.url('changeset_home',
175 'url': h.route_path('repo_commit',
176 repo_name=entry['repository'],
176 repo_name=entry['repository'],
177 revision=entry['commit_id'])
177 commit_id=entry['commit_id'])
178 }
178 }
179 for entry in result['results']]
179 for entry in result['results']]
180
180
@@ -36,6 +36,8
36
36
37 fixture = Fixture()
37 fixture = Fixture()
38
38
39 whitelist_view = ['RepoCommitsView:repo_commit_raw']
40
39
41
40 def route_path(name, params=None, **kwargs):
42 def route_path(name, params=None, **kwargs):
41 import urllib
43 import urllib
@@ -474,11 +476,10
474 def test_access_whitelisted_page_via_auth_token(
476 def test_access_whitelisted_page_via_auth_token(
475 self, test_name, auth_token, code, user_admin):
477 self, test_name, auth_token, code, user_admin):
476
478
477 whitelist_entry = ['ChangesetController:changeset_raw']
479 whitelist = self._get_api_whitelist(whitelist_view)
478 whitelist = self._get_api_whitelist(whitelist_entry)
479
480
480 with mock.patch.dict('rhodecode.CONFIG', whitelist):
481 with mock.patch.dict('rhodecode.CONFIG', whitelist):
481 assert whitelist_entry == whitelist['api_access_controllers_whitelist']
482 assert whitelist_view == whitelist['api_access_controllers_whitelist']
482
483
483 if test_name == 'proper_auth_token':
484 if test_name == 'proper_auth_token':
484 auth_token = user_admin.api_key
485 auth_token = user_admin.api_key
@@ -492,10 +493,9
492 status=code)
493 status=code)
493
494
494 def test_access_page_via_extra_auth_token(self):
495 def test_access_page_via_extra_auth_token(self):
495 whitelist = self._get_api_whitelist(
496 whitelist = self._get_api_whitelist(whitelist_view)
496 ['ChangesetController:changeset_raw'])
497 with mock.patch.dict('rhodecode.CONFIG', whitelist):
497 with mock.patch.dict('rhodecode.CONFIG', whitelist):
498 assert ['ChangesetController:changeset_raw'] == \
498 assert whitelist_view == \
499 whitelist['api_access_controllers_whitelist']
499 whitelist['api_access_controllers_whitelist']
500
500
501 new_auth_token = AuthTokenModel().create(
501 new_auth_token = AuthTokenModel().create(
@@ -509,10 +509,9
509 status=200)
509 status=200)
510
510
511 def test_access_page_via_expired_auth_token(self):
511 def test_access_page_via_expired_auth_token(self):
512 whitelist = self._get_api_whitelist(
512 whitelist = self._get_api_whitelist(whitelist_view)
513 ['ChangesetController:changeset_raw'])
514 with mock.patch.dict('rhodecode.CONFIG', whitelist):
513 with mock.patch.dict('rhodecode.CONFIG', whitelist):
515 assert ['ChangesetController:changeset_raw'] == \
514 assert whitelist_view == \
516 whitelist['api_access_controllers_whitelist']
515 whitelist['api_access_controllers_whitelist']
517
516
518 new_auth_token = AuthTokenModel().create(
517 new_auth_token = AuthTokenModel().create(
@@ -33,10 +33,52
33 pattern='/{repo_name:.*?[^/]}/summary-commits', repo_route=True)
33 pattern='/{repo_name:.*?[^/]}/summary-commits', repo_route=True)
34
34
35 # repo commits
35 # repo commits
36
36 config.add_route(
37 config.add_route(
37 name='repo_commit',
38 name='repo_commit',
38 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}', repo_route=True)
39 pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}', repo_route=True)
39
40
41 config.add_route(
42 name