Show More
@@ -0,0 +1,187 b'' | |||||
|
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 | import os | |||
|
22 | import csv | |||
|
23 | import datetime | |||
|
24 | ||||
|
25 | import pytest | |||
|
26 | ||||
|
27 | from rhodecode.tests import * | |||
|
28 | from rhodecode.tests.fixture import FIXTURES | |||
|
29 | from rhodecode.model.db import UserLog | |||
|
30 | from rhodecode.model.meta import Session | |||
|
31 | from rhodecode.lib.utils2 import safe_unicode | |||
|
32 | ||||
|
33 | ||||
|
34 | def route_path(name, params=None, **kwargs): | |||
|
35 | import urllib | |||
|
36 | from rhodecode.apps._base import ADMIN_PREFIX | |||
|
37 | ||||
|
38 | base_url = { | |||
|
39 | 'admin_home': ADMIN_PREFIX, | |||
|
40 | 'admin_audit_logs': ADMIN_PREFIX + '/audit_logs', | |||
|
41 | ||||
|
42 | }[name].format(**kwargs) | |||
|
43 | ||||
|
44 | if params: | |||
|
45 | base_url = '{}?{}'.format(base_url, urllib.urlencode(params)) | |||
|
46 | return base_url | |||
|
47 | ||||
|
48 | ||||
|
49 | class TestAdminController(TestController): | |||
|
50 | ||||
|
51 | @pytest.fixture(scope='class', autouse=True) | |||
|
52 | def prepare(self, request, pylonsapp): | |||
|
53 | UserLog.query().delete() | |||
|
54 | Session().commit() | |||
|
55 | ||||
|
56 | def strptime(val): | |||
|
57 | fmt = '%Y-%m-%d %H:%M:%S' | |||
|
58 | if '.' not in val: | |||
|
59 | return datetime.datetime.strptime(val, fmt) | |||
|
60 | ||||
|
61 | nofrag, frag = val.split(".") | |||
|
62 | date = datetime.datetime.strptime(nofrag, fmt) | |||
|
63 | ||||
|
64 | frag = frag[:6] # truncate to microseconds | |||
|
65 | frag += (6 - len(frag)) * '0' # add 0s | |||
|
66 | return date.replace(microsecond=int(frag)) | |||
|
67 | ||||
|
68 | with open(os.path.join(FIXTURES, 'journal_dump.csv')) as f: | |||
|
69 | for row in csv.DictReader(f): | |||
|
70 | ul = UserLog() | |||
|
71 | for k, v in row.iteritems(): | |||
|
72 | v = safe_unicode(v) | |||
|
73 | if k == 'action_date': | |||
|
74 | v = strptime(v) | |||
|
75 | if k in ['user_id', 'repository_id']: | |||
|
76 | # nullable due to FK problems | |||
|
77 | v = None | |||
|
78 | setattr(ul, k, v) | |||
|
79 | Session().add(ul) | |||
|
80 | Session().commit() | |||
|
81 | ||||
|
82 | @request.addfinalizer | |||
|
83 | def cleanup(): | |||
|
84 | UserLog.query().delete() | |||
|
85 | Session().commit() | |||
|
86 | ||||
|
87 | def test_index(self): | |||
|
88 | self.log_user() | |||
|
89 | response = self.app.get(route_path('admin_audit_logs')) | |||
|
90 | response.mustcontain('Admin audit logs') | |||
|
91 | ||||
|
92 | def test_filter_all_entries(self): | |||
|
93 | self.log_user() | |||
|
94 | response = self.app.get(route_path('admin_audit_logs')) | |||
|
95 | all_count = UserLog.query().count() | |||
|
96 | response.mustcontain('%s entries' % all_count) | |||
|
97 | ||||
|
98 | def test_filter_journal_filter_exact_match_on_repository(self): | |||
|
99 | self.log_user() | |||
|
100 | response = self.app.get(route_path('admin_audit_logs', | |||
|
101 | params=dict(filter='repository:rhodecode'))) | |||
|
102 | response.mustcontain('3 entries') | |||
|
103 | ||||
|
104 | def test_filter_journal_filter_exact_match_on_repository_CamelCase(self): | |||
|
105 | self.log_user() | |||
|
106 | response = self.app.get(route_path('admin_audit_logs', | |||
|
107 | params=dict(filter='repository:RhodeCode'))) | |||
|
108 | response.mustcontain('3 entries') | |||
|
109 | ||||
|
110 | def test_filter_journal_filter_wildcard_on_repository(self): | |||
|
111 | self.log_user() | |||
|
112 | response = self.app.get(route_path('admin_audit_logs', | |||
|
113 | params=dict(filter='repository:*test*'))) | |||
|
114 | response.mustcontain('862 entries') | |||
|
115 | ||||
|
116 | def test_filter_journal_filter_prefix_on_repository(self): | |||
|
117 | self.log_user() | |||
|
118 | response = self.app.get(route_path('admin_audit_logs', | |||
|
119 | params=dict(filter='repository:test*'))) | |||
|
120 | response.mustcontain('257 entries') | |||
|
121 | ||||
|
122 | def test_filter_journal_filter_prefix_on_repository_CamelCase(self): | |||
|
123 | self.log_user() | |||
|
124 | response = self.app.get(route_path('admin_audit_logs', | |||
|
125 | params=dict(filter='repository:Test*'))) | |||
|
126 | response.mustcontain('257 entries') | |||
|
127 | ||||
|
128 | def test_filter_journal_filter_prefix_on_repository_and_user(self): | |||
|
129 | self.log_user() | |||
|
130 | response = self.app.get(route_path('admin_audit_logs', | |||
|
131 | params=dict(filter='repository:test* AND username:demo'))) | |||
|
132 | response.mustcontain('130 entries') | |||
|
133 | ||||
|
134 | def test_filter_journal_filter_prefix_on_repository_or_target_repo(self): | |||
|
135 | self.log_user() | |||
|
136 | response = self.app.get(route_path('admin_audit_logs', | |||
|
137 | params=dict(filter='repository:test* OR repository:rhodecode'))) | |||
|
138 | response.mustcontain('260 entries') # 257 + 3 | |||
|
139 | ||||
|
140 | def test_filter_journal_filter_exact_match_on_username(self): | |||
|
141 | self.log_user() | |||
|
142 | response = self.app.get(route_path('admin_audit_logs', | |||
|
143 | params=dict(filter='username:demo'))) | |||
|
144 | response.mustcontain('1087 entries') | |||
|
145 | ||||
|
146 | def test_filter_journal_filter_exact_match_on_username_camelCase(self): | |||
|
147 | self.log_user() | |||
|
148 | response = self.app.get(route_path('admin_audit_logs', | |||
|
149 | params=dict(filter='username:DemO'))) | |||
|
150 | response.mustcontain('1087 entries') | |||
|
151 | ||||
|
152 | def test_filter_journal_filter_wildcard_on_username(self): | |||
|
153 | self.log_user() | |||
|
154 | response = self.app.get(route_path('admin_audit_logs', | |||
|
155 | params=dict(filter='username:*test*'))) | |||
|
156 | entries_count = UserLog.query().filter(UserLog.username.ilike('%test%')).count() | |||
|
157 | response.mustcontain('{} entries'.format(entries_count)) | |||
|
158 | ||||
|
159 | def test_filter_journal_filter_prefix_on_username(self): | |||
|
160 | self.log_user() | |||
|
161 | response = self.app.get(route_path('admin_audit_logs', | |||
|
162 | params=dict(filter='username:demo*'))) | |||
|
163 | response.mustcontain('1101 entries') | |||
|
164 | ||||
|
165 | def test_filter_journal_filter_prefix_on_user_or_other_user(self): | |||
|
166 | self.log_user() | |||
|
167 | response = self.app.get(route_path('admin_audit_logs', | |||
|
168 | params=dict(filter='username:demo OR username:volcan'))) | |||
|
169 | response.mustcontain('1095 entries') # 1087 + 8 | |||
|
170 | ||||
|
171 | def test_filter_journal_filter_wildcard_on_action(self): | |||
|
172 | self.log_user() | |||
|
173 | response = self.app.get(route_path('admin_audit_logs', | |||
|
174 | params=dict(filter='action:*pull_request*'))) | |||
|
175 | response.mustcontain('187 entries') | |||
|
176 | ||||
|
177 | def test_filter_journal_filter_on_date(self): | |||
|
178 | self.log_user() | |||
|
179 | response = self.app.get(route_path('admin_audit_logs', | |||
|
180 | params=dict(filter='date:20121010'))) | |||
|
181 | response.mustcontain('47 entries') | |||
|
182 | ||||
|
183 | def test_filter_journal_filter_on_date_2(self): | |||
|
184 | self.log_user() | |||
|
185 | response = self.app.get(route_path('admin_audit_logs', | |||
|
186 | params=dict(filter='date:20121020'))) | |||
|
187 | response.mustcontain('17 entries') |
@@ -0,0 +1,82 b'' | |||||
|
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 | import pytest | |||
|
22 | ||||
|
23 | from rhodecode.tests import TestController | |||
|
24 | from rhodecode.tests.fixture import Fixture | |||
|
25 | ||||
|
26 | fixture = Fixture() | |||
|
27 | ||||
|
28 | ||||
|
29 | def route_path(name, params=None, **kwargs): | |||
|
30 | import urllib | |||
|
31 | from rhodecode.apps._base import ADMIN_PREFIX | |||
|
32 | ||||
|
33 | base_url = { | |||
|
34 | 'admin_home': ADMIN_PREFIX, | |||
|
35 | 'pullrequest_show': '/{repo_name}/pull-request/{pull_request_id}', | |||
|
36 | 'pull_requests_global': ADMIN_PREFIX + '/pull-request/{pull_request_id}', | |||
|
37 | 'pull_requests_global_0': ADMIN_PREFIX + '/pull_requests/{pull_request_id}', | |||
|
38 | 'pull_requests_global_1': ADMIN_PREFIX + '/pull-requests/{pull_request_id}', | |||
|
39 | ||||
|
40 | }[name].format(**kwargs) | |||
|
41 | ||||
|
42 | if params: | |||
|
43 | base_url = '{}?{}'.format(base_url, urllib.urlencode(params)) | |||
|
44 | return base_url | |||
|
45 | ||||
|
46 | ||||
|
47 | class TestAdminMainView(TestController): | |||
|
48 | ||||
|
49 | def test_redirect_admin_home(self): | |||
|
50 | self.log_user() | |||
|
51 | response = self.app.get(route_path('admin_home'), status=302) | |||
|
52 | assert response.location.endswith('/audit_logs') | |||
|
53 | ||||
|
54 | def test_redirect_pull_request_view(self, view): | |||
|
55 | self.log_user() | |||
|
56 | self.app.get( | |||
|
57 | route_path(view, pull_request_id='xxxx'), | |||
|
58 | status=404) | |||
|
59 | ||||
|
60 | @pytest.mark.backends("git", "hg") | |||
|
61 | @pytest.mark.parametrize('view', [ | |||
|
62 | 'pull_requests_global', | |||
|
63 | 'pull_requests_global_0', | |||
|
64 | 'pull_requests_global_1', | |||
|
65 | ]) | |||
|
66 | def test_redirect_pull_request_view(self, view, pr_util): | |||
|
67 | self.log_user() | |||
|
68 | pull_request = pr_util.create_pull_request() | |||
|
69 | pull_request_id = pull_request.pull_request_id | |||
|
70 | ||||
|
71 | response = self.app.get( | |||
|
72 | route_path(view, pull_request_id=pull_request_id), | |||
|
73 | status=302) | |||
|
74 | assert response.location.endswith( | |||
|
75 | 'pull-request/{}'.format(pull_request_id)) | |||
|
76 | ||||
|
77 | repo_name = pull_request.target_repo.repo_name | |||
|
78 | redirect_url = route_path( | |||
|
79 | 'pullrequest_show', repo_name=repo_name, | |||
|
80 | pull_request_id=pull_request.pull_request_id) | |||
|
81 | ||||
|
82 | assert redirect_url in response.location |
@@ -0,0 +1,73 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | # Copyright (C) 2016-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 | import logging | |||
|
22 | ||||
|
23 | from pyramid.view import view_config | |||
|
24 | from sqlalchemy.orm import joinedload | |||
|
25 | ||||
|
26 | from rhodecode.apps._base import BaseAppView | |||
|
27 | from rhodecode.model.db import UserLog | |||
|
28 | from rhodecode.lib.user_log_filter import user_log_filter | |||
|
29 | from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator | |||
|
30 | from rhodecode.lib.utils2 import safe_int | |||
|
31 | from rhodecode.lib.helpers import Page | |||
|
32 | ||||
|
33 | log = logging.getLogger(__name__) | |||
|
34 | ||||
|
35 | ||||
|
36 | class AdminAuditLogsView(BaseAppView): | |||
|
37 | def load_default_context(self): | |||
|
38 | c = self._get_local_tmpl_context() | |||
|
39 | self._register_global_c(c) | |||
|
40 | return c | |||
|
41 | ||||
|
42 | @LoginRequired() | |||
|
43 | @HasPermissionAllDecorator('hg.admin') | |||
|
44 | @view_config( | |||
|
45 | route_name='admin_audit_logs', request_method='GET', | |||
|
46 | renderer='rhodecode:templates/admin/admin_audit_logs.mako') | |||
|
47 | def admin_audit_logs(self): | |||
|
48 | c = self.load_default_context() | |||
|
49 | ||||
|
50 | users_log = UserLog.query()\ | |||
|
51 | .options(joinedload(UserLog.user))\ | |||
|
52 | .options(joinedload(UserLog.repository)) | |||
|
53 | ||||
|
54 | # FILTERING | |||
|
55 | c.search_term = self.request.GET.get('filter') | |||
|
56 | try: | |||
|
57 | users_log = user_log_filter(users_log, c.search_term) | |||
|
58 | except Exception: | |||
|
59 | # we want this to crash for now | |||
|
60 | raise | |||
|
61 | ||||
|
62 | users_log = users_log.order_by(UserLog.action_date.desc()) | |||
|
63 | ||||
|
64 | p = safe_int(self.request.GET.get('page', 1), 1) | |||
|
65 | ||||
|
66 | def url_generator(**kw): | |||
|
67 | if c.search_term: | |||
|
68 | kw['filter'] = c.search_term | |||
|
69 | return self.request.current_route_path(_query=kw) | |||
|
70 | ||||
|
71 | c.audit_logs = Page(users_log, page=p, items_per_page=10, | |||
|
72 | url=url_generator) | |||
|
73 | return self._get_template_context(c) |
@@ -0,0 +1,63 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | # Copyright (C) 2016-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 | import logging | |||
|
22 | ||||
|
23 | ||||
|
24 | from pyramid.httpexceptions import HTTPFound | |||
|
25 | from pyramid.view import view_config | |||
|
26 | ||||
|
27 | from rhodecode.apps._base import BaseAppView | |||
|
28 | from rhodecode.lib import helpers as h | |||
|
29 | from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator) | |||
|
30 | from rhodecode.model.db import PullRequest | |||
|
31 | ||||
|
32 | ||||
|
33 | log = logging.getLogger(__name__) | |||
|
34 | ||||
|
35 | ||||
|
36 | class AdminMainView(BaseAppView): | |||
|
37 | ||||
|
38 | @LoginRequired() | |||
|
39 | @HasPermissionAllDecorator('hg.admin') | |||
|
40 | @view_config( | |||
|
41 | route_name='admin_home', request_method='GET') | |||
|
42 | def admin_main(self): | |||
|
43 | # redirect _admin to audit logs... | |||
|
44 | raise HTTPFound(h.route_path('admin_audit_logs')) | |||
|
45 | ||||
|
46 | @LoginRequired() | |||
|
47 | @view_config(route_name='pull_requests_global_0', request_method='GET') | |||
|
48 | @view_config(route_name='pull_requests_global_1', request_method='GET') | |||
|
49 | @view_config(route_name='pull_requests_global', request_method='GET') | |||
|
50 | def pull_requests(self): | |||
|
51 | """ | |||
|
52 | Global redirect for Pull Requests | |||
|
53 | ||||
|
54 | :param pull_request_id: id of pull requests in the system | |||
|
55 | """ | |||
|
56 | ||||
|
57 | pull_request_id = self.request.matchdict.get('pull_request_id') | |||
|
58 | pull_request = PullRequest.get_or_404(pull_request_id, pyramid_exc=True) | |||
|
59 | repo_name = pull_request.target_repo.repo_name | |||
|
60 | ||||
|
61 | raise HTTPFound( | |||
|
62 | h.route_path('pullrequest_show', repo_name=repo_name, | |||
|
63 | pull_request_id=pull_request_id)) |
@@ -30,6 +30,20 b' def admin_routes(config):' | |||||
30 | """ |
|
30 | """ | |
31 |
|
31 | |||
32 | config.add_route( |
|
32 | config.add_route( | |
|
33 | name='admin_audit_logs', | |||
|
34 | pattern='/audit_logs') | |||
|
35 | ||||
|
36 | config.add_route( | |||
|
37 | name='pull_requests_global_0', # backward compat | |||
|
38 | pattern='/pull_requests/{pull_request_id:[0-9]+}') | |||
|
39 | config.add_route( | |||
|
40 | name='pull_requests_global_1', # backward compat | |||
|
41 | pattern='/pull-requests/{pull_request_id:[0-9]+}') | |||
|
42 | config.add_route( | |||
|
43 | name='pull_requests_global', | |||
|
44 | pattern='/pull-request/{pull_request_id:[0-9]+}') | |||
|
45 | ||||
|
46 | config.add_route( | |||
33 | name='admin_settings_open_source', |
|
47 | name='admin_settings_open_source', | |
34 | pattern='/settings/open_source') |
|
48 | pattern='/settings/open_source') | |
35 | config.add_route( |
|
49 | config.add_route( | |
@@ -93,6 +107,8 b' def includeme(config):' | |||||
93 | navigation_registry = NavigationRegistry(labs_active=labs_active) |
|
107 | navigation_registry = NavigationRegistry(labs_active=labs_active) | |
94 | config.registry.registerUtility(navigation_registry) |
|
108 | config.registry.registerUtility(navigation_registry) | |
95 |
|
109 | |||
|
110 | # main admin routes | |||
|
111 | config.add_route(name='admin_home', pattern=ADMIN_PREFIX) | |||
96 | config.include(admin_routes, route_prefix=ADMIN_PREFIX) |
|
112 | config.include(admin_routes, route_prefix=ADMIN_PREFIX) | |
97 |
|
113 | |||
98 | # Scan module for configuration decorators. |
|
114 | # Scan module for configuration decorators. |
@@ -41,6 +41,12 b' def includeme(config):' | |||||
41 | name='bookmarks_home', |
|
41 | name='bookmarks_home', | |
42 | pattern='/{repo_name:.*?[^/]}/bookmarks', repo_route=True) |
|
42 | pattern='/{repo_name:.*?[^/]}/bookmarks', repo_route=True) | |
43 |
|
43 | |||
|
44 | # Pull Requests | |||
|
45 | config.add_route( | |||
|
46 | name='pullrequest_show', | |||
|
47 | pattern='/{repo_name:.*?[^/]}/pull-request/{pull_request_id}', | |||
|
48 | repo_route=True) | |||
|
49 | ||||
44 | # Settings |
|
50 | # Settings | |
45 | config.add_route( |
|
51 | config.add_route( | |
46 | name='edit_repo', |
|
52 | name='edit_repo', |
@@ -561,22 +561,6 b' def make_map(config):' | |||||
561 | action='show', conditions={'method': ['GET']}, |
|
561 | action='show', conditions={'method': ['GET']}, | |
562 | requirements=URL_NAME_REQUIREMENTS) |
|
562 | requirements=URL_NAME_REQUIREMENTS) | |
563 |
|
563 | |||
564 | # ADMIN MAIN PAGES |
|
|||
565 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
|||
566 | controller='admin/admin') as m: |
|
|||
567 | m.connect('admin_home', '', action='index') |
|
|||
568 | m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}', |
|
|||
569 | action='add_repo') |
|
|||
570 | m.connect( |
|
|||
571 | 'pull_requests_global_0', '/pull_requests/{pull_request_id:[0-9]+}', |
|
|||
572 | action='pull_requests') |
|
|||
573 | m.connect( |
|
|||
574 | 'pull_requests_global_1', '/pull-requests/{pull_request_id:[0-9]+}', |
|
|||
575 | action='pull_requests') |
|
|||
576 | m.connect( |
|
|||
577 | 'pull_requests_global', '/pull-request/{pull_request_id:[0-9]+}', |
|
|||
578 | action='pull_requests') |
|
|||
579 |
|
||||
580 | # USER JOURNAL |
|
564 | # USER JOURNAL | |
581 | rmap.connect('journal', '%s/journal' % (ADMIN_PREFIX,), |
|
565 | rmap.connect('journal', '%s/journal' % (ADMIN_PREFIX,), | |
582 | controller='journal', action='index') |
|
566 | controller='journal', action='index') |
@@ -34,11 +34,11 b' from webob.exc import HTTPBadRequest' | |||||
34 | from pylons import request, tmpl_context as c, response, url |
|
34 | from pylons import request, tmpl_context as c, response, url | |
35 | from pylons.i18n.translation import _ |
|
35 | from pylons.i18n.translation import _ | |
36 |
|
36 | |||
37 | from rhodecode.controllers.admin.admin import user_log_filter |
|
|||
38 | from rhodecode.model.db import UserLog, UserFollowing, User, UserApiKeys |
|
37 | from rhodecode.model.db import UserLog, UserFollowing, User, UserApiKeys | |
39 | from rhodecode.model.meta import Session |
|
38 | from rhodecode.model.meta import Session | |
40 | import rhodecode.lib.helpers as h |
|
39 | import rhodecode.lib.helpers as h | |
41 | from rhodecode.lib.helpers import Page |
|
40 | from rhodecode.lib.helpers import Page | |
|
41 | from rhodecode.lib.user_log_filter import user_log_filter | |||
42 | from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired |
|
42 | from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired | |
43 | from rhodecode.lib.base import BaseController, render |
|
43 | from rhodecode.lib.base import BaseController, render | |
44 | from rhodecode.lib.utils2 import safe_int, AttributeDict |
|
44 | from rhodecode.lib.utils2 import safe_int, AttributeDict |
@@ -69,6 +69,11 b' function registerRCRoutes() {' | |||||
69 | pyroutes.register('repo_integrations_create', '%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']); |
|
69 | pyroutes.register('repo_integrations_create', '%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']); | |
70 | pyroutes.register('repo_integrations_edit', '%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']); |
|
70 | pyroutes.register('repo_integrations_edit', '%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']); | |
71 | pyroutes.register('ops_ping', '_admin/ops/ping', []); |
|
71 | pyroutes.register('ops_ping', '_admin/ops/ping', []); | |
|
72 | pyroutes.register('admin_home', '/_admin', []); | |||
|
73 | pyroutes.register('admin_audit_logs', '_admin/audit_logs', []); | |||
|
74 | pyroutes.register('pull_requests_global_0', '_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']); | |||
|
75 | pyroutes.register('pull_requests_global_1', '_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']); | |||
|
76 | pyroutes.register('pull_requests_global', '_admin/pull-request/%(pull_request_id)s', ['pull_request_id']); | |||
72 | pyroutes.register('admin_settings_open_source', '_admin/settings/open_source', []); |
|
77 | pyroutes.register('admin_settings_open_source', '_admin/settings/open_source', []); | |
73 | pyroutes.register('admin_settings_vcs_svn_generate_cfg', '_admin/settings/vcs/svn_generate_cfg', []); |
|
78 | pyroutes.register('admin_settings_vcs_svn_generate_cfg', '_admin/settings/vcs/svn_generate_cfg', []); | |
74 | pyroutes.register('admin_settings_system', '_admin/settings/system', []); |
|
79 | pyroutes.register('admin_settings_system', '_admin/settings/system', []); | |
@@ -100,6 +105,7 b' function registerRCRoutes() {' | |||||
100 | pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']); |
|
105 | pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']); | |
101 | pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']); |
|
106 | pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']); | |
102 | pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']); |
|
107 | pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']); | |
|
108 | pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']); | |||
103 | pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']); |
|
109 | pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']); | |
104 | pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']); |
|
110 | pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']); | |
105 | pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']); |
|
111 | pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']); |
@@ -2,7 +2,7 b'' | |||||
2 | <%inherit file="/base/base.mako"/> |
|
2 | <%inherit file="/base/base.mako"/> | |
3 |
|
3 | |||
4 | <%def name="title()"> |
|
4 | <%def name="title()"> | |
5 |
${_('Admin |
|
5 | ${_('Admin audit logs')} | |
6 | %if c.rhodecode_name: |
|
6 | %if c.rhodecode_name: | |
7 | · ${h.branding(c.rhodecode_name)} |
|
7 | · ${h.branding(c.rhodecode_name)} | |
8 | %endif |
|
8 | %endif | |
@@ -10,9 +10,9 b'' | |||||
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 | ${h.form(None, id_="filter_form", method="get")} |
|
12 | ${h.form(None, id_="filter_form", method="get")} | |
13 |
<input class="q_filter_box ${'' if c.search_term else 'initial'}" id="j_filter" size="15" type="text" name="filter" value="${c.search_term or ''}" placeholder="${_(' |
|
13 | <input class="q_filter_box ${'' if c.search_term else 'initial'}" id="j_filter" size="15" type="text" name="filter" value="${c.search_term or ''}" placeholder="${_('filter...')}"/> | |
14 | <input type='submit' value="${_('filter')}" class="btn" /> |
|
14 | <input type='submit' value="${_('filter')}" class="btn" /> | |
15 |
${_('A |
|
15 | ${_('Audit logs')} - ${_ungettext('%s entry', '%s entries', c.audit_logs.item_count) % (c.audit_logs.item_count)} | |
16 | ${h.end_form()} |
|
16 | ${h.end_form()} | |
17 | <p class="tooltip filterexample" title="${h.tooltip(h.journal_filter_help())}">${_('Example Queries')}</p> |
|
17 | <p class="tooltip filterexample" title="${h.tooltip(h.journal_filter_help())}">${_('Example Queries')}</p> | |
18 | </%def> |
|
18 | </%def> | |
@@ -29,7 +29,7 b'' | |||||
29 | <!-- end box / title --> |
|
29 | <!-- end box / title --> | |
30 | <div class="table"> |
|
30 | <div class="table"> | |
31 | <div id="user_log"> |
|
31 | <div id="user_log"> | |
32 | ${c.log_data} |
|
32 | <%include file="/admin/admin_log_base.mako" /> | |
33 | </div> |
|
33 | </div> | |
34 | </div> |
|
34 | </div> | |
35 | </div> |
|
35 | </div> |
@@ -9,7 +9,7 b'' | |||||
9 | </%def> |
|
9 | </%def> | |
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 |
${h.link_to(_('Admin'),h. |
|
12 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
13 | » |
|
13 | » | |
14 | ${_('Authentication Plugins')} |
|
14 | ${_('Authentication Plugins')} | |
15 | </%def> |
|
15 | </%def> |
@@ -9,7 +9,7 b'' | |||||
9 | </%def> |
|
9 | </%def> | |
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 |
${h.link_to(_('Admin'),h. |
|
12 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
13 | » |
|
13 | » | |
14 | ${h.link_to(_('Authentication Plugins'),request.resource_path(resource.__parent__, route_name='auth_home'))} |
|
14 | ${h.link_to(_('Authentication Plugins'),request.resource_path(resource.__parent__, route_name='auth_home'))} | |
15 | » |
|
15 | » |
@@ -9,7 +9,7 b'' | |||||
9 | </%def> |
|
9 | </%def> | |
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 |
${h.link_to(_('Admin'),h. |
|
12 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
13 | » |
|
13 | » | |
14 | ${_('Repositories defaults')} |
|
14 | ${_('Repositories defaults')} | |
15 | </%def> |
|
15 | </%def> |
@@ -18,7 +18,7 b'' | |||||
18 | </%def> |
|
18 | </%def> | |
19 |
|
19 | |||
20 | <%def name="breadcrumbs_links()"> |
|
20 | <%def name="breadcrumbs_links()"> | |
21 |
${h.link_to(_('Admin'),h. |
|
21 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
22 | » |
|
22 | » | |
23 | ${_('Integrations')} |
|
23 | ${_('Integrations')} | |
24 | </%def> |
|
24 | </%def> |
@@ -12,7 +12,7 b'' | |||||
12 | repo_name=c.repo.repo_name, |
|
12 | repo_name=c.repo.repo_name, | |
13 | integration=current_IntegrationType.key))} |
|
13 | integration=current_IntegrationType.key))} | |
14 | %elif c.repo_group: |
|
14 | %elif c.repo_group: | |
15 |
${h.link_to(_('Admin'),h. |
|
15 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
16 | » |
|
16 | » | |
17 | ${h.link_to(_('Repository Groups'),h.url('repo_groups'))} |
|
17 | ${h.link_to(_('Repository Groups'),h.url('repo_groups'))} | |
18 | » |
|
18 | » | |
@@ -25,7 +25,7 b'' | |||||
25 | repo_group_name=c.repo_group.group_name, |
|
25 | repo_group_name=c.repo_group.group_name, | |
26 | integration=current_IntegrationType.key))} |
|
26 | integration=current_IntegrationType.key))} | |
27 | %else: |
|
27 | %else: | |
28 |
${h.link_to(_('Admin'),h. |
|
28 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
29 | » |
|
29 | » | |
30 | ${h.link_to(_('Settings'),h.url('admin_settings'))} |
|
30 | ${h.link_to(_('Settings'),h.url('admin_settings'))} | |
31 | » |
|
31 | » |
@@ -5,13 +5,13 b'' | |||||
5 | %if c.repo: |
|
5 | %if c.repo: | |
6 | ${h.link_to('Settings',h.route_path('edit_repo', repo_name=c.repo.repo_name))} |
|
6 | ${h.link_to('Settings',h.route_path('edit_repo', repo_name=c.repo.repo_name))} | |
7 | %elif c.repo_group: |
|
7 | %elif c.repo_group: | |
8 |
${h.link_to(_('Admin'),h. |
|
8 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
9 | » |
|
9 | » | |
10 | ${h.link_to(_('Repository Groups'),h.url('repo_groups'))} |
|
10 | ${h.link_to(_('Repository Groups'),h.url('repo_groups'))} | |
11 | » |
|
11 | » | |
12 | ${h.link_to(c.repo_group.group_name,h.url('edit_repo_group', group_name=c.repo_group.group_name))} |
|
12 | ${h.link_to(c.repo_group.group_name,h.url('edit_repo_group', group_name=c.repo_group.group_name))} | |
13 | %else: |
|
13 | %else: | |
14 |
${h.link_to(_('Admin'),h. |
|
14 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
15 | » |
|
15 | » | |
16 | ${h.link_to(_('Settings'),h.url('admin_settings'))} |
|
16 | ${h.link_to(_('Settings'),h.url('admin_settings'))} | |
17 | %endif |
|
17 | %endif |
@@ -8,7 +8,7 b'' | |||||
8 | » |
|
8 | » | |
9 | ${h.link_to(_('Integrations'),request.route_url(route_name='repo_integrations_home', repo_name=c.repo.repo_name))} |
|
9 | ${h.link_to(_('Integrations'),request.route_url(route_name='repo_integrations_home', repo_name=c.repo.repo_name))} | |
10 | %elif c.repo_group: |
|
10 | %elif c.repo_group: | |
11 |
${h.link_to(_('Admin'),h. |
|
11 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
12 | » |
|
12 | » | |
13 | ${h.link_to(_('Repository Groups'),h.url('repo_groups'))} |
|
13 | ${h.link_to(_('Repository Groups'),h.url('repo_groups'))} | |
14 | » |
|
14 | » | |
@@ -16,7 +16,7 b'' | |||||
16 | » |
|
16 | » | |
17 | ${h.link_to(_('Integrations'),request.route_url(route_name='repo_group_integrations_home', repo_group_name=c.repo_group.group_name))} |
|
17 | ${h.link_to(_('Integrations'),request.route_url(route_name='repo_group_integrations_home', repo_group_name=c.repo_group.group_name))} | |
18 | %else: |
|
18 | %else: | |
19 |
${h.link_to(_('Admin'),h. |
|
19 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
20 | » |
|
20 | » | |
21 | ${h.link_to(_('Settings'),h.url('admin_settings'))} |
|
21 | ${h.link_to(_('Settings'),h.url('admin_settings'))} | |
22 | » |
|
22 | » |
@@ -9,7 +9,7 b'' | |||||
9 | </%def> |
|
9 | </%def> | |
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 |
${h.link_to(_('Admin'),h. |
|
12 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
13 | » |
|
13 | » | |
14 | ${_('Permissions')} |
|
14 | ${_('Permissions')} | |
15 | </%def> |
|
15 | </%def> |
@@ -9,7 +9,7 b'' | |||||
9 | </%def> |
|
9 | </%def> | |
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 |
${h.link_to(_('Admin'),h. |
|
12 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
13 | » |
|
13 | » | |
14 | ${h.link_to(_('Repository groups'),h.url('repo_groups'))} |
|
14 | ${h.link_to(_('Repository groups'),h.url('repo_groups'))} | |
15 | » |
|
15 | » |
@@ -9,7 +9,7 b'' | |||||
9 | </%def> |
|
9 | </%def> | |
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 |
${h.link_to(_('Admin'),h. |
|
12 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
13 | » |
|
13 | » | |
14 | ${h.link_to(_('Repository Groups'),h.url('repo_groups'))} |
|
14 | ${h.link_to(_('Repository Groups'),h.url('repo_groups'))} | |
15 | %if c.repo_group.parent_group: |
|
15 | %if c.repo_group.parent_group: |
@@ -10,7 +10,7 b'' | |||||
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 | <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/> |
|
12 | <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/> | |
13 |
${h.link_to(_('Admin'),h. |
|
13 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} » <span id="repo_group_count">0</span> ${_('repository groups')} | |
14 | </%def> |
|
14 | </%def> | |
15 |
|
15 | |||
16 | <%def name="menu_bar_nav()"> |
|
16 | <%def name="menu_bar_nav()"> |
@@ -10,7 +10,7 b'' | |||||
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 | %if c.rhodecode_user.is_admin: |
|
12 | %if c.rhodecode_user.is_admin: | |
13 |
${h.link_to(_('Admin'),h. |
|
13 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
14 | » |
|
14 | » | |
15 | ${h.link_to(_('Repositories'),h.url('repos'))} |
|
15 | ${h.link_to(_('Repositories'),h.url('repos'))} | |
16 | %else: |
|
16 | %else: |
@@ -10,7 +10,7 b'' | |||||
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 | <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/> |
|
12 | <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/> | |
13 |
${h.link_to(_('Admin'),h. |
|
13 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} » <span id="repo_count">0</span> ${_('repositories')} | |
14 | </%def> |
|
14 | </%def> | |
15 |
|
15 | |||
16 | <%def name="menu_bar_nav()"> |
|
16 | <%def name="menu_bar_nav()"> |
@@ -9,7 +9,7 b'' | |||||
9 | </%def> |
|
9 | </%def> | |
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 |
${h.link_to(_('Admin'),h. |
|
12 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
13 | » |
|
13 | » | |
14 | ${_('Settings')} |
|
14 | ${_('Settings')} | |
15 | </%def> |
|
15 | </%def> |
@@ -8,7 +8,7 b'' | |||||
8 | %endif |
|
8 | %endif | |
9 | </%def> |
|
9 | </%def> | |
10 | <%def name="breadcrumbs_links()"> |
|
10 | <%def name="breadcrumbs_links()"> | |
11 |
${h.link_to(_('Admin'),h. |
|
11 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
12 | » |
|
12 | » | |
13 | ${h.link_to(_('User groups'),h.url('users_groups'))} |
|
13 | ${h.link_to(_('User groups'),h.url('users_groups'))} | |
14 | » |
|
14 | » |
@@ -9,7 +9,7 b'' | |||||
9 | </%def> |
|
9 | </%def> | |
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 |
${h.link_to(_('Admin'),h. |
|
12 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
13 | » |
|
13 | » | |
14 | ${h.link_to(_('User Groups'),h.url('users_groups'))} |
|
14 | ${h.link_to(_('User Groups'),h.url('users_groups'))} | |
15 | » |
|
15 | » |
@@ -10,7 +10,7 b'' | |||||
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 | <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/> |
|
12 | <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/> | |
13 |
${h.link_to(_('Admin'),h. |
|
13 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} » <span id="user_group_count">0</span> ${_('user groups')} | |
14 | </%def> |
|
14 | </%def> | |
15 |
|
15 | |||
16 | <%def name="menu_bar_nav()"> |
|
16 | <%def name="menu_bar_nav()"> |
@@ -8,7 +8,7 b'' | |||||
8 | %endif |
|
8 | %endif | |
9 | </%def> |
|
9 | </%def> | |
10 | <%def name="breadcrumbs_links()"> |
|
10 | <%def name="breadcrumbs_links()"> | |
11 |
${h.link_to(_('Admin'),h. |
|
11 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
12 | » |
|
12 | » | |
13 | ${h.link_to(_('Users'),h.route_path('users'))} |
|
13 | ${h.link_to(_('Users'),h.route_path('users'))} | |
14 | » |
|
14 | » |
@@ -9,7 +9,7 b'' | |||||
9 | </%def> |
|
9 | </%def> | |
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 |
${h.link_to(_('Admin'),h. |
|
12 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} | |
13 | » |
|
13 | » | |
14 | ${h.link_to(_('Users'),h.route_path('users'))} |
|
14 | ${h.link_to(_('Users'),h.route_path('users'))} | |
15 | » |
|
15 | » |
@@ -10,7 +10,7 b'' | |||||
10 |
|
10 | |||
11 | <%def name="breadcrumbs_links()"> |
|
11 | <%def name="breadcrumbs_links()"> | |
12 | <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/> |
|
12 | <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/> | |
13 |
${h.link_to(_('Admin'),h. |
|
13 | ${h.link_to(_('Admin'),h.route_path('admin_home'))} » <span id="user_count">0</span> | |
14 | </%def> |
|
14 | </%def> | |
15 |
|
15 | |||
16 | <%def name="menu_bar_nav()"> |
|
16 | <%def name="menu_bar_nav()"> |
@@ -72,7 +72,7 b'' | |||||
72 |
|
72 | |||
73 | <%def name="admin_menu()"> |
|
73 | <%def name="admin_menu()"> | |
74 | <ul class="admin_menu submenu"> |
|
74 | <ul class="admin_menu submenu"> | |
75 |
<li><a href="${h. |
|
75 | <li><a href="${h.route_path('admin_audit_logs')}">${_('Admin audit logs')}</a></li> | |
76 | <li><a href="${h.url('repos')}">${_('Repositories')}</a></li> |
|
76 | <li><a href="${h.url('repos')}">${_('Repositories')}</a></li> | |
77 | <li><a href="${h.url('repo_groups')}">${_('Repository groups')}</a></li> |
|
77 | <li><a href="${h.url('repo_groups')}">${_('Repository groups')}</a></li> | |
78 | <li><a href="${h.route_path('users')}">${_('Users')}</a></li> |
|
78 | <li><a href="${h.route_path('users')}">${_('Users')}</a></li> |
@@ -53,19 +53,6 b' class TestPullrequestsController:' | |||||
53 | 'pullrequest', repo_name=repo_name) |
|
53 | 'pullrequest', repo_name=repo_name) | |
54 | response.mustcontain(create_pr_link) |
|
54 | response.mustcontain(create_pr_link) | |
55 |
|
55 | |||
56 | def test_global_redirect_of_pr(self, backend, pr_util): |
|
|||
57 | pull_request = pr_util.create_pull_request() |
|
|||
58 |
|
||||
59 | response = self.app.get( |
|
|||
60 | url('pull_requests_global', |
|
|||
61 | pull_request_id=pull_request.pull_request_id)) |
|
|||
62 |
|
||||
63 | repo_name = pull_request.target_repo.repo_name |
|
|||
64 | redirect_url = url('pullrequest_show', repo_name=repo_name, |
|
|||
65 | pull_request_id=pull_request.pull_request_id) |
|
|||
66 | assert response.status == '302 Found' |
|
|||
67 | assert redirect_url in response.location |
|
|||
68 |
|
||||
69 | def test_create_pr_form_with_raw_commit_id(self, backend): |
|
56 | def test_create_pr_form_with_raw_commit_id(self, backend): | |
70 | repo = backend.repo |
|
57 | repo = backend.repo | |
71 |
|
58 |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now