Show More
@@ -1,514 +1,512 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 |
|
2 | |||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
3 | # Copyright (C) 2010-2020 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.apps._base import ADMIN_PREFIX |
|
26 | from rhodecode.apps._base import ADMIN_PREFIX | |
27 | from rhodecode.lib import auth |
|
27 | from rhodecode.lib import auth | |
28 | from rhodecode.lib.utils2 import safe_str |
|
28 | from rhodecode.lib.utils2 import safe_str | |
29 | from rhodecode.lib import helpers as h |
|
29 | from rhodecode.lib import helpers as h | |
30 | from rhodecode.model.db import ( |
|
30 | from rhodecode.model.db import ( | |
31 | Repository, RepoGroup, UserRepoToPerm, User, Permission) |
|
31 | Repository, RepoGroup, UserRepoToPerm, User, Permission) | |
32 | from rhodecode.model.meta import Session |
|
32 | from rhodecode.model.meta import Session | |
33 | from rhodecode.model.repo import RepoModel |
|
33 | from rhodecode.model.repo import RepoModel | |
34 | from rhodecode.model.repo_group import RepoGroupModel |
|
34 | from rhodecode.model.repo_group import RepoGroupModel | |
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, assert_session_flash, TEST_USER_ADMIN_LOGIN, |
|
37 | login_user_session, assert_session_flash, TEST_USER_ADMIN_LOGIN, | |
38 | TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) |
|
38 | TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) | |
39 | from rhodecode.tests.fixture import Fixture, error_function |
|
39 | from rhodecode.tests.fixture import Fixture, error_function | |
40 | from rhodecode.tests.utils import AssertResponse, repo_on_filesystem |
|
40 | from rhodecode.tests.utils import AssertResponse, repo_on_filesystem | |
41 |
|
41 | |||
42 | fixture = Fixture() |
|
42 | fixture = Fixture() | |
43 |
|
43 | |||
44 |
|
44 | |||
45 | def route_path(name, params=None, **kwargs): |
|
45 | def route_path(name, params=None, **kwargs): | |
46 | import urllib |
|
46 | import urllib | |
47 |
|
47 | |||
48 | base_url = { |
|
48 | base_url = { | |
49 | 'repos': ADMIN_PREFIX + '/repos', |
|
49 | 'repos': ADMIN_PREFIX + '/repos', | |
50 | 'repos_data': ADMIN_PREFIX + '/repos_data', |
|
50 | 'repos_data': ADMIN_PREFIX + '/repos_data', | |
51 | 'repo_new': ADMIN_PREFIX + '/repos/new', |
|
51 | 'repo_new': ADMIN_PREFIX + '/repos/new', | |
52 | 'repo_create': ADMIN_PREFIX + '/repos/create', |
|
52 | 'repo_create': ADMIN_PREFIX + '/repos/create', | |
53 |
|
53 | |||
54 | 'repo_creating_check': '/{repo_name}/repo_creating_check', |
|
54 | 'repo_creating_check': '/{repo_name}/repo_creating_check', | |
55 | }[name].format(**kwargs) |
|
55 | }[name].format(**kwargs) | |
56 |
|
56 | |||
57 | if params: |
|
57 | if params: | |
58 | base_url = '{}?{}'.format(base_url, urllib.urlencode(params)) |
|
58 | base_url = '{}?{}'.format(base_url, urllib.urlencode(params)) | |
59 | return base_url |
|
59 | return base_url | |
60 |
|
60 | |||
61 |
|
61 | |||
62 | def _get_permission_for_user(user, repo): |
|
62 | def _get_permission_for_user(user, repo): | |
63 | perm = UserRepoToPerm.query()\ |
|
63 | perm = UserRepoToPerm.query()\ | |
64 | .filter(UserRepoToPerm.repository == |
|
64 | .filter(UserRepoToPerm.repository == | |
65 | Repository.get_by_repo_name(repo))\ |
|
65 | Repository.get_by_repo_name(repo))\ | |
66 | .filter(UserRepoToPerm.user == User.get_by_username(user))\ |
|
66 | .filter(UserRepoToPerm.user == User.get_by_username(user))\ | |
67 | .all() |
|
67 | .all() | |
68 | return perm |
|
68 | return perm | |
69 |
|
69 | |||
70 |
|
70 | |||
71 | @pytest.mark.usefixtures("app") |
|
71 | @pytest.mark.usefixtures("app") | |
72 | class TestAdminRepos(object): |
|
72 | class TestAdminRepos(object): | |
73 |
|
73 | |||
74 | def test_repo_list(self, autologin_user, user_util, xhr_header): |
|
74 | def test_repo_list(self, autologin_user, user_util, xhr_header): | |
75 | repo = user_util.create_repo() |
|
75 | repo = user_util.create_repo() | |
76 | repo_name = repo.repo_name |
|
76 | repo_name = repo.repo_name | |
77 | response = self.app.get( |
|
77 | response = self.app.get( | |
78 | route_path('repos_data'), status=200, |
|
78 | route_path('repos_data'), status=200, | |
79 | extra_environ=xhr_header) |
|
79 | extra_environ=xhr_header) | |
80 |
|
80 | |||
81 | response.mustcontain(repo_name) |
|
81 | response.mustcontain(repo_name) | |
82 |
|
82 | |||
83 | def test_create_page_restricted_to_single_backend(self, autologin_user, backend): |
|
83 | def test_create_page_restricted_to_single_backend(self, autologin_user, backend): | |
84 | with mock.patch('rhodecode.BACKENDS', {'git': 'git'}): |
|
84 | with mock.patch('rhodecode.BACKENDS', {'git': 'git'}): | |
85 | response = self.app.get(route_path('repo_new'), status=200) |
|
85 | response = self.app.get(route_path('repo_new'), status=200) | |
86 | assert_response = response.assert_response() |
|
86 | assert_response = response.assert_response() | |
87 |
element = assert_response.get_element(' |
|
87 | element = assert_response.get_element('[name=repo_type]') | |
88 |
assert element. |
|
88 | assert element.get('value') == 'git' | |
89 |
|
89 | |||
90 | def test_create_page_non_restricted_backends(self, autologin_user, backend): |
|
90 | def test_create_page_non_restricted_backends(self, autologin_user, backend): | |
91 | response = self.app.get(route_path('repo_new'), status=200) |
|
91 | response = self.app.get(route_path('repo_new'), status=200) | |
92 | assert_response = response.assert_response() |
|
92 | assert_response = response.assert_response() | |
93 | assert_response.element_contains('#repo_type', 'git') |
|
93 | assert ['hg', 'git', 'svn'] == [x.get('value') for x in assert_response.get_elements('[name=repo_type]')] | |
94 | assert_response.element_contains('#repo_type', 'svn') |
|
|||
95 | assert_response.element_contains('#repo_type', 'hg') |
|
|||
96 |
|
94 | |||
97 | @pytest.mark.parametrize( |
|
95 | @pytest.mark.parametrize( | |
98 | "suffix", [u'', u'xxa'], ids=['', 'non-ascii']) |
|
96 | "suffix", [u'', u'xxa'], ids=['', 'non-ascii']) | |
99 | def test_create(self, autologin_user, backend, suffix, csrf_token): |
|
97 | def test_create(self, autologin_user, backend, suffix, csrf_token): | |
100 | repo_name_unicode = backend.new_repo_name(suffix=suffix) |
|
98 | repo_name_unicode = backend.new_repo_name(suffix=suffix) | |
101 | repo_name = repo_name_unicode.encode('utf8') |
|
99 | repo_name = repo_name_unicode.encode('utf8') | |
102 | description_unicode = u'description for newly created repo' + suffix |
|
100 | description_unicode = u'description for newly created repo' + suffix | |
103 | description = description_unicode.encode('utf8') |
|
101 | description = description_unicode.encode('utf8') | |
104 | response = self.app.post( |
|
102 | response = self.app.post( | |
105 | route_path('repo_create'), |
|
103 | route_path('repo_create'), | |
106 | fixture._get_repo_create_params( |
|
104 | fixture._get_repo_create_params( | |
107 | repo_private=False, |
|
105 | repo_private=False, | |
108 | repo_name=repo_name, |
|
106 | repo_name=repo_name, | |
109 | repo_type=backend.alias, |
|
107 | repo_type=backend.alias, | |
110 | repo_description=description, |
|
108 | repo_description=description, | |
111 | csrf_token=csrf_token), |
|
109 | csrf_token=csrf_token), | |
112 | status=302) |
|
110 | status=302) | |
113 |
|
111 | |||
114 | self.assert_repository_is_created_correctly( |
|
112 | self.assert_repository_is_created_correctly( | |
115 | repo_name, description, backend) |
|
113 | repo_name, description, backend) | |
116 |
|
114 | |||
117 | def test_create_numeric_name(self, autologin_user, backend, csrf_token): |
|
115 | def test_create_numeric_name(self, autologin_user, backend, csrf_token): | |
118 | numeric_repo = '1234' |
|
116 | numeric_repo = '1234' | |
119 | repo_name = numeric_repo |
|
117 | repo_name = numeric_repo | |
120 | description = 'description for newly created repo' + numeric_repo |
|
118 | description = 'description for newly created repo' + numeric_repo | |
121 | self.app.post( |
|
119 | self.app.post( | |
122 | route_path('repo_create'), |
|
120 | route_path('repo_create'), | |
123 | fixture._get_repo_create_params( |
|
121 | fixture._get_repo_create_params( | |
124 | repo_private=False, |
|
122 | repo_private=False, | |
125 | repo_name=repo_name, |
|
123 | repo_name=repo_name, | |
126 | repo_type=backend.alias, |
|
124 | repo_type=backend.alias, | |
127 | repo_description=description, |
|
125 | repo_description=description, | |
128 | csrf_token=csrf_token)) |
|
126 | csrf_token=csrf_token)) | |
129 |
|
127 | |||
130 | self.assert_repository_is_created_correctly( |
|
128 | self.assert_repository_is_created_correctly( | |
131 | repo_name, description, backend) |
|
129 | repo_name, description, backend) | |
132 |
|
130 | |||
133 | @pytest.mark.parametrize("suffix", [u'', u'Δ ΔΔ'], ids=['', 'non-ascii']) |
|
131 | @pytest.mark.parametrize("suffix", [u'', u'Δ ΔΔ'], ids=['', 'non-ascii']) | |
134 | def test_create_in_group( |
|
132 | def test_create_in_group( | |
135 | self, autologin_user, backend, suffix, csrf_token): |
|
133 | self, autologin_user, backend, suffix, csrf_token): | |
136 | # create GROUP |
|
134 | # create GROUP | |
137 | group_name = 'sometest_%s' % backend.alias |
|
135 | group_name = 'sometest_%s' % backend.alias | |
138 | gr = RepoGroupModel().create(group_name=group_name, |
|
136 | gr = RepoGroupModel().create(group_name=group_name, | |
139 | group_description='test', |
|
137 | group_description='test', | |
140 | owner=TEST_USER_ADMIN_LOGIN) |
|
138 | owner=TEST_USER_ADMIN_LOGIN) | |
141 | Session().commit() |
|
139 | Session().commit() | |
142 |
|
140 | |||
143 | repo_name = u'ingroup' + suffix |
|
141 | repo_name = u'ingroup' + suffix | |
144 | repo_name_full = RepoGroup.url_sep().join( |
|
142 | repo_name_full = RepoGroup.url_sep().join( | |
145 | [group_name, repo_name]) |
|
143 | [group_name, repo_name]) | |
146 | description = u'description for newly created repo' |
|
144 | description = u'description for newly created repo' | |
147 | self.app.post( |
|
145 | self.app.post( | |
148 | route_path('repo_create'), |
|
146 | route_path('repo_create'), | |
149 | fixture._get_repo_create_params( |
|
147 | fixture._get_repo_create_params( | |
150 | repo_private=False, |
|
148 | repo_private=False, | |
151 | repo_name=safe_str(repo_name), |
|
149 | repo_name=safe_str(repo_name), | |
152 | repo_type=backend.alias, |
|
150 | repo_type=backend.alias, | |
153 | repo_description=description, |
|
151 | repo_description=description, | |
154 | repo_group=gr.group_id, |
|
152 | repo_group=gr.group_id, | |
155 | csrf_token=csrf_token)) |
|
153 | csrf_token=csrf_token)) | |
156 |
|
154 | |||
157 | # TODO: johbo: Cleanup work to fixture |
|
155 | # TODO: johbo: Cleanup work to fixture | |
158 | try: |
|
156 | try: | |
159 | self.assert_repository_is_created_correctly( |
|
157 | self.assert_repository_is_created_correctly( | |
160 | repo_name_full, description, backend) |
|
158 | repo_name_full, description, backend) | |
161 |
|
159 | |||
162 | new_repo = RepoModel().get_by_repo_name(repo_name_full) |
|
160 | new_repo = RepoModel().get_by_repo_name(repo_name_full) | |
163 | inherited_perms = UserRepoToPerm.query().filter( |
|
161 | inherited_perms = UserRepoToPerm.query().filter( | |
164 | UserRepoToPerm.repository_id == new_repo.repo_id).all() |
|
162 | UserRepoToPerm.repository_id == new_repo.repo_id).all() | |
165 | assert len(inherited_perms) == 1 |
|
163 | assert len(inherited_perms) == 1 | |
166 | finally: |
|
164 | finally: | |
167 | RepoModel().delete(repo_name_full) |
|
165 | RepoModel().delete(repo_name_full) | |
168 | RepoGroupModel().delete(group_name) |
|
166 | RepoGroupModel().delete(group_name) | |
169 | Session().commit() |
|
167 | Session().commit() | |
170 |
|
168 | |||
171 | def test_create_in_group_numeric_name( |
|
169 | def test_create_in_group_numeric_name( | |
172 | self, autologin_user, backend, csrf_token): |
|
170 | self, autologin_user, backend, csrf_token): | |
173 | # create GROUP |
|
171 | # create GROUP | |
174 | group_name = 'sometest_%s' % backend.alias |
|
172 | group_name = 'sometest_%s' % backend.alias | |
175 | gr = RepoGroupModel().create(group_name=group_name, |
|
173 | gr = RepoGroupModel().create(group_name=group_name, | |
176 | group_description='test', |
|
174 | group_description='test', | |
177 | owner=TEST_USER_ADMIN_LOGIN) |
|
175 | owner=TEST_USER_ADMIN_LOGIN) | |
178 | Session().commit() |
|
176 | Session().commit() | |
179 |
|
177 | |||
180 | repo_name = '12345' |
|
178 | repo_name = '12345' | |
181 | repo_name_full = RepoGroup.url_sep().join([group_name, repo_name]) |
|
179 | repo_name_full = RepoGroup.url_sep().join([group_name, repo_name]) | |
182 | description = 'description for newly created repo' |
|
180 | description = 'description for newly created repo' | |
183 | self.app.post( |
|
181 | self.app.post( | |
184 | route_path('repo_create'), |
|
182 | route_path('repo_create'), | |
185 | fixture._get_repo_create_params( |
|
183 | fixture._get_repo_create_params( | |
186 | repo_private=False, |
|
184 | repo_private=False, | |
187 | repo_name=repo_name, |
|
185 | repo_name=repo_name, | |
188 | repo_type=backend.alias, |
|
186 | repo_type=backend.alias, | |
189 | repo_description=description, |
|
187 | repo_description=description, | |
190 | repo_group=gr.group_id, |
|
188 | repo_group=gr.group_id, | |
191 | csrf_token=csrf_token)) |
|
189 | csrf_token=csrf_token)) | |
192 |
|
190 | |||
193 | # TODO: johbo: Cleanup work to fixture |
|
191 | # TODO: johbo: Cleanup work to fixture | |
194 | try: |
|
192 | try: | |
195 | self.assert_repository_is_created_correctly( |
|
193 | self.assert_repository_is_created_correctly( | |
196 | repo_name_full, description, backend) |
|
194 | repo_name_full, description, backend) | |
197 |
|
195 | |||
198 | new_repo = RepoModel().get_by_repo_name(repo_name_full) |
|
196 | new_repo = RepoModel().get_by_repo_name(repo_name_full) | |
199 | inherited_perms = UserRepoToPerm.query()\ |
|
197 | inherited_perms = UserRepoToPerm.query()\ | |
200 | .filter(UserRepoToPerm.repository_id == new_repo.repo_id).all() |
|
198 | .filter(UserRepoToPerm.repository_id == new_repo.repo_id).all() | |
201 | assert len(inherited_perms) == 1 |
|
199 | assert len(inherited_perms) == 1 | |
202 | finally: |
|
200 | finally: | |
203 | RepoModel().delete(repo_name_full) |
|
201 | RepoModel().delete(repo_name_full) | |
204 | RepoGroupModel().delete(group_name) |
|
202 | RepoGroupModel().delete(group_name) | |
205 | Session().commit() |
|
203 | Session().commit() | |
206 |
|
204 | |||
207 | def test_create_in_group_without_needed_permissions(self, backend): |
|
205 | def test_create_in_group_without_needed_permissions(self, backend): | |
208 | session = login_user_session( |
|
206 | session = login_user_session( | |
209 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) |
|
207 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) | |
210 | csrf_token = auth.get_csrf_token(session) |
|
208 | csrf_token = auth.get_csrf_token(session) | |
211 | # revoke |
|
209 | # revoke | |
212 | user_model = UserModel() |
|
210 | user_model = UserModel() | |
213 | # disable fork and create on default user |
|
211 | # disable fork and create on default user | |
214 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.create.repository') |
|
212 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.create.repository') | |
215 | user_model.grant_perm(User.DEFAULT_USER, 'hg.create.none') |
|
213 | user_model.grant_perm(User.DEFAULT_USER, 'hg.create.none') | |
216 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.fork.repository') |
|
214 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.fork.repository') | |
217 | user_model.grant_perm(User.DEFAULT_USER, 'hg.fork.none') |
|
215 | user_model.grant_perm(User.DEFAULT_USER, 'hg.fork.none') | |
218 |
|
216 | |||
219 | # disable on regular user |
|
217 | # disable on regular user | |
220 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.repository') |
|
218 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.repository') | |
221 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.none') |
|
219 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.none') | |
222 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.repository') |
|
220 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.repository') | |
223 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.none') |
|
221 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.none') | |
224 | Session().commit() |
|
222 | Session().commit() | |
225 |
|
223 | |||
226 | # create GROUP |
|
224 | # create GROUP | |
227 | group_name = 'reg_sometest_%s' % backend.alias |
|
225 | group_name = 'reg_sometest_%s' % backend.alias | |
228 | gr = RepoGroupModel().create(group_name=group_name, |
|
226 | gr = RepoGroupModel().create(group_name=group_name, | |
229 | group_description='test', |
|
227 | group_description='test', | |
230 | owner=TEST_USER_ADMIN_LOGIN) |
|
228 | owner=TEST_USER_ADMIN_LOGIN) | |
231 | Session().commit() |
|
229 | Session().commit() | |
232 | repo_group_id = gr.group_id |
|
230 | repo_group_id = gr.group_id | |
233 |
|
231 | |||
234 | group_name_allowed = 'reg_sometest_allowed_%s' % backend.alias |
|
232 | group_name_allowed = 'reg_sometest_allowed_%s' % backend.alias | |
235 | gr_allowed = RepoGroupModel().create( |
|
233 | gr_allowed = RepoGroupModel().create( | |
236 | group_name=group_name_allowed, |
|
234 | group_name=group_name_allowed, | |
237 | group_description='test', |
|
235 | group_description='test', | |
238 | owner=TEST_USER_REGULAR_LOGIN) |
|
236 | owner=TEST_USER_REGULAR_LOGIN) | |
239 | allowed_repo_group_id = gr_allowed.group_id |
|
237 | allowed_repo_group_id = gr_allowed.group_id | |
240 | Session().commit() |
|
238 | Session().commit() | |
241 |
|
239 | |||
242 | repo_name = 'ingroup' |
|
240 | repo_name = 'ingroup' | |
243 | description = 'description for newly created repo' |
|
241 | description = 'description for newly created repo' | |
244 | response = self.app.post( |
|
242 | response = self.app.post( | |
245 | route_path('repo_create'), |
|
243 | route_path('repo_create'), | |
246 | fixture._get_repo_create_params( |
|
244 | fixture._get_repo_create_params( | |
247 | repo_private=False, |
|
245 | repo_private=False, | |
248 | repo_name=repo_name, |
|
246 | repo_name=repo_name, | |
249 | repo_type=backend.alias, |
|
247 | repo_type=backend.alias, | |
250 | repo_description=description, |
|
248 | repo_description=description, | |
251 | repo_group=repo_group_id, |
|
249 | repo_group=repo_group_id, | |
252 | csrf_token=csrf_token)) |
|
250 | csrf_token=csrf_token)) | |
253 |
|
251 | |||
254 | response.mustcontain('Invalid value') |
|
252 | response.mustcontain('Invalid value') | |
255 |
|
253 | |||
256 | # user is allowed to create in this group |
|
254 | # user is allowed to create in this group | |
257 | repo_name = 'ingroup' |
|
255 | repo_name = 'ingroup' | |
258 | repo_name_full = RepoGroup.url_sep().join( |
|
256 | repo_name_full = RepoGroup.url_sep().join( | |
259 | [group_name_allowed, repo_name]) |
|
257 | [group_name_allowed, repo_name]) | |
260 | description = 'description for newly created repo' |
|
258 | description = 'description for newly created repo' | |
261 | response = self.app.post( |
|
259 | response = self.app.post( | |
262 | route_path('repo_create'), |
|
260 | route_path('repo_create'), | |
263 | fixture._get_repo_create_params( |
|
261 | fixture._get_repo_create_params( | |
264 | repo_private=False, |
|
262 | repo_private=False, | |
265 | repo_name=repo_name, |
|
263 | repo_name=repo_name, | |
266 | repo_type=backend.alias, |
|
264 | repo_type=backend.alias, | |
267 | repo_description=description, |
|
265 | repo_description=description, | |
268 | repo_group=allowed_repo_group_id, |
|
266 | repo_group=allowed_repo_group_id, | |
269 | csrf_token=csrf_token)) |
|
267 | csrf_token=csrf_token)) | |
270 |
|
268 | |||
271 | # TODO: johbo: Cleanup in pytest fixture |
|
269 | # TODO: johbo: Cleanup in pytest fixture | |
272 | try: |
|
270 | try: | |
273 | self.assert_repository_is_created_correctly( |
|
271 | self.assert_repository_is_created_correctly( | |
274 | repo_name_full, description, backend) |
|
272 | repo_name_full, description, backend) | |
275 |
|
273 | |||
276 | new_repo = RepoModel().get_by_repo_name(repo_name_full) |
|
274 | new_repo = RepoModel().get_by_repo_name(repo_name_full) | |
277 | inherited_perms = UserRepoToPerm.query().filter( |
|
275 | inherited_perms = UserRepoToPerm.query().filter( | |
278 | UserRepoToPerm.repository_id == new_repo.repo_id).all() |
|
276 | UserRepoToPerm.repository_id == new_repo.repo_id).all() | |
279 | assert len(inherited_perms) == 1 |
|
277 | assert len(inherited_perms) == 1 | |
280 |
|
278 | |||
281 | assert repo_on_filesystem(repo_name_full) |
|
279 | assert repo_on_filesystem(repo_name_full) | |
282 | finally: |
|
280 | finally: | |
283 | RepoModel().delete(repo_name_full) |
|
281 | RepoModel().delete(repo_name_full) | |
284 | RepoGroupModel().delete(group_name) |
|
282 | RepoGroupModel().delete(group_name) | |
285 | RepoGroupModel().delete(group_name_allowed) |
|
283 | RepoGroupModel().delete(group_name_allowed) | |
286 | Session().commit() |
|
284 | Session().commit() | |
287 |
|
285 | |||
288 | def test_create_in_group_inherit_permissions(self, autologin_user, backend, |
|
286 | def test_create_in_group_inherit_permissions(self, autologin_user, backend, | |
289 | csrf_token): |
|
287 | csrf_token): | |
290 | # create GROUP |
|
288 | # create GROUP | |
291 | group_name = 'sometest_%s' % backend.alias |
|
289 | group_name = 'sometest_%s' % backend.alias | |
292 | gr = RepoGroupModel().create(group_name=group_name, |
|
290 | gr = RepoGroupModel().create(group_name=group_name, | |
293 | group_description='test', |
|
291 | group_description='test', | |
294 | owner=TEST_USER_ADMIN_LOGIN) |
|
292 | owner=TEST_USER_ADMIN_LOGIN) | |
295 | perm = Permission.get_by_key('repository.write') |
|
293 | perm = Permission.get_by_key('repository.write') | |
296 | RepoGroupModel().grant_user_permission( |
|
294 | RepoGroupModel().grant_user_permission( | |
297 | gr, TEST_USER_REGULAR_LOGIN, perm) |
|
295 | gr, TEST_USER_REGULAR_LOGIN, perm) | |
298 |
|
296 | |||
299 | # add repo permissions |
|
297 | # add repo permissions | |
300 | Session().commit() |
|
298 | Session().commit() | |
301 | repo_group_id = gr.group_id |
|
299 | repo_group_id = gr.group_id | |
302 | repo_name = 'ingroup_inherited_%s' % backend.alias |
|
300 | repo_name = 'ingroup_inherited_%s' % backend.alias | |
303 | repo_name_full = RepoGroup.url_sep().join([group_name, repo_name]) |
|
301 | repo_name_full = RepoGroup.url_sep().join([group_name, repo_name]) | |
304 | description = 'description for newly created repo' |
|
302 | description = 'description for newly created repo' | |
305 | self.app.post( |
|
303 | self.app.post( | |
306 | route_path('repo_create'), |
|
304 | route_path('repo_create'), | |
307 | fixture._get_repo_create_params( |
|
305 | fixture._get_repo_create_params( | |
308 | repo_private=False, |
|
306 | repo_private=False, | |
309 | repo_name=repo_name, |
|
307 | repo_name=repo_name, | |
310 | repo_type=backend.alias, |
|
308 | repo_type=backend.alias, | |
311 | repo_description=description, |
|
309 | repo_description=description, | |
312 | repo_group=repo_group_id, |
|
310 | repo_group=repo_group_id, | |
313 | repo_copy_permissions=True, |
|
311 | repo_copy_permissions=True, | |
314 | csrf_token=csrf_token)) |
|
312 | csrf_token=csrf_token)) | |
315 |
|
313 | |||
316 | # TODO: johbo: Cleanup to pytest fixture |
|
314 | # TODO: johbo: Cleanup to pytest fixture | |
317 | try: |
|
315 | try: | |
318 | self.assert_repository_is_created_correctly( |
|
316 | self.assert_repository_is_created_correctly( | |
319 | repo_name_full, description, backend) |
|
317 | repo_name_full, description, backend) | |
320 | except Exception: |
|
318 | except Exception: | |
321 | RepoGroupModel().delete(group_name) |
|
319 | RepoGroupModel().delete(group_name) | |
322 | Session().commit() |
|
320 | Session().commit() | |
323 | raise |
|
321 | raise | |
324 |
|
322 | |||
325 | # check if inherited permissions are applied |
|
323 | # check if inherited permissions are applied | |
326 | new_repo = RepoModel().get_by_repo_name(repo_name_full) |
|
324 | new_repo = RepoModel().get_by_repo_name(repo_name_full) | |
327 | inherited_perms = UserRepoToPerm.query().filter( |
|
325 | inherited_perms = UserRepoToPerm.query().filter( | |
328 | UserRepoToPerm.repository_id == new_repo.repo_id).all() |
|
326 | UserRepoToPerm.repository_id == new_repo.repo_id).all() | |
329 | assert len(inherited_perms) == 2 |
|
327 | assert len(inherited_perms) == 2 | |
330 |
|
328 | |||
331 | assert TEST_USER_REGULAR_LOGIN in [ |
|
329 | assert TEST_USER_REGULAR_LOGIN in [ | |
332 | x.user.username for x in inherited_perms] |
|
330 | x.user.username for x in inherited_perms] | |
333 | assert 'repository.write' in [ |
|
331 | assert 'repository.write' in [ | |
334 | x.permission.permission_name for x in inherited_perms] |
|
332 | x.permission.permission_name for x in inherited_perms] | |
335 |
|
333 | |||
336 | RepoModel().delete(repo_name_full) |
|
334 | RepoModel().delete(repo_name_full) | |
337 | RepoGroupModel().delete(group_name) |
|
335 | RepoGroupModel().delete(group_name) | |
338 | Session().commit() |
|
336 | Session().commit() | |
339 |
|
337 | |||
340 | @pytest.mark.xfail_backends( |
|
338 | @pytest.mark.xfail_backends( | |
341 | "git", "hg", reason="Missing reposerver support") |
|
339 | "git", "hg", reason="Missing reposerver support") | |
342 | def test_create_with_clone_uri(self, autologin_user, backend, reposerver, |
|
340 | def test_create_with_clone_uri(self, autologin_user, backend, reposerver, | |
343 | csrf_token): |
|
341 | csrf_token): | |
344 | source_repo = backend.create_repo(number_of_commits=2) |
|
342 | source_repo = backend.create_repo(number_of_commits=2) | |
345 | source_repo_name = source_repo.repo_name |
|
343 | source_repo_name = source_repo.repo_name | |
346 | reposerver.serve(source_repo.scm_instance()) |
|
344 | reposerver.serve(source_repo.scm_instance()) | |
347 |
|
345 | |||
348 | repo_name = backend.new_repo_name() |
|
346 | repo_name = backend.new_repo_name() | |
349 | response = self.app.post( |
|
347 | response = self.app.post( | |
350 | route_path('repo_create'), |
|
348 | route_path('repo_create'), | |
351 | fixture._get_repo_create_params( |
|
349 | fixture._get_repo_create_params( | |
352 | repo_private=False, |
|
350 | repo_private=False, | |
353 | repo_name=repo_name, |
|
351 | repo_name=repo_name, | |
354 | repo_type=backend.alias, |
|
352 | repo_type=backend.alias, | |
355 | repo_description='', |
|
353 | repo_description='', | |
356 | clone_uri=reposerver.url, |
|
354 | clone_uri=reposerver.url, | |
357 | csrf_token=csrf_token), |
|
355 | csrf_token=csrf_token), | |
358 | status=302) |
|
356 | status=302) | |
359 |
|
357 | |||
360 | # Should be redirected to the creating page |
|
358 | # Should be redirected to the creating page | |
361 | response.mustcontain('repo_creating') |
|
359 | response.mustcontain('repo_creating') | |
362 |
|
360 | |||
363 | # Expecting that both repositories have same history |
|
361 | # Expecting that both repositories have same history | |
364 | source_repo = RepoModel().get_by_repo_name(source_repo_name) |
|
362 | source_repo = RepoModel().get_by_repo_name(source_repo_name) | |
365 | source_vcs = source_repo.scm_instance() |
|
363 | source_vcs = source_repo.scm_instance() | |
366 | repo = RepoModel().get_by_repo_name(repo_name) |
|
364 | repo = RepoModel().get_by_repo_name(repo_name) | |
367 | repo_vcs = repo.scm_instance() |
|
365 | repo_vcs = repo.scm_instance() | |
368 | assert source_vcs[0].message == repo_vcs[0].message |
|
366 | assert source_vcs[0].message == repo_vcs[0].message | |
369 | assert source_vcs.count() == repo_vcs.count() |
|
367 | assert source_vcs.count() == repo_vcs.count() | |
370 | assert source_vcs.commit_ids == repo_vcs.commit_ids |
|
368 | assert source_vcs.commit_ids == repo_vcs.commit_ids | |
371 |
|
369 | |||
372 | @pytest.mark.xfail_backends("svn", reason="Depends on import support") |
|
370 | @pytest.mark.xfail_backends("svn", reason="Depends on import support") | |
373 | def test_create_remote_repo_wrong_clone_uri(self, autologin_user, backend, |
|
371 | def test_create_remote_repo_wrong_clone_uri(self, autologin_user, backend, | |
374 | csrf_token): |
|
372 | csrf_token): | |
375 | repo_name = backend.new_repo_name() |
|
373 | repo_name = backend.new_repo_name() | |
376 | description = 'description for newly created repo' |
|
374 | description = 'description for newly created repo' | |
377 | response = self.app.post( |
|
375 | response = self.app.post( | |
378 | route_path('repo_create'), |
|
376 | route_path('repo_create'), | |
379 | fixture._get_repo_create_params( |
|
377 | fixture._get_repo_create_params( | |
380 | repo_private=False, |
|
378 | repo_private=False, | |
381 | repo_name=repo_name, |
|
379 | repo_name=repo_name, | |
382 | repo_type=backend.alias, |
|
380 | repo_type=backend.alias, | |
383 | repo_description=description, |
|
381 | repo_description=description, | |
384 | clone_uri='http://repo.invalid/repo', |
|
382 | clone_uri='http://repo.invalid/repo', | |
385 | csrf_token=csrf_token)) |
|
383 | csrf_token=csrf_token)) | |
386 | response.mustcontain('invalid clone url') |
|
384 | response.mustcontain('invalid clone url') | |
387 |
|
385 | |||
388 | @pytest.mark.xfail_backends("svn", reason="Depends on import support") |
|
386 | @pytest.mark.xfail_backends("svn", reason="Depends on import support") | |
389 | def test_create_remote_repo_wrong_clone_uri_hg_svn( |
|
387 | def test_create_remote_repo_wrong_clone_uri_hg_svn( | |
390 | self, autologin_user, backend, csrf_token): |
|
388 | self, autologin_user, backend, csrf_token): | |
391 | repo_name = backend.new_repo_name() |
|
389 | repo_name = backend.new_repo_name() | |
392 | description = 'description for newly created repo' |
|
390 | description = 'description for newly created repo' | |
393 | response = self.app.post( |
|
391 | response = self.app.post( | |
394 | route_path('repo_create'), |
|
392 | route_path('repo_create'), | |
395 | fixture._get_repo_create_params( |
|
393 | fixture._get_repo_create_params( | |
396 | repo_private=False, |
|
394 | repo_private=False, | |
397 | repo_name=repo_name, |
|
395 | repo_name=repo_name, | |
398 | repo_type=backend.alias, |
|
396 | repo_type=backend.alias, | |
399 | repo_description=description, |
|
397 | repo_description=description, | |
400 | clone_uri='svn+http://svn.invalid/repo', |
|
398 | clone_uri='svn+http://svn.invalid/repo', | |
401 | csrf_token=csrf_token)) |
|
399 | csrf_token=csrf_token)) | |
402 | response.mustcontain('invalid clone url') |
|
400 | response.mustcontain('invalid clone url') | |
403 |
|
401 | |||
404 | def test_create_with_git_suffix( |
|
402 | def test_create_with_git_suffix( | |
405 | self, autologin_user, backend, csrf_token): |
|
403 | self, autologin_user, backend, csrf_token): | |
406 | repo_name = backend.new_repo_name() + ".git" |
|
404 | repo_name = backend.new_repo_name() + ".git" | |
407 | description = 'description for newly created repo' |
|
405 | description = 'description for newly created repo' | |
408 | response = self.app.post( |
|
406 | response = self.app.post( | |
409 | route_path('repo_create'), |
|
407 | route_path('repo_create'), | |
410 | fixture._get_repo_create_params( |
|
408 | fixture._get_repo_create_params( | |
411 | repo_private=False, |
|
409 | repo_private=False, | |
412 | repo_name=repo_name, |
|
410 | repo_name=repo_name, | |
413 | repo_type=backend.alias, |
|
411 | repo_type=backend.alias, | |
414 | repo_description=description, |
|
412 | repo_description=description, | |
415 | csrf_token=csrf_token)) |
|
413 | csrf_token=csrf_token)) | |
416 | response.mustcontain('Repository name cannot end with .git') |
|
414 | response.mustcontain('Repository name cannot end with .git') | |
417 |
|
415 | |||
418 | def test_default_user_cannot_access_private_repo_in_a_group( |
|
416 | def test_default_user_cannot_access_private_repo_in_a_group( | |
419 | self, autologin_user, user_util, backend): |
|
417 | self, autologin_user, user_util, backend): | |
420 |
|
418 | |||
421 | group = user_util.create_repo_group() |
|
419 | group = user_util.create_repo_group() | |
422 |
|
420 | |||
423 | repo = backend.create_repo( |
|
421 | repo = backend.create_repo( | |
424 | repo_private=True, repo_group=group, repo_copy_permissions=True) |
|
422 | repo_private=True, repo_group=group, repo_copy_permissions=True) | |
425 |
|
423 | |||
426 | permissions = _get_permission_for_user( |
|
424 | permissions = _get_permission_for_user( | |
427 | user='default', repo=repo.repo_name) |
|
425 | user='default', repo=repo.repo_name) | |
428 | assert len(permissions) == 1 |
|
426 | assert len(permissions) == 1 | |
429 | assert permissions[0].permission.permission_name == 'repository.none' |
|
427 | assert permissions[0].permission.permission_name == 'repository.none' | |
430 | assert permissions[0].repository.private is True |
|
428 | assert permissions[0].repository.private is True | |
431 |
|
429 | |||
432 | def test_create_on_top_level_without_permissions(self, backend): |
|
430 | def test_create_on_top_level_without_permissions(self, backend): | |
433 | session = login_user_session( |
|
431 | session = login_user_session( | |
434 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) |
|
432 | self.app, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS) | |
435 | csrf_token = auth.get_csrf_token(session) |
|
433 | csrf_token = auth.get_csrf_token(session) | |
436 |
|
434 | |||
437 | # revoke |
|
435 | # revoke | |
438 | user_model = UserModel() |
|
436 | user_model = UserModel() | |
439 | # disable fork and create on default user |
|
437 | # disable fork and create on default user | |
440 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.create.repository') |
|
438 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.create.repository') | |
441 | user_model.grant_perm(User.DEFAULT_USER, 'hg.create.none') |
|
439 | user_model.grant_perm(User.DEFAULT_USER, 'hg.create.none') | |
442 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.fork.repository') |
|
440 | user_model.revoke_perm(User.DEFAULT_USER, 'hg.fork.repository') | |
443 | user_model.grant_perm(User.DEFAULT_USER, 'hg.fork.none') |
|
441 | user_model.grant_perm(User.DEFAULT_USER, 'hg.fork.none') | |
444 |
|
442 | |||
445 | # disable on regular user |
|
443 | # disable on regular user | |
446 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.repository') |
|
444 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.repository') | |
447 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.none') |
|
445 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.create.none') | |
448 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.repository') |
|
446 | user_model.revoke_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.repository') | |
449 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.none') |
|
447 | user_model.grant_perm(TEST_USER_REGULAR_LOGIN, 'hg.fork.none') | |
450 | Session().commit() |
|
448 | Session().commit() | |
451 |
|
449 | |||
452 | repo_name = backend.new_repo_name() |
|
450 | repo_name = backend.new_repo_name() | |
453 | description = 'description for newly created repo' |
|
451 | description = 'description for newly created repo' | |
454 | response = self.app.post( |
|
452 | response = self.app.post( | |
455 | route_path('repo_create'), |
|
453 | route_path('repo_create'), | |
456 | fixture._get_repo_create_params( |
|
454 | fixture._get_repo_create_params( | |
457 | repo_private=False, |
|
455 | repo_private=False, | |
458 | repo_name=repo_name, |
|
456 | repo_name=repo_name, | |
459 | repo_type=backend.alias, |
|
457 | repo_type=backend.alias, | |
460 | repo_description=description, |
|
458 | repo_description=description, | |
461 | csrf_token=csrf_token)) |
|
459 | csrf_token=csrf_token)) | |
462 |
|
460 | |||
463 | response.mustcontain( |
|
461 | response.mustcontain( | |
464 | u"You do not have the permission to store repositories in " |
|
462 | u"You do not have the permission to store repositories in " | |
465 | u"the root location.") |
|
463 | u"the root location.") | |
466 |
|
464 | |||
467 | @mock.patch.object(RepoModel, '_create_filesystem_repo', error_function) |
|
465 | @mock.patch.object(RepoModel, '_create_filesystem_repo', error_function) | |
468 | def test_create_repo_when_filesystem_op_fails( |
|
466 | def test_create_repo_when_filesystem_op_fails( | |
469 | self, autologin_user, backend, csrf_token): |
|
467 | self, autologin_user, backend, csrf_token): | |
470 | repo_name = backend.new_repo_name() |
|
468 | repo_name = backend.new_repo_name() | |
471 | description = 'description for newly created repo' |
|
469 | description = 'description for newly created repo' | |
472 |
|
470 | |||
473 | response = self.app.post( |
|
471 | response = self.app.post( | |
474 | route_path('repo_create'), |
|
472 | route_path('repo_create'), | |
475 | fixture._get_repo_create_params( |
|
473 | fixture._get_repo_create_params( | |
476 | repo_private=False, |
|
474 | repo_private=False, | |
477 | repo_name=repo_name, |
|
475 | repo_name=repo_name, | |
478 | repo_type=backend.alias, |
|
476 | repo_type=backend.alias, | |
479 | repo_description=description, |
|
477 | repo_description=description, | |
480 | csrf_token=csrf_token)) |
|
478 | csrf_token=csrf_token)) | |
481 |
|
479 | |||
482 | assert_session_flash( |
|
480 | assert_session_flash( | |
483 | response, 'Error creating repository %s' % repo_name) |
|
481 | response, 'Error creating repository %s' % repo_name) | |
484 | # repo must not be in db |
|
482 | # repo must not be in db | |
485 | assert backend.repo is None |
|
483 | assert backend.repo is None | |
486 | # repo must not be in filesystem ! |
|
484 | # repo must not be in filesystem ! | |
487 | assert not repo_on_filesystem(repo_name) |
|
485 | assert not repo_on_filesystem(repo_name) | |
488 |
|
486 | |||
489 | def assert_repository_is_created_correctly( |
|
487 | def assert_repository_is_created_correctly( | |
490 | self, repo_name, description, backend): |
|
488 | self, repo_name, description, backend): | |
491 | repo_name_utf8 = safe_str(repo_name) |
|
489 | repo_name_utf8 = safe_str(repo_name) | |
492 |
|
490 | |||
493 | # run the check page that triggers the flash message |
|
491 | # run the check page that triggers the flash message | |
494 | response = self.app.get( |
|
492 | response = self.app.get( | |
495 | route_path('repo_creating_check', repo_name=safe_str(repo_name))) |
|
493 | route_path('repo_creating_check', repo_name=safe_str(repo_name))) | |
496 | assert response.json == {u'result': True} |
|
494 | assert response.json == {u'result': True} | |
497 |
|
495 | |||
498 | flash_msg = u'Created repository <a href="/{}">{}</a>'.format( |
|
496 | flash_msg = u'Created repository <a href="/{}">{}</a>'.format( | |
499 | urllib.quote(repo_name_utf8), repo_name) |
|
497 | urllib.quote(repo_name_utf8), repo_name) | |
500 | assert_session_flash(response, flash_msg) |
|
498 | assert_session_flash(response, flash_msg) | |
501 |
|
499 | |||
502 | # test if the repo was created in the database |
|
500 | # test if the repo was created in the database | |
503 | new_repo = RepoModel().get_by_repo_name(repo_name) |
|
501 | new_repo = RepoModel().get_by_repo_name(repo_name) | |
504 |
|
502 | |||
505 | assert new_repo.repo_name == repo_name |
|
503 | assert new_repo.repo_name == repo_name | |
506 | assert new_repo.description == description |
|
504 | assert new_repo.description == description | |
507 |
|
505 | |||
508 | # test if the repository is visible in the list ? |
|
506 | # test if the repository is visible in the list ? | |
509 | response = self.app.get( |
|
507 | response = self.app.get( | |
510 | h.route_path('repo_summary', repo_name=safe_str(repo_name))) |
|
508 | h.route_path('repo_summary', repo_name=safe_str(repo_name))) | |
511 | response.mustcontain(repo_name) |
|
509 | response.mustcontain(repo_name) | |
512 | response.mustcontain(backend.alias) |
|
510 | response.mustcontain(backend.alias) | |
513 |
|
511 | |||
514 | assert repo_on_filesystem(repo_name) |
|
512 | assert repo_on_filesystem(repo_name) |
@@ -1,175 +1,169 b'' | |||||
1 | ## -*- coding: utf-8 -*- |
|
1 | ## -*- coding: utf-8 -*- | |
2 |
|
2 | |||
3 | ${h.secure_form(h.route_path('repo_create'), request=request)} |
|
3 | ${h.secure_form(h.route_path('repo_create'), request=request)} | |
4 | <div class="form"> |
|
4 | <div class="form"> | |
5 | <!-- fields --> |
|
5 | <!-- fields --> | |
6 | <div class="fields"> |
|
6 | <div class="fields"> | |
7 | <div class="field"> |
|
7 | <div class="field"> | |
8 | <div class="label"> |
|
8 | <div class="label"> | |
9 | <label for="repo_name">${_('Repository name')}:</label> |
|
9 | <label for="repo_name">${_('Repository name')}:</label> | |
10 | </div> |
|
10 | </div> | |
11 | <div class="input"> |
|
11 | <div class="input"> | |
12 | ${h.text('repo_name', class_="medium")} |
|
12 | ${h.text('repo_name', class_="medium")} | |
13 | <div class="info-block"> |
|
13 | <div class="info-block"> | |
14 | <a id="remote_clone_toggle" href="#">${_('Import Existing Repository ?')}</a> |
|
14 | <a id="remote_clone_toggle" href="#">${_('Import Existing Repository ?')}</a> | |
15 | </div> |
|
15 | </div> | |
16 | %if not c.rhodecode_user.is_admin: |
|
16 | %if not c.rhodecode_user.is_admin: | |
17 | ${h.hidden('user_created',True)} |
|
17 | ${h.hidden('user_created',True)} | |
18 | %endif |
|
18 | %endif | |
19 | </div> |
|
19 | </div> | |
20 | </div> |
|
20 | </div> | |
21 | <div id="remote_clone" class="field" style="display: none;"> |
|
21 | <div id="remote_clone" class="field" style="display: none;"> | |
22 | <div class="label"> |
|
22 | <div class="label"> | |
23 | <label for="clone_uri">${_('Clone from')}:</label> |
|
23 | <label for="clone_uri">${_('Clone from')}:</label> | |
24 | </div> |
|
24 | </div> | |
25 | <div class="input"> |
|
25 | <div class="input"> | |
26 | ${h.text('clone_uri', class_="medium")} |
|
26 | ${h.text('clone_uri', class_="medium")} | |
27 | <span class="help-block"> |
|
27 | <span class="help-block"> | |
28 | <pre> |
|
28 | <pre> | |
29 | - The repository must be accessible over http:// or https:// |
|
29 | - The repository must be accessible over http:// or https:// | |
30 | - For Git projects it's recommended appending .git to the end of clone url. |
|
30 | - For Git projects it's recommended appending .git to the end of clone url. | |
31 | - Make sure to select proper repository type from the below selector before importing it. |
|
31 | - Make sure to select proper repository type from the below selector before importing it. | |
32 | - If your HTTP[S] repository is not publicly accessible, |
|
32 | - If your HTTP[S] repository is not publicly accessible, | |
33 | add authentication information to the URL: https://username:password@server.company.com/repo-name. |
|
33 | add authentication information to the URL: https://username:password@server.company.com/repo-name. | |
34 | - The Git LFS/Mercurial Largefiles objects will not be imported. |
|
34 | - The Git LFS/Mercurial Largefiles objects will not be imported. | |
35 | - For very large repositories, it's recommended to manually copy them into the |
|
35 | - For very large repositories, it's recommended to manually copy them into the | |
36 | RhodeCode <a href="${h.route_path('admin_settings_vcs', _anchor='vcs-storage-options')}">storage location</a> and run <a href="${h.route_path('admin_settings_mapping')}">Remap and Rescan</a>. |
|
36 | RhodeCode <a href="${h.route_path('admin_settings_vcs', _anchor='vcs-storage-options')}">storage location</a> and run <a href="${h.route_path('admin_settings_mapping')}">Remap and Rescan</a>. | |
37 | </pre> |
|
37 | </pre> | |
38 | </span> |
|
38 | </span> | |
39 | </div> |
|
39 | </div> | |
40 | </div> |
|
40 | </div> | |
41 | <div class="field"> |
|
41 | <div class="field"> | |
42 | <div class="label"> |
|
42 | <div class="label"> | |
43 | <label for="repo_group">${_('Repository group')}:</label> |
|
43 | <label for="repo_group">${_('Repository group')}:</label> | |
44 | </div> |
|
44 | </div> | |
45 | <div class="select"> |
|
45 | <div class="select"> | |
46 | ${h.select('repo_group',request.GET.get('parent_group'),c.repo_groups,class_="medium")} |
|
46 | ${h.select('repo_group',request.GET.get('parent_group'),c.repo_groups,class_="medium")} | |
47 | % if c.personal_repo_group: |
|
47 | % if c.personal_repo_group: | |
48 | <a class="btn" href="#" id="select_my_group" data-personal-group-id="${c.personal_repo_group.group_id}"> |
|
48 | <a class="btn" href="#" id="select_my_group" data-personal-group-id="${c.personal_repo_group.group_id}"> | |
49 | ${_('Select my personal group (%(repo_group_name)s)') % {'repo_group_name': c.personal_repo_group.group_name}} |
|
49 | ${_('Select my personal group (%(repo_group_name)s)') % {'repo_group_name': c.personal_repo_group.group_name}} | |
50 | </a> |
|
50 | </a> | |
51 | % endif |
|
51 | % endif | |
52 | <span class="help-block">${_('Optionally select a group to put this repository into.')}</span> |
|
52 | <span class="help-block">${_('Optionally select a group to put this repository into.')}</span> | |
53 | </div> |
|
53 | </div> | |
54 | </div> |
|
54 | </div> | |
55 |
|
55 | |||
56 | <div class="field"> |
|
56 | <div class="field"> | |
57 | <div class="label"> |
|
57 | <div class="label"> | |
58 | <label for="repo_type">${_('Type')}:</label> |
|
58 | <label for="repo_type">${_('Type')}:</label> | |
59 | </div> |
|
59 | </div> | |
60 | <div class="fields repo-type-radio"> |
|
60 | <div class="fields repo-type-radio"> | |
61 |
|
61 | |||
62 |
|
62 | |||
63 | % for backend in c.backends: |
|
63 | % for backend in c.backends: | |
64 | % if loop.index == 0: |
|
64 | % if loop.index == 0: | |
65 | <input id="repo_type_${backend}" name="repo_type" type="radio" value="${backend}" checked="checked"/> |
|
65 | <input id="repo_type_${backend}" name="repo_type" type="radio" value="${backend}" checked="checked"/> | |
66 | % else: |
|
66 | % else: | |
67 | <input id="repo_type_${backend}" name="repo_type" type="radio" value="${backend}" /> |
|
67 | <input id="repo_type_${backend}" name="repo_type" type="radio" value="${backend}" /> | |
68 | % endif |
|
68 | % endif | |
69 |
|
69 | |||
70 | <label for="repo_type_${backend}"> |
|
70 | <label for="repo_type_${backend}"> | |
71 | <i class="icon-${backend}" style="font-size: 16px"></i> |
|
71 | <i class="icon-${backend}" style="font-size: 16px"></i> | |
72 | ${backend.upper()} |
|
72 | ${backend.upper()} | |
73 | </label> |
|
73 | </label> | |
74 |
|
74 | |||
75 | % endfor |
|
75 | % endfor | |
76 |
|
76 | |||
77 |
|
77 | |||
78 | <span class="help-block">${_('Set the type of repository to create.')}</span> |
|
78 | <span class="help-block">${_('Set the type of repository to create.')}</span> | |
79 | </div> |
|
79 | </div> | |
80 | </div> |
|
80 | </div> | |
81 | <div class="field"> |
|
81 | <div class="field"> | |
82 | <div class="label"> |
|
82 | <div class="label"> | |
83 | <label for="repo_description">${_('Description')}:</label> |
|
83 | <label for="repo_description">${_('Description')}:</label> | |
84 | </div> |
|
84 | </div> | |
85 | <div class="textarea editor"> |
|
85 | <div class="textarea editor"> | |
86 | ${h.textarea('repo_description',cols=23,rows=5,class_="medium")} |
|
86 | ${h.textarea('repo_description',cols=23,rows=5,class_="medium")} | |
87 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> |
|
87 | <% metatags_url = h.literal('''<a href="#metatagsShow" onclick="$('#meta-tags-desc').toggle();return false">meta-tags</a>''') %> | |
88 | <span class="help-block"> |
|
88 | <span class="help-block"> | |
89 | % if c.visual.stylify_metatags: |
|
89 | % if c.visual.stylify_metatags: | |
90 | ${_('Plain text format with {metatags} support.').format(metatags=metatags_url)|n} |
|
90 | ${_('Plain text format with {metatags} support.').format(metatags=metatags_url)|n} | |
91 | % else: |
|
91 | % else: | |
92 | ${_('Plain text format.')} |
|
92 | ${_('Plain text format.')} | |
93 | % endif |
|
93 | % endif | |
94 | ${_('Add a README file for longer descriptions')} |
|
94 | ${_('Add a README file for longer descriptions')} | |
95 | </span> |
|
95 | </span> | |
96 | <span id="meta-tags-desc" style="display: none"> |
|
96 | <span id="meta-tags-desc" style="display: none"> | |
97 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> |
|
97 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> | |
98 | ${dt.metatags_help()} |
|
98 | ${dt.metatags_help()} | |
99 | </span> |
|
99 | </span> | |
100 | </div> |
|
100 | </div> | |
101 | </div> |
|
101 | </div> | |
102 | <div id="copy_perms" class="field"> |
|
102 | <div id="copy_perms" class="field"> | |
103 | <div class="label label-checkbox"> |
|
103 | <div class="label label-checkbox"> | |
104 | <label for="repo_copy_permissions">${_('Copy Parent Group Permissions')}:</label> |
|
104 | <label for="repo_copy_permissions">${_('Copy Parent Group Permissions')}:</label> | |
105 | </div> |
|
105 | </div> | |
106 | <div class="checkboxes"> |
|
106 | <div class="checkboxes"> | |
107 | ${h.checkbox('repo_copy_permissions', value="True", checked="checked")} |
|
107 | ${h.checkbox('repo_copy_permissions', value="True", checked="checked")} | |
108 | <span class="help-block">${_('Copy permissions from parent repository group.')}</span> |
|
108 | <span class="help-block">${_('Copy permissions from parent repository group.')}</span> | |
109 | </div> |
|
109 | </div> | |
110 | </div> |
|
110 | </div> | |
111 | <div class="field"> |
|
111 | <div class="field"> | |
112 | <div class="label label-checkbox"> |
|
112 | <div class="label label-checkbox"> | |
113 | <label for="repo_private">${_('Private Repository')}:</label> |
|
113 | <label for="repo_private">${_('Private Repository')}:</label> | |
114 | </div> |
|
114 | </div> | |
115 | <div class="checkboxes"> |
|
115 | <div class="checkboxes"> | |
116 | ${h.checkbox('repo_private',value="True")} |
|
116 | ${h.checkbox('repo_private',value="True")} | |
117 | <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span> |
|
117 | <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span> | |
118 | </div> |
|
118 | </div> | |
119 | </div> |
|
119 | </div> | |
120 | <div class="buttons"> |
|
120 | <div class="buttons"> | |
121 | ${h.submit('save',_('Create Repository'),class_="btn")} |
|
121 | ${h.submit('save',_('Create Repository'),class_="btn")} | |
122 | </div> |
|
122 | </div> | |
123 | </div> |
|
123 | </div> | |
124 | </div> |
|
124 | </div> | |
125 | <script> |
|
125 | <script> | |
126 | $(document).ready(function(){ |
|
126 | $(document).ready(function(){ | |
127 | var setCopyPermsOption = function(group_val){ |
|
127 | var setCopyPermsOption = function(group_val){ | |
128 | if(group_val != "-1"){ |
|
128 | if(group_val != "-1"){ | |
129 | $('#copy_perms').show() |
|
129 | $('#copy_perms').show() | |
130 | } |
|
130 | } | |
131 | else{ |
|
131 | else{ | |
132 | $('#copy_perms').hide(); |
|
132 | $('#copy_perms').hide(); | |
133 | } |
|
133 | } | |
134 | }; |
|
134 | }; | |
135 |
|
135 | |||
136 | $('#remote_clone_toggle').on('click', function(e){ |
|
136 | $('#remote_clone_toggle').on('click', function(e){ | |
137 | $('#remote_clone').show(); |
|
137 | $('#remote_clone').show(); | |
138 | e.preventDefault(); |
|
138 | e.preventDefault(); | |
139 | }); |
|
139 | }); | |
140 |
|
140 | |||
141 | if($('#remote_clone input').hasClass('error')){ |
|
141 | if($('#remote_clone input').hasClass('error')){ | |
142 | $('#remote_clone').show(); |
|
142 | $('#remote_clone').show(); | |
143 | } |
|
143 | } | |
144 | if($('#remote_clone input').val()){ |
|
144 | if($('#remote_clone input').val()){ | |
145 | $('#remote_clone').show(); |
|
145 | $('#remote_clone').show(); | |
146 | } |
|
146 | } | |
147 |
|
147 | |||
148 | $("#repo_group").select2({ |
|
148 | $("#repo_group").select2({ | |
149 | 'containerCssClass': "drop-menu", |
|
149 | 'containerCssClass': "drop-menu", | |
150 | 'dropdownCssClass': "drop-menu-dropdown", |
|
150 | 'dropdownCssClass': "drop-menu-dropdown", | |
151 | 'dropdownAutoWidth': true, |
|
151 | 'dropdownAutoWidth': true, | |
152 | 'width': "resolve" |
|
152 | 'width': "resolve" | |
153 | }); |
|
153 | }); | |
154 |
|
154 | |||
155 | setCopyPermsOption($('#repo_group').val()); |
|
155 | setCopyPermsOption($('#repo_group').val()); | |
156 | $("#repo_group").on("change", function(e) { |
|
156 | $("#repo_group").on("change", function(e) { | |
157 | setCopyPermsOption(e.val) |
|
157 | setCopyPermsOption(e.val) | |
158 | }); |
|
158 | }); | |
159 |
|
159 | |||
160 | $("#repo_type").select2({ |
|
|||
161 | 'containerCssClass': "drop-menu", |
|
|||
162 | 'dropdownCssClass': "drop-menu-dropdown", |
|
|||
163 | 'minimumResultsForSearch': -1, |
|
|||
164 | }); |
|
|||
165 |
|
||||
166 | $('#repo_name').focus(); |
|
160 | $('#repo_name').focus(); | |
167 |
|
161 | |||
168 | $('#select_my_group').on('click', function(e){ |
|
162 | $('#select_my_group').on('click', function(e){ | |
169 | e.preventDefault(); |
|
163 | e.preventDefault(); | |
170 | $("#repo_group").val($(this).data('personalGroupId')).trigger("change"); |
|
164 | $("#repo_group").val($(this).data('personalGroupId')).trigger("change"); | |
171 | }) |
|
165 | }) | |
172 |
|
166 | |||
173 | }) |
|
167 | }) | |
174 | </script> |
|
168 | </script> | |
175 | ${h.end_form()} |
|
169 | ${h.end_form()} |
General Comments 0
You need to be logged in to leave comments.
Login now