Show More
@@ -0,0 +1,150 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.lib.utils2 import safe_unicode, safe_str | |||
|
24 | from rhodecode.model.db import Repository | |||
|
25 | from rhodecode.model.repo import RepoModel | |||
|
26 | from rhodecode.tests import ( | |||
|
27 | HG_REPO, GIT_REPO, assert_session_flash, no_newline_id_generator) | |||
|
28 | from rhodecode.tests.fixture import Fixture | |||
|
29 | from rhodecode.tests.utils import repo_on_filesystem | |||
|
30 | ||||
|
31 | fixture = Fixture() | |||
|
32 | ||||
|
33 | ||||
|
34 | def route_path(name, params=None, **kwargs): | |||
|
35 | import urllib | |||
|
36 | ||||
|
37 | base_url = { | |||
|
38 | 'repo_summary_explicit': '/{repo_name}/summary', | |||
|
39 | 'repo_summary': '/{repo_name}', | |||
|
40 | 'edit_repo_advanced': '/{repo_name}/settings/advanced', | |||
|
41 | 'edit_repo_advanced_delete': '/{repo_name}/settings/advanced/delete', | |||
|
42 | 'edit_repo_advanced_fork': '/{repo_name}/settings/advanced/fork', | |||
|
43 | 'edit_repo_advanced_locking': '/{repo_name}/settings/advanced/locking', | |||
|
44 | 'edit_repo_advanced_journal': '/{repo_name}/settings/advanced/journal', | |||
|
45 | ||||
|
46 | }[name].format(**kwargs) | |||
|
47 | ||||
|
48 | if params: | |||
|
49 | base_url = '{}?{}'.format(base_url, urllib.urlencode(params)) | |||
|
50 | return base_url | |||
|
51 | ||||
|
52 | ||||
|
53 | @pytest.mark.usefixtures('autologin_user', 'app') | |||
|
54 | class TestAdminRepoSettingsAdvanced(object): | |||
|
55 | ||||
|
56 | def test_set_repo_fork_has_no_self_id(self, autologin_user, backend): | |||
|
57 | repo = backend.repo | |||
|
58 | response = self.app.get( | |||
|
59 | route_path('edit_repo_advanced', repo_name=backend.repo_name)) | |||
|
60 | opt = """<option value="%s">vcs_test_git</option>""" % repo.repo_id | |||
|
61 | response.mustcontain(no=[opt]) | |||
|
62 | ||||
|
63 | def test_set_fork_of_target_repo( | |||
|
64 | self, autologin_user, backend, csrf_token): | |||
|
65 | target_repo = 'target_%s' % backend.alias | |||
|
66 | fixture.create_repo(target_repo, repo_type=backend.alias) | |||
|
67 | repo2 = Repository.get_by_repo_name(target_repo) | |||
|
68 | response = self.app.post( | |||
|
69 | route_path('edit_repo_advanced_fork', repo_name=backend.repo_name), | |||
|
70 | params={'id_fork_of': repo2.repo_id, | |||
|
71 | 'csrf_token': csrf_token}) | |||
|
72 | repo = Repository.get_by_repo_name(backend.repo_name) | |||
|
73 | repo2 = Repository.get_by_repo_name(target_repo) | |||
|
74 | assert_session_flash( | |||
|
75 | response, | |||
|
76 | 'Marked repo %s as fork of %s' % (repo.repo_name, repo2.repo_name)) | |||
|
77 | ||||
|
78 | assert repo.fork == repo2 | |||
|
79 | response = response.follow() | |||
|
80 | # check if given repo is selected | |||
|
81 | ||||
|
82 | opt = 'This repository is a fork of <a href="%s">%s</a>' % ( | |||
|
83 | route_path('repo_summary', repo_name=repo2.repo_name), | |||
|
84 | repo2.repo_name) | |||
|
85 | ||||
|
86 | response.mustcontain(opt) | |||
|
87 | ||||
|
88 | fixture.destroy_repo(target_repo, forks='detach') | |||
|
89 | ||||
|
90 | @pytest.mark.backends("hg", "git") | |||
|
91 | def test_set_fork_of_other_type_repo( | |||
|
92 | self, autologin_user, backend, csrf_token): | |||
|
93 | TARGET_REPO_MAP = { | |||
|
94 | 'git': { | |||
|
95 | 'type': 'hg', | |||
|
96 | 'repo_name': HG_REPO}, | |||
|
97 | 'hg': { | |||
|
98 | 'type': 'git', | |||
|
99 | 'repo_name': GIT_REPO}, | |||
|
100 | } | |||
|
101 | target_repo = TARGET_REPO_MAP[backend.alias] | |||
|
102 | ||||
|
103 | repo2 = Repository.get_by_repo_name(target_repo['repo_name']) | |||
|
104 | response = self.app.post( | |||
|
105 | route_path('edit_repo_advanced_fork', repo_name=backend.repo_name), | |||
|
106 | params={'id_fork_of': repo2.repo_id, | |||
|
107 | 'csrf_token': csrf_token}) | |||
|
108 | assert_session_flash( | |||
|
109 | response, | |||
|
110 | 'Cannot set repository as fork of repository with other type') | |||
|
111 | ||||
|
112 | def test_set_fork_of_none(self, autologin_user, backend, csrf_token): | |||
|
113 | # mark it as None | |||
|
114 | response = self.app.post( | |||
|
115 | route_path('edit_repo_advanced_fork', repo_name=backend.repo_name), | |||
|
116 | params={'id_fork_of': None, '_method': 'put', | |||
|
117 | 'csrf_token': csrf_token}) | |||
|
118 | assert_session_flash( | |||
|
119 | response, | |||
|
120 | 'Marked repo %s as fork of %s' | |||
|
121 | % (backend.repo_name, "Nothing")) | |||
|
122 | assert backend.repo.fork is None | |||
|
123 | ||||
|
124 | def test_set_fork_of_same_repo(self, autologin_user, backend, csrf_token): | |||
|
125 | repo = Repository.get_by_repo_name(backend.repo_name) | |||
|
126 | response = self.app.post( | |||
|
127 | route_path('edit_repo_advanced_fork', repo_name=backend.repo_name), | |||
|
128 | params={'id_fork_of': repo.repo_id, 'csrf_token': csrf_token}) | |||
|
129 | assert_session_flash( | |||
|
130 | response, 'An error occurred during this operation') | |||
|
131 | ||||
|
132 | @pytest.mark.parametrize( | |||
|
133 | "suffix", | |||
|
134 | ['', u'Δ ΔΕ' , '123'], | |||
|
135 | ids=no_newline_id_generator) | |||
|
136 | def test_advanced_delete(self, autologin_user, backend, suffix, csrf_token): | |||
|
137 | repo = backend.create_repo(name_suffix=suffix) | |||
|
138 | repo_name = repo.repo_name | |||
|
139 | repo_name_str = safe_str(repo.repo_name) | |||
|
140 | ||||
|
141 | response = self.app.post( | |||
|
142 | route_path('edit_repo_advanced_delete', repo_name=repo_name_str), | |||
|
143 | params={'csrf_token': csrf_token}) | |||
|
144 | assert_session_flash(response, | |||
|
145 | u'Deleted repository `{}`'.format(repo_name)) | |||
|
146 | response.follow() | |||
|
147 | ||||
|
148 | # check if repo was deleted from db | |||
|
149 | assert RepoModel().get_by_repo_name(repo_name) is None | |||
|
150 | assert not repo_on_filesystem(repo_name_str) |
@@ -0,0 +1,225 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | # Copyright (C) 2011-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 pyramid.httpexceptions import HTTPFound | |||
|
25 | ||||
|
26 | from rhodecode.apps._base import RepoAppView | |||
|
27 | from rhodecode.lib import helpers as h | |||
|
28 | from rhodecode.lib import audit_logger | |||
|
29 | from rhodecode.lib.auth import ( | |||
|
30 | LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired) | |||
|
31 | from rhodecode.lib.exceptions import AttachedForksError | |||
|
32 | from rhodecode.lib.utils2 import safe_int | |||
|
33 | from rhodecode.lib.vcs import RepositoryError | |||
|
34 | from rhodecode.model.db import Session, UserFollowing, User, Repository | |||
|
35 | from rhodecode.model.repo import RepoModel | |||
|
36 | from rhodecode.model.scm import ScmModel | |||
|
37 | ||||
|
38 | log = logging.getLogger(__name__) | |||
|
39 | ||||
|
40 | ||||
|
41 | class RepoSettingsView(RepoAppView): | |||
|
42 | ||||
|
43 | def load_default_context(self): | |||
|
44 | c = self._get_local_tmpl_context() | |||
|
45 | ||||
|
46 | # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead | |||
|
47 | c.repo_info = self.db_repo | |||
|
48 | ||||
|
49 | self._register_global_c(c) | |||
|
50 | return c | |||
|
51 | ||||
|
52 | @LoginRequired() | |||
|
53 | @HasRepoPermissionAnyDecorator('repository.admin') | |||
|
54 | @view_config( | |||
|
55 | route_name='edit_repo_advanced', request_method='GET', | |||
|
56 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') | |||
|
57 | def edit_advanced(self): | |||
|
58 | c = self.load_default_context() | |||
|
59 | c.active = 'advanced' | |||
|
60 | ||||
|
61 | c.default_user_id = User.get_default_user().user_id | |||
|
62 | c.in_public_journal = UserFollowing.query() \ | |||
|
63 | .filter(UserFollowing.user_id == c.default_user_id) \ | |||
|
64 | .filter(UserFollowing.follows_repository == c.repo_info).scalar() | |||
|
65 | ||||
|
66 | c.has_origin_repo_read_perm = False | |||
|
67 | if self.db_repo.fork: | |||
|
68 | c.has_origin_repo_read_perm = h.HasRepoPermissionAny( | |||
|
69 | 'repository.write', 'repository.read', 'repository.admin')( | |||
|
70 | self.db_repo.fork.repo_name, 'repo set as fork page') | |||
|
71 | ||||
|
72 | return self._get_template_context(c) | |||
|
73 | ||||
|
74 | @LoginRequired() | |||
|
75 | @HasRepoPermissionAnyDecorator('repository.admin') | |||
|
76 | @view_config( | |||
|
77 | route_name='edit_repo_advanced_delete', request_method='POST', | |||
|
78 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') | |||
|
79 | def edit_advanced_delete(self): | |||
|
80 | """ | |||
|
81 | Deletes the repository, or shows warnings if deletion is not possible | |||
|
82 | because of attached forks or other errors. | |||
|
83 | """ | |||
|
84 | _ = self.request.translate | |||
|
85 | handle_forks = self.request.POST.get('forks', None) | |||
|
86 | ||||
|
87 | try: | |||
|
88 | _forks = self.db_repo.forks.count() | |||
|
89 | if _forks and handle_forks: | |||
|
90 | if handle_forks == 'detach_forks': | |||
|
91 | handle_forks = 'detach' | |||
|
92 | h.flash(_('Detached %s forks') % _forks, category='success') | |||
|
93 | elif handle_forks == 'delete_forks': | |||
|
94 | handle_forks = 'delete' | |||
|
95 | h.flash(_('Deleted %s forks') % _forks, category='success') | |||
|
96 | ||||
|
97 | repo_data = self.db_repo.get_api_data() | |||
|
98 | RepoModel().delete(self.db_repo, forks=handle_forks) | |||
|
99 | ||||
|
100 | repo = audit_logger.RepoWrap(repo_id=self.db_repo.repo_id, | |||
|
101 | repo_name=self.db_repo.repo_name) | |||
|
102 | audit_logger.store( | |||
|
103 | action='repo.delete', action_data={'repo_data': repo_data}, | |||
|
104 | user=self._rhodecode_user, repo=repo, commit=False) | |||
|
105 | ||||
|
106 | ScmModel().mark_for_invalidation(self.db_repo_name) | |||
|
107 | h.flash( | |||
|
108 | _('Deleted repository `%s`') % self.db_repo_name, | |||
|
109 | category='success') | |||
|
110 | Session().commit() | |||
|
111 | except AttachedForksError: | |||
|
112 | repo_advanced_url = h.route_path( | |||
|
113 | 'edit_repo_advanced', repo_name=self.db_repo_name, | |||
|
114 | _anchor='advanced-delete') | |||
|
115 | delete_anchor = h.link_to(_('detach or delete'), repo_advanced_url) | |||
|
116 | h.flash(_('Cannot delete `{repo}` it still contains attached forks. ' | |||
|
117 | 'Try using {delete_or_detach} option.') | |||
|
118 | .format(repo=self.db_repo_name, delete_or_detach=delete_anchor), | |||
|
119 | category='warning') | |||
|
120 | ||||
|
121 | # redirect to advanced for forks handle action ? | |||
|
122 | raise HTTPFound(repo_advanced_url) | |||
|
123 | ||||
|
124 | except Exception: | |||
|
125 | log.exception("Exception during deletion of repository") | |||
|
126 | h.flash(_('An error occurred during deletion of `%s`') | |||
|
127 | % self.db_repo_name, category='error') | |||
|
128 | # redirect to advanced for more deletion options | |||
|
129 | raise HTTPFound( | |||
|
130 | h.route_path('edit_repo_advanced', repo_name=self.db_repo_name), | |||
|
131 | _anchor='advanced-delete') | |||
|
132 | ||||
|
133 | raise HTTPFound(h.route_path('home')) | |||
|
134 | ||||
|
135 | @LoginRequired() | |||
|
136 | @HasRepoPermissionAnyDecorator('repository.admin') | |||
|
137 | @CSRFRequired() | |||
|
138 | @view_config( | |||
|
139 | route_name='edit_repo_advanced_journal', request_method='POST', | |||
|
140 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') | |||
|
141 | def edit_advanced_journal(self): | |||
|
142 | """ | |||
|
143 | Set's this repository to be visible in public journal, | |||
|
144 | in other words making default user to follow this repo | |||
|
145 | """ | |||
|
146 | _ = self.request.translate | |||
|
147 | ||||
|
148 | try: | |||
|
149 | user_id = User.get_default_user().user_id | |||
|
150 | ScmModel().toggle_following_repo(self.db_repo.repo_id, user_id) | |||
|
151 | h.flash(_('Updated repository visibility in public journal'), | |||
|
152 | category='success') | |||
|
153 | Session().commit() | |||
|
154 | except Exception: | |||
|
155 | h.flash(_('An error occurred during setting this ' | |||
|
156 | 'repository in public journal'), | |||
|
157 | category='error') | |||
|
158 | ||||
|
159 | raise HTTPFound( | |||
|
160 | h.route_path('edit_repo_advanced', repo_name=self.db_repo_name)) | |||
|
161 | ||||
|
162 | @LoginRequired() | |||
|
163 | @HasRepoPermissionAnyDecorator('repository.admin') | |||
|
164 | @CSRFRequired() | |||
|
165 | @view_config( | |||
|
166 | route_name='edit_repo_advanced_fork', request_method='POST', | |||
|
167 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') | |||
|
168 | def edit_advanced_fork(self): | |||
|
169 | """ | |||
|
170 | Mark given repository as a fork of another | |||
|
171 | """ | |||
|
172 | _ = self.request.translate | |||
|
173 | ||||
|
174 | new_fork_id = self.request.POST.get('id_fork_of') | |||
|
175 | try: | |||
|
176 | ||||
|
177 | if new_fork_id and not new_fork_id.isdigit(): | |||
|
178 | log.error('Given fork id %s is not an INT', new_fork_id) | |||
|
179 | ||||
|
180 | fork_id = safe_int(new_fork_id) | |||
|
181 | repo = ScmModel().mark_as_fork( | |||
|
182 | self.db_repo_name, fork_id, self._rhodecode_user.user_id) | |||
|
183 | fork = repo.fork.repo_name if repo.fork else _('Nothing') | |||
|
184 | Session().commit() | |||
|
185 | h.flash(_('Marked repo %s as fork of %s') % (self.db_repo_name, fork), | |||
|
186 | category='success') | |||
|
187 | except RepositoryError as e: | |||
|
188 | log.exception("Repository Error occurred") | |||
|
189 | h.flash(str(e), category='error') | |||
|
190 | except Exception as e: | |||
|
191 | log.exception("Exception while editing fork") | |||
|
192 | h.flash(_('An error occurred during this operation'), | |||
|
193 | category='error') | |||
|
194 | ||||
|
195 | raise HTTPFound( | |||
|
196 | h.route_path('edit_repo_advanced', repo_name=self.db_repo_name)) | |||
|
197 | ||||
|
198 | @LoginRequired() | |||
|
199 | @HasRepoPermissionAnyDecorator('repository.admin') | |||
|
200 | @CSRFRequired() | |||
|
201 | @view_config( | |||
|
202 | route_name='edit_repo_advanced_locking', request_method='POST', | |||
|
203 | renderer='rhodecode:templates/admin/repos/repo_edit.mako') | |||
|
204 | def edit_advanced_locking(self): | |||
|
205 | """ | |||
|
206 | Toggle locking of repository | |||
|
207 | """ | |||
|
208 | _ = self.request.translate | |||
|
209 | set_lock = self.request.POST.get('set_lock') | |||
|
210 | set_unlock = self.request.POST.get('set_unlock') | |||
|
211 | ||||
|
212 | try: | |||
|
213 | if set_lock: | |||
|
214 | Repository.lock(self.db_repo, self._rhodecode_user.user_id, | |||
|
215 | lock_reason=Repository.LOCK_WEB) | |||
|
216 | h.flash(_('Locked repository'), category='success') | |||
|
217 | elif set_unlock: | |||
|
218 | Repository.unlock(self.db_repo) | |||
|
219 | h.flash(_('Unlocked repository'), category='success') | |||
|
220 | except Exception as e: | |||
|
221 | log.exception("Exception during unlocking") | |||
|
222 | h.flash(_('An error occurred during unlocking'), category='error') | |||
|
223 | ||||
|
224 | raise HTTPFound( | |||
|
225 | h.route_path('edit_repo_advanced', repo_name=self.db_repo_name)) |
@@ -1,81 +1,109 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 | def includeme(config): |
|
22 | def includeme(config): | |
23 |
|
23 | |||
|
24 | # Summary | |||
|
25 | config.add_route( | |||
|
26 | name='repo_summary_explicit', | |||
|
27 | pattern='/{repo_name:.*?[^/]}/summary', repo_route=True) | |||
|
28 | ||||
24 | # Tags |
|
29 | # Tags | |
25 | config.add_route( |
|
30 | config.add_route( | |
26 | name='tags_home', |
|
31 | name='tags_home', | |
27 | pattern='/{repo_name:.*?[^/]}/tags', repo_route=True) |
|
32 | pattern='/{repo_name:.*?[^/]}/tags', repo_route=True) | |
28 |
|
33 | |||
29 | # Branches |
|
34 | # Branches | |
30 | config.add_route( |
|
35 | config.add_route( | |
31 | name='branches_home', |
|
36 | name='branches_home', | |
32 | pattern='/{repo_name:.*?[^/]}/branches', repo_route=True) |
|
37 | pattern='/{repo_name:.*?[^/]}/branches', repo_route=True) | |
33 |
|
38 | |||
34 | # Bookmarks |
|
39 | # Bookmarks | |
35 | config.add_route( |
|
40 | config.add_route( | |
36 | name='bookmarks_home', |
|
41 | name='bookmarks_home', | |
37 | pattern='/{repo_name:.*?[^/]}/bookmarks', repo_route=True) |
|
42 | pattern='/{repo_name:.*?[^/]}/bookmarks', repo_route=True) | |
38 |
|
43 | |||
39 | # Settings |
|
44 | # Settings | |
40 | config.add_route( |
|
45 | config.add_route( | |
41 | name='edit_repo', |
|
46 | name='edit_repo', | |
42 | pattern='/{repo_name:.*?[^/]}/settings', repo_route=True) |
|
47 | pattern='/{repo_name:.*?[^/]}/settings', repo_route=True) | |
43 |
|
48 | |||
|
49 | # Settings advanced | |||
|
50 | config.add_route( | |||
|
51 | name='edit_repo_advanced', | |||
|
52 | pattern='/{repo_name:.*?[^/]}/settings/advanced', repo_route=True) | |||
|
53 | config.add_route( | |||
|
54 | name='edit_repo_advanced_delete', | |||
|
55 | pattern='/{repo_name:.*?[^/]}/settings/advanced/delete', repo_route=True) | |||
|
56 | config.add_route( | |||
|
57 | name='edit_repo_advanced_locking', | |||
|
58 | pattern='/{repo_name:.*?[^/]}/settings/advanced/locking', repo_route=True) | |||
|
59 | config.add_route( | |||
|
60 | name='edit_repo_advanced_journal', | |||
|
61 | pattern='/{repo_name:.*?[^/]}/settings/advanced/journal', repo_route=True) | |||
|
62 | config.add_route( | |||
|
63 | name='edit_repo_advanced_fork', | |||
|
64 | pattern='/{repo_name:.*?[^/]}/settings/advanced/fork', repo_route=True) | |||
|
65 | ||||
44 | # Caches |
|
66 | # Caches | |
45 | config.add_route( |
|
67 | config.add_route( | |
46 | name='edit_repo_caches', |
|
68 | name='edit_repo_caches', | |
47 | pattern='/{repo_name:.*?[^/]}/settings/caches', repo_route=True) |
|
69 | pattern='/{repo_name:.*?[^/]}/settings/caches', repo_route=True) | |
48 |
|
70 | |||
49 | # Permissions |
|
71 | # Permissions | |
50 | config.add_route( |
|
72 | config.add_route( | |
51 | name='edit_repo_perms', |
|
73 | name='edit_repo_perms', | |
52 | pattern='/{repo_name:.*?[^/]}/settings/permissions', repo_route=True) |
|
74 | pattern='/{repo_name:.*?[^/]}/settings/permissions', repo_route=True) | |
53 |
|
75 | |||
54 | # Repo Review Rules |
|
76 | # Repo Review Rules | |
55 | config.add_route( |
|
77 | config.add_route( | |
56 | name='repo_reviewers', |
|
78 | name='repo_reviewers', | |
57 | pattern='/{repo_name:.*?[^/]}/settings/review/rules', repo_route=True) |
|
79 | pattern='/{repo_name:.*?[^/]}/settings/review/rules', repo_route=True) | |
58 |
|
80 | |||
59 | # Maintenance |
|
81 | # Maintenance | |
60 | config.add_route( |
|
82 | config.add_route( | |
61 | name='repo_maintenance', |
|
83 | name='repo_maintenance', | |
62 | pattern='/{repo_name:.*?[^/]}/settings/maintenance', repo_route=True) |
|
84 | pattern='/{repo_name:.*?[^/]}/settings/maintenance', repo_route=True) | |
63 |
|
85 | |||
64 | config.add_route( |
|
86 | config.add_route( | |
65 | name='repo_maintenance_execute', |
|
87 | name='repo_maintenance_execute', | |
66 | pattern='/{repo_name:.*?[^/]}/settings/maintenance/execute', repo_route=True) |
|
88 | pattern='/{repo_name:.*?[^/]}/settings/maintenance/execute', repo_route=True) | |
67 |
|
89 | |||
68 | # Strip |
|
90 | # Strip | |
69 | config.add_route( |
|
91 | config.add_route( | |
70 | name='strip', |
|
92 | name='strip', | |
71 | pattern='/{repo_name:.*?[^/]}/settings/strip', repo_route=True) |
|
93 | pattern='/{repo_name:.*?[^/]}/settings/strip', repo_route=True) | |
72 |
|
94 | |||
73 | config.add_route( |
|
95 | config.add_route( | |
74 | name='strip_check', |
|
96 | name='strip_check', | |
75 | pattern='/{repo_name:.*?[^/]}/settings/strip_check', repo_route=True) |
|
97 | pattern='/{repo_name:.*?[^/]}/settings/strip_check', repo_route=True) | |
76 |
|
98 | |||
77 | config.add_route( |
|
99 | config.add_route( | |
78 | name='strip_execute', |
|
100 | name='strip_execute', | |
79 | pattern='/{repo_name:.*?[^/]}/settings/strip_execute', repo_route=True) |
|
101 | pattern='/{repo_name:.*?[^/]}/settings/strip_execute', repo_route=True) | |
|
102 | ||||
|
103 | # NOTE(marcink): needs to be at the end for catch-all | |||
|
104 | # config.add_route( | |||
|
105 | # name='repo_summary', | |||
|
106 | # pattern='/{repo_name:.*?[^/]}', repo_route=True) | |||
|
107 | ||||
80 | # Scan module for configuration decorators. |
|
108 | # Scan module for configuration decorators. | |
81 | config.scan() |
|
109 | config.scan() |
@@ -1,232 +1,233 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 |
|
2 | |||
3 | # Copyright (C) 2010-2017 RhodeCode GmbH |
|
3 | # Copyright (C) 2010-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 mock |
|
21 | import mock | |
22 | import pytest |
|
22 | import pytest | |
23 |
|
23 | |||
24 | from rhodecode.lib.utils2 import str2bool |
|
24 | from rhodecode.lib.utils2 import str2bool | |
25 | from rhodecode.lib.vcs.exceptions import RepositoryRequirementError |
|
25 | from rhodecode.lib.vcs.exceptions import RepositoryRequirementError | |
26 | from rhodecode.model.db import Repository, UserRepoToPerm, Permission, User |
|
26 | from rhodecode.model.db import Repository, UserRepoToPerm, Permission, User | |
27 | from rhodecode.model.meta import Session |
|
27 | from rhodecode.model.meta import Session | |
28 | from rhodecode.tests import ( |
|
28 | from rhodecode.tests import ( | |
29 | url, HG_REPO, TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN, |
|
29 | url, HG_REPO, TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN, | |
30 | assert_session_flash) |
|
30 | assert_session_flash) | |
31 | from rhodecode.tests.fixture import Fixture |
|
31 | from rhodecode.tests.fixture import Fixture | |
32 |
|
32 | |||
33 | fixture = Fixture() |
|
33 | fixture = Fixture() | |
34 |
|
34 | |||
35 |
|
35 | |||
36 | def route_path(name, params=None, **kwargs): |
|
36 | def route_path(name, params=None, **kwargs): | |
37 | import urllib |
|
37 | import urllib | |
38 |
|
38 | |||
39 | base_url = { |
|
39 | base_url = { | |
40 | 'edit_repo': '/{repo_name}/settings', |
|
40 | 'edit_repo': '/{repo_name}/settings', | |
|
41 | 'edit_repo_advanced': '/{repo_name}/settings/advanced', | |||
41 | 'edit_repo_caches': '/{repo_name}/settings/caches', |
|
42 | 'edit_repo_caches': '/{repo_name}/settings/caches', | |
42 | 'edit_repo_perms': '/{repo_name}/settings/permissions', |
|
43 | 'edit_repo_perms': '/{repo_name}/settings/permissions', | |
43 | }[name].format(**kwargs) |
|
44 | }[name].format(**kwargs) | |
44 |
|
45 | |||
45 | if params: |
|
46 | if params: | |
46 | base_url = '{}?{}'.format(base_url, urllib.urlencode(params)) |
|
47 | base_url = '{}?{}'.format(base_url, urllib.urlencode(params)) | |
47 | return base_url |
|
48 | return base_url | |
48 |
|
49 | |||
49 |
|
50 | |||
50 | def _get_permission_for_user(user, repo): |
|
51 | def _get_permission_for_user(user, repo): | |
51 | perm = UserRepoToPerm.query()\ |
|
52 | perm = UserRepoToPerm.query()\ | |
52 | .filter(UserRepoToPerm.repository == |
|
53 | .filter(UserRepoToPerm.repository == | |
53 | Repository.get_by_repo_name(repo))\ |
|
54 | Repository.get_by_repo_name(repo))\ | |
54 | .filter(UserRepoToPerm.user == User.get_by_username(user))\ |
|
55 | .filter(UserRepoToPerm.user == User.get_by_username(user))\ | |
55 | .all() |
|
56 | .all() | |
56 | return perm |
|
57 | return perm | |
57 |
|
58 | |||
58 |
|
59 | |||
59 | @pytest.mark.usefixtures('autologin_user', 'app') |
|
60 | @pytest.mark.usefixtures('autologin_user', 'app') | |
60 | class TestAdminRepoSettings(object): |
|
61 | class TestAdminRepoSettings(object): | |
61 | @pytest.mark.parametrize('urlname', [ |
|
62 | @pytest.mark.parametrize('urlname', [ | |
62 | 'edit_repo', |
|
63 | 'edit_repo', | |
63 | 'edit_repo_caches', |
|
64 | 'edit_repo_caches', | |
64 | 'edit_repo_perms', |
|
65 | 'edit_repo_perms', | |
|
66 | 'edit_repo_advanced', | |||
65 | ]) |
|
67 | ]) | |
66 | def test_show_page(self, urlname, app, backend): |
|
68 | def test_show_page(self, urlname, app, backend): | |
67 | app.get(route_path(urlname, repo_name=backend.repo_name), status=200) |
|
69 | app.get(route_path(urlname, repo_name=backend.repo_name), status=200) | |
68 |
|
70 | |||
69 | def test_edit_accessible_when_missing_requirements( |
|
71 | def test_edit_accessible_when_missing_requirements( | |
70 | self, backend_hg, autologin_user): |
|
72 | self, backend_hg, autologin_user): | |
71 | scm_patcher = mock.patch.object( |
|
73 | scm_patcher = mock.patch.object( | |
72 | Repository, 'scm_instance', side_effect=RepositoryRequirementError) |
|
74 | Repository, 'scm_instance', side_effect=RepositoryRequirementError) | |
73 | with scm_patcher: |
|
75 | with scm_patcher: | |
74 | self.app.get(route_path('edit_repo', repo_name=backend_hg.repo_name)) |
|
76 | self.app.get(route_path('edit_repo', repo_name=backend_hg.repo_name)) | |
75 |
|
77 | |||
76 | @pytest.mark.parametrize('urlname', [ |
|
78 | @pytest.mark.parametrize('urlname', [ | |
77 | 'edit_repo_advanced', |
|
|||
78 | 'repo_vcs_settings', |
|
79 | 'repo_vcs_settings', | |
|
80 | 'repo_settings_issuetracker', | |||
79 | 'edit_repo_fields', |
|
81 | 'edit_repo_fields', | |
80 | 'repo_settings_issuetracker', |
|
|||
81 | 'edit_repo_remote', |
|
82 | 'edit_repo_remote', | |
82 | 'edit_repo_statistics', |
|
83 | 'edit_repo_statistics', | |
83 | ]) |
|
84 | ]) | |
84 | def test_show_page_pylons(self, urlname, app): |
|
85 | def test_show_page_pylons(self, urlname, app): | |
85 | app.get(url(urlname, repo_name=HG_REPO)) |
|
86 | app.get(url(urlname, repo_name=HG_REPO)) | |
86 |
|
87 | |||
87 | @pytest.mark.parametrize('update_settings', [ |
|
88 | @pytest.mark.parametrize('update_settings', [ | |
88 | {'repo_description': 'alter-desc'}, |
|
89 | {'repo_description': 'alter-desc'}, | |
89 | {'repo_owner': TEST_USER_REGULAR_LOGIN}, |
|
90 | {'repo_owner': TEST_USER_REGULAR_LOGIN}, | |
90 | {'repo_private': 'true'}, |
|
91 | {'repo_private': 'true'}, | |
91 | {'repo_enable_locking': 'true'}, |
|
92 | {'repo_enable_locking': 'true'}, | |
92 | {'repo_enable_downloads': 'true'}, |
|
93 | {'repo_enable_downloads': 'true'}, | |
93 | ]) |
|
94 | ]) | |
94 | def test_update_repo_settings(self, update_settings, csrf_token, backend, user_util): |
|
95 | def test_update_repo_settings(self, update_settings, csrf_token, backend, user_util): | |
95 | repo = user_util.create_repo(repo_type=backend.alias) |
|
96 | repo = user_util.create_repo(repo_type=backend.alias) | |
96 | repo_name = repo.repo_name |
|
97 | repo_name = repo.repo_name | |
97 |
|
98 | |||
98 | params = fixture._get_repo_create_params( |
|
99 | params = fixture._get_repo_create_params( | |
99 | csrf_token=csrf_token, |
|
100 | csrf_token=csrf_token, | |
100 | repo_name=repo_name, |
|
101 | repo_name=repo_name, | |
101 | repo_type=backend.alias, |
|
102 | repo_type=backend.alias, | |
102 | repo_owner=TEST_USER_ADMIN_LOGIN, |
|
103 | repo_owner=TEST_USER_ADMIN_LOGIN, | |
103 | repo_description='DESC', |
|
104 | repo_description='DESC', | |
104 |
|
105 | |||
105 | repo_private='false', |
|
106 | repo_private='false', | |
106 | repo_enable_locking='false', |
|
107 | repo_enable_locking='false', | |
107 | repo_enable_downloads='false') |
|
108 | repo_enable_downloads='false') | |
108 | params.update(update_settings) |
|
109 | params.update(update_settings) | |
109 | self.app.post( |
|
110 | self.app.post( | |
110 | route_path('edit_repo', repo_name=repo_name), |
|
111 | route_path('edit_repo', repo_name=repo_name), | |
111 | params=params, status=302) |
|
112 | params=params, status=302) | |
112 |
|
113 | |||
113 | repo = Repository.get_by_repo_name(repo_name) |
|
114 | repo = Repository.get_by_repo_name(repo_name) | |
114 | assert repo.user.username == \ |
|
115 | assert repo.user.username == \ | |
115 | update_settings.get('repo_owner', repo.user.username) |
|
116 | update_settings.get('repo_owner', repo.user.username) | |
116 |
|
117 | |||
117 | assert repo.description == \ |
|
118 | assert repo.description == \ | |
118 | update_settings.get('repo_description', repo.description) |
|
119 | update_settings.get('repo_description', repo.description) | |
119 |
|
120 | |||
120 | assert repo.private == \ |
|
121 | assert repo.private == \ | |
121 | str2bool(update_settings.get( |
|
122 | str2bool(update_settings.get( | |
122 | 'repo_private', repo.private)) |
|
123 | 'repo_private', repo.private)) | |
123 |
|
124 | |||
124 | assert repo.enable_locking == \ |
|
125 | assert repo.enable_locking == \ | |
125 | str2bool(update_settings.get( |
|
126 | str2bool(update_settings.get( | |
126 | 'repo_enable_locking', repo.enable_locking)) |
|
127 | 'repo_enable_locking', repo.enable_locking)) | |
127 |
|
128 | |||
128 | assert repo.enable_downloads == \ |
|
129 | assert repo.enable_downloads == \ | |
129 | str2bool(update_settings.get( |
|
130 | str2bool(update_settings.get( | |
130 | 'repo_enable_downloads', repo.enable_downloads)) |
|
131 | 'repo_enable_downloads', repo.enable_downloads)) | |
131 |
|
132 | |||
132 | def test_update_repo_name_via_settings(self, csrf_token, user_util, backend): |
|
133 | def test_update_repo_name_via_settings(self, csrf_token, user_util, backend): | |
133 | repo = user_util.create_repo(repo_type=backend.alias) |
|
134 | repo = user_util.create_repo(repo_type=backend.alias) | |
134 | repo_name = repo.repo_name |
|
135 | repo_name = repo.repo_name | |
135 |
|
136 | |||
136 | repo_group = user_util.create_repo_group() |
|
137 | repo_group = user_util.create_repo_group() | |
137 | repo_group_name = repo_group.group_name |
|
138 | repo_group_name = repo_group.group_name | |
138 | new_name = repo_group_name + '_' + repo_name |
|
139 | new_name = repo_group_name + '_' + repo_name | |
139 |
|
140 | |||
140 | params = fixture._get_repo_create_params( |
|
141 | params = fixture._get_repo_create_params( | |
141 | csrf_token=csrf_token, |
|
142 | csrf_token=csrf_token, | |
142 | repo_name=new_name, |
|
143 | repo_name=new_name, | |
143 | repo_type=backend.alias, |
|
144 | repo_type=backend.alias, | |
144 | repo_owner=TEST_USER_ADMIN_LOGIN, |
|
145 | repo_owner=TEST_USER_ADMIN_LOGIN, | |
145 | repo_description='DESC', |
|
146 | repo_description='DESC', | |
146 | repo_private='false', |
|
147 | repo_private='false', | |
147 | repo_enable_locking='false', |
|
148 | repo_enable_locking='false', | |
148 | repo_enable_downloads='false') |
|
149 | repo_enable_downloads='false') | |
149 | self.app.post( |
|
150 | self.app.post( | |
150 | route_path('edit_repo', repo_name=repo_name), |
|
151 | route_path('edit_repo', repo_name=repo_name), | |
151 | params=params, status=302) |
|
152 | params=params, status=302) | |
152 | repo = Repository.get_by_repo_name(new_name) |
|
153 | repo = Repository.get_by_repo_name(new_name) | |
153 | assert repo.repo_name == new_name |
|
154 | assert repo.repo_name == new_name | |
154 |
|
155 | |||
155 | def test_update_repo_group_via_settings(self, csrf_token, user_util, backend): |
|
156 | def test_update_repo_group_via_settings(self, csrf_token, user_util, backend): | |
156 | repo = user_util.create_repo(repo_type=backend.alias) |
|
157 | repo = user_util.create_repo(repo_type=backend.alias) | |
157 | repo_name = repo.repo_name |
|
158 | repo_name = repo.repo_name | |
158 |
|
159 | |||
159 | repo_group = user_util.create_repo_group() |
|
160 | repo_group = user_util.create_repo_group() | |
160 | repo_group_name = repo_group.group_name |
|
161 | repo_group_name = repo_group.group_name | |
161 | repo_group_id = repo_group.group_id |
|
162 | repo_group_id = repo_group.group_id | |
162 |
|
163 | |||
163 | new_name = repo_group_name + '/' + repo_name |
|
164 | new_name = repo_group_name + '/' + repo_name | |
164 | params = fixture._get_repo_create_params( |
|
165 | params = fixture._get_repo_create_params( | |
165 | csrf_token=csrf_token, |
|
166 | csrf_token=csrf_token, | |
166 | repo_name=repo_name, |
|
167 | repo_name=repo_name, | |
167 | repo_type=backend.alias, |
|
168 | repo_type=backend.alias, | |
168 | repo_owner=TEST_USER_ADMIN_LOGIN, |
|
169 | repo_owner=TEST_USER_ADMIN_LOGIN, | |
169 | repo_description='DESC', |
|
170 | repo_description='DESC', | |
170 | repo_group=repo_group_id, |
|
171 | repo_group=repo_group_id, | |
171 | repo_private='false', |
|
172 | repo_private='false', | |
172 | repo_enable_locking='false', |
|
173 | repo_enable_locking='false', | |
173 | repo_enable_downloads='false') |
|
174 | repo_enable_downloads='false') | |
174 | self.app.post( |
|
175 | self.app.post( | |
175 | route_path('edit_repo', repo_name=repo_name), |
|
176 | route_path('edit_repo', repo_name=repo_name), | |
176 | params=params, status=302) |
|
177 | params=params, status=302) | |
177 | repo = Repository.get_by_repo_name(new_name) |
|
178 | repo = Repository.get_by_repo_name(new_name) | |
178 | assert repo.repo_name == new_name |
|
179 | assert repo.repo_name == new_name | |
179 |
|
180 | |||
180 | def test_set_private_flag_sets_default_user_permissions_to_none( |
|
181 | def test_set_private_flag_sets_default_user_permissions_to_none( | |
181 | self, autologin_user, backend, csrf_token): |
|
182 | self, autologin_user, backend, csrf_token): | |
182 |
|
183 | |||
183 | # initially repository perm should be read |
|
184 | # initially repository perm should be read | |
184 | perm = _get_permission_for_user(user='default', repo=backend.repo_name) |
|
185 | perm = _get_permission_for_user(user='default', repo=backend.repo_name) | |
185 | assert len(perm) == 1 |
|
186 | assert len(perm) == 1 | |
186 | assert perm[0].permission.permission_name == 'repository.read' |
|
187 | assert perm[0].permission.permission_name == 'repository.read' | |
187 | assert not backend.repo.private |
|
188 | assert not backend.repo.private | |
188 |
|
189 | |||
189 | response = self.app.post( |
|
190 | response = self.app.post( | |
190 | route_path('edit_repo', repo_name=backend.repo_name), |
|
191 | route_path('edit_repo', repo_name=backend.repo_name), | |
191 | params=fixture._get_repo_create_params( |
|
192 | params=fixture._get_repo_create_params( | |
192 | repo_private='true', |
|
193 | repo_private='true', | |
193 | repo_name=backend.repo_name, |
|
194 | repo_name=backend.repo_name, | |
194 | repo_type=backend.alias, |
|
195 | repo_type=backend.alias, | |
195 | repo_owner=TEST_USER_ADMIN_LOGIN, |
|
196 | repo_owner=TEST_USER_ADMIN_LOGIN, | |
196 | csrf_token=csrf_token), status=302) |
|
197 | csrf_token=csrf_token), status=302) | |
197 |
|
198 | |||
198 | assert_session_flash( |
|
199 | assert_session_flash( | |
199 | response, |
|
200 | response, | |
200 | msg='Repository %s updated successfully' % (backend.repo_name)) |
|
201 | msg='Repository %s updated successfully' % (backend.repo_name)) | |
201 |
|
202 | |||
202 | repo = Repository.get_by_repo_name(backend.repo_name) |
|
203 | repo = Repository.get_by_repo_name(backend.repo_name) | |
203 | assert repo.private is True |
|
204 | assert repo.private is True | |
204 |
|
205 | |||
205 | # now the repo default permission should be None |
|
206 | # now the repo default permission should be None | |
206 | perm = _get_permission_for_user(user='default', repo=backend.repo_name) |
|
207 | perm = _get_permission_for_user(user='default', repo=backend.repo_name) | |
207 | assert len(perm) == 1 |
|
208 | assert len(perm) == 1 | |
208 | assert perm[0].permission.permission_name == 'repository.none' |
|
209 | assert perm[0].permission.permission_name == 'repository.none' | |
209 |
|
210 | |||
210 | response = self.app.post( |
|
211 | response = self.app.post( | |
211 | route_path('edit_repo', repo_name=backend.repo_name), |
|
212 | route_path('edit_repo', repo_name=backend.repo_name), | |
212 | params=fixture._get_repo_create_params( |
|
213 | params=fixture._get_repo_create_params( | |
213 | repo_private='false', |
|
214 | repo_private='false', | |
214 | repo_name=backend.repo_name, |
|
215 | repo_name=backend.repo_name, | |
215 | repo_type=backend.alias, |
|
216 | repo_type=backend.alias, | |
216 | repo_owner=TEST_USER_ADMIN_LOGIN, |
|
217 | repo_owner=TEST_USER_ADMIN_LOGIN, | |
217 | csrf_token=csrf_token), status=302) |
|
218 | csrf_token=csrf_token), status=302) | |
218 |
|
219 | |||
219 | assert_session_flash( |
|
220 | assert_session_flash( | |
220 | response, |
|
221 | response, | |
221 | msg='Repository %s updated successfully' % (backend.repo_name)) |
|
222 | msg='Repository %s updated successfully' % (backend.repo_name)) | |
222 | assert backend.repo.private is False |
|
223 | assert backend.repo.private is False | |
223 |
|
224 | |||
224 | # we turn off private now the repo default permission should stay None |
|
225 | # we turn off private now the repo default permission should stay None | |
225 | perm = _get_permission_for_user(user='default', repo=backend.repo_name) |
|
226 | perm = _get_permission_for_user(user='default', repo=backend.repo_name) | |
226 | assert len(perm) == 1 |
|
227 | assert len(perm) == 1 | |
227 | assert perm[0].permission.permission_name == 'repository.none' |
|
228 | assert perm[0].permission.permission_name == 'repository.none' | |
228 |
|
229 | |||
229 | # update this permission back |
|
230 | # update this permission back | |
230 | perm[0].permission = Permission.get_by_key('repository.read') |
|
231 | perm[0].permission = Permission.get_by_key('repository.read') | |
231 | Session().add(perm[0]) |
|
232 | Session().add(perm[0]) | |
232 | Session().commit() |
|
233 | Session().commit() |
@@ -1,1076 +1,1057 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 |
|
2 | |||
3 | # Copyright (C) 2010-2017 RhodeCode GmbH |
|
3 | # Copyright (C) 2010-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 | Routes configuration |
|
22 | Routes configuration | |
23 |
|
23 | |||
24 | The more specific and detailed routes should be defined first so they |
|
24 | The more specific and detailed routes should be defined first so they | |
25 | may take precedent over the more generic routes. For more information |
|
25 | may take precedent over the more generic routes. For more information | |
26 | refer to the routes manual at http://routes.groovie.org/docs/ |
|
26 | refer to the routes manual at http://routes.groovie.org/docs/ | |
27 |
|
27 | |||
28 | IMPORTANT: if you change any routing here, make sure to take a look at lib/base.py |
|
28 | IMPORTANT: if you change any routing here, make sure to take a look at lib/base.py | |
29 | and _route_name variable which uses some of stored naming here to do redirects. |
|
29 | and _route_name variable which uses some of stored naming here to do redirects. | |
30 | """ |
|
30 | """ | |
31 | import os |
|
31 | import os | |
32 | import re |
|
32 | import re | |
33 | from routes import Mapper |
|
33 | from routes import Mapper | |
34 |
|
34 | |||
35 | # prefix for non repository related links needs to be prefixed with `/` |
|
35 | # prefix for non repository related links needs to be prefixed with `/` | |
36 | ADMIN_PREFIX = '/_admin' |
|
36 | ADMIN_PREFIX = '/_admin' | |
37 | STATIC_FILE_PREFIX = '/_static' |
|
37 | STATIC_FILE_PREFIX = '/_static' | |
38 |
|
38 | |||
39 | # Default requirements for URL parts |
|
39 | # Default requirements for URL parts | |
40 | URL_NAME_REQUIREMENTS = { |
|
40 | URL_NAME_REQUIREMENTS = { | |
41 | # group name can have a slash in them, but they must not end with a slash |
|
41 | # group name can have a slash in them, but they must not end with a slash | |
42 | 'group_name': r'.*?[^/]', |
|
42 | 'group_name': r'.*?[^/]', | |
43 | 'repo_group_name': r'.*?[^/]', |
|
43 | 'repo_group_name': r'.*?[^/]', | |
44 | # repo names can have a slash in them, but they must not end with a slash |
|
44 | # repo names can have a slash in them, but they must not end with a slash | |
45 | 'repo_name': r'.*?[^/]', |
|
45 | 'repo_name': r'.*?[^/]', | |
46 | # file path eats up everything at the end |
|
46 | # file path eats up everything at the end | |
47 | 'f_path': r'.*', |
|
47 | 'f_path': r'.*', | |
48 | # reference types |
|
48 | # reference types | |
49 | 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)', |
|
49 | 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)', | |
50 | 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)', |
|
50 | 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)', | |
51 | } |
|
51 | } | |
52 |
|
52 | |||
53 |
|
53 | |||
54 | def add_route_requirements(route_path, requirements): |
|
54 | def add_route_requirements(route_path, requirements): | |
55 | """ |
|
55 | """ | |
56 | Adds regex requirements to pyramid routes using a mapping dict |
|
56 | Adds regex requirements to pyramid routes using a mapping dict | |
57 |
|
57 | |||
58 | >>> add_route_requirements('/{action}/{id}', {'id': r'\d+'}) |
|
58 | >>> add_route_requirements('/{action}/{id}', {'id': r'\d+'}) | |
59 | '/{action}/{id:\d+}' |
|
59 | '/{action}/{id:\d+}' | |
60 |
|
60 | |||
61 | """ |
|
61 | """ | |
62 | for key, regex in requirements.items(): |
|
62 | for key, regex in requirements.items(): | |
63 | route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex)) |
|
63 | route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex)) | |
64 | return route_path |
|
64 | return route_path | |
65 |
|
65 | |||
66 |
|
66 | |||
67 | class JSRoutesMapper(Mapper): |
|
67 | class JSRoutesMapper(Mapper): | |
68 | """ |
|
68 | """ | |
69 | Wrapper for routes.Mapper to make pyroutes compatible url definitions |
|
69 | Wrapper for routes.Mapper to make pyroutes compatible url definitions | |
70 | """ |
|
70 | """ | |
71 | _named_route_regex = re.compile(r'^[a-z-_0-9A-Z]+$') |
|
71 | _named_route_regex = re.compile(r'^[a-z-_0-9A-Z]+$') | |
72 | _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)') |
|
72 | _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)') | |
73 | def __init__(self, *args, **kw): |
|
73 | def __init__(self, *args, **kw): | |
74 | super(JSRoutesMapper, self).__init__(*args, **kw) |
|
74 | super(JSRoutesMapper, self).__init__(*args, **kw) | |
75 | self._jsroutes = [] |
|
75 | self._jsroutes = [] | |
76 |
|
76 | |||
77 | def connect(self, *args, **kw): |
|
77 | def connect(self, *args, **kw): | |
78 | """ |
|
78 | """ | |
79 | Wrapper for connect to take an extra argument jsroute=True |
|
79 | Wrapper for connect to take an extra argument jsroute=True | |
80 |
|
80 | |||
81 | :param jsroute: boolean, if True will add the route to the pyroutes list |
|
81 | :param jsroute: boolean, if True will add the route to the pyroutes list | |
82 | """ |
|
82 | """ | |
83 | if kw.pop('jsroute', False): |
|
83 | if kw.pop('jsroute', False): | |
84 | if not self._named_route_regex.match(args[0]): |
|
84 | if not self._named_route_regex.match(args[0]): | |
85 | raise Exception('only named routes can be added to pyroutes') |
|
85 | raise Exception('only named routes can be added to pyroutes') | |
86 | self._jsroutes.append(args[0]) |
|
86 | self._jsroutes.append(args[0]) | |
87 |
|
87 | |||
88 | super(JSRoutesMapper, self).connect(*args, **kw) |
|
88 | super(JSRoutesMapper, self).connect(*args, **kw) | |
89 |
|
89 | |||
90 | def _extract_route_information(self, route): |
|
90 | def _extract_route_information(self, route): | |
91 | """ |
|
91 | """ | |
92 | Convert a route into tuple(name, path, args), eg: |
|
92 | Convert a route into tuple(name, path, args), eg: | |
93 | ('show_user', '/profile/%(username)s', ['username']) |
|
93 | ('show_user', '/profile/%(username)s', ['username']) | |
94 | """ |
|
94 | """ | |
95 | routepath = route.routepath |
|
95 | routepath = route.routepath | |
96 | def replace(matchobj): |
|
96 | def replace(matchobj): | |
97 | if matchobj.group(1): |
|
97 | if matchobj.group(1): | |
98 | return "%%(%s)s" % matchobj.group(1).split(':')[0] |
|
98 | return "%%(%s)s" % matchobj.group(1).split(':')[0] | |
99 | else: |
|
99 | else: | |
100 | return "%%(%s)s" % matchobj.group(2) |
|
100 | return "%%(%s)s" % matchobj.group(2) | |
101 |
|
101 | |||
102 | routepath = self._argument_prog.sub(replace, routepath) |
|
102 | routepath = self._argument_prog.sub(replace, routepath) | |
103 | return ( |
|
103 | return ( | |
104 | route.name, |
|
104 | route.name, | |
105 | routepath, |
|
105 | routepath, | |
106 | [(arg[0].split(':')[0] if arg[0] != '' else arg[1]) |
|
106 | [(arg[0].split(':')[0] if arg[0] != '' else arg[1]) | |
107 | for arg in self._argument_prog.findall(route.routepath)] |
|
107 | for arg in self._argument_prog.findall(route.routepath)] | |
108 | ) |
|
108 | ) | |
109 |
|
109 | |||
110 | def jsroutes(self): |
|
110 | def jsroutes(self): | |
111 | """ |
|
111 | """ | |
112 | Return a list of pyroutes.js compatible routes |
|
112 | Return a list of pyroutes.js compatible routes | |
113 | """ |
|
113 | """ | |
114 | for route_name in self._jsroutes: |
|
114 | for route_name in self._jsroutes: | |
115 | yield self._extract_route_information(self._routenames[route_name]) |
|
115 | yield self._extract_route_information(self._routenames[route_name]) | |
116 |
|
116 | |||
117 |
|
117 | |||
118 | def make_map(config): |
|
118 | def make_map(config): | |
119 | """Create, configure and return the routes Mapper""" |
|
119 | """Create, configure and return the routes Mapper""" | |
120 | rmap = JSRoutesMapper(directory=config['pylons.paths']['controllers'], |
|
120 | rmap = JSRoutesMapper(directory=config['pylons.paths']['controllers'], | |
121 | always_scan=config['debug']) |
|
121 | always_scan=config['debug']) | |
122 | rmap.minimization = False |
|
122 | rmap.minimization = False | |
123 | rmap.explicit = False |
|
123 | rmap.explicit = False | |
124 |
|
124 | |||
125 | from rhodecode.lib.utils2 import str2bool |
|
125 | from rhodecode.lib.utils2 import str2bool | |
126 | from rhodecode.model import repo, repo_group |
|
126 | from rhodecode.model import repo, repo_group | |
127 |
|
127 | |||
128 | def check_repo(environ, match_dict): |
|
128 | def check_repo(environ, match_dict): | |
129 | """ |
|
129 | """ | |
130 | check for valid repository for proper 404 handling |
|
130 | check for valid repository for proper 404 handling | |
131 |
|
131 | |||
132 | :param environ: |
|
132 | :param environ: | |
133 | :param match_dict: |
|
133 | :param match_dict: | |
134 | """ |
|
134 | """ | |
135 | repo_name = match_dict.get('repo_name') |
|
135 | repo_name = match_dict.get('repo_name') | |
136 |
|
136 | |||
137 | if match_dict.get('f_path'): |
|
137 | if match_dict.get('f_path'): | |
138 | # fix for multiple initial slashes that causes errors |
|
138 | # fix for multiple initial slashes that causes errors | |
139 | match_dict['f_path'] = match_dict['f_path'].lstrip('/') |
|
139 | match_dict['f_path'] = match_dict['f_path'].lstrip('/') | |
140 | repo_model = repo.RepoModel() |
|
140 | repo_model = repo.RepoModel() | |
141 | by_name_match = repo_model.get_by_repo_name(repo_name) |
|
141 | by_name_match = repo_model.get_by_repo_name(repo_name) | |
142 | # if we match quickly from database, short circuit the operation, |
|
142 | # if we match quickly from database, short circuit the operation, | |
143 | # and validate repo based on the type. |
|
143 | # and validate repo based on the type. | |
144 | if by_name_match: |
|
144 | if by_name_match: | |
145 | return True |
|
145 | return True | |
146 |
|
146 | |||
147 | by_id_match = repo_model.get_repo_by_id(repo_name) |
|
147 | by_id_match = repo_model.get_repo_by_id(repo_name) | |
148 | if by_id_match: |
|
148 | if by_id_match: | |
149 | repo_name = by_id_match.repo_name |
|
149 | repo_name = by_id_match.repo_name | |
150 | match_dict['repo_name'] = repo_name |
|
150 | match_dict['repo_name'] = repo_name | |
151 | return True |
|
151 | return True | |
152 |
|
152 | |||
153 | return False |
|
153 | return False | |
154 |
|
154 | |||
155 | def check_group(environ, match_dict): |
|
155 | def check_group(environ, match_dict): | |
156 | """ |
|
156 | """ | |
157 | check for valid repository group path for proper 404 handling |
|
157 | check for valid repository group path for proper 404 handling | |
158 |
|
158 | |||
159 | :param environ: |
|
159 | :param environ: | |
160 | :param match_dict: |
|
160 | :param match_dict: | |
161 | """ |
|
161 | """ | |
162 | repo_group_name = match_dict.get('group_name') |
|
162 | repo_group_name = match_dict.get('group_name') | |
163 | repo_group_model = repo_group.RepoGroupModel() |
|
163 | repo_group_model = repo_group.RepoGroupModel() | |
164 | by_name_match = repo_group_model.get_by_group_name(repo_group_name) |
|
164 | by_name_match = repo_group_model.get_by_group_name(repo_group_name) | |
165 | if by_name_match: |
|
165 | if by_name_match: | |
166 | return True |
|
166 | return True | |
167 |
|
167 | |||
168 | return False |
|
168 | return False | |
169 |
|
169 | |||
170 | def check_user_group(environ, match_dict): |
|
170 | def check_user_group(environ, match_dict): | |
171 | """ |
|
171 | """ | |
172 | check for valid user group for proper 404 handling |
|
172 | check for valid user group for proper 404 handling | |
173 |
|
173 | |||
174 | :param environ: |
|
174 | :param environ: | |
175 | :param match_dict: |
|
175 | :param match_dict: | |
176 | """ |
|
176 | """ | |
177 | return True |
|
177 | return True | |
178 |
|
178 | |||
179 | def check_int(environ, match_dict): |
|
179 | def check_int(environ, match_dict): | |
180 | return match_dict.get('id').isdigit() |
|
180 | return match_dict.get('id').isdigit() | |
181 |
|
181 | |||
182 |
|
182 | |||
183 | #========================================================================== |
|
183 | #========================================================================== | |
184 | # CUSTOM ROUTES HERE |
|
184 | # CUSTOM ROUTES HERE | |
185 | #========================================================================== |
|
185 | #========================================================================== | |
186 |
|
186 | |||
187 | # MAIN PAGE |
|
187 | # MAIN PAGE | |
188 |
rmap.connect('home', '/', controller='home', action='index' |
|
188 | rmap.connect('home', '/', controller='home', action='index') | |
189 |
|
189 | |||
190 | # ping and pylons error test |
|
190 | # ping and pylons error test | |
191 | rmap.connect('ping', '%s/ping' % (ADMIN_PREFIX,), controller='home', action='ping') |
|
191 | rmap.connect('ping', '%s/ping' % (ADMIN_PREFIX,), controller='home', action='ping') | |
192 | rmap.connect('error_test', '%s/error_test' % (ADMIN_PREFIX,), controller='home', action='error_test') |
|
192 | rmap.connect('error_test', '%s/error_test' % (ADMIN_PREFIX,), controller='home', action='error_test') | |
193 |
|
193 | |||
194 | # ADMIN REPOSITORY ROUTES |
|
194 | # ADMIN REPOSITORY ROUTES | |
195 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
195 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
196 | controller='admin/repos') as m: |
|
196 | controller='admin/repos') as m: | |
197 | m.connect('repos', '/repos', |
|
197 | m.connect('repos', '/repos', | |
198 | action='create', conditions={'method': ['POST']}) |
|
198 | action='create', conditions={'method': ['POST']}) | |
199 | m.connect('repos', '/repos', |
|
199 | m.connect('repos', '/repos', | |
200 | action='index', conditions={'method': ['GET']}) |
|
200 | action='index', conditions={'method': ['GET']}) | |
201 | m.connect('new_repo', '/create_repository', jsroute=True, |
|
201 | m.connect('new_repo', '/create_repository', jsroute=True, | |
202 | action='create_repository', conditions={'method': ['GET']}) |
|
202 | action='create_repository', conditions={'method': ['GET']}) | |
203 | m.connect('delete_repo', '/repos/{repo_name}', |
|
203 | m.connect('delete_repo', '/repos/{repo_name}', | |
204 | action='delete', conditions={'method': ['DELETE']}, |
|
204 | action='delete', conditions={'method': ['DELETE']}, | |
205 | requirements=URL_NAME_REQUIREMENTS) |
|
205 | requirements=URL_NAME_REQUIREMENTS) | |
206 | m.connect('repo', '/repos/{repo_name}', |
|
206 | m.connect('repo', '/repos/{repo_name}', | |
207 | action='show', conditions={'method': ['GET'], |
|
207 | action='show', conditions={'method': ['GET'], | |
208 | 'function': check_repo}, |
|
208 | 'function': check_repo}, | |
209 | requirements=URL_NAME_REQUIREMENTS) |
|
209 | requirements=URL_NAME_REQUIREMENTS) | |
210 |
|
210 | |||
211 | # ADMIN REPOSITORY GROUPS ROUTES |
|
211 | # ADMIN REPOSITORY GROUPS ROUTES | |
212 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
212 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
213 | controller='admin/repo_groups') as m: |
|
213 | controller='admin/repo_groups') as m: | |
214 | m.connect('repo_groups', '/repo_groups', |
|
214 | m.connect('repo_groups', '/repo_groups', | |
215 | action='create', conditions={'method': ['POST']}) |
|
215 | action='create', conditions={'method': ['POST']}) | |
216 | m.connect('repo_groups', '/repo_groups', |
|
216 | m.connect('repo_groups', '/repo_groups', | |
217 | action='index', conditions={'method': ['GET']}) |
|
217 | action='index', conditions={'method': ['GET']}) | |
218 | m.connect('new_repo_group', '/repo_groups/new', |
|
218 | m.connect('new_repo_group', '/repo_groups/new', | |
219 | action='new', conditions={'method': ['GET']}) |
|
219 | action='new', conditions={'method': ['GET']}) | |
220 | m.connect('update_repo_group', '/repo_groups/{group_name}', |
|
220 | m.connect('update_repo_group', '/repo_groups/{group_name}', | |
221 | action='update', conditions={'method': ['PUT'], |
|
221 | action='update', conditions={'method': ['PUT'], | |
222 | 'function': check_group}, |
|
222 | 'function': check_group}, | |
223 | requirements=URL_NAME_REQUIREMENTS) |
|
223 | requirements=URL_NAME_REQUIREMENTS) | |
224 |
|
224 | |||
225 | # EXTRAS REPO GROUP ROUTES |
|
225 | # EXTRAS REPO GROUP ROUTES | |
226 | m.connect('edit_repo_group', '/repo_groups/{group_name}/edit', |
|
226 | m.connect('edit_repo_group', '/repo_groups/{group_name}/edit', | |
227 | action='edit', |
|
227 | action='edit', | |
228 | conditions={'method': ['GET'], 'function': check_group}, |
|
228 | conditions={'method': ['GET'], 'function': check_group}, | |
229 | requirements=URL_NAME_REQUIREMENTS) |
|
229 | requirements=URL_NAME_REQUIREMENTS) | |
230 | m.connect('edit_repo_group', '/repo_groups/{group_name}/edit', |
|
230 | m.connect('edit_repo_group', '/repo_groups/{group_name}/edit', | |
231 | action='edit', |
|
231 | action='edit', | |
232 | conditions={'method': ['PUT'], 'function': check_group}, |
|
232 | conditions={'method': ['PUT'], 'function': check_group}, | |
233 | requirements=URL_NAME_REQUIREMENTS) |
|
233 | requirements=URL_NAME_REQUIREMENTS) | |
234 |
|
234 | |||
235 | m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced', |
|
235 | m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced', | |
236 | action='edit_repo_group_advanced', |
|
236 | action='edit_repo_group_advanced', | |
237 | conditions={'method': ['GET'], 'function': check_group}, |
|
237 | conditions={'method': ['GET'], 'function': check_group}, | |
238 | requirements=URL_NAME_REQUIREMENTS) |
|
238 | requirements=URL_NAME_REQUIREMENTS) | |
239 | m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced', |
|
239 | m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced', | |
240 | action='edit_repo_group_advanced', |
|
240 | action='edit_repo_group_advanced', | |
241 | conditions={'method': ['PUT'], 'function': check_group}, |
|
241 | conditions={'method': ['PUT'], 'function': check_group}, | |
242 | requirements=URL_NAME_REQUIREMENTS) |
|
242 | requirements=URL_NAME_REQUIREMENTS) | |
243 |
|
243 | |||
244 | m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions', |
|
244 | m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions', | |
245 | action='edit_repo_group_perms', |
|
245 | action='edit_repo_group_perms', | |
246 | conditions={'method': ['GET'], 'function': check_group}, |
|
246 | conditions={'method': ['GET'], 'function': check_group}, | |
247 | requirements=URL_NAME_REQUIREMENTS) |
|
247 | requirements=URL_NAME_REQUIREMENTS) | |
248 | m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions', |
|
248 | m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions', | |
249 | action='update_perms', |
|
249 | action='update_perms', | |
250 | conditions={'method': ['PUT'], 'function': check_group}, |
|
250 | conditions={'method': ['PUT'], 'function': check_group}, | |
251 | requirements=URL_NAME_REQUIREMENTS) |
|
251 | requirements=URL_NAME_REQUIREMENTS) | |
252 |
|
252 | |||
253 | m.connect('delete_repo_group', '/repo_groups/{group_name}', |
|
253 | m.connect('delete_repo_group', '/repo_groups/{group_name}', | |
254 | action='delete', conditions={'method': ['DELETE'], |
|
254 | action='delete', conditions={'method': ['DELETE'], | |
255 | 'function': check_group}, |
|
255 | 'function': check_group}, | |
256 | requirements=URL_NAME_REQUIREMENTS) |
|
256 | requirements=URL_NAME_REQUIREMENTS) | |
257 |
|
257 | |||
258 | # ADMIN USER ROUTES |
|
258 | # ADMIN USER ROUTES | |
259 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
259 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
260 | controller='admin/users') as m: |
|
260 | controller='admin/users') as m: | |
261 | m.connect('users', '/users', |
|
261 | m.connect('users', '/users', | |
262 | action='create', conditions={'method': ['POST']}) |
|
262 | action='create', conditions={'method': ['POST']}) | |
263 | m.connect('new_user', '/users/new', |
|
263 | m.connect('new_user', '/users/new', | |
264 | action='new', conditions={'method': ['GET']}) |
|
264 | action='new', conditions={'method': ['GET']}) | |
265 | m.connect('update_user', '/users/{user_id}', |
|
265 | m.connect('update_user', '/users/{user_id}', | |
266 | action='update', conditions={'method': ['PUT']}) |
|
266 | action='update', conditions={'method': ['PUT']}) | |
267 | m.connect('delete_user', '/users/{user_id}', |
|
267 | m.connect('delete_user', '/users/{user_id}', | |
268 | action='delete', conditions={'method': ['DELETE']}) |
|
268 | action='delete', conditions={'method': ['DELETE']}) | |
269 | m.connect('edit_user', '/users/{user_id}/edit', |
|
269 | m.connect('edit_user', '/users/{user_id}/edit', | |
270 | action='edit', conditions={'method': ['GET']}, jsroute=True) |
|
270 | action='edit', conditions={'method': ['GET']}, jsroute=True) | |
271 | m.connect('user', '/users/{user_id}', |
|
271 | m.connect('user', '/users/{user_id}', | |
272 | action='show', conditions={'method': ['GET']}) |
|
272 | action='show', conditions={'method': ['GET']}) | |
273 | m.connect('force_password_reset_user', '/users/{user_id}/password_reset', |
|
273 | m.connect('force_password_reset_user', '/users/{user_id}/password_reset', | |
274 | action='reset_password', conditions={'method': ['POST']}) |
|
274 | action='reset_password', conditions={'method': ['POST']}) | |
275 | m.connect('create_personal_repo_group', '/users/{user_id}/create_repo_group', |
|
275 | m.connect('create_personal_repo_group', '/users/{user_id}/create_repo_group', | |
276 | action='create_personal_repo_group', conditions={'method': ['POST']}) |
|
276 | action='create_personal_repo_group', conditions={'method': ['POST']}) | |
277 |
|
277 | |||
278 | # EXTRAS USER ROUTES |
|
278 | # EXTRAS USER ROUTES | |
279 | m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced', |
|
279 | m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced', | |
280 | action='edit_advanced', conditions={'method': ['GET']}) |
|
280 | action='edit_advanced', conditions={'method': ['GET']}) | |
281 | m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced', |
|
281 | m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced', | |
282 | action='update_advanced', conditions={'method': ['PUT']}) |
|
282 | action='update_advanced', conditions={'method': ['PUT']}) | |
283 |
|
283 | |||
284 | m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions', |
|
284 | m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions', | |
285 | action='edit_global_perms', conditions={'method': ['GET']}) |
|
285 | action='edit_global_perms', conditions={'method': ['GET']}) | |
286 | m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions', |
|
286 | m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions', | |
287 | action='update_global_perms', conditions={'method': ['PUT']}) |
|
287 | action='update_global_perms', conditions={'method': ['PUT']}) | |
288 |
|
288 | |||
289 | m.connect('edit_user_perms_summary', '/users/{user_id}/edit/permissions_summary', |
|
289 | m.connect('edit_user_perms_summary', '/users/{user_id}/edit/permissions_summary', | |
290 | action='edit_perms_summary', conditions={'method': ['GET']}) |
|
290 | action='edit_perms_summary', conditions={'method': ['GET']}) | |
291 |
|
291 | |||
292 | m.connect('edit_user_emails', '/users/{user_id}/edit/emails', |
|
292 | m.connect('edit_user_emails', '/users/{user_id}/edit/emails', | |
293 | action='edit_emails', conditions={'method': ['GET']}) |
|
293 | action='edit_emails', conditions={'method': ['GET']}) | |
294 | m.connect('edit_user_emails', '/users/{user_id}/edit/emails', |
|
294 | m.connect('edit_user_emails', '/users/{user_id}/edit/emails', | |
295 | action='add_email', conditions={'method': ['PUT']}) |
|
295 | action='add_email', conditions={'method': ['PUT']}) | |
296 | m.connect('edit_user_emails', '/users/{user_id}/edit/emails', |
|
296 | m.connect('edit_user_emails', '/users/{user_id}/edit/emails', | |
297 | action='delete_email', conditions={'method': ['DELETE']}) |
|
297 | action='delete_email', conditions={'method': ['DELETE']}) | |
298 |
|
298 | |||
299 | m.connect('edit_user_ips', '/users/{user_id}/edit/ips', |
|
299 | m.connect('edit_user_ips', '/users/{user_id}/edit/ips', | |
300 | action='edit_ips', conditions={'method': ['GET']}) |
|
300 | action='edit_ips', conditions={'method': ['GET']}) | |
301 | m.connect('edit_user_ips', '/users/{user_id}/edit/ips', |
|
301 | m.connect('edit_user_ips', '/users/{user_id}/edit/ips', | |
302 | action='add_ip', conditions={'method': ['PUT']}) |
|
302 | action='add_ip', conditions={'method': ['PUT']}) | |
303 | m.connect('edit_user_ips', '/users/{user_id}/edit/ips', |
|
303 | m.connect('edit_user_ips', '/users/{user_id}/edit/ips', | |
304 | action='delete_ip', conditions={'method': ['DELETE']}) |
|
304 | action='delete_ip', conditions={'method': ['DELETE']}) | |
305 |
|
305 | |||
306 | # ADMIN USER GROUPS REST ROUTES |
|
306 | # ADMIN USER GROUPS REST ROUTES | |
307 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
307 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
308 | controller='admin/user_groups') as m: |
|
308 | controller='admin/user_groups') as m: | |
309 | m.connect('users_groups', '/user_groups', |
|
309 | m.connect('users_groups', '/user_groups', | |
310 | action='create', conditions={'method': ['POST']}) |
|
310 | action='create', conditions={'method': ['POST']}) | |
311 | m.connect('users_groups', '/user_groups', |
|
311 | m.connect('users_groups', '/user_groups', | |
312 | action='index', conditions={'method': ['GET']}) |
|
312 | action='index', conditions={'method': ['GET']}) | |
313 | m.connect('new_users_group', '/user_groups/new', |
|
313 | m.connect('new_users_group', '/user_groups/new', | |
314 | action='new', conditions={'method': ['GET']}) |
|
314 | action='new', conditions={'method': ['GET']}) | |
315 | m.connect('update_users_group', '/user_groups/{user_group_id}', |
|
315 | m.connect('update_users_group', '/user_groups/{user_group_id}', | |
316 | action='update', conditions={'method': ['PUT']}) |
|
316 | action='update', conditions={'method': ['PUT']}) | |
317 | m.connect('delete_users_group', '/user_groups/{user_group_id}', |
|
317 | m.connect('delete_users_group', '/user_groups/{user_group_id}', | |
318 | action='delete', conditions={'method': ['DELETE']}) |
|
318 | action='delete', conditions={'method': ['DELETE']}) | |
319 | m.connect('edit_users_group', '/user_groups/{user_group_id}/edit', |
|
319 | m.connect('edit_users_group', '/user_groups/{user_group_id}/edit', | |
320 | action='edit', conditions={'method': ['GET']}, |
|
320 | action='edit', conditions={'method': ['GET']}, | |
321 | function=check_user_group) |
|
321 | function=check_user_group) | |
322 |
|
322 | |||
323 | # EXTRAS USER GROUP ROUTES |
|
323 | # EXTRAS USER GROUP ROUTES | |
324 | m.connect('edit_user_group_global_perms', |
|
324 | m.connect('edit_user_group_global_perms', | |
325 | '/user_groups/{user_group_id}/edit/global_permissions', |
|
325 | '/user_groups/{user_group_id}/edit/global_permissions', | |
326 | action='edit_global_perms', conditions={'method': ['GET']}) |
|
326 | action='edit_global_perms', conditions={'method': ['GET']}) | |
327 | m.connect('edit_user_group_global_perms', |
|
327 | m.connect('edit_user_group_global_perms', | |
328 | '/user_groups/{user_group_id}/edit/global_permissions', |
|
328 | '/user_groups/{user_group_id}/edit/global_permissions', | |
329 | action='update_global_perms', conditions={'method': ['PUT']}) |
|
329 | action='update_global_perms', conditions={'method': ['PUT']}) | |
330 | m.connect('edit_user_group_perms_summary', |
|
330 | m.connect('edit_user_group_perms_summary', | |
331 | '/user_groups/{user_group_id}/edit/permissions_summary', |
|
331 | '/user_groups/{user_group_id}/edit/permissions_summary', | |
332 | action='edit_perms_summary', conditions={'method': ['GET']}) |
|
332 | action='edit_perms_summary', conditions={'method': ['GET']}) | |
333 |
|
333 | |||
334 | m.connect('edit_user_group_perms', |
|
334 | m.connect('edit_user_group_perms', | |
335 | '/user_groups/{user_group_id}/edit/permissions', |
|
335 | '/user_groups/{user_group_id}/edit/permissions', | |
336 | action='edit_perms', conditions={'method': ['GET']}) |
|
336 | action='edit_perms', conditions={'method': ['GET']}) | |
337 | m.connect('edit_user_group_perms', |
|
337 | m.connect('edit_user_group_perms', | |
338 | '/user_groups/{user_group_id}/edit/permissions', |
|
338 | '/user_groups/{user_group_id}/edit/permissions', | |
339 | action='update_perms', conditions={'method': ['PUT']}) |
|
339 | action='update_perms', conditions={'method': ['PUT']}) | |
340 |
|
340 | |||
341 | m.connect('edit_user_group_advanced', |
|
341 | m.connect('edit_user_group_advanced', | |
342 | '/user_groups/{user_group_id}/edit/advanced', |
|
342 | '/user_groups/{user_group_id}/edit/advanced', | |
343 | action='edit_advanced', conditions={'method': ['GET']}) |
|
343 | action='edit_advanced', conditions={'method': ['GET']}) | |
344 |
|
344 | |||
345 | m.connect('edit_user_group_advanced_sync', |
|
345 | m.connect('edit_user_group_advanced_sync', | |
346 | '/user_groups/{user_group_id}/edit/advanced/sync', |
|
346 | '/user_groups/{user_group_id}/edit/advanced/sync', | |
347 | action='edit_advanced_set_synchronization', conditions={'method': ['POST']}) |
|
347 | action='edit_advanced_set_synchronization', conditions={'method': ['POST']}) | |
348 |
|
348 | |||
349 | m.connect('edit_user_group_members', |
|
349 | m.connect('edit_user_group_members', | |
350 | '/user_groups/{user_group_id}/edit/members', jsroute=True, |
|
350 | '/user_groups/{user_group_id}/edit/members', jsroute=True, | |
351 | action='user_group_members', conditions={'method': ['GET']}) |
|
351 | action='user_group_members', conditions={'method': ['GET']}) | |
352 |
|
352 | |||
353 | # ADMIN PERMISSIONS ROUTES |
|
353 | # ADMIN PERMISSIONS ROUTES | |
354 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
354 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
355 | controller='admin/permissions') as m: |
|
355 | controller='admin/permissions') as m: | |
356 | m.connect('admin_permissions_application', '/permissions/application', |
|
356 | m.connect('admin_permissions_application', '/permissions/application', | |
357 | action='permission_application_update', conditions={'method': ['POST']}) |
|
357 | action='permission_application_update', conditions={'method': ['POST']}) | |
358 | m.connect('admin_permissions_application', '/permissions/application', |
|
358 | m.connect('admin_permissions_application', '/permissions/application', | |
359 | action='permission_application', conditions={'method': ['GET']}) |
|
359 | action='permission_application', conditions={'method': ['GET']}) | |
360 |
|
360 | |||
361 | m.connect('admin_permissions_global', '/permissions/global', |
|
361 | m.connect('admin_permissions_global', '/permissions/global', | |
362 | action='permission_global_update', conditions={'method': ['POST']}) |
|
362 | action='permission_global_update', conditions={'method': ['POST']}) | |
363 | m.connect('admin_permissions_global', '/permissions/global', |
|
363 | m.connect('admin_permissions_global', '/permissions/global', | |
364 | action='permission_global', conditions={'method': ['GET']}) |
|
364 | action='permission_global', conditions={'method': ['GET']}) | |
365 |
|
365 | |||
366 | m.connect('admin_permissions_object', '/permissions/object', |
|
366 | m.connect('admin_permissions_object', '/permissions/object', | |
367 | action='permission_objects_update', conditions={'method': ['POST']}) |
|
367 | action='permission_objects_update', conditions={'method': ['POST']}) | |
368 | m.connect('admin_permissions_object', '/permissions/object', |
|
368 | m.connect('admin_permissions_object', '/permissions/object', | |
369 | action='permission_objects', conditions={'method': ['GET']}) |
|
369 | action='permission_objects', conditions={'method': ['GET']}) | |
370 |
|
370 | |||
371 | m.connect('admin_permissions_ips', '/permissions/ips', |
|
371 | m.connect('admin_permissions_ips', '/permissions/ips', | |
372 | action='permission_ips', conditions={'method': ['POST']}) |
|
372 | action='permission_ips', conditions={'method': ['POST']}) | |
373 | m.connect('admin_permissions_ips', '/permissions/ips', |
|
373 | m.connect('admin_permissions_ips', '/permissions/ips', | |
374 | action='permission_ips', conditions={'method': ['GET']}) |
|
374 | action='permission_ips', conditions={'method': ['GET']}) | |
375 |
|
375 | |||
376 | m.connect('admin_permissions_overview', '/permissions/overview', |
|
376 | m.connect('admin_permissions_overview', '/permissions/overview', | |
377 | action='permission_perms', conditions={'method': ['GET']}) |
|
377 | action='permission_perms', conditions={'method': ['GET']}) | |
378 |
|
378 | |||
379 | # ADMIN DEFAULTS REST ROUTES |
|
379 | # ADMIN DEFAULTS REST ROUTES | |
380 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
380 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
381 | controller='admin/defaults') as m: |
|
381 | controller='admin/defaults') as m: | |
382 | m.connect('admin_defaults_repositories', '/defaults/repositories', |
|
382 | m.connect('admin_defaults_repositories', '/defaults/repositories', | |
383 | action='update_repository_defaults', conditions={'method': ['POST']}) |
|
383 | action='update_repository_defaults', conditions={'method': ['POST']}) | |
384 | m.connect('admin_defaults_repositories', '/defaults/repositories', |
|
384 | m.connect('admin_defaults_repositories', '/defaults/repositories', | |
385 | action='index', conditions={'method': ['GET']}) |
|
385 | action='index', conditions={'method': ['GET']}) | |
386 |
|
386 | |||
387 | # ADMIN DEBUG STYLE ROUTES |
|
387 | # ADMIN DEBUG STYLE ROUTES | |
388 | if str2bool(config.get('debug_style')): |
|
388 | if str2bool(config.get('debug_style')): | |
389 | with rmap.submapper(path_prefix=ADMIN_PREFIX + '/debug_style', |
|
389 | with rmap.submapper(path_prefix=ADMIN_PREFIX + '/debug_style', | |
390 | controller='debug_style') as m: |
|
390 | controller='debug_style') as m: | |
391 | m.connect('debug_style_home', '', |
|
391 | m.connect('debug_style_home', '', | |
392 | action='index', conditions={'method': ['GET']}) |
|
392 | action='index', conditions={'method': ['GET']}) | |
393 | m.connect('debug_style_template', '/t/{t_path}', |
|
393 | m.connect('debug_style_template', '/t/{t_path}', | |
394 | action='template', conditions={'method': ['GET']}) |
|
394 | action='template', conditions={'method': ['GET']}) | |
395 |
|
395 | |||
396 | # ADMIN SETTINGS ROUTES |
|
396 | # ADMIN SETTINGS ROUTES | |
397 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
397 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
398 | controller='admin/settings') as m: |
|
398 | controller='admin/settings') as m: | |
399 |
|
399 | |||
400 | # default |
|
400 | # default | |
401 | m.connect('admin_settings', '/settings', |
|
401 | m.connect('admin_settings', '/settings', | |
402 | action='settings_global_update', |
|
402 | action='settings_global_update', | |
403 | conditions={'method': ['POST']}) |
|
403 | conditions={'method': ['POST']}) | |
404 | m.connect('admin_settings', '/settings', |
|
404 | m.connect('admin_settings', '/settings', | |
405 | action='settings_global', conditions={'method': ['GET']}) |
|
405 | action='settings_global', conditions={'method': ['GET']}) | |
406 |
|
406 | |||
407 | m.connect('admin_settings_vcs', '/settings/vcs', |
|
407 | m.connect('admin_settings_vcs', '/settings/vcs', | |
408 | action='settings_vcs_update', |
|
408 | action='settings_vcs_update', | |
409 | conditions={'method': ['POST']}) |
|
409 | conditions={'method': ['POST']}) | |
410 | m.connect('admin_settings_vcs', '/settings/vcs', |
|
410 | m.connect('admin_settings_vcs', '/settings/vcs', | |
411 | action='settings_vcs', |
|
411 | action='settings_vcs', | |
412 | conditions={'method': ['GET']}) |
|
412 | conditions={'method': ['GET']}) | |
413 | m.connect('admin_settings_vcs', '/settings/vcs', |
|
413 | m.connect('admin_settings_vcs', '/settings/vcs', | |
414 | action='delete_svn_pattern', |
|
414 | action='delete_svn_pattern', | |
415 | conditions={'method': ['DELETE']}) |
|
415 | conditions={'method': ['DELETE']}) | |
416 |
|
416 | |||
417 | m.connect('admin_settings_mapping', '/settings/mapping', |
|
417 | m.connect('admin_settings_mapping', '/settings/mapping', | |
418 | action='settings_mapping_update', |
|
418 | action='settings_mapping_update', | |
419 | conditions={'method': ['POST']}) |
|
419 | conditions={'method': ['POST']}) | |
420 | m.connect('admin_settings_mapping', '/settings/mapping', |
|
420 | m.connect('admin_settings_mapping', '/settings/mapping', | |
421 | action='settings_mapping', conditions={'method': ['GET']}) |
|
421 | action='settings_mapping', conditions={'method': ['GET']}) | |
422 |
|
422 | |||
423 | m.connect('admin_settings_global', '/settings/global', |
|
423 | m.connect('admin_settings_global', '/settings/global', | |
424 | action='settings_global_update', |
|
424 | action='settings_global_update', | |
425 | conditions={'method': ['POST']}) |
|
425 | conditions={'method': ['POST']}) | |
426 | m.connect('admin_settings_global', '/settings/global', |
|
426 | m.connect('admin_settings_global', '/settings/global', | |
427 | action='settings_global', conditions={'method': ['GET']}) |
|
427 | action='settings_global', conditions={'method': ['GET']}) | |
428 |
|
428 | |||
429 | m.connect('admin_settings_visual', '/settings/visual', |
|
429 | m.connect('admin_settings_visual', '/settings/visual', | |
430 | action='settings_visual_update', |
|
430 | action='settings_visual_update', | |
431 | conditions={'method': ['POST']}) |
|
431 | conditions={'method': ['POST']}) | |
432 | m.connect('admin_settings_visual', '/settings/visual', |
|
432 | m.connect('admin_settings_visual', '/settings/visual', | |
433 | action='settings_visual', conditions={'method': ['GET']}) |
|
433 | action='settings_visual', conditions={'method': ['GET']}) | |
434 |
|
434 | |||
435 | m.connect('admin_settings_issuetracker', |
|
435 | m.connect('admin_settings_issuetracker', | |
436 | '/settings/issue-tracker', action='settings_issuetracker', |
|
436 | '/settings/issue-tracker', action='settings_issuetracker', | |
437 | conditions={'method': ['GET']}) |
|
437 | conditions={'method': ['GET']}) | |
438 | m.connect('admin_settings_issuetracker_save', |
|
438 | m.connect('admin_settings_issuetracker_save', | |
439 | '/settings/issue-tracker/save', |
|
439 | '/settings/issue-tracker/save', | |
440 | action='settings_issuetracker_save', |
|
440 | action='settings_issuetracker_save', | |
441 | conditions={'method': ['POST']}) |
|
441 | conditions={'method': ['POST']}) | |
442 | m.connect('admin_issuetracker_test', '/settings/issue-tracker/test', |
|
442 | m.connect('admin_issuetracker_test', '/settings/issue-tracker/test', | |
443 | action='settings_issuetracker_test', |
|
443 | action='settings_issuetracker_test', | |
444 | conditions={'method': ['POST']}) |
|
444 | conditions={'method': ['POST']}) | |
445 | m.connect('admin_issuetracker_delete', |
|
445 | m.connect('admin_issuetracker_delete', | |
446 | '/settings/issue-tracker/delete', |
|
446 | '/settings/issue-tracker/delete', | |
447 | action='settings_issuetracker_delete', |
|
447 | action='settings_issuetracker_delete', | |
448 | conditions={'method': ['DELETE']}) |
|
448 | conditions={'method': ['DELETE']}) | |
449 |
|
449 | |||
450 | m.connect('admin_settings_email', '/settings/email', |
|
450 | m.connect('admin_settings_email', '/settings/email', | |
451 | action='settings_email_update', |
|
451 | action='settings_email_update', | |
452 | conditions={'method': ['POST']}) |
|
452 | conditions={'method': ['POST']}) | |
453 | m.connect('admin_settings_email', '/settings/email', |
|
453 | m.connect('admin_settings_email', '/settings/email', | |
454 | action='settings_email', conditions={'method': ['GET']}) |
|
454 | action='settings_email', conditions={'method': ['GET']}) | |
455 |
|
455 | |||
456 | m.connect('admin_settings_hooks', '/settings/hooks', |
|
456 | m.connect('admin_settings_hooks', '/settings/hooks', | |
457 | action='settings_hooks_update', |
|
457 | action='settings_hooks_update', | |
458 | conditions={'method': ['POST', 'DELETE']}) |
|
458 | conditions={'method': ['POST', 'DELETE']}) | |
459 | m.connect('admin_settings_hooks', '/settings/hooks', |
|
459 | m.connect('admin_settings_hooks', '/settings/hooks', | |
460 | action='settings_hooks', conditions={'method': ['GET']}) |
|
460 | action='settings_hooks', conditions={'method': ['GET']}) | |
461 |
|
461 | |||
462 | m.connect('admin_settings_search', '/settings/search', |
|
462 | m.connect('admin_settings_search', '/settings/search', | |
463 | action='settings_search', conditions={'method': ['GET']}) |
|
463 | action='settings_search', conditions={'method': ['GET']}) | |
464 |
|
464 | |||
465 | m.connect('admin_settings_supervisor', '/settings/supervisor', |
|
465 | m.connect('admin_settings_supervisor', '/settings/supervisor', | |
466 | action='settings_supervisor', conditions={'method': ['GET']}) |
|
466 | action='settings_supervisor', conditions={'method': ['GET']}) | |
467 | m.connect('admin_settings_supervisor_log', '/settings/supervisor/{procid}/log', |
|
467 | m.connect('admin_settings_supervisor_log', '/settings/supervisor/{procid}/log', | |
468 | action='settings_supervisor_log', conditions={'method': ['GET']}) |
|
468 | action='settings_supervisor_log', conditions={'method': ['GET']}) | |
469 |
|
469 | |||
470 | m.connect('admin_settings_labs', '/settings/labs', |
|
470 | m.connect('admin_settings_labs', '/settings/labs', | |
471 | action='settings_labs_update', |
|
471 | action='settings_labs_update', | |
472 | conditions={'method': ['POST']}) |
|
472 | conditions={'method': ['POST']}) | |
473 | m.connect('admin_settings_labs', '/settings/labs', |
|
473 | m.connect('admin_settings_labs', '/settings/labs', | |
474 | action='settings_labs', conditions={'method': ['GET']}) |
|
474 | action='settings_labs', conditions={'method': ['GET']}) | |
475 |
|
475 | |||
476 | # ADMIN MY ACCOUNT |
|
476 | # ADMIN MY ACCOUNT | |
477 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
477 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
478 | controller='admin/my_account') as m: |
|
478 | controller='admin/my_account') as m: | |
479 |
|
479 | |||
480 | m.connect('my_account_edit', '/my_account/edit', |
|
480 | m.connect('my_account_edit', '/my_account/edit', | |
481 | action='my_account_edit', conditions={'method': ['GET']}) |
|
481 | action='my_account_edit', conditions={'method': ['GET']}) | |
482 | m.connect('my_account', '/my_account/update', |
|
482 | m.connect('my_account', '/my_account/update', | |
483 | action='my_account_update', conditions={'method': ['POST']}) |
|
483 | action='my_account_update', conditions={'method': ['POST']}) | |
484 |
|
484 | |||
485 | # NOTE(marcink): this needs to be kept for password force flag to be |
|
485 | # NOTE(marcink): this needs to be kept for password force flag to be | |
486 | # handler, remove after migration to pyramid |
|
486 | # handler, remove after migration to pyramid | |
487 | m.connect('my_account_password', '/my_account/password', |
|
487 | m.connect('my_account_password', '/my_account/password', | |
488 | action='my_account_password', conditions={'method': ['GET']}) |
|
488 | action='my_account_password', conditions={'method': ['GET']}) | |
489 |
|
489 | |||
490 | m.connect('my_account_repos', '/my_account/repos', |
|
490 | m.connect('my_account_repos', '/my_account/repos', | |
491 | action='my_account_repos', conditions={'method': ['GET']}) |
|
491 | action='my_account_repos', conditions={'method': ['GET']}) | |
492 |
|
492 | |||
493 | m.connect('my_account_watched', '/my_account/watched', |
|
493 | m.connect('my_account_watched', '/my_account/watched', | |
494 | action='my_account_watched', conditions={'method': ['GET']}) |
|
494 | action='my_account_watched', conditions={'method': ['GET']}) | |
495 |
|
495 | |||
496 | m.connect('my_account_pullrequests', '/my_account/pull_requests', |
|
496 | m.connect('my_account_pullrequests', '/my_account/pull_requests', | |
497 | action='my_account_pullrequests', conditions={'method': ['GET']}) |
|
497 | action='my_account_pullrequests', conditions={'method': ['GET']}) | |
498 |
|
498 | |||
499 | m.connect('my_account_perms', '/my_account/perms', |
|
499 | m.connect('my_account_perms', '/my_account/perms', | |
500 | action='my_account_perms', conditions={'method': ['GET']}) |
|
500 | action='my_account_perms', conditions={'method': ['GET']}) | |
501 |
|
501 | |||
502 | m.connect('my_account_emails', '/my_account/emails', |
|
502 | m.connect('my_account_emails', '/my_account/emails', | |
503 | action='my_account_emails', conditions={'method': ['GET']}) |
|
503 | action='my_account_emails', conditions={'method': ['GET']}) | |
504 | m.connect('my_account_emails', '/my_account/emails', |
|
504 | m.connect('my_account_emails', '/my_account/emails', | |
505 | action='my_account_emails_add', conditions={'method': ['POST']}) |
|
505 | action='my_account_emails_add', conditions={'method': ['POST']}) | |
506 | m.connect('my_account_emails', '/my_account/emails', |
|
506 | m.connect('my_account_emails', '/my_account/emails', | |
507 | action='my_account_emails_delete', conditions={'method': ['DELETE']}) |
|
507 | action='my_account_emails_delete', conditions={'method': ['DELETE']}) | |
508 |
|
508 | |||
509 | m.connect('my_account_notifications', '/my_account/notifications', |
|
509 | m.connect('my_account_notifications', '/my_account/notifications', | |
510 | action='my_notifications', |
|
510 | action='my_notifications', | |
511 | conditions={'method': ['GET']}) |
|
511 | conditions={'method': ['GET']}) | |
512 | m.connect('my_account_notifications_toggle_visibility', |
|
512 | m.connect('my_account_notifications_toggle_visibility', | |
513 | '/my_account/toggle_visibility', |
|
513 | '/my_account/toggle_visibility', | |
514 | action='my_notifications_toggle_visibility', |
|
514 | action='my_notifications_toggle_visibility', | |
515 | conditions={'method': ['POST']}) |
|
515 | conditions={'method': ['POST']}) | |
516 | m.connect('my_account_notifications_test_channelstream', |
|
516 | m.connect('my_account_notifications_test_channelstream', | |
517 | '/my_account/test_channelstream', |
|
517 | '/my_account/test_channelstream', | |
518 | action='my_account_notifications_test_channelstream', |
|
518 | action='my_account_notifications_test_channelstream', | |
519 | conditions={'method': ['POST']}) |
|
519 | conditions={'method': ['POST']}) | |
520 |
|
520 | |||
521 | # NOTIFICATION REST ROUTES |
|
521 | # NOTIFICATION REST ROUTES | |
522 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
522 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
523 | controller='admin/notifications') as m: |
|
523 | controller='admin/notifications') as m: | |
524 | m.connect('notifications', '/notifications', |
|
524 | m.connect('notifications', '/notifications', | |
525 | action='index', conditions={'method': ['GET']}) |
|
525 | action='index', conditions={'method': ['GET']}) | |
526 | m.connect('notifications_mark_all_read', '/notifications/mark_all_read', |
|
526 | m.connect('notifications_mark_all_read', '/notifications/mark_all_read', | |
527 | action='mark_all_read', conditions={'method': ['POST']}) |
|
527 | action='mark_all_read', conditions={'method': ['POST']}) | |
528 | m.connect('/notifications/{notification_id}', |
|
528 | m.connect('/notifications/{notification_id}', | |
529 | action='update', conditions={'method': ['PUT']}) |
|
529 | action='update', conditions={'method': ['PUT']}) | |
530 | m.connect('/notifications/{notification_id}', |
|
530 | m.connect('/notifications/{notification_id}', | |
531 | action='delete', conditions={'method': ['DELETE']}) |
|
531 | action='delete', conditions={'method': ['DELETE']}) | |
532 | m.connect('notification', '/notifications/{notification_id}', |
|
532 | m.connect('notification', '/notifications/{notification_id}', | |
533 | action='show', conditions={'method': ['GET']}) |
|
533 | action='show', conditions={'method': ['GET']}) | |
534 |
|
534 | |||
535 | # ADMIN GIST |
|
535 | # ADMIN GIST | |
536 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
536 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
537 | controller='admin/gists') as m: |
|
537 | controller='admin/gists') as m: | |
538 | m.connect('gists', '/gists', |
|
538 | m.connect('gists', '/gists', | |
539 | action='create', conditions={'method': ['POST']}) |
|
539 | action='create', conditions={'method': ['POST']}) | |
540 | m.connect('gists', '/gists', jsroute=True, |
|
540 | m.connect('gists', '/gists', jsroute=True, | |
541 | action='index', conditions={'method': ['GET']}) |
|
541 | action='index', conditions={'method': ['GET']}) | |
542 | m.connect('new_gist', '/gists/new', jsroute=True, |
|
542 | m.connect('new_gist', '/gists/new', jsroute=True, | |
543 | action='new', conditions={'method': ['GET']}) |
|
543 | action='new', conditions={'method': ['GET']}) | |
544 |
|
544 | |||
545 | m.connect('/gists/{gist_id}', |
|
545 | m.connect('/gists/{gist_id}', | |
546 | action='delete', conditions={'method': ['DELETE']}) |
|
546 | action='delete', conditions={'method': ['DELETE']}) | |
547 | m.connect('edit_gist', '/gists/{gist_id}/edit', |
|
547 | m.connect('edit_gist', '/gists/{gist_id}/edit', | |
548 | action='edit_form', conditions={'method': ['GET']}) |
|
548 | action='edit_form', conditions={'method': ['GET']}) | |
549 | m.connect('edit_gist', '/gists/{gist_id}/edit', |
|
549 | m.connect('edit_gist', '/gists/{gist_id}/edit', | |
550 | action='edit', conditions={'method': ['POST']}) |
|
550 | action='edit', conditions={'method': ['POST']}) | |
551 | m.connect( |
|
551 | m.connect( | |
552 | 'edit_gist_check_revision', '/gists/{gist_id}/edit/check_revision', |
|
552 | 'edit_gist_check_revision', '/gists/{gist_id}/edit/check_revision', | |
553 | action='check_revision', conditions={'method': ['GET']}) |
|
553 | action='check_revision', conditions={'method': ['GET']}) | |
554 |
|
554 | |||
555 | m.connect('gist', '/gists/{gist_id}', |
|
555 | m.connect('gist', '/gists/{gist_id}', | |
556 | action='show', conditions={'method': ['GET']}) |
|
556 | action='show', conditions={'method': ['GET']}) | |
557 | m.connect('gist_rev', '/gists/{gist_id}/{revision}', |
|
557 | m.connect('gist_rev', '/gists/{gist_id}/{revision}', | |
558 | revision='tip', |
|
558 | revision='tip', | |
559 | action='show', conditions={'method': ['GET']}) |
|
559 | action='show', conditions={'method': ['GET']}) | |
560 | m.connect('formatted_gist', '/gists/{gist_id}/{revision}/{format}', |
|
560 | m.connect('formatted_gist', '/gists/{gist_id}/{revision}/{format}', | |
561 | revision='tip', |
|
561 | revision='tip', | |
562 | action='show', conditions={'method': ['GET']}) |
|
562 | action='show', conditions={'method': ['GET']}) | |
563 | m.connect('formatted_gist_file', '/gists/{gist_id}/{revision}/{format}/{f_path}', |
|
563 | m.connect('formatted_gist_file', '/gists/{gist_id}/{revision}/{format}/{f_path}', | |
564 | revision='tip', |
|
564 | revision='tip', | |
565 | action='show', conditions={'method': ['GET']}, |
|
565 | action='show', conditions={'method': ['GET']}, | |
566 | requirements=URL_NAME_REQUIREMENTS) |
|
566 | requirements=URL_NAME_REQUIREMENTS) | |
567 |
|
567 | |||
568 | # ADMIN MAIN PAGES |
|
568 | # ADMIN MAIN PAGES | |
569 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
569 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
570 | controller='admin/admin') as m: |
|
570 | controller='admin/admin') as m: | |
571 | m.connect('admin_home', '', action='index') |
|
571 | m.connect('admin_home', '', action='index') | |
572 | m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}', |
|
572 | m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}', | |
573 | action='add_repo') |
|
573 | action='add_repo') | |
574 | m.connect( |
|
574 | m.connect( | |
575 | 'pull_requests_global_0', '/pull_requests/{pull_request_id:[0-9]+}', |
|
575 | 'pull_requests_global_0', '/pull_requests/{pull_request_id:[0-9]+}', | |
576 | action='pull_requests') |
|
576 | action='pull_requests') | |
577 | m.connect( |
|
577 | m.connect( | |
578 | 'pull_requests_global_1', '/pull-requests/{pull_request_id:[0-9]+}', |
|
578 | 'pull_requests_global_1', '/pull-requests/{pull_request_id:[0-9]+}', | |
579 | action='pull_requests') |
|
579 | action='pull_requests') | |
580 | m.connect( |
|
580 | m.connect( | |
581 | 'pull_requests_global', '/pull-request/{pull_request_id:[0-9]+}', |
|
581 | 'pull_requests_global', '/pull-request/{pull_request_id:[0-9]+}', | |
582 | action='pull_requests') |
|
582 | action='pull_requests') | |
583 |
|
583 | |||
584 | # USER JOURNAL |
|
584 | # USER JOURNAL | |
585 | rmap.connect('journal', '%s/journal' % (ADMIN_PREFIX,), |
|
585 | rmap.connect('journal', '%s/journal' % (ADMIN_PREFIX,), | |
586 | controller='journal', action='index') |
|
586 | controller='journal', action='index') | |
587 | rmap.connect('journal_rss', '%s/journal/rss' % (ADMIN_PREFIX,), |
|
587 | rmap.connect('journal_rss', '%s/journal/rss' % (ADMIN_PREFIX,), | |
588 | controller='journal', action='journal_rss') |
|
588 | controller='journal', action='journal_rss') | |
589 | rmap.connect('journal_atom', '%s/journal/atom' % (ADMIN_PREFIX,), |
|
589 | rmap.connect('journal_atom', '%s/journal/atom' % (ADMIN_PREFIX,), | |
590 | controller='journal', action='journal_atom') |
|
590 | controller='journal', action='journal_atom') | |
591 |
|
591 | |||
592 | rmap.connect('public_journal', '%s/public_journal' % (ADMIN_PREFIX,), |
|
592 | rmap.connect('public_journal', '%s/public_journal' % (ADMIN_PREFIX,), | |
593 | controller='journal', action='public_journal') |
|
593 | controller='journal', action='public_journal') | |
594 |
|
594 | |||
595 | rmap.connect('public_journal_rss', '%s/public_journal/rss' % (ADMIN_PREFIX,), |
|
595 | rmap.connect('public_journal_rss', '%s/public_journal/rss' % (ADMIN_PREFIX,), | |
596 | controller='journal', action='public_journal_rss') |
|
596 | controller='journal', action='public_journal_rss') | |
597 |
|
597 | |||
598 | rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % (ADMIN_PREFIX,), |
|
598 | rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % (ADMIN_PREFIX,), | |
599 | controller='journal', action='public_journal_rss') |
|
599 | controller='journal', action='public_journal_rss') | |
600 |
|
600 | |||
601 | rmap.connect('public_journal_atom', |
|
601 | rmap.connect('public_journal_atom', | |
602 | '%s/public_journal/atom' % (ADMIN_PREFIX,), controller='journal', |
|
602 | '%s/public_journal/atom' % (ADMIN_PREFIX,), controller='journal', | |
603 | action='public_journal_atom') |
|
603 | action='public_journal_atom') | |
604 |
|
604 | |||
605 | rmap.connect('public_journal_atom_old', |
|
605 | rmap.connect('public_journal_atom_old', | |
606 | '%s/public_journal_atom' % (ADMIN_PREFIX,), controller='journal', |
|
606 | '%s/public_journal_atom' % (ADMIN_PREFIX,), controller='journal', | |
607 | action='public_journal_atom') |
|
607 | action='public_journal_atom') | |
608 |
|
608 | |||
609 | rmap.connect('toggle_following', '%s/toggle_following' % (ADMIN_PREFIX,), |
|
609 | rmap.connect('toggle_following', '%s/toggle_following' % (ADMIN_PREFIX,), | |
610 | controller='journal', action='toggle_following', jsroute=True, |
|
610 | controller='journal', action='toggle_following', jsroute=True, | |
611 | conditions={'method': ['POST']}) |
|
611 | conditions={'method': ['POST']}) | |
612 |
|
612 | |||
613 | # FEEDS |
|
613 | # FEEDS | |
614 | rmap.connect('rss_feed_home', '/{repo_name}/feed/rss', |
|
614 | rmap.connect('rss_feed_home', '/{repo_name}/feed/rss', | |
615 | controller='feed', action='rss', |
|
615 | controller='feed', action='rss', | |
616 | conditions={'function': check_repo}, |
|
616 | conditions={'function': check_repo}, | |
617 | requirements=URL_NAME_REQUIREMENTS) |
|
617 | requirements=URL_NAME_REQUIREMENTS) | |
618 |
|
618 | |||
619 | rmap.connect('atom_feed_home', '/{repo_name}/feed/atom', |
|
619 | rmap.connect('atom_feed_home', '/{repo_name}/feed/atom', | |
620 | controller='feed', action='atom', |
|
620 | controller='feed', action='atom', | |
621 | conditions={'function': check_repo}, |
|
621 | conditions={'function': check_repo}, | |
622 | requirements=URL_NAME_REQUIREMENTS) |
|
622 | requirements=URL_NAME_REQUIREMENTS) | |
623 |
|
623 | |||
624 | #========================================================================== |
|
624 | #========================================================================== | |
625 | # REPOSITORY ROUTES |
|
625 | # REPOSITORY ROUTES | |
626 | #========================================================================== |
|
626 | #========================================================================== | |
627 |
|
627 | |||
628 | rmap.connect('repo_creating_home', '/{repo_name}/repo_creating', |
|
628 | rmap.connect('repo_creating_home', '/{repo_name}/repo_creating', | |
629 | controller='admin/repos', action='repo_creating', |
|
629 | controller='admin/repos', action='repo_creating', | |
630 | requirements=URL_NAME_REQUIREMENTS) |
|
630 | requirements=URL_NAME_REQUIREMENTS) | |
631 | rmap.connect('repo_check_home', '/{repo_name}/crepo_check', |
|
631 | rmap.connect('repo_check_home', '/{repo_name}/crepo_check', | |
632 | controller='admin/repos', action='repo_check', |
|
632 | controller='admin/repos', action='repo_check', | |
633 | requirements=URL_NAME_REQUIREMENTS) |
|
633 | requirements=URL_NAME_REQUIREMENTS) | |
634 |
|
634 | |||
635 | rmap.connect('repo_stats', '/{repo_name}/repo_stats/{commit_id}', |
|
635 | rmap.connect('repo_stats', '/{repo_name}/repo_stats/{commit_id}', | |
636 | controller='summary', action='repo_stats', |
|
636 | controller='summary', action='repo_stats', | |
637 | conditions={'function': check_repo}, |
|
637 | conditions={'function': check_repo}, | |
638 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
638 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
639 |
|
639 | |||
640 | rmap.connect('repo_refs_data', '/{repo_name}/refs-data', |
|
640 | rmap.connect('repo_refs_data', '/{repo_name}/refs-data', | |
641 | controller='summary', action='repo_refs_data', |
|
641 | controller='summary', action='repo_refs_data', | |
642 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
642 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
643 | rmap.connect('repo_refs_changelog_data', '/{repo_name}/refs-data-changelog', |
|
643 | rmap.connect('repo_refs_changelog_data', '/{repo_name}/refs-data-changelog', | |
644 | controller='summary', action='repo_refs_changelog_data', |
|
644 | controller='summary', action='repo_refs_changelog_data', | |
645 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
645 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
646 | rmap.connect('repo_default_reviewers_data', '/{repo_name}/default-reviewers', |
|
646 | rmap.connect('repo_default_reviewers_data', '/{repo_name}/default-reviewers', | |
647 | controller='summary', action='repo_default_reviewers_data', |
|
647 | controller='summary', action='repo_default_reviewers_data', | |
648 | jsroute=True, requirements=URL_NAME_REQUIREMENTS) |
|
648 | jsroute=True, requirements=URL_NAME_REQUIREMENTS) | |
649 |
|
649 | |||
650 | rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}', |
|
650 | rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}', | |
651 | controller='changeset', revision='tip', |
|
651 | controller='changeset', revision='tip', | |
652 | conditions={'function': check_repo}, |
|
652 | conditions={'function': check_repo}, | |
653 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
653 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
654 | rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}', |
|
654 | rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}', | |
655 | controller='changeset', revision='tip', action='changeset_children', |
|
655 | controller='changeset', revision='tip', action='changeset_children', | |
656 | conditions={'function': check_repo}, |
|
656 | conditions={'function': check_repo}, | |
657 | requirements=URL_NAME_REQUIREMENTS) |
|
657 | requirements=URL_NAME_REQUIREMENTS) | |
658 | rmap.connect('changeset_parents', '/{repo_name}/changeset_parents/{revision}', |
|
658 | rmap.connect('changeset_parents', '/{repo_name}/changeset_parents/{revision}', | |
659 | controller='changeset', revision='tip', action='changeset_parents', |
|
659 | controller='changeset', revision='tip', action='changeset_parents', | |
660 | conditions={'function': check_repo}, |
|
660 | conditions={'function': check_repo}, | |
661 | requirements=URL_NAME_REQUIREMENTS) |
|
661 | requirements=URL_NAME_REQUIREMENTS) | |
662 |
|
662 | |||
663 | # repo edit options |
|
663 | # repo edit options | |
664 | rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields', |
|
664 | rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields', | |
665 | controller='admin/repos', action='edit_fields', |
|
665 | controller='admin/repos', action='edit_fields', | |
666 | conditions={'method': ['GET'], 'function': check_repo}, |
|
666 | conditions={'method': ['GET'], 'function': check_repo}, | |
667 | requirements=URL_NAME_REQUIREMENTS) |
|
667 | requirements=URL_NAME_REQUIREMENTS) | |
668 | rmap.connect('create_repo_fields', '/{repo_name}/settings/fields/new', |
|
668 | rmap.connect('create_repo_fields', '/{repo_name}/settings/fields/new', | |
669 | controller='admin/repos', action='create_repo_field', |
|
669 | controller='admin/repos', action='create_repo_field', | |
670 | conditions={'method': ['PUT'], 'function': check_repo}, |
|
670 | conditions={'method': ['PUT'], 'function': check_repo}, | |
671 | requirements=URL_NAME_REQUIREMENTS) |
|
671 | requirements=URL_NAME_REQUIREMENTS) | |
672 | rmap.connect('delete_repo_fields', '/{repo_name}/settings/fields/{field_id}', |
|
672 | rmap.connect('delete_repo_fields', '/{repo_name}/settings/fields/{field_id}', | |
673 | controller='admin/repos', action='delete_repo_field', |
|
673 | controller='admin/repos', action='delete_repo_field', | |
674 | conditions={'method': ['DELETE'], 'function': check_repo}, |
|
674 | conditions={'method': ['DELETE'], 'function': check_repo}, | |
675 | requirements=URL_NAME_REQUIREMENTS) |
|
675 | requirements=URL_NAME_REQUIREMENTS) | |
676 |
|
676 | |||
677 | rmap.connect('edit_repo_advanced', '/{repo_name}/settings/advanced', |
|
|||
678 | controller='admin/repos', action='edit_advanced', |
|
|||
679 | conditions={'method': ['GET'], 'function': check_repo}, |
|
|||
680 | requirements=URL_NAME_REQUIREMENTS) |
|
|||
681 |
|
||||
682 | rmap.connect('edit_repo_advanced_locking', '/{repo_name}/settings/advanced/locking', |
|
|||
683 | controller='admin/repos', action='edit_advanced_locking', |
|
|||
684 | conditions={'method': ['PUT'], 'function': check_repo}, |
|
|||
685 | requirements=URL_NAME_REQUIREMENTS) |
|
|||
686 | rmap.connect('toggle_locking', '/{repo_name}/settings/advanced/locking_toggle', |
|
677 | rmap.connect('toggle_locking', '/{repo_name}/settings/advanced/locking_toggle', | |
687 | controller='admin/repos', action='toggle_locking', |
|
678 | controller='admin/repos', action='toggle_locking', | |
688 | conditions={'method': ['GET'], 'function': check_repo}, |
|
679 | conditions={'method': ['GET'], 'function': check_repo}, | |
689 | requirements=URL_NAME_REQUIREMENTS) |
|
680 | requirements=URL_NAME_REQUIREMENTS) | |
690 |
|
681 | |||
691 | rmap.connect('edit_repo_advanced_journal', '/{repo_name}/settings/advanced/journal', |
|
|||
692 | controller='admin/repos', action='edit_advanced_journal', |
|
|||
693 | conditions={'method': ['PUT'], 'function': check_repo}, |
|
|||
694 | requirements=URL_NAME_REQUIREMENTS) |
|
|||
695 |
|
||||
696 | rmap.connect('edit_repo_advanced_fork', '/{repo_name}/settings/advanced/fork', |
|
|||
697 | controller='admin/repos', action='edit_advanced_fork', |
|
|||
698 | conditions={'method': ['PUT'], 'function': check_repo}, |
|
|||
699 | requirements=URL_NAME_REQUIREMENTS) |
|
|||
700 |
|
||||
701 | rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote', |
|
682 | rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote', | |
702 | controller='admin/repos', action='edit_remote_form', |
|
683 | controller='admin/repos', action='edit_remote_form', | |
703 | conditions={'method': ['GET'], 'function': check_repo}, |
|
684 | conditions={'method': ['GET'], 'function': check_repo}, | |
704 | requirements=URL_NAME_REQUIREMENTS) |
|
685 | requirements=URL_NAME_REQUIREMENTS) | |
705 | rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote', |
|
686 | rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote', | |
706 | controller='admin/repos', action='edit_remote', |
|
687 | controller='admin/repos', action='edit_remote', | |
707 | conditions={'method': ['PUT'], 'function': check_repo}, |
|
688 | conditions={'method': ['PUT'], 'function': check_repo}, | |
708 | requirements=URL_NAME_REQUIREMENTS) |
|
689 | requirements=URL_NAME_REQUIREMENTS) | |
709 |
|
690 | |||
710 | rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics', |
|
691 | rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics', | |
711 | controller='admin/repos', action='edit_statistics_form', |
|
692 | controller='admin/repos', action='edit_statistics_form', | |
712 | conditions={'method': ['GET'], 'function': check_repo}, |
|
693 | conditions={'method': ['GET'], 'function': check_repo}, | |
713 | requirements=URL_NAME_REQUIREMENTS) |
|
694 | requirements=URL_NAME_REQUIREMENTS) | |
714 | rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics', |
|
695 | rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics', | |
715 | controller='admin/repos', action='edit_statistics', |
|
696 | controller='admin/repos', action='edit_statistics', | |
716 | conditions={'method': ['PUT'], 'function': check_repo}, |
|
697 | conditions={'method': ['PUT'], 'function': check_repo}, | |
717 | requirements=URL_NAME_REQUIREMENTS) |
|
698 | requirements=URL_NAME_REQUIREMENTS) | |
718 | rmap.connect('repo_settings_issuetracker', |
|
699 | rmap.connect('repo_settings_issuetracker', | |
719 | '/{repo_name}/settings/issue-tracker', |
|
700 | '/{repo_name}/settings/issue-tracker', | |
720 | controller='admin/repos', action='repo_issuetracker', |
|
701 | controller='admin/repos', action='repo_issuetracker', | |
721 | conditions={'method': ['GET'], 'function': check_repo}, |
|
702 | conditions={'method': ['GET'], 'function': check_repo}, | |
722 | requirements=URL_NAME_REQUIREMENTS) |
|
703 | requirements=URL_NAME_REQUIREMENTS) | |
723 | rmap.connect('repo_issuetracker_test', |
|
704 | rmap.connect('repo_issuetracker_test', | |
724 | '/{repo_name}/settings/issue-tracker/test', |
|
705 | '/{repo_name}/settings/issue-tracker/test', | |
725 | controller='admin/repos', action='repo_issuetracker_test', |
|
706 | controller='admin/repos', action='repo_issuetracker_test', | |
726 | conditions={'method': ['POST'], 'function': check_repo}, |
|
707 | conditions={'method': ['POST'], 'function': check_repo}, | |
727 | requirements=URL_NAME_REQUIREMENTS) |
|
708 | requirements=URL_NAME_REQUIREMENTS) | |
728 | rmap.connect('repo_issuetracker_delete', |
|
709 | rmap.connect('repo_issuetracker_delete', | |
729 | '/{repo_name}/settings/issue-tracker/delete', |
|
710 | '/{repo_name}/settings/issue-tracker/delete', | |
730 | controller='admin/repos', action='repo_issuetracker_delete', |
|
711 | controller='admin/repos', action='repo_issuetracker_delete', | |
731 | conditions={'method': ['DELETE'], 'function': check_repo}, |
|
712 | conditions={'method': ['DELETE'], 'function': check_repo}, | |
732 | requirements=URL_NAME_REQUIREMENTS) |
|
713 | requirements=URL_NAME_REQUIREMENTS) | |
733 | rmap.connect('repo_issuetracker_save', |
|
714 | rmap.connect('repo_issuetracker_save', | |
734 | '/{repo_name}/settings/issue-tracker/save', |
|
715 | '/{repo_name}/settings/issue-tracker/save', | |
735 | controller='admin/repos', action='repo_issuetracker_save', |
|
716 | controller='admin/repos', action='repo_issuetracker_save', | |
736 | conditions={'method': ['POST'], 'function': check_repo}, |
|
717 | conditions={'method': ['POST'], 'function': check_repo}, | |
737 | requirements=URL_NAME_REQUIREMENTS) |
|
718 | requirements=URL_NAME_REQUIREMENTS) | |
738 | rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs', |
|
719 | rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs', | |
739 | controller='admin/repos', action='repo_settings_vcs_update', |
|
720 | controller='admin/repos', action='repo_settings_vcs_update', | |
740 | conditions={'method': ['POST'], 'function': check_repo}, |
|
721 | conditions={'method': ['POST'], 'function': check_repo}, | |
741 | requirements=URL_NAME_REQUIREMENTS) |
|
722 | requirements=URL_NAME_REQUIREMENTS) | |
742 | rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs', |
|
723 | rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs', | |
743 | controller='admin/repos', action='repo_settings_vcs', |
|
724 | controller='admin/repos', action='repo_settings_vcs', | |
744 | conditions={'method': ['GET'], 'function': check_repo}, |
|
725 | conditions={'method': ['GET'], 'function': check_repo}, | |
745 | requirements=URL_NAME_REQUIREMENTS) |
|
726 | requirements=URL_NAME_REQUIREMENTS) | |
746 | rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs', |
|
727 | rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs', | |
747 | controller='admin/repos', action='repo_delete_svn_pattern', |
|
728 | controller='admin/repos', action='repo_delete_svn_pattern', | |
748 | conditions={'method': ['DELETE'], 'function': check_repo}, |
|
729 | conditions={'method': ['DELETE'], 'function': check_repo}, | |
749 | requirements=URL_NAME_REQUIREMENTS) |
|
730 | requirements=URL_NAME_REQUIREMENTS) | |
750 | rmap.connect('repo_pullrequest_settings', '/{repo_name}/settings/pullrequest', |
|
731 | rmap.connect('repo_pullrequest_settings', '/{repo_name}/settings/pullrequest', | |
751 | controller='admin/repos', action='repo_settings_pullrequest', |
|
732 | controller='admin/repos', action='repo_settings_pullrequest', | |
752 | conditions={'method': ['GET', 'POST'], 'function': check_repo}, |
|
733 | conditions={'method': ['GET', 'POST'], 'function': check_repo}, | |
753 | requirements=URL_NAME_REQUIREMENTS) |
|
734 | requirements=URL_NAME_REQUIREMENTS) | |
754 |
|
735 | |||
755 | # still working url for backward compat. |
|
736 | # still working url for backward compat. | |
756 | rmap.connect('raw_changeset_home_depraced', |
|
737 | rmap.connect('raw_changeset_home_depraced', | |
757 | '/{repo_name}/raw-changeset/{revision}', |
|
738 | '/{repo_name}/raw-changeset/{revision}', | |
758 | controller='changeset', action='changeset_raw', |
|
739 | controller='changeset', action='changeset_raw', | |
759 | revision='tip', conditions={'function': check_repo}, |
|
740 | revision='tip', conditions={'function': check_repo}, | |
760 | requirements=URL_NAME_REQUIREMENTS) |
|
741 | requirements=URL_NAME_REQUIREMENTS) | |
761 |
|
742 | |||
762 | # new URLs |
|
743 | # new URLs | |
763 | rmap.connect('changeset_raw_home', |
|
744 | rmap.connect('changeset_raw_home', | |
764 | '/{repo_name}/changeset-diff/{revision}', |
|
745 | '/{repo_name}/changeset-diff/{revision}', | |
765 | controller='changeset', action='changeset_raw', |
|
746 | controller='changeset', action='changeset_raw', | |
766 | revision='tip', conditions={'function': check_repo}, |
|
747 | revision='tip', conditions={'function': check_repo}, | |
767 | requirements=URL_NAME_REQUIREMENTS) |
|
748 | requirements=URL_NAME_REQUIREMENTS) | |
768 |
|
749 | |||
769 | rmap.connect('changeset_patch_home', |
|
750 | rmap.connect('changeset_patch_home', | |
770 | '/{repo_name}/changeset-patch/{revision}', |
|
751 | '/{repo_name}/changeset-patch/{revision}', | |
771 | controller='changeset', action='changeset_patch', |
|
752 | controller='changeset', action='changeset_patch', | |
772 | revision='tip', conditions={'function': check_repo}, |
|
753 | revision='tip', conditions={'function': check_repo}, | |
773 | requirements=URL_NAME_REQUIREMENTS) |
|
754 | requirements=URL_NAME_REQUIREMENTS) | |
774 |
|
755 | |||
775 | rmap.connect('changeset_download_home', |
|
756 | rmap.connect('changeset_download_home', | |
776 | '/{repo_name}/changeset-download/{revision}', |
|
757 | '/{repo_name}/changeset-download/{revision}', | |
777 | controller='changeset', action='changeset_download', |
|
758 | controller='changeset', action='changeset_download', | |
778 | revision='tip', conditions={'function': check_repo}, |
|
759 | revision='tip', conditions={'function': check_repo}, | |
779 | requirements=URL_NAME_REQUIREMENTS) |
|
760 | requirements=URL_NAME_REQUIREMENTS) | |
780 |
|
761 | |||
781 | rmap.connect('changeset_comment', |
|
762 | rmap.connect('changeset_comment', | |
782 | '/{repo_name}/changeset/{revision}/comment', jsroute=True, |
|
763 | '/{repo_name}/changeset/{revision}/comment', jsroute=True, | |
783 | controller='changeset', revision='tip', action='comment', |
|
764 | controller='changeset', revision='tip', action='comment', | |
784 | conditions={'function': check_repo}, |
|
765 | conditions={'function': check_repo}, | |
785 | requirements=URL_NAME_REQUIREMENTS) |
|
766 | requirements=URL_NAME_REQUIREMENTS) | |
786 |
|
767 | |||
787 | rmap.connect('changeset_comment_preview', |
|
768 | rmap.connect('changeset_comment_preview', | |
788 | '/{repo_name}/changeset/comment/preview', jsroute=True, |
|
769 | '/{repo_name}/changeset/comment/preview', jsroute=True, | |
789 | controller='changeset', action='preview_comment', |
|
770 | controller='changeset', action='preview_comment', | |
790 | conditions={'function': check_repo, 'method': ['POST']}, |
|
771 | conditions={'function': check_repo, 'method': ['POST']}, | |
791 | requirements=URL_NAME_REQUIREMENTS) |
|
772 | requirements=URL_NAME_REQUIREMENTS) | |
792 |
|
773 | |||
793 | rmap.connect('changeset_comment_delete', |
|
774 | rmap.connect('changeset_comment_delete', | |
794 | '/{repo_name}/changeset/comment/{comment_id}/delete', |
|
775 | '/{repo_name}/changeset/comment/{comment_id}/delete', | |
795 | controller='changeset', action='delete_comment', |
|
776 | controller='changeset', action='delete_comment', | |
796 | conditions={'function': check_repo, 'method': ['DELETE']}, |
|
777 | conditions={'function': check_repo, 'method': ['DELETE']}, | |
797 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
778 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
798 |
|
779 | |||
799 | rmap.connect('changeset_info', '/{repo_name}/changeset_info/{revision}', |
|
780 | rmap.connect('changeset_info', '/{repo_name}/changeset_info/{revision}', | |
800 | controller='changeset', action='changeset_info', |
|
781 | controller='changeset', action='changeset_info', | |
801 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
782 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
802 |
|
783 | |||
803 | rmap.connect('compare_home', |
|
784 | rmap.connect('compare_home', | |
804 | '/{repo_name}/compare', |
|
785 | '/{repo_name}/compare', | |
805 | controller='compare', action='index', |
|
786 | controller='compare', action='index', | |
806 | conditions={'function': check_repo}, |
|
787 | conditions={'function': check_repo}, | |
807 | requirements=URL_NAME_REQUIREMENTS) |
|
788 | requirements=URL_NAME_REQUIREMENTS) | |
808 |
|
789 | |||
809 | rmap.connect('compare_url', |
|
790 | rmap.connect('compare_url', | |
810 | '/{repo_name}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}', |
|
791 | '/{repo_name}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}', | |
811 | controller='compare', action='compare', |
|
792 | controller='compare', action='compare', | |
812 | conditions={'function': check_repo}, |
|
793 | conditions={'function': check_repo}, | |
813 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
794 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
814 |
|
795 | |||
815 | rmap.connect('pullrequest_home', |
|
796 | rmap.connect('pullrequest_home', | |
816 | '/{repo_name}/pull-request/new', controller='pullrequests', |
|
797 | '/{repo_name}/pull-request/new', controller='pullrequests', | |
817 | action='index', conditions={'function': check_repo, |
|
798 | action='index', conditions={'function': check_repo, | |
818 | 'method': ['GET']}, |
|
799 | 'method': ['GET']}, | |
819 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
800 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
820 |
|
801 | |||
821 | rmap.connect('pullrequest', |
|
802 | rmap.connect('pullrequest', | |
822 | '/{repo_name}/pull-request/new', controller='pullrequests', |
|
803 | '/{repo_name}/pull-request/new', controller='pullrequests', | |
823 | action='create', conditions={'function': check_repo, |
|
804 | action='create', conditions={'function': check_repo, | |
824 | 'method': ['POST']}, |
|
805 | 'method': ['POST']}, | |
825 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
806 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
826 |
|
807 | |||
827 | rmap.connect('pullrequest_repo_refs', |
|
808 | rmap.connect('pullrequest_repo_refs', | |
828 | '/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}', |
|
809 | '/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}', | |
829 | controller='pullrequests', |
|
810 | controller='pullrequests', | |
830 | action='get_repo_refs', |
|
811 | action='get_repo_refs', | |
831 | conditions={'function': check_repo, 'method': ['GET']}, |
|
812 | conditions={'function': check_repo, 'method': ['GET']}, | |
832 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
813 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
833 |
|
814 | |||
834 | rmap.connect('pullrequest_repo_destinations', |
|
815 | rmap.connect('pullrequest_repo_destinations', | |
835 | '/{repo_name}/pull-request/repo-destinations', |
|
816 | '/{repo_name}/pull-request/repo-destinations', | |
836 | controller='pullrequests', |
|
817 | controller='pullrequests', | |
837 | action='get_repo_destinations', |
|
818 | action='get_repo_destinations', | |
838 | conditions={'function': check_repo, 'method': ['GET']}, |
|
819 | conditions={'function': check_repo, 'method': ['GET']}, | |
839 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
820 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
840 |
|
821 | |||
841 | rmap.connect('pullrequest_show', |
|
822 | rmap.connect('pullrequest_show', | |
842 | '/{repo_name}/pull-request/{pull_request_id}', |
|
823 | '/{repo_name}/pull-request/{pull_request_id}', | |
843 | controller='pullrequests', |
|
824 | controller='pullrequests', | |
844 | action='show', conditions={'function': check_repo, |
|
825 | action='show', conditions={'function': check_repo, | |
845 | 'method': ['GET']}, |
|
826 | 'method': ['GET']}, | |
846 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
827 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
847 |
|
828 | |||
848 | rmap.connect('pullrequest_update', |
|
829 | rmap.connect('pullrequest_update', | |
849 | '/{repo_name}/pull-request/{pull_request_id}', |
|
830 | '/{repo_name}/pull-request/{pull_request_id}', | |
850 | controller='pullrequests', |
|
831 | controller='pullrequests', | |
851 | action='update', conditions={'function': check_repo, |
|
832 | action='update', conditions={'function': check_repo, | |
852 | 'method': ['PUT']}, |
|
833 | 'method': ['PUT']}, | |
853 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
834 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
854 |
|
835 | |||
855 | rmap.connect('pullrequest_merge', |
|
836 | rmap.connect('pullrequest_merge', | |
856 | '/{repo_name}/pull-request/{pull_request_id}', |
|
837 | '/{repo_name}/pull-request/{pull_request_id}', | |
857 | controller='pullrequests', |
|
838 | controller='pullrequests', | |
858 | action='merge', conditions={'function': check_repo, |
|
839 | action='merge', conditions={'function': check_repo, | |
859 | 'method': ['POST']}, |
|
840 | 'method': ['POST']}, | |
860 | requirements=URL_NAME_REQUIREMENTS) |
|
841 | requirements=URL_NAME_REQUIREMENTS) | |
861 |
|
842 | |||
862 | rmap.connect('pullrequest_delete', |
|
843 | rmap.connect('pullrequest_delete', | |
863 | '/{repo_name}/pull-request/{pull_request_id}', |
|
844 | '/{repo_name}/pull-request/{pull_request_id}', | |
864 | controller='pullrequests', |
|
845 | controller='pullrequests', | |
865 | action='delete', conditions={'function': check_repo, |
|
846 | action='delete', conditions={'function': check_repo, | |
866 | 'method': ['DELETE']}, |
|
847 | 'method': ['DELETE']}, | |
867 | requirements=URL_NAME_REQUIREMENTS) |
|
848 | requirements=URL_NAME_REQUIREMENTS) | |
868 |
|
849 | |||
869 | rmap.connect('pullrequest_show_all', |
|
850 | rmap.connect('pullrequest_show_all', | |
870 | '/{repo_name}/pull-request', |
|
851 | '/{repo_name}/pull-request', | |
871 | controller='pullrequests', |
|
852 | controller='pullrequests', | |
872 | action='show_all', conditions={'function': check_repo, |
|
853 | action='show_all', conditions={'function': check_repo, | |
873 | 'method': ['GET']}, |
|
854 | 'method': ['GET']}, | |
874 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
855 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
875 |
|
856 | |||
876 | rmap.connect('pullrequest_comment', |
|
857 | rmap.connect('pullrequest_comment', | |
877 | '/{repo_name}/pull-request-comment/{pull_request_id}', |
|
858 | '/{repo_name}/pull-request-comment/{pull_request_id}', | |
878 | controller='pullrequests', |
|
859 | controller='pullrequests', | |
879 | action='comment', conditions={'function': check_repo, |
|
860 | action='comment', conditions={'function': check_repo, | |
880 | 'method': ['POST']}, |
|
861 | 'method': ['POST']}, | |
881 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
862 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
882 |
|
863 | |||
883 | rmap.connect('pullrequest_comment_delete', |
|
864 | rmap.connect('pullrequest_comment_delete', | |
884 | '/{repo_name}/pull-request-comment/{comment_id}/delete', |
|
865 | '/{repo_name}/pull-request-comment/{comment_id}/delete', | |
885 | controller='pullrequests', action='delete_comment', |
|
866 | controller='pullrequests', action='delete_comment', | |
886 | conditions={'function': check_repo, 'method': ['DELETE']}, |
|
867 | conditions={'function': check_repo, 'method': ['DELETE']}, | |
887 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
868 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
888 |
|
869 | |||
889 | rmap.connect('summary_home_explicit', '/{repo_name}/summary', |
|
870 | rmap.connect('summary_home_explicit', '/{repo_name}/summary', | |
890 | controller='summary', conditions={'function': check_repo}, |
|
871 | controller='summary', conditions={'function': check_repo}, | |
891 | requirements=URL_NAME_REQUIREMENTS) |
|
872 | requirements=URL_NAME_REQUIREMENTS) | |
892 |
|
873 | |||
893 | rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True, |
|
874 | rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True, | |
894 | controller='changelog', conditions={'function': check_repo}, |
|
875 | controller='changelog', conditions={'function': check_repo}, | |
895 | requirements=URL_NAME_REQUIREMENTS) |
|
876 | requirements=URL_NAME_REQUIREMENTS) | |
896 |
|
877 | |||
897 | rmap.connect('changelog_summary_home', '/{repo_name}/changelog_summary', |
|
878 | rmap.connect('changelog_summary_home', '/{repo_name}/changelog_summary', | |
898 | controller='changelog', action='changelog_summary', |
|
879 | controller='changelog', action='changelog_summary', | |
899 | conditions={'function': check_repo}, |
|
880 | conditions={'function': check_repo}, | |
900 | requirements=URL_NAME_REQUIREMENTS) |
|
881 | requirements=URL_NAME_REQUIREMENTS) | |
901 |
|
882 | |||
902 | rmap.connect('changelog_file_home', |
|
883 | rmap.connect('changelog_file_home', | |
903 | '/{repo_name}/changelog/{revision}/{f_path}', |
|
884 | '/{repo_name}/changelog/{revision}/{f_path}', | |
904 | controller='changelog', f_path=None, |
|
885 | controller='changelog', f_path=None, | |
905 | conditions={'function': check_repo}, |
|
886 | conditions={'function': check_repo}, | |
906 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
887 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
907 |
|
888 | |||
908 | rmap.connect('changelog_elements', '/{repo_name}/changelog_details', |
|
889 | rmap.connect('changelog_elements', '/{repo_name}/changelog_details', | |
909 | controller='changelog', action='changelog_elements', |
|
890 | controller='changelog', action='changelog_elements', | |
910 | conditions={'function': check_repo}, |
|
891 | conditions={'function': check_repo}, | |
911 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
892 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
912 |
|
893 | |||
913 | rmap.connect('files_home', '/{repo_name}/files/{revision}/{f_path}', |
|
894 | rmap.connect('files_home', '/{repo_name}/files/{revision}/{f_path}', | |
914 | controller='files', revision='tip', f_path='', |
|
895 | controller='files', revision='tip', f_path='', | |
915 | conditions={'function': check_repo}, |
|
896 | conditions={'function': check_repo}, | |
916 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
897 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
917 |
|
898 | |||
918 | rmap.connect('files_home_simple_catchrev', |
|
899 | rmap.connect('files_home_simple_catchrev', | |
919 | '/{repo_name}/files/{revision}', |
|
900 | '/{repo_name}/files/{revision}', | |
920 | controller='files', revision='tip', f_path='', |
|
901 | controller='files', revision='tip', f_path='', | |
921 | conditions={'function': check_repo}, |
|
902 | conditions={'function': check_repo}, | |
922 | requirements=URL_NAME_REQUIREMENTS) |
|
903 | requirements=URL_NAME_REQUIREMENTS) | |
923 |
|
904 | |||
924 | rmap.connect('files_home_simple_catchall', |
|
905 | rmap.connect('files_home_simple_catchall', | |
925 | '/{repo_name}/files', |
|
906 | '/{repo_name}/files', | |
926 | controller='files', revision='tip', f_path='', |
|
907 | controller='files', revision='tip', f_path='', | |
927 | conditions={'function': check_repo}, |
|
908 | conditions={'function': check_repo}, | |
928 | requirements=URL_NAME_REQUIREMENTS) |
|
909 | requirements=URL_NAME_REQUIREMENTS) | |
929 |
|
910 | |||
930 | rmap.connect('files_history_home', |
|
911 | rmap.connect('files_history_home', | |
931 | '/{repo_name}/history/{revision}/{f_path}', |
|
912 | '/{repo_name}/history/{revision}/{f_path}', | |
932 | controller='files', action='history', revision='tip', f_path='', |
|
913 | controller='files', action='history', revision='tip', f_path='', | |
933 | conditions={'function': check_repo}, |
|
914 | conditions={'function': check_repo}, | |
934 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
915 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
935 |
|
916 | |||
936 | rmap.connect('files_authors_home', |
|
917 | rmap.connect('files_authors_home', | |
937 | '/{repo_name}/authors/{revision}/{f_path}', |
|
918 | '/{repo_name}/authors/{revision}/{f_path}', | |
938 | controller='files', action='authors', revision='tip', f_path='', |
|
919 | controller='files', action='authors', revision='tip', f_path='', | |
939 | conditions={'function': check_repo}, |
|
920 | conditions={'function': check_repo}, | |
940 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
921 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
941 |
|
922 | |||
942 | rmap.connect('files_diff_home', '/{repo_name}/diff/{f_path}', |
|
923 | rmap.connect('files_diff_home', '/{repo_name}/diff/{f_path}', | |
943 | controller='files', action='diff', f_path='', |
|
924 | controller='files', action='diff', f_path='', | |
944 | conditions={'function': check_repo}, |
|
925 | conditions={'function': check_repo}, | |
945 | requirements=URL_NAME_REQUIREMENTS) |
|
926 | requirements=URL_NAME_REQUIREMENTS) | |
946 |
|
927 | |||
947 | rmap.connect('files_diff_2way_home', |
|
928 | rmap.connect('files_diff_2way_home', | |
948 | '/{repo_name}/diff-2way/{f_path}', |
|
929 | '/{repo_name}/diff-2way/{f_path}', | |
949 | controller='files', action='diff_2way', f_path='', |
|
930 | controller='files', action='diff_2way', f_path='', | |
950 | conditions={'function': check_repo}, |
|
931 | conditions={'function': check_repo}, | |
951 | requirements=URL_NAME_REQUIREMENTS) |
|
932 | requirements=URL_NAME_REQUIREMENTS) | |
952 |
|
933 | |||
953 | rmap.connect('files_rawfile_home', |
|
934 | rmap.connect('files_rawfile_home', | |
954 | '/{repo_name}/rawfile/{revision}/{f_path}', |
|
935 | '/{repo_name}/rawfile/{revision}/{f_path}', | |
955 | controller='files', action='rawfile', revision='tip', |
|
936 | controller='files', action='rawfile', revision='tip', | |
956 | f_path='', conditions={'function': check_repo}, |
|
937 | f_path='', conditions={'function': check_repo}, | |
957 | requirements=URL_NAME_REQUIREMENTS) |
|
938 | requirements=URL_NAME_REQUIREMENTS) | |
958 |
|
939 | |||
959 | rmap.connect('files_raw_home', |
|
940 | rmap.connect('files_raw_home', | |
960 | '/{repo_name}/raw/{revision}/{f_path}', |
|
941 | '/{repo_name}/raw/{revision}/{f_path}', | |
961 | controller='files', action='raw', revision='tip', f_path='', |
|
942 | controller='files', action='raw', revision='tip', f_path='', | |
962 | conditions={'function': check_repo}, |
|
943 | conditions={'function': check_repo}, | |
963 | requirements=URL_NAME_REQUIREMENTS) |
|
944 | requirements=URL_NAME_REQUIREMENTS) | |
964 |
|
945 | |||
965 | rmap.connect('files_render_home', |
|
946 | rmap.connect('files_render_home', | |
966 | '/{repo_name}/render/{revision}/{f_path}', |
|
947 | '/{repo_name}/render/{revision}/{f_path}', | |
967 | controller='files', action='index', revision='tip', f_path='', |
|
948 | controller='files', action='index', revision='tip', f_path='', | |
968 | rendered=True, conditions={'function': check_repo}, |
|
949 | rendered=True, conditions={'function': check_repo}, | |
969 | requirements=URL_NAME_REQUIREMENTS) |
|
950 | requirements=URL_NAME_REQUIREMENTS) | |
970 |
|
951 | |||
971 | rmap.connect('files_annotate_home', |
|
952 | rmap.connect('files_annotate_home', | |
972 | '/{repo_name}/annotate/{revision}/{f_path}', |
|
953 | '/{repo_name}/annotate/{revision}/{f_path}', | |
973 | controller='files', action='index', revision='tip', |
|
954 | controller='files', action='index', revision='tip', | |
974 | f_path='', annotate=True, conditions={'function': check_repo}, |
|
955 | f_path='', annotate=True, conditions={'function': check_repo}, | |
975 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
956 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
976 |
|
957 | |||
977 | rmap.connect('files_annotate_previous', |
|
958 | rmap.connect('files_annotate_previous', | |
978 | '/{repo_name}/annotate-previous/{revision}/{f_path}', |
|
959 | '/{repo_name}/annotate-previous/{revision}/{f_path}', | |
979 | controller='files', action='annotate_previous', revision='tip', |
|
960 | controller='files', action='annotate_previous', revision='tip', | |
980 | f_path='', annotate=True, conditions={'function': check_repo}, |
|
961 | f_path='', annotate=True, conditions={'function': check_repo}, | |
981 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
962 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
982 |
|
963 | |||
983 | rmap.connect('files_edit', |
|
964 | rmap.connect('files_edit', | |
984 | '/{repo_name}/edit/{revision}/{f_path}', |
|
965 | '/{repo_name}/edit/{revision}/{f_path}', | |
985 | controller='files', action='edit', revision='tip', |
|
966 | controller='files', action='edit', revision='tip', | |
986 | f_path='', |
|
967 | f_path='', | |
987 | conditions={'function': check_repo, 'method': ['POST']}, |
|
968 | conditions={'function': check_repo, 'method': ['POST']}, | |
988 | requirements=URL_NAME_REQUIREMENTS) |
|
969 | requirements=URL_NAME_REQUIREMENTS) | |
989 |
|
970 | |||
990 | rmap.connect('files_edit_home', |
|
971 | rmap.connect('files_edit_home', | |
991 | '/{repo_name}/edit/{revision}/{f_path}', |
|
972 | '/{repo_name}/edit/{revision}/{f_path}', | |
992 | controller='files', action='edit_home', revision='tip', |
|
973 | controller='files', action='edit_home', revision='tip', | |
993 | f_path='', conditions={'function': check_repo}, |
|
974 | f_path='', conditions={'function': check_repo}, | |
994 | requirements=URL_NAME_REQUIREMENTS) |
|
975 | requirements=URL_NAME_REQUIREMENTS) | |
995 |
|
976 | |||
996 | rmap.connect('files_add', |
|
977 | rmap.connect('files_add', | |
997 | '/{repo_name}/add/{revision}/{f_path}', |
|
978 | '/{repo_name}/add/{revision}/{f_path}', | |
998 | controller='files', action='add', revision='tip', |
|
979 | controller='files', action='add', revision='tip', | |
999 | f_path='', |
|
980 | f_path='', | |
1000 | conditions={'function': check_repo, 'method': ['POST']}, |
|
981 | conditions={'function': check_repo, 'method': ['POST']}, | |
1001 | requirements=URL_NAME_REQUIREMENTS) |
|
982 | requirements=URL_NAME_REQUIREMENTS) | |
1002 |
|
983 | |||
1003 | rmap.connect('files_add_home', |
|
984 | rmap.connect('files_add_home', | |
1004 | '/{repo_name}/add/{revision}/{f_path}', |
|
985 | '/{repo_name}/add/{revision}/{f_path}', | |
1005 | controller='files', action='add_home', revision='tip', |
|
986 | controller='files', action='add_home', revision='tip', | |
1006 | f_path='', conditions={'function': check_repo}, |
|
987 | f_path='', conditions={'function': check_repo}, | |
1007 | requirements=URL_NAME_REQUIREMENTS) |
|
988 | requirements=URL_NAME_REQUIREMENTS) | |
1008 |
|
989 | |||
1009 | rmap.connect('files_delete', |
|
990 | rmap.connect('files_delete', | |
1010 | '/{repo_name}/delete/{revision}/{f_path}', |
|
991 | '/{repo_name}/delete/{revision}/{f_path}', | |
1011 | controller='files', action='delete', revision='tip', |
|
992 | controller='files', action='delete', revision='tip', | |
1012 | f_path='', |
|
993 | f_path='', | |
1013 | conditions={'function': check_repo, 'method': ['POST']}, |
|
994 | conditions={'function': check_repo, 'method': ['POST']}, | |
1014 | requirements=URL_NAME_REQUIREMENTS) |
|
995 | requirements=URL_NAME_REQUIREMENTS) | |
1015 |
|
996 | |||
1016 | rmap.connect('files_delete_home', |
|
997 | rmap.connect('files_delete_home', | |
1017 | '/{repo_name}/delete/{revision}/{f_path}', |
|
998 | '/{repo_name}/delete/{revision}/{f_path}', | |
1018 | controller='files', action='delete_home', revision='tip', |
|
999 | controller='files', action='delete_home', revision='tip', | |
1019 | f_path='', conditions={'function': check_repo}, |
|
1000 | f_path='', conditions={'function': check_repo}, | |
1020 | requirements=URL_NAME_REQUIREMENTS) |
|
1001 | requirements=URL_NAME_REQUIREMENTS) | |
1021 |
|
1002 | |||
1022 | rmap.connect('files_archive_home', '/{repo_name}/archive/{fname}', |
|
1003 | rmap.connect('files_archive_home', '/{repo_name}/archive/{fname}', | |
1023 | controller='files', action='archivefile', |
|
1004 | controller='files', action='archivefile', | |
1024 | conditions={'function': check_repo}, |
|
1005 | conditions={'function': check_repo}, | |
1025 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
1006 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
1026 |
|
1007 | |||
1027 | rmap.connect('files_nodelist_home', |
|
1008 | rmap.connect('files_nodelist_home', | |
1028 | '/{repo_name}/nodelist/{revision}/{f_path}', |
|
1009 | '/{repo_name}/nodelist/{revision}/{f_path}', | |
1029 | controller='files', action='nodelist', |
|
1010 | controller='files', action='nodelist', | |
1030 | conditions={'function': check_repo}, |
|
1011 | conditions={'function': check_repo}, | |
1031 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
1012 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
1032 |
|
1013 | |||
1033 | rmap.connect('files_nodetree_full', |
|
1014 | rmap.connect('files_nodetree_full', | |
1034 | '/{repo_name}/nodetree_full/{commit_id}/{f_path}', |
|
1015 | '/{repo_name}/nodetree_full/{commit_id}/{f_path}', | |
1035 | controller='files', action='nodetree_full', |
|
1016 | controller='files', action='nodetree_full', | |
1036 | conditions={'function': check_repo}, |
|
1017 | conditions={'function': check_repo}, | |
1037 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) |
|
1018 | requirements=URL_NAME_REQUIREMENTS, jsroute=True) | |
1038 |
|
1019 | |||
1039 | rmap.connect('repo_fork_create_home', '/{repo_name}/fork', |
|
1020 | rmap.connect('repo_fork_create_home', '/{repo_name}/fork', | |
1040 | controller='forks', action='fork_create', |
|
1021 | controller='forks', action='fork_create', | |
1041 | conditions={'function': check_repo, 'method': ['POST']}, |
|
1022 | conditions={'function': check_repo, 'method': ['POST']}, | |
1042 | requirements=URL_NAME_REQUIREMENTS) |
|
1023 | requirements=URL_NAME_REQUIREMENTS) | |
1043 |
|
1024 | |||
1044 | rmap.connect('repo_fork_home', '/{repo_name}/fork', |
|
1025 | rmap.connect('repo_fork_home', '/{repo_name}/fork', | |
1045 | controller='forks', action='fork', |
|
1026 | controller='forks', action='fork', | |
1046 | conditions={'function': check_repo}, |
|
1027 | conditions={'function': check_repo}, | |
1047 | requirements=URL_NAME_REQUIREMENTS) |
|
1028 | requirements=URL_NAME_REQUIREMENTS) | |
1048 |
|
1029 | |||
1049 | rmap.connect('repo_forks_home', '/{repo_name}/forks', |
|
1030 | rmap.connect('repo_forks_home', '/{repo_name}/forks', | |
1050 | controller='forks', action='forks', |
|
1031 | controller='forks', action='forks', | |
1051 | conditions={'function': check_repo}, |
|
1032 | conditions={'function': check_repo}, | |
1052 | requirements=URL_NAME_REQUIREMENTS) |
|
1033 | requirements=URL_NAME_REQUIREMENTS) | |
1053 |
|
1034 | |||
1054 | # must be here for proper group/repo catching pattern |
|
1035 | # must be here for proper group/repo catching pattern | |
1055 | _connect_with_slash( |
|
1036 | _connect_with_slash( | |
1056 | rmap, 'repo_group_home', '/{group_name}', |
|
1037 | rmap, 'repo_group_home', '/{group_name}', | |
1057 | controller='home', action='index_repo_group', |
|
1038 | controller='home', action='index_repo_group', | |
1058 | conditions={'function': check_group}, |
|
1039 | conditions={'function': check_group}, | |
1059 | requirements=URL_NAME_REQUIREMENTS) |
|
1040 | requirements=URL_NAME_REQUIREMENTS) | |
1060 |
|
1041 | |||
1061 | # catch all, at the end |
|
1042 | # catch all, at the end | |
1062 | _connect_with_slash( |
|
1043 | _connect_with_slash( | |
1063 | rmap, 'summary_home', '/{repo_name}', jsroute=True, |
|
1044 | rmap, 'summary_home', '/{repo_name}', jsroute=True, | |
1064 | controller='summary', action='index', |
|
1045 | controller='summary', action='index', | |
1065 | conditions={'function': check_repo}, |
|
1046 | conditions={'function': check_repo}, | |
1066 | requirements=URL_NAME_REQUIREMENTS) |
|
1047 | requirements=URL_NAME_REQUIREMENTS) | |
1067 |
|
1048 | |||
1068 | return rmap |
|
1049 | return rmap | |
1069 |
|
1050 | |||
1070 |
|
1051 | |||
1071 | def _connect_with_slash(mapper, name, path, *args, **kwargs): |
|
1052 | def _connect_with_slash(mapper, name, path, *args, **kwargs): | |
1072 | """ |
|
1053 | """ | |
1073 | Connect a route with an optional trailing slash in `path`. |
|
1054 | Connect a route with an optional trailing slash in `path`. | |
1074 | """ |
|
1055 | """ | |
1075 | mapper.connect(name + '_slash', path + '/', *args, **kwargs) |
|
1056 | mapper.connect(name + '_slash', path + '/', *args, **kwargs) | |
1076 | mapper.connect(name, path, *args, **kwargs) |
|
1057 | mapper.connect(name, path, *args, **kwargs) |
@@ -1,754 +1,610 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 |
|
2 | |||
3 | # Copyright (C) 2013-2017 RhodeCode GmbH |
|
3 | # Copyright (C) 2013-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 | """ |
|
22 | """ | |
23 | Repositories controller for RhodeCode |
|
23 | Repositories controller for RhodeCode | |
24 | """ |
|
24 | """ | |
25 |
|
25 | |||
26 | import logging |
|
26 | import logging | |
27 | import traceback |
|
27 | import traceback | |
28 |
|
28 | |||
29 | import formencode |
|
29 | import formencode | |
30 | from formencode import htmlfill |
|
30 | from formencode import htmlfill | |
31 | from pylons import request, tmpl_context as c, url |
|
31 | from pylons import request, tmpl_context as c, url | |
32 | from pylons.controllers.util import redirect |
|
32 | from pylons.controllers.util import redirect | |
33 | from pylons.i18n.translation import _ |
|
33 | from pylons.i18n.translation import _ | |
34 | from webob.exc import HTTPForbidden, HTTPNotFound, HTTPBadRequest |
|
34 | from webob.exc import HTTPForbidden, HTTPNotFound, HTTPBadRequest | |
35 |
|
35 | |||
36 | import rhodecode |
|
36 | import rhodecode | |
37 | from rhodecode.lib import auth, helpers as h |
|
37 | from rhodecode.lib import auth, helpers as h | |
38 | from rhodecode.lib.auth import ( |
|
38 | from rhodecode.lib.auth import ( | |
39 | LoginRequired, HasPermissionAllDecorator, |
|
39 | LoginRequired, HasPermissionAllDecorator, | |
40 | HasRepoPermissionAllDecorator, NotAnonymous, HasPermissionAny, |
|
40 | HasRepoPermissionAllDecorator, NotAnonymous, HasPermissionAny, | |
41 | HasRepoGroupPermissionAny, HasRepoPermissionAnyDecorator) |
|
41 | HasRepoGroupPermissionAny, HasRepoPermissionAnyDecorator) | |
42 | from rhodecode.lib.base import BaseRepoController, render |
|
42 | from rhodecode.lib.base import BaseRepoController, render | |
43 | from rhodecode.lib.ext_json import json |
|
43 | from rhodecode.lib.ext_json import json | |
44 | from rhodecode.lib.exceptions import AttachedForksError |
|
44 | from rhodecode.lib.exceptions import AttachedForksError | |
45 | from rhodecode.lib.utils import action_logger, repo_name_slug, jsonify |
|
45 | from rhodecode.lib.utils import action_logger, repo_name_slug, jsonify | |
46 | from rhodecode.lib.utils2 import safe_int, str2bool |
|
46 | from rhodecode.lib.utils2 import safe_int, str2bool | |
47 | from rhodecode.lib.vcs import RepositoryError |
|
47 | from rhodecode.lib.vcs import RepositoryError | |
48 | from rhodecode.model.db import ( |
|
48 | from rhodecode.model.db import ( | |
49 | User, Repository, UserFollowing, RepoGroup, RepositoryField) |
|
49 | User, Repository, UserFollowing, RepoGroup, RepositoryField) | |
50 | from rhodecode.model.forms import ( |
|
50 | from rhodecode.model.forms import ( | |
51 | RepoForm, RepoFieldForm, RepoPermsForm, RepoVcsSettingsForm, |
|
51 | RepoForm, RepoFieldForm, RepoPermsForm, RepoVcsSettingsForm, | |
52 | IssueTrackerPatternsForm) |
|
52 | IssueTrackerPatternsForm) | |
53 | from rhodecode.model.meta import Session |
|
53 | from rhodecode.model.meta import Session | |
54 | from rhodecode.model.repo import RepoModel |
|
54 | from rhodecode.model.repo import RepoModel | |
55 | from rhodecode.model.scm import ScmModel, RepoGroupList, RepoList |
|
55 | from rhodecode.model.scm import ScmModel, RepoGroupList, RepoList | |
56 | from rhodecode.model.settings import ( |
|
56 | from rhodecode.model.settings import ( | |
57 | SettingsModel, IssueTrackerSettingsModel, VcsSettingsModel, |
|
57 | SettingsModel, IssueTrackerSettingsModel, VcsSettingsModel, | |
58 | SettingNotFound) |
|
58 | SettingNotFound) | |
59 |
|
59 | |||
60 | log = logging.getLogger(__name__) |
|
60 | log = logging.getLogger(__name__) | |
61 |
|
61 | |||
62 |
|
62 | |||
63 | class ReposController(BaseRepoController): |
|
63 | class ReposController(BaseRepoController): | |
64 | """ |
|
64 | """ | |
65 | REST Controller styled on the Atom Publishing Protocol""" |
|
65 | REST Controller styled on the Atom Publishing Protocol""" | |
66 | # To properly map this controller, ensure your config/routing.py |
|
66 | # To properly map this controller, ensure your config/routing.py | |
67 | # file has a resource setup: |
|
67 | # file has a resource setup: | |
68 | # map.resource('repo', 'repos') |
|
68 | # map.resource('repo', 'repos') | |
69 |
|
69 | |||
70 | @LoginRequired() |
|
70 | @LoginRequired() | |
71 | def __before__(self): |
|
71 | def __before__(self): | |
72 | super(ReposController, self).__before__() |
|
72 | super(ReposController, self).__before__() | |
73 |
|
73 | |||
74 | def _load_repo(self, repo_name): |
|
74 | def _load_repo(self, repo_name): | |
75 | repo_obj = Repository.get_by_repo_name(repo_name) |
|
75 | repo_obj = Repository.get_by_repo_name(repo_name) | |
76 |
|
76 | |||
77 | if repo_obj is None: |
|
77 | if repo_obj is None: | |
78 | h.not_mapped_error(repo_name) |
|
78 | h.not_mapped_error(repo_name) | |
79 | return redirect(url('repos')) |
|
79 | return redirect(url('repos')) | |
80 |
|
80 | |||
81 | return repo_obj |
|
81 | return repo_obj | |
82 |
|
82 | |||
83 | def __load_defaults(self, repo=None): |
|
83 | def __load_defaults(self, repo=None): | |
84 | acl_groups = RepoGroupList(RepoGroup.query().all(), |
|
84 | acl_groups = RepoGroupList(RepoGroup.query().all(), | |
85 | perm_set=['group.write', 'group.admin']) |
|
85 | perm_set=['group.write', 'group.admin']) | |
86 | c.repo_groups = RepoGroup.groups_choices(groups=acl_groups) |
|
86 | c.repo_groups = RepoGroup.groups_choices(groups=acl_groups) | |
87 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) |
|
87 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) | |
88 |
|
88 | |||
89 | # in case someone no longer have a group.write access to a repository |
|
89 | # in case someone no longer have a group.write access to a repository | |
90 | # pre fill the list with this entry, we don't care if this is the same |
|
90 | # pre fill the list with this entry, we don't care if this is the same | |
91 | # but it will allow saving repo data properly. |
|
91 | # but it will allow saving repo data properly. | |
92 |
|
92 | |||
93 | repo_group = None |
|
93 | repo_group = None | |
94 | if repo: |
|
94 | if repo: | |
95 | repo_group = repo.group |
|
95 | repo_group = repo.group | |
96 | if repo_group and unicode(repo_group.group_id) not in c.repo_groups_choices: |
|
96 | if repo_group and unicode(repo_group.group_id) not in c.repo_groups_choices: | |
97 | c.repo_groups_choices.append(unicode(repo_group.group_id)) |
|
97 | c.repo_groups_choices.append(unicode(repo_group.group_id)) | |
98 | c.repo_groups.append(RepoGroup._generate_choice(repo_group)) |
|
98 | c.repo_groups.append(RepoGroup._generate_choice(repo_group)) | |
99 |
|
99 | |||
100 | choices, c.landing_revs = ScmModel().get_repo_landing_revs() |
|
100 | choices, c.landing_revs = ScmModel().get_repo_landing_revs() | |
101 | c.landing_revs_choices = choices |
|
101 | c.landing_revs_choices = choices | |
102 |
|
102 | |||
103 | def __load_data(self, repo_name=None): |
|
103 | def __load_data(self, repo_name=None): | |
104 | """ |
|
104 | """ | |
105 | Load defaults settings for edit, and update |
|
105 | Load defaults settings for edit, and update | |
106 |
|
106 | |||
107 | :param repo_name: |
|
107 | :param repo_name: | |
108 | """ |
|
108 | """ | |
109 | c.repo_info = self._load_repo(repo_name) |
|
109 | c.repo_info = self._load_repo(repo_name) | |
110 | self.__load_defaults(c.repo_info) |
|
110 | self.__load_defaults(c.repo_info) | |
111 |
|
111 | |||
112 | # override defaults for exact repo info here git/hg etc |
|
112 | # override defaults for exact repo info here git/hg etc | |
113 | if not c.repository_requirements_missing: |
|
113 | if not c.repository_requirements_missing: | |
114 | choices, c.landing_revs = ScmModel().get_repo_landing_revs( |
|
114 | choices, c.landing_revs = ScmModel().get_repo_landing_revs( | |
115 | c.repo_info) |
|
115 | c.repo_info) | |
116 | c.landing_revs_choices = choices |
|
116 | c.landing_revs_choices = choices | |
117 | defaults = RepoModel()._get_defaults(repo_name) |
|
117 | defaults = RepoModel()._get_defaults(repo_name) | |
118 |
|
118 | |||
119 | return defaults |
|
119 | return defaults | |
120 |
|
120 | |||
121 | def _log_creation_exception(self, e, repo_name): |
|
121 | def _log_creation_exception(self, e, repo_name): | |
122 | reason = None |
|
122 | reason = None | |
123 | if len(e.args) == 2: |
|
123 | if len(e.args) == 2: | |
124 | reason = e.args[1] |
|
124 | reason = e.args[1] | |
125 |
|
125 | |||
126 | if reason == 'INVALID_CERTIFICATE': |
|
126 | if reason == 'INVALID_CERTIFICATE': | |
127 | log.exception( |
|
127 | log.exception( | |
128 | 'Exception creating a repository: invalid certificate') |
|
128 | 'Exception creating a repository: invalid certificate') | |
129 | msg = (_('Error creating repository %s: invalid certificate') |
|
129 | msg = (_('Error creating repository %s: invalid certificate') | |
130 | % repo_name) |
|
130 | % repo_name) | |
131 | else: |
|
131 | else: | |
132 | log.exception("Exception creating a repository") |
|
132 | log.exception("Exception creating a repository") | |
133 | msg = (_('Error creating repository %s') |
|
133 | msg = (_('Error creating repository %s') | |
134 | % repo_name) |
|
134 | % repo_name) | |
135 |
|
135 | |||
136 | return msg |
|
136 | return msg | |
137 |
|
137 | |||
138 | @NotAnonymous() |
|
138 | @NotAnonymous() | |
139 | def index(self, format='html'): |
|
139 | def index(self, format='html'): | |
140 | """GET /repos: All items in the collection""" |
|
140 | """GET /repos: All items in the collection""" | |
141 | # url('repos') |
|
141 | # url('repos') | |
142 |
|
142 | |||
143 | repo_list = Repository.get_all_repos() |
|
143 | repo_list = Repository.get_all_repos() | |
144 | c.repo_list = RepoList(repo_list, perm_set=['repository.admin']) |
|
144 | c.repo_list = RepoList(repo_list, perm_set=['repository.admin']) | |
145 | repos_data = RepoModel().get_repos_as_dict( |
|
145 | repos_data = RepoModel().get_repos_as_dict( | |
146 | repo_list=c.repo_list, admin=True, super_user_actions=True) |
|
146 | repo_list=c.repo_list, admin=True, super_user_actions=True) | |
147 | # json used to render the grid |
|
147 | # json used to render the grid | |
148 | c.data = json.dumps(repos_data) |
|
148 | c.data = json.dumps(repos_data) | |
149 |
|
149 | |||
150 | return render('admin/repos/repos.mako') |
|
150 | return render('admin/repos/repos.mako') | |
151 |
|
151 | |||
152 | # perms check inside |
|
152 | # perms check inside | |
153 | @NotAnonymous() |
|
153 | @NotAnonymous() | |
154 | @auth.CSRFRequired() |
|
154 | @auth.CSRFRequired() | |
155 | def create(self): |
|
155 | def create(self): | |
156 | """ |
|
156 | """ | |
157 | POST /repos: Create a new item""" |
|
157 | POST /repos: Create a new item""" | |
158 | # url('repos') |
|
158 | # url('repos') | |
159 |
|
159 | |||
160 | self.__load_defaults() |
|
160 | self.__load_defaults() | |
161 | form_result = {} |
|
161 | form_result = {} | |
162 | task_id = None |
|
162 | task_id = None | |
163 | c.personal_repo_group = c.rhodecode_user.personal_repo_group |
|
163 | c.personal_repo_group = c.rhodecode_user.personal_repo_group | |
164 | try: |
|
164 | try: | |
165 | # CanWriteToGroup validators checks permissions of this POST |
|
165 | # CanWriteToGroup validators checks permissions of this POST | |
166 | form_result = RepoForm(repo_groups=c.repo_groups_choices, |
|
166 | form_result = RepoForm(repo_groups=c.repo_groups_choices, | |
167 | landing_revs=c.landing_revs_choices)()\ |
|
167 | landing_revs=c.landing_revs_choices)()\ | |
168 | .to_python(dict(request.POST)) |
|
168 | .to_python(dict(request.POST)) | |
169 |
|
169 | |||
170 | # create is done sometimes async on celery, db transaction |
|
170 | # create is done sometimes async on celery, db transaction | |
171 | # management is handled there. |
|
171 | # management is handled there. | |
172 | task = RepoModel().create(form_result, c.rhodecode_user.user_id) |
|
172 | task = RepoModel().create(form_result, c.rhodecode_user.user_id) | |
173 | from celery.result import BaseAsyncResult |
|
173 | from celery.result import BaseAsyncResult | |
174 | if isinstance(task, BaseAsyncResult): |
|
174 | if isinstance(task, BaseAsyncResult): | |
175 | task_id = task.task_id |
|
175 | task_id = task.task_id | |
176 | except formencode.Invalid as errors: |
|
176 | except formencode.Invalid as errors: | |
177 | return htmlfill.render( |
|
177 | return htmlfill.render( | |
178 | render('admin/repos/repo_add.mako'), |
|
178 | render('admin/repos/repo_add.mako'), | |
179 | defaults=errors.value, |
|
179 | defaults=errors.value, | |
180 | errors=errors.error_dict or {}, |
|
180 | errors=errors.error_dict or {}, | |
181 | prefix_error=False, |
|
181 | prefix_error=False, | |
182 | encoding="UTF-8", |
|
182 | encoding="UTF-8", | |
183 | force_defaults=False) |
|
183 | force_defaults=False) | |
184 |
|
184 | |||
185 | except Exception as e: |
|
185 | except Exception as e: | |
186 | msg = self._log_creation_exception(e, form_result.get('repo_name')) |
|
186 | msg = self._log_creation_exception(e, form_result.get('repo_name')) | |
187 | h.flash(msg, category='error') |
|
187 | h.flash(msg, category='error') | |
188 | return redirect(url('home')) |
|
188 | return redirect(url('home')) | |
189 |
|
189 | |||
190 | return redirect(h.url('repo_creating_home', |
|
190 | return redirect(h.url('repo_creating_home', | |
191 | repo_name=form_result['repo_name_full'], |
|
191 | repo_name=form_result['repo_name_full'], | |
192 | task_id=task_id)) |
|
192 | task_id=task_id)) | |
193 |
|
193 | |||
194 | # perms check inside |
|
194 | # perms check inside | |
195 | @NotAnonymous() |
|
195 | @NotAnonymous() | |
196 | def create_repository(self): |
|
196 | def create_repository(self): | |
197 | """GET /_admin/create_repository: Form to create a new item""" |
|
197 | """GET /_admin/create_repository: Form to create a new item""" | |
198 | new_repo = request.GET.get('repo', '') |
|
198 | new_repo = request.GET.get('repo', '') | |
199 | parent_group = safe_int(request.GET.get('parent_group')) |
|
199 | parent_group = safe_int(request.GET.get('parent_group')) | |
200 | _gr = RepoGroup.get(parent_group) |
|
200 | _gr = RepoGroup.get(parent_group) | |
201 |
|
201 | |||
202 | if not HasPermissionAny('hg.admin', 'hg.create.repository')(): |
|
202 | if not HasPermissionAny('hg.admin', 'hg.create.repository')(): | |
203 | # you're not super admin nor have global create permissions, |
|
203 | # you're not super admin nor have global create permissions, | |
204 | # but maybe you have at least write permission to a parent group ? |
|
204 | # but maybe you have at least write permission to a parent group ? | |
205 |
|
205 | |||
206 | gr_name = _gr.group_name if _gr else None |
|
206 | gr_name = _gr.group_name if _gr else None | |
207 | # create repositories with write permission on group is set to true |
|
207 | # create repositories with write permission on group is set to true | |
208 | create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')() |
|
208 | create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')() | |
209 | group_admin = HasRepoGroupPermissionAny('group.admin')(group_name=gr_name) |
|
209 | group_admin = HasRepoGroupPermissionAny('group.admin')(group_name=gr_name) | |
210 | group_write = HasRepoGroupPermissionAny('group.write')(group_name=gr_name) |
|
210 | group_write = HasRepoGroupPermissionAny('group.write')(group_name=gr_name) | |
211 | if not (group_admin or (group_write and create_on_write)): |
|
211 | if not (group_admin or (group_write and create_on_write)): | |
212 | raise HTTPForbidden |
|
212 | raise HTTPForbidden | |
213 |
|
213 | |||
214 | acl_groups = RepoGroupList(RepoGroup.query().all(), |
|
214 | acl_groups = RepoGroupList(RepoGroup.query().all(), | |
215 | perm_set=['group.write', 'group.admin']) |
|
215 | perm_set=['group.write', 'group.admin']) | |
216 | c.repo_groups = RepoGroup.groups_choices(groups=acl_groups) |
|
216 | c.repo_groups = RepoGroup.groups_choices(groups=acl_groups) | |
217 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) |
|
217 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) | |
218 | choices, c.landing_revs = ScmModel().get_repo_landing_revs() |
|
218 | choices, c.landing_revs = ScmModel().get_repo_landing_revs() | |
219 | c.personal_repo_group = c.rhodecode_user.personal_repo_group |
|
219 | c.personal_repo_group = c.rhodecode_user.personal_repo_group | |
220 | c.new_repo = repo_name_slug(new_repo) |
|
220 | c.new_repo = repo_name_slug(new_repo) | |
221 |
|
221 | |||
222 | # apply the defaults from defaults page |
|
222 | # apply the defaults from defaults page | |
223 | defaults = SettingsModel().get_default_repo_settings(strip_prefix=True) |
|
223 | defaults = SettingsModel().get_default_repo_settings(strip_prefix=True) | |
224 | # set checkbox to autochecked |
|
224 | # set checkbox to autochecked | |
225 | defaults['repo_copy_permissions'] = True |
|
225 | defaults['repo_copy_permissions'] = True | |
226 |
|
226 | |||
227 | parent_group_choice = '-1' |
|
227 | parent_group_choice = '-1' | |
228 | if not c.rhodecode_user.is_admin and c.rhodecode_user.personal_repo_group: |
|
228 | if not c.rhodecode_user.is_admin and c.rhodecode_user.personal_repo_group: | |
229 | parent_group_choice = c.rhodecode_user.personal_repo_group |
|
229 | parent_group_choice = c.rhodecode_user.personal_repo_group | |
230 |
|
230 | |||
231 | if parent_group and _gr: |
|
231 | if parent_group and _gr: | |
232 | if parent_group in [x[0] for x in c.repo_groups]: |
|
232 | if parent_group in [x[0] for x in c.repo_groups]: | |
233 | parent_group_choice = unicode(parent_group) |
|
233 | parent_group_choice = unicode(parent_group) | |
234 |
|
234 | |||
235 | defaults.update({'repo_group': parent_group_choice}) |
|
235 | defaults.update({'repo_group': parent_group_choice}) | |
236 |
|
236 | |||
237 | return htmlfill.render( |
|
237 | return htmlfill.render( | |
238 | render('admin/repos/repo_add.mako'), |
|
238 | render('admin/repos/repo_add.mako'), | |
239 | defaults=defaults, |
|
239 | defaults=defaults, | |
240 | errors={}, |
|
240 | errors={}, | |
241 | prefix_error=False, |
|
241 | prefix_error=False, | |
242 | encoding="UTF-8", |
|
242 | encoding="UTF-8", | |
243 | force_defaults=False |
|
243 | force_defaults=False | |
244 | ) |
|
244 | ) | |
245 |
|
245 | |||
246 | @NotAnonymous() |
|
246 | @NotAnonymous() | |
247 | def repo_creating(self, repo_name): |
|
247 | def repo_creating(self, repo_name): | |
248 | c.repo = repo_name |
|
248 | c.repo = repo_name | |
249 | c.task_id = request.GET.get('task_id') |
|
249 | c.task_id = request.GET.get('task_id') | |
250 | if not c.repo: |
|
250 | if not c.repo: | |
251 | raise HTTPNotFound() |
|
251 | raise HTTPNotFound() | |
252 | return render('admin/repos/repo_creating.mako') |
|
252 | return render('admin/repos/repo_creating.mako') | |
253 |
|
253 | |||
254 | @NotAnonymous() |
|
254 | @NotAnonymous() | |
255 | @jsonify |
|
255 | @jsonify | |
256 | def repo_check(self, repo_name): |
|
256 | def repo_check(self, repo_name): | |
257 | c.repo = repo_name |
|
257 | c.repo = repo_name | |
258 | task_id = request.GET.get('task_id') |
|
258 | task_id = request.GET.get('task_id') | |
259 |
|
259 | |||
260 | if task_id and task_id not in ['None']: |
|
260 | if task_id and task_id not in ['None']: | |
261 | import rhodecode |
|
261 | import rhodecode | |
262 | from celery.result import AsyncResult |
|
262 | from celery.result import AsyncResult | |
263 | if rhodecode.CELERY_ENABLED: |
|
263 | if rhodecode.CELERY_ENABLED: | |
264 | task = AsyncResult(task_id) |
|
264 | task = AsyncResult(task_id) | |
265 | if task.failed(): |
|
265 | if task.failed(): | |
266 | msg = self._log_creation_exception(task.result, c.repo) |
|
266 | msg = self._log_creation_exception(task.result, c.repo) | |
267 | h.flash(msg, category='error') |
|
267 | h.flash(msg, category='error') | |
268 | return redirect(url('home'), code=501) |
|
268 | return redirect(url('home'), code=501) | |
269 |
|
269 | |||
270 | repo = Repository.get_by_repo_name(repo_name) |
|
270 | repo = Repository.get_by_repo_name(repo_name) | |
271 | if repo and repo.repo_state == Repository.STATE_CREATED: |
|
271 | if repo and repo.repo_state == Repository.STATE_CREATED: | |
272 | if repo.clone_uri: |
|
272 | if repo.clone_uri: | |
273 | clone_uri = repo.clone_uri_hidden |
|
273 | clone_uri = repo.clone_uri_hidden | |
274 | h.flash(_('Created repository %s from %s') |
|
274 | h.flash(_('Created repository %s from %s') | |
275 | % (repo.repo_name, clone_uri), category='success') |
|
275 | % (repo.repo_name, clone_uri), category='success') | |
276 | else: |
|
276 | else: | |
277 | repo_url = h.link_to(repo.repo_name, |
|
277 | repo_url = h.link_to(repo.repo_name, | |
278 | h.url('summary_home', |
|
278 | h.url('summary_home', | |
279 | repo_name=repo.repo_name)) |
|
279 | repo_name=repo.repo_name)) | |
280 | fork = repo.fork |
|
280 | fork = repo.fork | |
281 | if fork: |
|
281 | if fork: | |
282 | fork_name = fork.repo_name |
|
282 | fork_name = fork.repo_name | |
283 | h.flash(h.literal(_('Forked repository %s as %s') |
|
283 | h.flash(h.literal(_('Forked repository %s as %s') | |
284 | % (fork_name, repo_url)), category='success') |
|
284 | % (fork_name, repo_url)), category='success') | |
285 | else: |
|
285 | else: | |
286 | h.flash(h.literal(_('Created repository %s') % repo_url), |
|
286 | h.flash(h.literal(_('Created repository %s') % repo_url), | |
287 | category='success') |
|
287 | category='success') | |
288 | return {'result': True} |
|
288 | return {'result': True} | |
289 | return {'result': False} |
|
289 | return {'result': False} | |
290 |
|
290 | |||
291 | @HasRepoPermissionAllDecorator('repository.admin') |
|
|||
292 | @auth.CSRFRequired() |
|
|||
293 | def delete(self, repo_name): |
|
|||
294 | """ |
|
|||
295 | DELETE /repos/repo_name: Delete an existing item""" |
|
|||
296 | # Forms posted to this method should contain a hidden field: |
|
|||
297 | # <input type="hidden" name="_method" value="DELETE" /> |
|
|||
298 | # Or using helpers: |
|
|||
299 | # h.form(url('repo', repo_name=ID), |
|
|||
300 | # method='delete') |
|
|||
301 | # url('repo', repo_name=ID) |
|
|||
302 |
|
||||
303 | repo_model = RepoModel() |
|
|||
304 | repo = repo_model.get_by_repo_name(repo_name) |
|
|||
305 | if not repo: |
|
|||
306 | h.not_mapped_error(repo_name) |
|
|||
307 | return redirect(url('repos')) |
|
|||
308 | try: |
|
|||
309 | _forks = repo.forks.count() |
|
|||
310 | handle_forks = None |
|
|||
311 | if _forks and request.POST.get('forks'): |
|
|||
312 | do = request.POST['forks'] |
|
|||
313 | if do == 'detach_forks': |
|
|||
314 | handle_forks = 'detach' |
|
|||
315 | h.flash(_('Detached %s forks') % _forks, category='success') |
|
|||
316 | elif do == 'delete_forks': |
|
|||
317 | handle_forks = 'delete' |
|
|||
318 | h.flash(_('Deleted %s forks') % _forks, category='success') |
|
|||
319 | repo_model.delete(repo, forks=handle_forks) |
|
|||
320 | action_logger(c.rhodecode_user, 'admin_deleted_repo', |
|
|||
321 | repo_name, self.ip_addr, self.sa) |
|
|||
322 | ScmModel().mark_for_invalidation(repo_name) |
|
|||
323 | h.flash(_('Deleted repository %s') % repo_name, category='success') |
|
|||
324 | Session().commit() |
|
|||
325 | except AttachedForksError: |
|
|||
326 | h.flash(_('Cannot delete %s it still contains attached forks') |
|
|||
327 | % repo_name, category='warning') |
|
|||
328 |
|
||||
329 | except Exception: |
|
|||
330 | log.exception("Exception during deletion of repository") |
|
|||
331 | h.flash(_('An error occurred during deletion of %s') % repo_name, |
|
|||
332 | category='error') |
|
|||
333 |
|
||||
334 | return redirect(url('repos')) |
|
|||
335 |
|
||||
336 | @HasPermissionAllDecorator('hg.admin') |
|
291 | @HasPermissionAllDecorator('hg.admin') | |
337 | def show(self, repo_name, format='html'): |
|
292 | def show(self, repo_name, format='html'): | |
338 | """GET /repos/repo_name: Show a specific item""" |
|
293 | """GET /repos/repo_name: Show a specific item""" | |
339 | # url('repo', repo_name=ID) |
|
294 | # url('repo', repo_name=ID) | |
340 |
|
295 | |||
341 | @HasRepoPermissionAllDecorator('repository.admin') |
|
296 | @HasRepoPermissionAllDecorator('repository.admin') | |
342 | def edit_fields(self, repo_name): |
|
297 | def edit_fields(self, repo_name): | |
343 | """GET /repo_name/settings: Form to edit an existing item""" |
|
298 | """GET /repo_name/settings: Form to edit an existing item""" | |
344 | c.repo_info = self._load_repo(repo_name) |
|
299 | c.repo_info = self._load_repo(repo_name) | |
345 | c.repo_fields = RepositoryField.query()\ |
|
300 | c.repo_fields = RepositoryField.query()\ | |
346 | .filter(RepositoryField.repository == c.repo_info).all() |
|
301 | .filter(RepositoryField.repository == c.repo_info).all() | |
347 | c.active = 'fields' |
|
302 | c.active = 'fields' | |
348 | if request.POST: |
|
303 | if request.POST: | |
349 |
|
304 | |||
350 | return redirect(url('repo_edit_fields')) |
|
305 | return redirect(url('repo_edit_fields')) | |
351 | return render('admin/repos/repo_edit.mako') |
|
306 | return render('admin/repos/repo_edit.mako') | |
352 |
|
307 | |||
353 | @HasRepoPermissionAllDecorator('repository.admin') |
|
308 | @HasRepoPermissionAllDecorator('repository.admin') | |
354 | @auth.CSRFRequired() |
|
309 | @auth.CSRFRequired() | |
355 | def create_repo_field(self, repo_name): |
|
310 | def create_repo_field(self, repo_name): | |
356 | try: |
|
311 | try: | |
357 | form_result = RepoFieldForm()().to_python(dict(request.POST)) |
|
312 | form_result = RepoFieldForm()().to_python(dict(request.POST)) | |
358 | RepoModel().add_repo_field( |
|
313 | RepoModel().add_repo_field( | |
359 | repo_name, form_result['new_field_key'], |
|
314 | repo_name, form_result['new_field_key'], | |
360 | field_type=form_result['new_field_type'], |
|
315 | field_type=form_result['new_field_type'], | |
361 | field_value=form_result['new_field_value'], |
|
316 | field_value=form_result['new_field_value'], | |
362 | field_label=form_result['new_field_label'], |
|
317 | field_label=form_result['new_field_label'], | |
363 | field_desc=form_result['new_field_desc']) |
|
318 | field_desc=form_result['new_field_desc']) | |
364 |
|
319 | |||
365 | Session().commit() |
|
320 | Session().commit() | |
366 | except Exception as e: |
|
321 | except Exception as e: | |
367 | log.exception("Exception creating field") |
|
322 | log.exception("Exception creating field") | |
368 | msg = _('An error occurred during creation of field') |
|
323 | msg = _('An error occurred during creation of field') | |
369 | if isinstance(e, formencode.Invalid): |
|
324 | if isinstance(e, formencode.Invalid): | |
370 | msg += ". " + e.msg |
|
325 | msg += ". " + e.msg | |
371 | h.flash(msg, category='error') |
|
326 | h.flash(msg, category='error') | |
372 | return redirect(url('edit_repo_fields', repo_name=repo_name)) |
|
327 | return redirect(url('edit_repo_fields', repo_name=repo_name)) | |
373 |
|
328 | |||
374 | @HasRepoPermissionAllDecorator('repository.admin') |
|
329 | @HasRepoPermissionAllDecorator('repository.admin') | |
375 | @auth.CSRFRequired() |
|
330 | @auth.CSRFRequired() | |
376 | def delete_repo_field(self, repo_name, field_id): |
|
331 | def delete_repo_field(self, repo_name, field_id): | |
377 | field = RepositoryField.get_or_404(field_id) |
|
332 | field = RepositoryField.get_or_404(field_id) | |
378 | try: |
|
333 | try: | |
379 | RepoModel().delete_repo_field(repo_name, field.field_key) |
|
334 | RepoModel().delete_repo_field(repo_name, field.field_key) | |
380 | Session().commit() |
|
335 | Session().commit() | |
381 | except Exception as e: |
|
336 | except Exception as e: | |
382 | log.exception("Exception during removal of field") |
|
337 | log.exception("Exception during removal of field") | |
383 | msg = _('An error occurred during removal of field') |
|
338 | msg = _('An error occurred during removal of field') | |
384 | h.flash(msg, category='error') |
|
339 | h.flash(msg, category='error') | |
385 | return redirect(url('edit_repo_fields', repo_name=repo_name)) |
|
340 | return redirect(url('edit_repo_fields', repo_name=repo_name)) | |
386 |
|
341 | |||
387 | @HasRepoPermissionAllDecorator('repository.admin') |
|
|||
388 | def edit_advanced(self, repo_name): |
|
|||
389 | """GET /repo_name/settings: Form to edit an existing item""" |
|
|||
390 | c.repo_info = self._load_repo(repo_name) |
|
|||
391 | c.default_user_id = User.get_default_user().user_id |
|
|||
392 | c.in_public_journal = UserFollowing.query()\ |
|
|||
393 | .filter(UserFollowing.user_id == c.default_user_id)\ |
|
|||
394 | .filter(UserFollowing.follows_repository == c.repo_info).scalar() |
|
|||
395 |
|
||||
396 | c.active = 'advanced' |
|
|||
397 | c.has_origin_repo_read_perm = False |
|
|||
398 | if c.repo_info.fork: |
|
|||
399 | c.has_origin_repo_read_perm = h.HasRepoPermissionAny( |
|
|||
400 | 'repository.write', 'repository.read', 'repository.admin')( |
|
|||
401 | c.repo_info.fork.repo_name, 'repo set as fork page') |
|
|||
402 |
|
||||
403 | if request.POST: |
|
|||
404 | return redirect(url('repo_edit_advanced')) |
|
|||
405 | return render('admin/repos/repo_edit.mako') |
|
|||
406 |
|
||||
407 | @HasRepoPermissionAllDecorator('repository.admin') |
|
|||
408 | @auth.CSRFRequired() |
|
|||
409 | def edit_advanced_journal(self, repo_name): |
|
|||
410 | """ |
|
|||
411 | Set's this repository to be visible in public journal, |
|
|||
412 | in other words assing default user to follow this repo |
|
|||
413 |
|
||||
414 | :param repo_name: |
|
|||
415 | """ |
|
|||
416 |
|
||||
417 | try: |
|
|||
418 | repo_id = Repository.get_by_repo_name(repo_name).repo_id |
|
|||
419 | user_id = User.get_default_user().user_id |
|
|||
420 | self.scm_model.toggle_following_repo(repo_id, user_id) |
|
|||
421 | h.flash(_('Updated repository visibility in public journal'), |
|
|||
422 | category='success') |
|
|||
423 | Session().commit() |
|
|||
424 | except Exception: |
|
|||
425 | h.flash(_('An error occurred during setting this' |
|
|||
426 | ' repository in public journal'), |
|
|||
427 | category='error') |
|
|||
428 |
|
||||
429 | return redirect(url('edit_repo_advanced', repo_name=repo_name)) |
|
|||
430 |
|
||||
431 | @HasRepoPermissionAllDecorator('repository.admin') |
|
|||
432 | @auth.CSRFRequired() |
|
|||
433 | def edit_advanced_fork(self, repo_name): |
|
|||
434 | """ |
|
|||
435 | Mark given repository as a fork of another |
|
|||
436 |
|
||||
437 | :param repo_name: |
|
|||
438 | """ |
|
|||
439 |
|
||||
440 | new_fork_id = request.POST.get('id_fork_of') |
|
|||
441 | try: |
|
|||
442 |
|
||||
443 | if new_fork_id and not new_fork_id.isdigit(): |
|
|||
444 | log.error('Given fork id %s is not an INT', new_fork_id) |
|
|||
445 |
|
||||
446 | fork_id = safe_int(new_fork_id) |
|
|||
447 | repo = ScmModel().mark_as_fork(repo_name, fork_id, |
|
|||
448 | c.rhodecode_user.username) |
|
|||
449 | fork = repo.fork.repo_name if repo.fork else _('Nothing') |
|
|||
450 | Session().commit() |
|
|||
451 | h.flash(_('Marked repo %s as fork of %s') % (repo_name, fork), |
|
|||
452 | category='success') |
|
|||
453 | except RepositoryError as e: |
|
|||
454 | log.exception("Repository Error occurred") |
|
|||
455 | h.flash(str(e), category='error') |
|
|||
456 | except Exception as e: |
|
|||
457 | log.exception("Exception while editing fork") |
|
|||
458 | h.flash(_('An error occurred during this operation'), |
|
|||
459 | category='error') |
|
|||
460 |
|
||||
461 | return redirect(url('edit_repo_advanced', repo_name=repo_name)) |
|
|||
462 |
|
||||
463 | @HasRepoPermissionAllDecorator('repository.admin') |
|
|||
464 | @auth.CSRFRequired() |
|
|||
465 | def edit_advanced_locking(self, repo_name): |
|
|||
466 | """ |
|
|||
467 | Unlock repository when it is locked ! |
|
|||
468 |
|
||||
469 | :param repo_name: |
|
|||
470 | """ |
|
|||
471 | try: |
|
|||
472 | repo = Repository.get_by_repo_name(repo_name) |
|
|||
473 | if request.POST.get('set_lock'): |
|
|||
474 | Repository.lock(repo, c.rhodecode_user.user_id, |
|
|||
475 | lock_reason=Repository.LOCK_WEB) |
|
|||
476 | h.flash(_('Locked repository'), category='success') |
|
|||
477 | elif request.POST.get('set_unlock'): |
|
|||
478 | Repository.unlock(repo) |
|
|||
479 | h.flash(_('Unlocked repository'), category='success') |
|
|||
480 | except Exception as e: |
|
|||
481 | log.exception("Exception during unlocking") |
|
|||
482 | h.flash(_('An error occurred during unlocking'), |
|
|||
483 | category='error') |
|
|||
484 | return redirect(url('edit_repo_advanced', repo_name=repo_name)) |
|
|||
485 |
|
||||
486 | @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') |
|
342 | @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') | |
487 | @auth.CSRFRequired() |
|
343 | @auth.CSRFRequired() | |
488 | def toggle_locking(self, repo_name): |
|
344 | def toggle_locking(self, repo_name): | |
489 | """ |
|
345 | """ | |
490 | Toggle locking of repository by simple GET call to url |
|
346 | Toggle locking of repository by simple GET call to url | |
491 |
|
347 | |||
492 | :param repo_name: |
|
348 | :param repo_name: | |
493 | """ |
|
349 | """ | |
494 |
|
350 | |||
495 | try: |
|
351 | try: | |
496 | repo = Repository.get_by_repo_name(repo_name) |
|
352 | repo = Repository.get_by_repo_name(repo_name) | |
497 |
|
353 | |||
498 | if repo.enable_locking: |
|
354 | if repo.enable_locking: | |
499 | if repo.locked[0]: |
|
355 | if repo.locked[0]: | |
500 | Repository.unlock(repo) |
|
356 | Repository.unlock(repo) | |
501 | action = _('Unlocked') |
|
357 | action = _('Unlocked') | |
502 | else: |
|
358 | else: | |
503 | Repository.lock(repo, c.rhodecode_user.user_id, |
|
359 | Repository.lock(repo, c.rhodecode_user.user_id, | |
504 | lock_reason=Repository.LOCK_WEB) |
|
360 | lock_reason=Repository.LOCK_WEB) | |
505 | action = _('Locked') |
|
361 | action = _('Locked') | |
506 |
|
362 | |||
507 | h.flash(_('Repository has been %s') % action, |
|
363 | h.flash(_('Repository has been %s') % action, | |
508 | category='success') |
|
364 | category='success') | |
509 | except Exception: |
|
365 | except Exception: | |
510 | log.exception("Exception during unlocking") |
|
366 | log.exception("Exception during unlocking") | |
511 | h.flash(_('An error occurred during unlocking'), |
|
367 | h.flash(_('An error occurred during unlocking'), | |
512 | category='error') |
|
368 | category='error') | |
513 | return redirect(url('summary_home', repo_name=repo_name)) |
|
369 | return redirect(url('summary_home', repo_name=repo_name)) | |
514 |
|
370 | |||
515 | @HasRepoPermissionAllDecorator('repository.admin') |
|
371 | @HasRepoPermissionAllDecorator('repository.admin') | |
516 | @auth.CSRFRequired() |
|
372 | @auth.CSRFRequired() | |
517 | def edit_remote(self, repo_name): |
|
373 | def edit_remote(self, repo_name): | |
518 | """PUT /{repo_name}/settings/remote: edit the repo remote.""" |
|
374 | """PUT /{repo_name}/settings/remote: edit the repo remote.""" | |
519 | try: |
|
375 | try: | |
520 | ScmModel().pull_changes(repo_name, c.rhodecode_user.username) |
|
376 | ScmModel().pull_changes(repo_name, c.rhodecode_user.username) | |
521 | h.flash(_('Pulled from remote location'), category='success') |
|
377 | h.flash(_('Pulled from remote location'), category='success') | |
522 | except Exception: |
|
378 | except Exception: | |
523 | log.exception("Exception during pull from remote") |
|
379 | log.exception("Exception during pull from remote") | |
524 | h.flash(_('An error occurred during pull from remote location'), |
|
380 | h.flash(_('An error occurred during pull from remote location'), | |
525 | category='error') |
|
381 | category='error') | |
526 | return redirect(url('edit_repo_remote', repo_name=c.repo_name)) |
|
382 | return redirect(url('edit_repo_remote', repo_name=c.repo_name)) | |
527 |
|
383 | |||
528 | @HasRepoPermissionAllDecorator('repository.admin') |
|
384 | @HasRepoPermissionAllDecorator('repository.admin') | |
529 | def edit_remote_form(self, repo_name): |
|
385 | def edit_remote_form(self, repo_name): | |
530 | """GET /repo_name/settings: Form to edit an existing item""" |
|
386 | """GET /repo_name/settings: Form to edit an existing item""" | |
531 | c.repo_info = self._load_repo(repo_name) |
|
387 | c.repo_info = self._load_repo(repo_name) | |
532 | c.active = 'remote' |
|
388 | c.active = 'remote' | |
533 |
|
389 | |||
534 | return render('admin/repos/repo_edit.mako') |
|
390 | return render('admin/repos/repo_edit.mako') | |
535 |
|
391 | |||
536 | @HasRepoPermissionAllDecorator('repository.admin') |
|
392 | @HasRepoPermissionAllDecorator('repository.admin') | |
537 | @auth.CSRFRequired() |
|
393 | @auth.CSRFRequired() | |
538 | def edit_statistics(self, repo_name): |
|
394 | def edit_statistics(self, repo_name): | |
539 | """PUT /{repo_name}/settings/statistics: reset the repo statistics.""" |
|
395 | """PUT /{repo_name}/settings/statistics: reset the repo statistics.""" | |
540 | try: |
|
396 | try: | |
541 | RepoModel().delete_stats(repo_name) |
|
397 | RepoModel().delete_stats(repo_name) | |
542 | Session().commit() |
|
398 | Session().commit() | |
543 | except Exception as e: |
|
399 | except Exception as e: | |
544 | log.error(traceback.format_exc()) |
|
400 | log.error(traceback.format_exc()) | |
545 | h.flash(_('An error occurred during deletion of repository stats'), |
|
401 | h.flash(_('An error occurred during deletion of repository stats'), | |
546 | category='error') |
|
402 | category='error') | |
547 | return redirect(url('edit_repo_statistics', repo_name=c.repo_name)) |
|
403 | return redirect(url('edit_repo_statistics', repo_name=c.repo_name)) | |
548 |
|
404 | |||
549 | @HasRepoPermissionAllDecorator('repository.admin') |
|
405 | @HasRepoPermissionAllDecorator('repository.admin') | |
550 | def edit_statistics_form(self, repo_name): |
|
406 | def edit_statistics_form(self, repo_name): | |
551 | """GET /repo_name/settings: Form to edit an existing item""" |
|
407 | """GET /repo_name/settings: Form to edit an existing item""" | |
552 | c.repo_info = self._load_repo(repo_name) |
|
408 | c.repo_info = self._load_repo(repo_name) | |
553 | repo = c.repo_info.scm_instance() |
|
409 | repo = c.repo_info.scm_instance() | |
554 |
|
410 | |||
555 | if c.repo_info.stats: |
|
411 | if c.repo_info.stats: | |
556 | # this is on what revision we ended up so we add +1 for count |
|
412 | # this is on what revision we ended up so we add +1 for count | |
557 | last_rev = c.repo_info.stats.stat_on_revision + 1 |
|
413 | last_rev = c.repo_info.stats.stat_on_revision + 1 | |
558 | else: |
|
414 | else: | |
559 | last_rev = 0 |
|
415 | last_rev = 0 | |
560 | c.stats_revision = last_rev |
|
416 | c.stats_revision = last_rev | |
561 |
|
417 | |||
562 | c.repo_last_rev = repo.count() |
|
418 | c.repo_last_rev = repo.count() | |
563 |
|
419 | |||
564 | if last_rev == 0 or c.repo_last_rev == 0: |
|
420 | if last_rev == 0 or c.repo_last_rev == 0: | |
565 | c.stats_percentage = 0 |
|
421 | c.stats_percentage = 0 | |
566 | else: |
|
422 | else: | |
567 | c.stats_percentage = '%.2f' % ((float((last_rev)) / c.repo_last_rev) * 100) |
|
423 | c.stats_percentage = '%.2f' % ((float((last_rev)) / c.repo_last_rev) * 100) | |
568 |
|
424 | |||
569 | c.active = 'statistics' |
|
425 | c.active = 'statistics' | |
570 |
|
426 | |||
571 | return render('admin/repos/repo_edit.mako') |
|
427 | return render('admin/repos/repo_edit.mako') | |
572 |
|
428 | |||
573 | @HasRepoPermissionAllDecorator('repository.admin') |
|
429 | @HasRepoPermissionAllDecorator('repository.admin') | |
574 | @auth.CSRFRequired() |
|
430 | @auth.CSRFRequired() | |
575 | def repo_issuetracker_test(self, repo_name): |
|
431 | def repo_issuetracker_test(self, repo_name): | |
576 | if request.is_xhr: |
|
432 | if request.is_xhr: | |
577 | return h.urlify_commit_message( |
|
433 | return h.urlify_commit_message( | |
578 | request.POST.get('test_text', ''), |
|
434 | request.POST.get('test_text', ''), | |
579 | repo_name) |
|
435 | repo_name) | |
580 | else: |
|
436 | else: | |
581 | raise HTTPBadRequest() |
|
437 | raise HTTPBadRequest() | |
582 |
|
438 | |||
583 | @HasRepoPermissionAllDecorator('repository.admin') |
|
439 | @HasRepoPermissionAllDecorator('repository.admin') | |
584 | @auth.CSRFRequired() |
|
440 | @auth.CSRFRequired() | |
585 | def repo_issuetracker_delete(self, repo_name): |
|
441 | def repo_issuetracker_delete(self, repo_name): | |
586 | uid = request.POST.get('uid') |
|
442 | uid = request.POST.get('uid') | |
587 | repo_settings = IssueTrackerSettingsModel(repo=repo_name) |
|
443 | repo_settings = IssueTrackerSettingsModel(repo=repo_name) | |
588 | try: |
|
444 | try: | |
589 | repo_settings.delete_entries(uid) |
|
445 | repo_settings.delete_entries(uid) | |
590 | except Exception: |
|
446 | except Exception: | |
591 | h.flash(_('Error occurred during deleting issue tracker entry'), |
|
447 | h.flash(_('Error occurred during deleting issue tracker entry'), | |
592 | category='error') |
|
448 | category='error') | |
593 | else: |
|
449 | else: | |
594 | h.flash(_('Removed issue tracker entry'), category='success') |
|
450 | h.flash(_('Removed issue tracker entry'), category='success') | |
595 | return redirect(url('repo_settings_issuetracker', |
|
451 | return redirect(url('repo_settings_issuetracker', | |
596 | repo_name=repo_name)) |
|
452 | repo_name=repo_name)) | |
597 |
|
453 | |||
598 | def _update_patterns(self, form, repo_settings): |
|
454 | def _update_patterns(self, form, repo_settings): | |
599 | for uid in form['delete_patterns']: |
|
455 | for uid in form['delete_patterns']: | |
600 | repo_settings.delete_entries(uid) |
|
456 | repo_settings.delete_entries(uid) | |
601 |
|
457 | |||
602 | for pattern in form['patterns']: |
|
458 | for pattern in form['patterns']: | |
603 | for setting, value, type_ in pattern: |
|
459 | for setting, value, type_ in pattern: | |
604 | sett = repo_settings.create_or_update_setting( |
|
460 | sett = repo_settings.create_or_update_setting( | |
605 | setting, value, type_) |
|
461 | setting, value, type_) | |
606 | Session().add(sett) |
|
462 | Session().add(sett) | |
607 |
|
463 | |||
608 | Session().commit() |
|
464 | Session().commit() | |
609 |
|
465 | |||
610 | @HasRepoPermissionAllDecorator('repository.admin') |
|
466 | @HasRepoPermissionAllDecorator('repository.admin') | |
611 | @auth.CSRFRequired() |
|
467 | @auth.CSRFRequired() | |
612 | def repo_issuetracker_save(self, repo_name): |
|
468 | def repo_issuetracker_save(self, repo_name): | |
613 | # Save inheritance |
|
469 | # Save inheritance | |
614 | repo_settings = IssueTrackerSettingsModel(repo=repo_name) |
|
470 | repo_settings = IssueTrackerSettingsModel(repo=repo_name) | |
615 | inherited = (request.POST.get('inherit_global_issuetracker') |
|
471 | inherited = (request.POST.get('inherit_global_issuetracker') | |
616 | == "inherited") |
|
472 | == "inherited") | |
617 | repo_settings.inherit_global_settings = inherited |
|
473 | repo_settings.inherit_global_settings = inherited | |
618 | Session().commit() |
|
474 | Session().commit() | |
619 |
|
475 | |||
620 | form = IssueTrackerPatternsForm()().to_python(request.POST) |
|
476 | form = IssueTrackerPatternsForm()().to_python(request.POST) | |
621 | if form: |
|
477 | if form: | |
622 | self._update_patterns(form, repo_settings) |
|
478 | self._update_patterns(form, repo_settings) | |
623 |
|
479 | |||
624 | h.flash(_('Updated issue tracker entries'), category='success') |
|
480 | h.flash(_('Updated issue tracker entries'), category='success') | |
625 | return redirect(url('repo_settings_issuetracker', |
|
481 | return redirect(url('repo_settings_issuetracker', | |
626 | repo_name=repo_name)) |
|
482 | repo_name=repo_name)) | |
627 |
|
483 | |||
628 | @HasRepoPermissionAllDecorator('repository.admin') |
|
484 | @HasRepoPermissionAllDecorator('repository.admin') | |
629 | def repo_issuetracker(self, repo_name): |
|
485 | def repo_issuetracker(self, repo_name): | |
630 | """GET /admin/settings/issue-tracker: All items in the collection""" |
|
486 | """GET /admin/settings/issue-tracker: All items in the collection""" | |
631 | c.active = 'issuetracker' |
|
487 | c.active = 'issuetracker' | |
632 | c.data = 'data' |
|
488 | c.data = 'data' | |
633 | c.repo_info = self._load_repo(repo_name) |
|
489 | c.repo_info = self._load_repo(repo_name) | |
634 |
|
490 | |||
635 | repo = Repository.get_by_repo_name(repo_name) |
|
491 | repo = Repository.get_by_repo_name(repo_name) | |
636 | c.settings_model = IssueTrackerSettingsModel(repo=repo) |
|
492 | c.settings_model = IssueTrackerSettingsModel(repo=repo) | |
637 | c.global_patterns = c.settings_model.get_global_settings() |
|
493 | c.global_patterns = c.settings_model.get_global_settings() | |
638 | c.repo_patterns = c.settings_model.get_repo_settings() |
|
494 | c.repo_patterns = c.settings_model.get_repo_settings() | |
639 |
|
495 | |||
640 | return render('admin/repos/repo_edit.mako') |
|
496 | return render('admin/repos/repo_edit.mako') | |
641 |
|
497 | |||
642 | @HasRepoPermissionAllDecorator('repository.admin') |
|
498 | @HasRepoPermissionAllDecorator('repository.admin') | |
643 | def repo_settings_vcs(self, repo_name): |
|
499 | def repo_settings_vcs(self, repo_name): | |
644 | """GET /{repo_name}/settings/vcs/: All items in the collection""" |
|
500 | """GET /{repo_name}/settings/vcs/: All items in the collection""" | |
645 |
|
501 | |||
646 | model = VcsSettingsModel(repo=repo_name) |
|
502 | model = VcsSettingsModel(repo=repo_name) | |
647 |
|
503 | |||
648 | c.active = 'vcs' |
|
504 | c.active = 'vcs' | |
649 | c.global_svn_branch_patterns = model.get_global_svn_branch_patterns() |
|
505 | c.global_svn_branch_patterns = model.get_global_svn_branch_patterns() | |
650 | c.global_svn_tag_patterns = model.get_global_svn_tag_patterns() |
|
506 | c.global_svn_tag_patterns = model.get_global_svn_tag_patterns() | |
651 | c.svn_branch_patterns = model.get_repo_svn_branch_patterns() |
|
507 | c.svn_branch_patterns = model.get_repo_svn_branch_patterns() | |
652 | c.svn_tag_patterns = model.get_repo_svn_tag_patterns() |
|
508 | c.svn_tag_patterns = model.get_repo_svn_tag_patterns() | |
653 | c.repo_info = self._load_repo(repo_name) |
|
509 | c.repo_info = self._load_repo(repo_name) | |
654 | defaults = self._vcs_form_defaults(repo_name) |
|
510 | defaults = self._vcs_form_defaults(repo_name) | |
655 | c.inherit_global_settings = defaults['inherit_global_settings'] |
|
511 | c.inherit_global_settings = defaults['inherit_global_settings'] | |
656 | c.labs_active = str2bool( |
|
512 | c.labs_active = str2bool( | |
657 | rhodecode.CONFIG.get('labs_settings_active', 'true')) |
|
513 | rhodecode.CONFIG.get('labs_settings_active', 'true')) | |
658 |
|
514 | |||
659 | return htmlfill.render( |
|
515 | return htmlfill.render( | |
660 | render('admin/repos/repo_edit.mako'), |
|
516 | render('admin/repos/repo_edit.mako'), | |
661 | defaults=defaults, |
|
517 | defaults=defaults, | |
662 | encoding="UTF-8", |
|
518 | encoding="UTF-8", | |
663 | force_defaults=False) |
|
519 | force_defaults=False) | |
664 |
|
520 | |||
665 | @HasRepoPermissionAllDecorator('repository.admin') |
|
521 | @HasRepoPermissionAllDecorator('repository.admin') | |
666 | @auth.CSRFRequired() |
|
522 | @auth.CSRFRequired() | |
667 | def repo_settings_vcs_update(self, repo_name): |
|
523 | def repo_settings_vcs_update(self, repo_name): | |
668 | """POST /{repo_name}/settings/vcs/: All items in the collection""" |
|
524 | """POST /{repo_name}/settings/vcs/: All items in the collection""" | |
669 | c.active = 'vcs' |
|
525 | c.active = 'vcs' | |
670 |
|
526 | |||
671 | model = VcsSettingsModel(repo=repo_name) |
|
527 | model = VcsSettingsModel(repo=repo_name) | |
672 | c.global_svn_branch_patterns = model.get_global_svn_branch_patterns() |
|
528 | c.global_svn_branch_patterns = model.get_global_svn_branch_patterns() | |
673 | c.global_svn_tag_patterns = model.get_global_svn_tag_patterns() |
|
529 | c.global_svn_tag_patterns = model.get_global_svn_tag_patterns() | |
674 | c.svn_branch_patterns = model.get_repo_svn_branch_patterns() |
|
530 | c.svn_branch_patterns = model.get_repo_svn_branch_patterns() | |
675 | c.svn_tag_patterns = model.get_repo_svn_tag_patterns() |
|
531 | c.svn_tag_patterns = model.get_repo_svn_tag_patterns() | |
676 | c.repo_info = self._load_repo(repo_name) |
|
532 | c.repo_info = self._load_repo(repo_name) | |
677 | defaults = self._vcs_form_defaults(repo_name) |
|
533 | defaults = self._vcs_form_defaults(repo_name) | |
678 | c.inherit_global_settings = defaults['inherit_global_settings'] |
|
534 | c.inherit_global_settings = defaults['inherit_global_settings'] | |
679 |
|
535 | |||
680 | application_form = RepoVcsSettingsForm(repo_name)() |
|
536 | application_form = RepoVcsSettingsForm(repo_name)() | |
681 | try: |
|
537 | try: | |
682 | form_result = application_form.to_python(dict(request.POST)) |
|
538 | form_result = application_form.to_python(dict(request.POST)) | |
683 | except formencode.Invalid as errors: |
|
539 | except formencode.Invalid as errors: | |
684 | h.flash( |
|
540 | h.flash( | |
685 | _("Some form inputs contain invalid data."), |
|
541 | _("Some form inputs contain invalid data."), | |
686 | category='error') |
|
542 | category='error') | |
687 | return htmlfill.render( |
|
543 | return htmlfill.render( | |
688 | render('admin/repos/repo_edit.mako'), |
|
544 | render('admin/repos/repo_edit.mako'), | |
689 | defaults=errors.value, |
|
545 | defaults=errors.value, | |
690 | errors=errors.error_dict or {}, |
|
546 | errors=errors.error_dict or {}, | |
691 | prefix_error=False, |
|
547 | prefix_error=False, | |
692 | encoding="UTF-8", |
|
548 | encoding="UTF-8", | |
693 | force_defaults=False |
|
549 | force_defaults=False | |
694 | ) |
|
550 | ) | |
695 |
|
551 | |||
696 | try: |
|
552 | try: | |
697 | inherit_global_settings = form_result['inherit_global_settings'] |
|
553 | inherit_global_settings = form_result['inherit_global_settings'] | |
698 | model.create_or_update_repo_settings( |
|
554 | model.create_or_update_repo_settings( | |
699 | form_result, inherit_global_settings=inherit_global_settings) |
|
555 | form_result, inherit_global_settings=inherit_global_settings) | |
700 | except Exception: |
|
556 | except Exception: | |
701 | log.exception("Exception while updating settings") |
|
557 | log.exception("Exception while updating settings") | |
702 | h.flash( |
|
558 | h.flash( | |
703 | _('Error occurred during updating repository VCS settings'), |
|
559 | _('Error occurred during updating repository VCS settings'), | |
704 | category='error') |
|
560 | category='error') | |
705 | else: |
|
561 | else: | |
706 | Session().commit() |
|
562 | Session().commit() | |
707 | h.flash(_('Updated VCS settings'), category='success') |
|
563 | h.flash(_('Updated VCS settings'), category='success') | |
708 | return redirect(url('repo_vcs_settings', repo_name=repo_name)) |
|
564 | return redirect(url('repo_vcs_settings', repo_name=repo_name)) | |
709 |
|
565 | |||
710 | return htmlfill.render( |
|
566 | return htmlfill.render( | |
711 | render('admin/repos/repo_edit.mako'), |
|
567 | render('admin/repos/repo_edit.mako'), | |
712 | defaults=self._vcs_form_defaults(repo_name), |
|
568 | defaults=self._vcs_form_defaults(repo_name), | |
713 | encoding="UTF-8", |
|
569 | encoding="UTF-8", | |
714 | force_defaults=False) |
|
570 | force_defaults=False) | |
715 |
|
571 | |||
716 | @HasRepoPermissionAllDecorator('repository.admin') |
|
572 | @HasRepoPermissionAllDecorator('repository.admin') | |
717 | @auth.CSRFRequired() |
|
573 | @auth.CSRFRequired() | |
718 | @jsonify |
|
574 | @jsonify | |
719 | def repo_delete_svn_pattern(self, repo_name): |
|
575 | def repo_delete_svn_pattern(self, repo_name): | |
720 | if not request.is_xhr: |
|
576 | if not request.is_xhr: | |
721 | return False |
|
577 | return False | |
722 |
|
578 | |||
723 | delete_pattern_id = request.POST.get('delete_svn_pattern') |
|
579 | delete_pattern_id = request.POST.get('delete_svn_pattern') | |
724 | model = VcsSettingsModel(repo=repo_name) |
|
580 | model = VcsSettingsModel(repo=repo_name) | |
725 | try: |
|
581 | try: | |
726 | model.delete_repo_svn_pattern(delete_pattern_id) |
|
582 | model.delete_repo_svn_pattern(delete_pattern_id) | |
727 | except SettingNotFound: |
|
583 | except SettingNotFound: | |
728 | raise HTTPBadRequest() |
|
584 | raise HTTPBadRequest() | |
729 |
|
585 | |||
730 | Session().commit() |
|
586 | Session().commit() | |
731 | return True |
|
587 | return True | |
732 |
|
588 | |||
733 | def _vcs_form_defaults(self, repo_name): |
|
589 | def _vcs_form_defaults(self, repo_name): | |
734 | model = VcsSettingsModel(repo=repo_name) |
|
590 | model = VcsSettingsModel(repo=repo_name) | |
735 | global_defaults = model.get_global_settings() |
|
591 | global_defaults = model.get_global_settings() | |
736 |
|
592 | |||
737 | repo_defaults = {} |
|
593 | repo_defaults = {} | |
738 | repo_defaults.update(global_defaults) |
|
594 | repo_defaults.update(global_defaults) | |
739 | repo_defaults.update(model.get_repo_settings()) |
|
595 | repo_defaults.update(model.get_repo_settings()) | |
740 |
|
596 | |||
741 | global_defaults = { |
|
597 | global_defaults = { | |
742 | '{}_inherited'.format(k): global_defaults[k] |
|
598 | '{}_inherited'.format(k): global_defaults[k] | |
743 | for k in global_defaults} |
|
599 | for k in global_defaults} | |
744 |
|
600 | |||
745 | defaults = { |
|
601 | defaults = { | |
746 | 'inherit_global_settings': model.inherit_global_settings |
|
602 | 'inherit_global_settings': model.inherit_global_settings | |
747 | } |
|
603 | } | |
748 | defaults.update(global_defaults) |
|
604 | defaults.update(global_defaults) | |
749 | defaults.update(repo_defaults) |
|
605 | defaults.update(repo_defaults) | |
750 | defaults.update({ |
|
606 | defaults.update({ | |
751 | 'new_svn_branch': '', |
|
607 | 'new_svn_branch': '', | |
752 | 'new_svn_tag': '', |
|
608 | 'new_svn_tag': '', | |
753 | }) |
|
609 | }) | |
754 | return defaults |
|
610 | return defaults |
@@ -1,183 +1,184 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 |
|
2 | |||
3 | # Copyright (C) 2017-2017 RhodeCode GmbH |
|
3 | # Copyright (C) 2017-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 logging |
|
21 | import logging | |
22 | import datetime |
|
22 | import datetime | |
23 |
|
23 | |||
24 | from rhodecode.model import meta |
|
24 | from rhodecode.model import meta | |
25 | from rhodecode.model.db import User, UserLog, Repository |
|
25 | from rhodecode.model.db import User, UserLog, Repository | |
26 |
|
26 | |||
27 |
|
27 | |||
28 | log = logging.getLogger(__name__) |
|
28 | log = logging.getLogger(__name__) | |
29 |
|
29 | |||
30 |
|
30 | |||
31 | ACTIONS = { |
|
31 | ACTIONS = { | |
32 | 'user.login.success': {}, |
|
32 | 'user.login.success': {}, | |
33 | 'user.login.failure': {}, |
|
33 | 'user.login.failure': {}, | |
34 | 'user.logout': {}, |
|
34 | 'user.logout': {}, | |
35 | 'user.password.reset_request': {}, |
|
35 | 'user.password.reset_request': {}, | |
36 | 'user.push': {}, |
|
36 | 'user.push': {}, | |
37 | 'user.pull': {}, |
|
37 | 'user.pull': {}, | |
38 |
|
38 | |||
39 |
'repo. |
|
39 | 'repo.create': {}, | |
40 | 'repo.edit': {}, |
|
40 | 'repo.edit': {}, | |
41 | 'repo.edit.permissions': {}, |
|
41 | 'repo.edit.permissions': {}, | |
|
42 | 'repo.delete': {}, | |||
42 | 'repo.commit.strip': {}, |
|
43 | 'repo.commit.strip': {}, | |
43 | 'repo.archive.download': {}, |
|
44 | 'repo.archive.download': {}, | |
44 | } |
|
45 | } | |
45 |
|
46 | |||
46 |
|
47 | |||
47 | class UserWrap(object): |
|
48 | class UserWrap(object): | |
48 | """ |
|
49 | """ | |
49 | Fake object used to imitate AuthUser |
|
50 | Fake object used to imitate AuthUser | |
50 | """ |
|
51 | """ | |
51 |
|
52 | |||
52 | def __init__(self, user_id=None, username=None, ip_addr=None): |
|
53 | def __init__(self, user_id=None, username=None, ip_addr=None): | |
53 | self.user_id = user_id |
|
54 | self.user_id = user_id | |
54 | self.username = username |
|
55 | self.username = username | |
55 | self.ip_addr = ip_addr |
|
56 | self.ip_addr = ip_addr | |
56 |
|
57 | |||
57 |
|
58 | |||
58 | class RepoWrap(object): |
|
59 | class RepoWrap(object): | |
59 | """ |
|
60 | """ | |
60 | Fake object used to imitate RepoObject that audit logger requires |
|
61 | Fake object used to imitate RepoObject that audit logger requires | |
61 | """ |
|
62 | """ | |
62 |
|
63 | |||
63 | def __init__(self, repo_id=None, repo_name=None): |
|
64 | def __init__(self, repo_id=None, repo_name=None): | |
64 | self.repo_id = repo_id |
|
65 | self.repo_id = repo_id | |
65 | self.repo_name = repo_name |
|
66 | self.repo_name = repo_name | |
66 |
|
67 | |||
67 |
|
68 | |||
68 | def _store_log(action_name, action_data, user_id, username, user_data, |
|
69 | def _store_log(action_name, action_data, user_id, username, user_data, | |
69 | ip_address, repository_id, repository_name): |
|
70 | ip_address, repository_id, repository_name): | |
70 | user_log = UserLog() |
|
71 | user_log = UserLog() | |
71 | user_log.version = UserLog.VERSION_2 |
|
72 | user_log.version = UserLog.VERSION_2 | |
72 |
|
73 | |||
73 | user_log.action = action_name |
|
74 | user_log.action = action_name | |
74 | user_log.action_data = action_data |
|
75 | user_log.action_data = action_data | |
75 |
|
76 | |||
76 | user_log.user_ip = ip_address |
|
77 | user_log.user_ip = ip_address | |
77 |
|
78 | |||
78 | user_log.user_id = user_id |
|
79 | user_log.user_id = user_id | |
79 | user_log.username = username |
|
80 | user_log.username = username | |
80 | user_log.user_data = user_data |
|
81 | user_log.user_data = user_data | |
81 |
|
82 | |||
82 | user_log.repository_id = repository_id |
|
83 | user_log.repository_id = repository_id | |
83 | user_log.repository_name = repository_name |
|
84 | user_log.repository_name = repository_name | |
84 |
|
85 | |||
85 | user_log.action_date = datetime.datetime.now() |
|
86 | user_log.action_date = datetime.datetime.now() | |
86 |
|
87 | |||
87 | log.info('AUDIT: Logging action: `%s` by user:id:%s[%s] ip:%s', |
|
88 | log.info('AUDIT: Logging action: `%s` by user:id:%s[%s] ip:%s', | |
88 | action_name, user_id, username, ip_address) |
|
89 | action_name, user_id, username, ip_address) | |
89 |
|
90 | |||
90 | return user_log |
|
91 | return user_log | |
91 |
|
92 | |||
92 |
|
93 | |||
93 | def store( |
|
94 | def store( | |
94 | action, user, action_data=None, user_data=None, ip_addr=None, |
|
95 | action, user, action_data=None, user_data=None, ip_addr=None, | |
95 | repo=None, sa_session=None, commit=False): |
|
96 | repo=None, sa_session=None, commit=False): | |
96 | """ |
|
97 | """ | |
97 | Audit logger for various actions made by users, typically this results in a call such:: |
|
98 | Audit logger for various actions made by users, typically this results in a call such:: | |
98 |
|
99 | |||
99 | from rhodecode.lib import audit_logger |
|
100 | from rhodecode.lib import audit_logger | |
100 |
|
101 | |||
101 | audit_logger.store( |
|
102 | audit_logger.store( | |
102 | action='repo.edit', user=self._rhodecode_user) |
|
103 | action='repo.edit', user=self._rhodecode_user) | |
103 | audit_logger.store( |
|
104 | audit_logger.store( | |
104 | action='repo.delete', |
|
105 | action='repo.delete', action_data={'repo_data': repo_data}, | |
105 | user=audit_logger.UserWrap(username='itried-login', ip_addr='8.8.8.8')) |
|
106 | user=audit_logger.UserWrap(username='itried-login', ip_addr='8.8.8.8')) | |
106 |
|
107 | |||
107 | # repo action |
|
108 | # repo action | |
108 | audit_logger.store( |
|
109 | audit_logger.store( | |
109 | action='repo.delete', |
|
110 | action='repo.delete', | |
110 | user=audit_logger.UserWrap(username='itried-login', ip_addr='8.8.8.8'), |
|
111 | user=audit_logger.UserWrap(username='itried-login', ip_addr='8.8.8.8'), | |
111 | repo=audit_logger.RepoWrap(repo_name='some-repo')) |
|
112 | repo=audit_logger.RepoWrap(repo_name='some-repo')) | |
112 |
|
113 | |||
113 | # repo action, when we know and have the repository object already |
|
114 | # repo action, when we know and have the repository object already | |
114 | audit_logger.store( |
|
115 | audit_logger.store( | |
115 | action='repo.delete', |
|
116 | action='repo.delete', | |
116 | user=audit_logger.UserWrap(username='itried-login', ip_addr='8.8.8.8'), |
|
117 | user=audit_logger.UserWrap(username='itried-login', ip_addr='8.8.8.8'), | |
117 | repo=repo_object) |
|
118 | repo=repo_object) | |
118 |
|
119 | |||
119 | # without an user ? |
|
120 | # without an user ? | |
120 | audit_logger.store( |
|
121 | audit_logger.store( | |
121 | action='user.login.failure', |
|
122 | action='user.login.failure', | |
122 | user=audit_logger.UserWrap( |
|
123 | user=audit_logger.UserWrap( | |
123 | username=self.request.params.get('username'), |
|
124 | username=self.request.params.get('username'), | |
124 | ip_addr=self.request.remote_addr)) |
|
125 | ip_addr=self.request.remote_addr)) | |
125 |
|
126 | |||
126 | """ |
|
127 | """ | |
127 | from rhodecode.lib.utils2 import safe_unicode |
|
128 | from rhodecode.lib.utils2 import safe_unicode | |
128 | from rhodecode.lib.auth import AuthUser |
|
129 | from rhodecode.lib.auth import AuthUser | |
129 |
|
130 | |||
130 | if action not in ACTIONS: |
|
131 | if action not in ACTIONS: | |
131 | raise ValueError('Action `{}` not in valid actions'.format(action)) |
|
132 | raise ValueError('Action `{}` not in valid actions'.format(action)) | |
132 |
|
133 | |||
133 | if not sa_session: |
|
134 | if not sa_session: | |
134 | sa_session = meta.Session() |
|
135 | sa_session = meta.Session() | |
135 |
|
136 | |||
136 | try: |
|
137 | try: | |
137 | username = getattr(user, 'username', None) |
|
138 | username = getattr(user, 'username', None) | |
138 | if not username: |
|
139 | if not username: | |
139 | pass |
|
140 | pass | |
140 |
|
141 | |||
141 | user_id = getattr(user, 'user_id', None) |
|
142 | user_id = getattr(user, 'user_id', None) | |
142 | if not user_id: |
|
143 | if not user_id: | |
143 | # maybe we have username ? Try to figure user_id from username |
|
144 | # maybe we have username ? Try to figure user_id from username | |
144 | if username: |
|
145 | if username: | |
145 | user_id = getattr( |
|
146 | user_id = getattr( | |
146 | User.get_by_username(username), 'user_id', None) |
|
147 | User.get_by_username(username), 'user_id', None) | |
147 |
|
148 | |||
148 | ip_addr = ip_addr or getattr(user, 'ip_addr', None) |
|
149 | ip_addr = ip_addr or getattr(user, 'ip_addr', None) | |
149 | if not ip_addr: |
|
150 | if not ip_addr: | |
150 | pass |
|
151 | pass | |
151 |
|
152 | |||
152 | if not user_data: |
|
153 | if not user_data: | |
153 | # try to get this from the auth user |
|
154 | # try to get this from the auth user | |
154 | if isinstance(user, AuthUser): |
|
155 | if isinstance(user, AuthUser): | |
155 | user_data = { |
|
156 | user_data = { | |
156 | 'username': user.username, |
|
157 | 'username': user.username, | |
157 | 'email': user.email, |
|
158 | 'email': user.email, | |
158 | } |
|
159 | } | |
159 |
|
160 | |||
160 | repository_name = getattr(repo, 'repo_name', None) |
|
161 | repository_name = getattr(repo, 'repo_name', None) | |
161 | repository_id = getattr(repo, 'repo_id', None) |
|
162 | repository_id = getattr(repo, 'repo_id', None) | |
162 | if not repository_id: |
|
163 | if not repository_id: | |
163 | # maybe we have repo_name ? Try to figure repo_id from repo_name |
|
164 | # maybe we have repo_name ? Try to figure repo_id from repo_name | |
164 | if repository_name: |
|
165 | if repository_name: | |
165 | repository_id = getattr( |
|
166 | repository_id = getattr( | |
166 | Repository.get_by_repo_name(repository_name), 'repo_id', None) |
|
167 | Repository.get_by_repo_name(repository_name), 'repo_id', None) | |
167 |
|
168 | |||
168 | user_log = _store_log( |
|
169 | user_log = _store_log( | |
169 | action_name=safe_unicode(action), |
|
170 | action_name=safe_unicode(action), | |
170 | action_data=action_data or {}, |
|
171 | action_data=action_data or {}, | |
171 | user_id=user_id, |
|
172 | user_id=user_id, | |
172 | username=username, |
|
173 | username=username, | |
173 | user_data=user_data or {}, |
|
174 | user_data=user_data or {}, | |
174 | ip_address=safe_unicode(ip_addr), |
|
175 | ip_address=safe_unicode(ip_addr), | |
175 | repository_id=repository_id, |
|
176 | repository_id=repository_id, | |
176 | repository_name=repository_name |
|
177 | repository_name=repository_name | |
177 | ) |
|
178 | ) | |
178 | sa_session.add(user_log) |
|
179 | sa_session.add(user_log) | |
179 | if commit: |
|
180 | if commit: | |
180 | sa_session.commit() |
|
181 | sa_session.commit() | |
181 |
|
182 | |||
182 | except Exception: |
|
183 | except Exception: | |
183 | log.exception('AUDIT: failed to store audit log') |
|
184 | log.exception('AUDIT: failed to store audit log') |
@@ -1,121 +1,127 b'' | |||||
1 |
|
1 | |||
2 | /****************************************************************************** |
|
2 | /****************************************************************************** | |
3 | * * |
|
3 | * * | |
4 | * DO NOT CHANGE THIS FILE MANUALLY * |
|
4 | * DO NOT CHANGE THIS FILE MANUALLY * | |
5 | * * |
|
5 | * * | |
6 | * * |
|
6 | * * | |
7 | * This file is automatically generated when the app starts up with * |
|
7 | * This file is automatically generated when the app starts up with * | |
8 | * generate_js_files = true * |
|
8 | * generate_js_files = true * | |
9 | * * |
|
9 | * * | |
10 | * To add a route here pass jsroute=True to the route definition in the app * |
|
10 | * To add a route here pass jsroute=True to the route definition in the app * | |
11 | * * |
|
11 | * * | |
12 | ******************************************************************************/ |
|
12 | ******************************************************************************/ | |
13 | function registerRCRoutes() { |
|
13 | function registerRCRoutes() { | |
14 | // routes registration |
|
14 | // routes registration | |
15 | pyroutes.register('home', '/', []); |
|
15 | pyroutes.register('home', '/', []); | |
16 | pyroutes.register('new_repo', '/_admin/create_repository', []); |
|
16 | pyroutes.register('new_repo', '/_admin/create_repository', []); | |
17 | pyroutes.register('edit_user', '/_admin/users/%(user_id)s/edit', ['user_id']); |
|
17 | pyroutes.register('edit_user', '/_admin/users/%(user_id)s/edit', ['user_id']); | |
18 | pyroutes.register('edit_user_group_members', '/_admin/user_groups/%(user_group_id)s/edit/members', ['user_group_id']); |
|
18 | pyroutes.register('edit_user_group_members', '/_admin/user_groups/%(user_group_id)s/edit/members', ['user_group_id']); | |
19 | pyroutes.register('gists', '/_admin/gists', []); |
|
19 | pyroutes.register('gists', '/_admin/gists', []); | |
20 | pyroutes.register('new_gist', '/_admin/gists/new', []); |
|
20 | pyroutes.register('new_gist', '/_admin/gists/new', []); | |
21 | pyroutes.register('toggle_following', '/_admin/toggle_following', []); |
|
21 | pyroutes.register('toggle_following', '/_admin/toggle_following', []); | |
22 | pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']); |
|
22 | pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']); | |
23 | pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']); |
|
23 | pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']); | |
24 | pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']); |
|
24 | pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']); | |
25 | pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/default-reviewers', ['repo_name']); |
|
25 | pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/default-reviewers', ['repo_name']); | |
26 | pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']); |
|
26 | pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']); | |
27 | pyroutes.register('changeset_comment', '/%(repo_name)s/changeset/%(revision)s/comment', ['repo_name', 'revision']); |
|
27 | pyroutes.register('changeset_comment', '/%(repo_name)s/changeset/%(revision)s/comment', ['repo_name', 'revision']); | |
28 | pyroutes.register('changeset_comment_preview', '/%(repo_name)s/changeset/comment/preview', ['repo_name']); |
|
28 | pyroutes.register('changeset_comment_preview', '/%(repo_name)s/changeset/comment/preview', ['repo_name']); | |
29 | pyroutes.register('changeset_comment_delete', '/%(repo_name)s/changeset/comment/%(comment_id)s/delete', ['repo_name', 'comment_id']); |
|
29 | pyroutes.register('changeset_comment_delete', '/%(repo_name)s/changeset/comment/%(comment_id)s/delete', ['repo_name', 'comment_id']); | |
30 | pyroutes.register('changeset_info', '/%(repo_name)s/changeset_info/%(revision)s', ['repo_name', 'revision']); |
|
30 | pyroutes.register('changeset_info', '/%(repo_name)s/changeset_info/%(revision)s', ['repo_name', 'revision']); | |
31 | pyroutes.register('compare_url', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']); |
|
31 | pyroutes.register('compare_url', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']); | |
32 | pyroutes.register('pullrequest_home', '/%(repo_name)s/pull-request/new', ['repo_name']); |
|
32 | pyroutes.register('pullrequest_home', '/%(repo_name)s/pull-request/new', ['repo_name']); | |
33 | pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']); |
|
33 | pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']); | |
34 | pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']); |
|
34 | pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']); | |
35 | pyroutes.register('pullrequest_repo_destinations', '/%(repo_name)s/pull-request/repo-destinations', ['repo_name']); |
|
35 | pyroutes.register('pullrequest_repo_destinations', '/%(repo_name)s/pull-request/repo-destinations', ['repo_name']); | |
36 | pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']); |
|
36 | pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']); | |
37 | pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']); |
|
37 | pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']); | |
38 | pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']); |
|
38 | pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']); | |
39 | pyroutes.register('pullrequest_comment', '/%(repo_name)s/pull-request-comment/%(pull_request_id)s', ['repo_name', 'pull_request_id']); |
|
39 | pyroutes.register('pullrequest_comment', '/%(repo_name)s/pull-request-comment/%(pull_request_id)s', ['repo_name', 'pull_request_id']); | |
40 | pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request-comment/%(comment_id)s/delete', ['repo_name', 'comment_id']); |
|
40 | pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request-comment/%(comment_id)s/delete', ['repo_name', 'comment_id']); | |
41 | pyroutes.register('changelog_home', '/%(repo_name)s/changelog', ['repo_name']); |
|
41 | pyroutes.register('changelog_home', '/%(repo_name)s/changelog', ['repo_name']); | |
42 | pyroutes.register('changelog_file_home', '/%(repo_name)s/changelog/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); |
|
42 | pyroutes.register('changelog_file_home', '/%(repo_name)s/changelog/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); | |
43 | pyroutes.register('changelog_elements', '/%(repo_name)s/changelog_details', ['repo_name']); |
|
43 | pyroutes.register('changelog_elements', '/%(repo_name)s/changelog_details', ['repo_name']); | |
44 | pyroutes.register('files_home', '/%(repo_name)s/files/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); |
|
44 | pyroutes.register('files_home', '/%(repo_name)s/files/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); | |
45 | pyroutes.register('files_history_home', '/%(repo_name)s/history/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); |
|
45 | pyroutes.register('files_history_home', '/%(repo_name)s/history/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); | |
46 | pyroutes.register('files_authors_home', '/%(repo_name)s/authors/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); |
|
46 | pyroutes.register('files_authors_home', '/%(repo_name)s/authors/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); | |
47 | pyroutes.register('files_annotate_home', '/%(repo_name)s/annotate/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); |
|
47 | pyroutes.register('files_annotate_home', '/%(repo_name)s/annotate/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); | |
48 | pyroutes.register('files_annotate_previous', '/%(repo_name)s/annotate-previous/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); |
|
48 | pyroutes.register('files_annotate_previous', '/%(repo_name)s/annotate-previous/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); | |
49 | pyroutes.register('files_archive_home', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']); |
|
49 | pyroutes.register('files_archive_home', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']); | |
50 | pyroutes.register('files_nodelist_home', '/%(repo_name)s/nodelist/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); |
|
50 | pyroutes.register('files_nodelist_home', '/%(repo_name)s/nodelist/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']); | |
51 | pyroutes.register('files_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
51 | pyroutes.register('files_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
52 | pyroutes.register('summary_home_slash', '/%(repo_name)s/', ['repo_name']); |
|
52 | pyroutes.register('summary_home_slash', '/%(repo_name)s/', ['repo_name']); | |
53 | pyroutes.register('summary_home', '/%(repo_name)s', ['repo_name']); |
|
53 | pyroutes.register('summary_home', '/%(repo_name)s', ['repo_name']); | |
54 | pyroutes.register('favicon', '/favicon.ico', []); |
|
54 | pyroutes.register('favicon', '/favicon.ico', []); | |
55 | pyroutes.register('robots', '/robots.txt', []); |
|
55 | pyroutes.register('robots', '/robots.txt', []); | |
56 | pyroutes.register('auth_home', '/_admin/auth*traverse', []); |
|
56 | pyroutes.register('auth_home', '/_admin/auth*traverse', []); | |
57 | pyroutes.register('global_integrations_new', '/_admin/integrations/new', []); |
|
57 | pyroutes.register('global_integrations_new', '/_admin/integrations/new', []); | |
58 | pyroutes.register('global_integrations_home', '/_admin/integrations', []); |
|
58 | pyroutes.register('global_integrations_home', '/_admin/integrations', []); | |
59 | pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']); |
|
59 | pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']); | |
60 | pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']); |
|
60 | pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']); | |
61 | pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']); |
|
61 | pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']); | |
62 | pyroutes.register('repo_group_integrations_home', '%(repo_group_name)s/settings/integrations', ['repo_group_name']); |
|
62 | pyroutes.register('repo_group_integrations_home', '%(repo_group_name)s/settings/integrations', ['repo_group_name']); | |
63 | pyroutes.register('repo_group_integrations_list', '%(repo_group_name)s/settings/integrations/%(integration)s', ['repo_group_name', 'integration']); |
|
63 | pyroutes.register('repo_group_integrations_list', '%(repo_group_name)s/settings/integrations/%(integration)s', ['repo_group_name', 'integration']); | |
64 | pyroutes.register('repo_group_integrations_new', '%(repo_group_name)s/settings/integrations/new', ['repo_group_name']); |
|
64 | pyroutes.register('repo_group_integrations_new', '%(repo_group_name)s/settings/integrations/new', ['repo_group_name']); | |
65 | pyroutes.register('repo_group_integrations_create', '%(repo_group_name)s/settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']); |
|
65 | pyroutes.register('repo_group_integrations_create', '%(repo_group_name)s/settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']); | |
66 | pyroutes.register('repo_group_integrations_edit', '%(repo_group_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']); |
|
66 | pyroutes.register('repo_group_integrations_edit', '%(repo_group_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']); | |
67 | pyroutes.register('repo_integrations_home', '%(repo_name)s/settings/integrations', ['repo_name']); |
|
67 | pyroutes.register('repo_integrations_home', '%(repo_name)s/settings/integrations', ['repo_name']); | |
68 | pyroutes.register('repo_integrations_list', '%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']); |
|
68 | pyroutes.register('repo_integrations_list', '%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']); | |
69 | pyroutes.register('repo_integrations_new', '%(repo_name)s/settings/integrations/new', ['repo_name']); |
|
69 | pyroutes.register('repo_integrations_new', '%(repo_name)s/settings/integrations/new', ['repo_name']); | |
70 | pyroutes.register('repo_integrations_create', '%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']); |
|
70 | pyroutes.register('repo_integrations_create', '%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']); | |
71 | pyroutes.register('repo_integrations_edit', '%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']); |
|
71 | pyroutes.register('repo_integrations_edit', '%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']); | |
72 | pyroutes.register('ops_ping', '_admin/ops/ping', []); |
|
72 | pyroutes.register('ops_ping', '_admin/ops/ping', []); | |
73 | pyroutes.register('admin_settings_open_source', '_admin/settings/open_source', []); |
|
73 | pyroutes.register('admin_settings_open_source', '_admin/settings/open_source', []); | |
74 | pyroutes.register('admin_settings_vcs_svn_generate_cfg', '_admin/settings/vcs/svn_generate_cfg', []); |
|
74 | pyroutes.register('admin_settings_vcs_svn_generate_cfg', '_admin/settings/vcs/svn_generate_cfg', []); | |
75 | pyroutes.register('admin_settings_system', '_admin/settings/system', []); |
|
75 | pyroutes.register('admin_settings_system', '_admin/settings/system', []); | |
76 | pyroutes.register('admin_settings_system_update', '_admin/settings/system/updates', []); |
|
76 | pyroutes.register('admin_settings_system_update', '_admin/settings/system/updates', []); | |
77 | pyroutes.register('admin_settings_sessions', '_admin/settings/sessions', []); |
|
77 | pyroutes.register('admin_settings_sessions', '_admin/settings/sessions', []); | |
78 | pyroutes.register('admin_settings_sessions_cleanup', '_admin/settings/sessions/cleanup', []); |
|
78 | pyroutes.register('admin_settings_sessions_cleanup', '_admin/settings/sessions/cleanup', []); | |
79 | pyroutes.register('users', '_admin/users', []); |
|
79 | pyroutes.register('users', '_admin/users', []); | |
80 | pyroutes.register('users_data', '_admin/users_data', []); |
|
80 | pyroutes.register('users_data', '_admin/users_data', []); | |
81 | pyroutes.register('edit_user_auth_tokens', '_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']); |
|
81 | pyroutes.register('edit_user_auth_tokens', '_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']); | |
82 | pyroutes.register('edit_user_auth_tokens_add', '_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']); |
|
82 | pyroutes.register('edit_user_auth_tokens_add', '_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']); | |
83 | pyroutes.register('edit_user_auth_tokens_delete', '_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']); |
|
83 | pyroutes.register('edit_user_auth_tokens_delete', '_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']); | |
84 | pyroutes.register('edit_user_groups_management', '_admin/users/%(user_id)s/edit/groups_management', ['user_id']); |
|
84 | pyroutes.register('edit_user_groups_management', '_admin/users/%(user_id)s/edit/groups_management', ['user_id']); | |
85 | pyroutes.register('edit_user_groups_management_updates', '_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']); |
|
85 | pyroutes.register('edit_user_groups_management_updates', '_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']); | |
86 | pyroutes.register('edit_user_audit_logs', '_admin/users/%(user_id)s/edit/audit', ['user_id']); |
|
86 | pyroutes.register('edit_user_audit_logs', '_admin/users/%(user_id)s/edit/audit', ['user_id']); | |
87 | pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []); |
|
87 | pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []); | |
88 | pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []); |
|
88 | pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []); | |
89 | pyroutes.register('channelstream_proxy', '/_channelstream', []); |
|
89 | pyroutes.register('channelstream_proxy', '/_channelstream', []); | |
90 | pyroutes.register('login', '/_admin/login', []); |
|
90 | pyroutes.register('login', '/_admin/login', []); | |
91 | pyroutes.register('logout', '/_admin/logout', []); |
|
91 | pyroutes.register('logout', '/_admin/logout', []); | |
92 | pyroutes.register('register', '/_admin/register', []); |
|
92 | pyroutes.register('register', '/_admin/register', []); | |
93 | pyroutes.register('reset_password', '/_admin/password_reset', []); |
|
93 | pyroutes.register('reset_password', '/_admin/password_reset', []); | |
94 | pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []); |
|
94 | pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []); | |
95 | pyroutes.register('user_autocomplete_data', '/_users', []); |
|
95 | pyroutes.register('user_autocomplete_data', '/_users', []); | |
96 | pyroutes.register('user_group_autocomplete_data', '/_user_groups', []); |
|
96 | pyroutes.register('user_group_autocomplete_data', '/_user_groups', []); | |
97 | pyroutes.register('repo_list_data', '/_repos', []); |
|
97 | pyroutes.register('repo_list_data', '/_repos', []); | |
98 | pyroutes.register('goto_switcher_data', '/_goto_data', []); |
|
98 | pyroutes.register('goto_switcher_data', '/_goto_data', []); | |
|
99 | pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']); | |||
99 | pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']); |
|
100 | pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']); | |
100 | pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']); |
|
101 | pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']); | |
101 | pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']); |
|
102 | pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']); | |
102 | pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']); |
|
103 | pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']); | |
|
104 | 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']); | |||
|
106 | pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']); | |||
|
107 | pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']); | |||
|
108 | pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']); | |||
103 | pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']); |
|
109 | pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']); | |
104 | pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']); |
|
110 | pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']); | |
105 | pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']); |
|
111 | pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']); | |
106 | pyroutes.register('repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']); |
|
112 | pyroutes.register('repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']); | |
107 | pyroutes.register('repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']); |
|
113 | pyroutes.register('repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']); | |
108 | pyroutes.register('strip', '/%(repo_name)s/settings/strip', ['repo_name']); |
|
114 | pyroutes.register('strip', '/%(repo_name)s/settings/strip', ['repo_name']); | |
109 | pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']); |
|
115 | pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']); | |
110 | pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']); |
|
116 | pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']); | |
111 | pyroutes.register('search', '/_admin/search', []); |
|
117 | pyroutes.register('search', '/_admin/search', []); | |
112 | pyroutes.register('search_repo', '/%(repo_name)s/search', ['repo_name']); |
|
118 | pyroutes.register('search_repo', '/%(repo_name)s/search', ['repo_name']); | |
113 | pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']); |
|
119 | pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']); | |
114 | pyroutes.register('my_account_profile', '/_admin/my_account/profile', []); |
|
120 | pyroutes.register('my_account_profile', '/_admin/my_account/profile', []); | |
115 | pyroutes.register('my_account_password', '/_admin/my_account/password', []); |
|
121 | pyroutes.register('my_account_password', '/_admin/my_account/password', []); | |
116 | pyroutes.register('my_account_password_update', '/_admin/my_account/password', []); |
|
122 | pyroutes.register('my_account_password_update', '/_admin/my_account/password', []); | |
117 | pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []); |
|
123 | pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []); | |
118 | pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []); |
|
124 | pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []); | |
119 | pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []); |
|
125 | pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []); | |
120 | pyroutes.register('apiv2', '/_admin/api', []); |
|
126 | pyroutes.register('apiv2', '/_admin/api', []); | |
121 | } |
|
127 | } |
@@ -1,95 +1,95 b'' | |||||
1 | ## -*- coding: utf-8 -*- |
|
1 | ## -*- coding: utf-8 -*- | |
2 | ## |
|
2 | ## | |
3 | ## See also repo_settings.html |
|
3 | ## See also repo_settings.html | |
4 | ## |
|
4 | ## | |
5 | <%inherit file="/base/base.mako"/> |
|
5 | <%inherit file="/base/base.mako"/> | |
6 |
|
6 | |||
7 | <%def name="title()"> |
|
7 | <%def name="title()"> | |
8 | ${_('%s repository settings') % c.repo_info.repo_name} |
|
8 | ${_('%s repository settings') % c.repo_info.repo_name} | |
9 | %if c.rhodecode_name: |
|
9 | %if c.rhodecode_name: | |
10 | · ${h.branding(c.rhodecode_name)} |
|
10 | · ${h.branding(c.rhodecode_name)} | |
11 | %endif |
|
11 | %endif | |
12 | </%def> |
|
12 | </%def> | |
13 |
|
13 | |||
14 | <%def name="breadcrumbs_links()"> |
|
14 | <%def name="breadcrumbs_links()"> | |
15 | ${_('Settings')} |
|
15 | ${_('Settings')} | |
16 | </%def> |
|
16 | </%def> | |
17 |
|
17 | |||
18 | <%def name="menu_bar_nav()"> |
|
18 | <%def name="menu_bar_nav()"> | |
19 | ${self.menu_items(active='repositories')} |
|
19 | ${self.menu_items(active='repositories')} | |
20 | </%def> |
|
20 | </%def> | |
21 |
|
21 | |||
22 | <%def name="menu_bar_subnav()"> |
|
22 | <%def name="menu_bar_subnav()"> | |
23 | ${self.repo_menu(active='options')} |
|
23 | ${self.repo_menu(active='options')} | |
24 | </%def> |
|
24 | </%def> | |
25 |
|
25 | |||
26 | <%def name="main_content()"> |
|
26 | <%def name="main_content()"> | |
27 | <%include file="/admin/repos/repo_edit_${c.active}.mako"/> |
|
27 | <%include file="/admin/repos/repo_edit_${c.active}.mako"/> | |
28 | </%def> |
|
28 | </%def> | |
29 |
|
29 | |||
30 |
|
30 | |||
31 | <%def name="main()"> |
|
31 | <%def name="main()"> | |
32 | <div class="box"> |
|
32 | <div class="box"> | |
33 | <div class="title"> |
|
33 | <div class="title"> | |
34 | ${self.repo_page_title(c.rhodecode_db_repo)} |
|
34 | ${self.repo_page_title(c.rhodecode_db_repo)} | |
35 | ${self.breadcrumbs()} |
|
35 | ${self.breadcrumbs()} | |
36 | </div> |
|
36 | </div> | |
37 |
|
37 | |||
38 | <div class="sidebar-col-wrapper scw-small"> |
|
38 | <div class="sidebar-col-wrapper scw-small"> | |
39 | <div class="sidebar"> |
|
39 | <div class="sidebar"> | |
40 | <ul class="nav nav-pills nav-stacked"> |
|
40 | <ul class="nav nav-pills nav-stacked"> | |
41 | <li class="${'active' if c.active=='settings' else ''}"> |
|
41 | <li class="${'active' if c.active=='settings' else ''}"> | |
42 | <a href="${h.route_path('edit_repo', repo_name=c.repo_name)}">${_('Settings')}</a> |
|
42 | <a href="${h.route_path('edit_repo', repo_name=c.repo_name)}">${_('Settings')}</a> | |
43 | </li> |
|
43 | </li> | |
44 | <li class="${'active' if c.active=='permissions' else ''}"> |
|
44 | <li class="${'active' if c.active=='permissions' else ''}"> | |
45 | <a href="${h.route_path('edit_repo_perms', repo_name=c.repo_name)}">${_('Permissions')}</a> |
|
45 | <a href="${h.route_path('edit_repo_perms', repo_name=c.repo_name)}">${_('Permissions')}</a> | |
46 | </li> |
|
46 | </li> | |
47 | <li class="${'active' if c.active=='advanced' else ''}"> |
|
47 | <li class="${'active' if c.active=='advanced' else ''}"> | |
48 |
<a href="${h. |
|
48 | <a href="${h.route_path('edit_repo_advanced', repo_name=c.repo_name)}">${_('Advanced')}</a> | |
49 | </li> |
|
49 | </li> | |
50 | <li class="${'active' if c.active=='vcs' else ''}"> |
|
50 | <li class="${'active' if c.active=='vcs' else ''}"> | |
51 | <a href="${h.url('repo_vcs_settings', repo_name=c.repo_name)}">${_('VCS')}</a> |
|
51 | <a href="${h.url('repo_vcs_settings', repo_name=c.repo_name)}">${_('VCS')}</a> | |
52 | </li> |
|
52 | </li> | |
53 | <li class="${'active' if c.active=='fields' else ''}"> |
|
53 | <li class="${'active' if c.active=='fields' else ''}"> | |
54 | <a href="${h.url('edit_repo_fields', repo_name=c.repo_name)}">${_('Extra Fields')}</a> |
|
54 | <a href="${h.url('edit_repo_fields', repo_name=c.repo_name)}">${_('Extra Fields')}</a> | |
55 | </li> |
|
55 | </li> | |
56 | <li class="${'active' if c.active=='issuetracker' else ''}"> |
|
56 | <li class="${'active' if c.active=='issuetracker' else ''}"> | |
57 | <a href="${h.url('repo_settings_issuetracker', repo_name=c.repo_name)}">${_('Issue Tracker')}</a> |
|
57 | <a href="${h.url('repo_settings_issuetracker', repo_name=c.repo_name)}">${_('Issue Tracker')}</a> | |
58 | </li> |
|
58 | </li> | |
59 | <li class="${'active' if c.active=='caches' else ''}"> |
|
59 | <li class="${'active' if c.active=='caches' else ''}"> | |
60 | <a href="${h.route_path('edit_repo_caches', repo_name=c.repo_name)}">${_('Caches')}</a> |
|
60 | <a href="${h.route_path('edit_repo_caches', repo_name=c.repo_name)}">${_('Caches')}</a> | |
61 | </li> |
|
61 | </li> | |
62 | %if c.repo_info.repo_type != 'svn': |
|
62 | %if c.repo_info.repo_type != 'svn': | |
63 | <li class="${'active' if c.active=='remote' else ''}"> |
|
63 | <li class="${'active' if c.active=='remote' else ''}"> | |
64 | <a href="${h.url('edit_repo_remote', repo_name=c.repo_name)}">${_('Remote')}</a> |
|
64 | <a href="${h.url('edit_repo_remote', repo_name=c.repo_name)}">${_('Remote')}</a> | |
65 | </li> |
|
65 | </li> | |
66 | %endif |
|
66 | %endif | |
67 | <li class="${'active' if c.active=='statistics' else ''}"> |
|
67 | <li class="${'active' if c.active=='statistics' else ''}"> | |
68 | <a href="${h.url('edit_repo_statistics', repo_name=c.repo_name)}">${_('Statistics')}</a> |
|
68 | <a href="${h.url('edit_repo_statistics', repo_name=c.repo_name)}">${_('Statistics')}</a> | |
69 | </li> |
|
69 | </li> | |
70 | <li class="${'active' if c.active=='integrations' else ''}"> |
|
70 | <li class="${'active' if c.active=='integrations' else ''}"> | |
71 | <a href="${h.route_path('repo_integrations_home', repo_name=c.repo_name)}">${_('Integrations')}</a> |
|
71 | <a href="${h.route_path('repo_integrations_home', repo_name=c.repo_name)}">${_('Integrations')}</a> | |
72 | </li> |
|
72 | </li> | |
73 | %if c.repo_info.repo_type != 'svn': |
|
73 | %if c.repo_info.repo_type != 'svn': | |
74 | <li class="${'active' if c.active=='reviewers' else ''}"> |
|
74 | <li class="${'active' if c.active=='reviewers' else ''}"> | |
75 | <a href="${h.route_path('repo_reviewers', repo_name=c.repo_name)}">${_('Reviewer Rules')}</a> |
|
75 | <a href="${h.route_path('repo_reviewers', repo_name=c.repo_name)}">${_('Reviewer Rules')}</a> | |
76 | </li> |
|
76 | </li> | |
77 | %endif |
|
77 | %endif | |
78 | <li class="${'active' if c.active=='maintenance' else ''}"> |
|
78 | <li class="${'active' if c.active=='maintenance' else ''}"> | |
79 | <a href="${h.route_path('repo_maintenance', repo_name=c.repo_name)}">${_('Maintenance')}</a> |
|
79 | <a href="${h.route_path('repo_maintenance', repo_name=c.repo_name)}">${_('Maintenance')}</a> | |
80 | </li> |
|
80 | </li> | |
81 | <li class="${'active' if c.active=='strip' else ''}"> |
|
81 | <li class="${'active' if c.active=='strip' else ''}"> | |
82 | <a href="${h.route_path('strip', repo_name=c.repo_name)}">${_('Strip')}</a> |
|
82 | <a href="${h.route_path('strip', repo_name=c.repo_name)}">${_('Strip')}</a> | |
83 | </li> |
|
83 | </li> | |
84 |
|
84 | |||
85 | </ul> |
|
85 | </ul> | |
86 | </div> |
|
86 | </div> | |
87 |
|
87 | |||
88 | <div class="main-content-full-width"> |
|
88 | <div class="main-content-full-width"> | |
89 | ${self.main_content()} |
|
89 | ${self.main_content()} | |
90 | </div> |
|
90 | </div> | |
91 |
|
91 | |||
92 | </div> |
|
92 | </div> | |
93 | </div> |
|
93 | </div> | |
94 |
|
94 | |||
95 | </%def> No newline at end of file |
|
95 | </%def> |
@@ -1,211 +1,210 b'' | |||||
1 | <%namespace name="base" file="/base/base.mako"/> |
|
1 | <%namespace name="base" file="/base/base.mako"/> | |
2 |
|
2 | |||
3 | <% |
|
3 | <% | |
4 | elems = [ |
|
4 | elems = [ | |
5 | (_('Owner'), lambda:base.gravatar_with_user(c.repo_info.user.email), '', ''), |
|
5 | (_('Owner'), lambda:base.gravatar_with_user(c.repo_info.user.email), '', ''), | |
6 | (_('Created on'), h.format_date(c.repo_info.created_on), '', ''), |
|
6 | (_('Created on'), h.format_date(c.repo_info.created_on), '', ''), | |
7 | (_('Updated on'), h.format_date(c.repo_info.updated_on), '', ''), |
|
7 | (_('Updated on'), h.format_date(c.repo_info.updated_on), '', ''), | |
8 | (_('Cached Commit id'), lambda: h.link_to(c.repo_info.changeset_cache.get('short_id'), h.url('changeset_home',repo_name=c.repo_name,revision=c.repo_info.changeset_cache.get('raw_id'))), '', ''), |
|
8 | (_('Cached Commit id'), lambda: h.link_to(c.repo_info.changeset_cache.get('short_id'), h.url('changeset_home',repo_name=c.repo_name,revision=c.repo_info.changeset_cache.get('raw_id'))), '', ''), | |
9 | ] |
|
9 | ] | |
10 | %> |
|
10 | %> | |
11 |
|
11 | |||
12 | <div class="panel panel-default"> |
|
12 | <div class="panel panel-default"> | |
13 | <div class="panel-heading"> |
|
13 | <div class="panel-heading" id="advanced-info" > | |
14 | <h3 class="panel-title">${_('Repository: %s') % c.repo_info.repo_name}</h3> |
|
14 | <h3 class="panel-title">${_('Repository: %s') % c.repo_info.repo_name} <a class="permalink" href="#advanced-info"> ΒΆ</a></h3> | |
15 | </div> |
|
15 | </div> | |
16 | <div class="panel-body"> |
|
16 | <div class="panel-body"> | |
17 | ${base.dt_info_panel(elems)} |
|
17 | ${base.dt_info_panel(elems)} | |
18 | </div> |
|
18 | </div> | |
19 | </div> |
|
19 | </div> | |
20 |
|
20 | |||
21 |
|
21 | |||
22 | <div class="panel panel-default"> |
|
22 | <div class="panel panel-default"> | |
23 | <div class="panel-heading"> |
|
23 | <div class="panel-heading" id="advanced-fork"> | |
24 | <h3 class="panel-title">${_('Fork Reference')}</h3> |
|
24 | <h3 class="panel-title">${_('Fork Reference')} <a class="permalink" href="#advanced-fork"> ΒΆ</a></h3> | |
25 | </div> |
|
25 | </div> | |
26 | <div class="panel-body"> |
|
26 | <div class="panel-body"> | |
27 |
${h.secure_form( |
|
27 | ${h.secure_form(h.route_path('edit_repo_advanced_fork', repo_name=c.repo_info.repo_name), method='POST')} | |
28 |
|
28 | |||
29 | % if c.repo_info.fork: |
|
29 | % if c.repo_info.fork: | |
30 | <div class="panel-body-title-text">${h.literal(_('This repository is a fork of %(repo_link)s') % {'repo_link': h.link_to_if(c.has_origin_repo_read_perm,c.repo_info.fork.repo_name, h.url('summary_home', repo_name=c.repo_info.fork.repo_name))})} |
|
30 | <div class="panel-body-title-text">${h.literal(_('This repository is a fork of %(repo_link)s') % {'repo_link': h.link_to_if(c.has_origin_repo_read_perm,c.repo_info.fork.repo_name, h.url('summary_home', repo_name=c.repo_info.fork.repo_name))})} | |
31 | | <button class="btn btn-link btn-danger" type="submit">Remove fork reference</button></div> |
|
31 | | <button class="btn btn-link btn-danger" type="submit">Remove fork reference</button></div> | |
32 | % endif |
|
32 | % endif | |
33 |
|
33 | |||
34 | <div class="field"> |
|
34 | <div class="field"> | |
35 | ${h.hidden('id_fork_of')} |
|
35 | ${h.hidden('id_fork_of')} | |
36 | ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('Set'),class_="btn btn-small",)} |
|
36 | ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('Set'),class_="btn btn-small",)} | |
37 | </div> |
|
37 | </div> | |
38 | <div class="field"> |
|
38 | <div class="field"> | |
39 | <span class="help-block">${_('Manually set this repository as a fork of another from the list')}</span> |
|
39 | <span class="help-block">${_('Manually set this repository as a fork of another from the list')}</span> | |
40 | </div> |
|
40 | </div> | |
41 | ${h.end_form()} |
|
41 | ${h.end_form()} | |
42 | </div> |
|
42 | </div> | |
43 | </div> |
|
43 | </div> | |
44 |
|
44 | |||
45 |
|
45 | |||
46 | <div class="panel panel-default"> |
|
46 | <div class="panel panel-default"> | |
47 | <div class="panel-heading"> |
|
47 | <div class="panel-heading" id="advanced-journal"> | |
48 | <h3 class="panel-title">${_('Public Journal Visibility')}</h3> |
|
48 | <h3 class="panel-title">${_('Public Journal Visibility')} <a class="permalink" href="#advanced-journal"> ΒΆ</a></h3> | |
49 | </div> |
|
49 | </div> | |
50 | <div class="panel-body"> |
|
50 | <div class="panel-body"> | |
51 |
${h.secure_form( |
|
51 | ${h.secure_form(h.route_path('edit_repo_advanced_journal', repo_name=c.repo_info.repo_name), method='POST')} | |
52 | <div class="field"> |
|
52 | <div class="field"> | |
53 | %if c.in_public_journal: |
|
53 | %if c.in_public_journal: | |
54 | <button class="btn btn-small" type="submit"> |
|
54 | <button class="btn btn-small" type="submit"> | |
55 | <i class="icon-minus"></i> |
|
|||
56 | ${_('Remove from Public Journal')} |
|
55 | ${_('Remove from Public Journal')} | |
57 | </button> |
|
56 | </button> | |
58 | %else: |
|
57 | %else: | |
59 | <button class="btn btn-small" type="submit"> |
|
58 | <button class="btn btn-small" type="submit"> | |
60 | ${_('Add to Public Journal')} |
|
59 | ${_('Add to Public Journal')} | |
61 | </button> |
|
60 | </button> | |
62 | %endif |
|
61 | %endif | |
63 | </div> |
|
62 | </div> | |
64 | <div class="field" > |
|
63 | <div class="field" > | |
65 | <span class="help-block">${_('All actions made on this repository will be visible to everyone following the public journal.')}</span> |
|
64 | <span class="help-block">${_('All actions made on this repository will be visible to everyone following the public journal.')}</span> | |
66 | </div> |
|
65 | </div> | |
67 | ${h.end_form()} |
|
66 | ${h.end_form()} | |
68 | </div> |
|
67 | </div> | |
69 | </div> |
|
68 | </div> | |
70 |
|
69 | |||
71 |
|
70 | |||
72 | <div class="panel panel-default"> |
|
71 | <div class="panel panel-default"> | |
73 | <div class="panel-heading"> |
|
72 | <div class="panel-heading" id="advanced-locking"> | |
74 | <h3 class="panel-title">${_('Locking state')}</h3> |
|
73 | <h3 class="panel-title">${_('Locking state')} <a class="permalink" href="#advanced-locking"> ΒΆ</a></h3> | |
75 | </div> |
|
74 | </div> | |
76 | <div class="panel-body"> |
|
75 | <div class="panel-body"> | |
77 |
${h.secure_form( |
|
76 | ${h.secure_form(h.route_path('edit_repo_advanced_locking', repo_name=c.repo_info.repo_name), method='POST')} | |
78 |
|
77 | |||
79 | %if c.repo_info.locked[0]: |
|
78 | %if c.repo_info.locked[0]: | |
80 | <div class="panel-body-title-text">${'Locked by %s on %s. Lock reason: %s' % (h.person_by_id(c.repo_info.locked[0]), |
|
79 | <div class="panel-body-title-text">${'Locked by %s on %s. Lock reason: %s' % (h.person_by_id(c.repo_info.locked[0]), | |
81 | h.format_date(h. time_to_datetime(c.repo_info.locked[1])), c.repo_info.locked[2])}</div> |
|
80 | h.format_date(h. time_to_datetime(c.repo_info.locked[1])), c.repo_info.locked[2])}</div> | |
82 | %else: |
|
81 | %else: | |
83 | <div class="panel-body-title-text">${_('This Repository is not currently locked.')}</div> |
|
82 | <div class="panel-body-title-text">${_('This Repository is not currently locked.')}</div> | |
84 | %endif |
|
83 | %endif | |
85 |
|
84 | |||
86 | <div class="field" > |
|
85 | <div class="field" > | |
87 | %if c.repo_info.locked[0]: |
|
86 | %if c.repo_info.locked[0]: | |
88 | ${h.hidden('set_unlock', '1')} |
|
87 | ${h.hidden('set_unlock', '1')} | |
89 | <button class="btn btn-small" type="submit" |
|
88 | <button class="btn btn-small" type="submit" | |
90 | onclick="return confirm('${_('Confirm to unlock repository.')}');"> |
|
89 | onclick="return confirm('${_('Confirm to unlock repository.')}');"> | |
91 | <i class="icon-unlock"></i> |
|
90 | <i class="icon-unlock"></i> | |
92 | ${_('Unlock repository')} |
|
91 | ${_('Unlock repository')} | |
93 | </button> |
|
92 | </button> | |
94 | %else: |
|
93 | %else: | |
95 | ${h.hidden('set_lock', '1')} |
|
94 | ${h.hidden('set_lock', '1')} | |
96 | <button class="btn btn-small" type="submit" |
|
95 | <button class="btn btn-small" type="submit" | |
97 | onclick="return confirm('${_('Confirm to lock repository.')}');"> |
|
96 | onclick="return confirm('${_('Confirm to lock repository.')}');"> | |
98 | <i class="icon-lock"></i> |
|
97 | <i class="icon-lock"></i> | |
99 | ${_('Lock Repository')} |
|
98 | ${_('Lock Repository')} | |
100 | </button> |
|
99 | </button> | |
101 | %endif |
|
100 | %endif | |
102 | </div> |
|
101 | </div> | |
103 | <div class="field" > |
|
102 | <div class="field" > | |
104 | <span class="help-block"> |
|
103 | <span class="help-block"> | |
105 | ${_('Force repository locking. This only works when anonymous access is disabled. Pulling from the repository locks the repository to that user until the same user pushes to that repository again.')} |
|
104 | ${_('Force repository locking. This only works when anonymous access is disabled. Pulling from the repository locks the repository to that user until the same user pushes to that repository again.')} | |
106 | </span> |
|
105 | </span> | |
107 | </div> |
|
106 | </div> | |
108 | ${h.end_form()} |
|
107 | ${h.end_form()} | |
109 | </div> |
|
108 | </div> | |
110 | </div> |
|
109 | </div> | |
111 |
|
110 | |||
112 | <div class="panel panel-danger"> |
|
111 | <div class="panel panel-danger"> | |
113 | <div class="panel-heading"> |
|
112 | <div class="panel-heading" id="advanced-delete"> | |
114 | <h3 class="panel-title">${_('Delete repository')}</h3> |
|
113 | <h3 class="panel-title">${_('Delete repository')} <a class="permalink" href="#advanced-delete"> ΒΆ</a></h3> | |
115 | </div> |
|
114 | </div> | |
116 | <div class="panel-body"> |
|
115 | <div class="panel-body"> | |
117 |
${h.secure_form( |
|
116 | ${h.secure_form(h.route_path('edit_repo_advanced_delete', repo_name=c.repo_name), method='POST')} | |
118 | <table class="display"> |
|
117 | <table class="display"> | |
119 | <tr> |
|
118 | <tr> | |
120 | <td> |
|
119 | <td> | |
121 |
${ungettext('This repository has %s fork.', 'This repository has %s forks.', c.repo_info. |
|
120 | ${_ungettext('This repository has %s fork.', 'This repository has %s forks.', c.repo_info.forks.count()) % c.repo_info.forks.count()} | |
122 | </td> |
|
121 | </td> | |
123 | <td> |
|
122 | <td> | |
124 | %if c.repo_info.forks.count(): |
|
123 | %if c.repo_info.forks.count(): | |
125 | <input type="radio" name="forks" value="detach_forks" checked="checked"/> <label for="forks">${_('Detach forks')}</label> |
|
124 | <input type="radio" name="forks" value="detach_forks" checked="checked"/> <label for="forks">${_('Detach forks')}</label> | |
126 | %endif |
|
125 | %endif | |
127 | </td> |
|
126 | </td> | |
128 | <td> |
|
127 | <td> | |
129 | %if c.repo_info.forks.count(): |
|
128 | %if c.repo_info.forks.count(): | |
130 | <input type="radio" name="forks" value="delete_forks"/> <label for="forks">${_('Delete forks')}</label> |
|
129 | <input type="radio" name="forks" value="delete_forks"/> <label for="forks">${_('Delete forks')}</label> | |
131 | %endif |
|
130 | %endif | |
132 | </td> |
|
131 | </td> | |
133 | </tr> |
|
132 | </tr> | |
134 | </table> |
|
133 | </table> | |
135 | <div style="margin: 0 0 20px 0" class="fake-space"></div> |
|
134 | <div style="margin: 0 0 20px 0" class="fake-space"></div> | |
136 |
|
135 | |||
137 | <div class="field"> |
|
136 | <div class="field"> | |
138 | <button class="btn btn-small btn-danger" type="submit" |
|
137 | <button class="btn btn-small btn-danger" type="submit" | |
139 | onclick="return confirm('${_('Confirm to delete this repository: %s') % c.repo_name}');"> |
|
138 | onclick="return confirm('${_('Confirm to delete this repository: %s') % c.repo_name}');"> | |
140 | <i class="icon-remove-sign"></i> |
|
139 | <i class="icon-remove-sign"></i> | |
141 | ${_('Delete This Repository')} |
|
140 | ${_('Delete This Repository')} | |
142 | </button> |
|
141 | </button> | |
143 | </div> |
|
142 | </div> | |
144 | <div class="field"> |
|
143 | <div class="field"> | |
145 | <span class="help-block"> |
|
144 | <span class="help-block"> | |
146 | ${_('This repository will be renamed in a special way in order to make it inaccessible to RhodeCode Enterprise and its VCS systems. If you need to fully delete it from the file system, please do it manually, or with rhodecode-cleanup-repos command.')} |
|
145 | ${_('This repository will be renamed in a special way in order to make it inaccessible to RhodeCode Enterprise and its VCS systems. If you need to fully delete it from the file system, please do it manually, or with rhodecode-cleanup-repos command available in rhodecode-tools.')} | |
147 | </span> |
|
146 | </span> | |
148 | </div> |
|
147 | </div> | |
149 |
|
148 | |||
150 | ${h.end_form()} |
|
149 | ${h.end_form()} | |
151 | </div> |
|
150 | </div> | |
152 | </div> |
|
151 | </div> | |
153 |
|
152 | |||
154 |
|
153 | |||
155 | <script> |
|
154 | <script> | |
156 |
|
155 | |||
157 | var currentRepoId = ${c.repo_info.repo_id}; |
|
156 | var currentRepoId = ${c.repo_info.repo_id}; | |
158 |
|
157 | |||
159 | var repoTypeFilter = function(data) { |
|
158 | var repoTypeFilter = function(data) { | |
160 | var results = []; |
|
159 | var results = []; | |
161 |
|
160 | |||
162 | if (!data.results[0]) { |
|
161 | if (!data.results[0]) { | |
163 | return data |
|
162 | return data | |
164 | } |
|
163 | } | |
165 |
|
164 | |||
166 | $.each(data.results[0].children, function() { |
|
165 | $.each(data.results[0].children, function() { | |
167 | // filter out the SAME repo, it cannot be used as fork of itself |
|
166 | // filter out the SAME repo, it cannot be used as fork of itself | |
168 | if (this.obj.repo_id != currentRepoId) { |
|
167 | if (this.obj.repo_id != currentRepoId) { | |
169 | this.id = this.obj.repo_id; |
|
168 | this.id = this.obj.repo_id; | |
170 | results.push(this) |
|
169 | results.push(this) | |
171 | } |
|
170 | } | |
172 | }); |
|
171 | }); | |
173 | data.results[0].children = results; |
|
172 | data.results[0].children = results; | |
174 | return data; |
|
173 | return data; | |
175 | }; |
|
174 | }; | |
176 |
|
175 | |||
177 | $("#id_fork_of").select2({ |
|
176 | $("#id_fork_of").select2({ | |
178 | cachedDataSource: {}, |
|
177 | cachedDataSource: {}, | |
179 | minimumInputLength: 2, |
|
178 | minimumInputLength: 2, | |
180 | placeholder: "${_('Change repository') if c.repo_info.fork else _('Pick repository')}", |
|
179 | placeholder: "${_('Change repository') if c.repo_info.fork else _('Pick repository')}", | |
181 | dropdownAutoWidth: true, |
|
180 | dropdownAutoWidth: true, | |
182 | containerCssClass: "drop-menu", |
|
181 | containerCssClass: "drop-menu", | |
183 | dropdownCssClass: "drop-menu-dropdown", |
|
182 | dropdownCssClass: "drop-menu-dropdown", | |
184 | formatResult: formatResult, |
|
183 | formatResult: formatResult, | |
185 | query: $.debounce(250, function(query){ |
|
184 | query: $.debounce(250, function(query){ | |
186 | self = this; |
|
185 | self = this; | |
187 | var cacheKey = query.term; |
|
186 | var cacheKey = query.term; | |
188 | var cachedData = self.cachedDataSource[cacheKey]; |
|
187 | var cachedData = self.cachedDataSource[cacheKey]; | |
189 |
|
188 | |||
190 | if (cachedData) { |
|
189 | if (cachedData) { | |
191 | query.callback({results: cachedData.results}); |
|
190 | query.callback({results: cachedData.results}); | |
192 | } else { |
|
191 | } else { | |
193 | $.ajax({ |
|
192 | $.ajax({ | |
194 | url: pyroutes.url('repo_list_data'), |
|
193 | url: pyroutes.url('repo_list_data'), | |
195 | data: {'query': query.term, repo_type: '${c.repo_info.repo_type}'}, |
|
194 | data: {'query': query.term, repo_type: '${c.repo_info.repo_type}'}, | |
196 | dataType: 'json', |
|
195 | dataType: 'json', | |
197 | type: 'GET', |
|
196 | type: 'GET', | |
198 | success: function(data) { |
|
197 | success: function(data) { | |
199 | data = repoTypeFilter(data); |
|
198 | data = repoTypeFilter(data); | |
200 | self.cachedDataSource[cacheKey] = data; |
|
199 | self.cachedDataSource[cacheKey] = data; | |
201 | query.callback({results: data.results}); |
|
200 | query.callback({results: data.results}); | |
202 | }, |
|
201 | }, | |
203 | error: function(data, textStatus, errorThrown) { |
|
202 | error: function(data, textStatus, errorThrown) { | |
204 | alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText)); |
|
203 | alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText)); | |
205 | } |
|
204 | } | |
206 | }) |
|
205 | }) | |
207 | } |
|
206 | } | |
208 | }) |
|
207 | }) | |
209 | }); |
|
208 | }); | |
210 | </script> |
|
209 | </script> | |
211 |
|
210 |
@@ -1,317 +1,317 b'' | |||||
1 | ## DATA TABLE RE USABLE ELEMENTS |
|
1 | ## DATA TABLE RE USABLE ELEMENTS | |
2 | ## usage: |
|
2 | ## usage: | |
3 | ## <%namespace name="dt" file="/data_table/_dt_elements.mako"/> |
|
3 | ## <%namespace name="dt" file="/data_table/_dt_elements.mako"/> | |
4 | <%namespace name="base" file="/base/base.mako"/> |
|
4 | <%namespace name="base" file="/base/base.mako"/> | |
5 |
|
5 | |||
6 | ## REPOSITORY RENDERERS |
|
6 | ## REPOSITORY RENDERERS | |
7 | <%def name="quick_menu(repo_name)"> |
|
7 | <%def name="quick_menu(repo_name)"> | |
8 | <i class="pointer icon-more"></i> |
|
8 | <i class="pointer icon-more"></i> | |
9 | <div class="menu_items_container hidden"> |
|
9 | <div class="menu_items_container hidden"> | |
10 | <ul class="menu_items"> |
|
10 | <ul class="menu_items"> | |
11 | <li> |
|
11 | <li> | |
12 | <a title="${_('Summary')}" href="${h.url('summary_home',repo_name=repo_name)}"> |
|
12 | <a title="${_('Summary')}" href="${h.url('summary_home',repo_name=repo_name)}"> | |
13 | <span>${_('Summary')}</span> |
|
13 | <span>${_('Summary')}</span> | |
14 | </a> |
|
14 | </a> | |
15 | </li> |
|
15 | </li> | |
16 | <li> |
|
16 | <li> | |
17 | <a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=repo_name)}"> |
|
17 | <a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=repo_name)}"> | |
18 | <span>${_('Changelog')}</span> |
|
18 | <span>${_('Changelog')}</span> | |
19 | </a> |
|
19 | </a> | |
20 | </li> |
|
20 | </li> | |
21 | <li> |
|
21 | <li> | |
22 | <a title="${_('Files')}" href="${h.url('files_home',repo_name=repo_name)}"> |
|
22 | <a title="${_('Files')}" href="${h.url('files_home',repo_name=repo_name)}"> | |
23 | <span>${_('Files')}</span> |
|
23 | <span>${_('Files')}</span> | |
24 | </a> |
|
24 | </a> | |
25 | </li> |
|
25 | </li> | |
26 | <li> |
|
26 | <li> | |
27 | <a title="${_('Fork')}" href="${h.url('repo_fork_home',repo_name=repo_name)}"> |
|
27 | <a title="${_('Fork')}" href="${h.url('repo_fork_home',repo_name=repo_name)}"> | |
28 | <span>${_('Fork')}</span> |
|
28 | <span>${_('Fork')}</span> | |
29 | </a> |
|
29 | </a> | |
30 | </li> |
|
30 | </li> | |
31 | </ul> |
|
31 | </ul> | |
32 | </div> |
|
32 | </div> | |
33 | </%def> |
|
33 | </%def> | |
34 |
|
34 | |||
35 | <%def name="repo_name(name,rtype,rstate,private,fork_of,short_name=False,admin=False)"> |
|
35 | <%def name="repo_name(name,rtype,rstate,private,fork_of,short_name=False,admin=False)"> | |
36 | <% |
|
36 | <% | |
37 | def get_name(name,short_name=short_name): |
|
37 | def get_name(name,short_name=short_name): | |
38 | if short_name: |
|
38 | if short_name: | |
39 | return name.split('/')[-1] |
|
39 | return name.split('/')[-1] | |
40 | else: |
|
40 | else: | |
41 | return name |
|
41 | return name | |
42 | %> |
|
42 | %> | |
43 | <div class="${'repo_state_pending' if rstate == 'repo_state_pending' else ''} truncate"> |
|
43 | <div class="${'repo_state_pending' if rstate == 'repo_state_pending' else ''} truncate"> | |
44 | ##NAME |
|
44 | ##NAME | |
45 | <a href="${h.route_path('edit_repo',repo_name=name) if admin else h.url('summary_home',repo_name=name)}"> |
|
45 | <a href="${h.route_path('edit_repo',repo_name=name) if admin else h.url('summary_home',repo_name=name)}"> | |
46 |
|
46 | |||
47 | ##TYPE OF REPO |
|
47 | ##TYPE OF REPO | |
48 | %if h.is_hg(rtype): |
|
48 | %if h.is_hg(rtype): | |
49 | <span title="${_('Mercurial repository')}"><i class="icon-hg"></i></span> |
|
49 | <span title="${_('Mercurial repository')}"><i class="icon-hg"></i></span> | |
50 | %elif h.is_git(rtype): |
|
50 | %elif h.is_git(rtype): | |
51 | <span title="${_('Git repository')}"><i class="icon-git"></i></span> |
|
51 | <span title="${_('Git repository')}"><i class="icon-git"></i></span> | |
52 | %elif h.is_svn(rtype): |
|
52 | %elif h.is_svn(rtype): | |
53 | <span title="${_('Subversion repository')}"><i class="icon-svn"></i></span> |
|
53 | <span title="${_('Subversion repository')}"><i class="icon-svn"></i></span> | |
54 | %endif |
|
54 | %endif | |
55 |
|
55 | |||
56 | ##PRIVATE/PUBLIC |
|
56 | ##PRIVATE/PUBLIC | |
57 | %if private and c.visual.show_private_icon: |
|
57 | %if private and c.visual.show_private_icon: | |
58 | <i class="icon-lock" title="${_('Private repository')}"></i> |
|
58 | <i class="icon-lock" title="${_('Private repository')}"></i> | |
59 | %elif not private and c.visual.show_public_icon: |
|
59 | %elif not private and c.visual.show_public_icon: | |
60 | <i class="icon-unlock-alt" title="${_('Public repository')}"></i> |
|
60 | <i class="icon-unlock-alt" title="${_('Public repository')}"></i> | |
61 | %else: |
|
61 | %else: | |
62 | <span></span> |
|
62 | <span></span> | |
63 | %endif |
|
63 | %endif | |
64 | ${get_name(name)} |
|
64 | ${get_name(name)} | |
65 | </a> |
|
65 | </a> | |
66 | %if fork_of: |
|
66 | %if fork_of: | |
67 | <a href="${h.url('summary_home',repo_name=fork_of.repo_name)}"><i class="icon-code-fork"></i></a> |
|
67 | <a href="${h.url('summary_home',repo_name=fork_of.repo_name)}"><i class="icon-code-fork"></i></a> | |
68 | %endif |
|
68 | %endif | |
69 | %if rstate == 'repo_state_pending': |
|
69 | %if rstate == 'repo_state_pending': | |
70 | <i class="icon-cogs" title="${_('Repository creating in progress...')}"></i> |
|
70 | <i class="icon-cogs" title="${_('Repository creating in progress...')}"></i> | |
71 | %endif |
|
71 | %endif | |
72 | </div> |
|
72 | </div> | |
73 | </%def> |
|
73 | </%def> | |
74 |
|
74 | |||
75 | <%def name="repo_desc(description)"> |
|
75 | <%def name="repo_desc(description)"> | |
76 | <div class="truncate-wrap">${description}</div> |
|
76 | <div class="truncate-wrap">${description}</div> | |
77 | </%def> |
|
77 | </%def> | |
78 |
|
78 | |||
79 | <%def name="last_change(last_change)"> |
|
79 | <%def name="last_change(last_change)"> | |
80 | ${h.age_component(last_change)} |
|
80 | ${h.age_component(last_change)} | |
81 | </%def> |
|
81 | </%def> | |
82 |
|
82 | |||
83 | <%def name="revision(name,rev,tip,author,last_msg)"> |
|
83 | <%def name="revision(name,rev,tip,author,last_msg)"> | |
84 | <div> |
|
84 | <div> | |
85 | %if rev >= 0: |
|
85 | %if rev >= 0: | |
86 | <code><a title="${h.tooltip('%s:\n\n%s' % (author,last_msg))}" class="tooltip" href="${h.url('changeset_home',repo_name=name,revision=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a></code> |
|
86 | <code><a title="${h.tooltip('%s:\n\n%s' % (author,last_msg))}" class="tooltip" href="${h.url('changeset_home',repo_name=name,revision=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a></code> | |
87 | %else: |
|
87 | %else: | |
88 | ${_('No commits yet')} |
|
88 | ${_('No commits yet')} | |
89 | %endif |
|
89 | %endif | |
90 | </div> |
|
90 | </div> | |
91 | </%def> |
|
91 | </%def> | |
92 |
|
92 | |||
93 | <%def name="rss(name)"> |
|
93 | <%def name="rss(name)"> | |
94 | %if c.rhodecode_user.username != h.DEFAULT_USER: |
|
94 | %if c.rhodecode_user.username != h.DEFAULT_USER: | |
95 | <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name,auth_token=c.rhodecode_user.feed_token)}"><i class="icon-rss-sign"></i></a> |
|
95 | <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name,auth_token=c.rhodecode_user.feed_token)}"><i class="icon-rss-sign"></i></a> | |
96 | %else: |
|
96 | %else: | |
97 | <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name)}"><i class="icon-rss-sign"></i></a> |
|
97 | <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name)}"><i class="icon-rss-sign"></i></a> | |
98 | %endif |
|
98 | %endif | |
99 | </%def> |
|
99 | </%def> | |
100 |
|
100 | |||
101 | <%def name="atom(name)"> |
|
101 | <%def name="atom(name)"> | |
102 | %if c.rhodecode_user.username != h.DEFAULT_USER: |
|
102 | %if c.rhodecode_user.username != h.DEFAULT_USER: | |
103 | <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name,auth_token=c.rhodecode_user.feed_token)}"><i class="icon-rss-sign"></i></a> |
|
103 | <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name,auth_token=c.rhodecode_user.feed_token)}"><i class="icon-rss-sign"></i></a> | |
104 | %else: |
|
104 | %else: | |
105 | <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name)}"><i class="icon-rss-sign"></i></a> |
|
105 | <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name)}"><i class="icon-rss-sign"></i></a> | |
106 | %endif |
|
106 | %endif | |
107 | </%def> |
|
107 | </%def> | |
108 |
|
108 | |||
109 | <%def name="user_gravatar(email, size=16)"> |
|
109 | <%def name="user_gravatar(email, size=16)"> | |
110 | <div class="rc-user tooltip" title="${h.author_string(email)}"> |
|
110 | <div class="rc-user tooltip" title="${h.author_string(email)}"> | |
111 | ${base.gravatar(email, 16)} |
|
111 | ${base.gravatar(email, 16)} | |
112 | </div> |
|
112 | </div> | |
113 | </%def> |
|
113 | </%def> | |
114 |
|
114 | |||
115 | <%def name="repo_actions(repo_name, super_user=True)"> |
|
115 | <%def name="repo_actions(repo_name, super_user=True)"> | |
116 | <div> |
|
116 | <div> | |
117 | <div class="grid_edit"> |
|
117 | <div class="grid_edit"> | |
118 | <a href="${h.route_path('edit_repo',repo_name=repo_name)}" title="${_('Edit')}"> |
|
118 | <a href="${h.route_path('edit_repo',repo_name=repo_name)}" title="${_('Edit')}"> | |
119 | <i class="icon-pencil"></i>Edit</a> |
|
119 | <i class="icon-pencil"></i>Edit</a> | |
120 | </div> |
|
120 | </div> | |
121 | <div class="grid_delete"> |
|
121 | <div class="grid_delete"> | |
122 |
${h.secure_form(h. |
|
122 | ${h.secure_form(h.route_path('edit_repo_advanced_delete', repo_name=repo_name), method='POST')} | |
123 | ${h.submit('remove_%s' % repo_name,_('Delete'),class_="btn btn-link btn-danger", |
|
123 | ${h.submit('remove_%s' % repo_name,_('Delete'),class_="btn btn-link btn-danger", | |
124 | onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")} |
|
124 | onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")} | |
125 | ${h.end_form()} |
|
125 | ${h.end_form()} | |
126 | </div> |
|
126 | </div> | |
127 | </div> |
|
127 | </div> | |
128 | </%def> |
|
128 | </%def> | |
129 |
|
129 | |||
130 | <%def name="repo_state(repo_state)"> |
|
130 | <%def name="repo_state(repo_state)"> | |
131 | <div> |
|
131 | <div> | |
132 | %if repo_state == 'repo_state_pending': |
|
132 | %if repo_state == 'repo_state_pending': | |
133 | <div class="tag tag4">${_('Creating')}</div> |
|
133 | <div class="tag tag4">${_('Creating')}</div> | |
134 | %elif repo_state == 'repo_state_created': |
|
134 | %elif repo_state == 'repo_state_created': | |
135 | <div class="tag tag1">${_('Created')}</div> |
|
135 | <div class="tag tag1">${_('Created')}</div> | |
136 | %else: |
|
136 | %else: | |
137 | <div class="tag alert2" title="${repo_state}">invalid</div> |
|
137 | <div class="tag alert2" title="${repo_state}">invalid</div> | |
138 | %endif |
|
138 | %endif | |
139 | </div> |
|
139 | </div> | |
140 | </%def> |
|
140 | </%def> | |
141 |
|
141 | |||
142 |
|
142 | |||
143 | ## REPO GROUP RENDERERS |
|
143 | ## REPO GROUP RENDERERS | |
144 | <%def name="quick_repo_group_menu(repo_group_name)"> |
|
144 | <%def name="quick_repo_group_menu(repo_group_name)"> | |
145 | <i class="pointer icon-more"></i> |
|
145 | <i class="pointer icon-more"></i> | |
146 | <div class="menu_items_container hidden"> |
|
146 | <div class="menu_items_container hidden"> | |
147 | <ul class="menu_items"> |
|
147 | <ul class="menu_items"> | |
148 | <li> |
|
148 | <li> | |
149 | <a href="${h.url('repo_group_home',group_name=repo_group_name)}"> |
|
149 | <a href="${h.url('repo_group_home',group_name=repo_group_name)}"> | |
150 | <span class="icon"> |
|
150 | <span class="icon"> | |
151 | <i class="icon-file-text"></i> |
|
151 | <i class="icon-file-text"></i> | |
152 | </span> |
|
152 | </span> | |
153 | <span>${_('Summary')}</span> |
|
153 | <span>${_('Summary')}</span> | |
154 | </a> |
|
154 | </a> | |
155 | </li> |
|
155 | </li> | |
156 |
|
156 | |||
157 | </ul> |
|
157 | </ul> | |
158 | </div> |
|
158 | </div> | |
159 | </%def> |
|
159 | </%def> | |
160 |
|
160 | |||
161 | <%def name="repo_group_name(repo_group_name, children_groups=None)"> |
|
161 | <%def name="repo_group_name(repo_group_name, children_groups=None)"> | |
162 | <div> |
|
162 | <div> | |
163 | <a href="${h.url('repo_group_home',group_name=repo_group_name)}"> |
|
163 | <a href="${h.url('repo_group_home',group_name=repo_group_name)}"> | |
164 | <i class="icon-folder-close" title="${_('Repository group')}"></i> |
|
164 | <i class="icon-folder-close" title="${_('Repository group')}"></i> | |
165 | %if children_groups: |
|
165 | %if children_groups: | |
166 | ${h.literal(' » '.join(children_groups))} |
|
166 | ${h.literal(' » '.join(children_groups))} | |
167 | %else: |
|
167 | %else: | |
168 | ${repo_group_name} |
|
168 | ${repo_group_name} | |
169 | %endif |
|
169 | %endif | |
170 | </a> |
|
170 | </a> | |
171 | </div> |
|
171 | </div> | |
172 | </%def> |
|
172 | </%def> | |
173 |
|
173 | |||
174 | <%def name="repo_group_desc(description)"> |
|
174 | <%def name="repo_group_desc(description)"> | |
175 | <div class="truncate-wrap">${description}</div> |
|
175 | <div class="truncate-wrap">${description}</div> | |
176 | </%def> |
|
176 | </%def> | |
177 |
|
177 | |||
178 | <%def name="repo_group_actions(repo_group_id, repo_group_name, gr_count)"> |
|
178 | <%def name="repo_group_actions(repo_group_id, repo_group_name, gr_count)"> | |
179 | <div class="grid_edit"> |
|
179 | <div class="grid_edit"> | |
180 | <a href="${h.url('edit_repo_group',group_name=repo_group_name)}" title="${_('Edit')}">Edit</a> |
|
180 | <a href="${h.url('edit_repo_group',group_name=repo_group_name)}" title="${_('Edit')}">Edit</a> | |
181 | </div> |
|
181 | </div> | |
182 | <div class="grid_delete"> |
|
182 | <div class="grid_delete"> | |
183 | ${h.secure_form(h.url('delete_repo_group', group_name=repo_group_name),method='delete')} |
|
183 | ${h.secure_form(h.url('delete_repo_group', group_name=repo_group_name),method='delete')} | |
184 | ${h.submit('remove_%s' % repo_group_name,_('Delete'),class_="btn btn-link btn-danger", |
|
184 | ${h.submit('remove_%s' % repo_group_name,_('Delete'),class_="btn btn-link btn-danger", | |
185 | onclick="return confirm('"+ungettext('Confirm to delete this group: %s with %s repository','Confirm to delete this group: %s with %s repositories',gr_count) % (repo_group_name, gr_count)+"');")} |
|
185 | onclick="return confirm('"+ungettext('Confirm to delete this group: %s with %s repository','Confirm to delete this group: %s with %s repositories',gr_count) % (repo_group_name, gr_count)+"');")} | |
186 | ${h.end_form()} |
|
186 | ${h.end_form()} | |
187 | </div> |
|
187 | </div> | |
188 | </%def> |
|
188 | </%def> | |
189 |
|
189 | |||
190 |
|
190 | |||
191 | <%def name="user_actions(user_id, username)"> |
|
191 | <%def name="user_actions(user_id, username)"> | |
192 | <div class="grid_edit"> |
|
192 | <div class="grid_edit"> | |
193 | <a href="${h.url('edit_user',user_id=user_id)}" title="${_('Edit')}"> |
|
193 | <a href="${h.url('edit_user',user_id=user_id)}" title="${_('Edit')}"> | |
194 | <i class="icon-pencil"></i>Edit</a> |
|
194 | <i class="icon-pencil"></i>Edit</a> | |
195 | </div> |
|
195 | </div> | |
196 | <div class="grid_delete"> |
|
196 | <div class="grid_delete"> | |
197 | ${h.secure_form(h.url('delete_user', user_id=user_id),method='delete')} |
|
197 | ${h.secure_form(h.url('delete_user', user_id=user_id),method='delete')} | |
198 | ${h.submit('remove_',_('Delete'),id="remove_user_%s" % user_id, class_="btn btn-link btn-danger", |
|
198 | ${h.submit('remove_',_('Delete'),id="remove_user_%s" % user_id, class_="btn btn-link btn-danger", | |
199 | onclick="return confirm('"+_('Confirm to delete this user: %s') % username+"');")} |
|
199 | onclick="return confirm('"+_('Confirm to delete this user: %s') % username+"');")} | |
200 | ${h.end_form()} |
|
200 | ${h.end_form()} | |
201 | </div> |
|
201 | </div> | |
202 | </%def> |
|
202 | </%def> | |
203 |
|
203 | |||
204 | <%def name="user_group_actions(user_group_id, user_group_name)"> |
|
204 | <%def name="user_group_actions(user_group_id, user_group_name)"> | |
205 | <div class="grid_edit"> |
|
205 | <div class="grid_edit"> | |
206 | <a href="${h.url('edit_users_group', user_group_id=user_group_id)}" title="${_('Edit')}">Edit</a> |
|
206 | <a href="${h.url('edit_users_group', user_group_id=user_group_id)}" title="${_('Edit')}">Edit</a> | |
207 | </div> |
|
207 | </div> | |
208 | <div class="grid_delete"> |
|
208 | <div class="grid_delete"> | |
209 | ${h.secure_form(h.url('delete_users_group', user_group_id=user_group_id),method='delete')} |
|
209 | ${h.secure_form(h.url('delete_users_group', user_group_id=user_group_id),method='delete')} | |
210 | ${h.submit('remove_',_('Delete'),id="remove_group_%s" % user_group_id, class_="btn btn-link btn-danger", |
|
210 | ${h.submit('remove_',_('Delete'),id="remove_group_%s" % user_group_id, class_="btn btn-link btn-danger", | |
211 | onclick="return confirm('"+_('Confirm to delete this user group: %s') % user_group_name+"');")} |
|
211 | onclick="return confirm('"+_('Confirm to delete this user group: %s') % user_group_name+"');")} | |
212 | ${h.end_form()} |
|
212 | ${h.end_form()} | |
213 | </div> |
|
213 | </div> | |
214 | </%def> |
|
214 | </%def> | |
215 |
|
215 | |||
216 |
|
216 | |||
217 | <%def name="user_name(user_id, username)"> |
|
217 | <%def name="user_name(user_id, username)"> | |
218 | ${h.link_to(h.person(username, 'username_or_name_or_email'), h.url('edit_user', user_id=user_id))} |
|
218 | ${h.link_to(h.person(username, 'username_or_name_or_email'), h.url('edit_user', user_id=user_id))} | |
219 | </%def> |
|
219 | </%def> | |
220 |
|
220 | |||
221 | <%def name="user_profile(username)"> |
|
221 | <%def name="user_profile(username)"> | |
222 | ${base.gravatar_with_user(username, 16)} |
|
222 | ${base.gravatar_with_user(username, 16)} | |
223 | </%def> |
|
223 | </%def> | |
224 |
|
224 | |||
225 | <%def name="user_group_name(user_group_id, user_group_name)"> |
|
225 | <%def name="user_group_name(user_group_id, user_group_name)"> | |
226 | <div> |
|
226 | <div> | |
227 | <a href="${h.url('edit_users_group', user_group_id=user_group_id)}"> |
|
227 | <a href="${h.url('edit_users_group', user_group_id=user_group_id)}"> | |
228 | <i class="icon-group" title="${_('User group')}"></i> ${user_group_name}</a> |
|
228 | <i class="icon-group" title="${_('User group')}"></i> ${user_group_name}</a> | |
229 | </div> |
|
229 | </div> | |
230 | </%def> |
|
230 | </%def> | |
231 |
|
231 | |||
232 |
|
232 | |||
233 | ## GISTS |
|
233 | ## GISTS | |
234 |
|
234 | |||
235 | <%def name="gist_gravatar(full_contact)"> |
|
235 | <%def name="gist_gravatar(full_contact)"> | |
236 | <div class="gist_gravatar"> |
|
236 | <div class="gist_gravatar"> | |
237 | ${base.gravatar(full_contact, 30)} |
|
237 | ${base.gravatar(full_contact, 30)} | |
238 | </div> |
|
238 | </div> | |
239 | </%def> |
|
239 | </%def> | |
240 |
|
240 | |||
241 | <%def name="gist_access_id(gist_access_id, full_contact)"> |
|
241 | <%def name="gist_access_id(gist_access_id, full_contact)"> | |
242 | <div> |
|
242 | <div> | |
243 | <b> |
|
243 | <b> | |
244 | <a href="${h.url('gist',gist_id=gist_access_id)}">gist: ${gist_access_id}</a> |
|
244 | <a href="${h.url('gist',gist_id=gist_access_id)}">gist: ${gist_access_id}</a> | |
245 | </b> |
|
245 | </b> | |
246 | </div> |
|
246 | </div> | |
247 | </%def> |
|
247 | </%def> | |
248 |
|
248 | |||
249 | <%def name="gist_author(full_contact, created_on, expires)"> |
|
249 | <%def name="gist_author(full_contact, created_on, expires)"> | |
250 | ${base.gravatar_with_user(full_contact, 16)} |
|
250 | ${base.gravatar_with_user(full_contact, 16)} | |
251 | </%def> |
|
251 | </%def> | |
252 |
|
252 | |||
253 |
|
253 | |||
254 | <%def name="gist_created(created_on)"> |
|
254 | <%def name="gist_created(created_on)"> | |
255 | <div class="created"> |
|
255 | <div class="created"> | |
256 | ${h.age_component(created_on, time_is_local=True)} |
|
256 | ${h.age_component(created_on, time_is_local=True)} | |
257 | </div> |
|
257 | </div> | |
258 | </%def> |
|
258 | </%def> | |
259 |
|
259 | |||
260 | <%def name="gist_expires(expires)"> |
|
260 | <%def name="gist_expires(expires)"> | |
261 | <div class="created"> |
|
261 | <div class="created"> | |
262 | %if expires == -1: |
|
262 | %if expires == -1: | |
263 | ${_('never')} |
|
263 | ${_('never')} | |
264 | %else: |
|
264 | %else: | |
265 | ${h.age_component(h.time_to_utcdatetime(expires))} |
|
265 | ${h.age_component(h.time_to_utcdatetime(expires))} | |
266 | %endif |
|
266 | %endif | |
267 | </div> |
|
267 | </div> | |
268 | </%def> |
|
268 | </%def> | |
269 |
|
269 | |||
270 | <%def name="gist_type(gist_type)"> |
|
270 | <%def name="gist_type(gist_type)"> | |
271 | %if gist_type != 'public': |
|
271 | %if gist_type != 'public': | |
272 | <div class="tag">${_('Private')}</div> |
|
272 | <div class="tag">${_('Private')}</div> | |
273 | %endif |
|
273 | %endif | |
274 | </%def> |
|
274 | </%def> | |
275 |
|
275 | |||
276 | <%def name="gist_description(gist_description)"> |
|
276 | <%def name="gist_description(gist_description)"> | |
277 | ${gist_description} |
|
277 | ${gist_description} | |
278 | </%def> |
|
278 | </%def> | |
279 |
|
279 | |||
280 |
|
280 | |||
281 | ## PULL REQUESTS GRID RENDERERS |
|
281 | ## PULL REQUESTS GRID RENDERERS | |
282 |
|
282 | |||
283 | <%def name="pullrequest_target_repo(repo_name)"> |
|
283 | <%def name="pullrequest_target_repo(repo_name)"> | |
284 | <div class="truncate"> |
|
284 | <div class="truncate"> | |
285 | ${h.link_to(repo_name,h.url('summary_home',repo_name=repo_name))} |
|
285 | ${h.link_to(repo_name,h.url('summary_home',repo_name=repo_name))} | |
286 | </div> |
|
286 | </div> | |
287 | </%def> |
|
287 | </%def> | |
288 | <%def name="pullrequest_status(status)"> |
|
288 | <%def name="pullrequest_status(status)"> | |
289 | <div class="${'flag_status %s' % status} pull-left"></div> |
|
289 | <div class="${'flag_status %s' % status} pull-left"></div> | |
290 | </%def> |
|
290 | </%def> | |
291 |
|
291 | |||
292 | <%def name="pullrequest_title(title, description)"> |
|
292 | <%def name="pullrequest_title(title, description)"> | |
293 | ${title} <br/> |
|
293 | ${title} <br/> | |
294 | ${h.shorter(description, 40)} |
|
294 | ${h.shorter(description, 40)} | |
295 | </%def> |
|
295 | </%def> | |
296 |
|
296 | |||
297 | <%def name="pullrequest_comments(comments_nr)"> |
|
297 | <%def name="pullrequest_comments(comments_nr)"> | |
298 | <i class="icon-comment"></i> ${comments_nr} |
|
298 | <i class="icon-comment"></i> ${comments_nr} | |
299 | </%def> |
|
299 | </%def> | |
300 |
|
300 | |||
301 | <%def name="pullrequest_name(pull_request_id, target_repo_name, short=False)"> |
|
301 | <%def name="pullrequest_name(pull_request_id, target_repo_name, short=False)"> | |
302 | <a href="${h.url('pullrequest_show',repo_name=target_repo_name,pull_request_id=pull_request_id)}"> |
|
302 | <a href="${h.url('pullrequest_show',repo_name=target_repo_name,pull_request_id=pull_request_id)}"> | |
303 | % if short: |
|
303 | % if short: | |
304 | #${pull_request_id} |
|
304 | #${pull_request_id} | |
305 | % else: |
|
305 | % else: | |
306 | ${_('Pull request #%(pr_number)s') % {'pr_number': pull_request_id,}} |
|
306 | ${_('Pull request #%(pr_number)s') % {'pr_number': pull_request_id,}} | |
307 | % endif |
|
307 | % endif | |
308 | </a> |
|
308 | </a> | |
309 | </%def> |
|
309 | </%def> | |
310 |
|
310 | |||
311 | <%def name="pullrequest_updated_on(updated_on)"> |
|
311 | <%def name="pullrequest_updated_on(updated_on)"> | |
312 | ${h.age_component(h.time_to_utcdatetime(updated_on))} |
|
312 | ${h.age_component(h.time_to_utcdatetime(updated_on))} | |
313 | </%def> |
|
313 | </%def> | |
314 |
|
314 | |||
315 | <%def name="pullrequest_author(full_contact)"> |
|
315 | <%def name="pullrequest_author(full_contact)"> | |
316 | ${base.gravatar_with_user(full_contact, 16)} |
|
316 | ${base.gravatar_with_user(full_contact, 16)} | |
317 | </%def> |
|
317 | </%def> |
@@ -1,1208 +1,1117 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 |
|
2 | |||
3 | # Copyright (C) 2010-2017 RhodeCode GmbH |
|
3 | # Copyright (C) 2010-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 urllib |
|
21 | import urllib | |
22 |
|
22 | |||
23 | import mock |
|
23 | import mock | |
24 | import pytest |
|
24 | import pytest | |
25 |
|
25 | |||
26 | from rhodecode.lib import auth |
|
26 | from rhodecode.lib import auth | |
27 | from rhodecode.lib.utils2 import safe_str, str2bool, safe_unicode |
|
27 | from rhodecode.lib.utils2 import safe_str, str2bool, safe_unicode | |
28 | from rhodecode.lib.vcs.exceptions import RepositoryRequirementError |
|
28 | from rhodecode.lib.vcs.exceptions import RepositoryRequirementError | |
29 | from rhodecode.model.db import Repository, RepoGroup, UserRepoToPerm, User,\ |
|
29 | from rhodecode.model.db import Repository, RepoGroup, UserRepoToPerm, User,\ | |
30 | Permission |
|
30 | Permission | |
31 | from rhodecode.model.meta import Session |
|
31 | from rhodecode.model.meta import Session | |
32 | from rhodecode.model.repo import RepoModel |
|
32 | from rhodecode.model.repo import RepoModel | |
33 | from rhodecode.model.repo_group import RepoGroupModel |
|
33 | from rhodecode.model.repo_group import RepoGroupModel | |
34 | from rhodecode.model.settings import SettingsModel, VcsSettingsModel |
|
34 | from rhodecode.model.settings import SettingsModel, VcsSettingsModel | |
35 | from rhodecode.model.user import UserModel |
|
35 | from rhodecode.model.user import UserModel | |
36 | from rhodecode.tests import ( |
|
36 | from rhodecode.tests import ( | |
37 | login_user_session, url, assert_session_flash, TEST_USER_ADMIN_LOGIN, |
|
37 | login_user_session, url, assert_session_flash, TEST_USER_ADMIN_LOGIN, | |
38 | TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, HG_REPO, GIT_REPO, |
|
38 | TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, HG_REPO, GIT_REPO, | |
39 | logout_user_session) |
|
39 | logout_user_session) | |
40 | from rhodecode.tests.fixture import Fixture, error_function |
|
40 | from rhodecode.tests.fixture import Fixture, error_function | |
41 | from rhodecode.tests.utils import AssertResponse, repo_on_filesystem |
|
41 | from rhodecode.tests.utils import AssertResponse, repo_on_filesystem | |
42 |
|
42 | |||
43 | fixture = Fixture() |
|
43 | fixture = Fixture() | |
44 |
|
44 | |||
45 |
|
45 | |||
46 | @pytest.mark.usefixtures("app") |
|
46 | @pytest.mark.usefixtures("app") | |
47 | class TestAdminRepos(object): |
|
47 | class TestAdminRepos(object): | |
48 |
|
48 | |||
49 | def test_index(self): |
|
49 | def test_index(self): | |
50 | self.app.get(url('repos')) |
|
50 | self.app.get(url('repos')) | |
51 |
|
51 | |||
52 | def test_create_page_restricted(self, autologin_user, backend): |
|
52 | def test_create_page_restricted(self, autologin_user, backend): | |
53 | with mock.patch('rhodecode.BACKENDS', {'git': 'git'}): |
|
53 | with mock.patch('rhodecode.BACKENDS', {'git': 'git'}): | |
54 | response = self.app.get(url('new_repo'), status=200) |
|
54 | response = self.app.get(url('new_repo'), status=200) | |
55 | assert_response = AssertResponse(response) |
|
55 | assert_response = AssertResponse(response) | |
56 | element = assert_response.get_element('#repo_type') |
|
56 | element = assert_response.get_element('#repo_type') | |
57 | assert element.text_content() == '\ngit\n' |
|
57 | assert element.text_content() == '\ngit\n' | |
58 |
|
58 | |||
59 | def test_create_page_non_restricted(self, autologin_user, backend): |
|
59 | def test_create_page_non_restricted(self, autologin_user, backend): | |
60 | response = self.app.get(url('new_repo'), status=200) |
|
60 | response = self.app.get(url('new_repo'), status=200) | |
61 | assert_response = AssertResponse(response) |
|
61 | assert_response = AssertResponse(response) | |
62 | assert_response.element_contains('#repo_type', 'git') |
|
62 | assert_response.element_contains('#repo_type', 'git') | |
63 | assert_response.element_contains('#repo_type', 'svn') |
|
63 | assert_response.element_contains('#repo_type', 'svn') | |
64 | assert_response.element_contains('#repo_type', 'hg') |
|
64 | assert_response.element_contains('#repo_type', 'hg') | |
65 |
|
65 | |||
66 | @pytest.mark.parametrize("suffix", |
|
66 | @pytest.mark.parametrize("suffix", | |
67 | [u'', u'xxa'], ids=['', 'non-ascii']) |
|
67 | [u'', u'xxa'], ids=['', 'non-ascii']) | |
68 | def test_create(self, autologin_user, backend, suffix, csrf_token): |
|
68 | def test_create(self, autologin_user, backend, suffix, csrf_token): | |
69 | repo_name_unicode = backend.new_repo_name(suffix=suffix) |
|
69 | repo_name_unicode = backend.new_repo_name(suffix=suffix) | |
70 | repo_name = repo_name_unicode.encode('utf8') |
|
70 | repo_name = repo_name_unicode.encode('utf8') | |
71 | description_unicode = u'description for newly created repo' + suffix |
|
71 | description_unicode = u'description for newly created repo' + suffix | |
72 | description = description_unicode.encode('utf8') |
|
72 | description = description_unicode.encode('utf8') | |
73 | response = self.app.post( |
|
73 | response = self.app.post( | |
74 | url('repos'), |
|
74 | url('repos'), | |
75 | fixture._get_repo_create_params( |
|
75 | fixture._get_repo_create_params( | |
76 | repo_private=False, |
|
76 | repo_private=False, | |
77 | repo_name=repo_name, |
|
77 | repo_name=repo_name, | |
78 | repo_type=backend.alias, |
|
78 | repo_type=backend.alias, | |
79 | repo_description=description, |
|
79 | repo_description=description, | |
80 | csrf_token=csrf_token), |
|
80 | csrf_token=csrf_token), | |
81 | status=302) |
|
81 | status=302) | |
82 |
|
82 | |||
83 | self.assert_repository_is_created_correctly( |
|
83 | self.assert_repository_is_created_correctly( | |
84 | repo_name, description, backend) |
|
84 | repo_name, description, backend) | |
85 |
|
85 | |||
86 | def test_create_numeric(self, autologin_user, backend, csrf_token): |
|
86 | def test_create_numeric(self, autologin_user, backend, csrf_token): | |
87 | numeric_repo = '1234' |
|
87 | numeric_repo = '1234' | |
88 | repo_name = numeric_repo |
|
88 | repo_name = numeric_repo | |
89 | description = 'description for newly created repo' + numeric_repo |
|
89 | description = 'description for newly created repo' + numeric_repo | |
90 | self.app.post( |
|
90 | self.app.post( | |
91 | url('repos'), |
|
91 | url('repos'), | |
92 | fixture._get_repo_create_params( |
|
92 | fixture._get_repo_create_params( | |
93 | repo_private=False, |
|
93 | repo_private=False, | |
94 | repo_name=repo_name, |
|
94 | repo_name=repo_name, | |
95 | repo_type=backend.alias, |
|
95 | repo_type=backend.alias, | |
96 | repo_description=description, |
|
96 | repo_description=description, | |
97 | csrf_token=csrf_token)) |
|
97 | csrf_token=csrf_token)) | |
98 |
|
98 | |||
99 | self.assert_repository_is_created_correctly( |
|
99 | self.assert_repository_is_created_correctly( | |
100 | repo_name, description, backend) |
|
100 | repo_name, description, backend) | |
101 |
|
101 | |||
102 | @pytest.mark.parametrize("suffix", [u'', u'Δ ΔΔ'], ids=['', 'non-ascii']) |
|
102 | @pytest.mark.parametrize("suffix", [u'', u'Δ ΔΔ'], ids=['', 'non-ascii']) | |
103 | def test_create_in_group( |
|
103 | def test_create_in_group( | |
104 | self, autologin_user, backend, suffix, csrf_token): |
|
104 | self, autologin_user, backend, suffix, csrf_token): | |
105 | # create GROUP |
|
105 | # create GROUP | |
106 | group_name = 'sometest_%s' % backend.alias |
|
106 | group_name = 'sometest_%s' % backend.alias | |
107 | gr = RepoGroupModel().create(group_name=group_name, |
|
107 | gr = RepoGroupModel().create(group_name=group_name, | |
108 | group_description='test', |
|
108 | group_description='test', | |
109 | owner=TEST_USER_ADMIN_LOGIN) |
|
109 | owner=TEST_USER_ADMIN_LOGIN) | |
110 | Session().commit() |
|
110 | Session().commit() | |
111 |
|
111 | |||
112 | repo_name = u'ingroup' + suffix |
|
112 | repo_name = u'ingroup' + suffix | |
113 | repo_name_full = RepoGroup.url_sep().join( |
|
113 | repo_name_full = RepoGroup.url_sep().join( | |
114 | [group_name, repo_name]) |
|
114 | [group_name, repo_name]) | |
115 | description = u'description for newly created repo' |
|
115 | description = u'description for newly created repo' | |
116 | self.app.post( |
|
116 | self.app.post( | |
117 | url('repos'), |
|
117 | url('repos'), | |
118 | fixture._get_repo_create_params( |
|
118 | fixture._get_repo_create_params( | |
119 | repo_private=False, |
|
119 | repo_private=False, | |
120 | repo_name=safe_str(repo_name), |
|
120 | repo_name=safe_str(repo_name), | |
121 | repo_type=backend.alias, |
|
121 | repo_type=backend.alias, | |
122 | repo_description=description, |
|
122 | repo_description=description, | |
123 | repo_group=gr.group_id, |
|
123 | repo_group=gr.group_id, | |
124 | csrf_token=csrf_token)) |
|
124 | csrf_token=csrf_token)) | |
125 |
|
125 | |||
126 | # TODO: johbo: Cleanup work to fixture |
|
126 | # TODO: johbo: Cleanup work to fixture | |
127 | try: |
|
127 | try: | |
128 | self.assert_repository_is_created_correctly( |
|
128 | self.assert_repository_is_created_correctly( | |
129 | repo_name_full, description, backend) |
|
129 | repo_name_full, description, backend) | |
130 |
|
130 | |||
131 | new_repo = RepoModel().get_by_repo_name(repo_name_full) |
|
131 | new_repo = RepoModel().get_by_repo_name(repo_name_full) | |
132 | inherited_perms = UserRepoToPerm.query().filter( |
|
132 | inherited_perms = UserRepoToPerm.query().filter( | |
133 | UserRepoToPerm.repository_id == new_repo.repo_id).all() |
|
133 | UserRepoToPerm.repository_id == new_repo.repo_id).all() | |
134 | assert len(inherited_perms) == 1 |
|
134 | assert len(inherited_perms) == 1 | |
135 | finally: |
|
135 | finally: | |
136 | RepoModel().delete(repo_name_full) |
|
136 | RepoModel().delete(repo_name_full) | |
137 | RepoGroupModel().delete(group_name) |
|
137 | RepoGroupModel().delete(group_name) | |
138 | Session().commit() |
|
138 | Session().commit() | |
139 |
|
139 | |||
140 | def test_create_in_group_numeric( |
|
140 | def test_create_in_group_numeric( | |
141 | self, autologin_user, backend, csrf_token): |
|
141 | self, autologin_user, backend, csrf_token): | |
142 | # create GROUP |
|
142 | # create GROUP | |
143 | group_name = 'sometest_%s' % backend.alias |
|
143 | group_name = 'sometest_%s' % backend.alias | |
144 | gr = RepoGroupModel().create(group_name=group_name, |
|
144 | gr = RepoGroupModel().create(group_name=group_name, | |
145 | group_description='test', |
|
145 | group_description='test', | |
146 | owner=TEST_USER_ADMIN_LOGIN) |
|
146 | owner=TEST_USER_ADMIN_LOGIN) | |
147 | Session().commit() |
|
147 | Session().commit() | |
148 |
|
148 | |||
149 | repo_name = '12345' |
|
149 | repo_name = '12345' | |
150 | repo_name_full = RepoGroup.url_sep().join([group_name, repo_name]) |
|
150 | repo_name_full = RepoGroup.url_sep().join([group_name, repo_name]) | |
151 | description = 'description for newly created repo' |
|
151 | description = 'description for newly created repo' | |
152 | self.app.post( |
|
152 | self.app.post( | |
153 | url('repos'), |
|
153 | url('repos'), | |
154 | fixture._get_repo_create_params( |
|
154 | fixture._get_repo_create_params( | |
155 | repo_private=False, |
|
155 | repo_private=False, | |
156 | repo_name=repo_name, |
|
156 | repo_name=repo_name, | |
157 | repo_type=backend.alias, |
|
157 | repo_type=backend.alias, | |
158 | repo_description=description, |
|
158 | repo_description=description, | |
159 | repo_group=gr.group_id, |
|
159 | repo_group=gr.group_id, | |
160 | csrf_token=csrf_token)) |
|
160 | csrf_token=csrf_token)) | |
161 |
|
161 | |||
162 | # TODO: johbo: Cleanup work to fixture |
|
162 | # TODO: johbo: Cleanup work to fixture | |
163 | try: |
|
163 | try: | |
164 | self.assert_repository_is_created_correctly( |
|
164 | self.assert_repository_is_created_correctly( | |
165 | repo_name_full, description, backend) |
|
165 | repo_name_full, description, backend) | |
166 |
|
166 | |||
167 | new_repo = RepoModel().get_by_repo_name(repo_name_full) |
|
167 | new_repo = RepoModel().get_by_repo_name(repo_name_full) | |
168 | inherited_perms = UserRepoToPerm.query()\ |
|
168 | inherited_perms = UserRepoToPerm.query()\ | |
169 | .filter(UserRepoToPerm.repository_id == new_repo.repo_id).all() |
|
169 | .filter(UserRepoToPerm.repository_id == new_repo.repo_id).all() | |
170 | assert len(inherited_perms) == 1 |
|
170 | assert len(inherited_perms) == 1 | |
171 | finally: |
|
171 | finally: | |
172 | RepoModel().delete(repo_name_full) |
|
172 | RepoModel().delete(repo_name_full) | |
173 | RepoGroupModel().delete(group_name) |
|
173 | RepoGroupModel().delete(group_name) | |
174 | Session().commit() |
|
174 | Session().commit() | |
175 |
|
175 | |||
176 | def test_create_in_group_without_needed_permissions(self, backend): |
|
176 | def test_create_in_group_without_needed_permissions(self, backend): | |
177 | session = login_user_session( |
|
177 | session = login_user_session( | |
178 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) |
|
178 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) | |
179 | csrf_token = auth.get_csrf_token(session) |
|
179 | csrf_token = auth.get_csrf_token(session) | |
180 | # revoke |
|
180 | # revoke | |
181 | user_model = UserModel() |
|
181 | user_model = UserModel() | |
182 | # disable fork and create on default user |
|
182 | # disable fork and create on default user | |
183 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.create.repository') |
|
183 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.create.repository') | |
184 | user_model.grant_perm(User.DEFAULT_USER, 'hg.create.none') |
|
184 | user_model.grant_perm(User.DEFAULT_USER, 'hg.create.none') | |
185 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.fork.repository') |
|
185 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.fork.repository') | |
186 | user_model.grant_perm(User.DEFAULT_USER, 'hg.fork.none') |
|
186 | user_model.grant_perm(User.DEFAULT_USER, 'hg.fork.none') | |
187 |
|
187 | |||
188 | # disable on regular user |
|
188 | # disable on regular user | |
189 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.repository') |
|
189 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.repository') | |
190 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.none') |
|
190 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.none') | |
191 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.repository') |
|
191 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.repository') | |
192 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.none') |
|
192 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.none') | |
193 | Session().commit() |
|
193 | Session().commit() | |
194 |
|
194 | |||
195 | # create GROUP |
|
195 | # create GROUP | |
196 | group_name = 'reg_sometest_%s' % backend.alias |
|
196 | group_name = 'reg_sometest_%s' % backend.alias | |
197 | gr = RepoGroupModel().create(group_name=group_name, |
|
197 | gr = RepoGroupModel().create(group_name=group_name, | |
198 | group_description='test', |
|
198 | group_description='test', | |
199 | owner=TEST_USER_ADMIN_LOGIN) |
|
199 | owner=TEST_USER_ADMIN_LOGIN) | |
200 | Session().commit() |
|
200 | Session().commit() | |
201 |
|
201 | |||
202 | group_name_allowed = 'reg_sometest_allowed_%s' % backend.alias |
|
202 | group_name_allowed = 'reg_sometest_allowed_%s' % backend.alias | |
203 | gr_allowed = RepoGroupModel().create( |
|
203 | gr_allowed = RepoGroupModel().create( | |
204 | group_name=group_name_allowed, |
|
204 | group_name=group_name_allowed, | |
205 | group_description='test', |
|
205 | group_description='test', | |
206 | owner=TEST_USER_REGULAR_LOGIN) |
|
206 | owner=TEST_USER_REGULAR_LOGIN) | |
207 | Session().commit() |
|
207 | Session().commit() | |
208 |
|
208 | |||
209 | repo_name = 'ingroup' |
|
209 | repo_name = 'ingroup' | |
210 | description = 'description for newly created repo' |
|
210 | description = 'description for newly created repo' | |
211 | response = self.app.post( |
|
211 | response = self.app.post( | |
212 | url('repos'), |
|
212 | url('repos'), | |
213 | fixture._get_repo_create_params( |
|
213 | fixture._get_repo_create_params( | |
214 | repo_private=False, |
|
214 | repo_private=False, | |
215 | repo_name=repo_name, |
|
215 | repo_name=repo_name, | |
216 | repo_type=backend.alias, |
|
216 | repo_type=backend.alias, | |
217 | repo_description=description, |
|
217 | repo_description=description, | |
218 | repo_group=gr.group_id, |
|
218 | repo_group=gr.group_id, | |
219 | csrf_token=csrf_token)) |
|
219 | csrf_token=csrf_token)) | |
220 |
|
220 | |||
221 | response.mustcontain('Invalid value') |
|
221 | response.mustcontain('Invalid value') | |
222 |
|
222 | |||
223 | # user is allowed to create in this group |
|
223 | # user is allowed to create in this group | |
224 | repo_name = 'ingroup' |
|
224 | repo_name = 'ingroup' | |
225 | repo_name_full = RepoGroup.url_sep().join( |
|
225 | repo_name_full = RepoGroup.url_sep().join( | |
226 | [group_name_allowed, repo_name]) |
|
226 | [group_name_allowed, repo_name]) | |
227 | description = 'description for newly created repo' |
|
227 | description = 'description for newly created repo' | |
228 | response = self.app.post( |
|
228 | response = self.app.post( | |
229 | url('repos'), |
|
229 | url('repos'), | |
230 | fixture._get_repo_create_params( |
|
230 | fixture._get_repo_create_params( | |
231 | repo_private=False, |
|
231 | repo_private=False, | |
232 | repo_name=repo_name, |
|
232 | repo_name=repo_name, | |
233 | repo_type=backend.alias, |
|
233 | repo_type=backend.alias, | |
234 | repo_description=description, |
|
234 | repo_description=description, | |
235 | repo_group=gr_allowed.group_id, |
|
235 | repo_group=gr_allowed.group_id, | |
236 | csrf_token=csrf_token)) |
|
236 | csrf_token=csrf_token)) | |
237 |
|
237 | |||
238 | # TODO: johbo: Cleanup in pytest fixture |
|
238 | # TODO: johbo: Cleanup in pytest fixture | |
239 | try: |
|
239 | try: | |
240 | self.assert_repository_is_created_correctly( |
|
240 | self.assert_repository_is_created_correctly( | |
241 | repo_name_full, description, backend) |
|
241 | repo_name_full, description, backend) | |
242 |
|
242 | |||
243 | new_repo = RepoModel().get_by_repo_name(repo_name_full) |
|
243 | new_repo = RepoModel().get_by_repo_name(repo_name_full) | |
244 | inherited_perms = UserRepoToPerm.query().filter( |
|
244 | inherited_perms = UserRepoToPerm.query().filter( | |
245 | UserRepoToPerm.repository_id == new_repo.repo_id).all() |
|
245 | UserRepoToPerm.repository_id == new_repo.repo_id).all() | |
246 | assert len(inherited_perms) == 1 |
|
246 | assert len(inherited_perms) == 1 | |
247 |
|
247 | |||
248 | assert repo_on_filesystem(repo_name_full) |
|
248 | assert repo_on_filesystem(repo_name_full) | |
249 | finally: |
|
249 | finally: | |
250 | RepoModel().delete(repo_name_full) |
|
250 | RepoModel().delete(repo_name_full) | |
251 | RepoGroupModel().delete(group_name) |
|
251 | RepoGroupModel().delete(group_name) | |
252 | RepoGroupModel().delete(group_name_allowed) |
|
252 | RepoGroupModel().delete(group_name_allowed) | |
253 | Session().commit() |
|
253 | Session().commit() | |
254 |
|
254 | |||
255 | def test_create_in_group_inherit_permissions(self, autologin_user, backend, |
|
255 | def test_create_in_group_inherit_permissions(self, autologin_user, backend, | |
256 | csrf_token): |
|
256 | csrf_token): | |
257 | # create GROUP |
|
257 | # create GROUP | |
258 | group_name = 'sometest_%s' % backend.alias |
|
258 | group_name = 'sometest_%s' % backend.alias | |
259 | gr = RepoGroupModel().create(group_name=group_name, |
|
259 | gr = RepoGroupModel().create(group_name=group_name, | |
260 | group_description='test', |
|
260 | group_description='test', | |
261 | owner=TEST_USER_ADMIN_LOGIN) |
|
261 | owner=TEST_USER_ADMIN_LOGIN) | |
262 | perm = Permission.get_by_key('repository.write') |
|
262 | perm = Permission.get_by_key('repository.write') | |
263 | RepoGroupModel().grant_user_permission( |
|
263 | RepoGroupModel().grant_user_permission( | |
264 | gr, TEST_USER_REGULAR_LOGIN, perm) |
|
264 | gr, TEST_USER_REGULAR_LOGIN, perm) | |
265 |
|
265 | |||
266 | # add repo permissions |
|
266 | # add repo permissions | |
267 | Session().commit() |
|
267 | Session().commit() | |
268 |
|
268 | |||
269 | repo_name = 'ingroup_inherited_%s' % backend.alias |
|
269 | repo_name = 'ingroup_inherited_%s' % backend.alias | |
270 | repo_name_full = RepoGroup.url_sep().join([group_name, repo_name]) |
|
270 | repo_name_full = RepoGroup.url_sep().join([group_name, repo_name]) | |
271 | description = 'description for newly created repo' |
|
271 | description = 'description for newly created repo' | |
272 | self.app.post( |
|
272 | self.app.post( | |
273 | url('repos'), |
|
273 | url('repos'), | |
274 | fixture._get_repo_create_params( |
|
274 | fixture._get_repo_create_params( | |
275 | repo_private=False, |
|
275 | repo_private=False, | |
276 | repo_name=repo_name, |
|
276 | repo_name=repo_name, | |
277 | repo_type=backend.alias, |
|
277 | repo_type=backend.alias, | |
278 | repo_description=description, |
|
278 | repo_description=description, | |
279 | repo_group=gr.group_id, |
|
279 | repo_group=gr.group_id, | |
280 | repo_copy_permissions=True, |
|
280 | repo_copy_permissions=True, | |
281 | csrf_token=csrf_token)) |
|
281 | csrf_token=csrf_token)) | |
282 |
|
282 | |||
283 | # TODO: johbo: Cleanup to pytest fixture |
|
283 | # TODO: johbo: Cleanup to pytest fixture | |
284 | try: |
|
284 | try: | |
285 | self.assert_repository_is_created_correctly( |
|
285 | self.assert_repository_is_created_correctly( | |
286 | repo_name_full, description, backend) |
|
286 | repo_name_full, description, backend) | |
287 | except Exception: |
|
287 | except Exception: | |
288 | RepoGroupModel().delete(group_name) |
|
288 | RepoGroupModel().delete(group_name) | |
289 | Session().commit() |
|
289 | Session().commit() | |
290 | raise |
|
290 | raise | |
291 |
|
291 | |||
292 | # check if inherited permissions are applied |
|
292 | # check if inherited permissions are applied | |
293 | new_repo = RepoModel().get_by_repo_name(repo_name_full) |
|
293 | new_repo = RepoModel().get_by_repo_name(repo_name_full) | |
294 | inherited_perms = UserRepoToPerm.query().filter( |
|
294 | inherited_perms = UserRepoToPerm.query().filter( | |
295 | UserRepoToPerm.repository_id == new_repo.repo_id).all() |
|
295 | UserRepoToPerm.repository_id == new_repo.repo_id).all() | |
296 | assert len(inherited_perms) == 2 |
|
296 | assert len(inherited_perms) == 2 | |
297 |
|
297 | |||
298 | assert TEST_USER_REGULAR_LOGIN in [ |
|
298 | assert TEST_USER_REGULAR_LOGIN in [ | |
299 | x.user.username for x in inherited_perms] |
|
299 | x.user.username for x in inherited_perms] | |
300 | assert 'repository.write' in [ |
|
300 | assert 'repository.write' in [ | |
301 | x.permission.permission_name for x in inherited_perms] |
|
301 | x.permission.permission_name for x in inherited_perms] | |
302 |
|
302 | |||
303 | RepoModel().delete(repo_name_full) |
|
303 | RepoModel().delete(repo_name_full) | |
304 | RepoGroupModel().delete(group_name) |
|
304 | RepoGroupModel().delete(group_name) | |
305 | Session().commit() |
|
305 | Session().commit() | |
306 |
|
306 | |||
307 | @pytest.mark.xfail_backends( |
|
307 | @pytest.mark.xfail_backends( | |
308 | "git", "hg", reason="Missing reposerver support") |
|
308 | "git", "hg", reason="Missing reposerver support") | |
309 | def test_create_with_clone_uri(self, autologin_user, backend, reposerver, |
|
309 | def test_create_with_clone_uri(self, autologin_user, backend, reposerver, | |
310 | csrf_token): |
|
310 | csrf_token): | |
311 | source_repo = backend.create_repo(number_of_commits=2) |
|
311 | source_repo = backend.create_repo(number_of_commits=2) | |
312 | source_repo_name = source_repo.repo_name |
|
312 | source_repo_name = source_repo.repo_name | |
313 | reposerver.serve(source_repo.scm_instance()) |
|
313 | reposerver.serve(source_repo.scm_instance()) | |
314 |
|
314 | |||
315 | repo_name = backend.new_repo_name() |
|
315 | repo_name = backend.new_repo_name() | |
316 | response = self.app.post( |
|
316 | response = self.app.post( | |
317 | url('repos'), |
|
317 | url('repos'), | |
318 | fixture._get_repo_create_params( |
|
318 | fixture._get_repo_create_params( | |
319 | repo_private=False, |
|
319 | repo_private=False, | |
320 | repo_name=repo_name, |
|
320 | repo_name=repo_name, | |
321 | repo_type=backend.alias, |
|
321 | repo_type=backend.alias, | |
322 | repo_description='', |
|
322 | repo_description='', | |
323 | clone_uri=reposerver.url, |
|
323 | clone_uri=reposerver.url, | |
324 | csrf_token=csrf_token), |
|
324 | csrf_token=csrf_token), | |
325 | status=302) |
|
325 | status=302) | |
326 |
|
326 | |||
327 | # Should be redirected to the creating page |
|
327 | # Should be redirected to the creating page | |
328 | response.mustcontain('repo_creating') |
|
328 | response.mustcontain('repo_creating') | |
329 |
|
329 | |||
330 | # Expecting that both repositories have same history |
|
330 | # Expecting that both repositories have same history | |
331 | source_repo = RepoModel().get_by_repo_name(source_repo_name) |
|
331 | source_repo = RepoModel().get_by_repo_name(source_repo_name) | |
332 | source_vcs = source_repo.scm_instance() |
|
332 | source_vcs = source_repo.scm_instance() | |
333 | repo = RepoModel().get_by_repo_name(repo_name) |
|
333 | repo = RepoModel().get_by_repo_name(repo_name) | |
334 | repo_vcs = repo.scm_instance() |
|
334 | repo_vcs = repo.scm_instance() | |
335 | assert source_vcs[0].message == repo_vcs[0].message |
|
335 | assert source_vcs[0].message == repo_vcs[0].message | |
336 | assert source_vcs.count() == repo_vcs.count() |
|
336 | assert source_vcs.count() == repo_vcs.count() | |
337 | assert source_vcs.commit_ids == repo_vcs.commit_ids |
|
337 | assert source_vcs.commit_ids == repo_vcs.commit_ids | |
338 |
|
338 | |||
339 | @pytest.mark.xfail_backends("svn", reason="Depends on import support") |
|
339 | @pytest.mark.xfail_backends("svn", reason="Depends on import support") | |
340 | def test_create_remote_repo_wrong_clone_uri(self, autologin_user, backend, |
|
340 | def test_create_remote_repo_wrong_clone_uri(self, autologin_user, backend, | |
341 | csrf_token): |
|
341 | csrf_token): | |
342 | repo_name = backend.new_repo_name() |
|
342 | repo_name = backend.new_repo_name() | |
343 | description = 'description for newly created repo' |
|
343 | description = 'description for newly created repo' | |
344 | response = self.app.post( |
|
344 | response = self.app.post( | |
345 | url('repos'), |
|
345 | url('repos'), | |
346 | fixture._get_repo_create_params( |
|
346 | fixture._get_repo_create_params( | |
347 | repo_private=False, |
|
347 | repo_private=False, | |
348 | repo_name=repo_name, |
|
348 | repo_name=repo_name, | |
349 | repo_type=backend.alias, |
|
349 | repo_type=backend.alias, | |
350 | repo_description=description, |
|
350 | repo_description=description, | |
351 | clone_uri='http://repo.invalid/repo', |
|
351 | clone_uri='http://repo.invalid/repo', | |
352 | csrf_token=csrf_token)) |
|
352 | csrf_token=csrf_token)) | |
353 | response.mustcontain('invalid clone url') |
|
353 | response.mustcontain('invalid clone url') | |
354 |
|
354 | |||
355 | @pytest.mark.xfail_backends("svn", reason="Depends on import support") |
|
355 | @pytest.mark.xfail_backends("svn", reason="Depends on import support") | |
356 | def test_create_remote_repo_wrong_clone_uri_hg_svn( |
|
356 | def test_create_remote_repo_wrong_clone_uri_hg_svn( | |
357 | self, autologin_user, backend, csrf_token): |
|
357 | self, autologin_user, backend, csrf_token): | |
358 | repo_name = backend.new_repo_name() |
|
358 | repo_name = backend.new_repo_name() | |
359 | description = 'description for newly created repo' |
|
359 | description = 'description for newly created repo' | |
360 | response = self.app.post( |
|
360 | response = self.app.post( | |
361 | url('repos'), |
|
361 | url('repos'), | |
362 | fixture._get_repo_create_params( |
|
362 | fixture._get_repo_create_params( | |
363 | repo_private=False, |
|
363 | repo_private=False, | |
364 | repo_name=repo_name, |
|
364 | repo_name=repo_name, | |
365 | repo_type=backend.alias, |
|
365 | repo_type=backend.alias, | |
366 | repo_description=description, |
|
366 | repo_description=description, | |
367 | clone_uri='svn+http://svn.invalid/repo', |
|
367 | clone_uri='svn+http://svn.invalid/repo', | |
368 | csrf_token=csrf_token)) |
|
368 | csrf_token=csrf_token)) | |
369 | response.mustcontain('invalid clone url') |
|
369 | response.mustcontain('invalid clone url') | |
370 |
|
370 | |||
371 | def test_create_with_git_suffix( |
|
371 | def test_create_with_git_suffix( | |
372 | self, autologin_user, backend, csrf_token): |
|
372 | self, autologin_user, backend, csrf_token): | |
373 | repo_name = backend.new_repo_name() + ".git" |
|
373 | repo_name = backend.new_repo_name() + ".git" | |
374 | description = 'description for newly created repo' |
|
374 | description = 'description for newly created repo' | |
375 | response = self.app.post( |
|
375 | response = self.app.post( | |
376 | url('repos'), |
|
376 | url('repos'), | |
377 | fixture._get_repo_create_params( |
|
377 | fixture._get_repo_create_params( | |
378 | repo_private=False, |
|
378 | repo_private=False, | |
379 | repo_name=repo_name, |
|
379 | repo_name=repo_name, | |
380 | repo_type=backend.alias, |
|
380 | repo_type=backend.alias, | |
381 | repo_description=description, |
|
381 | repo_description=description, | |
382 | csrf_token=csrf_token)) |
|
382 | csrf_token=csrf_token)) | |
383 | response.mustcontain('Repository name cannot end with .git') |
|
383 | response.mustcontain('Repository name cannot end with .git') | |
384 |
|
384 | |||
385 | @pytest.mark.parametrize("suffix", [u'', u'Δ ΔΕ'], ids=['', 'non-ascii']) |
|
|||
386 | def test_delete(self, autologin_user, backend, suffix, csrf_token): |
|
|||
387 | repo = backend.create_repo(name_suffix=suffix) |
|
|||
388 | repo_name = repo.repo_name |
|
|||
389 |
|
||||
390 | response = self.app.post(url('repo', repo_name=repo_name), |
|
|||
391 | params={'_method': 'delete', |
|
|||
392 | 'csrf_token': csrf_token}) |
|
|||
393 | assert_session_flash(response, 'Deleted repository %s' % (repo_name)) |
|
|||
394 | response.follow() |
|
|||
395 |
|
||||
396 | # check if repo was deleted from db |
|
|||
397 | assert RepoModel().get_by_repo_name(repo_name) is None |
|
|||
398 | assert not repo_on_filesystem(repo_name) |
|
|||
399 |
|
||||
400 | def test_show(self, autologin_user, backend): |
|
385 | def test_show(self, autologin_user, backend): | |
401 | self.app.get(url('repo', repo_name=backend.repo_name)) |
|
386 | self.app.get(url('repo', repo_name=backend.repo_name)) | |
402 |
|
387 | |||
403 | def test_default_user_cannot_access_private_repo_in_a_group( |
|
388 | def test_default_user_cannot_access_private_repo_in_a_group( | |
404 | self, autologin_user, user_util, backend, csrf_token): |
|
389 | self, autologin_user, user_util, backend, csrf_token): | |
405 |
|
390 | |||
406 | group = user_util.create_repo_group() |
|
391 | group = user_util.create_repo_group() | |
407 |
|
392 | |||
408 | repo = backend.create_repo( |
|
393 | repo = backend.create_repo( | |
409 | repo_private=True, repo_group=group, repo_copy_permissions=True) |
|
394 | repo_private=True, repo_group=group, repo_copy_permissions=True) | |
410 |
|
395 | |||
411 | permissions = _get_permission_for_user( |
|
396 | permissions = _get_permission_for_user( | |
412 | user='default', repo=repo.repo_name) |
|
397 | user='default', repo=repo.repo_name) | |
413 | assert len(permissions) == 1 |
|
398 | assert len(permissions) == 1 | |
414 | assert permissions[0].permission.permission_name == 'repository.none' |
|
399 | assert permissions[0].permission.permission_name == 'repository.none' | |
415 | assert permissions[0].repository.private is True |
|
400 | assert permissions[0].repository.private is True | |
416 |
|
401 | |||
417 | def test_set_repo_fork_has_no_self_id(self, autologin_user, backend): |
|
|||
418 | repo = backend.repo |
|
|||
419 | response = self.app.get( |
|
|||
420 | url('edit_repo_advanced', repo_name=backend.repo_name)) |
|
|||
421 | opt = """<option value="%s">vcs_test_git</option>""" % repo.repo_id |
|
|||
422 | response.mustcontain(no=[opt]) |
|
|||
423 |
|
||||
424 | def test_set_fork_of_target_repo( |
|
|||
425 | self, autologin_user, backend, csrf_token): |
|
|||
426 | target_repo = 'target_%s' % backend.alias |
|
|||
427 | fixture.create_repo(target_repo, repo_type=backend.alias) |
|
|||
428 | repo2 = Repository.get_by_repo_name(target_repo) |
|
|||
429 | response = self.app.post( |
|
|||
430 | url('edit_repo_advanced_fork', repo_name=backend.repo_name), |
|
|||
431 | params={'id_fork_of': repo2.repo_id, '_method': 'put', |
|
|||
432 | 'csrf_token': csrf_token}) |
|
|||
433 | repo = Repository.get_by_repo_name(backend.repo_name) |
|
|||
434 | repo2 = Repository.get_by_repo_name(target_repo) |
|
|||
435 | assert_session_flash( |
|
|||
436 | response, |
|
|||
437 | 'Marked repo %s as fork of %s' % (repo.repo_name, repo2.repo_name)) |
|
|||
438 |
|
||||
439 | assert repo.fork == repo2 |
|
|||
440 | response = response.follow() |
|
|||
441 | # check if given repo is selected |
|
|||
442 |
|
||||
443 | opt = 'This repository is a fork of <a href="%s">%s</a>' % ( |
|
|||
444 | url('summary_home', repo_name=repo2.repo_name), repo2.repo_name) |
|
|||
445 |
|
||||
446 | response.mustcontain(opt) |
|
|||
447 |
|
||||
448 | fixture.destroy_repo(target_repo, forks='detach') |
|
|||
449 |
|
||||
450 | @pytest.mark.backends("hg", "git") |
|
|||
451 | def test_set_fork_of_other_type_repo(self, autologin_user, backend, |
|
|||
452 | csrf_token): |
|
|||
453 | TARGET_REPO_MAP = { |
|
|||
454 | 'git': { |
|
|||
455 | 'type': 'hg', |
|
|||
456 | 'repo_name': HG_REPO}, |
|
|||
457 | 'hg': { |
|
|||
458 | 'type': 'git', |
|
|||
459 | 'repo_name': GIT_REPO}, |
|
|||
460 | } |
|
|||
461 | target_repo = TARGET_REPO_MAP[backend.alias] |
|
|||
462 |
|
||||
463 | repo2 = Repository.get_by_repo_name(target_repo['repo_name']) |
|
|||
464 | response = self.app.post( |
|
|||
465 | url('edit_repo_advanced_fork', repo_name=backend.repo_name), |
|
|||
466 | params={'id_fork_of': repo2.repo_id, '_method': 'put', |
|
|||
467 | 'csrf_token': csrf_token}) |
|
|||
468 | assert_session_flash( |
|
|||
469 | response, |
|
|||
470 | 'Cannot set repository as fork of repository with other type') |
|
|||
471 |
|
||||
472 | def test_set_fork_of_none(self, autologin_user, backend, csrf_token): |
|
|||
473 | # mark it as None |
|
|||
474 | response = self.app.post( |
|
|||
475 | url('edit_repo_advanced_fork', repo_name=backend.repo_name), |
|
|||
476 | params={'id_fork_of': None, '_method': 'put', |
|
|||
477 | 'csrf_token': csrf_token}) |
|
|||
478 | assert_session_flash( |
|
|||
479 | response, |
|
|||
480 | 'Marked repo %s as fork of %s' |
|
|||
481 | % (backend.repo_name, "Nothing")) |
|
|||
482 | assert backend.repo.fork is None |
|
|||
483 |
|
||||
484 | def test_set_fork_of_same_repo(self, autologin_user, backend, csrf_token): |
|
|||
485 | repo = Repository.get_by_repo_name(backend.repo_name) |
|
|||
486 | response = self.app.post( |
|
|||
487 | url('edit_repo_advanced_fork', repo_name=backend.repo_name), |
|
|||
488 | params={'id_fork_of': repo.repo_id, '_method': 'put', |
|
|||
489 | 'csrf_token': csrf_token}) |
|
|||
490 | assert_session_flash( |
|
|||
491 | response, 'An error occurred during this operation') |
|
|||
492 |
|
||||
493 | def test_create_on_top_level_without_permissions(self, backend): |
|
402 | def test_create_on_top_level_without_permissions(self, backend): | |
494 | session = login_user_session( |
|
403 | session = login_user_session( | |
495 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) |
|
404 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) | |
496 | csrf_token = auth.get_csrf_token(session) |
|
405 | csrf_token = auth.get_csrf_token(session) | |
497 |
|
406 | |||
498 | # revoke |
|
407 | # revoke | |
499 | user_model = UserModel() |
|
408 | user_model = UserModel() | |
500 | # disable fork and create on default user |
|
409 | # disable fork and create on default user | |
501 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.create.repository') |
|
410 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.create.repository') | |
502 | user_model.grant_perm(User.DEFAULT_USER, 'hg.create.none') |
|
411 | user_model.grant_perm(User.DEFAULT_USER, 'hg.create.none') | |
503 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.fork.repository') |
|
412 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.fork.repository') | |
504 | user_model.grant_perm(User.DEFAULT_USER, 'hg.fork.none') |
|
413 | user_model.grant_perm(User.DEFAULT_USER, 'hg.fork.none') | |
505 |
|
414 | |||
506 | # disable on regular user |
|
415 | # disable on regular user | |
507 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.repository') |
|
416 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.repository') | |
508 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.none') |
|
417 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.none') | |
509 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.repository') |
|
418 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.repository') | |
510 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.none') |
|
419 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.none') | |
511 | Session().commit() |
|
420 | Session().commit() | |
512 |
|
421 | |||
513 | repo_name = backend.new_repo_name() |
|
422 | repo_name = backend.new_repo_name() | |
514 | description = 'description for newly created repo' |
|
423 | description = 'description for newly created repo' | |
515 | response = self.app.post( |
|
424 | response = self.app.post( | |
516 | url('repos'), |
|
425 | url('repos'), | |
517 | fixture._get_repo_create_params( |
|
426 | fixture._get_repo_create_params( | |
518 | repo_private=False, |
|
427 | repo_private=False, | |
519 | repo_name=repo_name, |
|
428 | repo_name=repo_name, | |
520 | repo_type=backend.alias, |
|
429 | repo_type=backend.alias, | |
521 | repo_description=description, |
|
430 | repo_description=description, | |
522 | csrf_token=csrf_token)) |
|
431 | csrf_token=csrf_token)) | |
523 |
|
432 | |||
524 | response.mustcontain( |
|
433 | response.mustcontain( | |
525 | u"You do not have the permission to store repositories in " |
|
434 | u"You do not have the permission to store repositories in " | |
526 | u"the root location.") |
|
435 | u"the root location.") | |
527 |
|
436 | |||
528 | @mock.patch.object(RepoModel, '_create_filesystem_repo', error_function) |
|
437 | @mock.patch.object(RepoModel, '_create_filesystem_repo', error_function) | |
529 | def test_create_repo_when_filesystem_op_fails( |
|
438 | def test_create_repo_when_filesystem_op_fails( | |
530 | self, autologin_user, backend, csrf_token): |
|
439 | self, autologin_user, backend, csrf_token): | |
531 | repo_name = backend.new_repo_name() |
|
440 | repo_name = backend.new_repo_name() | |
532 | description = 'description for newly created repo' |
|
441 | description = 'description for newly created repo' | |
533 |
|
442 | |||
534 | response = self.app.post( |
|
443 | response = self.app.post( | |
535 | url('repos'), |
|
444 | url('repos'), | |
536 | fixture._get_repo_create_params( |
|
445 | fixture._get_repo_create_params( | |
537 | repo_private=False, |
|
446 | repo_private=False, | |
538 | repo_name=repo_name, |
|
447 | repo_name=repo_name, | |
539 | repo_type=backend.alias, |
|
448 | repo_type=backend.alias, | |
540 | repo_description=description, |
|
449 | repo_description=description, | |
541 | csrf_token=csrf_token)) |
|
450 | csrf_token=csrf_token)) | |
542 |
|
451 | |||
543 | assert_session_flash( |
|
452 | assert_session_flash( | |
544 | response, 'Error creating repository %s' % repo_name) |
|
453 | response, 'Error creating repository %s' % repo_name) | |
545 | # repo must not be in db |
|
454 | # repo must not be in db | |
546 | assert backend.repo is None |
|
455 | assert backend.repo is None | |
547 | # repo must not be in filesystem ! |
|
456 | # repo must not be in filesystem ! | |
548 | assert not repo_on_filesystem(repo_name) |
|
457 | assert not repo_on_filesystem(repo_name) | |
549 |
|
458 | |||
550 | def assert_repository_is_created_correctly( |
|
459 | def assert_repository_is_created_correctly( | |
551 | self, repo_name, description, backend): |
|
460 | self, repo_name, description, backend): | |
552 | repo_name_utf8 = safe_str(repo_name) |
|
461 | repo_name_utf8 = safe_str(repo_name) | |
553 |
|
462 | |||
554 | # run the check page that triggers the flash message |
|
463 | # run the check page that triggers the flash message | |
555 | response = self.app.get(url('repo_check_home', repo_name=repo_name)) |
|
464 | response = self.app.get(url('repo_check_home', repo_name=repo_name)) | |
556 | assert response.json == {u'result': True} |
|
465 | assert response.json == {u'result': True} | |
557 |
|
466 | |||
558 | flash_msg = u'Created repository <a href="/{}">{}</a>'.format( |
|
467 | flash_msg = u'Created repository <a href="/{}">{}</a>'.format( | |
559 | urllib.quote(repo_name_utf8), repo_name) |
|
468 | urllib.quote(repo_name_utf8), repo_name) | |
560 | assert_session_flash(response, flash_msg) |
|
469 | assert_session_flash(response, flash_msg) | |
561 |
|
470 | |||
562 | # test if the repo was created in the database |
|
471 | # test if the repo was created in the database | |
563 | new_repo = RepoModel().get_by_repo_name(repo_name) |
|
472 | new_repo = RepoModel().get_by_repo_name(repo_name) | |
564 |
|
473 | |||
565 | assert new_repo.repo_name == repo_name |
|
474 | assert new_repo.repo_name == repo_name | |
566 | assert new_repo.description == description |
|
475 | assert new_repo.description == description | |
567 |
|
476 | |||
568 | # test if the repository is visible in the list ? |
|
477 | # test if the repository is visible in the list ? | |
569 | response = self.app.get(url('summary_home', repo_name=repo_name)) |
|
478 | response = self.app.get(url('summary_home', repo_name=repo_name)) | |
570 | response.mustcontain(repo_name) |
|
479 | response.mustcontain(repo_name) | |
571 | response.mustcontain(backend.alias) |
|
480 | response.mustcontain(backend.alias) | |
572 |
|
481 | |||
573 | assert repo_on_filesystem(repo_name) |
|
482 | assert repo_on_filesystem(repo_name) | |
574 |
|
483 | |||
575 |
|
484 | |||
576 | @pytest.mark.usefixtures("app") |
|
485 | @pytest.mark.usefixtures("app") | |
577 | class TestVcsSettings(object): |
|
486 | class TestVcsSettings(object): | |
578 | FORM_DATA = { |
|
487 | FORM_DATA = { | |
579 | 'inherit_global_settings': False, |
|
488 | 'inherit_global_settings': False, | |
580 | 'hooks_changegroup_repo_size': False, |
|
489 | 'hooks_changegroup_repo_size': False, | |
581 | 'hooks_changegroup_push_logger': False, |
|
490 | 'hooks_changegroup_push_logger': False, | |
582 | 'hooks_outgoing_pull_logger': False, |
|
491 | 'hooks_outgoing_pull_logger': False, | |
583 | 'extensions_largefiles': False, |
|
492 | 'extensions_largefiles': False, | |
584 | 'extensions_evolve': False, |
|
493 | 'extensions_evolve': False, | |
585 | 'phases_publish': 'False', |
|
494 | 'phases_publish': 'False', | |
586 | 'rhodecode_pr_merge_enabled': False, |
|
495 | 'rhodecode_pr_merge_enabled': False, | |
587 | 'rhodecode_use_outdated_comments': False, |
|
496 | 'rhodecode_use_outdated_comments': False, | |
588 | 'new_svn_branch': '', |
|
497 | 'new_svn_branch': '', | |
589 | 'new_svn_tag': '' |
|
498 | 'new_svn_tag': '' | |
590 | } |
|
499 | } | |
591 |
|
500 | |||
592 | @pytest.mark.skip_backends('svn') |
|
501 | @pytest.mark.skip_backends('svn') | |
593 | def test_global_settings_initial_values(self, autologin_user, backend): |
|
502 | def test_global_settings_initial_values(self, autologin_user, backend): | |
594 | repo_name = backend.repo_name |
|
503 | repo_name = backend.repo_name | |
595 | response = self.app.get(url('repo_vcs_settings', repo_name=repo_name)) |
|
504 | response = self.app.get(url('repo_vcs_settings', repo_name=repo_name)) | |
596 |
|
505 | |||
597 | expected_settings = ( |
|
506 | expected_settings = ( | |
598 | 'rhodecode_use_outdated_comments', 'rhodecode_pr_merge_enabled', |
|
507 | 'rhodecode_use_outdated_comments', 'rhodecode_pr_merge_enabled', | |
599 | 'hooks_changegroup_repo_size', 'hooks_changegroup_push_logger', |
|
508 | 'hooks_changegroup_repo_size', 'hooks_changegroup_push_logger', | |
600 | 'hooks_outgoing_pull_logger' |
|
509 | 'hooks_outgoing_pull_logger' | |
601 | ) |
|
510 | ) | |
602 | for setting in expected_settings: |
|
511 | for setting in expected_settings: | |
603 | self.assert_repo_value_equals_global_value(response, setting) |
|
512 | self.assert_repo_value_equals_global_value(response, setting) | |
604 |
|
513 | |||
605 | def test_show_settings_requires_repo_admin_permission( |
|
514 | def test_show_settings_requires_repo_admin_permission( | |
606 | self, backend, user_util, settings_util): |
|
515 | self, backend, user_util, settings_util): | |
607 | repo = backend.create_repo() |
|
516 | repo = backend.create_repo() | |
608 | repo_name = repo.repo_name |
|
517 | repo_name = repo.repo_name | |
609 | user = UserModel().get_by_username(TEST_USER_REGULAR_LOGIN) |
|
518 | user = UserModel().get_by_username(TEST_USER_REGULAR_LOGIN) | |
610 | user_util.grant_user_permission_to_repo(repo, user, 'repository.admin') |
|
519 | user_util.grant_user_permission_to_repo(repo, user, 'repository.admin') | |
611 | login_user_session( |
|
520 | login_user_session( | |
612 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) |
|
521 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) | |
613 | self.app.get(url('repo_vcs_settings', repo_name=repo_name), status=200) |
|
522 | self.app.get(url('repo_vcs_settings', repo_name=repo_name), status=200) | |
614 |
|
523 | |||
615 | def test_inherit_global_settings_flag_is_true_by_default( |
|
524 | def test_inherit_global_settings_flag_is_true_by_default( | |
616 | self, autologin_user, backend): |
|
525 | self, autologin_user, backend): | |
617 | repo_name = backend.repo_name |
|
526 | repo_name = backend.repo_name | |
618 | response = self.app.get(url('repo_vcs_settings', repo_name=repo_name)) |
|
527 | response = self.app.get(url('repo_vcs_settings', repo_name=repo_name)) | |
619 |
|
528 | |||
620 | assert_response = AssertResponse(response) |
|
529 | assert_response = AssertResponse(response) | |
621 | element = assert_response.get_element('#inherit_global_settings') |
|
530 | element = assert_response.get_element('#inherit_global_settings') | |
622 | assert element.checked |
|
531 | assert element.checked | |
623 |
|
532 | |||
624 | @pytest.mark.parametrize('checked_value', [True, False]) |
|
533 | @pytest.mark.parametrize('checked_value', [True, False]) | |
625 | def test_inherit_global_settings_value( |
|
534 | def test_inherit_global_settings_value( | |
626 | self, autologin_user, backend, checked_value, settings_util): |
|
535 | self, autologin_user, backend, checked_value, settings_util): | |
627 | repo = backend.create_repo() |
|
536 | repo = backend.create_repo() | |
628 | repo_name = repo.repo_name |
|
537 | repo_name = repo.repo_name | |
629 | settings_util.create_repo_rhodecode_setting( |
|
538 | settings_util.create_repo_rhodecode_setting( | |
630 | repo, 'inherit_vcs_settings', checked_value, 'bool') |
|
539 | repo, 'inherit_vcs_settings', checked_value, 'bool') | |
631 | response = self.app.get(url('repo_vcs_settings', repo_name=repo_name)) |
|
540 | response = self.app.get(url('repo_vcs_settings', repo_name=repo_name)) | |
632 |
|
541 | |||
633 | assert_response = AssertResponse(response) |
|
542 | assert_response = AssertResponse(response) | |
634 | element = assert_response.get_element('#inherit_global_settings') |
|
543 | element = assert_response.get_element('#inherit_global_settings') | |
635 | assert element.checked == checked_value |
|
544 | assert element.checked == checked_value | |
636 |
|
545 | |||
637 | @pytest.mark.skip_backends('svn') |
|
546 | @pytest.mark.skip_backends('svn') | |
638 | def test_hooks_settings_are_created( |
|
547 | def test_hooks_settings_are_created( | |
639 | self, autologin_user, backend, csrf_token): |
|
548 | self, autologin_user, backend, csrf_token): | |
640 | repo_name = backend.repo_name |
|
549 | repo_name = backend.repo_name | |
641 | data = self.FORM_DATA.copy() |
|
550 | data = self.FORM_DATA.copy() | |
642 | data['csrf_token'] = csrf_token |
|
551 | data['csrf_token'] = csrf_token | |
643 | self.app.post( |
|
552 | self.app.post( | |
644 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
553 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
645 | settings = SettingsModel(repo=repo_name) |
|
554 | settings = SettingsModel(repo=repo_name) | |
646 | try: |
|
555 | try: | |
647 | for section, key in VcsSettingsModel.HOOKS_SETTINGS: |
|
556 | for section, key in VcsSettingsModel.HOOKS_SETTINGS: | |
648 | ui = settings.get_ui_by_section_and_key(section, key) |
|
557 | ui = settings.get_ui_by_section_and_key(section, key) | |
649 | assert ui.ui_active is False |
|
558 | assert ui.ui_active is False | |
650 | finally: |
|
559 | finally: | |
651 | self._cleanup_repo_settings(settings) |
|
560 | self._cleanup_repo_settings(settings) | |
652 |
|
561 | |||
653 | def test_hooks_settings_are_not_created_for_svn( |
|
562 | def test_hooks_settings_are_not_created_for_svn( | |
654 | self, autologin_user, backend_svn, csrf_token): |
|
563 | self, autologin_user, backend_svn, csrf_token): | |
655 | repo_name = backend_svn.repo_name |
|
564 | repo_name = backend_svn.repo_name | |
656 | data = self.FORM_DATA.copy() |
|
565 | data = self.FORM_DATA.copy() | |
657 | data['csrf_token'] = csrf_token |
|
566 | data['csrf_token'] = csrf_token | |
658 | self.app.post( |
|
567 | self.app.post( | |
659 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
568 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
660 | settings = SettingsModel(repo=repo_name) |
|
569 | settings = SettingsModel(repo=repo_name) | |
661 | try: |
|
570 | try: | |
662 | for section, key in VcsSettingsModel.HOOKS_SETTINGS: |
|
571 | for section, key in VcsSettingsModel.HOOKS_SETTINGS: | |
663 | ui = settings.get_ui_by_section_and_key(section, key) |
|
572 | ui = settings.get_ui_by_section_and_key(section, key) | |
664 | assert ui is None |
|
573 | assert ui is None | |
665 | finally: |
|
574 | finally: | |
666 | self._cleanup_repo_settings(settings) |
|
575 | self._cleanup_repo_settings(settings) | |
667 |
|
576 | |||
668 | @pytest.mark.skip_backends('svn') |
|
577 | @pytest.mark.skip_backends('svn') | |
669 | def test_hooks_settings_are_updated( |
|
578 | def test_hooks_settings_are_updated( | |
670 | self, autologin_user, backend, csrf_token): |
|
579 | self, autologin_user, backend, csrf_token): | |
671 | repo_name = backend.repo_name |
|
580 | repo_name = backend.repo_name | |
672 | settings = SettingsModel(repo=repo_name) |
|
581 | settings = SettingsModel(repo=repo_name) | |
673 | for section, key in VcsSettingsModel.HOOKS_SETTINGS: |
|
582 | for section, key in VcsSettingsModel.HOOKS_SETTINGS: | |
674 | settings.create_ui_section_value(section, '', key=key, active=True) |
|
583 | settings.create_ui_section_value(section, '', key=key, active=True) | |
675 |
|
584 | |||
676 | data = self.FORM_DATA.copy() |
|
585 | data = self.FORM_DATA.copy() | |
677 | data['csrf_token'] = csrf_token |
|
586 | data['csrf_token'] = csrf_token | |
678 | self.app.post( |
|
587 | self.app.post( | |
679 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
588 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
680 | try: |
|
589 | try: | |
681 | for section, key in VcsSettingsModel.HOOKS_SETTINGS: |
|
590 | for section, key in VcsSettingsModel.HOOKS_SETTINGS: | |
682 | ui = settings.get_ui_by_section_and_key(section, key) |
|
591 | ui = settings.get_ui_by_section_and_key(section, key) | |
683 | assert ui.ui_active is False |
|
592 | assert ui.ui_active is False | |
684 | finally: |
|
593 | finally: | |
685 | self._cleanup_repo_settings(settings) |
|
594 | self._cleanup_repo_settings(settings) | |
686 |
|
595 | |||
687 | def test_hooks_settings_are_not_updated_for_svn( |
|
596 | def test_hooks_settings_are_not_updated_for_svn( | |
688 | self, autologin_user, backend_svn, csrf_token): |
|
597 | self, autologin_user, backend_svn, csrf_token): | |
689 | repo_name = backend_svn.repo_name |
|
598 | repo_name = backend_svn.repo_name | |
690 | settings = SettingsModel(repo=repo_name) |
|
599 | settings = SettingsModel(repo=repo_name) | |
691 | for section, key in VcsSettingsModel.HOOKS_SETTINGS: |
|
600 | for section, key in VcsSettingsModel.HOOKS_SETTINGS: | |
692 | settings.create_ui_section_value(section, '', key=key, active=True) |
|
601 | settings.create_ui_section_value(section, '', key=key, active=True) | |
693 |
|
602 | |||
694 | data = self.FORM_DATA.copy() |
|
603 | data = self.FORM_DATA.copy() | |
695 | data['csrf_token'] = csrf_token |
|
604 | data['csrf_token'] = csrf_token | |
696 | self.app.post( |
|
605 | self.app.post( | |
697 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
606 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
698 | try: |
|
607 | try: | |
699 | for section, key in VcsSettingsModel.HOOKS_SETTINGS: |
|
608 | for section, key in VcsSettingsModel.HOOKS_SETTINGS: | |
700 | ui = settings.get_ui_by_section_and_key(section, key) |
|
609 | ui = settings.get_ui_by_section_and_key(section, key) | |
701 | assert ui.ui_active is True |
|
610 | assert ui.ui_active is True | |
702 | finally: |
|
611 | finally: | |
703 | self._cleanup_repo_settings(settings) |
|
612 | self._cleanup_repo_settings(settings) | |
704 |
|
613 | |||
705 | @pytest.mark.skip_backends('svn') |
|
614 | @pytest.mark.skip_backends('svn') | |
706 | def test_pr_settings_are_created( |
|
615 | def test_pr_settings_are_created( | |
707 | self, autologin_user, backend, csrf_token): |
|
616 | self, autologin_user, backend, csrf_token): | |
708 | repo_name = backend.repo_name |
|
617 | repo_name = backend.repo_name | |
709 | data = self.FORM_DATA.copy() |
|
618 | data = self.FORM_DATA.copy() | |
710 | data['csrf_token'] = csrf_token |
|
619 | data['csrf_token'] = csrf_token | |
711 | self.app.post( |
|
620 | self.app.post( | |
712 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
621 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
713 | settings = SettingsModel(repo=repo_name) |
|
622 | settings = SettingsModel(repo=repo_name) | |
714 | try: |
|
623 | try: | |
715 | for name in VcsSettingsModel.GENERAL_SETTINGS: |
|
624 | for name in VcsSettingsModel.GENERAL_SETTINGS: | |
716 | setting = settings.get_setting_by_name(name) |
|
625 | setting = settings.get_setting_by_name(name) | |
717 | assert setting.app_settings_value is False |
|
626 | assert setting.app_settings_value is False | |
718 | finally: |
|
627 | finally: | |
719 | self._cleanup_repo_settings(settings) |
|
628 | self._cleanup_repo_settings(settings) | |
720 |
|
629 | |||
721 | def test_pr_settings_are_not_created_for_svn( |
|
630 | def test_pr_settings_are_not_created_for_svn( | |
722 | self, autologin_user, backend_svn, csrf_token): |
|
631 | self, autologin_user, backend_svn, csrf_token): | |
723 | repo_name = backend_svn.repo_name |
|
632 | repo_name = backend_svn.repo_name | |
724 | data = self.FORM_DATA.copy() |
|
633 | data = self.FORM_DATA.copy() | |
725 | data['csrf_token'] = csrf_token |
|
634 | data['csrf_token'] = csrf_token | |
726 | self.app.post( |
|
635 | self.app.post( | |
727 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
636 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
728 | settings = SettingsModel(repo=repo_name) |
|
637 | settings = SettingsModel(repo=repo_name) | |
729 | try: |
|
638 | try: | |
730 | for name in VcsSettingsModel.GENERAL_SETTINGS: |
|
639 | for name in VcsSettingsModel.GENERAL_SETTINGS: | |
731 | setting = settings.get_setting_by_name(name) |
|
640 | setting = settings.get_setting_by_name(name) | |
732 | assert setting is None |
|
641 | assert setting is None | |
733 | finally: |
|
642 | finally: | |
734 | self._cleanup_repo_settings(settings) |
|
643 | self._cleanup_repo_settings(settings) | |
735 |
|
644 | |||
736 | def test_pr_settings_creation_requires_repo_admin_permission( |
|
645 | def test_pr_settings_creation_requires_repo_admin_permission( | |
737 | self, backend, user_util, settings_util, csrf_token): |
|
646 | self, backend, user_util, settings_util, csrf_token): | |
738 | repo = backend.create_repo() |
|
647 | repo = backend.create_repo() | |
739 | repo_name = repo.repo_name |
|
648 | repo_name = repo.repo_name | |
740 |
|
649 | |||
741 | logout_user_session(self.app, csrf_token) |
|
650 | logout_user_session(self.app, csrf_token) | |
742 | session = login_user_session( |
|
651 | session = login_user_session( | |
743 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) |
|
652 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) | |
744 | new_csrf_token = auth.get_csrf_token(session) |
|
653 | new_csrf_token = auth.get_csrf_token(session) | |
745 |
|
654 | |||
746 | user = UserModel().get_by_username(TEST_USER_REGULAR_LOGIN) |
|
655 | user = UserModel().get_by_username(TEST_USER_REGULAR_LOGIN) | |
747 | repo = Repository.get_by_repo_name(repo_name) |
|
656 | repo = Repository.get_by_repo_name(repo_name) | |
748 | user_util.grant_user_permission_to_repo(repo, user, 'repository.admin') |
|
657 | user_util.grant_user_permission_to_repo(repo, user, 'repository.admin') | |
749 | data = self.FORM_DATA.copy() |
|
658 | data = self.FORM_DATA.copy() | |
750 | data['csrf_token'] = new_csrf_token |
|
659 | data['csrf_token'] = new_csrf_token | |
751 | settings = SettingsModel(repo=repo_name) |
|
660 | settings = SettingsModel(repo=repo_name) | |
752 |
|
661 | |||
753 | try: |
|
662 | try: | |
754 | self.app.post( |
|
663 | self.app.post( | |
755 | url('repo_vcs_settings', repo_name=repo_name), data, |
|
664 | url('repo_vcs_settings', repo_name=repo_name), data, | |
756 | status=302) |
|
665 | status=302) | |
757 | finally: |
|
666 | finally: | |
758 | self._cleanup_repo_settings(settings) |
|
667 | self._cleanup_repo_settings(settings) | |
759 |
|
668 | |||
760 | @pytest.mark.skip_backends('svn') |
|
669 | @pytest.mark.skip_backends('svn') | |
761 | def test_pr_settings_are_updated( |
|
670 | def test_pr_settings_are_updated( | |
762 | self, autologin_user, backend, csrf_token): |
|
671 | self, autologin_user, backend, csrf_token): | |
763 | repo_name = backend.repo_name |
|
672 | repo_name = backend.repo_name | |
764 | settings = SettingsModel(repo=repo_name) |
|
673 | settings = SettingsModel(repo=repo_name) | |
765 | for name in VcsSettingsModel.GENERAL_SETTINGS: |
|
674 | for name in VcsSettingsModel.GENERAL_SETTINGS: | |
766 | settings.create_or_update_setting(name, True, 'bool') |
|
675 | settings.create_or_update_setting(name, True, 'bool') | |
767 |
|
676 | |||
768 | data = self.FORM_DATA.copy() |
|
677 | data = self.FORM_DATA.copy() | |
769 | data['csrf_token'] = csrf_token |
|
678 | data['csrf_token'] = csrf_token | |
770 | self.app.post( |
|
679 | self.app.post( | |
771 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
680 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
772 | try: |
|
681 | try: | |
773 | for name in VcsSettingsModel.GENERAL_SETTINGS: |
|
682 | for name in VcsSettingsModel.GENERAL_SETTINGS: | |
774 | setting = settings.get_setting_by_name(name) |
|
683 | setting = settings.get_setting_by_name(name) | |
775 | assert setting.app_settings_value is False |
|
684 | assert setting.app_settings_value is False | |
776 | finally: |
|
685 | finally: | |
777 | self._cleanup_repo_settings(settings) |
|
686 | self._cleanup_repo_settings(settings) | |
778 |
|
687 | |||
779 | def test_pr_settings_are_not_updated_for_svn( |
|
688 | def test_pr_settings_are_not_updated_for_svn( | |
780 | self, autologin_user, backend_svn, csrf_token): |
|
689 | self, autologin_user, backend_svn, csrf_token): | |
781 | repo_name = backend_svn.repo_name |
|
690 | repo_name = backend_svn.repo_name | |
782 | settings = SettingsModel(repo=repo_name) |
|
691 | settings = SettingsModel(repo=repo_name) | |
783 | for name in VcsSettingsModel.GENERAL_SETTINGS: |
|
692 | for name in VcsSettingsModel.GENERAL_SETTINGS: | |
784 | settings.create_or_update_setting(name, True, 'bool') |
|
693 | settings.create_or_update_setting(name, True, 'bool') | |
785 |
|
694 | |||
786 | data = self.FORM_DATA.copy() |
|
695 | data = self.FORM_DATA.copy() | |
787 | data['csrf_token'] = csrf_token |
|
696 | data['csrf_token'] = csrf_token | |
788 | self.app.post( |
|
697 | self.app.post( | |
789 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
698 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
790 | try: |
|
699 | try: | |
791 | for name in VcsSettingsModel.GENERAL_SETTINGS: |
|
700 | for name in VcsSettingsModel.GENERAL_SETTINGS: | |
792 | setting = settings.get_setting_by_name(name) |
|
701 | setting = settings.get_setting_by_name(name) | |
793 | assert setting.app_settings_value is True |
|
702 | assert setting.app_settings_value is True | |
794 | finally: |
|
703 | finally: | |
795 | self._cleanup_repo_settings(settings) |
|
704 | self._cleanup_repo_settings(settings) | |
796 |
|
705 | |||
797 | def test_svn_settings_are_created( |
|
706 | def test_svn_settings_are_created( | |
798 | self, autologin_user, backend_svn, csrf_token, settings_util): |
|
707 | self, autologin_user, backend_svn, csrf_token, settings_util): | |
799 | repo_name = backend_svn.repo_name |
|
708 | repo_name = backend_svn.repo_name | |
800 | data = self.FORM_DATA.copy() |
|
709 | data = self.FORM_DATA.copy() | |
801 | data['new_svn_tag'] = 'svn-tag' |
|
710 | data['new_svn_tag'] = 'svn-tag' | |
802 | data['new_svn_branch'] = 'svn-branch' |
|
711 | data['new_svn_branch'] = 'svn-branch' | |
803 | data['csrf_token'] = csrf_token |
|
712 | data['csrf_token'] = csrf_token | |
804 |
|
713 | |||
805 | # Create few global settings to make sure that uniqueness validators |
|
714 | # Create few global settings to make sure that uniqueness validators | |
806 | # are not triggered |
|
715 | # are not triggered | |
807 | settings_util.create_rhodecode_ui( |
|
716 | settings_util.create_rhodecode_ui( | |
808 | VcsSettingsModel.SVN_BRANCH_SECTION, 'svn-branch') |
|
717 | VcsSettingsModel.SVN_BRANCH_SECTION, 'svn-branch') | |
809 | settings_util.create_rhodecode_ui( |
|
718 | settings_util.create_rhodecode_ui( | |
810 | VcsSettingsModel.SVN_TAG_SECTION, 'svn-tag') |
|
719 | VcsSettingsModel.SVN_TAG_SECTION, 'svn-tag') | |
811 |
|
720 | |||
812 | self.app.post( |
|
721 | self.app.post( | |
813 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
722 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
814 | settings = SettingsModel(repo=repo_name) |
|
723 | settings = SettingsModel(repo=repo_name) | |
815 | try: |
|
724 | try: | |
816 | svn_branches = settings.get_ui_by_section( |
|
725 | svn_branches = settings.get_ui_by_section( | |
817 | VcsSettingsModel.SVN_BRANCH_SECTION) |
|
726 | VcsSettingsModel.SVN_BRANCH_SECTION) | |
818 | svn_branch_names = [b.ui_value for b in svn_branches] |
|
727 | svn_branch_names = [b.ui_value for b in svn_branches] | |
819 | svn_tags = settings.get_ui_by_section( |
|
728 | svn_tags = settings.get_ui_by_section( | |
820 | VcsSettingsModel.SVN_TAG_SECTION) |
|
729 | VcsSettingsModel.SVN_TAG_SECTION) | |
821 | svn_tag_names = [b.ui_value for b in svn_tags] |
|
730 | svn_tag_names = [b.ui_value for b in svn_tags] | |
822 | assert 'svn-branch' in svn_branch_names |
|
731 | assert 'svn-branch' in svn_branch_names | |
823 | assert 'svn-tag' in svn_tag_names |
|
732 | assert 'svn-tag' in svn_tag_names | |
824 | finally: |
|
733 | finally: | |
825 | self._cleanup_repo_settings(settings) |
|
734 | self._cleanup_repo_settings(settings) | |
826 |
|
735 | |||
827 | def test_svn_settings_are_unique( |
|
736 | def test_svn_settings_are_unique( | |
828 | self, autologin_user, backend_svn, csrf_token, settings_util): |
|
737 | self, autologin_user, backend_svn, csrf_token, settings_util): | |
829 | repo = backend_svn.repo |
|
738 | repo = backend_svn.repo | |
830 | repo_name = repo.repo_name |
|
739 | repo_name = repo.repo_name | |
831 | data = self.FORM_DATA.copy() |
|
740 | data = self.FORM_DATA.copy() | |
832 | data['new_svn_tag'] = 'test_tag' |
|
741 | data['new_svn_tag'] = 'test_tag' | |
833 | data['new_svn_branch'] = 'test_branch' |
|
742 | data['new_svn_branch'] = 'test_branch' | |
834 | data['csrf_token'] = csrf_token |
|
743 | data['csrf_token'] = csrf_token | |
835 | settings_util.create_repo_rhodecode_ui( |
|
744 | settings_util.create_repo_rhodecode_ui( | |
836 | repo, VcsSettingsModel.SVN_BRANCH_SECTION, 'test_branch') |
|
745 | repo, VcsSettingsModel.SVN_BRANCH_SECTION, 'test_branch') | |
837 | settings_util.create_repo_rhodecode_ui( |
|
746 | settings_util.create_repo_rhodecode_ui( | |
838 | repo, VcsSettingsModel.SVN_TAG_SECTION, 'test_tag') |
|
747 | repo, VcsSettingsModel.SVN_TAG_SECTION, 'test_tag') | |
839 |
|
748 | |||
840 | response = self.app.post( |
|
749 | response = self.app.post( | |
841 | url('repo_vcs_settings', repo_name=repo_name), data, status=200) |
|
750 | url('repo_vcs_settings', repo_name=repo_name), data, status=200) | |
842 | response.mustcontain('Pattern already exists') |
|
751 | response.mustcontain('Pattern already exists') | |
843 |
|
752 | |||
844 | def test_svn_settings_with_empty_values_are_not_created( |
|
753 | def test_svn_settings_with_empty_values_are_not_created( | |
845 | self, autologin_user, backend_svn, csrf_token): |
|
754 | self, autologin_user, backend_svn, csrf_token): | |
846 | repo_name = backend_svn.repo_name |
|
755 | repo_name = backend_svn.repo_name | |
847 | data = self.FORM_DATA.copy() |
|
756 | data = self.FORM_DATA.copy() | |
848 | data['csrf_token'] = csrf_token |
|
757 | data['csrf_token'] = csrf_token | |
849 | self.app.post( |
|
758 | self.app.post( | |
850 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
759 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
851 | settings = SettingsModel(repo=repo_name) |
|
760 | settings = SettingsModel(repo=repo_name) | |
852 | try: |
|
761 | try: | |
853 | svn_branches = settings.get_ui_by_section( |
|
762 | svn_branches = settings.get_ui_by_section( | |
854 | VcsSettingsModel.SVN_BRANCH_SECTION) |
|
763 | VcsSettingsModel.SVN_BRANCH_SECTION) | |
855 | svn_tags = settings.get_ui_by_section( |
|
764 | svn_tags = settings.get_ui_by_section( | |
856 | VcsSettingsModel.SVN_TAG_SECTION) |
|
765 | VcsSettingsModel.SVN_TAG_SECTION) | |
857 | assert len(svn_branches) == 0 |
|
766 | assert len(svn_branches) == 0 | |
858 | assert len(svn_tags) == 0 |
|
767 | assert len(svn_tags) == 0 | |
859 | finally: |
|
768 | finally: | |
860 | self._cleanup_repo_settings(settings) |
|
769 | self._cleanup_repo_settings(settings) | |
861 |
|
770 | |||
862 | def test_svn_settings_are_shown_for_svn_repository( |
|
771 | def test_svn_settings_are_shown_for_svn_repository( | |
863 | self, autologin_user, backend_svn, csrf_token): |
|
772 | self, autologin_user, backend_svn, csrf_token): | |
864 | repo_name = backend_svn.repo_name |
|
773 | repo_name = backend_svn.repo_name | |
865 | response = self.app.get( |
|
774 | response = self.app.get( | |
866 | url('repo_vcs_settings', repo_name=repo_name), status=200) |
|
775 | url('repo_vcs_settings', repo_name=repo_name), status=200) | |
867 | response.mustcontain('Subversion Settings') |
|
776 | response.mustcontain('Subversion Settings') | |
868 |
|
777 | |||
869 | @pytest.mark.skip_backends('svn') |
|
778 | @pytest.mark.skip_backends('svn') | |
870 | def test_svn_settings_are_not_created_for_not_svn_repository( |
|
779 | def test_svn_settings_are_not_created_for_not_svn_repository( | |
871 | self, autologin_user, backend, csrf_token): |
|
780 | self, autologin_user, backend, csrf_token): | |
872 | repo_name = backend.repo_name |
|
781 | repo_name = backend.repo_name | |
873 | data = self.FORM_DATA.copy() |
|
782 | data = self.FORM_DATA.copy() | |
874 | data['csrf_token'] = csrf_token |
|
783 | data['csrf_token'] = csrf_token | |
875 | self.app.post( |
|
784 | self.app.post( | |
876 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
785 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
877 | settings = SettingsModel(repo=repo_name) |
|
786 | settings = SettingsModel(repo=repo_name) | |
878 | try: |
|
787 | try: | |
879 | svn_branches = settings.get_ui_by_section( |
|
788 | svn_branches = settings.get_ui_by_section( | |
880 | VcsSettingsModel.SVN_BRANCH_SECTION) |
|
789 | VcsSettingsModel.SVN_BRANCH_SECTION) | |
881 | svn_tags = settings.get_ui_by_section( |
|
790 | svn_tags = settings.get_ui_by_section( | |
882 | VcsSettingsModel.SVN_TAG_SECTION) |
|
791 | VcsSettingsModel.SVN_TAG_SECTION) | |
883 | assert len(svn_branches) == 0 |
|
792 | assert len(svn_branches) == 0 | |
884 | assert len(svn_tags) == 0 |
|
793 | assert len(svn_tags) == 0 | |
885 | finally: |
|
794 | finally: | |
886 | self._cleanup_repo_settings(settings) |
|
795 | self._cleanup_repo_settings(settings) | |
887 |
|
796 | |||
888 | @pytest.mark.skip_backends('svn') |
|
797 | @pytest.mark.skip_backends('svn') | |
889 | def test_svn_settings_are_shown_only_for_svn_repository( |
|
798 | def test_svn_settings_are_shown_only_for_svn_repository( | |
890 | self, autologin_user, backend, csrf_token): |
|
799 | self, autologin_user, backend, csrf_token): | |
891 | repo_name = backend.repo_name |
|
800 | repo_name = backend.repo_name | |
892 | response = self.app.get( |
|
801 | response = self.app.get( | |
893 | url('repo_vcs_settings', repo_name=repo_name), status=200) |
|
802 | url('repo_vcs_settings', repo_name=repo_name), status=200) | |
894 | response.mustcontain(no='Subversion Settings') |
|
803 | response.mustcontain(no='Subversion Settings') | |
895 |
|
804 | |||
896 | def test_hg_settings_are_created( |
|
805 | def test_hg_settings_are_created( | |
897 | self, autologin_user, backend_hg, csrf_token): |
|
806 | self, autologin_user, backend_hg, csrf_token): | |
898 | repo_name = backend_hg.repo_name |
|
807 | repo_name = backend_hg.repo_name | |
899 | data = self.FORM_DATA.copy() |
|
808 | data = self.FORM_DATA.copy() | |
900 | data['new_svn_tag'] = 'svn-tag' |
|
809 | data['new_svn_tag'] = 'svn-tag' | |
901 | data['new_svn_branch'] = 'svn-branch' |
|
810 | data['new_svn_branch'] = 'svn-branch' | |
902 | data['csrf_token'] = csrf_token |
|
811 | data['csrf_token'] = csrf_token | |
903 | self.app.post( |
|
812 | self.app.post( | |
904 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
813 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
905 | settings = SettingsModel(repo=repo_name) |
|
814 | settings = SettingsModel(repo=repo_name) | |
906 | try: |
|
815 | try: | |
907 | largefiles_ui = settings.get_ui_by_section_and_key( |
|
816 | largefiles_ui = settings.get_ui_by_section_and_key( | |
908 | 'extensions', 'largefiles') |
|
817 | 'extensions', 'largefiles') | |
909 | assert largefiles_ui.ui_active is False |
|
818 | assert largefiles_ui.ui_active is False | |
910 | phases_ui = settings.get_ui_by_section_and_key( |
|
819 | phases_ui = settings.get_ui_by_section_and_key( | |
911 | 'phases', 'publish') |
|
820 | 'phases', 'publish') | |
912 | assert str2bool(phases_ui.ui_value) is False |
|
821 | assert str2bool(phases_ui.ui_value) is False | |
913 | finally: |
|
822 | finally: | |
914 | self._cleanup_repo_settings(settings) |
|
823 | self._cleanup_repo_settings(settings) | |
915 |
|
824 | |||
916 | def test_hg_settings_are_updated( |
|
825 | def test_hg_settings_are_updated( | |
917 | self, autologin_user, backend_hg, csrf_token): |
|
826 | self, autologin_user, backend_hg, csrf_token): | |
918 | repo_name = backend_hg.repo_name |
|
827 | repo_name = backend_hg.repo_name | |
919 | settings = SettingsModel(repo=repo_name) |
|
828 | settings = SettingsModel(repo=repo_name) | |
920 | settings.create_ui_section_value( |
|
829 | settings.create_ui_section_value( | |
921 | 'extensions', '', key='largefiles', active=True) |
|
830 | 'extensions', '', key='largefiles', active=True) | |
922 | settings.create_ui_section_value( |
|
831 | settings.create_ui_section_value( | |
923 | 'phases', '1', key='publish', active=True) |
|
832 | 'phases', '1', key='publish', active=True) | |
924 |
|
833 | |||
925 | data = self.FORM_DATA.copy() |
|
834 | data = self.FORM_DATA.copy() | |
926 | data['csrf_token'] = csrf_token |
|
835 | data['csrf_token'] = csrf_token | |
927 | self.app.post( |
|
836 | self.app.post( | |
928 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
837 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
929 | try: |
|
838 | try: | |
930 | largefiles_ui = settings.get_ui_by_section_and_key( |
|
839 | largefiles_ui = settings.get_ui_by_section_and_key( | |
931 | 'extensions', 'largefiles') |
|
840 | 'extensions', 'largefiles') | |
932 | assert largefiles_ui.ui_active is False |
|
841 | assert largefiles_ui.ui_active is False | |
933 | phases_ui = settings.get_ui_by_section_and_key( |
|
842 | phases_ui = settings.get_ui_by_section_and_key( | |
934 | 'phases', 'publish') |
|
843 | 'phases', 'publish') | |
935 | assert str2bool(phases_ui.ui_value) is False |
|
844 | assert str2bool(phases_ui.ui_value) is False | |
936 | finally: |
|
845 | finally: | |
937 | self._cleanup_repo_settings(settings) |
|
846 | self._cleanup_repo_settings(settings) | |
938 |
|
847 | |||
939 | def test_hg_settings_are_shown_for_hg_repository( |
|
848 | def test_hg_settings_are_shown_for_hg_repository( | |
940 | self, autologin_user, backend_hg, csrf_token): |
|
849 | self, autologin_user, backend_hg, csrf_token): | |
941 | repo_name = backend_hg.repo_name |
|
850 | repo_name = backend_hg.repo_name | |
942 | response = self.app.get( |
|
851 | response = self.app.get( | |
943 | url('repo_vcs_settings', repo_name=repo_name), status=200) |
|
852 | url('repo_vcs_settings', repo_name=repo_name), status=200) | |
944 | response.mustcontain('Mercurial Settings') |
|
853 | response.mustcontain('Mercurial Settings') | |
945 |
|
854 | |||
946 | @pytest.mark.skip_backends('hg') |
|
855 | @pytest.mark.skip_backends('hg') | |
947 | def test_hg_settings_are_created_only_for_hg_repository( |
|
856 | def test_hg_settings_are_created_only_for_hg_repository( | |
948 | self, autologin_user, backend, csrf_token): |
|
857 | self, autologin_user, backend, csrf_token): | |
949 | repo_name = backend.repo_name |
|
858 | repo_name = backend.repo_name | |
950 | data = self.FORM_DATA.copy() |
|
859 | data = self.FORM_DATA.copy() | |
951 | data['csrf_token'] = csrf_token |
|
860 | data['csrf_token'] = csrf_token | |
952 | self.app.post( |
|
861 | self.app.post( | |
953 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
862 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
954 | settings = SettingsModel(repo=repo_name) |
|
863 | settings = SettingsModel(repo=repo_name) | |
955 | try: |
|
864 | try: | |
956 | largefiles_ui = settings.get_ui_by_section_and_key( |
|
865 | largefiles_ui = settings.get_ui_by_section_and_key( | |
957 | 'extensions', 'largefiles') |
|
866 | 'extensions', 'largefiles') | |
958 | assert largefiles_ui is None |
|
867 | assert largefiles_ui is None | |
959 | phases_ui = settings.get_ui_by_section_and_key( |
|
868 | phases_ui = settings.get_ui_by_section_and_key( | |
960 | 'phases', 'publish') |
|
869 | 'phases', 'publish') | |
961 | assert phases_ui is None |
|
870 | assert phases_ui is None | |
962 | finally: |
|
871 | finally: | |
963 | self._cleanup_repo_settings(settings) |
|
872 | self._cleanup_repo_settings(settings) | |
964 |
|
873 | |||
965 | @pytest.mark.skip_backends('hg') |
|
874 | @pytest.mark.skip_backends('hg') | |
966 | def test_hg_settings_are_shown_only_for_hg_repository( |
|
875 | def test_hg_settings_are_shown_only_for_hg_repository( | |
967 | self, autologin_user, backend, csrf_token): |
|
876 | self, autologin_user, backend, csrf_token): | |
968 | repo_name = backend.repo_name |
|
877 | repo_name = backend.repo_name | |
969 | response = self.app.get( |
|
878 | response = self.app.get( | |
970 | url('repo_vcs_settings', repo_name=repo_name), status=200) |
|
879 | url('repo_vcs_settings', repo_name=repo_name), status=200) | |
971 | response.mustcontain(no='Mercurial Settings') |
|
880 | response.mustcontain(no='Mercurial Settings') | |
972 |
|
881 | |||
973 | @pytest.mark.skip_backends('hg') |
|
882 | @pytest.mark.skip_backends('hg') | |
974 | def test_hg_settings_are_updated_only_for_hg_repository( |
|
883 | def test_hg_settings_are_updated_only_for_hg_repository( | |
975 | self, autologin_user, backend, csrf_token): |
|
884 | self, autologin_user, backend, csrf_token): | |
976 | repo_name = backend.repo_name |
|
885 | repo_name = backend.repo_name | |
977 | settings = SettingsModel(repo=repo_name) |
|
886 | settings = SettingsModel(repo=repo_name) | |
978 | settings.create_ui_section_value( |
|
887 | settings.create_ui_section_value( | |
979 | 'extensions', '', key='largefiles', active=True) |
|
888 | 'extensions', '', key='largefiles', active=True) | |
980 | settings.create_ui_section_value( |
|
889 | settings.create_ui_section_value( | |
981 | 'phases', '1', key='publish', active=True) |
|
890 | 'phases', '1', key='publish', active=True) | |
982 |
|
891 | |||
983 | data = self.FORM_DATA.copy() |
|
892 | data = self.FORM_DATA.copy() | |
984 | data['csrf_token'] = csrf_token |
|
893 | data['csrf_token'] = csrf_token | |
985 | self.app.post( |
|
894 | self.app.post( | |
986 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
895 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
987 | try: |
|
896 | try: | |
988 | largefiles_ui = settings.get_ui_by_section_and_key( |
|
897 | largefiles_ui = settings.get_ui_by_section_and_key( | |
989 | 'extensions', 'largefiles') |
|
898 | 'extensions', 'largefiles') | |
990 | assert largefiles_ui.ui_active is True |
|
899 | assert largefiles_ui.ui_active is True | |
991 | phases_ui = settings.get_ui_by_section_and_key( |
|
900 | phases_ui = settings.get_ui_by_section_and_key( | |
992 | 'phases', 'publish') |
|
901 | 'phases', 'publish') | |
993 | assert phases_ui.ui_value == '1' |
|
902 | assert phases_ui.ui_value == '1' | |
994 | finally: |
|
903 | finally: | |
995 | self._cleanup_repo_settings(settings) |
|
904 | self._cleanup_repo_settings(settings) | |
996 |
|
905 | |||
997 | def test_per_repo_svn_settings_are_displayed( |
|
906 | def test_per_repo_svn_settings_are_displayed( | |
998 | self, autologin_user, backend_svn, settings_util): |
|
907 | self, autologin_user, backend_svn, settings_util): | |
999 | repo = backend_svn.create_repo() |
|
908 | repo = backend_svn.create_repo() | |
1000 | repo_name = repo.repo_name |
|
909 | repo_name = repo.repo_name | |
1001 | branches = [ |
|
910 | branches = [ | |
1002 | settings_util.create_repo_rhodecode_ui( |
|
911 | settings_util.create_repo_rhodecode_ui( | |
1003 | repo, VcsSettingsModel.SVN_BRANCH_SECTION, |
|
912 | repo, VcsSettingsModel.SVN_BRANCH_SECTION, | |
1004 | 'branch_{}'.format(i)) |
|
913 | 'branch_{}'.format(i)) | |
1005 | for i in range(10)] |
|
914 | for i in range(10)] | |
1006 | tags = [ |
|
915 | tags = [ | |
1007 | settings_util.create_repo_rhodecode_ui( |
|
916 | settings_util.create_repo_rhodecode_ui( | |
1008 | repo, VcsSettingsModel.SVN_TAG_SECTION, 'tag_{}'.format(i)) |
|
917 | repo, VcsSettingsModel.SVN_TAG_SECTION, 'tag_{}'.format(i)) | |
1009 | for i in range(10)] |
|
918 | for i in range(10)] | |
1010 |
|
919 | |||
1011 | response = self.app.get( |
|
920 | response = self.app.get( | |
1012 | url('repo_vcs_settings', repo_name=repo_name), status=200) |
|
921 | url('repo_vcs_settings', repo_name=repo_name), status=200) | |
1013 | assert_response = AssertResponse(response) |
|
922 | assert_response = AssertResponse(response) | |
1014 | for branch in branches: |
|
923 | for branch in branches: | |
1015 | css_selector = '[name=branch_value_{}]'.format(branch.ui_id) |
|
924 | css_selector = '[name=branch_value_{}]'.format(branch.ui_id) | |
1016 | element = assert_response.get_element(css_selector) |
|
925 | element = assert_response.get_element(css_selector) | |
1017 | assert element.value == branch.ui_value |
|
926 | assert element.value == branch.ui_value | |
1018 | for tag in tags: |
|
927 | for tag in tags: | |
1019 | css_selector = '[name=tag_ui_value_new_{}]'.format(tag.ui_id) |
|
928 | css_selector = '[name=tag_ui_value_new_{}]'.format(tag.ui_id) | |
1020 | element = assert_response.get_element(css_selector) |
|
929 | element = assert_response.get_element(css_selector) | |
1021 | assert element.value == tag.ui_value |
|
930 | assert element.value == tag.ui_value | |
1022 |
|
931 | |||
1023 | def test_per_repo_hg_and_pr_settings_are_not_displayed_for_svn( |
|
932 | def test_per_repo_hg_and_pr_settings_are_not_displayed_for_svn( | |
1024 | self, autologin_user, backend_svn, settings_util): |
|
933 | self, autologin_user, backend_svn, settings_util): | |
1025 | repo = backend_svn.create_repo() |
|
934 | repo = backend_svn.create_repo() | |
1026 | repo_name = repo.repo_name |
|
935 | repo_name = repo.repo_name | |
1027 | response = self.app.get( |
|
936 | response = self.app.get( | |
1028 | url('repo_vcs_settings', repo_name=repo_name), status=200) |
|
937 | url('repo_vcs_settings', repo_name=repo_name), status=200) | |
1029 | response.mustcontain(no='<label>Hooks:</label>') |
|
938 | response.mustcontain(no='<label>Hooks:</label>') | |
1030 | response.mustcontain(no='<label>Pull Request Settings:</label>') |
|
939 | response.mustcontain(no='<label>Pull Request Settings:</label>') | |
1031 |
|
940 | |||
1032 | def test_inherit_global_settings_value_is_saved( |
|
941 | def test_inherit_global_settings_value_is_saved( | |
1033 | self, autologin_user, backend, csrf_token): |
|
942 | self, autologin_user, backend, csrf_token): | |
1034 | repo_name = backend.repo_name |
|
943 | repo_name = backend.repo_name | |
1035 | data = self.FORM_DATA.copy() |
|
944 | data = self.FORM_DATA.copy() | |
1036 | data['csrf_token'] = csrf_token |
|
945 | data['csrf_token'] = csrf_token | |
1037 | data['inherit_global_settings'] = True |
|
946 | data['inherit_global_settings'] = True | |
1038 | self.app.post( |
|
947 | self.app.post( | |
1039 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
948 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
1040 |
|
949 | |||
1041 | settings = SettingsModel(repo=repo_name) |
|
950 | settings = SettingsModel(repo=repo_name) | |
1042 | vcs_settings = VcsSettingsModel(repo=repo_name) |
|
951 | vcs_settings = VcsSettingsModel(repo=repo_name) | |
1043 | try: |
|
952 | try: | |
1044 | assert vcs_settings.inherit_global_settings is True |
|
953 | assert vcs_settings.inherit_global_settings is True | |
1045 | finally: |
|
954 | finally: | |
1046 | self._cleanup_repo_settings(settings) |
|
955 | self._cleanup_repo_settings(settings) | |
1047 |
|
956 | |||
1048 | def test_repo_cache_is_invalidated_when_settings_are_updated( |
|
957 | def test_repo_cache_is_invalidated_when_settings_are_updated( | |
1049 | self, autologin_user, backend, csrf_token): |
|
958 | self, autologin_user, backend, csrf_token): | |
1050 | repo_name = backend.repo_name |
|
959 | repo_name = backend.repo_name | |
1051 | data = self.FORM_DATA.copy() |
|
960 | data = self.FORM_DATA.copy() | |
1052 | data['csrf_token'] = csrf_token |
|
961 | data['csrf_token'] = csrf_token | |
1053 | data['inherit_global_settings'] = True |
|
962 | data['inherit_global_settings'] = True | |
1054 | settings = SettingsModel(repo=repo_name) |
|
963 | settings = SettingsModel(repo=repo_name) | |
1055 |
|
964 | |||
1056 | invalidation_patcher = mock.patch( |
|
965 | invalidation_patcher = mock.patch( | |
1057 | 'rhodecode.controllers.admin.repos.ScmModel.mark_for_invalidation') |
|
966 | 'rhodecode.controllers.admin.repos.ScmModel.mark_for_invalidation') | |
1058 | with invalidation_patcher as invalidation_mock: |
|
967 | with invalidation_patcher as invalidation_mock: | |
1059 | self.app.post( |
|
968 | self.app.post( | |
1060 | url('repo_vcs_settings', repo_name=repo_name), data, |
|
969 | url('repo_vcs_settings', repo_name=repo_name), data, | |
1061 | status=302) |
|
970 | status=302) | |
1062 | try: |
|
971 | try: | |
1063 | invalidation_mock.assert_called_once_with(repo_name, delete=True) |
|
972 | invalidation_mock.assert_called_once_with(repo_name, delete=True) | |
1064 | finally: |
|
973 | finally: | |
1065 | self._cleanup_repo_settings(settings) |
|
974 | self._cleanup_repo_settings(settings) | |
1066 |
|
975 | |||
1067 | def test_other_settings_not_saved_inherit_global_settings_is_true( |
|
976 | def test_other_settings_not_saved_inherit_global_settings_is_true( | |
1068 | self, autologin_user, backend, csrf_token): |
|
977 | self, autologin_user, backend, csrf_token): | |
1069 | repo_name = backend.repo_name |
|
978 | repo_name = backend.repo_name | |
1070 | data = self.FORM_DATA.copy() |
|
979 | data = self.FORM_DATA.copy() | |
1071 | data['csrf_token'] = csrf_token |
|
980 | data['csrf_token'] = csrf_token | |
1072 | data['inherit_global_settings'] = True |
|
981 | data['inherit_global_settings'] = True | |
1073 | self.app.post( |
|
982 | self.app.post( | |
1074 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) |
|
983 | url('repo_vcs_settings', repo_name=repo_name), data, status=302) | |
1075 |
|
984 | |||
1076 | settings = SettingsModel(repo=repo_name) |
|
985 | settings = SettingsModel(repo=repo_name) | |
1077 | ui_settings = ( |
|
986 | ui_settings = ( | |
1078 | VcsSettingsModel.HOOKS_SETTINGS + VcsSettingsModel.HG_SETTINGS) |
|
987 | VcsSettingsModel.HOOKS_SETTINGS + VcsSettingsModel.HG_SETTINGS) | |
1079 |
|
988 | |||
1080 | vcs_settings = [] |
|
989 | vcs_settings = [] | |
1081 | try: |
|
990 | try: | |
1082 | for section, key in ui_settings: |
|
991 | for section, key in ui_settings: | |
1083 | ui = settings.get_ui_by_section_and_key(section, key) |
|
992 | ui = settings.get_ui_by_section_and_key(section, key) | |
1084 | if ui: |
|
993 | if ui: | |
1085 | vcs_settings.append(ui) |
|
994 | vcs_settings.append(ui) | |
1086 | vcs_settings.extend(settings.get_ui_by_section( |
|
995 | vcs_settings.extend(settings.get_ui_by_section( | |
1087 | VcsSettingsModel.SVN_BRANCH_SECTION)) |
|
996 | VcsSettingsModel.SVN_BRANCH_SECTION)) | |
1088 | vcs_settings.extend(settings.get_ui_by_section( |
|
997 | vcs_settings.extend(settings.get_ui_by_section( | |
1089 | VcsSettingsModel.SVN_TAG_SECTION)) |
|
998 | VcsSettingsModel.SVN_TAG_SECTION)) | |
1090 | for name in VcsSettingsModel.GENERAL_SETTINGS: |
|
999 | for name in VcsSettingsModel.GENERAL_SETTINGS: | |
1091 | setting = settings.get_setting_by_name(name) |
|
1000 | setting = settings.get_setting_by_name(name) | |
1092 | if setting: |
|
1001 | if setting: | |
1093 | vcs_settings.append(setting) |
|
1002 | vcs_settings.append(setting) | |
1094 | assert vcs_settings == [] |
|
1003 | assert vcs_settings == [] | |
1095 | finally: |
|
1004 | finally: | |
1096 | self._cleanup_repo_settings(settings) |
|
1005 | self._cleanup_repo_settings(settings) | |
1097 |
|
1006 | |||
1098 | def test_delete_svn_branch_and_tag_patterns( |
|
1007 | def test_delete_svn_branch_and_tag_patterns( | |
1099 | self, autologin_user, backend_svn, settings_util, csrf_token): |
|
1008 | self, autologin_user, backend_svn, settings_util, csrf_token): | |
1100 | repo = backend_svn.create_repo() |
|
1009 | repo = backend_svn.create_repo() | |
1101 | repo_name = repo.repo_name |
|
1010 | repo_name = repo.repo_name | |
1102 | branch = settings_util.create_repo_rhodecode_ui( |
|
1011 | branch = settings_util.create_repo_rhodecode_ui( | |
1103 | repo, VcsSettingsModel.SVN_BRANCH_SECTION, 'test_branch', |
|
1012 | repo, VcsSettingsModel.SVN_BRANCH_SECTION, 'test_branch', | |
1104 | cleanup=False) |
|
1013 | cleanup=False) | |
1105 | tag = settings_util.create_repo_rhodecode_ui( |
|
1014 | tag = settings_util.create_repo_rhodecode_ui( | |
1106 | repo, VcsSettingsModel.SVN_TAG_SECTION, 'test_tag', cleanup=False) |
|
1015 | repo, VcsSettingsModel.SVN_TAG_SECTION, 'test_tag', cleanup=False) | |
1107 | data = { |
|
1016 | data = { | |
1108 | '_method': 'delete', |
|
1017 | '_method': 'delete', | |
1109 | 'csrf_token': csrf_token |
|
1018 | 'csrf_token': csrf_token | |
1110 | } |
|
1019 | } | |
1111 | for id_ in (branch.ui_id, tag.ui_id): |
|
1020 | for id_ in (branch.ui_id, tag.ui_id): | |
1112 | data['delete_svn_pattern'] = id_, |
|
1021 | data['delete_svn_pattern'] = id_, | |
1113 | self.app.post( |
|
1022 | self.app.post( | |
1114 | url('repo_vcs_settings', repo_name=repo_name), data, |
|
1023 | url('repo_vcs_settings', repo_name=repo_name), data, | |
1115 | headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200) |
|
1024 | headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200) | |
1116 | settings = VcsSettingsModel(repo=repo_name) |
|
1025 | settings = VcsSettingsModel(repo=repo_name) | |
1117 | assert settings.get_repo_svn_branch_patterns() == [] |
|
1026 | assert settings.get_repo_svn_branch_patterns() == [] | |
1118 |
|
1027 | |||
1119 | def test_delete_svn_branch_requires_repo_admin_permission( |
|
1028 | def test_delete_svn_branch_requires_repo_admin_permission( | |
1120 | self, backend_svn, user_util, settings_util, csrf_token): |
|
1029 | self, backend_svn, user_util, settings_util, csrf_token): | |
1121 | repo = backend_svn.create_repo() |
|
1030 | repo = backend_svn.create_repo() | |
1122 | repo_name = repo.repo_name |
|
1031 | repo_name = repo.repo_name | |
1123 |
|
1032 | |||
1124 | logout_user_session(self.app, csrf_token) |
|
1033 | logout_user_session(self.app, csrf_token) | |
1125 | session = login_user_session( |
|
1034 | session = login_user_session( | |
1126 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) |
|
1035 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) | |
1127 | csrf_token = auth.get_csrf_token(session) |
|
1036 | csrf_token = auth.get_csrf_token(session) | |
1128 |
|
1037 | |||
1129 | repo = Repository.get_by_repo_name(repo_name) |
|
1038 | repo = Repository.get_by_repo_name(repo_name) | |
1130 | user = UserModel().get_by_username(TEST_USER_REGULAR_LOGIN) |
|
1039 | user = UserModel().get_by_username(TEST_USER_REGULAR_LOGIN) | |
1131 | user_util.grant_user_permission_to_repo(repo, user, 'repository.admin') |
|
1040 | user_util.grant_user_permission_to_repo(repo, user, 'repository.admin') | |
1132 | branch = settings_util.create_repo_rhodecode_ui( |
|
1041 | branch = settings_util.create_repo_rhodecode_ui( | |
1133 | repo, VcsSettingsModel.SVN_BRANCH_SECTION, 'test_branch', |
|
1042 | repo, VcsSettingsModel.SVN_BRANCH_SECTION, 'test_branch', | |
1134 | cleanup=False) |
|
1043 | cleanup=False) | |
1135 | data = { |
|
1044 | data = { | |
1136 | '_method': 'delete', |
|
1045 | '_method': 'delete', | |
1137 | 'csrf_token': csrf_token, |
|
1046 | 'csrf_token': csrf_token, | |
1138 | 'delete_svn_pattern': branch.ui_id |
|
1047 | 'delete_svn_pattern': branch.ui_id | |
1139 | } |
|
1048 | } | |
1140 | self.app.post( |
|
1049 | self.app.post( | |
1141 | url('repo_vcs_settings', repo_name=repo_name), data, |
|
1050 | url('repo_vcs_settings', repo_name=repo_name), data, | |
1142 | headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200) |
|
1051 | headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200) | |
1143 |
|
1052 | |||
1144 | def test_delete_svn_branch_raises_400_when_not_found( |
|
1053 | def test_delete_svn_branch_raises_400_when_not_found( | |
1145 | self, autologin_user, backend_svn, settings_util, csrf_token): |
|
1054 | self, autologin_user, backend_svn, settings_util, csrf_token): | |
1146 | repo_name = backend_svn.repo_name |
|
1055 | repo_name = backend_svn.repo_name | |
1147 | data = { |
|
1056 | data = { | |
1148 | '_method': 'delete', |
|
1057 | '_method': 'delete', | |
1149 | 'delete_svn_pattern': 123, |
|
1058 | 'delete_svn_pattern': 123, | |
1150 | 'csrf_token': csrf_token |
|
1059 | 'csrf_token': csrf_token | |
1151 | } |
|
1060 | } | |
1152 | self.app.post( |
|
1061 | self.app.post( | |
1153 | url('repo_vcs_settings', repo_name=repo_name), data, |
|
1062 | url('repo_vcs_settings', repo_name=repo_name), data, | |
1154 | headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=400) |
|
1063 | headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=400) | |
1155 |
|
1064 | |||
1156 | def test_delete_svn_branch_raises_400_when_no_id_specified( |
|
1065 | def test_delete_svn_branch_raises_400_when_no_id_specified( | |
1157 | self, autologin_user, backend_svn, settings_util, csrf_token): |
|
1066 | self, autologin_user, backend_svn, settings_util, csrf_token): | |
1158 | repo_name = backend_svn.repo_name |
|
1067 | repo_name = backend_svn.repo_name | |
1159 | data = { |
|
1068 | data = { | |
1160 | '_method': 'delete', |
|
1069 | '_method': 'delete', | |
1161 | 'csrf_token': csrf_token |
|
1070 | 'csrf_token': csrf_token | |
1162 | } |
|
1071 | } | |
1163 | self.app.post( |
|
1072 | self.app.post( | |
1164 | url('repo_vcs_settings', repo_name=repo_name), data, |
|
1073 | url('repo_vcs_settings', repo_name=repo_name), data, | |
1165 | headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=400) |
|
1074 | headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=400) | |
1166 |
|
1075 | |||
1167 | def _cleanup_repo_settings(self, settings_model): |
|
1076 | def _cleanup_repo_settings(self, settings_model): | |
1168 | cleanup = [] |
|
1077 | cleanup = [] | |
1169 | ui_settings = ( |
|
1078 | ui_settings = ( | |
1170 | VcsSettingsModel.HOOKS_SETTINGS + VcsSettingsModel.HG_SETTINGS) |
|
1079 | VcsSettingsModel.HOOKS_SETTINGS + VcsSettingsModel.HG_SETTINGS) | |
1171 |
|
1080 | |||
1172 | for section, key in ui_settings: |
|
1081 | for section, key in ui_settings: | |
1173 | ui = settings_model.get_ui_by_section_and_key(section, key) |
|
1082 | ui = settings_model.get_ui_by_section_and_key(section, key) | |
1174 | if ui: |
|
1083 | if ui: | |
1175 | cleanup.append(ui) |
|
1084 | cleanup.append(ui) | |
1176 |
|
1085 | |||
1177 | cleanup.extend(settings_model.get_ui_by_section( |
|
1086 | cleanup.extend(settings_model.get_ui_by_section( | |
1178 | VcsSettingsModel.INHERIT_SETTINGS)) |
|
1087 | VcsSettingsModel.INHERIT_SETTINGS)) | |
1179 | cleanup.extend(settings_model.get_ui_by_section( |
|
1088 | cleanup.extend(settings_model.get_ui_by_section( | |
1180 | VcsSettingsModel.SVN_BRANCH_SECTION)) |
|
1089 | VcsSettingsModel.SVN_BRANCH_SECTION)) | |
1181 | cleanup.extend(settings_model.get_ui_by_section( |
|
1090 | cleanup.extend(settings_model.get_ui_by_section( | |
1182 | VcsSettingsModel.SVN_TAG_SECTION)) |
|
1091 | VcsSettingsModel.SVN_TAG_SECTION)) | |
1183 |
|
1092 | |||
1184 | for name in VcsSettingsModel.GENERAL_SETTINGS: |
|
1093 | for name in VcsSettingsModel.GENERAL_SETTINGS: | |
1185 | setting = settings_model.get_setting_by_name(name) |
|
1094 | setting = settings_model.get_setting_by_name(name) | |
1186 | if setting: |
|
1095 | if setting: | |
1187 | cleanup.append(setting) |
|
1096 | cleanup.append(setting) | |
1188 |
|
1097 | |||
1189 | for object_ in cleanup: |
|
1098 | for object_ in cleanup: | |
1190 | Session().delete(object_) |
|
1099 | Session().delete(object_) | |
1191 | Session().commit() |
|
1100 | Session().commit() | |
1192 |
|
1101 | |||
1193 | def assert_repo_value_equals_global_value(self, response, setting): |
|
1102 | def assert_repo_value_equals_global_value(self, response, setting): | |
1194 | assert_response = AssertResponse(response) |
|
1103 | assert_response = AssertResponse(response) | |
1195 | global_css_selector = '[name={}_inherited]'.format(setting) |
|
1104 | global_css_selector = '[name={}_inherited]'.format(setting) | |
1196 | repo_css_selector = '[name={}]'.format(setting) |
|
1105 | repo_css_selector = '[name={}]'.format(setting) | |
1197 | repo_element = assert_response.get_element(repo_css_selector) |
|
1106 | repo_element = assert_response.get_element(repo_css_selector) | |
1198 | global_element = assert_response.get_element(global_css_selector) |
|
1107 | global_element = assert_response.get_element(global_css_selector) | |
1199 | assert repo_element.value == global_element.value |
|
1108 | assert repo_element.value == global_element.value | |
1200 |
|
1109 | |||
1201 |
|
1110 | |||
1202 | def _get_permission_for_user(user, repo): |
|
1111 | def _get_permission_for_user(user, repo): | |
1203 | perm = UserRepoToPerm.query()\ |
|
1112 | perm = UserRepoToPerm.query()\ | |
1204 | .filter(UserRepoToPerm.repository == |
|
1113 | .filter(UserRepoToPerm.repository == | |
1205 | Repository.get_by_repo_name(repo))\ |
|
1114 | Repository.get_by_repo_name(repo))\ | |
1206 | .filter(UserRepoToPerm.user == User.get_by_username(user))\ |
|
1115 | .filter(UserRepoToPerm.user == User.get_by_username(user))\ | |
1207 | .all() |
|
1116 | .all() | |
1208 | return perm |
|
1117 | return perm |
@@ -1,274 +1,272 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 |
|
2 | |||
3 | # Copyright (C) 2010-2017 RhodeCode GmbH |
|
3 | # Copyright (C) 2010-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 pytest |
|
21 | import pytest | |
22 |
|
22 | |||
23 | from rhodecode.tests import * |
|
23 | from rhodecode.tests import * | |
24 | from rhodecode.tests.fixture import Fixture |
|
24 | from rhodecode.tests.fixture import Fixture | |
25 |
|
25 | |||
26 | from rhodecode.model.db import Repository |
|
26 | from rhodecode.model.db import Repository | |
27 | from rhodecode.model.repo import RepoModel |
|
27 | from rhodecode.model.repo import RepoModel | |
28 | from rhodecode.model.user import UserModel |
|
28 | from rhodecode.model.user import UserModel | |
29 | from rhodecode.model.meta import Session |
|
29 | from rhodecode.model.meta import Session | |
30 |
|
30 | |||
31 | fixture = Fixture() |
|
31 | fixture = Fixture() | |
32 |
|
32 | |||
33 |
|
33 | |||
34 | class _BaseTest(TestController): |
|
34 | class _BaseTest(TestController): | |
35 |
|
35 | |||
36 | REPO = None |
|
36 | REPO = None | |
37 | REPO_TYPE = None |
|
37 | REPO_TYPE = None | |
38 | NEW_REPO = None |
|
38 | NEW_REPO = None | |
39 | REPO_FORK = None |
|
39 | REPO_FORK = None | |
40 |
|
40 | |||
41 | @pytest.fixture(autouse=True) |
|
41 | @pytest.fixture(autouse=True) | |
42 | def prepare(self, request, pylonsapp): |
|
42 | def prepare(self, request, pylonsapp): | |
43 | self.username = u'forkuser' |
|
43 | self.username = u'forkuser' | |
44 | self.password = u'qweqwe' |
|
44 | self.password = u'qweqwe' | |
45 | self.u1 = fixture.create_user(self.username, password=self.password, |
|
45 | self.u1 = fixture.create_user(self.username, password=self.password, | |
46 | email=u'fork_king@rhodecode.org') |
|
46 | email=u'fork_king@rhodecode.org') | |
47 | Session().commit() |
|
47 | Session().commit() | |
48 | self.u1id = self.u1.user_id |
|
48 | self.u1id = self.u1.user_id | |
49 | request.addfinalizer(self.cleanup) |
|
49 | request.addfinalizer(self.cleanup) | |
50 |
|
50 | |||
51 | def cleanup(self): |
|
51 | def cleanup(self): | |
52 | u1 = UserModel().get(self.u1id) |
|
52 | u1 = UserModel().get(self.u1id) | |
53 | Session().delete(u1) |
|
53 | Session().delete(u1) | |
54 | Session().commit() |
|
54 | Session().commit() | |
55 |
|
55 | |||
56 | def test_index(self): |
|
56 | def test_index(self): | |
57 | self.log_user() |
|
57 | self.log_user() | |
58 | repo_name = self.REPO |
|
58 | repo_name = self.REPO | |
59 | response = self.app.get(url(controller='forks', action='forks', |
|
59 | response = self.app.get(url(controller='forks', action='forks', | |
60 | repo_name=repo_name)) |
|
60 | repo_name=repo_name)) | |
61 |
|
61 | |||
62 | response.mustcontain("""There are no forks yet""") |
|
62 | response.mustcontain("""There are no forks yet""") | |
63 |
|
63 | |||
64 | def test_no_permissions_to_fork(self): |
|
64 | def test_no_permissions_to_fork(self): | |
65 | usr = self.log_user(TEST_USER_REGULAR_LOGIN, |
|
65 | usr = self.log_user(TEST_USER_REGULAR_LOGIN, | |
66 | TEST_USER_REGULAR_PASS)['user_id'] |
|
66 | TEST_USER_REGULAR_PASS)['user_id'] | |
67 | user_model = UserModel() |
|
67 | user_model = UserModel() | |
68 | user_model.revoke_perm(usr, 'hg.fork.repository') |
|
68 | user_model.revoke_perm(usr, 'hg.fork.repository') | |
69 | user_model.grant_perm(usr, 'hg.fork.none') |
|
69 | user_model.grant_perm(usr, 'hg.fork.none') | |
70 | u = UserModel().get(usr) |
|
70 | u = UserModel().get(usr) | |
71 | u.inherit_default_permissions = False |
|
71 | u.inherit_default_permissions = False | |
72 | Session().commit() |
|
72 | Session().commit() | |
73 | # try create a fork |
|
73 | # try create a fork | |
74 | repo_name = self.REPO |
|
74 | repo_name = self.REPO | |
75 | self.app.post( |
|
75 | self.app.post( | |
76 | url(controller='forks', action='fork_create', repo_name=repo_name), |
|
76 | url(controller='forks', action='fork_create', repo_name=repo_name), | |
77 | {'csrf_token': self.csrf_token}, status=403) |
|
77 | {'csrf_token': self.csrf_token}, status=403) | |
78 |
|
78 | |||
79 | def test_index_with_fork(self): |
|
79 | def test_index_with_fork(self): | |
80 | self.log_user() |
|
80 | self.log_user() | |
81 |
|
81 | |||
82 | # create a fork |
|
82 | # create a fork | |
83 | fork_name = self.REPO_FORK |
|
83 | fork_name = self.REPO_FORK | |
84 | description = 'fork of vcs test' |
|
84 | description = 'fork of vcs test' | |
85 | repo_name = self.REPO |
|
85 | repo_name = self.REPO | |
86 | source_repo = Repository.get_by_repo_name(repo_name) |
|
86 | source_repo = Repository.get_by_repo_name(repo_name) | |
87 | creation_args = { |
|
87 | creation_args = { | |
88 | 'repo_name': fork_name, |
|
88 | 'repo_name': fork_name, | |
89 | 'repo_group': '', |
|
89 | 'repo_group': '', | |
90 | 'fork_parent_id': source_repo.repo_id, |
|
90 | 'fork_parent_id': source_repo.repo_id, | |
91 | 'repo_type': self.REPO_TYPE, |
|
91 | 'repo_type': self.REPO_TYPE, | |
92 | 'description': description, |
|
92 | 'description': description, | |
93 | 'private': 'False', |
|
93 | 'private': 'False', | |
94 | 'landing_rev': 'rev:tip', |
|
94 | 'landing_rev': 'rev:tip', | |
95 | 'csrf_token': self.csrf_token, |
|
95 | 'csrf_token': self.csrf_token, | |
96 | } |
|
96 | } | |
97 |
|
97 | |||
98 | self.app.post(url(controller='forks', action='fork_create', |
|
98 | self.app.post(url(controller='forks', action='fork_create', | |
99 | repo_name=repo_name), creation_args) |
|
99 | repo_name=repo_name), creation_args) | |
100 |
|
100 | |||
101 | response = self.app.get(url(controller='forks', action='forks', |
|
101 | response = self.app.get(url(controller='forks', action='forks', | |
102 | repo_name=repo_name)) |
|
102 | repo_name=repo_name)) | |
103 |
|
103 | |||
104 | response.mustcontain( |
|
104 | response.mustcontain( | |
105 | """<a href="/%s">%s</a>""" % (fork_name, fork_name) |
|
105 | """<a href="/%s">%s</a>""" % (fork_name, fork_name) | |
106 | ) |
|
106 | ) | |
107 |
|
107 | |||
108 | # remove this fork |
|
108 | # remove this fork | |
109 | response = self.app.post( |
|
109 | fixture.destroy_repo(fork_name) | |
110 | url('repo', repo_name=fork_name), |
|
|||
111 | params={'_method': 'delete', 'csrf_token': self.csrf_token}) |
|
|||
112 |
|
110 | |||
113 | def test_fork_create_into_group(self): |
|
111 | def test_fork_create_into_group(self): | |
114 | self.log_user() |
|
112 | self.log_user() | |
115 | group = fixture.create_repo_group('vc') |
|
113 | group = fixture.create_repo_group('vc') | |
116 | group_id = group.group_id |
|
114 | group_id = group.group_id | |
117 | fork_name = self.REPO_FORK |
|
115 | fork_name = self.REPO_FORK | |
118 | fork_name_full = 'vc/%s' % fork_name |
|
116 | fork_name_full = 'vc/%s' % fork_name | |
119 | description = 'fork of vcs test' |
|
117 | description = 'fork of vcs test' | |
120 | repo_name = self.REPO |
|
118 | repo_name = self.REPO | |
121 | source_repo = Repository.get_by_repo_name(repo_name) |
|
119 | source_repo = Repository.get_by_repo_name(repo_name) | |
122 | creation_args = { |
|
120 | creation_args = { | |
123 | 'repo_name': fork_name, |
|
121 | 'repo_name': fork_name, | |
124 | 'repo_group': group_id, |
|
122 | 'repo_group': group_id, | |
125 | 'fork_parent_id': source_repo.repo_id, |
|
123 | 'fork_parent_id': source_repo.repo_id, | |
126 | 'repo_type': self.REPO_TYPE, |
|
124 | 'repo_type': self.REPO_TYPE, | |
127 | 'description': description, |
|
125 | 'description': description, | |
128 | 'private': 'False', |
|
126 | 'private': 'False', | |
129 | 'landing_rev': 'rev:tip', |
|
127 | 'landing_rev': 'rev:tip', | |
130 | 'csrf_token': self.csrf_token, |
|
128 | 'csrf_token': self.csrf_token, | |
131 | } |
|
129 | } | |
132 | self.app.post(url(controller='forks', action='fork_create', |
|
130 | self.app.post(url(controller='forks', action='fork_create', | |
133 | repo_name=repo_name), creation_args) |
|
131 | repo_name=repo_name), creation_args) | |
134 | repo = Repository.get_by_repo_name(fork_name_full) |
|
132 | repo = Repository.get_by_repo_name(fork_name_full) | |
135 | assert repo.fork.repo_name == self.REPO |
|
133 | assert repo.fork.repo_name == self.REPO | |
136 |
|
134 | |||
137 | # run the check page that triggers the flash message |
|
135 | # run the check page that triggers the flash message | |
138 | response = self.app.get(url('repo_check_home', repo_name=fork_name_full)) |
|
136 | response = self.app.get(url('repo_check_home', repo_name=fork_name_full)) | |
139 | # test if we have a message that fork is ok |
|
137 | # test if we have a message that fork is ok | |
140 | assert_session_flash(response, |
|
138 | assert_session_flash(response, | |
141 | 'Forked repository %s as <a href="/%s">%s</a>' |
|
139 | 'Forked repository %s as <a href="/%s">%s</a>' | |
142 | % (repo_name, fork_name_full, fork_name_full)) |
|
140 | % (repo_name, fork_name_full, fork_name_full)) | |
143 |
|
141 | |||
144 | # test if the fork was created in the database |
|
142 | # test if the fork was created in the database | |
145 | fork_repo = Session().query(Repository)\ |
|
143 | fork_repo = Session().query(Repository)\ | |
146 | .filter(Repository.repo_name == fork_name_full).one() |
|
144 | .filter(Repository.repo_name == fork_name_full).one() | |
147 |
|
145 | |||
148 | assert fork_repo.repo_name == fork_name_full |
|
146 | assert fork_repo.repo_name == fork_name_full | |
149 | assert fork_repo.fork.repo_name == repo_name |
|
147 | assert fork_repo.fork.repo_name == repo_name | |
150 |
|
148 | |||
151 | # test if the repository is visible in the list ? |
|
149 | # test if the repository is visible in the list ? | |
152 | response = self.app.get(url('summary_home', repo_name=fork_name_full)) |
|
150 | response = self.app.get(url('summary_home', repo_name=fork_name_full)) | |
153 | response.mustcontain(fork_name_full) |
|
151 | response.mustcontain(fork_name_full) | |
154 | response.mustcontain(self.REPO_TYPE) |
|
152 | response.mustcontain(self.REPO_TYPE) | |
155 |
|
153 | |||
156 | response.mustcontain('Fork of') |
|
154 | response.mustcontain('Fork of') | |
157 | response.mustcontain('<a href="/%s">%s</a>' % (repo_name, repo_name)) |
|
155 | response.mustcontain('<a href="/%s">%s</a>' % (repo_name, repo_name)) | |
158 |
|
156 | |||
159 | fixture.destroy_repo(fork_name_full) |
|
157 | fixture.destroy_repo(fork_name_full) | |
160 | fixture.destroy_repo_group(group_id) |
|
158 | fixture.destroy_repo_group(group_id) | |
161 |
|
159 | |||
162 | def test_z_fork_create(self): |
|
160 | def test_z_fork_create(self): | |
163 | self.log_user() |
|
161 | self.log_user() | |
164 | fork_name = self.REPO_FORK |
|
162 | fork_name = self.REPO_FORK | |
165 | description = 'fork of vcs test' |
|
163 | description = 'fork of vcs test' | |
166 | repo_name = self.REPO |
|
164 | repo_name = self.REPO | |
167 | source_repo = Repository.get_by_repo_name(repo_name) |
|
165 | source_repo = Repository.get_by_repo_name(repo_name) | |
168 | creation_args = { |
|
166 | creation_args = { | |
169 | 'repo_name': fork_name, |
|
167 | 'repo_name': fork_name, | |
170 | 'repo_group': '', |
|
168 | 'repo_group': '', | |
171 | 'fork_parent_id': source_repo.repo_id, |
|
169 | 'fork_parent_id': source_repo.repo_id, | |
172 | 'repo_type': self.REPO_TYPE, |
|
170 | 'repo_type': self.REPO_TYPE, | |
173 | 'description': description, |
|
171 | 'description': description, | |
174 | 'private': 'False', |
|
172 | 'private': 'False', | |
175 | 'landing_rev': 'rev:tip', |
|
173 | 'landing_rev': 'rev:tip', | |
176 | 'csrf_token': self.csrf_token, |
|
174 | 'csrf_token': self.csrf_token, | |
177 | } |
|
175 | } | |
178 | self.app.post(url(controller='forks', action='fork_create', |
|
176 | self.app.post(url(controller='forks', action='fork_create', | |
179 | repo_name=repo_name), creation_args) |
|
177 | repo_name=repo_name), creation_args) | |
180 | repo = Repository.get_by_repo_name(self.REPO_FORK) |
|
178 | repo = Repository.get_by_repo_name(self.REPO_FORK) | |
181 | assert repo.fork.repo_name == self.REPO |
|
179 | assert repo.fork.repo_name == self.REPO | |
182 |
|
180 | |||
183 | # run the check page that triggers the flash message |
|
181 | # run the check page that triggers the flash message | |
184 | response = self.app.get(url('repo_check_home', repo_name=fork_name)) |
|
182 | response = self.app.get(url('repo_check_home', repo_name=fork_name)) | |
185 | # test if we have a message that fork is ok |
|
183 | # test if we have a message that fork is ok | |
186 | assert_session_flash(response, |
|
184 | assert_session_flash(response, | |
187 | 'Forked repository %s as <a href="/%s">%s</a>' |
|
185 | 'Forked repository %s as <a href="/%s">%s</a>' | |
188 | % (repo_name, fork_name, fork_name)) |
|
186 | % (repo_name, fork_name, fork_name)) | |
189 |
|
187 | |||
190 | # test if the fork was created in the database |
|
188 | # test if the fork was created in the database | |
191 | fork_repo = Session().query(Repository)\ |
|
189 | fork_repo = Session().query(Repository)\ | |
192 | .filter(Repository.repo_name == fork_name).one() |
|
190 | .filter(Repository.repo_name == fork_name).one() | |
193 |
|
191 | |||
194 | assert fork_repo.repo_name == fork_name |
|
192 | assert fork_repo.repo_name == fork_name | |
195 | assert fork_repo.fork.repo_name == repo_name |
|
193 | assert fork_repo.fork.repo_name == repo_name | |
196 |
|
194 | |||
197 | # test if the repository is visible in the list ? |
|
195 | # test if the repository is visible in the list ? | |
198 | response = self.app.get(url('summary_home', repo_name=fork_name)) |
|
196 | response = self.app.get(url('summary_home', repo_name=fork_name)) | |
199 | response.mustcontain(fork_name) |
|
197 | response.mustcontain(fork_name) | |
200 | response.mustcontain(self.REPO_TYPE) |
|
198 | response.mustcontain(self.REPO_TYPE) | |
201 | response.mustcontain('Fork of') |
|
199 | response.mustcontain('Fork of') | |
202 | response.mustcontain('<a href="/%s">%s</a>' % (repo_name, repo_name)) |
|
200 | response.mustcontain('<a href="/%s">%s</a>' % (repo_name, repo_name)) | |
203 |
|
201 | |||
204 | def test_zz_fork_permission_page(self): |
|
202 | def test_zz_fork_permission_page(self): | |
205 | usr = self.log_user(self.username, self.password)['user_id'] |
|
203 | usr = self.log_user(self.username, self.password)['user_id'] | |
206 | repo_name = self.REPO |
|
204 | repo_name = self.REPO | |
207 |
|
205 | |||
208 | forks = Repository.query()\ |
|
206 | forks = Repository.query()\ | |
209 | .filter(Repository.repo_type == self.REPO_TYPE)\ |
|
207 | .filter(Repository.repo_type == self.REPO_TYPE)\ | |
210 | .filter(Repository.fork_id != None).all() |
|
208 | .filter(Repository.fork_id != None).all() | |
211 | assert 1 == len(forks) |
|
209 | assert 1 == len(forks) | |
212 |
|
210 | |||
213 | # set read permissions for this |
|
211 | # set read permissions for this | |
214 | RepoModel().grant_user_permission(repo=forks[0], |
|
212 | RepoModel().grant_user_permission(repo=forks[0], | |
215 | user=usr, |
|
213 | user=usr, | |
216 | perm='repository.read') |
|
214 | perm='repository.read') | |
217 | Session().commit() |
|
215 | Session().commit() | |
218 |
|
216 | |||
219 | response = self.app.get(url(controller='forks', action='forks', |
|
217 | response = self.app.get(url(controller='forks', action='forks', | |
220 | repo_name=repo_name)) |
|
218 | repo_name=repo_name)) | |
221 |
|
219 | |||
222 | response.mustcontain('fork of vcs test') |
|
220 | response.mustcontain('fork of vcs test') | |
223 |
|
221 | |||
224 | def test_zzz_fork_permission_page(self): |
|
222 | def test_zzz_fork_permission_page(self): | |
225 | usr = self.log_user(self.username, self.password)['user_id'] |
|
223 | usr = self.log_user(self.username, self.password)['user_id'] | |
226 | repo_name = self.REPO |
|
224 | repo_name = self.REPO | |
227 |
|
225 | |||
228 | forks = Repository.query()\ |
|
226 | forks = Repository.query()\ | |
229 | .filter(Repository.repo_type == self.REPO_TYPE)\ |
|
227 | .filter(Repository.repo_type == self.REPO_TYPE)\ | |
230 | .filter(Repository.fork_id != None).all() |
|
228 | .filter(Repository.fork_id != None).all() | |
231 | assert 1 == len(forks) |
|
229 | assert 1 == len(forks) | |
232 |
|
230 | |||
233 | # set none |
|
231 | # set none | |
234 | RepoModel().grant_user_permission(repo=forks[0], |
|
232 | RepoModel().grant_user_permission(repo=forks[0], | |
235 | user=usr, perm='repository.none') |
|
233 | user=usr, perm='repository.none') | |
236 | Session().commit() |
|
234 | Session().commit() | |
237 | # fork shouldn't be there |
|
235 | # fork shouldn't be there | |
238 | response = self.app.get(url(controller='forks', action='forks', |
|
236 | response = self.app.get(url(controller='forks', action='forks', | |
239 | repo_name=repo_name)) |
|
237 | repo_name=repo_name)) | |
240 | response.mustcontain('There are no forks yet') |
|
238 | response.mustcontain('There are no forks yet') | |
241 |
|
239 | |||
242 |
|
240 | |||
243 | class TestGIT(_BaseTest): |
|
241 | class TestGIT(_BaseTest): | |
244 | REPO = GIT_REPO |
|
242 | REPO = GIT_REPO | |
245 | NEW_REPO = NEW_GIT_REPO |
|
243 | NEW_REPO = NEW_GIT_REPO | |
246 | REPO_TYPE = 'git' |
|
244 | REPO_TYPE = 'git' | |
247 | REPO_FORK = GIT_FORK |
|
245 | REPO_FORK = GIT_FORK | |
248 |
|
246 | |||
249 |
|
247 | |||
250 | class TestHG(_BaseTest): |
|
248 | class TestHG(_BaseTest): | |
251 | REPO = HG_REPO |
|
249 | REPO = HG_REPO | |
252 | NEW_REPO = NEW_HG_REPO |
|
250 | NEW_REPO = NEW_HG_REPO | |
253 | REPO_TYPE = 'hg' |
|
251 | REPO_TYPE = 'hg' | |
254 | REPO_FORK = HG_FORK |
|
252 | REPO_FORK = HG_FORK | |
255 |
|
253 | |||
256 |
|
254 | |||
257 | @pytest.mark.usefixtures('app', 'autologin_user') |
|
255 | @pytest.mark.usefixtures('app', 'autologin_user') | |
258 | @pytest.mark.skip_backends('git','hg') |
|
256 | @pytest.mark.skip_backends('git','hg') | |
259 | class TestSVNFork: |
|
257 | class TestSVNFork: | |
260 |
|
258 | |||
261 | def test_fork_redirects(self, backend): |
|
259 | def test_fork_redirects(self, backend): | |
262 | denied_actions = ['fork','fork_create'] |
|
260 | denied_actions = ['fork','fork_create'] | |
263 | for action in denied_actions: |
|
261 | for action in denied_actions: | |
264 | response = self.app.get(url( |
|
262 | response = self.app.get(url( | |
265 | controller='forks', action=action, |
|
263 | controller='forks', action=action, | |
266 | repo_name=backend.repo_name)) |
|
264 | repo_name=backend.repo_name)) | |
267 | assert response.status_int == 302 |
|
265 | assert response.status_int == 302 | |
268 |
|
266 | |||
269 | # Not allowed, redirect to the summary |
|
267 | # Not allowed, redirect to the summary | |
270 | redirected = response.follow() |
|
268 | redirected = response.follow() | |
271 | summary_url = url('summary_home', repo_name=backend.repo_name) |
|
269 | summary_url = url('summary_home', repo_name=backend.repo_name) | |
272 |
|
270 | |||
273 | # URL adds leading slash and path doesn't have it |
|
271 | # URL adds leading slash and path doesn't have it | |
274 | assert redirected.req.path == summary_url |
|
272 | assert redirected.req.path == summary_url |
General Comments 0
You need to be logged in to leave comments.
Login now