Show More
@@ -1,390 +1,380 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import pytest |
|
22 | 21 | |
|
23 | 22 | from rhodecode.model.comment import CommentsModel |
|
24 | 23 | from rhodecode.model.db import UserLog, User, ChangesetComment |
|
25 | 24 | from rhodecode.model.pull_request import PullRequestModel |
|
26 | 25 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
27 | 26 | from rhodecode.api.tests.utils import ( |
|
28 | 27 | build_data, api_call, assert_error, assert_ok) |
|
29 | 28 | |
|
30 | 29 | |
|
31 | 30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
32 | 31 | class TestCommentPullRequest(object): |
|
33 | 32 | finalizers = [] |
|
34 | 33 | |
|
35 | 34 | def teardown_method(self, method): |
|
36 | 35 | if self.finalizers: |
|
37 | 36 | for finalizer in self.finalizers: |
|
38 | 37 | finalizer() |
|
39 | 38 | self.finalizers = [] |
|
40 | 39 | |
|
41 | 40 | @pytest.mark.backends("git", "hg") |
|
42 | 41 | def test_api_comment_pull_request(self, pr_util, no_notifications): |
|
43 | 42 | pull_request = pr_util.create_pull_request() |
|
44 | 43 | pull_request_id = pull_request.pull_request_id |
|
45 | 44 | author = pull_request.user_id |
|
46 | 45 | repo = pull_request.target_repo.repo_id |
|
47 | 46 | id_, params = build_data( |
|
48 | 47 | self.apikey, 'comment_pull_request', |
|
49 | 48 | repoid=pull_request.target_repo.repo_name, |
|
50 | 49 | pullrequestid=pull_request.pull_request_id, |
|
51 | 50 | message='test message') |
|
52 | 51 | response = api_call(self.app, params) |
|
53 | 52 | pull_request = PullRequestModel().get(pull_request.pull_request_id) |
|
54 | 53 | |
|
55 | 54 | comments = CommentsModel().get_comments( |
|
56 | 55 | pull_request.target_repo.repo_id, pull_request=pull_request) |
|
57 | 56 | |
|
58 | 57 | expected = { |
|
59 | 58 | 'pull_request_id': pull_request.pull_request_id, |
|
60 | 59 | 'comment_id': comments[-1].comment_id, |
|
61 | 60 | 'status': {'given': None, 'was_changed': None} |
|
62 | 61 | } |
|
63 | 62 | assert_ok(id_, expected, response.body) |
|
64 | 63 | |
|
65 | 64 | journal = UserLog.query()\ |
|
66 | 65 | .filter(UserLog.user_id == author)\ |
|
67 | 66 | .filter(UserLog.repository_id == repo) \ |
|
68 | 67 | .order_by(UserLog.user_log_id.asc()) \ |
|
69 | 68 | .all() |
|
70 | 69 | assert journal[-1].action == 'repo.pull_request.comment.create' |
|
71 | 70 | |
|
72 | 71 | @pytest.mark.backends("git", "hg") |
|
73 | 72 | def test_api_comment_pull_request_with_extra_recipients(self, pr_util, user_util): |
|
74 | 73 | pull_request = pr_util.create_pull_request() |
|
75 | 74 | |
|
76 | 75 | user1 = user_util.create_user() |
|
77 | 76 | user1_id = user1.user_id |
|
78 | 77 | user2 = user_util.create_user() |
|
79 | 78 | user2_id = user2.user_id |
|
80 | 79 | |
|
81 | 80 | id_, params = build_data( |
|
82 | 81 | self.apikey, 'comment_pull_request', |
|
83 | 82 | repoid=pull_request.target_repo.repo_name, |
|
84 | 83 | pullrequestid=pull_request.pull_request_id, |
|
85 | 84 | message='test message', |
|
86 | 85 | extra_recipients=[user1.user_id, user2.username] |
|
87 | 86 | ) |
|
88 | 87 | response = api_call(self.app, params) |
|
89 | 88 | pull_request = PullRequestModel().get(pull_request.pull_request_id) |
|
90 | 89 | |
|
91 | 90 | comments = CommentsModel().get_comments( |
|
92 | 91 | pull_request.target_repo.repo_id, pull_request=pull_request) |
|
93 | 92 | |
|
94 | 93 | expected = { |
|
95 | 94 | 'pull_request_id': pull_request.pull_request_id, |
|
96 | 95 | 'comment_id': comments[-1].comment_id, |
|
97 | 96 | 'status': {'given': None, 'was_changed': None} |
|
98 | 97 | } |
|
99 | 98 | assert_ok(id_, expected, response.body) |
|
100 | 99 | # check user1/user2 inbox for notification |
|
101 | 100 | user1 = User.get(user1_id) |
|
102 | 101 | assert 1 == len(user1.notifications) |
|
103 | 102 | assert 'test message' in user1.notifications[0].notification.body |
|
104 | 103 | |
|
105 | 104 | user2 = User.get(user2_id) |
|
106 | 105 | assert 1 == len(user2.notifications) |
|
107 | 106 | assert 'test message' in user2.notifications[0].notification.body |
|
108 | 107 | |
|
109 | 108 | @pytest.mark.backends("git", "hg") |
|
110 | 109 | def test_api_comment_pull_request_change_status( |
|
111 | 110 | self, pr_util, no_notifications): |
|
112 | 111 | pull_request = pr_util.create_pull_request() |
|
113 | 112 | pull_request_id = pull_request.pull_request_id |
|
114 | 113 | id_, params = build_data( |
|
115 | 114 | self.apikey, 'comment_pull_request', |
|
116 | 115 | repoid=pull_request.target_repo.repo_name, |
|
117 | 116 | pullrequestid=pull_request.pull_request_id, |
|
118 | 117 | status='rejected') |
|
119 | 118 | response = api_call(self.app, params) |
|
120 | 119 | pull_request = PullRequestModel().get(pull_request_id) |
|
121 | 120 | |
|
122 | 121 | comments = CommentsModel().get_comments( |
|
123 | 122 | pull_request.target_repo.repo_id, pull_request=pull_request) |
|
124 | 123 | expected = { |
|
125 | 124 | 'pull_request_id': pull_request.pull_request_id, |
|
126 | 125 | 'comment_id': comments[-1].comment_id, |
|
127 | 126 | 'status': {'given': 'rejected', 'was_changed': True} |
|
128 | 127 | } |
|
129 | 128 | assert_ok(id_, expected, response.body) |
|
130 | 129 | |
|
131 | 130 | @pytest.mark.backends("git", "hg") |
|
132 | def test_api_comment_pull_request_change_status_with_specific_commit_id( | |
|
131 | def test_api_comment_pull_request_change_status_with_specific_commit_id_and_test_commit( | |
|
133 | 132 | self, pr_util, no_notifications): |
|
134 | 133 | pull_request = pr_util.create_pull_request() |
|
135 | 134 | pull_request_id = pull_request.pull_request_id |
|
136 | 135 | latest_commit_id = 'test_commit' |
|
136 | ||
|
137 | 137 | # inject additional revision, to fail test the status change on |
|
138 | 138 | # non-latest commit |
|
139 | 139 | pull_request.revisions = pull_request.revisions + ['test_commit'] |
|
140 | 140 | |
|
141 | 141 | id_, params = build_data( |
|
142 | 142 | self.apikey, 'comment_pull_request', |
|
143 | message='test-change-of-status-not-allowed', | |
|
143 | 144 | repoid=pull_request.target_repo.repo_name, |
|
144 | 145 | pullrequestid=pull_request.pull_request_id, |
|
145 | 146 | status='approved', commit_id=latest_commit_id) |
|
146 | 147 | response = api_call(self.app, params) |
|
147 | 148 | pull_request = PullRequestModel().get(pull_request_id) |
|
149 | comments = CommentsModel().get_comments( | |
|
150 | pull_request.target_repo.repo_id, pull_request=pull_request) | |
|
148 | 151 | |
|
149 | 152 | expected = { |
|
150 | 153 | 'pull_request_id': pull_request.pull_request_id, |
|
151 |
'comment_id': |
|
|
154 | 'comment_id': comments[-1].comment_id, | |
|
152 | 155 | 'status': {'given': 'approved', 'was_changed': False} |
|
153 | 156 | } |
|
154 | 157 | assert_ok(id_, expected, response.body) |
|
155 | 158 | |
|
156 | 159 | @pytest.mark.backends("git", "hg") |
|
157 | 160 | def test_api_comment_pull_request_change_status_with_specific_commit_id( |
|
158 | 161 | self, pr_util, no_notifications): |
|
159 | 162 | pull_request = pr_util.create_pull_request() |
|
160 | 163 | pull_request_id = pull_request.pull_request_id |
|
161 | 164 | latest_commit_id = pull_request.revisions[0] |
|
162 | 165 | |
|
163 | 166 | id_, params = build_data( |
|
164 | 167 | self.apikey, 'comment_pull_request', |
|
165 | 168 | repoid=pull_request.target_repo.repo_name, |
|
166 | 169 | pullrequestid=pull_request.pull_request_id, |
|
167 | 170 | status='approved', commit_id=latest_commit_id) |
|
168 | 171 | response = api_call(self.app, params) |
|
169 | 172 | pull_request = PullRequestModel().get(pull_request_id) |
|
170 | 173 | |
|
171 | 174 | comments = CommentsModel().get_comments( |
|
172 | 175 | pull_request.target_repo.repo_id, pull_request=pull_request) |
|
173 | 176 | expected = { |
|
174 | 177 | 'pull_request_id': pull_request.pull_request_id, |
|
175 | 178 | 'comment_id': comments[-1].comment_id, |
|
176 | 179 | 'status': {'given': 'approved', 'was_changed': True} |
|
177 | 180 | } |
|
178 | 181 | assert_ok(id_, expected, response.body) |
|
179 | 182 | |
|
180 | 183 | @pytest.mark.backends("git", "hg") |
|
181 | 184 | def test_api_comment_pull_request_missing_params_error(self, pr_util): |
|
182 | 185 | pull_request = pr_util.create_pull_request() |
|
183 | 186 | pull_request_id = pull_request.pull_request_id |
|
184 | 187 | pull_request_repo = pull_request.target_repo.repo_name |
|
185 | 188 | id_, params = build_data( |
|
186 | 189 | self.apikey, 'comment_pull_request', |
|
187 | 190 | repoid=pull_request_repo, |
|
188 | 191 | pullrequestid=pull_request_id) |
|
189 | 192 | response = api_call(self.app, params) |
|
190 | 193 | |
|
191 | 194 | expected = 'Both message and status parameters are missing. At least one is required.' |
|
192 | 195 | assert_error(id_, expected, given=response.body) |
|
193 | 196 | |
|
194 | 197 | @pytest.mark.backends("git", "hg") |
|
195 | 198 | def test_api_comment_pull_request_unknown_status_error(self, pr_util): |
|
196 | 199 | pull_request = pr_util.create_pull_request() |
|
197 | 200 | pull_request_id = pull_request.pull_request_id |
|
198 | 201 | pull_request_repo = pull_request.target_repo.repo_name |
|
199 | 202 | id_, params = build_data( |
|
200 | 203 | self.apikey, 'comment_pull_request', |
|
201 | 204 | repoid=pull_request_repo, |
|
202 | 205 | pullrequestid=pull_request_id, |
|
203 | 206 | status='42') |
|
204 | 207 | response = api_call(self.app, params) |
|
205 | 208 | |
|
206 | 209 | expected = 'Unknown comment status: `42`' |
|
207 | 210 | assert_error(id_, expected, given=response.body) |
|
208 | 211 | |
|
209 | 212 | @pytest.mark.backends("git", "hg") |
|
210 | 213 | def test_api_comment_pull_request_repo_error(self, pr_util): |
|
211 | 214 | pull_request = pr_util.create_pull_request() |
|
212 | 215 | id_, params = build_data( |
|
213 | 216 | self.apikey, 'comment_pull_request', |
|
214 | 217 | repoid=666, pullrequestid=pull_request.pull_request_id) |
|
215 | 218 | response = api_call(self.app, params) |
|
216 | 219 | |
|
217 | 220 | expected = 'repository `666` does not exist' |
|
218 | 221 | assert_error(id_, expected, given=response.body) |
|
219 | 222 | |
|
220 | 223 | @pytest.mark.backends("git", "hg") |
|
221 | 224 | def test_api_comment_pull_request_non_admin_with_userid_error(self, pr_util): |
|
222 | 225 | pull_request = pr_util.create_pull_request() |
|
223 | 226 | id_, params = build_data( |
|
224 | 227 | self.apikey_regular, 'comment_pull_request', |
|
225 | 228 | repoid=pull_request.target_repo.repo_name, |
|
226 | 229 | pullrequestid=pull_request.pull_request_id, |
|
227 | 230 | userid=TEST_USER_ADMIN_LOGIN) |
|
228 | 231 | response = api_call(self.app, params) |
|
229 | 232 | |
|
230 | 233 | expected = 'userid is not the same as your user' |
|
231 | 234 | assert_error(id_, expected, given=response.body) |
|
232 | 235 | |
|
233 | 236 | @pytest.mark.backends("git", "hg") |
|
234 | def test_api_comment_pull_request_non_admin_with_userid_error(self, pr_util): | |
|
235 | pull_request = pr_util.create_pull_request() | |
|
236 | id_, params = build_data( | |
|
237 | self.apikey_regular, 'comment_pull_request', | |
|
238 | repoid=pull_request.target_repo.repo_name, | |
|
239 | pullrequestid=pull_request.pull_request_id, | |
|
240 | userid=TEST_USER_ADMIN_LOGIN) | |
|
241 | response = api_call(self.app, params) | |
|
242 | ||
|
243 | expected = 'userid is not the same as your user' | |
|
244 | assert_error(id_, expected, given=response.body) | |
|
245 | ||
|
246 | @pytest.mark.backends("git", "hg") | |
|
247 | 237 | def test_api_comment_pull_request_wrong_commit_id_error(self, pr_util): |
|
248 | 238 | pull_request = pr_util.create_pull_request() |
|
249 | 239 | id_, params = build_data( |
|
250 | 240 | self.apikey_regular, 'comment_pull_request', |
|
251 | 241 | repoid=pull_request.target_repo.repo_name, |
|
252 | 242 | status='approved', |
|
253 | 243 | pullrequestid=pull_request.pull_request_id, |
|
254 | 244 | commit_id='XXX') |
|
255 | 245 | response = api_call(self.app, params) |
|
256 | 246 | |
|
257 | 247 | expected = 'Invalid commit_id `XXX` for this pull request.' |
|
258 | 248 | assert_error(id_, expected, given=response.body) |
|
259 | 249 | |
|
260 | 250 | @pytest.mark.backends("git", "hg") |
|
261 | 251 | def test_api_edit_comment(self, pr_util): |
|
262 | 252 | pull_request = pr_util.create_pull_request() |
|
263 | 253 | |
|
264 | 254 | id_, params = build_data( |
|
265 | 255 | self.apikey, |
|
266 | 256 | 'comment_pull_request', |
|
267 | 257 | repoid=pull_request.target_repo.repo_name, |
|
268 | 258 | pullrequestid=pull_request.pull_request_id, |
|
269 | 259 | message='test message', |
|
270 | 260 | ) |
|
271 | 261 | response = api_call(self.app, params) |
|
272 | 262 | json_response = response.json |
|
273 | 263 | comment_id = json_response['result']['comment_id'] |
|
274 | 264 | |
|
275 | 265 | message_after_edit = 'just message' |
|
276 | 266 | id_, params = build_data( |
|
277 | 267 | self.apikey, |
|
278 | 268 | 'edit_comment', |
|
279 | 269 | comment_id=comment_id, |
|
280 | 270 | message=message_after_edit, |
|
281 | 271 | version=0, |
|
282 | 272 | ) |
|
283 | 273 | response = api_call(self.app, params) |
|
284 | 274 | json_response = response.json |
|
285 | 275 | assert json_response['result']['version'] == 1 |
|
286 | 276 | |
|
287 | 277 | text_form_db = ChangesetComment.get(comment_id).text |
|
288 | 278 | assert message_after_edit == text_form_db |
|
289 | 279 | |
|
290 | 280 | @pytest.mark.backends("git", "hg") |
|
291 | def test_api_edit_comment_wrong_version(self, pr_util): | |
|
281 | def test_api_edit_comment_wrong_version_mismatch(self, pr_util): | |
|
292 | 282 | pull_request = pr_util.create_pull_request() |
|
293 | 283 | |
|
294 | 284 | id_, params = build_data( |
|
295 | 285 | self.apikey, 'comment_pull_request', |
|
296 | 286 | repoid=pull_request.target_repo.repo_name, |
|
297 | 287 | pullrequestid=pull_request.pull_request_id, |
|
298 | 288 | message='test message') |
|
299 | 289 | response = api_call(self.app, params) |
|
300 | 290 | json_response = response.json |
|
301 | 291 | comment_id = json_response['result']['comment_id'] |
|
302 | 292 | |
|
303 | 293 | message_after_edit = 'just message' |
|
304 | 294 | id_, params = build_data( |
|
305 |
self.apikey |
|
|
295 | self.apikey, | |
|
306 | 296 | 'edit_comment', |
|
307 | 297 | comment_id=comment_id, |
|
308 | 298 | message=message_after_edit, |
|
309 | 299 | version=1, |
|
310 | 300 | ) |
|
311 | 301 | response = api_call(self.app, params) |
|
312 | 302 | expected = 'comment ({}) version ({}) mismatch'.format(comment_id, 1) |
|
313 | 303 | assert_error(id_, expected, given=response.body) |
|
314 | 304 | |
|
315 | 305 | @pytest.mark.backends("git", "hg") |
|
316 | 306 | def test_api_edit_comment_wrong_version(self, pr_util): |
|
317 | 307 | pull_request = pr_util.create_pull_request() |
|
318 | 308 | |
|
319 | 309 | id_, params = build_data( |
|
320 | 310 | self.apikey, 'comment_pull_request', |
|
321 | 311 | repoid=pull_request.target_repo.repo_name, |
|
322 | 312 | pullrequestid=pull_request.pull_request_id, |
|
323 | 313 | message='test message') |
|
324 | 314 | response = api_call(self.app, params) |
|
325 | 315 | json_response = response.json |
|
326 | 316 | comment_id = json_response['result']['comment_id'] |
|
327 | 317 | |
|
328 | 318 | id_, params = build_data( |
|
329 | 319 | self.apikey, |
|
330 | 320 | 'edit_comment', |
|
331 | 321 | comment_id=comment_id, |
|
332 | 322 | message='', |
|
333 | 323 | version=0, |
|
334 | 324 | ) |
|
335 | 325 | response = api_call(self.app, params) |
|
336 |
expected = "comment ({}) can't be changed with empty string" |
|
|
326 | expected = f"comment ({comment_id}) can't be changed with empty string" | |
|
337 | 327 | assert_error(id_, expected, given=response.body) |
|
338 | 328 | |
|
339 | 329 | @pytest.mark.backends("git", "hg") |
|
340 | 330 | def test_api_edit_comment_wrong_user_set_by_non_admin(self, pr_util): |
|
341 | 331 | pull_request = pr_util.create_pull_request() |
|
342 | 332 | pull_request_id = pull_request.pull_request_id |
|
343 | 333 | id_, params = build_data( |
|
344 | 334 | self.apikey, |
|
345 | 335 | 'comment_pull_request', |
|
346 | 336 | repoid=pull_request.target_repo.repo_name, |
|
347 | 337 | pullrequestid=pull_request_id, |
|
348 | 338 | message='test message' |
|
349 | 339 | ) |
|
350 | 340 | response = api_call(self.app, params) |
|
351 | 341 | json_response = response.json |
|
352 | 342 | comment_id = json_response['result']['comment_id'] |
|
353 | 343 | |
|
354 | 344 | id_, params = build_data( |
|
355 | 345 | self.apikey_regular, |
|
356 | 346 | 'edit_comment', |
|
357 | 347 | comment_id=comment_id, |
|
358 | 348 | message='just message', |
|
359 | 349 | version=0, |
|
360 | 350 | userid=TEST_USER_ADMIN_LOGIN |
|
361 | 351 | ) |
|
362 | 352 | response = api_call(self.app, params) |
|
363 | 353 | expected = 'userid is not the same as your user' |
|
364 | 354 | assert_error(id_, expected, given=response.body) |
|
365 | 355 | |
|
366 | 356 | @pytest.mark.backends("git", "hg") |
|
367 | 357 | def test_api_edit_comment_wrong_user_with_permissions_to_edit_comment(self, pr_util): |
|
368 | 358 | pull_request = pr_util.create_pull_request() |
|
369 | 359 | pull_request_id = pull_request.pull_request_id |
|
370 | 360 | id_, params = build_data( |
|
371 | 361 | self.apikey, |
|
372 | 362 | 'comment_pull_request', |
|
373 | 363 | repoid=pull_request.target_repo.repo_name, |
|
374 | 364 | pullrequestid=pull_request_id, |
|
375 | 365 | message='test message' |
|
376 | 366 | ) |
|
377 | 367 | response = api_call(self.app, params) |
|
378 | 368 | json_response = response.json |
|
379 | 369 | comment_id = json_response['result']['comment_id'] |
|
380 | 370 | |
|
381 | 371 | id_, params = build_data( |
|
382 | 372 | self.apikey_regular, |
|
383 | 373 | 'edit_comment', |
|
384 | 374 | comment_id=comment_id, |
|
385 | 375 | message='just message', |
|
386 | 376 | version=0, |
|
387 | 377 | ) |
|
388 | 378 | response = api_call(self.app, params) |
|
389 | 379 | expected = "you don't have access to edit this comment" |
|
390 | 380 | assert_error(id_, expected, given=response.body) |
@@ -1,102 +1,101 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.db import Gist |
|
25 | 24 | from rhodecode.model.gist import GistModel |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_error, assert_ok, crash) |
|
28 | 27 | from rhodecode.tests.fixture import Fixture |
|
29 | 28 | |
|
30 | 29 | |
|
31 | 30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
32 | 31 | class TestApiCreateGist(object): |
|
33 | 32 | @pytest.mark.parametrize("lifetime, gist_type, gist_acl_level", [ |
|
34 | 33 | (10, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC), |
|
35 | 34 | (20, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PRIVATE), |
|
36 | 35 | (40, Gist.GIST_PRIVATE, Gist.ACL_LEVEL_PUBLIC), |
|
37 | 36 | (80, Gist.GIST_PRIVATE, Gist.ACL_LEVEL_PRIVATE), |
|
38 | 37 | ]) |
|
39 | 38 | def test_api_create_gist(self, lifetime, gist_type, gist_acl_level): |
|
40 | 39 | id_, params = build_data( |
|
41 | 40 | self.apikey_regular, 'create_gist', |
|
42 | 41 | lifetime=lifetime, |
|
43 | 42 | description='foobar-gist', |
|
44 | 43 | gist_type=gist_type, |
|
45 | 44 | acl_level=gist_acl_level, |
|
46 | 45 | files={'foobar_ąć': {'content': 'foo'}}) |
|
47 | 46 | response = api_call(self.app, params) |
|
48 | 47 | response_json = response.json |
|
49 | 48 | gist = response_json['result']['gist'] |
|
50 | 49 | expected = { |
|
51 | 50 | 'gist': { |
|
52 | 51 | 'access_id': gist['access_id'], |
|
53 | 52 | 'created_on': gist['created_on'], |
|
54 | 53 | 'modified_at': gist['modified_at'], |
|
55 | 54 | 'description': 'foobar-gist', |
|
56 | 55 | 'expires': gist['expires'], |
|
57 | 56 | 'gist_id': gist['gist_id'], |
|
58 | 57 | 'type': gist_type, |
|
59 | 58 | 'url': gist['url'], |
|
60 | 59 | # content is empty since we don't show it here |
|
61 | 60 | 'content': None, |
|
62 | 61 | 'acl_level': gist_acl_level, |
|
63 | 62 | }, |
|
64 | 63 | 'msg': 'created new gist' |
|
65 | 64 | } |
|
66 | 65 | try: |
|
67 | 66 | assert_ok(id_, expected, given=response.body) |
|
68 | 67 | finally: |
|
69 | 68 | Fixture().destroy_gists() |
|
70 | 69 | |
|
71 | 70 | @pytest.mark.parametrize("expected, lifetime, gist_type, gist_acl_level, files", [ |
|
72 | 71 | ({'gist_type': '"ups" is not one of private, public'}, |
|
73 | 72 | 10, 'ups', Gist.ACL_LEVEL_PUBLIC, {'f': {'content': 'f'}}), |
|
74 | 73 | |
|
75 | 74 | ({'lifetime': '-120 is less than minimum value -1'}, |
|
76 | 75 | -120, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC, {'f': {'content': 'f'}}), |
|
77 | 76 | |
|
78 | 77 | ({'0.content': 'Required'}, |
|
79 | 78 | 10, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC, {'f': {'x': 'f'}}), |
|
80 | 79 | ]) |
|
81 | 80 | def test_api_try_create_gist( |
|
82 | 81 | self, expected, lifetime, gist_type, gist_acl_level, files): |
|
83 | 82 | id_, params = build_data( |
|
84 | 83 | self.apikey_regular, 'create_gist', |
|
85 | 84 | lifetime=lifetime, |
|
86 | 85 | description='foobar-gist', |
|
87 | 86 | gist_type=gist_type, |
|
88 | 87 | acl_level=gist_acl_level, |
|
89 | 88 | files=files) |
|
90 | 89 | response = api_call(self.app, params) |
|
91 | 90 | |
|
92 | 91 | try: |
|
93 | 92 | assert_error(id_, expected, given=response.body) |
|
94 | 93 | finally: |
|
95 | 94 | Fixture().destroy_gists() |
|
96 | 95 | |
|
97 | 96 | @mock.patch.object(GistModel, 'create', crash) |
|
98 | 97 | def test_api_create_gist_exception_occurred(self): |
|
99 | 98 | id_, params = build_data(self.apikey_regular, 'create_gist', files={}) |
|
100 | 99 | response = api_call(self.app, params) |
|
101 | 100 | expected = 'failed to create gist' |
|
102 | 101 | assert_error(id_, expected, given=response.body) |
@@ -1,368 +1,367 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import pytest |
|
22 | 21 | |
|
23 | 22 | from rhodecode.model.db import User |
|
24 | 23 | from rhodecode.model.pull_request import PullRequestModel |
|
25 | 24 | from rhodecode.model.repo import RepoModel |
|
26 | 25 | from rhodecode.model.user import UserModel |
|
27 | 26 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN |
|
28 | 27 | from rhodecode.api.tests.utils import build_data, api_call, assert_error |
|
29 | 28 | |
|
30 | 29 | |
|
31 | 30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
32 | 31 | class TestCreatePullRequestApi(object): |
|
33 | 32 | finalizers = [] |
|
34 | 33 | |
|
35 | 34 | def teardown_method(self, method): |
|
36 | 35 | if self.finalizers: |
|
37 | 36 | for finalizer in self.finalizers: |
|
38 | 37 | finalizer() |
|
39 | 38 | self.finalizers = [] |
|
40 | 39 | |
|
41 | 40 | def test_create_with_wrong_data(self): |
|
42 | 41 | required_data = { |
|
43 | 42 | 'source_repo': 'tests/source_repo', |
|
44 | 43 | 'target_repo': 'tests/target_repo', |
|
45 | 44 | 'source_ref': 'branch:default:initial', |
|
46 | 45 | 'target_ref': 'branch:default:new-feature', |
|
47 | 46 | } |
|
48 | 47 | for key in required_data: |
|
49 | 48 | data = required_data.copy() |
|
50 | 49 | data.pop(key) |
|
51 | 50 | id_, params = build_data( |
|
52 | 51 | self.apikey, 'create_pull_request', **data) |
|
53 | 52 | response = api_call(self.app, params) |
|
54 | 53 | |
|
55 | 54 | expected = 'Missing non optional `{}` arg in JSON DATA'.format(key) |
|
56 | 55 | assert_error(id_, expected, given=response.body) |
|
57 | 56 | |
|
58 | 57 | @pytest.mark.backends("git", "hg") |
|
59 | 58 | @pytest.mark.parametrize('source_ref', [ |
|
60 | 59 | 'bookmarg:default:initial' |
|
61 | 60 | ]) |
|
62 | 61 | def test_create_with_wrong_refs_data(self, backend, source_ref): |
|
63 | 62 | |
|
64 | 63 | data = self._prepare_data(backend) |
|
65 | 64 | data['source_ref'] = source_ref |
|
66 | 65 | |
|
67 | 66 | id_, params = build_data( |
|
68 | 67 | self.apikey_regular, 'create_pull_request', **data) |
|
69 | 68 | |
|
70 | 69 | response = api_call(self.app, params) |
|
71 | 70 | |
|
72 | 71 | expected = "Ref `{}` type is not allowed. " \ |
|
73 | 72 | "Only:['bookmark', 'book', 'tag', 'branch'] " \ |
|
74 | 73 | "are possible.".format(source_ref) |
|
75 | 74 | assert_error(id_, expected, given=response.body) |
|
76 | 75 | |
|
77 | 76 | @pytest.mark.backends("git", "hg") |
|
78 | 77 | def test_create_with_correct_data(self, backend): |
|
79 | 78 | data = self._prepare_data(backend) |
|
80 | 79 | RepoModel().revoke_user_permission( |
|
81 | 80 | self.source.repo_name, User.DEFAULT_USER) |
|
82 | 81 | id_, params = build_data( |
|
83 | 82 | self.apikey_regular, 'create_pull_request', **data) |
|
84 | 83 | response = api_call(self.app, params) |
|
85 | 84 | expected_message = "Created new pull request `{title}`".format( |
|
86 | 85 | title=data['title']) |
|
87 | 86 | result = response.json |
|
88 | 87 | assert result['error'] is None |
|
89 | 88 | assert result['result']['msg'] == expected_message |
|
90 | 89 | pull_request_id = result['result']['pull_request_id'] |
|
91 | 90 | pull_request = PullRequestModel().get(pull_request_id) |
|
92 | 91 | assert pull_request.title == data['title'] |
|
93 | 92 | assert pull_request.description == data['description'] |
|
94 | 93 | assert pull_request.source_ref == data['source_ref'] |
|
95 | 94 | assert pull_request.target_ref == data['target_ref'] |
|
96 | 95 | assert pull_request.source_repo.repo_name == data['source_repo'] |
|
97 | 96 | assert pull_request.target_repo.repo_name == data['target_repo'] |
|
98 | 97 | assert pull_request.revisions == [self.commit_ids['change']] |
|
99 | 98 | assert len(pull_request.reviewers) == 1 |
|
100 | 99 | |
|
101 | 100 | @pytest.mark.backends("git", "hg") |
|
102 | 101 | def test_create_with_empty_description(self, backend): |
|
103 | 102 | data = self._prepare_data(backend) |
|
104 | 103 | data.pop('description') |
|
105 | 104 | id_, params = build_data( |
|
106 | 105 | self.apikey_regular, 'create_pull_request', **data) |
|
107 | 106 | response = api_call(self.app, params) |
|
108 | 107 | expected_message = "Created new pull request `{title}`".format( |
|
109 | 108 | title=data['title']) |
|
110 | 109 | result = response.json |
|
111 | 110 | assert result['error'] is None |
|
112 | 111 | assert result['result']['msg'] == expected_message |
|
113 | 112 | pull_request_id = result['result']['pull_request_id'] |
|
114 | 113 | pull_request = PullRequestModel().get(pull_request_id) |
|
115 | 114 | assert pull_request.description == '' |
|
116 | 115 | |
|
117 | 116 | @pytest.mark.backends("git", "hg") |
|
118 | 117 | def test_create_with_empty_title(self, backend): |
|
119 | 118 | data = self._prepare_data(backend) |
|
120 | 119 | data.pop('title') |
|
121 | 120 | id_, params = build_data( |
|
122 | 121 | self.apikey_regular, 'create_pull_request', **data) |
|
123 | 122 | response = api_call(self.app, params) |
|
124 | 123 | result = response.json |
|
125 | 124 | pull_request_id = result['result']['pull_request_id'] |
|
126 | 125 | pull_request = PullRequestModel().get(pull_request_id) |
|
127 | 126 | data['ref'] = backend.default_branch_name |
|
128 | 127 | title = '{source_repo}#{ref} to {target_repo}'.format(**data) |
|
129 | 128 | assert pull_request.title == title |
|
130 | 129 | |
|
131 | 130 | @pytest.mark.backends("git", "hg") |
|
132 | 131 | def test_create_with_reviewers_specified_by_names( |
|
133 | 132 | self, backend, no_notifications): |
|
134 | 133 | data = self._prepare_data(backend) |
|
135 | 134 | reviewers = [ |
|
136 | 135 | {'username': TEST_USER_REGULAR_LOGIN, |
|
137 | 136 | 'reasons': ['{} added manually'.format(TEST_USER_REGULAR_LOGIN)]}, |
|
138 | 137 | {'username': TEST_USER_ADMIN_LOGIN, |
|
139 | 138 | 'reasons': ['{} added manually'.format(TEST_USER_ADMIN_LOGIN)], |
|
140 | 139 | 'mandatory': True}, |
|
141 | 140 | ] |
|
142 | 141 | data['reviewers'] = reviewers |
|
143 | 142 | |
|
144 | 143 | id_, params = build_data( |
|
145 | 144 | self.apikey_regular, 'create_pull_request', **data) |
|
146 | 145 | response = api_call(self.app, params) |
|
147 | 146 | |
|
148 | 147 | expected_message = "Created new pull request `{title}`".format( |
|
149 | 148 | title=data['title']) |
|
150 | 149 | result = response.json |
|
151 | 150 | assert result['error'] is None |
|
152 | 151 | assert result['result']['msg'] == expected_message |
|
153 | 152 | pull_request_id = result['result']['pull_request_id'] |
|
154 | 153 | pull_request = PullRequestModel().get(pull_request_id) |
|
155 | 154 | |
|
156 | 155 | actual_reviewers = [] |
|
157 | 156 | for rev in pull_request.reviewers: |
|
158 | 157 | entry = { |
|
159 | 158 | 'username': rev.user.username, |
|
160 | 159 | 'reasons': rev.reasons, |
|
161 | 160 | } |
|
162 | 161 | if rev.mandatory: |
|
163 | 162 | entry['mandatory'] = rev.mandatory |
|
164 | 163 | actual_reviewers.append(entry) |
|
165 | 164 | |
|
166 | 165 | owner_username = pull_request.target_repo.user.username |
|
167 | 166 | for spec_reviewer in reviewers[::]: |
|
168 | 167 | # default reviewer will be added who is an owner of the repo |
|
169 | 168 | # this get's overridden by a add owner to reviewers rule |
|
170 | 169 | if spec_reviewer['username'] == owner_username: |
|
171 | 170 | spec_reviewer['reasons'] = [u'Default reviewer', u'Repository owner'] |
|
172 | 171 | # since owner is more important, we don't inherit mandatory flag |
|
173 | 172 | del spec_reviewer['mandatory'] |
|
174 | 173 | |
|
175 | 174 | assert sorted(actual_reviewers, key=lambda e: e['username']) \ |
|
176 | 175 | == sorted(reviewers, key=lambda e: e['username']) |
|
177 | 176 | |
|
178 | 177 | @pytest.mark.backends("git", "hg") |
|
179 | 178 | def test_create_with_reviewers_specified_by_ids( |
|
180 | 179 | self, backend, no_notifications): |
|
181 | 180 | data = self._prepare_data(backend) |
|
182 | 181 | reviewers = [ |
|
183 | 182 | {'username': UserModel().get_by_username( |
|
184 | 183 | TEST_USER_REGULAR_LOGIN).user_id, |
|
185 | 184 | 'reasons': ['added manually']}, |
|
186 | 185 | {'username': UserModel().get_by_username( |
|
187 | 186 | TEST_USER_ADMIN_LOGIN).user_id, |
|
188 | 187 | 'reasons': ['added manually']}, |
|
189 | 188 | ] |
|
190 | 189 | |
|
191 | 190 | data['reviewers'] = reviewers |
|
192 | 191 | id_, params = build_data( |
|
193 | 192 | self.apikey_regular, 'create_pull_request', **data) |
|
194 | 193 | response = api_call(self.app, params) |
|
195 | 194 | |
|
196 | 195 | expected_message = "Created new pull request `{title}`".format( |
|
197 | 196 | title=data['title']) |
|
198 | 197 | result = response.json |
|
199 | 198 | assert result['error'] is None |
|
200 | 199 | assert result['result']['msg'] == expected_message |
|
201 | 200 | pull_request_id = result['result']['pull_request_id'] |
|
202 | 201 | pull_request = PullRequestModel().get(pull_request_id) |
|
203 | 202 | |
|
204 | 203 | actual_reviewers = [] |
|
205 | 204 | for rev in pull_request.reviewers: |
|
206 | 205 | entry = { |
|
207 | 206 | 'username': rev.user.user_id, |
|
208 | 207 | 'reasons': rev.reasons, |
|
209 | 208 | } |
|
210 | 209 | if rev.mandatory: |
|
211 | 210 | entry['mandatory'] = rev.mandatory |
|
212 | 211 | actual_reviewers.append(entry) |
|
213 | 212 | |
|
214 | 213 | owner_user_id = pull_request.target_repo.user.user_id |
|
215 | 214 | for spec_reviewer in reviewers[::]: |
|
216 | 215 | # default reviewer will be added who is an owner of the repo |
|
217 | 216 | # this get's overridden by a add owner to reviewers rule |
|
218 | 217 | if spec_reviewer['username'] == owner_user_id: |
|
219 | 218 | spec_reviewer['reasons'] = [u'Default reviewer', u'Repository owner'] |
|
220 | 219 | |
|
221 | 220 | assert sorted(actual_reviewers, key=lambda e: e['username']) \ |
|
222 | 221 | == sorted(reviewers, key=lambda e: e['username']) |
|
223 | 222 | |
|
224 | 223 | @pytest.mark.backends("git", "hg") |
|
225 | 224 | def test_create_fails_when_the_reviewer_is_not_found(self, backend): |
|
226 | 225 | data = self._prepare_data(backend) |
|
227 | 226 | data['reviewers'] = [{'username': 'somebody'}] |
|
228 | 227 | id_, params = build_data( |
|
229 | 228 | self.apikey_regular, 'create_pull_request', **data) |
|
230 | 229 | response = api_call(self.app, params) |
|
231 | 230 | expected_message = 'user `somebody` does not exist' |
|
232 | 231 | assert_error(id_, expected_message, given=response.body) |
|
233 | 232 | |
|
234 | 233 | @pytest.mark.backends("git", "hg") |
|
235 | 234 | def test_cannot_create_with_reviewers_in_wrong_format(self, backend): |
|
236 | 235 | data = self._prepare_data(backend) |
|
237 | 236 | reviewers = ','.join([TEST_USER_REGULAR_LOGIN, TEST_USER_ADMIN_LOGIN]) |
|
238 | 237 | data['reviewers'] = reviewers |
|
239 | 238 | id_, params = build_data( |
|
240 | 239 | self.apikey_regular, 'create_pull_request', **data) |
|
241 | 240 | response = api_call(self.app, params) |
|
242 | 241 | expected_message = {u'': '"test_regular,test_admin" is not iterable'} |
|
243 | 242 | assert_error(id_, expected_message, given=response.body) |
|
244 | 243 | |
|
245 | 244 | @pytest.mark.backends("git", "hg") |
|
246 | 245 | def test_create_with_no_commit_hashes(self, backend): |
|
247 | 246 | data = self._prepare_data(backend) |
|
248 | 247 | expected_source_ref = data['source_ref'] |
|
249 | 248 | expected_target_ref = data['target_ref'] |
|
250 | 249 | data['source_ref'] = 'branch:{}'.format(backend.default_branch_name) |
|
251 | 250 | data['target_ref'] = 'branch:{}'.format(backend.default_branch_name) |
|
252 | 251 | id_, params = build_data( |
|
253 | 252 | self.apikey_regular, 'create_pull_request', **data) |
|
254 | 253 | response = api_call(self.app, params) |
|
255 | 254 | expected_message = "Created new pull request `{title}`".format( |
|
256 | 255 | title=data['title']) |
|
257 | 256 | result = response.json |
|
258 | 257 | assert result['result']['msg'] == expected_message |
|
259 | 258 | pull_request_id = result['result']['pull_request_id'] |
|
260 | 259 | pull_request = PullRequestModel().get(pull_request_id) |
|
261 | 260 | assert pull_request.source_ref == expected_source_ref |
|
262 | 261 | assert pull_request.target_ref == expected_target_ref |
|
263 | 262 | |
|
264 | 263 | @pytest.mark.backends("git", "hg") |
|
265 | 264 | @pytest.mark.parametrize("data_key", ["source_repo", "target_repo"]) |
|
266 | 265 | def test_create_fails_with_wrong_repo(self, backend, data_key): |
|
267 | 266 | repo_name = 'fake-repo' |
|
268 | 267 | data = self._prepare_data(backend) |
|
269 | 268 | data[data_key] = repo_name |
|
270 | 269 | id_, params = build_data( |
|
271 | 270 | self.apikey_regular, 'create_pull_request', **data) |
|
272 | 271 | response = api_call(self.app, params) |
|
273 | 272 | expected_message = 'repository `{}` does not exist'.format(repo_name) |
|
274 | 273 | assert_error(id_, expected_message, given=response.body) |
|
275 | 274 | |
|
276 | 275 | @pytest.mark.backends("git", "hg") |
|
277 | 276 | @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"]) |
|
278 | 277 | def test_create_fails_with_non_existing_branch(self, backend, data_key): |
|
279 | 278 | branch_name = 'test-branch' |
|
280 | 279 | data = self._prepare_data(backend) |
|
281 | 280 | data[data_key] = "branch:{}".format(branch_name) |
|
282 | 281 | id_, params = build_data( |
|
283 | 282 | self.apikey_regular, 'create_pull_request', **data) |
|
284 | 283 | response = api_call(self.app, params) |
|
285 | 284 | expected_message = 'The specified value:{type}:`{name}` ' \ |
|
286 | 285 | 'does not exist, or is not allowed.'.format(type='branch', |
|
287 | 286 | name=branch_name) |
|
288 | 287 | assert_error(id_, expected_message, given=response.body) |
|
289 | 288 | |
|
290 | 289 | @pytest.mark.backends("git", "hg") |
|
291 | 290 | @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"]) |
|
292 | 291 | def test_create_fails_with_ref_in_a_wrong_format(self, backend, data_key): |
|
293 | 292 | data = self._prepare_data(backend) |
|
294 | 293 | ref = 'stange-ref' |
|
295 | 294 | data[data_key] = ref |
|
296 | 295 | id_, params = build_data( |
|
297 | 296 | self.apikey_regular, 'create_pull_request', **data) |
|
298 | 297 | response = api_call(self.app, params) |
|
299 | 298 | expected_message = ( |
|
300 | 299 | 'Ref `{ref}` given in a wrong format. Please check the API' |
|
301 | 300 | ' documentation for more details'.format(ref=ref)) |
|
302 | 301 | assert_error(id_, expected_message, given=response.body) |
|
303 | 302 | |
|
304 | 303 | @pytest.mark.backends("git", "hg") |
|
305 | 304 | @pytest.mark.parametrize("data_key", ["source_ref", "target_ref"]) |
|
306 | 305 | def test_create_fails_with_non_existing_ref(self, backend, data_key): |
|
307 | 306 | commit_id = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10' |
|
308 | 307 | ref = self._get_full_ref(backend, commit_id) |
|
309 | 308 | data = self._prepare_data(backend) |
|
310 | 309 | data[data_key] = ref |
|
311 | 310 | id_, params = build_data( |
|
312 | 311 | self.apikey_regular, 'create_pull_request', **data) |
|
313 | 312 | response = api_call(self.app, params) |
|
314 | 313 | expected_message = 'Ref `{}` does not exist'.format(ref) |
|
315 | 314 | assert_error(id_, expected_message, given=response.body) |
|
316 | 315 | |
|
317 | 316 | @pytest.mark.backends("git", "hg") |
|
318 | 317 | def test_create_fails_when_no_revisions(self, backend): |
|
319 | 318 | data = self._prepare_data(backend, source_head='initial') |
|
320 | 319 | id_, params = build_data( |
|
321 | 320 | self.apikey_regular, 'create_pull_request', **data) |
|
322 | 321 | response = api_call(self.app, params) |
|
323 | 322 | expected_message = 'no commits found for merge between specified references' |
|
324 | 323 | assert_error(id_, expected_message, given=response.body) |
|
325 | 324 | |
|
326 | 325 | @pytest.mark.backends("git", "hg") |
|
327 | 326 | def test_create_fails_when_no_permissions(self, backend): |
|
328 | 327 | data = self._prepare_data(backend) |
|
329 | 328 | RepoModel().revoke_user_permission( |
|
330 | 329 | self.source.repo_name, self.test_user) |
|
331 | 330 | RepoModel().revoke_user_permission( |
|
332 | 331 | self.source.repo_name, User.DEFAULT_USER) |
|
333 | 332 | |
|
334 | 333 | id_, params = build_data( |
|
335 | 334 | self.apikey_regular, 'create_pull_request', **data) |
|
336 | 335 | response = api_call(self.app, params) |
|
337 | 336 | expected_message = 'repository `{}` does not exist'.format( |
|
338 | 337 | self.source.repo_name) |
|
339 | 338 | assert_error(id_, expected_message, given=response.body) |
|
340 | 339 | |
|
341 | 340 | def _prepare_data( |
|
342 | 341 | self, backend, source_head='change', target_head='initial'): |
|
343 | 342 | commits = [ |
|
344 | 343 | {'message': 'initial'}, |
|
345 | 344 | {'message': 'change'}, |
|
346 | 345 | {'message': 'new-feature', 'parents': ['initial']}, |
|
347 | 346 | ] |
|
348 | 347 | self.commit_ids = backend.create_master_repo(commits) |
|
349 | 348 | self.source = backend.create_repo(heads=[source_head]) |
|
350 | 349 | self.target = backend.create_repo(heads=[target_head]) |
|
351 | 350 | |
|
352 | 351 | data = { |
|
353 | 352 | 'source_repo': self.source.repo_name, |
|
354 | 353 | 'target_repo': self.target.repo_name, |
|
355 | 354 | 'source_ref': self._get_full_ref( |
|
356 | 355 | backend, self.commit_ids[source_head]), |
|
357 | 356 | 'target_ref': self._get_full_ref( |
|
358 | 357 | backend, self.commit_ids[target_head]), |
|
359 | 358 | 'title': 'Test PR 1', |
|
360 | 359 | 'description': 'Test' |
|
361 | 360 | } |
|
362 | 361 | RepoModel().grant_user_permission( |
|
363 | 362 | self.source.repo_name, self.TEST_USER_LOGIN, 'repository.read') |
|
364 | 363 | return data |
|
365 | 364 | |
|
366 | 365 | def _get_full_ref(self, backend, commit_id): |
|
367 | 366 | return 'branch:{branch}:{commit_id}'.format( |
|
368 | 367 | branch=backend.default_branch_name, commit_id=commit_id) |
@@ -1,350 +1,348 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | import json | |
|
22 | ||
|
23 | 20 | import mock |
|
24 | 21 | import pytest |
|
25 | 22 | |
|
26 | from rhodecode.lib.utils2 import safe_unicode | |
|
27 | 23 | from rhodecode.lib.vcs import settings |
|
28 | 24 | from rhodecode.model.meta import Session |
|
29 | 25 | from rhodecode.model.repo import RepoModel |
|
30 | 26 | from rhodecode.model.user import UserModel |
|
31 | 27 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
32 | 28 | from rhodecode.api.tests.utils import ( |
|
33 | 29 | build_data, api_call, assert_ok, assert_error, crash) |
|
34 | 30 | from rhodecode.tests.fixture import Fixture |
|
31 | from rhodecode.lib.ext_json import json | |
|
32 | from rhodecode.lib.str_utils import safe_str | |
|
35 | 33 | |
|
36 | 34 | |
|
37 | 35 | fixture = Fixture() |
|
38 | 36 | |
|
39 | 37 | |
|
40 | 38 | @pytest.mark.usefixtures("testuser_api", "app") |
|
41 | 39 | class TestCreateRepo(object): |
|
42 | 40 | |
|
43 | 41 | @pytest.mark.parametrize('given, expected_name, expected_exc', [ |
|
44 | 42 | ('api repo-1', 'api-repo-1', False), |
|
45 | 43 | ('api-repo 1-ąć', 'api-repo-1-ąć', False), |
|
46 | 44 | (u'unicode-ąć', u'unicode-ąć', False), |
|
47 | 45 | ('some repo v1.2', 'some-repo-v1.2', False), |
|
48 | 46 | ('v2.0', 'v2.0', False), |
|
49 | 47 | ]) |
|
50 | 48 | def test_api_create_repo(self, backend, given, expected_name, expected_exc): |
|
51 | 49 | |
|
52 | 50 | id_, params = build_data( |
|
53 | 51 | self.apikey, |
|
54 | 52 | 'create_repo', |
|
55 | 53 | repo_name=given, |
|
56 | 54 | owner=TEST_USER_ADMIN_LOGIN, |
|
57 | 55 | repo_type=backend.alias, |
|
58 | 56 | ) |
|
59 | 57 | response = api_call(self.app, params) |
|
60 | 58 | |
|
61 | 59 | ret = { |
|
62 | 60 | 'msg': 'Created new repository `%s`' % (expected_name,), |
|
63 | 61 | 'success': True, |
|
64 | 62 | 'task': None, |
|
65 | 63 | } |
|
66 | 64 | expected = ret |
|
67 | 65 | assert_ok(id_, expected, given=response.body) |
|
68 | 66 | |
|
69 |
repo = RepoModel().get_by_repo_name(safe_ |
|
|
67 | repo = RepoModel().get_by_repo_name(safe_str(expected_name)) | |
|
70 | 68 | assert repo is not None |
|
71 | 69 | |
|
72 | 70 | id_, params = build_data(self.apikey, 'get_repo', repoid=expected_name) |
|
73 | 71 | response = api_call(self.app, params) |
|
74 | 72 | body = json.loads(response.body) |
|
75 | 73 | |
|
76 | 74 | assert body['result']['enable_downloads'] is False |
|
77 | 75 | assert body['result']['enable_locking'] is False |
|
78 | 76 | assert body['result']['enable_statistics'] is False |
|
79 | 77 | |
|
80 |
fixture.destroy_repo(safe_ |
|
|
78 | fixture.destroy_repo(safe_str(expected_name)) | |
|
81 | 79 | |
|
82 | 80 | def test_api_create_restricted_repo_type(self, backend): |
|
83 | 81 | repo_name = 'api-repo-type-{0}'.format(backend.alias) |
|
84 | 82 | id_, params = build_data( |
|
85 | 83 | self.apikey, |
|
86 | 84 | 'create_repo', |
|
87 | 85 | repo_name=repo_name, |
|
88 | 86 | owner=TEST_USER_ADMIN_LOGIN, |
|
89 | 87 | repo_type=backend.alias, |
|
90 | 88 | ) |
|
91 | 89 | git_backend = settings.BACKENDS['git'] |
|
92 | 90 | with mock.patch( |
|
93 | 91 | 'rhodecode.lib.vcs.settings.BACKENDS', {'git': git_backend}): |
|
94 | 92 | response = api_call(self.app, params) |
|
95 | 93 | |
|
96 | 94 | repo = RepoModel().get_by_repo_name(repo_name) |
|
97 | 95 | |
|
98 | 96 | if backend.alias == 'git': |
|
99 | 97 | assert repo is not None |
|
100 | 98 | expected = { |
|
101 | 99 | 'msg': 'Created new repository `{0}`'.format(repo_name,), |
|
102 | 100 | 'success': True, |
|
103 | 101 | 'task': None, |
|
104 | 102 | } |
|
105 | 103 | assert_ok(id_, expected, given=response.body) |
|
106 | 104 | else: |
|
107 | 105 | assert repo is None |
|
108 | 106 | |
|
109 | 107 | fixture.destroy_repo(repo_name) |
|
110 | 108 | |
|
111 | 109 | def test_api_create_repo_with_booleans(self, backend): |
|
112 | 110 | repo_name = 'api-repo-2' |
|
113 | 111 | id_, params = build_data( |
|
114 | 112 | self.apikey, |
|
115 | 113 | 'create_repo', |
|
116 | 114 | repo_name=repo_name, |
|
117 | 115 | owner=TEST_USER_ADMIN_LOGIN, |
|
118 | 116 | repo_type=backend.alias, |
|
119 | 117 | enable_statistics=True, |
|
120 | 118 | enable_locking=True, |
|
121 | 119 | enable_downloads=True |
|
122 | 120 | ) |
|
123 | 121 | response = api_call(self.app, params) |
|
124 | 122 | |
|
125 | 123 | repo = RepoModel().get_by_repo_name(repo_name) |
|
126 | 124 | |
|
127 | 125 | assert repo is not None |
|
128 | 126 | ret = { |
|
129 | 127 | 'msg': 'Created new repository `%s`' % (repo_name,), |
|
130 | 128 | 'success': True, |
|
131 | 129 | 'task': None, |
|
132 | 130 | } |
|
133 | 131 | expected = ret |
|
134 | 132 | assert_ok(id_, expected, given=response.body) |
|
135 | 133 | |
|
136 | 134 | id_, params = build_data(self.apikey, 'get_repo', repoid=repo_name) |
|
137 | 135 | response = api_call(self.app, params) |
|
138 | 136 | body = json.loads(response.body) |
|
139 | 137 | |
|
140 | 138 | assert body['result']['enable_downloads'] is True |
|
141 | 139 | assert body['result']['enable_locking'] is True |
|
142 | 140 | assert body['result']['enable_statistics'] is True |
|
143 | 141 | |
|
144 | 142 | fixture.destroy_repo(repo_name) |
|
145 | 143 | |
|
146 | 144 | def test_api_create_repo_in_group(self, backend): |
|
147 | 145 | repo_group_name = 'my_gr' |
|
148 | 146 | # create the parent |
|
149 | 147 | fixture.create_repo_group(repo_group_name) |
|
150 | 148 | |
|
151 | 149 | repo_name = '%s/api-repo-gr' % (repo_group_name,) |
|
152 | 150 | id_, params = build_data( |
|
153 | 151 | self.apikey, 'create_repo', |
|
154 | 152 | repo_name=repo_name, |
|
155 | 153 | owner=TEST_USER_ADMIN_LOGIN, |
|
156 | 154 | repo_type=backend.alias,) |
|
157 | 155 | response = api_call(self.app, params) |
|
158 | 156 | repo = RepoModel().get_by_repo_name(repo_name) |
|
159 | 157 | assert repo is not None |
|
160 | 158 | assert repo.group is not None |
|
161 | 159 | |
|
162 | 160 | ret = { |
|
163 | 161 | 'msg': 'Created new repository `%s`' % (repo_name,), |
|
164 | 162 | 'success': True, |
|
165 | 163 | 'task': None, |
|
166 | 164 | } |
|
167 | 165 | expected = ret |
|
168 | 166 | assert_ok(id_, expected, given=response.body) |
|
169 | 167 | fixture.destroy_repo(repo_name) |
|
170 | 168 | fixture.destroy_repo_group(repo_group_name) |
|
171 | 169 | |
|
172 | 170 | def test_create_repo_in_group_that_doesnt_exist(self, backend, user_util): |
|
173 | 171 | repo_group_name = 'fake_group' |
|
174 | 172 | |
|
175 | 173 | repo_name = '%s/api-repo-gr' % (repo_group_name,) |
|
176 | 174 | id_, params = build_data( |
|
177 | 175 | self.apikey, 'create_repo', |
|
178 | 176 | repo_name=repo_name, |
|
179 | 177 | owner=TEST_USER_ADMIN_LOGIN, |
|
180 | 178 | repo_type=backend.alias,) |
|
181 | 179 | response = api_call(self.app, params) |
|
182 | 180 | |
|
183 | 181 | expected = {'repo_group': 'Repository group `{}` does not exist'.format( |
|
184 | 182 | repo_group_name)} |
|
185 | 183 | assert_error(id_, expected, given=response.body) |
|
186 | 184 | |
|
187 | 185 | def test_api_create_repo_unknown_owner(self, backend): |
|
188 | 186 | repo_name = 'api-repo-2' |
|
189 | 187 | owner = 'i-dont-exist' |
|
190 | 188 | id_, params = build_data( |
|
191 | 189 | self.apikey, 'create_repo', |
|
192 | 190 | repo_name=repo_name, |
|
193 | 191 | owner=owner, |
|
194 | 192 | repo_type=backend.alias) |
|
195 | 193 | response = api_call(self.app, params) |
|
196 | 194 | expected = 'user `%s` does not exist' % (owner,) |
|
197 | 195 | assert_error(id_, expected, given=response.body) |
|
198 | 196 | |
|
199 | 197 | def test_api_create_repo_dont_specify_owner(self, backend): |
|
200 | 198 | repo_name = 'api-repo-3' |
|
201 | 199 | id_, params = build_data( |
|
202 | 200 | self.apikey, 'create_repo', |
|
203 | 201 | repo_name=repo_name, |
|
204 | 202 | repo_type=backend.alias) |
|
205 | 203 | response = api_call(self.app, params) |
|
206 | 204 | |
|
207 | 205 | repo = RepoModel().get_by_repo_name(repo_name) |
|
208 | 206 | assert repo is not None |
|
209 | 207 | ret = { |
|
210 | 208 | 'msg': 'Created new repository `%s`' % (repo_name,), |
|
211 | 209 | 'success': True, |
|
212 | 210 | 'task': None, |
|
213 | 211 | } |
|
214 | 212 | expected = ret |
|
215 | 213 | assert_ok(id_, expected, given=response.body) |
|
216 | 214 | fixture.destroy_repo(repo_name) |
|
217 | 215 | |
|
218 | 216 | def test_api_create_repo_by_non_admin(self, backend): |
|
219 | 217 | repo_name = 'api-repo-4' |
|
220 | 218 | id_, params = build_data( |
|
221 | 219 | self.apikey_regular, 'create_repo', |
|
222 | 220 | repo_name=repo_name, |
|
223 | 221 | repo_type=backend.alias) |
|
224 | 222 | response = api_call(self.app, params) |
|
225 | 223 | |
|
226 | 224 | repo = RepoModel().get_by_repo_name(repo_name) |
|
227 | 225 | assert repo is not None |
|
228 | 226 | ret = { |
|
229 | 227 | 'msg': 'Created new repository `%s`' % (repo_name,), |
|
230 | 228 | 'success': True, |
|
231 | 229 | 'task': None, |
|
232 | 230 | } |
|
233 | 231 | expected = ret |
|
234 | 232 | assert_ok(id_, expected, given=response.body) |
|
235 | 233 | fixture.destroy_repo(repo_name) |
|
236 | 234 | |
|
237 | 235 | def test_api_create_repo_by_non_admin_specify_owner(self, backend): |
|
238 | 236 | repo_name = 'api-repo-5' |
|
239 | 237 | owner = 'i-dont-exist' |
|
240 | 238 | id_, params = build_data( |
|
241 | 239 | self.apikey_regular, 'create_repo', |
|
242 | 240 | repo_name=repo_name, |
|
243 | 241 | repo_type=backend.alias, |
|
244 | 242 | owner=owner) |
|
245 | 243 | response = api_call(self.app, params) |
|
246 | 244 | |
|
247 | 245 | expected = 'Only RhodeCode super-admin can specify `owner` param' |
|
248 | 246 | assert_error(id_, expected, given=response.body) |
|
249 | 247 | fixture.destroy_repo(repo_name) |
|
250 | 248 | |
|
251 | 249 | def test_api_create_repo_by_non_admin_no_parent_group_perms(self, backend): |
|
252 | 250 | repo_group_name = 'no-access' |
|
253 | 251 | fixture.create_repo_group(repo_group_name) |
|
254 | 252 | repo_name = 'no-access/api-repo' |
|
255 | 253 | |
|
256 | 254 | id_, params = build_data( |
|
257 | 255 | self.apikey_regular, 'create_repo', |
|
258 | 256 | repo_name=repo_name, |
|
259 | 257 | repo_type=backend.alias) |
|
260 | 258 | response = api_call(self.app, params) |
|
261 | 259 | |
|
262 | 260 | expected = {'repo_group': 'Repository group `{}` does not exist'.format( |
|
263 | 261 | repo_group_name)} |
|
264 | 262 | assert_error(id_, expected, given=response.body) |
|
265 | 263 | fixture.destroy_repo_group(repo_group_name) |
|
266 | 264 | fixture.destroy_repo(repo_name) |
|
267 | 265 | |
|
268 | 266 | def test_api_create_repo_non_admin_no_permission_to_create_to_root_level( |
|
269 | 267 | self, backend, user_util): |
|
270 | 268 | |
|
271 | 269 | regular_user = user_util.create_user() |
|
272 | 270 | regular_user_api_key = regular_user.api_key |
|
273 | 271 | |
|
274 | 272 | usr = UserModel().get_by_username(regular_user.username) |
|
275 | 273 | usr.inherit_default_permissions = False |
|
276 | 274 | Session().add(usr) |
|
277 | 275 | |
|
278 | 276 | repo_name = backend.new_repo_name() |
|
279 | 277 | id_, params = build_data( |
|
280 | 278 | regular_user_api_key, 'create_repo', |
|
281 | 279 | repo_name=repo_name, |
|
282 | 280 | repo_type=backend.alias) |
|
283 | 281 | response = api_call(self.app, params) |
|
284 | 282 | expected = { |
|
285 | 283 | "repo_name": "You do not have the permission to " |
|
286 | 284 | "store repositories in the root location."} |
|
287 | 285 | assert_error(id_, expected, given=response.body) |
|
288 | 286 | |
|
289 | 287 | def test_api_create_repo_exists(self, backend): |
|
290 | 288 | repo_name = backend.repo_name |
|
291 | 289 | id_, params = build_data( |
|
292 | 290 | self.apikey, 'create_repo', |
|
293 | 291 | repo_name=repo_name, |
|
294 | 292 | owner=TEST_USER_ADMIN_LOGIN, |
|
295 | 293 | repo_type=backend.alias,) |
|
296 | 294 | response = api_call(self.app, params) |
|
297 | 295 | expected = { |
|
298 | 296 | 'unique_repo_name': 'Repository with name `{}` already exists'.format( |
|
299 | 297 | repo_name)} |
|
300 | 298 | assert_error(id_, expected, given=response.body) |
|
301 | 299 | |
|
302 | 300 | @mock.patch.object(RepoModel, 'create', crash) |
|
303 | 301 | def test_api_create_repo_exception_occurred(self, backend): |
|
304 | 302 | repo_name = 'api-repo-6' |
|
305 | 303 | id_, params = build_data( |
|
306 | 304 | self.apikey, 'create_repo', |
|
307 | 305 | repo_name=repo_name, |
|
308 | 306 | owner=TEST_USER_ADMIN_LOGIN, |
|
309 | 307 | repo_type=backend.alias,) |
|
310 | 308 | response = api_call(self.app, params) |
|
311 | 309 | expected = 'failed to create repository `%s`' % (repo_name,) |
|
312 | 310 | assert_error(id_, expected, given=response.body) |
|
313 | 311 | |
|
314 | 312 | @pytest.mark.parametrize('parent_group, dirty_name, expected_name', [ |
|
315 | 313 | (None, 'foo bar x', 'foo-bar-x'), |
|
316 | 314 | ('foo', '/foo//bar x', 'foo/bar-x'), |
|
317 | 315 | ('foo-bar', 'foo-bar //bar x', 'foo-bar/bar-x'), |
|
318 | 316 | ]) |
|
319 | 317 | def test_create_repo_with_extra_slashes_in_name( |
|
320 | 318 | self, backend, parent_group, dirty_name, expected_name): |
|
321 | 319 | |
|
322 | 320 | if parent_group: |
|
323 | 321 | gr = fixture.create_repo_group(parent_group) |
|
324 | 322 | assert gr.group_name == parent_group |
|
325 | 323 | |
|
326 | 324 | id_, params = build_data( |
|
327 | 325 | self.apikey, 'create_repo', |
|
328 | 326 | repo_name=dirty_name, |
|
329 | 327 | repo_type=backend.alias, |
|
330 | 328 | owner=TEST_USER_ADMIN_LOGIN,) |
|
331 | 329 | response = api_call(self.app, params) |
|
332 | 330 | expected ={ |
|
333 | 331 | "msg": "Created new repository `{}`".format(expected_name), |
|
334 | 332 | "task": None, |
|
335 | 333 | "success": True |
|
336 | 334 | } |
|
337 | 335 | assert_ok(id_, expected, response.body) |
|
338 | 336 | |
|
339 | 337 | repo = RepoModel().get_by_repo_name(expected_name) |
|
340 | 338 | assert repo is not None |
|
341 | 339 | |
|
342 | 340 | expected = { |
|
343 | 341 | 'msg': 'Created new repository `%s`' % (expected_name,), |
|
344 | 342 | 'success': True, |
|
345 | 343 | 'task': None, |
|
346 | 344 | } |
|
347 | 345 | assert_ok(id_, expected, given=response.body) |
|
348 | 346 | fixture.destroy_repo(expected_name) |
|
349 | 347 | if parent_group: |
|
350 | 348 | fixture.destroy_repo_group(parent_group) |
@@ -1,289 +1,288 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.meta import Session |
|
25 | 24 | from rhodecode.model.repo_group import RepoGroupModel |
|
26 | 25 | from rhodecode.model.user import UserModel |
|
27 | 26 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
28 | 27 | from rhodecode.api.tests.utils import ( |
|
29 | 28 | build_data, api_call, assert_ok, assert_error, crash) |
|
30 | 29 | from rhodecode.tests.fixture import Fixture |
|
31 | 30 | |
|
32 | 31 | |
|
33 | 32 | fixture = Fixture() |
|
34 | 33 | |
|
35 | 34 | |
|
36 | 35 | @pytest.mark.usefixtures("testuser_api", "app") |
|
37 | 36 | class TestCreateRepoGroup(object): |
|
38 | 37 | def test_api_create_repo_group(self): |
|
39 | 38 | repo_group_name = 'api-repo-group' |
|
40 | 39 | |
|
41 | 40 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
42 | 41 | assert repo_group is None |
|
43 | 42 | |
|
44 | 43 | id_, params = build_data( |
|
45 | 44 | self.apikey, 'create_repo_group', |
|
46 | 45 | group_name=repo_group_name, |
|
47 | 46 | owner=TEST_USER_ADMIN_LOGIN,) |
|
48 | 47 | response = api_call(self.app, params) |
|
49 | 48 | |
|
50 | 49 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
51 | 50 | assert repo_group is not None |
|
52 | 51 | ret = { |
|
53 | 52 | 'msg': 'Created new repo group `%s`' % (repo_group_name,), |
|
54 | 53 | 'repo_group': repo_group.get_api_data() |
|
55 | 54 | } |
|
56 | 55 | expected = ret |
|
57 | 56 | try: |
|
58 | 57 | assert_ok(id_, expected, given=response.body) |
|
59 | 58 | finally: |
|
60 | 59 | fixture.destroy_repo_group(repo_group_name) |
|
61 | 60 | |
|
62 | 61 | def test_api_create_repo_group_in_another_group(self): |
|
63 | 62 | repo_group_name = 'api-repo-group' |
|
64 | 63 | |
|
65 | 64 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
66 | 65 | assert repo_group is None |
|
67 | 66 | # create the parent |
|
68 | 67 | fixture.create_repo_group(repo_group_name) |
|
69 | 68 | |
|
70 | 69 | full_repo_group_name = repo_group_name+'/'+repo_group_name |
|
71 | 70 | id_, params = build_data( |
|
72 | 71 | self.apikey, 'create_repo_group', |
|
73 | 72 | group_name=full_repo_group_name, |
|
74 | 73 | owner=TEST_USER_ADMIN_LOGIN, |
|
75 | 74 | copy_permissions=True) |
|
76 | 75 | response = api_call(self.app, params) |
|
77 | 76 | |
|
78 | 77 | repo_group = RepoGroupModel.cls.get_by_group_name(full_repo_group_name) |
|
79 | 78 | assert repo_group is not None |
|
80 | 79 | ret = { |
|
81 | 80 | 'msg': 'Created new repo group `%s`' % (full_repo_group_name,), |
|
82 | 81 | 'repo_group': repo_group.get_api_data() |
|
83 | 82 | } |
|
84 | 83 | expected = ret |
|
85 | 84 | try: |
|
86 | 85 | assert_ok(id_, expected, given=response.body) |
|
87 | 86 | finally: |
|
88 | 87 | fixture.destroy_repo_group(full_repo_group_name) |
|
89 | 88 | fixture.destroy_repo_group(repo_group_name) |
|
90 | 89 | |
|
91 | 90 | def test_api_create_repo_group_in_another_group_not_existing(self): |
|
92 | 91 | repo_group_name = 'api-repo-group-no' |
|
93 | 92 | |
|
94 | 93 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
95 | 94 | assert repo_group is None |
|
96 | 95 | |
|
97 | 96 | full_repo_group_name = repo_group_name+'/'+repo_group_name |
|
98 | 97 | id_, params = build_data( |
|
99 | 98 | self.apikey, 'create_repo_group', |
|
100 | 99 | group_name=full_repo_group_name, |
|
101 | 100 | owner=TEST_USER_ADMIN_LOGIN, |
|
102 | 101 | copy_permissions=True) |
|
103 | 102 | response = api_call(self.app, params) |
|
104 | 103 | expected = { |
|
105 | 104 | 'repo_group': |
|
106 | 105 | 'Parent repository group `{}` does not exist'.format( |
|
107 | 106 | repo_group_name)} |
|
108 | 107 | assert_error(id_, expected, given=response.body) |
|
109 | 108 | |
|
110 | 109 | def test_api_create_repo_group_that_exists(self): |
|
111 | 110 | repo_group_name = 'api-repo-group' |
|
112 | 111 | |
|
113 | 112 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
114 | 113 | assert repo_group is None |
|
115 | 114 | |
|
116 | 115 | fixture.create_repo_group(repo_group_name) |
|
117 | 116 | id_, params = build_data( |
|
118 | 117 | self.apikey, 'create_repo_group', |
|
119 | 118 | group_name=repo_group_name, |
|
120 | 119 | owner=TEST_USER_ADMIN_LOGIN,) |
|
121 | 120 | response = api_call(self.app, params) |
|
122 | 121 | expected = { |
|
123 | 122 | 'unique_repo_group_name': |
|
124 | 123 | 'Repository group with name `{}` already exists'.format( |
|
125 | 124 | repo_group_name)} |
|
126 | 125 | try: |
|
127 | 126 | assert_error(id_, expected, given=response.body) |
|
128 | 127 | finally: |
|
129 | 128 | fixture.destroy_repo_group(repo_group_name) |
|
130 | 129 | |
|
131 | 130 | def test_api_create_repo_group_regular_user_wit_root_location_perms( |
|
132 | 131 | self, user_util): |
|
133 | 132 | regular_user = user_util.create_user() |
|
134 | 133 | regular_user_api_key = regular_user.api_key |
|
135 | 134 | |
|
136 | 135 | repo_group_name = 'api-repo-group-by-regular-user' |
|
137 | 136 | |
|
138 | 137 | usr = UserModel().get_by_username(regular_user.username) |
|
139 | 138 | usr.inherit_default_permissions = False |
|
140 | 139 | Session().add(usr) |
|
141 | 140 | |
|
142 | 141 | UserModel().grant_perm( |
|
143 | 142 | regular_user.username, 'hg.repogroup.create.true') |
|
144 | 143 | Session().commit() |
|
145 | 144 | |
|
146 | 145 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
147 | 146 | assert repo_group is None |
|
148 | 147 | |
|
149 | 148 | id_, params = build_data( |
|
150 | 149 | regular_user_api_key, 'create_repo_group', |
|
151 | 150 | group_name=repo_group_name) |
|
152 | 151 | response = api_call(self.app, params) |
|
153 | 152 | |
|
154 | 153 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
155 | 154 | assert repo_group is not None |
|
156 | 155 | expected = { |
|
157 | 156 | 'msg': 'Created new repo group `%s`' % (repo_group_name,), |
|
158 | 157 | 'repo_group': repo_group.get_api_data() |
|
159 | 158 | } |
|
160 | 159 | try: |
|
161 | 160 | assert_ok(id_, expected, given=response.body) |
|
162 | 161 | finally: |
|
163 | 162 | fixture.destroy_repo_group(repo_group_name) |
|
164 | 163 | |
|
165 | 164 | def test_api_create_repo_group_regular_user_with_admin_perms_to_parent( |
|
166 | 165 | self, user_util): |
|
167 | 166 | |
|
168 | 167 | repo_group_name = 'api-repo-group-parent' |
|
169 | 168 | |
|
170 | 169 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
171 | 170 | assert repo_group is None |
|
172 | 171 | # create the parent |
|
173 | 172 | fixture.create_repo_group(repo_group_name) |
|
174 | 173 | |
|
175 | 174 | # user perms |
|
176 | 175 | regular_user = user_util.create_user() |
|
177 | 176 | regular_user_api_key = regular_user.api_key |
|
178 | 177 | |
|
179 | 178 | usr = UserModel().get_by_username(regular_user.username) |
|
180 | 179 | usr.inherit_default_permissions = False |
|
181 | 180 | Session().add(usr) |
|
182 | 181 | |
|
183 | 182 | RepoGroupModel().grant_user_permission( |
|
184 | 183 | repo_group_name, regular_user.username, 'group.admin') |
|
185 | 184 | Session().commit() |
|
186 | 185 | |
|
187 | 186 | full_repo_group_name = repo_group_name + '/' + repo_group_name |
|
188 | 187 | id_, params = build_data( |
|
189 | 188 | regular_user_api_key, 'create_repo_group', |
|
190 | 189 | group_name=full_repo_group_name) |
|
191 | 190 | response = api_call(self.app, params) |
|
192 | 191 | |
|
193 | 192 | repo_group = RepoGroupModel.cls.get_by_group_name(full_repo_group_name) |
|
194 | 193 | assert repo_group is not None |
|
195 | 194 | expected = { |
|
196 | 195 | 'msg': 'Created new repo group `{}`'.format(full_repo_group_name), |
|
197 | 196 | 'repo_group': repo_group.get_api_data() |
|
198 | 197 | } |
|
199 | 198 | try: |
|
200 | 199 | assert_ok(id_, expected, given=response.body) |
|
201 | 200 | finally: |
|
202 | 201 | fixture.destroy_repo_group(full_repo_group_name) |
|
203 | 202 | fixture.destroy_repo_group(repo_group_name) |
|
204 | 203 | |
|
205 | 204 | def test_api_create_repo_group_regular_user_no_permission_to_create_to_root_level(self): |
|
206 | 205 | repo_group_name = 'api-repo-group' |
|
207 | 206 | |
|
208 | 207 | id_, params = build_data( |
|
209 | 208 | self.apikey_regular, 'create_repo_group', |
|
210 | 209 | group_name=repo_group_name) |
|
211 | 210 | response = api_call(self.app, params) |
|
212 | 211 | |
|
213 | 212 | expected = { |
|
214 | 213 | 'repo_group': |
|
215 | 214 | u'You do not have the permission to store ' |
|
216 | 215 | u'repository groups in the root location.'} |
|
217 | 216 | assert_error(id_, expected, given=response.body) |
|
218 | 217 | |
|
219 | 218 | def test_api_create_repo_group_regular_user_no_parent_group_perms(self): |
|
220 | 219 | repo_group_name = 'api-repo-group-regular-user' |
|
221 | 220 | |
|
222 | 221 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
223 | 222 | assert repo_group is None |
|
224 | 223 | # create the parent |
|
225 | 224 | fixture.create_repo_group(repo_group_name) |
|
226 | 225 | |
|
227 | 226 | full_repo_group_name = repo_group_name+'/'+repo_group_name |
|
228 | 227 | |
|
229 | 228 | id_, params = build_data( |
|
230 | 229 | self.apikey_regular, 'create_repo_group', |
|
231 | 230 | group_name=full_repo_group_name) |
|
232 | 231 | response = api_call(self.app, params) |
|
233 | 232 | |
|
234 | 233 | expected = { |
|
235 | 234 | 'repo_group': |
|
236 | 235 | u"You do not have the permissions to store " |
|
237 | 236 | u"repository groups inside repository group `{}`".format(repo_group_name)} |
|
238 | 237 | try: |
|
239 | 238 | assert_error(id_, expected, given=response.body) |
|
240 | 239 | finally: |
|
241 | 240 | fixture.destroy_repo_group(repo_group_name) |
|
242 | 241 | |
|
243 | 242 | def test_api_create_repo_group_regular_user_no_permission_to_specify_owner( |
|
244 | 243 | self): |
|
245 | 244 | repo_group_name = 'api-repo-group' |
|
246 | 245 | |
|
247 | 246 | id_, params = build_data( |
|
248 | 247 | self.apikey_regular, 'create_repo_group', |
|
249 | 248 | group_name=repo_group_name, |
|
250 | 249 | owner=TEST_USER_ADMIN_LOGIN,) |
|
251 | 250 | response = api_call(self.app, params) |
|
252 | 251 | |
|
253 | 252 | expected = "Only RhodeCode super-admin can specify `owner` param" |
|
254 | 253 | assert_error(id_, expected, given=response.body) |
|
255 | 254 | |
|
256 | 255 | @mock.patch.object(RepoGroupModel, 'create', crash) |
|
257 | 256 | def test_api_create_repo_group_exception_occurred(self): |
|
258 | 257 | repo_group_name = 'api-repo-group' |
|
259 | 258 | |
|
260 | 259 | repo_group = RepoGroupModel.cls.get_by_group_name(repo_group_name) |
|
261 | 260 | assert repo_group is None |
|
262 | 261 | |
|
263 | 262 | id_, params = build_data( |
|
264 | 263 | self.apikey, 'create_repo_group', |
|
265 | 264 | group_name=repo_group_name, |
|
266 | 265 | owner=TEST_USER_ADMIN_LOGIN,) |
|
267 | 266 | response = api_call(self.app, params) |
|
268 | 267 | expected = 'failed to create repo group `%s`' % (repo_group_name,) |
|
269 | 268 | assert_error(id_, expected, given=response.body) |
|
270 | 269 | |
|
271 | 270 | def test_create_group_with_extra_slashes_in_name(self, user_util): |
|
272 | 271 | existing_repo_group = user_util.create_repo_group() |
|
273 | 272 | dirty_group_name = '//{}//group2//'.format( |
|
274 | 273 | existing_repo_group.group_name) |
|
275 | 274 | cleaned_group_name = '{}/group2'.format( |
|
276 | 275 | existing_repo_group.group_name) |
|
277 | 276 | |
|
278 | 277 | id_, params = build_data( |
|
279 | 278 | self.apikey, 'create_repo_group', |
|
280 | 279 | group_name=dirty_group_name, |
|
281 | 280 | owner=TEST_USER_ADMIN_LOGIN,) |
|
282 | 281 | response = api_call(self.app, params) |
|
283 | 282 | repo_group = RepoGroupModel.cls.get_by_group_name(cleaned_group_name) |
|
284 | 283 | expected = { |
|
285 | 284 | 'msg': 'Created new repo group `%s`' % (cleaned_group_name,), |
|
286 | 285 | 'repo_group': repo_group.get_api_data() |
|
287 | 286 | } |
|
288 | 287 | assert_ok(id_, expected, given=response.body) |
|
289 | 288 | fixture.destroy_repo_group(cleaned_group_name) |
@@ -1,207 +1,206 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.lib.auth import check_password |
|
25 | 24 | from rhodecode.model.user import UserModel |
|
26 | 25 | from rhodecode.tests import ( |
|
27 | 26 | TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_EMAIL) |
|
28 | 27 | from rhodecode.api.tests.utils import ( |
|
29 | 28 | build_data, api_call, assert_ok, assert_error, jsonify, crash) |
|
30 | 29 | from rhodecode.tests.fixture import Fixture |
|
31 | 30 | from rhodecode.model.db import RepoGroup |
|
32 | 31 | |
|
33 | 32 | |
|
34 | 33 | # TODO: mikhail: remove fixture from here |
|
35 | 34 | fixture = Fixture() |
|
36 | 35 | |
|
37 | 36 | |
|
38 | 37 | @pytest.mark.usefixtures("testuser_api", "app") |
|
39 | 38 | class TestCreateUser(object): |
|
40 | 39 | def test_api_create_existing_user(self): |
|
41 | 40 | id_, params = build_data( |
|
42 | 41 | self.apikey, 'create_user', |
|
43 | 42 | username=TEST_USER_ADMIN_LOGIN, |
|
44 | 43 | email='test@foo.com', |
|
45 | 44 | password='trololo') |
|
46 | 45 | response = api_call(self.app, params) |
|
47 | 46 | |
|
48 | 47 | expected = "user `%s` already exist" % (TEST_USER_ADMIN_LOGIN,) |
|
49 | 48 | assert_error(id_, expected, given=response.body) |
|
50 | 49 | |
|
51 | 50 | def test_api_create_user_with_existing_email(self): |
|
52 | 51 | id_, params = build_data( |
|
53 | 52 | self.apikey, 'create_user', |
|
54 | 53 | username=TEST_USER_ADMIN_LOGIN + 'new', |
|
55 | 54 | email=TEST_USER_REGULAR_EMAIL, |
|
56 | 55 | password='trololo') |
|
57 | 56 | response = api_call(self.app, params) |
|
58 | 57 | |
|
59 | 58 | expected = "email `%s` already exist" % (TEST_USER_REGULAR_EMAIL,) |
|
60 | 59 | assert_error(id_, expected, given=response.body) |
|
61 | 60 | |
|
62 | 61 | def test_api_create_user_with_wrong_username(self): |
|
63 | 62 | bad_username = '<> HELLO WORLD <>' |
|
64 | 63 | id_, params = build_data( |
|
65 | 64 | self.apikey, 'create_user', |
|
66 | 65 | username=bad_username, |
|
67 | 66 | email='new@email.com', |
|
68 | 67 | password='trololo') |
|
69 | 68 | response = api_call(self.app, params) |
|
70 | 69 | |
|
71 | 70 | expected = {'username': |
|
72 | 71 | "Username may only contain alphanumeric characters " |
|
73 | 72 | "underscores, periods or dashes and must begin with " |
|
74 | 73 | "alphanumeric character or underscore"} |
|
75 | 74 | assert_error(id_, expected, given=response.body) |
|
76 | 75 | |
|
77 | 76 | def test_api_create_user(self): |
|
78 | 77 | username = 'test_new_api_user' |
|
79 | 78 | email = username + "@foo.com" |
|
80 | 79 | |
|
81 | 80 | id_, params = build_data( |
|
82 | 81 | self.apikey, 'create_user', |
|
83 | 82 | username=username, |
|
84 | 83 | email=email, |
|
85 | 84 | description='CTO of Things', |
|
86 | 85 | password='example') |
|
87 | 86 | response = api_call(self.app, params) |
|
88 | 87 | |
|
89 | 88 | usr = UserModel().get_by_username(username) |
|
90 | 89 | ret = { |
|
91 | 90 | 'msg': 'created new user `%s`' % (username,), |
|
92 | 91 | 'user': jsonify(usr.get_api_data(include_secrets=True)), |
|
93 | 92 | } |
|
94 | 93 | try: |
|
95 | 94 | expected = ret |
|
96 | 95 | assert check_password('example', usr.password) |
|
97 | 96 | assert_ok(id_, expected, given=response.body) |
|
98 | 97 | finally: |
|
99 | 98 | fixture.destroy_user(usr.user_id) |
|
100 | 99 | |
|
101 | 100 | def test_api_create_user_without_password(self): |
|
102 | 101 | username = 'test_new_api_user_passwordless' |
|
103 | 102 | email = username + "@foo.com" |
|
104 | 103 | |
|
105 | 104 | id_, params = build_data( |
|
106 | 105 | self.apikey, 'create_user', |
|
107 | 106 | username=username, |
|
108 | 107 | email=email) |
|
109 | 108 | response = api_call(self.app, params) |
|
110 | 109 | |
|
111 | 110 | usr = UserModel().get_by_username(username) |
|
112 | 111 | ret = { |
|
113 | 112 | 'msg': 'created new user `%s`' % (username,), |
|
114 | 113 | 'user': jsonify(usr.get_api_data(include_secrets=True)), |
|
115 | 114 | } |
|
116 | 115 | try: |
|
117 | 116 | expected = ret |
|
118 | 117 | assert_ok(id_, expected, given=response.body) |
|
119 | 118 | finally: |
|
120 | 119 | fixture.destroy_user(usr.user_id) |
|
121 | 120 | |
|
122 | 121 | def test_api_create_user_with_extern_name(self): |
|
123 | 122 | username = 'test_new_api_user_passwordless' |
|
124 | 123 | email = username + "@foo.com" |
|
125 | 124 | |
|
126 | 125 | id_, params = build_data( |
|
127 | 126 | self.apikey, 'create_user', |
|
128 | 127 | username=username, |
|
129 | 128 | email=email, extern_name='rhodecode') |
|
130 | 129 | response = api_call(self.app, params) |
|
131 | 130 | |
|
132 | 131 | usr = UserModel().get_by_username(username) |
|
133 | 132 | ret = { |
|
134 | 133 | 'msg': 'created new user `%s`' % (username,), |
|
135 | 134 | 'user': jsonify(usr.get_api_data(include_secrets=True)), |
|
136 | 135 | } |
|
137 | 136 | try: |
|
138 | 137 | expected = ret |
|
139 | 138 | assert_ok(id_, expected, given=response.body) |
|
140 | 139 | finally: |
|
141 | 140 | fixture.destroy_user(usr.user_id) |
|
142 | 141 | |
|
143 | 142 | def test_api_create_user_with_password_change(self): |
|
144 | 143 | username = 'test_new_api_user_password_change' |
|
145 | 144 | email = username + "@foo.com" |
|
146 | 145 | |
|
147 | 146 | id_, params = build_data( |
|
148 | 147 | self.apikey, 'create_user', |
|
149 | 148 | username=username, |
|
150 | 149 | email=email, extern_name='rhodecode', |
|
151 | 150 | force_password_change=True) |
|
152 | 151 | response = api_call(self.app, params) |
|
153 | 152 | |
|
154 | 153 | usr = UserModel().get_by_username(username) |
|
155 | 154 | ret = { |
|
156 | 155 | 'msg': 'created new user `%s`' % (username,), |
|
157 | 156 | 'user': jsonify(usr.get_api_data(include_secrets=True)), |
|
158 | 157 | } |
|
159 | 158 | try: |
|
160 | 159 | expected = ret |
|
161 | 160 | assert_ok(id_, expected, given=response.body) |
|
162 | 161 | finally: |
|
163 | 162 | fixture.destroy_user(usr.user_id) |
|
164 | 163 | |
|
165 | 164 | def test_api_create_user_with_personal_repo_group(self): |
|
166 | 165 | username = 'test_new_api_user_personal_group' |
|
167 | 166 | email = username + "@foo.com" |
|
168 | 167 | |
|
169 | 168 | id_, params = build_data( |
|
170 | 169 | self.apikey, 'create_user', |
|
171 | 170 | username=username, |
|
172 | 171 | email=email, extern_name='rhodecode', |
|
173 | 172 | create_personal_repo_group=True) |
|
174 | 173 | response = api_call(self.app, params) |
|
175 | 174 | |
|
176 | 175 | usr = UserModel().get_by_username(username) |
|
177 | 176 | ret = { |
|
178 | 177 | 'msg': 'created new user `%s`' % (username,), |
|
179 | 178 | 'user': jsonify(usr.get_api_data(include_secrets=True)), |
|
180 | 179 | } |
|
181 | 180 | |
|
182 | 181 | personal_group = RepoGroup.get_by_group_name(username) |
|
183 | 182 | assert personal_group |
|
184 | 183 | assert personal_group.personal == True |
|
185 | 184 | assert personal_group.user.username == username |
|
186 | 185 | |
|
187 | 186 | try: |
|
188 | 187 | expected = ret |
|
189 | 188 | assert_ok(id_, expected, given=response.body) |
|
190 | 189 | finally: |
|
191 | 190 | fixture.destroy_repo_group(username) |
|
192 | 191 | fixture.destroy_user(usr.user_id) |
|
193 | 192 | |
|
194 | 193 | @mock.patch.object(UserModel, 'create_or_update', crash) |
|
195 | 194 | def test_api_create_user_when_exception_happened(self): |
|
196 | 195 | |
|
197 | 196 | username = 'test_new_api_user' |
|
198 | 197 | email = username + "@foo.com" |
|
199 | 198 | |
|
200 | 199 | id_, params = build_data( |
|
201 | 200 | self.apikey, 'create_user', |
|
202 | 201 | username=username, |
|
203 | 202 | email=email, |
|
204 | 203 | password='trololo') |
|
205 | 204 | response = api_call(self.app, params) |
|
206 | 205 | expected = 'failed to create user `%s`' % (username,) |
|
207 | 206 | assert_error(id_, expected, given=response.body) |
@@ -1,127 +1,126 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.meta import Session |
|
25 | 24 | from rhodecode.model.user import UserModel |
|
26 | 25 | from rhodecode.model.user_group import UserGroupModel |
|
27 | 26 | from rhodecode.api.tests.utils import ( |
|
28 | 27 | build_data, api_call, assert_error, assert_ok, crash, jsonify) |
|
29 | 28 | from rhodecode.tests.fixture import Fixture |
|
30 | 29 | |
|
31 | 30 | |
|
32 | 31 | @pytest.mark.usefixtures("testuser_api", "app") |
|
33 | 32 | class TestCreateUserGroup(object): |
|
34 | 33 | fixture = Fixture() |
|
35 | 34 | |
|
36 | 35 | def test_api_create_user_group(self): |
|
37 | 36 | group_name = 'some_new_group' |
|
38 | 37 | id_, params = build_data( |
|
39 | 38 | self.apikey, 'create_user_group', group_name=group_name) |
|
40 | 39 | response = api_call(self.app, params) |
|
41 | 40 | |
|
42 | 41 | ret = { |
|
43 | 42 | 'msg': 'created new user group `%s`' % (group_name,), |
|
44 | 43 | 'user_group': jsonify( |
|
45 | 44 | UserGroupModel() |
|
46 | 45 | .get_by_name(group_name) |
|
47 | 46 | .get_api_data() |
|
48 | 47 | ) |
|
49 | 48 | } |
|
50 | 49 | expected = ret |
|
51 | 50 | assert_ok(id_, expected, given=response.body) |
|
52 | 51 | self.fixture.destroy_user_group(group_name) |
|
53 | 52 | |
|
54 | 53 | def test_api_create_user_group_regular_user(self): |
|
55 | 54 | group_name = 'some_new_group' |
|
56 | 55 | |
|
57 | 56 | usr = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
58 | 57 | usr.inherit_default_permissions = False |
|
59 | 58 | Session().add(usr) |
|
60 | 59 | UserModel().grant_perm( |
|
61 | 60 | self.TEST_USER_LOGIN, 'hg.usergroup.create.true') |
|
62 | 61 | Session().commit() |
|
63 | 62 | |
|
64 | 63 | id_, params = build_data( |
|
65 | 64 | self.apikey_regular, 'create_user_group', group_name=group_name) |
|
66 | 65 | response = api_call(self.app, params) |
|
67 | 66 | |
|
68 | 67 | expected = { |
|
69 | 68 | 'msg': 'created new user group `%s`' % (group_name,), |
|
70 | 69 | 'user_group': jsonify( |
|
71 | 70 | UserGroupModel() |
|
72 | 71 | .get_by_name(group_name) |
|
73 | 72 | .get_api_data() |
|
74 | 73 | ) |
|
75 | 74 | } |
|
76 | 75 | try: |
|
77 | 76 | assert_ok(id_, expected, given=response.body) |
|
78 | 77 | finally: |
|
79 | 78 | self.fixture.destroy_user_group(group_name) |
|
80 | 79 | UserModel().revoke_perm( |
|
81 | 80 | self.TEST_USER_LOGIN, 'hg.usergroup.create.true') |
|
82 | 81 | usr = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
83 | 82 | usr.inherit_default_permissions = True |
|
84 | 83 | Session().add(usr) |
|
85 | 84 | Session().commit() |
|
86 | 85 | |
|
87 | 86 | def test_api_create_user_group_regular_user_no_permission(self): |
|
88 | 87 | group_name = 'some_new_group' |
|
89 | 88 | id_, params = build_data( |
|
90 | 89 | self.apikey_regular, 'create_user_group', group_name=group_name) |
|
91 | 90 | response = api_call(self.app, params) |
|
92 | 91 | expected = "Access was denied to this resource." |
|
93 | 92 | assert_error(id_, expected, given=response.body) |
|
94 | 93 | |
|
95 | 94 | def test_api_create_user_group_that_exist(self, user_util): |
|
96 | 95 | group = user_util.create_user_group() |
|
97 | 96 | group_name = group.users_group_name |
|
98 | 97 | |
|
99 | 98 | id_, params = build_data( |
|
100 | 99 | self.apikey, 'create_user_group', group_name=group_name) |
|
101 | 100 | response = api_call(self.app, params) |
|
102 | 101 | |
|
103 | 102 | expected = "user group `%s` already exist" % (group_name,) |
|
104 | 103 | assert_error(id_, expected, given=response.body) |
|
105 | 104 | |
|
106 | 105 | @mock.patch.object(UserGroupModel, 'create', crash) |
|
107 | 106 | def test_api_create_user_group_exception_occurred(self): |
|
108 | 107 | group_name = 'exception_happens' |
|
109 | 108 | id_, params = build_data( |
|
110 | 109 | self.apikey, 'create_user_group', group_name=group_name) |
|
111 | 110 | response = api_call(self.app, params) |
|
112 | 111 | |
|
113 | 112 | expected = 'failed to create group `%s`' % (group_name,) |
|
114 | 113 | assert_error(id_, expected, given=response.body) |
|
115 | 114 | |
|
116 | 115 | def test_api_create_user_group_with_wrong_name(self, user_util): |
|
117 | 116 | |
|
118 | 117 | group_name = 'wrong NAME <>' |
|
119 | 118 | id_, params = build_data( |
|
120 | 119 | self.apikey, 'create_user_group', group_name=group_name) |
|
121 | 120 | response = api_call(self.app, params) |
|
122 | 121 | |
|
123 | 122 | expected = {"user_group_name": |
|
124 | 123 | "Allowed in name are letters, numbers, and `-`, `_`, " |
|
125 | 124 | "`.` Name must start with a letter or number. " |
|
126 | 125 | "Got `{}`".format(group_name)} |
|
127 | 126 | assert_error(id_, expected, given=response.body) |
@@ -1,61 +1,60 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.gist import GistModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_error, assert_ok, crash) |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 29 | class TestApiDeleteGist(object): |
|
31 | 30 | def test_api_delete_gist(self, gist_util): |
|
32 | 31 | gist_id = gist_util.create_gist().gist_access_id |
|
33 | 32 | id_, params = build_data(self.apikey, 'delete_gist', gistid=gist_id) |
|
34 | 33 | response = api_call(self.app, params) |
|
35 | 34 | expected = {'gist': None, 'msg': 'deleted gist ID:%s' % (gist_id,)} |
|
36 | 35 | assert_ok(id_, expected, given=response.body) |
|
37 | 36 | |
|
38 | 37 | def test_api_delete_gist_regular_user(self, gist_util): |
|
39 | 38 | gist_id = gist_util.create_gist( |
|
40 | 39 | owner=self.TEST_USER_LOGIN).gist_access_id |
|
41 | 40 | id_, params = build_data( |
|
42 | 41 | self.apikey_regular, 'delete_gist', gistid=gist_id) |
|
43 | 42 | response = api_call(self.app, params) |
|
44 | 43 | expected = {'gist': None, 'msg': 'deleted gist ID:%s' % (gist_id,)} |
|
45 | 44 | assert_ok(id_, expected, given=response.body) |
|
46 | 45 | |
|
47 | 46 | def test_api_delete_gist_regular_user_no_permission(self, gist_util): |
|
48 | 47 | gist_id = gist_util.create_gist().gist_access_id |
|
49 | 48 | id_, params = build_data( |
|
50 | 49 | self.apikey_regular, 'delete_gist', gistid=gist_id) |
|
51 | 50 | response = api_call(self.app, params) |
|
52 | 51 | expected = 'gist `%s` does not exist' % (gist_id,) |
|
53 | 52 | assert_error(id_, expected, given=response.body) |
|
54 | 53 | |
|
55 | 54 | @mock.patch.object(GistModel, 'delete', crash) |
|
56 | 55 | def test_api_delete_gist_exception_occurred(self, gist_util): |
|
57 | 56 | gist_id = gist_util.create_gist().gist_access_id |
|
58 | 57 | id_, params = build_data(self.apikey, 'delete_gist', gistid=gist_id) |
|
59 | 58 | response = api_call(self.app, params) |
|
60 | 59 | expected = 'failed to delete gist ID:%s' % (gist_id,) |
|
61 | 60 | assert_error(id_, expected, given=response.body) |
@@ -1,74 +1,73 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.repo import RepoModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_error, assert_ok, crash) |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 29 | class TestApiDeleteRepo(object): |
|
31 | 30 | def test_api_delete_repo(self, backend): |
|
32 | 31 | repo = backend.create_repo() |
|
33 | 32 | repo_name = repo.repo_name |
|
34 | 33 | id_, params = build_data( |
|
35 | 34 | self.apikey, 'delete_repo', repoid=repo.repo_name, ) |
|
36 | 35 | response = api_call(self.app, params) |
|
37 | 36 | |
|
38 | 37 | expected = { |
|
39 | 38 | 'msg': 'Deleted repository `%s`' % (repo_name,), |
|
40 | 39 | 'success': True |
|
41 | 40 | } |
|
42 | 41 | assert_ok(id_, expected, given=response.body) |
|
43 | 42 | |
|
44 | 43 | def test_api_delete_repo_by_non_admin(self, backend, user_regular): |
|
45 | 44 | repo = backend.create_repo(cur_user=user_regular.username) |
|
46 | 45 | repo_name = repo.repo_name |
|
47 | 46 | id_, params = build_data( |
|
48 | 47 | user_regular.api_key, 'delete_repo', repoid=repo.repo_name, ) |
|
49 | 48 | response = api_call(self.app, params) |
|
50 | 49 | |
|
51 | 50 | expected = { |
|
52 | 51 | 'msg': 'Deleted repository `%s`' % (repo_name,), |
|
53 | 52 | 'success': True |
|
54 | 53 | } |
|
55 | 54 | assert_ok(id_, expected, given=response.body) |
|
56 | 55 | |
|
57 | 56 | def test_api_delete_repo_by_non_admin_no_permission(self, backend): |
|
58 | 57 | repo = backend.create_repo() |
|
59 | 58 | repo_name = repo.repo_name |
|
60 | 59 | id_, params = build_data( |
|
61 | 60 | self.apikey_regular, 'delete_repo', repoid=repo.repo_name, ) |
|
62 | 61 | response = api_call(self.app, params) |
|
63 | 62 | expected = 'repository `%s` does not exist' % (repo_name) |
|
64 | 63 | assert_error(id_, expected, given=response.body) |
|
65 | 64 | |
|
66 | 65 | def test_api_delete_repo_exception_occurred(self, backend): |
|
67 | 66 | repo = backend.create_repo() |
|
68 | 67 | repo_name = repo.repo_name |
|
69 | 68 | id_, params = build_data( |
|
70 | 69 | self.apikey, 'delete_repo', repoid=repo.repo_name, ) |
|
71 | 70 | with mock.patch.object(RepoModel, 'delete', crash): |
|
72 | 71 | response = api_call(self.app, params) |
|
73 | 72 | expected = 'failed to delete repository `%s`' % (repo_name,) |
|
74 | 73 | assert_error(id_, expected, given=response.body) |
@@ -1,86 +1,85 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.repo_group import RepoGroupModel |
|
25 | 24 | from rhodecode.model.user import UserModel |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_error, assert_ok) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestApiDeleteRepoGroup(object): |
|
32 | 31 | def test_api_delete_repo_group(self, user_util): |
|
33 | 32 | repo_group = user_util.create_repo_group(auto_cleanup=False) |
|
34 | 33 | repo_group_name = repo_group.group_name |
|
35 | 34 | repo_group_id = repo_group.group_id |
|
36 | 35 | id_, params = build_data( |
|
37 | 36 | self.apikey, 'delete_repo_group', repogroupid=repo_group_name, ) |
|
38 | 37 | response = api_call(self.app, params) |
|
39 | 38 | |
|
40 | 39 | ret = { |
|
41 | 40 | 'msg': 'deleted repo group ID:%s %s' % ( |
|
42 | 41 | repo_group_id, repo_group_name |
|
43 | 42 | ), |
|
44 | 43 | 'repo_group': None |
|
45 | 44 | } |
|
46 | 45 | expected = ret |
|
47 | 46 | assert_ok(id_, expected, given=response.body) |
|
48 | 47 | gr = RepoGroupModel()._get_repo_group(repo_group_name) |
|
49 | 48 | assert gr is None |
|
50 | 49 | |
|
51 | 50 | def test_api_delete_repo_group_regular_user(self, user_util): |
|
52 | 51 | repo_group = user_util.create_repo_group(auto_cleanup=False) |
|
53 | 52 | repo_group_name = repo_group.group_name |
|
54 | 53 | repo_group_id = repo_group.group_id |
|
55 | 54 | |
|
56 | 55 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
57 | 56 | user_util.grant_user_permission_to_repo_group( |
|
58 | 57 | repo_group, user, 'group.admin') |
|
59 | 58 | |
|
60 | 59 | id_, params = build_data( |
|
61 | 60 | self.apikey, 'delete_repo_group', repogroupid=repo_group_name, ) |
|
62 | 61 | response = api_call(self.app, params) |
|
63 | 62 | |
|
64 | 63 | ret = { |
|
65 | 64 | 'msg': 'deleted repo group ID:%s %s' % ( |
|
66 | 65 | repo_group_id, repo_group_name |
|
67 | 66 | ), |
|
68 | 67 | 'repo_group': None |
|
69 | 68 | } |
|
70 | 69 | expected = ret |
|
71 | 70 | assert_ok(id_, expected, given=response.body) |
|
72 | 71 | gr = RepoGroupModel()._get_repo_group(repo_group_name) |
|
73 | 72 | assert gr is None |
|
74 | 73 | |
|
75 | 74 | def test_api_delete_repo_group_regular_user_no_permission(self, user_util): |
|
76 | 75 | repo_group = user_util.create_repo_group() |
|
77 | 76 | repo_group_name = repo_group.group_name |
|
78 | 77 | |
|
79 | 78 | id_, params = build_data( |
|
80 | 79 | self.apikey_regular, 'delete_repo_group', |
|
81 | 80 | repogroupid=repo_group_name, ) |
|
82 | 81 | response = api_call(self.app, params) |
|
83 | 82 | |
|
84 | 83 | expected = 'repository group `%s` does not exist' % ( |
|
85 | 84 | repo_group_name,) |
|
86 | 85 | assert_error(id_, expected, given=response.body) |
@@ -1,57 +1,56 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import mock |
|
23 | 22 | import pytest |
|
24 | 23 | |
|
25 | 24 | from rhodecode.model.user import UserModel |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_ok, assert_error, crash) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestDeleteUser(object): |
|
32 | 31 | def test_api_delete_user(self, user_util): |
|
33 | 32 | usr = user_util.create_user(auto_cleanup=False) |
|
34 | 33 | |
|
35 | 34 | username = usr.username |
|
36 | 35 | usr_id = usr.user_id |
|
37 | 36 | |
|
38 | 37 | id_, params = build_data(self.apikey, 'delete_user', userid=username) |
|
39 | 38 | response = api_call(self.app, params) |
|
40 | 39 | |
|
41 | 40 | ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username), |
|
42 | 41 | 'user': None} |
|
43 | 42 | expected = ret |
|
44 | 43 | assert_ok(id_, expected, given=response.body) |
|
45 | 44 | |
|
46 | 45 | @mock.patch.object(UserModel, 'delete', crash) |
|
47 | 46 | def test_api_delete_user_when_exception_happened(self, user_util): |
|
48 | 47 | usr = user_util.create_user() |
|
49 | 48 | username = usr.username |
|
50 | 49 | |
|
51 | 50 | id_, params = build_data( |
|
52 | 51 | self.apikey, 'delete_user', userid=username, ) |
|
53 | 52 | response = api_call(self.app, params) |
|
54 | 53 | ret = 'failed to delete user ID:%s %s' % (usr.user_id, |
|
55 | 54 | usr.username) |
|
56 | 55 | expected = ret |
|
57 | 56 | assert_error(id_, expected, given=response.body) |
@@ -1,106 +1,105 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import mock |
|
23 | 22 | import pytest |
|
24 | 23 | |
|
25 | 24 | from rhodecode.model.user import UserModel |
|
26 | 25 | from rhodecode.model.user_group import UserGroupModel |
|
27 | 26 | from rhodecode.api.tests.utils import ( |
|
28 | 27 | build_data, api_call, assert_error, assert_ok, crash) |
|
29 | 28 | |
|
30 | 29 | |
|
31 | 30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
32 | 31 | class TestDeleteUserGroup(object): |
|
33 | 32 | def test_api_delete_user_group(self, user_util): |
|
34 | 33 | user_group = user_util.create_user_group(auto_cleanup=False) |
|
35 | 34 | group_name = user_group.users_group_name |
|
36 | 35 | group_id = user_group.users_group_id |
|
37 | 36 | id_, params = build_data( |
|
38 | 37 | self.apikey, 'delete_user_group', usergroupid=group_name) |
|
39 | 38 | response = api_call(self.app, params) |
|
40 | 39 | |
|
41 | 40 | expected = { |
|
42 | 41 | 'user_group': None, |
|
43 | 42 | 'msg': 'deleted user group ID:%s %s' % (group_id, group_name) |
|
44 | 43 | } |
|
45 | 44 | assert_ok(id_, expected, given=response.body) |
|
46 | 45 | |
|
47 | 46 | def test_api_delete_user_group_regular_user(self, user_util): |
|
48 | 47 | ugroup = user_util.create_user_group(auto_cleanup=False) |
|
49 | 48 | group_name = ugroup.users_group_name |
|
50 | 49 | group_id = ugroup.users_group_id |
|
51 | 50 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
52 | 51 | |
|
53 | 52 | user_util.grant_user_permission_to_user_group( |
|
54 | 53 | ugroup, user, 'usergroup.admin') |
|
55 | 54 | |
|
56 | 55 | id_, params = build_data( |
|
57 | 56 | self.apikey_regular, 'delete_user_group', usergroupid=group_name) |
|
58 | 57 | response = api_call(self.app, params) |
|
59 | 58 | |
|
60 | 59 | expected = { |
|
61 | 60 | 'user_group': None, |
|
62 | 61 | 'msg': 'deleted user group ID:%s %s' % (group_id, group_name) |
|
63 | 62 | } |
|
64 | 63 | assert_ok(id_, expected, given=response.body) |
|
65 | 64 | |
|
66 | 65 | def test_api_delete_user_group_regular_user_no_permission(self, user_util): |
|
67 | 66 | user_group = user_util.create_user_group() |
|
68 | 67 | group_name = user_group.users_group_name |
|
69 | 68 | |
|
70 | 69 | id_, params = build_data( |
|
71 | 70 | self.apikey_regular, 'delete_user_group', usergroupid=group_name) |
|
72 | 71 | response = api_call(self.app, params) |
|
73 | 72 | |
|
74 | 73 | expected = 'user group `%s` does not exist' % (group_name) |
|
75 | 74 | assert_error(id_, expected, given=response.body) |
|
76 | 75 | |
|
77 | 76 | def test_api_delete_user_group_that_is_assigned(self, backend, user_util): |
|
78 | 77 | ugroup = user_util.create_user_group() |
|
79 | 78 | group_name = ugroup.users_group_name |
|
80 | 79 | repo = backend.create_repo() |
|
81 | 80 | |
|
82 | 81 | ugr_to_perm = user_util.grant_user_group_permission_to_repo( |
|
83 | 82 | repo, ugroup, 'repository.write') |
|
84 | 83 | msg = 'UserGroup assigned to %s' % (ugr_to_perm.repository) |
|
85 | 84 | |
|
86 | 85 | id_, params = build_data( |
|
87 | 86 | self.apikey, 'delete_user_group', |
|
88 | 87 | usergroupid=group_name) |
|
89 | 88 | response = api_call(self.app, params) |
|
90 | 89 | |
|
91 | 90 | expected = msg |
|
92 | 91 | assert_error(id_, expected, given=response.body) |
|
93 | 92 | |
|
94 | 93 | def test_api_delete_user_group_exception_occurred(self, user_util): |
|
95 | 94 | ugroup = user_util.create_user_group() |
|
96 | 95 | group_name = ugroup.users_group_name |
|
97 | 96 | group_id = ugroup.users_group_id |
|
98 | 97 | id_, params = build_data( |
|
99 | 98 | self.apikey, 'delete_user_group', |
|
100 | 99 | usergroupid=group_name) |
|
101 | 100 | |
|
102 | 101 | with mock.patch.object(UserGroupModel, 'delete', crash): |
|
103 | 102 | response = api_call(self.app, params) |
|
104 | 103 | expected = 'failed to delete user group ID:%s %s' % ( |
|
105 | 104 | group_id, group_name) |
|
106 | 105 | assert_error(id_, expected, given=response.body) |
@@ -1,79 +1,78 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.api.views import deprecated_api |
|
25 | 24 | from rhodecode.lib.ext_json import json |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestCommitComment(object): |
|
32 | 31 | def test_deprecated_message_in_docstring(self): |
|
33 | 32 | docstring = deprecated_api.changeset_comment.__doc__ |
|
34 | 33 | assert '.. deprecated:: 3.4.0' in docstring |
|
35 | 34 | assert 'Please use method `comment_commit` instead.' in docstring |
|
36 | 35 | |
|
37 | 36 | def test_deprecated_message_in_retvalue(self): |
|
38 | 37 | |
|
39 | 38 | id_, params = build_data( |
|
40 | 39 | self.apikey, 'show_ip') |
|
41 | 40 | response = api_call(self.app, params) |
|
42 | 41 | |
|
43 | 42 | expected = { |
|
44 | 43 | 'id': id_, |
|
45 | 44 | 'error': None, |
|
46 | 45 | 'result': json.loads(response.body)['result'], |
|
47 | 46 | 'DEPRECATION_WARNING': |
|
48 | 47 | 'DEPRECATED METHOD Please use method `get_ip` instead.' |
|
49 | 48 | } |
|
50 | 49 | assert expected == json.loads(response.body) |
|
51 | 50 | |
|
52 | 51 | # def test_calls_comment_commit(self, backend, no_notifications): |
|
53 | 52 | # data = { |
|
54 | 53 | # 'repoid': backend.repo_name, |
|
55 | 54 | # 'status': ChangesetStatus.STATUS_APPROVED, |
|
56 | 55 | # 'message': 'Approved', |
|
57 | 56 | # 'revision': 'tip' |
|
58 | 57 | # } |
|
59 | 58 | # with patch.object(repo_api, 'changeset_commit') as comment_mock: |
|
60 | 59 | # id_, params = build_data(self.apikey, 'comment_commit', **data) |
|
61 | 60 | # api_call(self.app, params) |
|
62 | 61 | # |
|
63 | 62 | # _, call_args = comment_mock.call_args |
|
64 | 63 | # data['commit_id'] = data.pop('revision') |
|
65 | 64 | # for key in data: |
|
66 | 65 | # assert call_args[key] == data[key] |
|
67 | 66 | |
|
68 | 67 | # def test_warning_log_contains_deprecation_message(self): |
|
69 | 68 | # api = self.SampleApi() |
|
70 | 69 | # with patch.object(utils, 'log') as log_mock: |
|
71 | 70 | # api.api_method() |
|
72 | 71 | # |
|
73 | 72 | # assert log_mock.warning.call_count == 1 |
|
74 | 73 | # call_args = log_mock.warning.call_args[0] |
|
75 | 74 | # assert ( |
|
76 | 75 | # call_args[0] == |
|
77 | 76 | # 'DEPRECATED API CALL on function %s, please use `%s` instead') |
|
78 | 77 | # assert call_args[1].__name__ == 'api_method' |
|
79 | 78 | # assert call_args[2] == 'new_method' No newline at end of file |
@@ -1,279 +1,278 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import mock |
|
23 | 22 | import pytest |
|
24 | 23 | |
|
25 | 24 | from rhodecode.model.meta import Session |
|
26 | 25 | from rhodecode.model.repo import RepoModel |
|
27 | 26 | from rhodecode.model.repo_group import RepoGroupModel |
|
28 | 27 | from rhodecode.model.user import UserModel |
|
29 | 28 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
30 | 29 | from rhodecode.api.tests.utils import ( |
|
31 | 30 | build_data, api_call, assert_error, assert_ok, crash) |
|
32 | 31 | from rhodecode.tests.fixture import Fixture |
|
33 | 32 | |
|
34 | 33 | |
|
35 | 34 | fixture = Fixture() |
|
36 | 35 | |
|
37 | 36 | |
|
38 | 37 | @pytest.mark.usefixtures("testuser_api", "app") |
|
39 | 38 | class TestApiForkRepo(object): |
|
40 | 39 | def test_api_fork_repo(self, backend): |
|
41 | 40 | source_name = backend['minimal'].repo_name |
|
42 | 41 | fork_name = backend.new_repo_name() |
|
43 | 42 | |
|
44 | 43 | id_, params = build_data( |
|
45 | 44 | self.apikey, 'fork_repo', |
|
46 | 45 | repoid=source_name, |
|
47 | 46 | fork_name=fork_name, |
|
48 | 47 | owner=TEST_USER_ADMIN_LOGIN) |
|
49 | 48 | response = api_call(self.app, params) |
|
50 | 49 | |
|
51 | 50 | expected = { |
|
52 | 51 | 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name), |
|
53 | 52 | 'success': True, |
|
54 | 53 | 'task': None, |
|
55 | 54 | } |
|
56 | 55 | try: |
|
57 | 56 | assert_ok(id_, expected, given=response.body) |
|
58 | 57 | finally: |
|
59 | 58 | fixture.destroy_repo(fork_name) |
|
60 | 59 | |
|
61 | 60 | def test_api_fork_repo_into_group(self, backend, user_util): |
|
62 | 61 | source_name = backend['minimal'].repo_name |
|
63 | 62 | repo_group = user_util.create_repo_group() |
|
64 | 63 | fork_name = '%s/api-repo-fork' % repo_group.group_name |
|
65 | 64 | id_, params = build_data( |
|
66 | 65 | self.apikey, 'fork_repo', |
|
67 | 66 | repoid=source_name, |
|
68 | 67 | fork_name=fork_name, |
|
69 | 68 | owner=TEST_USER_ADMIN_LOGIN) |
|
70 | 69 | response = api_call(self.app, params) |
|
71 | 70 | |
|
72 | 71 | ret = { |
|
73 | 72 | 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name), |
|
74 | 73 | 'success': True, |
|
75 | 74 | 'task': None, |
|
76 | 75 | } |
|
77 | 76 | expected = ret |
|
78 | 77 | try: |
|
79 | 78 | assert_ok(id_, expected, given=response.body) |
|
80 | 79 | finally: |
|
81 | 80 | fixture.destroy_repo(fork_name) |
|
82 | 81 | |
|
83 | 82 | def test_api_fork_repo_non_admin(self, backend): |
|
84 | 83 | source_name = backend['minimal'].repo_name |
|
85 | 84 | fork_name = backend.new_repo_name() |
|
86 | 85 | |
|
87 | 86 | id_, params = build_data( |
|
88 | 87 | self.apikey_regular, 'fork_repo', |
|
89 | 88 | repoid=source_name, |
|
90 | 89 | fork_name=fork_name) |
|
91 | 90 | response = api_call(self.app, params) |
|
92 | 91 | |
|
93 | 92 | expected = { |
|
94 | 93 | 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name), |
|
95 | 94 | 'success': True, |
|
96 | 95 | 'task': None, |
|
97 | 96 | } |
|
98 | 97 | try: |
|
99 | 98 | assert_ok(id_, expected, given=response.body) |
|
100 | 99 | finally: |
|
101 | 100 | fixture.destroy_repo(fork_name) |
|
102 | 101 | |
|
103 | 102 | def test_api_fork_repo_non_admin_into_group_no_permission(self, backend, user_util): |
|
104 | 103 | source_name = backend['minimal'].repo_name |
|
105 | 104 | repo_group = user_util.create_repo_group() |
|
106 | 105 | repo_group_name = repo_group.group_name |
|
107 | 106 | fork_name = '%s/api-repo-fork' % repo_group_name |
|
108 | 107 | |
|
109 | 108 | id_, params = build_data( |
|
110 | 109 | self.apikey_regular, 'fork_repo', |
|
111 | 110 | repoid=source_name, |
|
112 | 111 | fork_name=fork_name) |
|
113 | 112 | response = api_call(self.app, params) |
|
114 | 113 | |
|
115 | 114 | expected = { |
|
116 | 115 | 'repo_group': 'Repository group `{}` does not exist'.format( |
|
117 | 116 | repo_group_name)} |
|
118 | 117 | try: |
|
119 | 118 | assert_error(id_, expected, given=response.body) |
|
120 | 119 | finally: |
|
121 | 120 | fixture.destroy_repo(fork_name) |
|
122 | 121 | |
|
123 | 122 | def test_api_fork_repo_non_admin_into_group(self, backend, user_util): |
|
124 | 123 | source_name = backend['minimal'].repo_name |
|
125 | 124 | repo_group = user_util.create_repo_group() |
|
126 | 125 | fork_name = '%s/api-repo-fork' % repo_group.group_name |
|
127 | 126 | |
|
128 | 127 | RepoGroupModel().grant_user_permission( |
|
129 | 128 | repo_group, self.TEST_USER_LOGIN, 'group.admin') |
|
130 | 129 | Session().commit() |
|
131 | 130 | |
|
132 | 131 | id_, params = build_data( |
|
133 | 132 | self.apikey_regular, 'fork_repo', |
|
134 | 133 | repoid=source_name, |
|
135 | 134 | fork_name=fork_name) |
|
136 | 135 | response = api_call(self.app, params) |
|
137 | 136 | |
|
138 | 137 | expected = { |
|
139 | 138 | 'msg': 'Created fork of `%s` as `%s`' % (source_name, fork_name), |
|
140 | 139 | 'success': True, |
|
141 | 140 | 'task': None, |
|
142 | 141 | } |
|
143 | 142 | try: |
|
144 | 143 | assert_ok(id_, expected, given=response.body) |
|
145 | 144 | finally: |
|
146 | 145 | fixture.destroy_repo(fork_name) |
|
147 | 146 | |
|
148 | 147 | def test_api_fork_repo_non_admin_specify_owner(self, backend): |
|
149 | 148 | source_name = backend['minimal'].repo_name |
|
150 | 149 | fork_name = backend.new_repo_name() |
|
151 | 150 | id_, params = build_data( |
|
152 | 151 | self.apikey_regular, 'fork_repo', |
|
153 | 152 | repoid=source_name, |
|
154 | 153 | fork_name=fork_name, |
|
155 | 154 | owner=TEST_USER_ADMIN_LOGIN) |
|
156 | 155 | response = api_call(self.app, params) |
|
157 | 156 | expected = 'Only RhodeCode super-admin can specify `owner` param' |
|
158 | 157 | assert_error(id_, expected, given=response.body) |
|
159 | 158 | |
|
160 | 159 | def test_api_fork_repo_non_admin_no_permission_of_source_repo( |
|
161 | 160 | self, backend): |
|
162 | 161 | source_name = backend['minimal'].repo_name |
|
163 | 162 | RepoModel().grant_user_permission(repo=source_name, |
|
164 | 163 | user=self.TEST_USER_LOGIN, |
|
165 | 164 | perm='repository.none') |
|
166 | 165 | fork_name = backend.new_repo_name() |
|
167 | 166 | id_, params = build_data( |
|
168 | 167 | self.apikey_regular, 'fork_repo', |
|
169 | 168 | repoid=backend.repo_name, |
|
170 | 169 | fork_name=fork_name) |
|
171 | 170 | response = api_call(self.app, params) |
|
172 | 171 | expected = 'repository `%s` does not exist' % (backend.repo_name) |
|
173 | 172 | assert_error(id_, expected, given=response.body) |
|
174 | 173 | |
|
175 | 174 | def test_api_fork_repo_non_admin_no_permission_to_fork_to_root_level( |
|
176 | 175 | self, backend, user_util): |
|
177 | 176 | |
|
178 | 177 | regular_user = user_util.create_user() |
|
179 | 178 | regular_user_api_key = regular_user.api_key |
|
180 | 179 | usr = UserModel().get_by_username(regular_user.username) |
|
181 | 180 | usr.inherit_default_permissions = False |
|
182 | 181 | Session().add(usr) |
|
183 | 182 | UserModel().grant_perm(regular_user.username, 'hg.fork.repository') |
|
184 | 183 | |
|
185 | 184 | source_name = backend['minimal'].repo_name |
|
186 | 185 | fork_name = backend.new_repo_name() |
|
187 | 186 | id_, params = build_data( |
|
188 | 187 | regular_user_api_key, 'fork_repo', |
|
189 | 188 | repoid=source_name, |
|
190 | 189 | fork_name=fork_name) |
|
191 | 190 | response = api_call(self.app, params) |
|
192 | 191 | expected = { |
|
193 | 192 | "repo_name": "You do not have the permission to " |
|
194 | 193 | "store repositories in the root location."} |
|
195 | 194 | assert_error(id_, expected, given=response.body) |
|
196 | 195 | |
|
197 | 196 | def test_api_fork_repo_non_admin_no_permission_to_fork( |
|
198 | 197 | self, backend, user_util): |
|
199 | 198 | |
|
200 | 199 | regular_user = user_util.create_user() |
|
201 | 200 | regular_user_api_key = regular_user.api_key |
|
202 | 201 | usr = UserModel().get_by_username(regular_user.username) |
|
203 | 202 | usr.inherit_default_permissions = False |
|
204 | 203 | Session().add(usr) |
|
205 | 204 | |
|
206 | 205 | source_name = backend['minimal'].repo_name |
|
207 | 206 | fork_name = backend.new_repo_name() |
|
208 | 207 | id_, params = build_data( |
|
209 | 208 | regular_user_api_key, 'fork_repo', |
|
210 | 209 | repoid=source_name, |
|
211 | 210 | fork_name=fork_name) |
|
212 | 211 | response = api_call(self.app, params) |
|
213 | 212 | |
|
214 | 213 | expected = "Access was denied to this resource." |
|
215 | 214 | assert_error(id_, expected, given=response.body) |
|
216 | 215 | |
|
217 | 216 | def test_api_fork_repo_unknown_owner(self, backend): |
|
218 | 217 | source_name = backend['minimal'].repo_name |
|
219 | 218 | fork_name = backend.new_repo_name() |
|
220 | 219 | owner = 'i-dont-exist' |
|
221 | 220 | id_, params = build_data( |
|
222 | 221 | self.apikey, 'fork_repo', |
|
223 | 222 | repoid=source_name, |
|
224 | 223 | fork_name=fork_name, |
|
225 | 224 | owner=owner) |
|
226 | 225 | response = api_call(self.app, params) |
|
227 | 226 | expected = 'user `%s` does not exist' % (owner,) |
|
228 | 227 | assert_error(id_, expected, given=response.body) |
|
229 | 228 | |
|
230 | 229 | def test_api_fork_repo_fork_exists(self, backend): |
|
231 | 230 | source_name = backend['minimal'].repo_name |
|
232 | 231 | fork_name = backend.new_repo_name() |
|
233 | 232 | fork_repo = fixture.create_fork(source_name, fork_name) |
|
234 | 233 | |
|
235 | 234 | id_, params = build_data( |
|
236 | 235 | self.apikey, 'fork_repo', |
|
237 | 236 | repoid=source_name, |
|
238 | 237 | fork_name=fork_name, |
|
239 | 238 | owner=TEST_USER_ADMIN_LOGIN) |
|
240 | 239 | response = api_call(self.app, params) |
|
241 | 240 | |
|
242 | 241 | try: |
|
243 | 242 | expected = { |
|
244 | 243 | 'unique_repo_name': 'Repository with name `{}` already exists'.format( |
|
245 | 244 | fork_name)} |
|
246 | 245 | assert_error(id_, expected, given=response.body) |
|
247 | 246 | finally: |
|
248 | 247 | fixture.destroy_repo(fork_repo.repo_name) |
|
249 | 248 | |
|
250 | 249 | def test_api_fork_repo_repo_exists(self, backend): |
|
251 | 250 | source_name = backend['minimal'].repo_name |
|
252 | 251 | fork_name = source_name |
|
253 | 252 | |
|
254 | 253 | id_, params = build_data( |
|
255 | 254 | self.apikey, 'fork_repo', |
|
256 | 255 | repoid=source_name, |
|
257 | 256 | fork_name=fork_name, |
|
258 | 257 | owner=TEST_USER_ADMIN_LOGIN) |
|
259 | 258 | response = api_call(self.app, params) |
|
260 | 259 | |
|
261 | 260 | expected = { |
|
262 | 261 | 'unique_repo_name': 'Repository with name `{}` already exists'.format( |
|
263 | 262 | fork_name)} |
|
264 | 263 | assert_error(id_, expected, given=response.body) |
|
265 | 264 | |
|
266 | 265 | @mock.patch.object(RepoModel, 'create_fork', crash) |
|
267 | 266 | def test_api_fork_repo_exception_occurred(self, backend): |
|
268 | 267 | source_name = backend['minimal'].repo_name |
|
269 | 268 | fork_name = backend.new_repo_name() |
|
270 | 269 | id_, params = build_data( |
|
271 | 270 | self.apikey, 'fork_repo', |
|
272 | 271 | repoid=source_name, |
|
273 | 272 | fork_name=fork_name, |
|
274 | 273 | owner=TEST_USER_ADMIN_LOGIN) |
|
275 | 274 | response = api_call(self.app, params) |
|
276 | 275 | |
|
277 | 276 | expected = 'failed to fork repository `%s` as `%s`' % (source_name, |
|
278 | 277 | fork_name) |
|
279 | 278 | assert_error(id_, expected, given=response.body) |
@@ -1,115 +1,114 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import pytest |
|
22 | 21 | from rhodecode.tests import HG_REPO |
|
23 | 22 | from rhodecode.api.tests.utils import ( |
|
24 | 23 | build_data, api_call, assert_error, assert_ok) |
|
25 | 24 | |
|
26 | 25 | |
|
27 | 26 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | 27 | class TestApiSearch(object): |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.parametrize("sort_dir", [ |
|
31 | 30 | "asc", |
|
32 | 31 | "desc", |
|
33 | 32 | ]) |
|
34 | 33 | @pytest.mark.parametrize("sort", [ |
|
35 | 34 | "xxx", |
|
36 | 35 | "author_email", |
|
37 | 36 | "date", |
|
38 | 37 | "message", |
|
39 | 38 | ]) |
|
40 | 39 | @pytest.mark.parametrize("query, expected_hits, expected_paths", [ |
|
41 | 40 | ('todo', 23, [ |
|
42 | 41 | 'vcs/backends/hg/inmemory.py', |
|
43 | 42 | 'vcs/tests/test_git.py']), |
|
44 | 43 | ('extension:rst installation', 6, [ |
|
45 | 44 | 'docs/index.rst', |
|
46 | 45 | 'docs/installation.rst']), |
|
47 | 46 | ('def repo', 87, [ |
|
48 | 47 | 'vcs/tests/test_git.py', |
|
49 | 48 | 'vcs/tests/test_changesets.py']), |
|
50 | 49 | ('repository:%s def test' % HG_REPO, 18, [ |
|
51 | 50 | 'vcs/tests/test_git.py', |
|
52 | 51 | 'vcs/tests/test_changesets.py']), |
|
53 | 52 | ('"def main"', 9, [ |
|
54 | 53 | 'vcs/__init__.py', |
|
55 | 54 | 'vcs/tests/__init__.py', |
|
56 | 55 | 'vcs/utils/progressbar.py']), |
|
57 | 56 | ('owner:test_admin', 358, [ |
|
58 | 57 | 'vcs/tests/base.py', |
|
59 | 58 | 'MANIFEST.in', |
|
60 | 59 | 'vcs/utils/termcolors.py', |
|
61 | 60 | 'docs/theme/ADC/static/documentation.png']), |
|
62 | 61 | ('owner:test_admin def main', 72, [ |
|
63 | 62 | 'vcs/__init__.py', |
|
64 | 63 | 'vcs/tests/test_utils_filesize.py', |
|
65 | 64 | 'vcs/tests/test_cli.py']), |
|
66 | 65 | ('owner:michał test', 0, []), |
|
67 | 66 | ]) |
|
68 | 67 | def test_search_content_results(self, sort_dir, sort, query, expected_hits, expected_paths): |
|
69 | 68 | id_, params = build_data( |
|
70 | 69 | self.apikey_regular, 'search', |
|
71 | 70 | search_query=query, |
|
72 | 71 | search_sort='{}:{}'.format(sort_dir, sort), |
|
73 | 72 | search_type='content') |
|
74 | 73 | |
|
75 | 74 | response = api_call(self.app, params) |
|
76 | 75 | json_response = response.json |
|
77 | 76 | |
|
78 | 77 | assert json_response['result']['item_count'] == expected_hits |
|
79 | 78 | paths = [x['f_path'] for x in json_response['result']['results']] |
|
80 | 79 | |
|
81 | 80 | for expected_path in expected_paths: |
|
82 | 81 | assert expected_path in paths |
|
83 | 82 | |
|
84 | 83 | @pytest.mark.parametrize("sort_dir", [ |
|
85 | 84 | "asc", |
|
86 | 85 | "desc", |
|
87 | 86 | ]) |
|
88 | 87 | @pytest.mark.parametrize("sort", [ |
|
89 | 88 | "xxx", |
|
90 | 89 | "date", |
|
91 | 90 | "file", |
|
92 | 91 | "size", |
|
93 | 92 | ]) |
|
94 | 93 | @pytest.mark.parametrize("query, expected_hits, expected_paths", [ |
|
95 | 94 | ('readme.rst', 3, []), |
|
96 | 95 | ('test*', 75, []), |
|
97 | 96 | ('*model*', 1, []), |
|
98 | 97 | ('extension:rst', 48, []), |
|
99 | 98 | ('extension:rst api', 24, []), |
|
100 | 99 | ]) |
|
101 | 100 | def test_search_file_paths(self, sort_dir, sort, query, expected_hits, expected_paths): |
|
102 | 101 | id_, params = build_data( |
|
103 | 102 | self.apikey_regular, 'search', |
|
104 | 103 | search_query=query, |
|
105 | 104 | search_sort='{}:{}'.format(sort_dir, sort), |
|
106 | 105 | search_type='path') |
|
107 | 106 | |
|
108 | 107 | response = api_call(self.app, params) |
|
109 | 108 | json_response = response.json |
|
110 | 109 | |
|
111 | 110 | assert json_response['result']['item_count'] == expected_hits |
|
112 | 111 | paths = [x['f_path'] for x in json_response['result']['results']] |
|
113 | 112 | |
|
114 | 113 | for expected_path in expected_paths: |
|
115 | 114 | assert expected_path in paths |
@@ -1,101 +1,101 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
23 | from rhodecode.lib.str_utils import safe_bytes | |
|
24 | 24 | from rhodecode.model.db import Gist |
|
25 | 25 | from rhodecode.api.tests.utils import ( |
|
26 | 26 | build_data, api_call, assert_error, assert_ok) |
|
27 | 27 | |
|
28 | 28 | |
|
29 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 30 | class TestApiGetGist(object): |
|
31 | 31 | def test_api_get_gist(self, gist_util, http_host_only_stub): |
|
32 | 32 | gist = gist_util.create_gist() |
|
33 | 33 | gist_id = gist.gist_access_id |
|
34 | 34 | gist_created_on = gist.created_on |
|
35 | 35 | gist_modified_at = gist.modified_at |
|
36 | 36 | id_, params = build_data( |
|
37 | 37 | self.apikey, 'get_gist', gistid=gist_id, ) |
|
38 | 38 | response = api_call(self.app, params) |
|
39 | 39 | |
|
40 | 40 | expected = { |
|
41 | 41 | 'access_id': gist_id, |
|
42 | 42 | 'created_on': gist_created_on, |
|
43 | 43 | 'modified_at': gist_modified_at, |
|
44 | 44 | 'description': 'new-gist', |
|
45 | 45 | 'expires': -1.0, |
|
46 | 46 | 'gist_id': int(gist_id), |
|
47 | 47 | 'type': 'public', |
|
48 | 48 | 'url': 'http://%s/_admin/gists/%s' % (http_host_only_stub, gist_id,), |
|
49 | 49 | 'acl_level': Gist.ACL_LEVEL_PUBLIC, |
|
50 | 50 | 'content': None, |
|
51 | 51 | } |
|
52 | 52 | |
|
53 | 53 | assert_ok(id_, expected, given=response.body) |
|
54 | 54 | |
|
55 | 55 | def test_api_get_gist_with_content(self, gist_util, http_host_only_stub): |
|
56 | 56 | mapping = { |
|
57 |
|
|
|
58 |
|
|
|
57 | b'filename1.txt': {'content': b'hello world'}, | |
|
58 | safe_bytes('filename1Ä….txt'): {'content': safe_bytes('hello worldÄ™')} | |
|
59 | 59 | } |
|
60 | 60 | gist = gist_util.create_gist(gist_mapping=mapping) |
|
61 | 61 | gist_id = gist.gist_access_id |
|
62 | 62 | gist_created_on = gist.created_on |
|
63 | 63 | gist_modified_at = gist.modified_at |
|
64 | 64 | id_, params = build_data( |
|
65 | 65 | self.apikey, 'get_gist', gistid=gist_id, content=True) |
|
66 | 66 | response = api_call(self.app, params) |
|
67 | 67 | |
|
68 | 68 | expected = { |
|
69 | 69 | 'access_id': gist_id, |
|
70 | 70 | 'created_on': gist_created_on, |
|
71 | 71 | 'modified_at': gist_modified_at, |
|
72 | 72 | 'description': 'new-gist', |
|
73 | 73 | 'expires': -1.0, |
|
74 | 74 | 'gist_id': int(gist_id), |
|
75 | 75 | 'type': 'public', |
|
76 | 76 | 'url': 'http://%s/_admin/gists/%s' % (http_host_only_stub, gist_id,), |
|
77 | 77 | 'acl_level': Gist.ACL_LEVEL_PUBLIC, |
|
78 | 78 | 'content': { |
|
79 | 79 | u'filename1.txt': u'hello world', |
|
80 | 80 | u'filename1Ä….txt': u'hello worldÄ™' |
|
81 | 81 | }, |
|
82 | 82 | } |
|
83 | 83 | |
|
84 | 84 | assert_ok(id_, expected, given=response.body) |
|
85 | 85 | |
|
86 | 86 | def test_api_get_gist_not_existing(self): |
|
87 | 87 | id_, params = build_data( |
|
88 | 88 | self.apikey_regular, 'get_gist', gistid='12345', ) |
|
89 | 89 | response = api_call(self.app, params) |
|
90 | 90 | expected = 'gist `%s` does not exist' % ('12345',) |
|
91 | 91 | assert_error(id_, expected, given=response.body) |
|
92 | 92 | |
|
93 | 93 | def test_api_get_gist_private_gist_without_permission(self, gist_util): |
|
94 | 94 | gist = gist_util.create_gist() |
|
95 | 95 | gist_id = gist.gist_access_id |
|
96 | 96 | id_, params = build_data( |
|
97 | 97 | self.apikey_regular, 'get_gist', gistid=gist_id, ) |
|
98 | 98 | response = api_call(self.app, params) |
|
99 | 99 | |
|
100 | 100 | expected = 'gist `%s` does not exist' % (gist_id,) |
|
101 | 101 | assert_error(id_, expected, given=response.body) |
@@ -1,74 +1,73 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_error) |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 29 | class TestApiGetGist(object): |
|
31 | 30 | def test_api_get_gists(self, gist_util): |
|
32 | 31 | gist_util.create_gist() |
|
33 | 32 | gist_util.create_gist() |
|
34 | 33 | |
|
35 | 34 | id_, params = build_data(self.apikey, 'get_gists') |
|
36 | 35 | response = api_call(self.app, params) |
|
37 | 36 | assert len(response.json['result']) == 2 |
|
38 | 37 | |
|
39 | 38 | def test_api_get_gists_regular_user(self, gist_util): |
|
40 | 39 | # by admin |
|
41 | 40 | gist_util.create_gist() |
|
42 | 41 | gist_util.create_gist() |
|
43 | 42 | |
|
44 | 43 | # by reg user |
|
45 | 44 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) |
|
46 | 45 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) |
|
47 | 46 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) |
|
48 | 47 | |
|
49 | 48 | id_, params = build_data(self.apikey_regular, 'get_gists') |
|
50 | 49 | response = api_call(self.app, params) |
|
51 | 50 | assert len(response.json['result']) == 3 |
|
52 | 51 | |
|
53 | 52 | def test_api_get_gists_only_for_regular_user(self, gist_util): |
|
54 | 53 | # by admin |
|
55 | 54 | gist_util.create_gist() |
|
56 | 55 | gist_util.create_gist() |
|
57 | 56 | |
|
58 | 57 | # by reg user |
|
59 | 58 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) |
|
60 | 59 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) |
|
61 | 60 | gist_util.create_gist(owner=self.TEST_USER_LOGIN) |
|
62 | 61 | |
|
63 | 62 | id_, params = build_data( |
|
64 | 63 | self.apikey, 'get_gists', userid=self.TEST_USER_LOGIN) |
|
65 | 64 | response = api_call(self.app, params) |
|
66 | 65 | assert len(response.json['result']) == 3 |
|
67 | 66 | |
|
68 | 67 | def test_api_get_gists_regular_user_with_different_userid(self): |
|
69 | 68 | id_, params = build_data( |
|
70 | 69 | self.apikey_regular, 'get_gists', |
|
71 | 70 | userid=TEST_USER_ADMIN_LOGIN) |
|
72 | 71 | response = api_call(self.app, params) |
|
73 | 72 | expected = 'userid is not the same as your user' |
|
74 | 73 | assert_error(id_, expected, given=response.body) |
@@ -1,36 +1,35 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok |
|
25 | 24 | |
|
26 | 25 | |
|
27 | 26 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | 27 | class TestGetIp(object): |
|
29 | 28 | def test_api_get_ip(self): |
|
30 | 29 | id_, params = build_data(self.apikey, 'get_ip') |
|
31 | 30 | response = api_call(self.app, params) |
|
32 | 31 | expected = { |
|
33 | 32 | 'server_ip_addr': '0.0.0.0', |
|
34 | 33 | 'user_ips': [] |
|
35 | 34 | } |
|
36 | 35 | assert_ok(id_, expected, given=response.body) |
@@ -1,91 +1,90 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.db import Repository, User |
|
25 | 24 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_ok, assert_error) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestGetLocks(object): |
|
32 | 31 | def test_api_get_user_locks_regular_user(self): |
|
33 | 32 | id_, params = build_data(self.apikey_regular, 'get_user_locks') |
|
34 | 33 | response = api_call(self.app, params) |
|
35 | 34 | expected = [] |
|
36 | 35 | assert_ok(id_, expected, given=response.body) |
|
37 | 36 | |
|
38 | 37 | def test_api_get_user_locks_with_userid_regular_user(self): |
|
39 | 38 | id_, params = build_data( |
|
40 | 39 | self.apikey_regular, 'get_user_locks', userid=TEST_USER_ADMIN_LOGIN) |
|
41 | 40 | response = api_call(self.app, params) |
|
42 | 41 | expected = 'userid is not the same as your user' |
|
43 | 42 | assert_error(id_, expected, given=response.body) |
|
44 | 43 | |
|
45 | 44 | def test_api_get_user_locks(self): |
|
46 | 45 | id_, params = build_data(self.apikey, 'get_user_locks') |
|
47 | 46 | response = api_call(self.app, params) |
|
48 | 47 | expected = [] |
|
49 | 48 | assert_ok(id_, expected, given=response.body) |
|
50 | 49 | |
|
51 | 50 | @pytest.mark.parametrize("apikey_attr, expect_secrets", [ |
|
52 | 51 | ('apikey', True), |
|
53 | 52 | ('apikey_regular', False), |
|
54 | 53 | ]) |
|
55 | 54 | def test_api_get_user_locks_with_one_locked_repo( |
|
56 | 55 | self, apikey_attr, expect_secrets, backend): |
|
57 | 56 | |
|
58 | 57 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) |
|
59 | 58 | Repository.lock( |
|
60 | 59 | repo, User.get_by_username(self.TEST_USER_LOGIN).user_id) |
|
61 | 60 | |
|
62 | 61 | apikey = getattr(self, apikey_attr) |
|
63 | 62 | |
|
64 | 63 | id_, params = build_data(apikey, 'get_user_locks') |
|
65 | 64 | if apikey_attr == 'apikey': |
|
66 | 65 | # super-admin should call in specific user |
|
67 | 66 | id_, params = build_data(apikey, 'get_user_locks', |
|
68 | 67 | userid=self.TEST_USER_LOGIN) |
|
69 | 68 | |
|
70 | 69 | response = api_call(self.app, params) |
|
71 | 70 | expected = [repo.get_api_data(include_secrets=expect_secrets)] |
|
72 | 71 | assert_ok(id_, expected, given=response.body) |
|
73 | 72 | |
|
74 | 73 | def test_api_get_user_locks_with_one_locked_repo_for_specific_user( |
|
75 | 74 | self, backend): |
|
76 | 75 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) |
|
77 | 76 | |
|
78 | 77 | Repository.lock(repo, User.get_by_username( |
|
79 | 78 | self.TEST_USER_LOGIN).user_id) |
|
80 | 79 | id_, params = build_data( |
|
81 | 80 | self.apikey, 'get_user_locks', userid=self.TEST_USER_LOGIN) |
|
82 | 81 | response = api_call(self.app, params) |
|
83 | 82 | expected = [repo.get_api_data(include_secrets=True)] |
|
84 | 83 | assert_ok(id_, expected, given=response.body) |
|
85 | 84 | |
|
86 | 85 | def test_api_get_user_locks_with_userid(self): |
|
87 | 86 | id_, params = build_data( |
|
88 | 87 | self.apikey, 'get_user_locks', userid=TEST_USER_REGULAR_LOGIN) |
|
89 | 88 | response = api_call(self.app, params) |
|
90 | 89 | expected = [] |
|
91 | 90 | assert_ok(id_, expected, given=response.body) |
@@ -1,63 +1,62 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok |
|
25 | 24 | |
|
26 | 25 | |
|
27 | 26 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | 27 | class TestGetMethod(object): |
|
29 | 28 | def test_get_methods_no_matches(self): |
|
30 | 29 | id_, params = build_data(self.apikey, 'get_method', pattern='hello') |
|
31 | 30 | response = api_call(self.app, params) |
|
32 | 31 | |
|
33 | 32 | expected = [] |
|
34 | 33 | assert_ok(id_, expected, given=response.body) |
|
35 | 34 | |
|
36 | 35 | def test_get_methods(self): |
|
37 | 36 | id_, params = build_data(self.apikey, 'get_method', pattern='*comment*') |
|
38 | 37 | response = api_call(self.app, params) |
|
39 | 38 | |
|
40 | 39 | expected = [ |
|
41 | 40 | 'changeset_comment', 'comment_pull_request', 'get_pull_request_comments', |
|
42 | 41 | 'comment_commit', 'edit_comment', 'get_comment', 'get_repo_comments' |
|
43 | 42 | ] |
|
44 | 43 | assert_ok(id_, expected, given=response.body) |
|
45 | 44 | |
|
46 | 45 | def test_get_methods_on_single_match(self): |
|
47 | 46 | id_, params = build_data(self.apikey, 'get_method', |
|
48 | 47 | pattern='*comment_commit*') |
|
49 | 48 | response = api_call(self.app, params) |
|
50 | 49 | |
|
51 | 50 | expected = ['comment_commit', |
|
52 | 51 | {'apiuser': '<RequiredType>', |
|
53 |
'comment_type': "<Optional: |
|
|
52 | 'comment_type': "<Optional:'note'>", | |
|
54 | 53 | 'commit_id': '<RequiredType>', |
|
55 | 54 | 'extra_recipients': '<Optional:[]>', |
|
56 | 55 | 'message': '<RequiredType>', |
|
57 | 56 | 'repoid': '<RequiredType>', |
|
58 | 57 | 'request': '<RequiredType>', |
|
59 | 58 | 'resolves_comment_id': '<Optional:None>', |
|
60 | 59 | 'status': '<Optional:None>', |
|
61 | 60 | 'userid': '<Optional:<OptionalAttr:apiuser>>', |
|
62 | 61 | 'send_email': '<Optional:True>'}] |
|
63 | 62 | assert_ok(id_, expected, given=response.body) |
@@ -1,143 +1,143 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | import urlobject |
|
24 | 23 | |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_error, assert_ok) |
|
27 | 26 | from rhodecode.lib import helpers as h |
|
28 |
from rhodecode.lib.utils |
|
|
27 | from rhodecode.lib.str_utils import safe_str | |
|
28 | ||
|
29 | 29 | |
|
30 | 30 | pytestmark = pytest.mark.backends("git", "hg") |
|
31 | 31 | |
|
32 | 32 | |
|
33 | 33 | @pytest.mark.usefixtures("testuser_api", "app") |
|
34 | 34 | class TestGetPullRequest(object): |
|
35 | 35 | |
|
36 | 36 | def test_api_get_pull_request(self, pr_util, http_host_only_stub): |
|
37 | 37 | from rhodecode.model.pull_request import PullRequestModel |
|
38 | 38 | pull_request = pr_util.create_pull_request(mergeable=True) |
|
39 | 39 | id_, params = build_data( |
|
40 | 40 | self.apikey, 'get_pull_request', |
|
41 | 41 | pullrequestid=pull_request.pull_request_id, merge_state=True) |
|
42 | 42 | |
|
43 | 43 | response = api_call(self.app, params) |
|
44 | 44 | |
|
45 | 45 | assert response.status == '200 OK' |
|
46 | 46 | |
|
47 | 47 | url_obj = urlobject.URLObject( |
|
48 | 48 | h.route_url( |
|
49 | 49 | 'pullrequest_show', |
|
50 | 50 | repo_name=pull_request.target_repo.repo_name, |
|
51 | 51 | pull_request_id=pull_request.pull_request_id)) |
|
52 | 52 | |
|
53 |
pr_url = safe_ |
|
|
53 | pr_url = safe_str( | |
|
54 | 54 | url_obj.with_netloc(http_host_only_stub)) |
|
55 |
source_url = safe_ |
|
|
55 | source_url = safe_str( | |
|
56 | 56 | pull_request.source_repo.clone_url().with_netloc(http_host_only_stub)) |
|
57 |
target_url = safe_ |
|
|
57 | target_url = safe_str( | |
|
58 | 58 | pull_request.target_repo.clone_url().with_netloc(http_host_only_stub)) |
|
59 |
shadow_url = safe_ |
|
|
59 | shadow_url = safe_str( | |
|
60 | 60 | PullRequestModel().get_shadow_clone_url(pull_request)) |
|
61 | 61 | |
|
62 | 62 | expected = { |
|
63 | 63 | 'pull_request_id': pull_request.pull_request_id, |
|
64 | 64 | 'url': pr_url, |
|
65 | 65 | 'title': pull_request.title, |
|
66 | 66 | 'description': pull_request.description, |
|
67 | 67 | 'status': pull_request.status, |
|
68 | 68 | 'state': pull_request.pull_request_state, |
|
69 | 69 | 'created_on': pull_request.created_on, |
|
70 | 70 | 'updated_on': pull_request.updated_on, |
|
71 | 71 | 'commit_ids': pull_request.revisions, |
|
72 | 72 | 'review_status': pull_request.calculated_review_status(), |
|
73 | 73 | 'mergeable': { |
|
74 | 74 | 'status': True, |
|
75 | 75 | 'message': 'This pull request can be automatically merged.', |
|
76 | 76 | }, |
|
77 | 77 | 'source': { |
|
78 | 78 | 'clone_url': source_url, |
|
79 | 79 | 'repository': pull_request.source_repo.repo_name, |
|
80 | 80 | 'reference': { |
|
81 | 81 | 'name': pull_request.source_ref_parts.name, |
|
82 | 82 | 'type': pull_request.source_ref_parts.type, |
|
83 | 83 | 'commit_id': pull_request.source_ref_parts.commit_id, |
|
84 | 84 | }, |
|
85 | 85 | }, |
|
86 | 86 | 'target': { |
|
87 | 87 | 'clone_url': target_url, |
|
88 | 88 | 'repository': pull_request.target_repo.repo_name, |
|
89 | 89 | 'reference': { |
|
90 | 90 | 'name': pull_request.target_ref_parts.name, |
|
91 | 91 | 'type': pull_request.target_ref_parts.type, |
|
92 | 92 | 'commit_id': pull_request.target_ref_parts.commit_id, |
|
93 | 93 | }, |
|
94 | 94 | }, |
|
95 | 95 | 'merge': { |
|
96 | 96 | 'clone_url': shadow_url, |
|
97 | 97 | 'reference': { |
|
98 | 98 | 'name': pull_request.shadow_merge_ref.name, |
|
99 | 99 | 'type': pull_request.shadow_merge_ref.type, |
|
100 | 100 | 'commit_id': pull_request.shadow_merge_ref.commit_id, |
|
101 | 101 | }, |
|
102 | 102 | }, |
|
103 | 103 | 'author': pull_request.author.get_api_data(include_secrets=False, |
|
104 | 104 | details='basic'), |
|
105 | 105 | 'reviewers': [ |
|
106 | 106 | { |
|
107 | 107 | 'user': reviewer.get_api_data(include_secrets=False, |
|
108 | 108 | details='basic'), |
|
109 | 109 | 'reasons': reasons, |
|
110 | 110 | 'review_status': st[0][1].status if st else 'not_reviewed', |
|
111 | 111 | } |
|
112 | 112 | for obj, reviewer, reasons, mandatory, st in |
|
113 | 113 | pull_request.reviewers_statuses() |
|
114 | 114 | ] |
|
115 | 115 | } |
|
116 | 116 | assert_ok(id_, expected, response.body) |
|
117 | 117 | |
|
118 | 118 | def test_api_get_pull_request_repo_error(self, pr_util): |
|
119 | 119 | pull_request = pr_util.create_pull_request() |
|
120 | 120 | id_, params = build_data( |
|
121 | 121 | self.apikey, 'get_pull_request', |
|
122 | 122 | repoid=666, pullrequestid=pull_request.pull_request_id) |
|
123 | 123 | response = api_call(self.app, params) |
|
124 | 124 | |
|
125 | 125 | expected = 'repository `666` does not exist' |
|
126 | 126 | assert_error(id_, expected, given=response.body) |
|
127 | 127 | |
|
128 | 128 | def test_api_get_pull_request_pull_request_error(self): |
|
129 | 129 | id_, params = build_data( |
|
130 | 130 | self.apikey, 'get_pull_request', pullrequestid=666) |
|
131 | 131 | response = api_call(self.app, params) |
|
132 | 132 | |
|
133 | 133 | expected = 'pull request `666` does not exist' |
|
134 | 134 | assert_error(id_, expected, given=response.body) |
|
135 | 135 | |
|
136 | 136 | def test_api_get_pull_request_pull_request_error_just_pr_id(self): |
|
137 | 137 | id_, params = build_data( |
|
138 | 138 | self.apikey, 'get_pull_request', |
|
139 | 139 | pullrequestid=666) |
|
140 | 140 | response = api_call(self.app, params) |
|
141 | 141 | |
|
142 | 142 | expected = 'pull request `666` does not exist' |
|
143 | 143 | assert_error(id_, expected, given=response.body) |
@@ -1,87 +1,83 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | import urlobject | |
|
24 | 22 | |
|
25 | 23 | from rhodecode.api.tests.utils import ( |
|
26 | 24 | build_data, api_call, assert_error, assert_ok) |
|
27 | from rhodecode.lib import helpers as h | |
|
28 | from rhodecode.lib.utils2 import safe_unicode | |
|
29 | 25 | |
|
30 | 26 | pytestmark = pytest.mark.backends("git", "hg") |
|
31 | 27 | |
|
32 | 28 | |
|
33 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
34 | 30 | class TestGetPullRequestComments(object): |
|
35 | 31 | |
|
36 | 32 | def test_api_get_pull_request_comments(self, pr_util, http_host_only_stub): |
|
37 | 33 | from rhodecode.model.pull_request import PullRequestModel |
|
38 | 34 | |
|
39 | 35 | pull_request = pr_util.create_pull_request(mergeable=True) |
|
40 | 36 | id_, params = build_data( |
|
41 | 37 | self.apikey, 'get_pull_request_comments', |
|
42 | 38 | pullrequestid=pull_request.pull_request_id) |
|
43 | 39 | |
|
44 | 40 | response = api_call(self.app, params) |
|
45 | 41 | |
|
46 | 42 | assert response.status == '200 OK' |
|
47 | 43 | resp_date = response.json['result'][0]['comment_created_on'] |
|
48 | 44 | resp_comment_id = response.json['result'][0]['comment_id'] |
|
49 | 45 | |
|
50 | 46 | expected = [ |
|
51 | 47 | {'comment_author': {'active': True, |
|
52 | 48 | 'full_name_or_username': 'RhodeCode Admin', |
|
53 | 49 | 'username': 'test_admin'}, |
|
54 | 50 | 'comment_created_on': resp_date, |
|
55 | 51 | 'comment_f_path': None, |
|
56 | 52 | 'comment_id': resp_comment_id, |
|
57 | 53 | 'comment_lineno': None, |
|
58 | 54 | 'comment_status': {'status': 'under_review', |
|
59 | 55 | 'status_lbl': 'Under Review'}, |
|
60 | 56 | 'comment_text': 'Auto status change to |new_status|\n\n.. |new_status| replace:: *"Under Review"*', |
|
61 | 57 | 'comment_type': 'note', |
|
62 | 58 | 'comment_resolved_by': None, |
|
63 | 59 | 'pull_request_version': None, |
|
64 | 60 | 'comment_last_version': 0, |
|
65 | 61 | 'comment_commit_id': None, |
|
66 | 62 | 'comment_pull_request_id': pull_request.pull_request_id |
|
67 | 63 | } |
|
68 | 64 | ] |
|
69 | 65 | assert_ok(id_, expected, response.body) |
|
70 | 66 | |
|
71 | 67 | def test_api_get_pull_request_comments_repo_error(self, pr_util): |
|
72 | 68 | pull_request = pr_util.create_pull_request() |
|
73 | 69 | id_, params = build_data( |
|
74 | 70 | self.apikey, 'get_pull_request_comments', |
|
75 | 71 | repoid=666, pullrequestid=pull_request.pull_request_id) |
|
76 | 72 | response = api_call(self.app, params) |
|
77 | 73 | |
|
78 | 74 | expected = 'repository `666` does not exist' |
|
79 | 75 | assert_error(id_, expected, given=response.body) |
|
80 | 76 | |
|
81 | 77 | def test_api_get_pull_request_comments_pull_request_error(self): |
|
82 | 78 | id_, params = build_data( |
|
83 | 79 | self.apikey, 'get_pull_request_comments', pullrequestid=666) |
|
84 | 80 | response = api_call(self.app, params) |
|
85 | 81 | |
|
86 | 82 | expected = 'pull request `666` does not exist' |
|
87 | 83 | assert_error(id_, expected, given=response.body) |
@@ -1,82 +1,81 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.meta import Session |
|
25 | 24 | from rhodecode.model.pull_request import PullRequestModel |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_error) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestGetPullRequest(object): |
|
32 | 31 | |
|
33 | 32 | @pytest.mark.backends("git", "hg") |
|
34 | 33 | def test_api_get_pull_requests(self, pr_util): |
|
35 | 34 | pull_request = pr_util.create_pull_request() |
|
36 | 35 | pull_request_2 = PullRequestModel().create( |
|
37 | 36 | created_by=pull_request.author, |
|
38 | 37 | source_repo=pull_request.source_repo, |
|
39 | 38 | source_ref=pull_request.source_ref, |
|
40 | 39 | target_repo=pull_request.target_repo, |
|
41 | 40 | target_ref=pull_request.target_ref, |
|
42 | 41 | revisions=pull_request.revisions, |
|
43 | 42 | reviewers=(), |
|
44 | 43 | observers=(), |
|
45 | 44 | title=pull_request.title, |
|
46 | 45 | description=pull_request.description, |
|
47 | 46 | ) |
|
48 | 47 | Session().commit() |
|
49 | 48 | id_, params = build_data( |
|
50 | 49 | self.apikey, 'get_pull_requests', |
|
51 | 50 | repoid=pull_request.target_repo.repo_name) |
|
52 | 51 | response = api_call(self.app, params) |
|
53 | 52 | assert response.status == '200 OK' |
|
54 | 53 | assert len(response.json['result']) == 2 |
|
55 | 54 | |
|
56 | 55 | PullRequestModel().close_pull_request( |
|
57 | 56 | pull_request_2, pull_request_2.author) |
|
58 | 57 | Session().commit() |
|
59 | 58 | |
|
60 | 59 | id_, params = build_data( |
|
61 | 60 | self.apikey, 'get_pull_requests', |
|
62 | 61 | repoid=pull_request.target_repo.repo_name, |
|
63 | 62 | status='new') |
|
64 | 63 | response = api_call(self.app, params) |
|
65 | 64 | assert response.status == '200 OK' |
|
66 | 65 | assert len(response.json['result']) == 1 |
|
67 | 66 | |
|
68 | 67 | id_, params = build_data( |
|
69 | 68 | self.apikey, 'get_pull_requests', |
|
70 | 69 | repoid=pull_request.target_repo.repo_name, |
|
71 | 70 | status='closed') |
|
72 | 71 | response = api_call(self.app, params) |
|
73 | 72 | assert response.status == '200 OK' |
|
74 | 73 | assert len(response.json['result']) == 1 |
|
75 | 74 | |
|
76 | 75 | @pytest.mark.backends("git", "hg") |
|
77 | 76 | def test_api_get_pull_requests_repo_error(self): |
|
78 | 77 | id_, params = build_data(self.apikey, 'get_pull_requests', repoid=666) |
|
79 | 78 | response = api_call(self.app, params) |
|
80 | 79 | |
|
81 | 80 | expected = 'repository `666` does not exist' |
|
82 | 81 | assert_error(id_, expected, given=response.body) |
@@ -1,143 +1,142 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.meta import Session |
|
25 | 24 | from rhodecode.model.repo import RepoModel |
|
26 | 25 | from rhodecode.model.user import UserModel |
|
27 | 26 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
28 | 27 | from rhodecode.api.tests.utils import ( |
|
29 | 28 | build_data, api_call, assert_ok, assert_error, expected_permissions) |
|
30 | 29 | |
|
31 | 30 | |
|
32 | 31 | @pytest.mark.usefixtures("testuser_api", "app") |
|
33 | 32 | class TestGetRepo(object): |
|
34 | 33 | @pytest.mark.parametrize("apikey_attr, expect_secrets", [ |
|
35 | 34 | ('apikey', True), |
|
36 | 35 | ('apikey_regular', False), |
|
37 | 36 | ]) |
|
38 | 37 | @pytest.mark.parametrize("cache_param", [ |
|
39 | 38 | True, |
|
40 | 39 | False, |
|
41 | 40 | None, |
|
42 | 41 | ]) |
|
43 | 42 | def test_api_get_repo( |
|
44 | 43 | self, apikey_attr, expect_secrets, cache_param, backend, |
|
45 | 44 | user_util): |
|
46 | 45 | repo = backend.create_repo() |
|
47 | 46 | repo_id = repo.repo_id |
|
48 | 47 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
49 | 48 | group = user_util.create_user_group(members=[usr]) |
|
50 | 49 | user_util.grant_user_group_permission_to_repo( |
|
51 | 50 | repo=repo, user_group=group, permission_name='repository.read') |
|
52 | 51 | Session().commit() |
|
53 | 52 | kwargs = { |
|
54 | 53 | 'repoid': repo.repo_name, |
|
55 | 54 | } |
|
56 | 55 | if cache_param is not None: |
|
57 | 56 | kwargs['cache'] = cache_param |
|
58 | 57 | |
|
59 | 58 | apikey = getattr(self, apikey_attr) |
|
60 | 59 | id_, params = build_data(apikey, 'get_repo', **kwargs) |
|
61 | 60 | response = api_call(self.app, params) |
|
62 | 61 | |
|
63 | 62 | ret = repo.get_api_data() |
|
64 | 63 | |
|
65 | 64 | permissions = expected_permissions(repo) |
|
66 | 65 | |
|
67 | 66 | followers = [] |
|
68 | 67 | |
|
69 | 68 | repo = RepoModel().get(repo_id) |
|
70 | 69 | for user in repo.followers: |
|
71 | 70 | followers.append(user.user.get_api_data( |
|
72 | 71 | include_secrets=expect_secrets)) |
|
73 | 72 | |
|
74 | 73 | ret['permissions'] = permissions |
|
75 | 74 | ret['followers'] = followers |
|
76 | 75 | |
|
77 | 76 | expected = ret |
|
78 | 77 | |
|
79 | 78 | assert_ok(id_, expected, given=response.body) |
|
80 | 79 | |
|
81 | 80 | @pytest.mark.parametrize("grant_perm", [ |
|
82 | 81 | 'repository.admin', |
|
83 | 82 | 'repository.write', |
|
84 | 83 | 'repository.read', |
|
85 | 84 | ]) |
|
86 | 85 | def test_api_get_repo_by_non_admin(self, grant_perm, backend): |
|
87 | 86 | # TODO: Depending on which tests are running before this one, we |
|
88 | 87 | # start with a different number of permissions in the database. |
|
89 | 88 | repo = RepoModel().get_by_repo_name(backend.repo_name) |
|
90 | 89 | repo_id = repo.repo_id |
|
91 | 90 | permission_count = len(repo.repo_to_perm) |
|
92 | 91 | |
|
93 | 92 | RepoModel().grant_user_permission(repo=backend.repo_name, |
|
94 | 93 | user=self.TEST_USER_LOGIN, |
|
95 | 94 | perm=grant_perm) |
|
96 | 95 | Session().commit() |
|
97 | 96 | id_, params = build_data( |
|
98 | 97 | self.apikey_regular, 'get_repo', repoid=backend.repo_name) |
|
99 | 98 | response = api_call(self.app, params) |
|
100 | 99 | |
|
101 | 100 | repo = RepoModel().get_by_repo_name(backend.repo_name) |
|
102 | 101 | ret = repo.get_api_data() |
|
103 | 102 | |
|
104 | 103 | assert permission_count + 1, len(repo.repo_to_perm) |
|
105 | 104 | |
|
106 | 105 | permissions = expected_permissions(repo) |
|
107 | 106 | |
|
108 | 107 | followers = [] |
|
109 | 108 | |
|
110 | 109 | repo = RepoModel().get(repo_id) |
|
111 | 110 | for user in repo.followers: |
|
112 | 111 | followers.append(user.user.get_api_data()) |
|
113 | 112 | |
|
114 | 113 | ret['permissions'] = permissions |
|
115 | 114 | ret['followers'] = followers |
|
116 | 115 | |
|
117 | 116 | expected = ret |
|
118 | 117 | try: |
|
119 | 118 | assert_ok(id_, expected, given=response.body) |
|
120 | 119 | finally: |
|
121 | 120 | RepoModel().revoke_user_permission( |
|
122 | 121 | backend.repo_name, self.TEST_USER_LOGIN) |
|
123 | 122 | |
|
124 | 123 | def test_api_get_repo_by_non_admin_no_permission_to_repo(self, backend): |
|
125 | 124 | RepoModel().grant_user_permission(repo=backend.repo_name, |
|
126 | 125 | user=self.TEST_USER_LOGIN, |
|
127 | 126 | perm='repository.none') |
|
128 | 127 | |
|
129 | 128 | id_, params = build_data( |
|
130 | 129 | self.apikey_regular, 'get_repo', repoid=backend.repo_name) |
|
131 | 130 | response = api_call(self.app, params) |
|
132 | 131 | |
|
133 | 132 | expected = 'repository `%s` does not exist' % (backend.repo_name) |
|
134 | 133 | assert_error(id_, expected, given=response.body) |
|
135 | 134 | |
|
136 | 135 | def test_api_get_repo_not_existing(self): |
|
137 | 136 | id_, params = build_data( |
|
138 | 137 | self.apikey, 'get_repo', repoid='no-such-repo') |
|
139 | 138 | response = api_call(self.app, params) |
|
140 | 139 | |
|
141 | 140 | ret = 'repository `%s` does not exist' % 'no-such-repo' |
|
142 | 141 | expected = ret |
|
143 | 142 | assert_error(id_, expected, given=response.body) |
@@ -1,141 +1,140 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.api.tests.utils import build_data, api_call, assert_error |
|
25 | 24 | |
|
26 | 25 | |
|
27 | 26 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | 27 | class TestGetRepoChangeset(object): |
|
29 | 28 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) |
|
30 | 29 | def test_get_repo_changeset(self, details, backend): |
|
31 | 30 | commit = backend.repo.get_commit(commit_idx=0) |
|
32 | 31 | __, params = build_data( |
|
33 | 32 | self.apikey, 'get_repo_changeset', |
|
34 | 33 | repoid=backend.repo_name, revision=commit.raw_id, |
|
35 | 34 | details=details, |
|
36 | 35 | ) |
|
37 | 36 | response = api_call(self.app, params) |
|
38 | 37 | result = response.json['result'] |
|
39 | 38 | assert result['revision'] == 0 |
|
40 | 39 | assert result['raw_id'] == commit.raw_id |
|
41 | 40 | |
|
42 | 41 | if details == 'full': |
|
43 | 42 | assert result['refs']['bookmarks'] == getattr( |
|
44 | 43 | commit, 'bookmarks', []) |
|
45 | 44 | branches = [commit.branch] if commit.branch else [] |
|
46 | 45 | assert result['refs']['branches'] == branches |
|
47 | 46 | assert result['refs']['tags'] == commit.tags |
|
48 | 47 | |
|
49 | 48 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) |
|
50 | 49 | def test_get_repo_changeset_bad_type(self, details, backend): |
|
51 | 50 | id_, params = build_data( |
|
52 | 51 | self.apikey, 'get_repo_changeset', |
|
53 | 52 | repoid=backend.repo_name, revision=0, |
|
54 | 53 | details=details, |
|
55 | 54 | ) |
|
56 | 55 | response = api_call(self.app, params) |
|
57 |
expected = "commit_id must be a string value got < |
|
|
56 | expected = "commit_id must be a string value got <class 'int'> instead" | |
|
58 | 57 | assert_error(id_, expected, given=response.body) |
|
59 | 58 | |
|
60 | 59 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) |
|
61 | 60 | def test_get_repo_changesets(self, details, backend): |
|
62 | 61 | limit = 2 |
|
63 | 62 | commit = backend.repo.get_commit(commit_idx=0) |
|
64 | 63 | __, params = build_data( |
|
65 | 64 | self.apikey, 'get_repo_changesets', |
|
66 | 65 | repoid=backend.repo_name, start_rev=commit.raw_id, limit=limit, |
|
67 | 66 | details=details, |
|
68 | 67 | ) |
|
69 | 68 | response = api_call(self.app, params) |
|
70 | 69 | result = response.json['result'] |
|
71 | 70 | assert result |
|
72 | 71 | assert len(result) == limit |
|
73 | 72 | for x in range(limit): |
|
74 | 73 | assert result[x]['revision'] == x |
|
75 | 74 | |
|
76 | 75 | if details == 'full': |
|
77 | 76 | for x in range(limit): |
|
78 | 77 | assert 'bookmarks' in result[x]['refs'] |
|
79 | 78 | assert 'branches' in result[x]['refs'] |
|
80 | 79 | assert 'tags' in result[x]['refs'] |
|
81 | 80 | |
|
82 | 81 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) |
|
83 | 82 | @pytest.mark.parametrize("start_rev, expected_revision", [ |
|
84 | 83 | ("0", 0), |
|
85 | 84 | ("10", 10), |
|
86 | 85 | ("20", 20), |
|
87 | 86 | ]) |
|
88 | 87 | @pytest.mark.backends("hg", "git") |
|
89 | 88 | def test_get_repo_changesets_commit_range( |
|
90 | 89 | self, details, backend, start_rev, expected_revision): |
|
91 | 90 | limit = 10 |
|
92 | 91 | __, params = build_data( |
|
93 | 92 | self.apikey, 'get_repo_changesets', |
|
94 | 93 | repoid=backend.repo_name, start_rev=start_rev, limit=limit, |
|
95 | 94 | details=details, |
|
96 | 95 | ) |
|
97 | 96 | response = api_call(self.app, params) |
|
98 | 97 | result = response.json['result'] |
|
99 | 98 | assert result |
|
100 | 99 | assert len(result) == limit |
|
101 | 100 | for i in range(limit): |
|
102 | 101 | assert result[i]['revision'] == int(expected_revision) + i |
|
103 | 102 | |
|
104 | 103 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) |
|
105 | 104 | @pytest.mark.parametrize("start_rev, expected_revision", [ |
|
106 | 105 | ("0", 0), |
|
107 | 106 | ("10", 9), |
|
108 | 107 | ("20", 19), |
|
109 | 108 | ]) |
|
110 | 109 | def test_get_repo_changesets_commit_range_svn( |
|
111 | 110 | self, details, backend_svn, start_rev, expected_revision): |
|
112 | 111 | |
|
113 | 112 | # TODO: johbo: SVN showed a problem here: The parameter "start_rev" |
|
114 | 113 | # in our API allows to pass in a "Commit ID" as well as a |
|
115 | 114 | # "Commit Index". In the case of Subversion it is not possible to |
|
116 | 115 | # distinguish these cases. As a workaround we implemented this |
|
117 | 116 | # behavior which gives a preference to see it as a "Commit ID". |
|
118 | 117 | |
|
119 | 118 | limit = 10 |
|
120 | 119 | __, params = build_data( |
|
121 | 120 | self.apikey, 'get_repo_changesets', |
|
122 | 121 | repoid=backend_svn.repo_name, start_rev=start_rev, limit=limit, |
|
123 | 122 | details=details, |
|
124 | 123 | ) |
|
125 | 124 | response = api_call(self.app, params) |
|
126 | 125 | result = response.json['result'] |
|
127 | 126 | assert result |
|
128 | 127 | assert len(result) == limit |
|
129 | 128 | for i in range(limit): |
|
130 | 129 | assert result[i]['revision'] == int(expected_revision) + i |
|
131 | 130 | |
|
132 | 131 | @pytest.mark.parametrize("details", ['basic', 'extended', 'full']) |
|
133 | 132 | def test_get_repo_changesets_bad_type(self, details, backend): |
|
134 | 133 | id_, params = build_data( |
|
135 | 134 | self.apikey, 'get_repo_changesets', |
|
136 | 135 | repoid=backend.repo_name, start_rev=0, limit=2, |
|
137 | 136 | details=details, |
|
138 | 137 | ) |
|
139 | 138 | response = api_call(self.app, params) |
|
140 |
expected = "commit_id must be a string value got < |
|
|
139 | expected = "commit_id must be a string value got <class 'int'> instead" | |
|
141 | 140 | assert_error(id_, expected, given=response.body) |
@@ -1,142 +1,141 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.db import User, ChangesetComment |
|
25 | 24 | from rhodecode.model.meta import Session |
|
26 | 25 | from rhodecode.model.comment import CommentsModel |
|
27 | 26 | from rhodecode.api.tests.utils import ( |
|
28 | 27 | build_data, api_call, assert_error, assert_call_ok) |
|
29 | 28 | |
|
30 | 29 | |
|
31 | 30 | @pytest.fixture() |
|
32 | 31 | def make_repo_comments_factory(request): |
|
33 | 32 | |
|
34 | 33 | class Make(object): |
|
35 | 34 | |
|
36 | 35 | def make_comments(self, repo): |
|
37 | 36 | user = User.get_first_super_admin() |
|
38 | 37 | commit = repo.scm_instance()[0] |
|
39 | 38 | |
|
40 | 39 | commit_id = commit.raw_id |
|
41 | 40 | file_0 = commit.affected_files[0] |
|
42 | 41 | comments = [] |
|
43 | 42 | |
|
44 | 43 | # general |
|
45 | 44 | comment = CommentsModel().create( |
|
46 | 45 | text='General Comment', repo=repo, user=user, commit_id=commit_id, |
|
47 | 46 | comment_type=ChangesetComment.COMMENT_TYPE_NOTE, send_email=False) |
|
48 | 47 | comments.append(comment) |
|
49 | 48 | |
|
50 | 49 | # inline |
|
51 | 50 | comment = CommentsModel().create( |
|
52 | 51 | text='Inline Comment', repo=repo, user=user, commit_id=commit_id, |
|
53 | 52 | f_path=file_0, line_no='n1', |
|
54 | 53 | comment_type=ChangesetComment.COMMENT_TYPE_NOTE, send_email=False) |
|
55 | 54 | comments.append(comment) |
|
56 | 55 | |
|
57 | 56 | # todo |
|
58 | 57 | comment = CommentsModel().create( |
|
59 | 58 | text='INLINE TODO Comment', repo=repo, user=user, commit_id=commit_id, |
|
60 | 59 | f_path=file_0, line_no='n1', |
|
61 | 60 | comment_type=ChangesetComment.COMMENT_TYPE_TODO, send_email=False) |
|
62 | 61 | comments.append(comment) |
|
63 | 62 | |
|
64 | 63 | return comments |
|
65 | 64 | |
|
66 | 65 | return Make() |
|
67 | 66 | |
|
68 | 67 | |
|
69 | 68 | @pytest.mark.usefixtures("testuser_api", "app") |
|
70 | 69 | class TestGetRepo(object): |
|
71 | 70 | |
|
72 | 71 | @pytest.mark.parametrize('filters, expected_count', [ |
|
73 | 72 | ({}, 3), |
|
74 | 73 | ({'comment_type': ChangesetComment.COMMENT_TYPE_NOTE}, 2), |
|
75 | 74 | ({'comment_type': ChangesetComment.COMMENT_TYPE_TODO}, 1), |
|
76 | 75 | ({'commit_id': 'FILLED DYNAMIC'}, 3), |
|
77 | 76 | ]) |
|
78 | 77 | def test_api_get_repo_comments(self, backend, user_util, |
|
79 | 78 | make_repo_comments_factory, filters, expected_count): |
|
80 | 79 | commits = [{'message': 'A'}, {'message': 'B'}] |
|
81 | 80 | repo = backend.create_repo(commits=commits) |
|
82 | 81 | make_repo_comments_factory.make_comments(repo) |
|
83 | 82 | |
|
84 | 83 | api_call_params = {'repoid': repo.repo_name,} |
|
85 | 84 | api_call_params.update(filters) |
|
86 | 85 | |
|
87 | 86 | if 'commit_id' in api_call_params: |
|
88 | 87 | commit = repo.scm_instance()[0] |
|
89 | 88 | commit_id = commit.raw_id |
|
90 | 89 | api_call_params['commit_id'] = commit_id |
|
91 | 90 | |
|
92 | 91 | id_, params = build_data(self.apikey, 'get_repo_comments', **api_call_params) |
|
93 | 92 | response = api_call(self.app, params) |
|
94 | 93 | result = assert_call_ok(id_, given=response.body) |
|
95 | 94 | |
|
96 | 95 | assert len(result) == expected_count |
|
97 | 96 | |
|
98 | 97 | def test_api_get_repo_comments_wrong_comment_type( |
|
99 | 98 | self, make_repo_comments_factory, backend_hg): |
|
100 | 99 | commits = [{'message': 'A'}, {'message': 'B'}] |
|
101 | 100 | repo = backend_hg.create_repo(commits=commits) |
|
102 | 101 | make_repo_comments_factory.make_comments(repo) |
|
103 | 102 | |
|
104 | 103 | api_call_params = {'repoid': repo.repo_name} |
|
105 | 104 | api_call_params.update({'comment_type': 'bogus'}) |
|
106 | 105 | |
|
107 | 106 | expected = 'comment_type must be one of `{}` got {}'.format( |
|
108 | 107 | ChangesetComment.COMMENT_TYPES, 'bogus') |
|
109 | 108 | id_, params = build_data(self.apikey, 'get_repo_comments', **api_call_params) |
|
110 | 109 | response = api_call(self.app, params) |
|
111 | 110 | assert_error(id_, expected, given=response.body) |
|
112 | 111 | |
|
113 | 112 | def test_api_get_comment(self, make_repo_comments_factory, backend_hg): |
|
114 | 113 | commits = [{'message': 'A'}, {'message': 'B'}] |
|
115 | 114 | repo = backend_hg.create_repo(commits=commits) |
|
116 | 115 | |
|
117 | 116 | comments = make_repo_comments_factory.make_comments(repo) |
|
118 | 117 | comment_ids = [x.comment_id for x in comments] |
|
119 | 118 | Session().commit() |
|
120 | 119 | |
|
121 | 120 | for comment_id in comment_ids: |
|
122 | 121 | id_, params = build_data(self.apikey, 'get_comment', |
|
123 | 122 | **{'comment_id': comment_id}) |
|
124 | 123 | response = api_call(self.app, params) |
|
125 | 124 | result = assert_call_ok(id_, given=response.body) |
|
126 | 125 | assert result['comment_id'] == comment_id |
|
127 | 126 | |
|
128 | 127 | def test_api_get_comment_no_access(self, make_repo_comments_factory, backend_hg, user_util): |
|
129 | 128 | commits = [{'message': 'A'}, {'message': 'B'}] |
|
130 | 129 | repo = backend_hg.create_repo(commits=commits) |
|
131 | 130 | comments = make_repo_comments_factory.make_comments(repo) |
|
132 | 131 | comment_id = comments[0].comment_id |
|
133 | 132 | |
|
134 | 133 | test_user = user_util.create_user() |
|
135 | 134 | user_util.grant_user_permission_to_repo(repo, test_user, 'repository.none') |
|
136 | 135 | |
|
137 | 136 | id_, params = build_data(test_user.api_key, 'get_comment', |
|
138 | 137 | **{'comment_id': comment_id}) |
|
139 | 138 | response = api_call(self.app, params) |
|
140 | 139 | assert_error(id_, |
|
141 | 140 | expected='comment `{}` does not exist'.format(comment_id), |
|
142 | 141 | given=response.body) |
@@ -1,55 +1,54 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.repo_group import RepoGroupModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_ok, assert_error, expected_permissions) |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 29 | class TestApiGetRepoGroup(object): |
|
31 | 30 | def test_api_get_repo_group(self, user_util): |
|
32 | 31 | repo_group = user_util.create_repo_group() |
|
33 | 32 | repo_group_name = repo_group.group_name |
|
34 | 33 | |
|
35 | 34 | id_, params = build_data( |
|
36 | 35 | self.apikey, 'get_repo_group', repogroupid=repo_group_name) |
|
37 | 36 | response = api_call(self.app, params) |
|
38 | 37 | |
|
39 | 38 | repo_group = RepoGroupModel()._get_repo_group(repo_group_name) |
|
40 | 39 | ret = repo_group.get_api_data() |
|
41 | 40 | |
|
42 | 41 | permissions = expected_permissions(repo_group) |
|
43 | 42 | |
|
44 | 43 | ret['permissions'] = permissions |
|
45 | 44 | expected = ret |
|
46 | 45 | assert_ok(id_, expected, given=response.body) |
|
47 | 46 | |
|
48 | 47 | def test_api_get_repo_group_not_existing(self): |
|
49 | 48 | id_, params = build_data( |
|
50 | 49 | self.apikey, 'get_repo_group', repogroupid='no-such-repo-group') |
|
51 | 50 | response = api_call(self.app, params) |
|
52 | 51 | |
|
53 | 52 | ret = 'repository group `%s` does not exist' % 'no-such-repo-group' |
|
54 | 53 | expected = ret |
|
55 | 54 | assert_error(id_, expected, given=response.body) |
@@ -1,40 +1,39 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.repo_group import RepoGroupModel |
|
25 | 24 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok, jsonify |
|
26 | 25 | |
|
27 | 26 | |
|
28 | 27 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | 28 | class TestApiGetRepoGroups(object): |
|
30 | 29 | def test_api_get_repo_groups(self): |
|
31 | 30 | id_, params = build_data(self.apikey, 'get_repo_groups') |
|
32 | 31 | response = api_call(self.app, params) |
|
33 | 32 | |
|
34 | 33 | result = [] |
|
35 | 34 | for repo in RepoGroupModel().get_all(): |
|
36 | 35 | result.append(repo.get_api_data()) |
|
37 | 36 | ret = jsonify(result) |
|
38 | 37 | |
|
39 | 38 | expected = ret |
|
40 | 39 | assert_ok(id_, expected, given=response.body) |
@@ -1,142 +1,141 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.meta import Session |
|
25 | 24 | from rhodecode.model.repo import RepoModel |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_error, assert_ok) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestGetRepoNodes(object): |
|
32 | 31 | @pytest.mark.parametrize("name, ret_type", [ |
|
33 | 32 | ('all', 'all'), |
|
34 | 33 | ('dirs', 'dirs'), |
|
35 | 34 | ('files', 'files'), |
|
36 | 35 | ]) |
|
37 | 36 | def test_api_get_repo_nodes(self, name, ret_type, backend): |
|
38 | 37 | commit_id = 'tip' |
|
39 | 38 | path = '/' |
|
40 | 39 | id_, params = build_data( |
|
41 | 40 | self.apikey, 'get_repo_nodes', |
|
42 | 41 | repoid=backend.repo_name, revision=commit_id, |
|
43 | 42 | root_path=path, |
|
44 | 43 | ret_type=ret_type) |
|
45 | 44 | response = api_call(self.app, params) |
|
46 | 45 | |
|
47 | 46 | # we don't the actual return types here since it's tested somewhere |
|
48 | 47 | # else |
|
49 | 48 | expected = response.json['result'] |
|
50 | 49 | assert_ok(id_, expected, given=response.body) |
|
51 | 50 | |
|
52 | 51 | def test_api_get_repo_nodes_bad_commits(self, backend): |
|
53 | 52 | commit_id = 'i-dont-exist' |
|
54 | 53 | path = '/' |
|
55 | 54 | id_, params = build_data( |
|
56 | 55 | self.apikey, 'get_repo_nodes', |
|
57 | 56 | repoid=backend.repo_name, revision=commit_id, |
|
58 | 57 | root_path=path, ) |
|
59 | 58 | response = api_call(self.app, params) |
|
60 | 59 | |
|
61 | 60 | expected = 'failed to get repo: `%s` nodes' % (backend.repo_name,) |
|
62 | 61 | assert_error(id_, expected, given=response.body) |
|
63 | 62 | |
|
64 | 63 | def test_api_get_repo_nodes_bad_path(self, backend): |
|
65 | 64 | commit_id = 'tip' |
|
66 | 65 | path = '/idontexits' |
|
67 | 66 | id_, params = build_data( |
|
68 | 67 | self.apikey, 'get_repo_nodes', |
|
69 | 68 | repoid=backend.repo_name, revision=commit_id, |
|
70 | 69 | root_path=path, ) |
|
71 | 70 | response = api_call(self.app, params) |
|
72 | 71 | |
|
73 | 72 | expected = 'failed to get repo: `%s` nodes' % (backend.repo_name,) |
|
74 | 73 | assert_error(id_, expected, given=response.body) |
|
75 | 74 | |
|
76 | 75 | def test_api_get_repo_nodes_max_file_bytes(self, backend): |
|
77 | 76 | commit_id = 'tip' |
|
78 | 77 | path = '/' |
|
79 | 78 | max_file_bytes = 500 |
|
80 | 79 | |
|
81 | 80 | id_, params = build_data( |
|
82 | 81 | self.apikey, 'get_repo_nodes', |
|
83 | 82 | repoid=backend.repo_name, revision=commit_id, details='full', |
|
84 | 83 | root_path=path) |
|
85 | 84 | response = api_call(self.app, params) |
|
86 | 85 | assert any(file['content'] and len(file['content']) > max_file_bytes |
|
87 | 86 | for file in response.json['result']) |
|
88 | 87 | |
|
89 | 88 | id_, params = build_data( |
|
90 | 89 | self.apikey, 'get_repo_nodes', |
|
91 | 90 | repoid=backend.repo_name, revision=commit_id, |
|
92 | 91 | root_path=path, details='full', |
|
93 | 92 | max_file_bytes=max_file_bytes) |
|
94 | 93 | response = api_call(self.app, params) |
|
95 | 94 | assert all( |
|
96 | 95 | file['content'] is None if file['size'] > max_file_bytes else True |
|
97 | 96 | for file in response.json['result']) |
|
98 | 97 | |
|
99 | 98 | def test_api_get_repo_nodes_bad_ret_type(self, backend): |
|
100 | 99 | commit_id = 'tip' |
|
101 | 100 | path = '/' |
|
102 | 101 | ret_type = 'error' |
|
103 | 102 | id_, params = build_data( |
|
104 | 103 | self.apikey, 'get_repo_nodes', |
|
105 | 104 | repoid=backend.repo_name, revision=commit_id, |
|
106 | 105 | root_path=path, |
|
107 | 106 | ret_type=ret_type) |
|
108 | 107 | response = api_call(self.app, params) |
|
109 | 108 | |
|
110 | 109 | expected = ('ret_type must be one of %s' |
|
111 | 110 | % (','.join(['all', 'dirs', 'files']))) |
|
112 | 111 | assert_error(id_, expected, given=response.body) |
|
113 | 112 | |
|
114 | 113 | @pytest.mark.parametrize("name, ret_type, grant_perm", [ |
|
115 | 114 | ('all', 'all', 'repository.write'), |
|
116 | 115 | ('dirs', 'dirs', 'repository.admin'), |
|
117 | 116 | ('files', 'files', 'repository.read'), |
|
118 | 117 | ]) |
|
119 | 118 | def test_api_get_repo_nodes_by_regular_user( |
|
120 | 119 | self, name, ret_type, grant_perm, backend): |
|
121 | 120 | RepoModel().grant_user_permission(repo=backend.repo_name, |
|
122 | 121 | user=self.TEST_USER_LOGIN, |
|
123 | 122 | perm=grant_perm) |
|
124 | 123 | Session().commit() |
|
125 | 124 | |
|
126 | 125 | commit_id = 'tip' |
|
127 | 126 | path = '/' |
|
128 | 127 | id_, params = build_data( |
|
129 | 128 | self.apikey_regular, 'get_repo_nodes', |
|
130 | 129 | repoid=backend.repo_name, revision=commit_id, |
|
131 | 130 | root_path=path, |
|
132 | 131 | ret_type=ret_type) |
|
133 | 132 | response = api_call(self.app, params) |
|
134 | 133 | |
|
135 | 134 | # we don't the actual return types here since it's tested somewhere |
|
136 | 135 | # else |
|
137 | 136 | expected = response.json['result'] |
|
138 | 137 | try: |
|
139 | 138 | assert_ok(id_, expected, given=response.body) |
|
140 | 139 | finally: |
|
141 | 140 | RepoModel().revoke_user_permission( |
|
142 | 141 | backend.repo_name, self.TEST_USER_LOGIN) |
@@ -1,40 +1,39 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.meta import Session |
|
25 | 24 | from rhodecode.model.repo import RepoModel |
|
26 | 25 | from rhodecode.model.user import UserModel |
|
27 | 26 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
28 | 27 | from rhodecode.api.tests.utils import ( |
|
29 | 28 | build_data, api_call, assert_ok, assert_error, expected_permissions) |
|
30 | 29 | |
|
31 | 30 | |
|
32 | 31 | @pytest.mark.usefixtures("testuser_api", "app") |
|
33 | 32 | class TestGetRepo(object): |
|
34 | 33 | def test_api_get_repo_refs(self, backend, user_util): |
|
35 | 34 | repo = backend.create_repo() |
|
36 | 35 | id_, params = build_data(self.apikey, 'get_repo_refs', |
|
37 | 36 | **{'repoid': repo.repo_name,}) |
|
38 | 37 | response = api_call(self.app, params) |
|
39 | 38 | expected = repo.scm_instance().refs() |
|
40 | 39 | assert_ok(id_, expected, given=response.body) |
@@ -1,129 +1,128 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.repo import RepoModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_ok, assert_error, jsonify) |
|
27 | 26 | from rhodecode.model.db import User |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestGetRepos(object): |
|
32 | 31 | def test_api_get_repos(self): |
|
33 | 32 | id_, params = build_data(self.apikey, 'get_repos') |
|
34 | 33 | response = api_call(self.app, params) |
|
35 | 34 | |
|
36 | 35 | result = [] |
|
37 | 36 | for repo in RepoModel().get_all(): |
|
38 | 37 | result.append(repo.get_api_data(include_secrets=True)) |
|
39 | 38 | ret = jsonify(result) |
|
40 | 39 | |
|
41 | 40 | expected = ret |
|
42 | 41 | assert_ok(id_, expected, given=response.body) |
|
43 | 42 | |
|
44 | 43 | def test_api_get_repos_only_toplevel(self, user_util): |
|
45 | 44 | repo_group = user_util.create_repo_group(auto_cleanup=True) |
|
46 | 45 | user_util.create_repo(parent=repo_group) |
|
47 | 46 | |
|
48 | 47 | id_, params = build_data(self.apikey, 'get_repos', traverse=0) |
|
49 | 48 | response = api_call(self.app, params) |
|
50 | 49 | |
|
51 | 50 | result = [] |
|
52 | 51 | for repo in RepoModel().get_repos_for_root(root=None): |
|
53 | 52 | result.append(repo.get_api_data(include_secrets=True)) |
|
54 | 53 | expected = jsonify(result) |
|
55 | 54 | |
|
56 | 55 | assert_ok(id_, expected, given=response.body) |
|
57 | 56 | |
|
58 | 57 | def test_api_get_repos_with_wrong_root(self): |
|
59 | 58 | id_, params = build_data(self.apikey, 'get_repos', root='abracadabra') |
|
60 | 59 | response = api_call(self.app, params) |
|
61 | 60 | |
|
62 | 61 | expected = 'Root repository group `abracadabra` does not exist' |
|
63 | 62 | assert_error(id_, expected, given=response.body) |
|
64 | 63 | |
|
65 | 64 | def test_api_get_repos_with_root(self, user_util): |
|
66 | 65 | repo_group = user_util.create_repo_group(auto_cleanup=True) |
|
67 | 66 | repo_group_name = repo_group.group_name |
|
68 | 67 | |
|
69 | 68 | user_util.create_repo(parent=repo_group) |
|
70 | 69 | user_util.create_repo(parent=repo_group) |
|
71 | 70 | |
|
72 | 71 | # nested, should not show up |
|
73 | 72 | user_util._test_name = '{}/'.format(repo_group_name) |
|
74 | 73 | sub_repo_group = user_util.create_repo_group(auto_cleanup=True) |
|
75 | 74 | user_util.create_repo(parent=sub_repo_group) |
|
76 | 75 | |
|
77 | 76 | id_, params = build_data(self.apikey, 'get_repos', |
|
78 | 77 | root=repo_group_name, traverse=0) |
|
79 | 78 | response = api_call(self.app, params) |
|
80 | 79 | |
|
81 | 80 | result = [] |
|
82 | 81 | for repo in RepoModel().get_repos_for_root(repo_group): |
|
83 | 82 | result.append(repo.get_api_data(include_secrets=True)) |
|
84 | 83 | |
|
85 | 84 | assert len(result) == 2 |
|
86 | 85 | expected = jsonify(result) |
|
87 | 86 | assert_ok(id_, expected, given=response.body) |
|
88 | 87 | |
|
89 | 88 | def test_api_get_repos_with_root_and_traverse(self, user_util): |
|
90 | 89 | repo_group = user_util.create_repo_group(auto_cleanup=True) |
|
91 | 90 | repo_group_name = repo_group.group_name |
|
92 | 91 | |
|
93 | 92 | user_util.create_repo(parent=repo_group) |
|
94 | 93 | user_util.create_repo(parent=repo_group) |
|
95 | 94 | |
|
96 | 95 | # nested, should not show up |
|
97 | 96 | user_util._test_name = '{}/'.format(repo_group_name) |
|
98 | 97 | sub_repo_group = user_util.create_repo_group(auto_cleanup=True) |
|
99 | 98 | user_util.create_repo(parent=sub_repo_group) |
|
100 | 99 | |
|
101 | 100 | id_, params = build_data(self.apikey, 'get_repos', |
|
102 | 101 | root=repo_group_name, traverse=1) |
|
103 | 102 | response = api_call(self.app, params) |
|
104 | 103 | |
|
105 | 104 | result = [] |
|
106 | 105 | for repo in RepoModel().get_repos_for_root( |
|
107 | 106 | repo_group_name, traverse=True): |
|
108 | 107 | result.append(repo.get_api_data(include_secrets=True)) |
|
109 | 108 | |
|
110 | 109 | assert len(result) == 3 |
|
111 | 110 | expected = jsonify(result) |
|
112 | 111 | assert_ok(id_, expected, given=response.body) |
|
113 | 112 | |
|
114 | 113 | def test_api_get_repos_non_admin(self): |
|
115 | 114 | id_, params = build_data(self.apikey_regular, 'get_repos') |
|
116 | 115 | response = api_call(self.app, params) |
|
117 | 116 | |
|
118 | 117 | user = User.get_by_username(self.TEST_USER_LOGIN) |
|
119 | 118 | allowed_repos = user.AuthUser().permissions['repositories'] |
|
120 | 119 | |
|
121 | 120 | result = [] |
|
122 | 121 | for repo in RepoModel().get_all(): |
|
123 | 122 | perm = allowed_repos[repo.repo_name] |
|
124 | 123 | if perm in ['repository.read', 'repository.write', 'repository.admin']: |
|
125 | 124 | result.append(repo.get_api_data()) |
|
126 | 125 | ret = jsonify(result) |
|
127 | 126 | |
|
128 | 127 | expected = ret |
|
129 | 128 | assert_ok(id_, expected, given=response.body) |
@@ -1,84 +1,83 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.scm import ScmModel |
|
25 | 24 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok |
|
26 | 25 | |
|
27 | 26 | |
|
28 | 27 | @pytest.fixture() |
|
29 | 28 | def http_host_stub(): |
|
30 | 29 | """ |
|
31 | 30 | To ensure that we can get an IP address, this test shall run with a |
|
32 | 31 | hostname set to "localhost". |
|
33 | 32 | """ |
|
34 | 33 | return 'localhost:80' |
|
35 | 34 | |
|
36 | 35 | |
|
37 | 36 | @pytest.mark.usefixtures("testuser_api", "app") |
|
38 | 37 | class TestGetServerInfo(object): |
|
39 | 38 | def test_api_get_server_info(self): |
|
40 | 39 | id_, params = build_data(self.apikey, 'get_server_info') |
|
41 | 40 | response = api_call(self.app, params) |
|
42 | 41 | resp = response.json |
|
43 | 42 | expected = ScmModel().get_server_info() |
|
44 | 43 | expected['memory'] = resp['result']['memory'] |
|
45 | 44 | expected['uptime'] = resp['result']['uptime'] |
|
46 | 45 | expected['load'] = resp['result']['load'] |
|
47 | 46 | expected['cpu'] = resp['result']['cpu'] |
|
48 | 47 | expected['storage'] = resp['result']['storage'] |
|
49 | 48 | expected['storage_temp'] = resp['result']['storage_temp'] |
|
50 | 49 | expected['storage_inodes'] = resp['result']['storage_inodes'] |
|
51 | 50 | expected['server'] = resp['result']['server'] |
|
52 | 51 | |
|
53 | 52 | expected['index_storage'] = resp['result']['index_storage'] |
|
54 | 53 | expected['storage'] = resp['result']['storage'] |
|
55 | 54 | |
|
56 | 55 | assert_ok(id_, expected, given=response.body) |
|
57 | 56 | |
|
58 | 57 | def test_api_get_server_info_ip(self): |
|
59 | 58 | id_, params = build_data(self.apikey, 'get_server_info') |
|
60 | 59 | response = api_call(self.app, params) |
|
61 | 60 | resp = response.json |
|
62 | 61 | expected = ScmModel().get_server_info({'SERVER_NAME': 'unknown'}) |
|
63 | 62 | expected['memory'] = resp['result']['memory'] |
|
64 | 63 | expected['uptime'] = resp['result']['uptime'] |
|
65 | 64 | expected['load'] = resp['result']['load'] |
|
66 | 65 | expected['cpu'] = resp['result']['cpu'] |
|
67 | 66 | expected['storage'] = resp['result']['storage'] |
|
68 | 67 | expected['storage_temp'] = resp['result']['storage_temp'] |
|
69 | 68 | expected['storage_inodes'] = resp['result']['storage_inodes'] |
|
70 | 69 | expected['server'] = resp['result']['server'] |
|
71 | 70 | |
|
72 | 71 | expected['index_storage'] = resp['result']['index_storage'] |
|
73 | 72 | expected['storage'] = resp['result']['storage'] |
|
74 | 73 | |
|
75 | 74 | assert_ok(id_, expected, given=response.body) |
|
76 | 75 | |
|
77 | 76 | def test_api_get_server_info_data_for_search_index_build(self): |
|
78 | 77 | id_, params = build_data(self.apikey, 'get_server_info') |
|
79 | 78 | response = api_call(self.app, params) |
|
80 | 79 | resp = response.json |
|
81 | 80 | |
|
82 | 81 | # required by indexer |
|
83 | 82 | assert resp['result']['index_storage'] |
|
84 | 83 | assert resp['result']['storage'] |
@@ -1,86 +1,85 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import pytest |
|
22 | 21 | |
|
23 | 22 | from rhodecode.lib.auth import AuthUser |
|
24 | 23 | from rhodecode.model.user import UserModel |
|
25 | 24 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_ok, assert_error) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestGetUser(object): |
|
32 | 31 | def test_api_get_user(self): |
|
33 | 32 | id_, params = build_data( |
|
34 | 33 | self.apikey, 'get_user', userid=TEST_USER_ADMIN_LOGIN) |
|
35 | 34 | response = api_call(self.app, params) |
|
36 | 35 | |
|
37 | 36 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
38 | 37 | ret = usr.get_api_data(include_secrets=True) |
|
39 | 38 | permissions = AuthUser(usr.user_id).permissions |
|
40 | 39 | ret['permissions'] = permissions |
|
41 | 40 | ret['permissions_summary'] = permissions |
|
42 | 41 | |
|
43 | 42 | expected = ret |
|
44 | 43 | assert_ok(id_, expected, given=response.body) |
|
45 | 44 | |
|
46 | 45 | def test_api_get_user_not_existing(self): |
|
47 | 46 | id_, params = build_data(self.apikey, 'get_user', userid='trololo') |
|
48 | 47 | response = api_call(self.app, params) |
|
49 | 48 | |
|
50 | 49 | expected = "user `%s` does not exist" % 'trololo' |
|
51 | 50 | assert_error(id_, expected, given=response.body) |
|
52 | 51 | |
|
53 | 52 | def test_api_get_user_without_giving_userid(self): |
|
54 | 53 | id_, params = build_data(self.apikey, 'get_user') |
|
55 | 54 | response = api_call(self.app, params) |
|
56 | 55 | |
|
57 | 56 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
58 | 57 | ret = usr.get_api_data(include_secrets=True) |
|
59 | 58 | permissions = AuthUser(usr.user_id).permissions |
|
60 | 59 | ret['permissions'] = permissions |
|
61 | 60 | ret['permissions_summary'] = permissions |
|
62 | 61 | |
|
63 | 62 | expected = ret |
|
64 | 63 | assert_ok(id_, expected, given=response.body) |
|
65 | 64 | |
|
66 | 65 | def test_api_get_user_without_giving_userid_non_admin(self): |
|
67 | 66 | id_, params = build_data(self.apikey_regular, 'get_user') |
|
68 | 67 | response = api_call(self.app, params) |
|
69 | 68 | |
|
70 | 69 | usr = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
71 | 70 | ret = usr.get_api_data(include_secrets=True) |
|
72 | 71 | permissions = AuthUser(usr.user_id).permissions |
|
73 | 72 | ret['permissions'] = permissions |
|
74 | 73 | ret['permissions_summary'] = permissions |
|
75 | 74 | |
|
76 | 75 | expected = ret |
|
77 | 76 | assert_ok(id_, expected, given=response.body) |
|
78 | 77 | |
|
79 | 78 | def test_api_get_user_with_giving_userid_non_admin(self): |
|
80 | 79 | id_, params = build_data( |
|
81 | 80 | self.apikey_regular, 'get_user', |
|
82 | 81 | userid=self.TEST_USER_LOGIN) |
|
83 | 82 | response = api_call(self.app, params) |
|
84 | 83 | |
|
85 | 84 | expected = 'userid is not the same as your user' |
|
86 | 85 | assert_error(id_, expected, given=response.body) |
@@ -1,76 +1,75 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import pytest |
|
22 | 21 | |
|
23 | 22 | from rhodecode.model.user import UserModel |
|
24 | 23 | from rhodecode.api.tests.utils import ( |
|
25 | 24 | build_data, api_call, assert_ok, assert_error, expected_permissions) |
|
26 | 25 | |
|
27 | 26 | |
|
28 | 27 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | 28 | class TestGetUserGroups(object): |
|
30 | 29 | def test_api_get_user_group(self, user_util): |
|
31 | 30 | user, group = user_util.create_user_with_group() |
|
32 | 31 | id_, params = build_data( |
|
33 | 32 | self.apikey, 'get_user_group', usergroupid=group.users_group_name) |
|
34 | 33 | response = api_call(self.app, params) |
|
35 | 34 | |
|
36 | 35 | ret = group.get_api_data() |
|
37 | 36 | ret['users'] = [user.get_api_data()] |
|
38 | 37 | |
|
39 | 38 | permissions = expected_permissions(group) |
|
40 | 39 | |
|
41 | 40 | ret['permissions'] = permissions |
|
42 | 41 | ret['permissions_summary'] = response.json['result']['permissions_summary'] |
|
43 | 42 | expected = ret |
|
44 | 43 | assert_ok(id_, expected, given=response.body) |
|
45 | 44 | |
|
46 | 45 | def test_api_get_user_group_regular_user(self, user_util): |
|
47 | 46 | user, group = user_util.create_user_with_group() |
|
48 | 47 | id_, params = build_data( |
|
49 | 48 | self.apikey_regular, 'get_user_group', |
|
50 | 49 | usergroupid=group.users_group_name) |
|
51 | 50 | response = api_call(self.app, params) |
|
52 | 51 | |
|
53 | 52 | ret = group.get_api_data() |
|
54 | 53 | ret['users'] = [user.get_api_data()] |
|
55 | 54 | |
|
56 | 55 | permissions = expected_permissions(group) |
|
57 | 56 | |
|
58 | 57 | ret['permissions'] = permissions |
|
59 | 58 | ret['permissions_summary'] = response.json['result']['permissions_summary'] |
|
60 | 59 | expected = ret |
|
61 | 60 | assert_ok(id_, expected, given=response.body) |
|
62 | 61 | |
|
63 | 62 | def test_api_get_user_group_regular_user_permission_denied( |
|
64 | 63 | self, user_util): |
|
65 | 64 | group = user_util.create_user_group() |
|
66 | 65 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
67 | 66 | group_name = group.users_group_name |
|
68 | 67 | user_util.grant_user_permission_to_user_group( |
|
69 | 68 | group, user, 'usergroup.none') |
|
70 | 69 | |
|
71 | 70 | id_, params = build_data( |
|
72 | 71 | self.apikey_regular, 'get_user_group', usergroupid=group_name) |
|
73 | 72 | response = api_call(self.app, params) |
|
74 | 73 | |
|
75 | 74 | expected = 'user group `%s` does not exist' % (group_name,) |
|
76 | 75 | assert_error(id_, expected, given=response.body) |
@@ -1,71 +1,69 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | import json | |
|
23 | ||
|
24 | 21 | import pytest |
|
25 | 22 | |
|
26 | 23 | from rhodecode.model.user import UserModel |
|
27 | 24 | from rhodecode.api.tests.utils import build_data, api_call |
|
25 | from rhodecode.lib.ext_json import json | |
|
28 | 26 | |
|
29 | 27 | |
|
30 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 29 | class TestGetUserGroups(object): |
|
32 | 30 | @pytest.mark.parametrize("apikey_attr, expect_secrets", [ |
|
33 | 31 | ('apikey', True), |
|
34 | 32 | ('apikey_regular', False), |
|
35 | 33 | ]) |
|
36 | 34 | def test_api_get_user_groups(self, apikey_attr, expect_secrets, user_util): |
|
37 | 35 | first_group = user_util.create_user_group() |
|
38 | 36 | second_group = user_util.create_user_group() |
|
39 | 37 | expected = [ |
|
40 | 38 | g.get_api_data(include_secrets=expect_secrets) |
|
41 | 39 | for g in (first_group, second_group)] |
|
42 | 40 | |
|
43 | 41 | apikey = getattr(self, apikey_attr) |
|
44 | 42 | id_, params = build_data(apikey, 'get_user_groups', ) |
|
45 | 43 | response = api_call(self.app, params) |
|
46 | 44 | self._assert_ok(id_, expected, response) |
|
47 | 45 | |
|
48 | 46 | def test_api_get_user_groups_regular_user(self, user_util): |
|
49 | 47 | first_group = user_util.create_user_group() |
|
50 | 48 | second_group = user_util.create_user_group() |
|
51 | 49 | expected = [g.get_api_data() for g in (first_group, second_group)] |
|
52 | 50 | |
|
53 | 51 | id_, params = build_data(self.apikey_regular, 'get_user_groups', ) |
|
54 | 52 | response = api_call(self.app, params) |
|
55 | 53 | self._assert_ok(id_, expected, response) |
|
56 | 54 | |
|
57 | 55 | def test_api_get_user_groups_regular_user_no_permission(self, user_util): |
|
58 | 56 | group = user_util.create_user_group() |
|
59 | 57 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
60 | 58 | user_util.grant_user_permission_to_user_group( |
|
61 | 59 | group, user, 'usergroup.none') |
|
62 | 60 | id_, params = build_data(self.apikey_regular, 'get_user_groups', ) |
|
63 | 61 | response = api_call(self.app, params) |
|
64 | 62 | expected = [] |
|
65 | 63 | self._assert_ok(id_, expected, response) |
|
66 | 64 | |
|
67 | 65 | def _assert_ok(self, id_, expected_list, response): |
|
68 | 66 | result = json.loads(response.body) |
|
69 | 67 | assert result['id'] == id_ |
|
70 | 68 | assert result['error'] is None |
|
71 |
assert |
|
|
69 | assert result['result'] == expected_list |
@@ -1,40 +1,39 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import pytest |
|
22 | 21 | |
|
23 | 22 | from rhodecode.model.db import User |
|
24 | 23 | from rhodecode.api.tests.utils import ( |
|
25 | 24 | build_data, api_call, assert_ok, jsonify) |
|
26 | 25 | |
|
27 | 26 | |
|
28 | 27 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | 28 | class TestGetUsers(object): |
|
30 | 29 | def test_api_get_users(self): |
|
31 | 30 | id_, params = build_data(self.apikey, 'get_users', ) |
|
32 | 31 | response = api_call(self.app, params) |
|
33 | 32 | ret_all = [] |
|
34 | 33 | _users = User.query().filter(User.username != User.DEFAULT_USER) \ |
|
35 | 34 | .order_by(User.username).all() |
|
36 | 35 | for usr in _users: |
|
37 | 36 | ret = usr.get_api_data(include_secrets=True) |
|
38 | 37 | ret_all.append(jsonify(ret)) |
|
39 | 38 | expected = ret_all |
|
40 | 39 | assert_ok(id_, expected, given=response.body) |
@@ -1,90 +1,89 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.repo import RepoModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_error, assert_ok, crash) |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 29 | class TestGrantUserGroupPermission(object): |
|
31 | 30 | @pytest.mark.parametrize("name, perm", [ |
|
32 | 31 | ('none', 'repository.none'), |
|
33 | 32 | ('read', 'repository.read'), |
|
34 | 33 | ('write', 'repository.write'), |
|
35 | 34 | ('admin', 'repository.admin') |
|
36 | 35 | ]) |
|
37 | 36 | def test_api_grant_user_group_permission( |
|
38 | 37 | self, name, perm, backend, user_util): |
|
39 | 38 | user_group = user_util.create_user_group() |
|
40 | 39 | id_, params = build_data( |
|
41 | 40 | self.apikey, |
|
42 | 41 | 'grant_user_group_permission', |
|
43 | 42 | repoid=backend.repo_name, |
|
44 | 43 | usergroupid=user_group.users_group_name, |
|
45 | 44 | perm=perm) |
|
46 | 45 | response = api_call(self.app, params) |
|
47 | 46 | |
|
48 | 47 | ret = { |
|
49 | 48 | 'msg': 'Granted perm: `%s` for user group: `%s` in repo: `%s`' % ( |
|
50 | 49 | perm, user_group.users_group_name, backend.repo_name |
|
51 | 50 | ), |
|
52 | 51 | 'success': True |
|
53 | 52 | } |
|
54 | 53 | expected = ret |
|
55 | 54 | assert_ok(id_, expected, given=response.body) |
|
56 | 55 | |
|
57 | 56 | def test_api_grant_user_group_permission_wrong_permission( |
|
58 | 57 | self, backend, user_util): |
|
59 | 58 | perm = 'haha.no.permission' |
|
60 | 59 | user_group = user_util.create_user_group() |
|
61 | 60 | id_, params = build_data( |
|
62 | 61 | self.apikey, |
|
63 | 62 | 'grant_user_group_permission', |
|
64 | 63 | repoid=backend.repo_name, |
|
65 | 64 | usergroupid=user_group.users_group_name, |
|
66 | 65 | perm=perm) |
|
67 | 66 | response = api_call(self.app, params) |
|
68 | 67 | |
|
69 | 68 | expected = 'permission `%s` does not exist.' % (perm,) |
|
70 | 69 | assert_error(id_, expected, given=response.body) |
|
71 | 70 | |
|
72 | 71 | @mock.patch.object(RepoModel, 'grant_user_group_permission', crash) |
|
73 | 72 | def test_api_grant_user_group_permission_exception_when_adding( |
|
74 | 73 | self, backend, user_util): |
|
75 | 74 | perm = 'repository.read' |
|
76 | 75 | user_group = user_util.create_user_group() |
|
77 | 76 | id_, params = build_data( |
|
78 | 77 | self.apikey, |
|
79 | 78 | 'grant_user_group_permission', |
|
80 | 79 | repoid=backend.repo_name, |
|
81 | 80 | usergroupid=user_group.users_group_name, |
|
82 | 81 | perm=perm) |
|
83 | 82 | response = api_call(self.app, params) |
|
84 | 83 | |
|
85 | 84 | expected = ( |
|
86 | 85 | 'failed to edit permission for user group: `%s` in repo: `%s`' % ( |
|
87 | 86 | user_group.users_group_name, backend.repo_name |
|
88 | 87 | ) |
|
89 | 88 | ) |
|
90 | 89 | assert_error(id_, expected, given=response.body) |
@@ -1,173 +1,172 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.user import UserModel |
|
25 | 24 | from rhodecode.model.repo_group import RepoGroupModel |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_error, assert_ok, crash) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestGrantUserGroupPermissionFromRepoGroup(object): |
|
32 | 31 | @pytest.mark.parametrize("name, perm, apply_to_children", [ |
|
33 | 32 | ('none', 'group.none', 'none'), |
|
34 | 33 | ('read', 'group.read', 'none'), |
|
35 | 34 | ('write', 'group.write', 'none'), |
|
36 | 35 | ('admin', 'group.admin', 'none'), |
|
37 | 36 | |
|
38 | 37 | ('none', 'group.none', 'all'), |
|
39 | 38 | ('read', 'group.read', 'all'), |
|
40 | 39 | ('write', 'group.write', 'all'), |
|
41 | 40 | ('admin', 'group.admin', 'all'), |
|
42 | 41 | |
|
43 | 42 | ('none', 'group.none', 'repos'), |
|
44 | 43 | ('read', 'group.read', 'repos'), |
|
45 | 44 | ('write', 'group.write', 'repos'), |
|
46 | 45 | ('admin', 'group.admin', 'repos'), |
|
47 | 46 | |
|
48 | 47 | ('none', 'group.none', 'groups'), |
|
49 | 48 | ('read', 'group.read', 'groups'), |
|
50 | 49 | ('write', 'group.write', 'groups'), |
|
51 | 50 | ('admin', 'group.admin', 'groups'), |
|
52 | 51 | ]) |
|
53 | 52 | def test_api_grant_user_group_permission_to_repo_group( |
|
54 | 53 | self, name, perm, apply_to_children, user_util): |
|
55 | 54 | user_group = user_util.create_user_group() |
|
56 | 55 | repo_group = user_util.create_repo_group() |
|
57 | 56 | user_util.create_repo(parent=repo_group) |
|
58 | 57 | |
|
59 | 58 | id_, params = build_data( |
|
60 | 59 | self.apikey, |
|
61 | 60 | 'grant_user_group_permission_to_repo_group', |
|
62 | 61 | repogroupid=repo_group.name, |
|
63 | 62 | usergroupid=user_group.users_group_name, |
|
64 | 63 | perm=perm, |
|
65 | 64 | apply_to_children=apply_to_children,) |
|
66 | 65 | response = api_call(self.app, params) |
|
67 | 66 | |
|
68 | 67 | ret = { |
|
69 | 68 | 'msg': ( |
|
70 | 69 | 'Granted perm: `%s` (recursive:%s) for user group: `%s`' |
|
71 | 70 | ' in repo group: `%s`' % ( |
|
72 | 71 | perm, apply_to_children, user_group.users_group_name, |
|
73 | 72 | repo_group.name |
|
74 | 73 | ) |
|
75 | 74 | ), |
|
76 | 75 | 'success': True |
|
77 | 76 | } |
|
78 | 77 | expected = ret |
|
79 | 78 | try: |
|
80 | 79 | assert_ok(id_, expected, given=response.body) |
|
81 | 80 | finally: |
|
82 | 81 | RepoGroupModel().revoke_user_group_permission( |
|
83 | 82 | repo_group.group_id, user_group.users_group_id) |
|
84 | 83 | |
|
85 | 84 | @pytest.mark.parametrize( |
|
86 | 85 | "name, perm, apply_to_children, grant_admin, access_ok", [ |
|
87 | 86 | ('none_fails', 'group.none', 'none', False, False), |
|
88 | 87 | ('read_fails', 'group.read', 'none', False, False), |
|
89 | 88 | ('write_fails', 'group.write', 'none', False, False), |
|
90 | 89 | ('admin_fails', 'group.admin', 'none', False, False), |
|
91 | 90 | |
|
92 | 91 | # with granted perms |
|
93 | 92 | ('none_ok', 'group.none', 'none', True, True), |
|
94 | 93 | ('read_ok', 'group.read', 'none', True, True), |
|
95 | 94 | ('write_ok', 'group.write', 'none', True, True), |
|
96 | 95 | ('admin_ok', 'group.admin', 'none', True, True), |
|
97 | 96 | ] |
|
98 | 97 | ) |
|
99 | 98 | def test_api_grant_user_group_permission_to_repo_group_by_regular_user( |
|
100 | 99 | self, name, perm, apply_to_children, grant_admin, access_ok, |
|
101 | 100 | user_util): |
|
102 | 101 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
103 | 102 | user_group = user_util.create_user_group() |
|
104 | 103 | repo_group = user_util.create_repo_group() |
|
105 | 104 | if grant_admin: |
|
106 | 105 | user_util.grant_user_permission_to_repo_group( |
|
107 | 106 | repo_group, user, 'group.admin') |
|
108 | 107 | |
|
109 | 108 | id_, params = build_data( |
|
110 | 109 | self.apikey_regular, |
|
111 | 110 | 'grant_user_group_permission_to_repo_group', |
|
112 | 111 | repogroupid=repo_group.name, |
|
113 | 112 | usergroupid=user_group.users_group_name, |
|
114 | 113 | perm=perm, |
|
115 | 114 | apply_to_children=apply_to_children,) |
|
116 | 115 | response = api_call(self.app, params) |
|
117 | 116 | if access_ok: |
|
118 | 117 | ret = { |
|
119 | 118 | 'msg': ( |
|
120 | 119 | 'Granted perm: `%s` (recursive:%s) for user group: `%s`' |
|
121 | 120 | ' in repo group: `%s`' % ( |
|
122 | 121 | perm, apply_to_children, user_group.users_group_name, |
|
123 | 122 | repo_group.name |
|
124 | 123 | ) |
|
125 | 124 | ), |
|
126 | 125 | 'success': True |
|
127 | 126 | } |
|
128 | 127 | expected = ret |
|
129 | 128 | try: |
|
130 | 129 | assert_ok(id_, expected, given=response.body) |
|
131 | 130 | finally: |
|
132 | 131 | RepoGroupModel().revoke_user_group_permission( |
|
133 | 132 | repo_group.group_id, user_group.users_group_id) |
|
134 | 133 | else: |
|
135 | 134 | expected = 'repository group `%s` does not exist' % (repo_group.name,) |
|
136 | 135 | assert_error(id_, expected, given=response.body) |
|
137 | 136 | |
|
138 | 137 | def test_api_grant_user_group_permission_to_repo_group_wrong_permission( |
|
139 | 138 | self, user_util): |
|
140 | 139 | user_group = user_util.create_user_group() |
|
141 | 140 | repo_group = user_util.create_repo_group() |
|
142 | 141 | perm = 'haha.no.permission' |
|
143 | 142 | id_, params = build_data( |
|
144 | 143 | self.apikey, |
|
145 | 144 | 'grant_user_group_permission_to_repo_group', |
|
146 | 145 | repogroupid=repo_group.name, |
|
147 | 146 | usergroupid=user_group.users_group_name, |
|
148 | 147 | perm=perm) |
|
149 | 148 | response = api_call(self.app, params) |
|
150 | 149 | |
|
151 | 150 | expected = 'permission `%s` does not exist. Permission should start with prefix: `group.`' % (perm,) |
|
152 | 151 | assert_error(id_, expected, given=response.body) |
|
153 | 152 | |
|
154 | 153 | @mock.patch.object(RepoGroupModel, 'grant_user_group_permission', crash) |
|
155 | 154 | def test_api_grant_user_group_permission_exception_when_adding_2( |
|
156 | 155 | self, user_util): |
|
157 | 156 | user_group = user_util.create_user_group() |
|
158 | 157 | repo_group = user_util.create_repo_group() |
|
159 | 158 | perm = 'group.read' |
|
160 | 159 | id_, params = build_data( |
|
161 | 160 | self.apikey, |
|
162 | 161 | 'grant_user_group_permission_to_repo_group', |
|
163 | 162 | repogroupid=repo_group.name, |
|
164 | 163 | usergroupid=user_group.users_group_name, |
|
165 | 164 | perm=perm) |
|
166 | 165 | response = api_call(self.app, params) |
|
167 | 166 | |
|
168 | 167 | expected = ( |
|
169 | 168 | 'failed to edit permission for user group: `%s`' |
|
170 | 169 | ' in repo group: `%s`' % ( |
|
171 | 170 | user_group.users_group_name, repo_group.name) |
|
172 | 171 | ) |
|
173 | 172 | assert_error(id_, expected, given=response.body) |
@@ -1,97 +1,96 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import pytest |
|
22 | 21 | |
|
23 | 22 | from rhodecode.model.user_group import UserGroupModel |
|
24 | 23 | from rhodecode.api.tests.utils import ( |
|
25 | 24 | build_data, api_call, assert_ok, assert_error) |
|
26 | 25 | |
|
27 | 26 | |
|
28 | 27 | @pytest.mark.usefixtures("testuser_api", "app") |
|
29 | 28 | class TestGrantUserGroupPermissionFromUserGroup(object): |
|
30 | 29 | @pytest.mark.parametrize("name, perm", [ |
|
31 | 30 | ('none', 'usergroup.none'), |
|
32 | 31 | ('read', 'usergroup.read'), |
|
33 | 32 | ('write', 'usergroup.write'), |
|
34 | 33 | ('admin', 'usergroup.admin'), |
|
35 | 34 | |
|
36 | 35 | ('none', 'usergroup.none'), |
|
37 | 36 | ('read', 'usergroup.read'), |
|
38 | 37 | ('write', 'usergroup.write'), |
|
39 | 38 | ('admin', 'usergroup.admin'), |
|
40 | 39 | |
|
41 | 40 | ('none', 'usergroup.none'), |
|
42 | 41 | ('read', 'usergroup.read'), |
|
43 | 42 | ('write', 'usergroup.write'), |
|
44 | 43 | ('admin', 'usergroup.admin'), |
|
45 | 44 | |
|
46 | 45 | ('none', 'usergroup.none'), |
|
47 | 46 | ('read', 'usergroup.read'), |
|
48 | 47 | ('write', 'usergroup.write'), |
|
49 | 48 | ('admin', 'usergroup.admin'), |
|
50 | 49 | ]) |
|
51 | 50 | def test_api_grant_user_group_permission_to_user_group( |
|
52 | 51 | self, name, perm, user_util): |
|
53 | 52 | group = user_util.create_user_group() |
|
54 | 53 | target_group = user_util.create_user_group() |
|
55 | 54 | |
|
56 | 55 | id_, params = build_data( |
|
57 | 56 | self.apikey, |
|
58 | 57 | 'grant_user_group_permission_to_user_group', |
|
59 | 58 | usergroupid=target_group.users_group_name, |
|
60 | 59 | sourceusergroupid=group.users_group_name, |
|
61 | 60 | perm=perm) |
|
62 | 61 | response = api_call(self.app, params) |
|
63 | 62 | |
|
64 | 63 | expected = { |
|
65 | 64 | 'msg': ( |
|
66 | 65 | 'Granted perm: `%s` for user group: `%s`' |
|
67 | 66 | ' in user group: `%s`' % ( |
|
68 | 67 | perm, group.users_group_name, |
|
69 | 68 | target_group.users_group_name |
|
70 | 69 | ) |
|
71 | 70 | ), |
|
72 | 71 | 'success': True |
|
73 | 72 | } |
|
74 | 73 | try: |
|
75 | 74 | assert_ok(id_, expected, given=response.body) |
|
76 | 75 | finally: |
|
77 | 76 | UserGroupModel().revoke_user_group_permission( |
|
78 | 77 | target_group.users_group_id, group.users_group_id) |
|
79 | 78 | |
|
80 | 79 | def test_api_grant_user_group_permission_to_user_group_same_failure( |
|
81 | 80 | self, user_util): |
|
82 | 81 | group = user_util.create_user_group() |
|
83 | 82 | |
|
84 | 83 | id_, params = build_data( |
|
85 | 84 | self.apikey, |
|
86 | 85 | 'grant_user_group_permission_to_user_group', |
|
87 | 86 | usergroupid=group.users_group_name, |
|
88 | 87 | sourceusergroupid=group.users_group_name, |
|
89 | 88 | perm='usergroup.none') |
|
90 | 89 | response = api_call(self.app, params) |
|
91 | 90 | |
|
92 | 91 | expected = ( |
|
93 | 92 | 'failed to edit permission for user group: `%s`' |
|
94 | 93 | ' in user group: `%s`' % ( |
|
95 | 94 | group.users_group_name, group.users_group_name) |
|
96 | 95 | ) |
|
97 | 96 | assert_error(id_, expected, given=response.body) |
@@ -1,87 +1,86 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.repo import RepoModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_error, assert_ok, crash) |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 29 | class TestGrantUserPermission(object): |
|
31 | 30 | @pytest.mark.parametrize("name, perm", [ |
|
32 | 31 | ('none', 'repository.none'), |
|
33 | 32 | ('read', 'repository.read'), |
|
34 | 33 | ('write', 'repository.write'), |
|
35 | 34 | ('admin', 'repository.admin') |
|
36 | 35 | ]) |
|
37 | 36 | def test_api_grant_user_permission(self, name, perm, backend, user_util): |
|
38 | 37 | user = user_util.create_user() |
|
39 | 38 | id_, params = build_data( |
|
40 | 39 | self.apikey, |
|
41 | 40 | 'grant_user_permission', |
|
42 | 41 | repoid=backend.repo_name, |
|
43 | 42 | userid=user.username, |
|
44 | 43 | perm=perm) |
|
45 | 44 | response = api_call(self.app, params) |
|
46 | 45 | |
|
47 | 46 | ret = { |
|
48 | 47 | 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % ( |
|
49 | 48 | perm, user.username, backend.repo_name |
|
50 | 49 | ), |
|
51 | 50 | 'success': True |
|
52 | 51 | } |
|
53 | 52 | expected = ret |
|
54 | 53 | assert_ok(id_, expected, given=response.body) |
|
55 | 54 | |
|
56 | 55 | def test_api_grant_user_permission_wrong_permission( |
|
57 | 56 | self, backend, user_util): |
|
58 | 57 | user = user_util.create_user() |
|
59 | 58 | perm = 'haha.no.permission' |
|
60 | 59 | id_, params = build_data( |
|
61 | 60 | self.apikey, |
|
62 | 61 | 'grant_user_permission', |
|
63 | 62 | repoid=backend.repo_name, |
|
64 | 63 | userid=user.username, |
|
65 | 64 | perm=perm) |
|
66 | 65 | response = api_call(self.app, params) |
|
67 | 66 | |
|
68 | 67 | expected = 'permission `%s` does not exist.' % (perm,) |
|
69 | 68 | assert_error(id_, expected, given=response.body) |
|
70 | 69 | |
|
71 | 70 | @mock.patch.object(RepoModel, 'grant_user_permission', crash) |
|
72 | 71 | def test_api_grant_user_permission_exception_when_adding( |
|
73 | 72 | self, backend, user_util): |
|
74 | 73 | user = user_util.create_user() |
|
75 | 74 | perm = 'repository.read' |
|
76 | 75 | id_, params = build_data( |
|
77 | 76 | self.apikey, |
|
78 | 77 | 'grant_user_permission', |
|
79 | 78 | repoid=backend.repo_name, |
|
80 | 79 | userid=user.username, |
|
81 | 80 | perm=perm) |
|
82 | 81 | response = api_call(self.app, params) |
|
83 | 82 | |
|
84 | 83 | expected = 'failed to edit permission for user: `%s` in repo: `%s`' % ( |
|
85 | 84 | user.username, backend.repo_name |
|
86 | 85 | ) |
|
87 | 86 | assert_error(id_, expected, given=response.body) |
@@ -1,157 +1,156 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.user import UserModel |
|
25 | 24 | from rhodecode.model.repo_group import RepoGroupModel |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_error, assert_ok, crash) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestGrantUserPermissionFromRepoGroup(object): |
|
32 | 31 | @pytest.mark.parametrize("name, perm, apply_to_children", [ |
|
33 | 32 | ('none', 'group.none', 'none'), |
|
34 | 33 | ('read', 'group.read', 'none'), |
|
35 | 34 | ('write', 'group.write', 'none'), |
|
36 | 35 | ('admin', 'group.admin', 'none'), |
|
37 | 36 | |
|
38 | 37 | ('none', 'group.none', 'all'), |
|
39 | 38 | ('read', 'group.read', 'all'), |
|
40 | 39 | ('write', 'group.write', 'all'), |
|
41 | 40 | ('admin', 'group.admin', 'all'), |
|
42 | 41 | |
|
43 | 42 | ('none', 'group.none', 'repos'), |
|
44 | 43 | ('read', 'group.read', 'repos'), |
|
45 | 44 | ('write', 'group.write', 'repos'), |
|
46 | 45 | ('admin', 'group.admin', 'repos'), |
|
47 | 46 | |
|
48 | 47 | ('none', 'group.none', 'groups'), |
|
49 | 48 | ('read', 'group.read', 'groups'), |
|
50 | 49 | ('write', 'group.write', 'groups'), |
|
51 | 50 | ('admin', 'group.admin', 'groups'), |
|
52 | 51 | ]) |
|
53 | 52 | def test_api_grant_user_permission_to_repo_group( |
|
54 | 53 | self, name, perm, apply_to_children, user_util): |
|
55 | 54 | user = user_util.create_user() |
|
56 | 55 | repo_group = user_util.create_repo_group() |
|
57 | 56 | id_, params = build_data( |
|
58 | 57 | self.apikey, 'grant_user_permission_to_repo_group', |
|
59 | 58 | repogroupid=repo_group.name, userid=user.username, |
|
60 | 59 | perm=perm, apply_to_children=apply_to_children) |
|
61 | 60 | response = api_call(self.app, params) |
|
62 | 61 | |
|
63 | 62 | ret = { |
|
64 | 63 | 'msg': ( |
|
65 | 64 | 'Granted perm: `%s` (recursive:%s) for user: `%s`' |
|
66 | 65 | ' in repo group: `%s`' % ( |
|
67 | 66 | perm, apply_to_children, user.username, repo_group.name |
|
68 | 67 | ) |
|
69 | 68 | ), |
|
70 | 69 | 'success': True |
|
71 | 70 | } |
|
72 | 71 | expected = ret |
|
73 | 72 | assert_ok(id_, expected, given=response.body) |
|
74 | 73 | |
|
75 | 74 | @pytest.mark.parametrize( |
|
76 | 75 | "name, perm, apply_to_children, grant_admin, access_ok", [ |
|
77 | 76 | ('none_fails', 'group.none', 'none', False, False), |
|
78 | 77 | ('read_fails', 'group.read', 'none', False, False), |
|
79 | 78 | ('write_fails', 'group.write', 'none', False, False), |
|
80 | 79 | ('admin_fails', 'group.admin', 'none', False, False), |
|
81 | 80 | |
|
82 | 81 | # with granted perms |
|
83 | 82 | ('none_ok', 'group.none', 'none', True, True), |
|
84 | 83 | ('read_ok', 'group.read', 'none', True, True), |
|
85 | 84 | ('write_ok', 'group.write', 'none', True, True), |
|
86 | 85 | ('admin_ok', 'group.admin', 'none', True, True), |
|
87 | 86 | ] |
|
88 | 87 | ) |
|
89 | 88 | def test_api_grant_user_permission_to_repo_group_by_regular_user( |
|
90 | 89 | self, name, perm, apply_to_children, grant_admin, access_ok, |
|
91 | 90 | user_util): |
|
92 | 91 | user = user_util.create_user() |
|
93 | 92 | repo_group = user_util.create_repo_group() |
|
94 | 93 | |
|
95 | 94 | if grant_admin: |
|
96 | 95 | test_user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
97 | 96 | user_util.grant_user_permission_to_repo_group( |
|
98 | 97 | repo_group, test_user, 'group.admin') |
|
99 | 98 | |
|
100 | 99 | id_, params = build_data( |
|
101 | 100 | self.apikey_regular, 'grant_user_permission_to_repo_group', |
|
102 | 101 | repogroupid=repo_group.name, userid=user.username, |
|
103 | 102 | perm=perm, apply_to_children=apply_to_children) |
|
104 | 103 | response = api_call(self.app, params) |
|
105 | 104 | if access_ok: |
|
106 | 105 | ret = { |
|
107 | 106 | 'msg': ( |
|
108 | 107 | 'Granted perm: `%s` (recursive:%s) for user: `%s`' |
|
109 | 108 | ' in repo group: `%s`' % ( |
|
110 | 109 | perm, apply_to_children, user.username, repo_group.name |
|
111 | 110 | ) |
|
112 | 111 | ), |
|
113 | 112 | 'success': True |
|
114 | 113 | } |
|
115 | 114 | expected = ret |
|
116 | 115 | assert_ok(id_, expected, given=response.body) |
|
117 | 116 | else: |
|
118 | 117 | expected = 'repository group `%s` does not exist' % ( |
|
119 | 118 | repo_group.name, ) |
|
120 | 119 | assert_error(id_, expected, given=response.body) |
|
121 | 120 | |
|
122 | 121 | def test_api_grant_user_permission_to_repo_group_wrong_permission( |
|
123 | 122 | self, user_util): |
|
124 | 123 | user = user_util.create_user() |
|
125 | 124 | repo_group = user_util.create_repo_group() |
|
126 | 125 | perm = 'haha.no.permission' |
|
127 | 126 | id_, params = build_data( |
|
128 | 127 | self.apikey, |
|
129 | 128 | 'grant_user_permission_to_repo_group', |
|
130 | 129 | repogroupid=repo_group.name, |
|
131 | 130 | userid=user.username, |
|
132 | 131 | perm=perm) |
|
133 | 132 | response = api_call(self.app, params) |
|
134 | 133 | |
|
135 | 134 | expected = 'permission `%s` does not exist. Permission should start with prefix: `group.`' % (perm,) |
|
136 | 135 | assert_error(id_, expected, given=response.body) |
|
137 | 136 | |
|
138 | 137 | @mock.patch.object(RepoGroupModel, 'grant_user_permission', crash) |
|
139 | 138 | def test_api_grant_user_permission_to_repo_group_exception_when_adding( |
|
140 | 139 | self, user_util): |
|
141 | 140 | user = user_util.create_user() |
|
142 | 141 | repo_group = user_util.create_repo_group() |
|
143 | 142 | perm = 'group.read' |
|
144 | 143 | id_, params = build_data( |
|
145 | 144 | self.apikey, |
|
146 | 145 | 'grant_user_permission_to_repo_group', |
|
147 | 146 | repogroupid=repo_group.name, |
|
148 | 147 | userid=user.username, |
|
149 | 148 | perm=perm) |
|
150 | 149 | response = api_call(self.app, params) |
|
151 | 150 | |
|
152 | 151 | expected = ( |
|
153 | 152 | 'failed to edit permission for user: `%s` in repo group: `%s`' % ( |
|
154 | 153 | user.username, repo_group.name |
|
155 | 154 | ) |
|
156 | 155 | ) |
|
157 | 156 | assert_error(id_, expected, given=response.body) |
@@ -1,156 +1,155 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.user import UserModel |
|
25 | 24 | from rhodecode.model.user_group import UserGroupModel |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_error, assert_ok, crash) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestGrantUserPermissionFromUserGroup(object): |
|
32 | 31 | @pytest.mark.parametrize("name, perm", [ |
|
33 | 32 | ('none', 'usergroup.none'), |
|
34 | 33 | ('read', 'usergroup.read'), |
|
35 | 34 | ('write', 'usergroup.write'), |
|
36 | 35 | ('admin', 'usergroup.admin'), |
|
37 | 36 | |
|
38 | 37 | ('none', 'usergroup.none'), |
|
39 | 38 | ('read', 'usergroup.read'), |
|
40 | 39 | ('write', 'usergroup.write'), |
|
41 | 40 | ('admin', 'usergroup.admin'), |
|
42 | 41 | |
|
43 | 42 | ('none', 'usergroup.none'), |
|
44 | 43 | ('read', 'usergroup.read'), |
|
45 | 44 | ('write', 'usergroup.write'), |
|
46 | 45 | ('admin', 'usergroup.admin'), |
|
47 | 46 | |
|
48 | 47 | ('none', 'usergroup.none'), |
|
49 | 48 | ('read', 'usergroup.read'), |
|
50 | 49 | ('write', 'usergroup.write'), |
|
51 | 50 | ('admin', 'usergroup.admin'), |
|
52 | 51 | ]) |
|
53 | 52 | def test_api_grant_user_permission_to_user_group( |
|
54 | 53 | self, name, perm, user_util): |
|
55 | 54 | user = user_util.create_user() |
|
56 | 55 | group = user_util.create_user_group() |
|
57 | 56 | id_, params = build_data( |
|
58 | 57 | self.apikey, |
|
59 | 58 | 'grant_user_permission_to_user_group', |
|
60 | 59 | usergroupid=group.users_group_name, |
|
61 | 60 | userid=user.username, |
|
62 | 61 | perm=perm) |
|
63 | 62 | response = api_call(self.app, params) |
|
64 | 63 | |
|
65 | 64 | ret = { |
|
66 | 65 | 'msg': 'Granted perm: `%s` for user: `%s` in user group: `%s`' % ( |
|
67 | 66 | perm, user.username, group.users_group_name |
|
68 | 67 | ), |
|
69 | 68 | 'success': True |
|
70 | 69 | } |
|
71 | 70 | expected = ret |
|
72 | 71 | assert_ok(id_, expected, given=response.body) |
|
73 | 72 | |
|
74 | 73 | @pytest.mark.parametrize("name, perm, grant_admin, access_ok", [ |
|
75 | 74 | ('none_fails', 'usergroup.none', False, False), |
|
76 | 75 | ('read_fails', 'usergroup.read', False, False), |
|
77 | 76 | ('write_fails', 'usergroup.write', False, False), |
|
78 | 77 | ('admin_fails', 'usergroup.admin', False, False), |
|
79 | 78 | |
|
80 | 79 | # with granted perms |
|
81 | 80 | ('none_ok', 'usergroup.none', True, True), |
|
82 | 81 | ('read_ok', 'usergroup.read', True, True), |
|
83 | 82 | ('write_ok', 'usergroup.write', True, True), |
|
84 | 83 | ('admin_ok', 'usergroup.admin', True, True), |
|
85 | 84 | ]) |
|
86 | 85 | def test_api_grant_user_permission_to_user_group_by_regular_user( |
|
87 | 86 | self, name, perm, grant_admin, access_ok, user_util): |
|
88 | 87 | api_user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
89 | 88 | user = user_util.create_user() |
|
90 | 89 | group = user_util.create_user_group() |
|
91 | 90 | # grant the user ability to at least read the group |
|
92 | 91 | permission = 'usergroup.admin' if grant_admin else 'usergroup.read' |
|
93 | 92 | user_util.grant_user_permission_to_user_group( |
|
94 | 93 | group, api_user, permission) |
|
95 | 94 | |
|
96 | 95 | id_, params = build_data( |
|
97 | 96 | self.apikey_regular, |
|
98 | 97 | 'grant_user_permission_to_user_group', |
|
99 | 98 | usergroupid=group.users_group_name, |
|
100 | 99 | userid=user.username, |
|
101 | 100 | perm=perm) |
|
102 | 101 | response = api_call(self.app, params) |
|
103 | 102 | |
|
104 | 103 | if access_ok: |
|
105 | 104 | ret = { |
|
106 | 105 | 'msg': ( |
|
107 | 106 | 'Granted perm: `%s` for user: `%s` in user group: `%s`' % ( |
|
108 | 107 | perm, user.username, group.users_group_name |
|
109 | 108 | ) |
|
110 | 109 | ), |
|
111 | 110 | 'success': True |
|
112 | 111 | } |
|
113 | 112 | expected = ret |
|
114 | 113 | assert_ok(id_, expected, given=response.body) |
|
115 | 114 | else: |
|
116 | 115 | expected = 'user group `%s` does not exist' % ( |
|
117 | 116 | group.users_group_name) |
|
118 | 117 | assert_error(id_, expected, given=response.body) |
|
119 | 118 | |
|
120 | 119 | def test_api_grant_user_permission_to_user_group_wrong_permission( |
|
121 | 120 | self, user_util): |
|
122 | 121 | user = user_util.create_user() |
|
123 | 122 | group = user_util.create_user_group() |
|
124 | 123 | perm = 'haha.no.permission' |
|
125 | 124 | id_, params = build_data( |
|
126 | 125 | self.apikey, |
|
127 | 126 | 'grant_user_permission_to_user_group', |
|
128 | 127 | usergroupid=group.users_group_name, |
|
129 | 128 | userid=user.username, |
|
130 | 129 | perm=perm) |
|
131 | 130 | response = api_call(self.app, params) |
|
132 | 131 | |
|
133 | 132 | expected = 'permission `%s` does not exist. Permission should start with prefix: `usergroup.`' % perm |
|
134 | 133 | assert_error(id_, expected, given=response.body) |
|
135 | 134 | |
|
136 | 135 | def test_api_grant_user_permission_to_user_group_exception_when_adding( |
|
137 | 136 | self, user_util): |
|
138 | 137 | user = user_util.create_user() |
|
139 | 138 | group = user_util.create_user_group() |
|
140 | 139 | |
|
141 | 140 | perm = 'usergroup.read' |
|
142 | 141 | id_, params = build_data( |
|
143 | 142 | self.apikey, |
|
144 | 143 | 'grant_user_permission_to_user_group', |
|
145 | 144 | usergroupid=group.users_group_name, |
|
146 | 145 | userid=user.username, |
|
147 | 146 | perm=perm) |
|
148 | 147 | with mock.patch.object(UserGroupModel, 'grant_user_permission', crash): |
|
149 | 148 | response = api_call(self.app, params) |
|
150 | 149 | |
|
151 | 150 | expected = ( |
|
152 | 151 | 'failed to edit permission for user: `%s` in user group: `%s`' % ( |
|
153 | 152 | user.username, group.users_group_name |
|
154 | 153 | ) |
|
155 | 154 | ) |
|
156 | 155 | assert_error(id_, expected, given=response.body) |
@@ -1,68 +1,67 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.scm import ScmModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_ok, assert_error, crash) |
|
27 | 26 | from rhodecode.model.repo import RepoModel |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestInvalidateCache(object): |
|
32 | 31 | |
|
33 | 32 | def _set_cache(self, repo_name): |
|
34 | 33 | repo = RepoModel().get_by_repo_name(repo_name) |
|
35 | 34 | repo.scm_instance(cache=True) |
|
36 | 35 | |
|
37 | 36 | def test_api_invalidate_cache(self, backend): |
|
38 | 37 | self._set_cache(backend.repo_name) |
|
39 | 38 | |
|
40 | 39 | id_, params = build_data( |
|
41 | 40 | self.apikey, 'invalidate_cache', repoid=backend.repo_name) |
|
42 | 41 | response = api_call(self.app, params) |
|
43 | 42 | |
|
44 | 43 | expected = { |
|
45 | 44 | 'msg': "Cache for repository `%s` was invalidated" % ( |
|
46 | 45 | backend.repo_name,), |
|
47 | 46 | 'repository': backend.repo_name, |
|
48 | 47 | } |
|
49 | 48 | assert_ok(id_, expected, given=response.body) |
|
50 | 49 | |
|
51 | 50 | @mock.patch.object(ScmModel, 'mark_for_invalidation', crash) |
|
52 | 51 | def test_api_invalidate_cache_error(self, backend): |
|
53 | 52 | id_, params = build_data( |
|
54 | 53 | self.apikey, 'invalidate_cache', repoid=backend.repo_name) |
|
55 | 54 | response = api_call(self.app, params) |
|
56 | 55 | |
|
57 | 56 | expected = 'Error occurred during cache invalidation action' |
|
58 | 57 | assert_error(id_, expected, given=response.body) |
|
59 | 58 | |
|
60 | 59 | def test_api_invalidate_cache_regular_user_no_permission(self, backend): |
|
61 | 60 | self._set_cache(backend.repo_name) |
|
62 | 61 | |
|
63 | 62 | id_, params = build_data( |
|
64 | 63 | self.apikey_regular, 'invalidate_cache', repoid=backend.repo_name) |
|
65 | 64 | response = api_call(self.app, params) |
|
66 | 65 | |
|
67 | 66 | expected = "repository `%s` does not exist" % (backend.repo_name,) |
|
68 | 67 | assert_error(id_, expected, given=response.body) |
@@ -1,259 +1,258 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import pytest |
|
22 | 21 | |
|
23 | 22 | from rhodecode.model.db import UserLog, PullRequest |
|
24 | 23 | from rhodecode.model.meta import Session |
|
25 | 24 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_error, assert_ok) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestMergePullRequest(object): |
|
32 | 31 | |
|
33 | 32 | @pytest.mark.backends("git", "hg") |
|
34 | 33 | def test_api_merge_pull_request_merge_failed(self, pr_util, no_notifications): |
|
35 | 34 | pull_request = pr_util.create_pull_request(mergeable=True) |
|
36 | 35 | pull_request_id = pull_request.pull_request_id |
|
37 | 36 | pull_request_repo = pull_request.target_repo.repo_name |
|
38 | 37 | |
|
39 | 38 | id_, params = build_data( |
|
40 | 39 | self.apikey, 'merge_pull_request', |
|
41 | 40 | repoid=pull_request_repo, |
|
42 | 41 | pullrequestid=pull_request_id) |
|
43 | 42 | |
|
44 | 43 | response = api_call(self.app, params) |
|
45 | 44 | |
|
46 | 45 | # The above api call detaches the pull request DB object from the |
|
47 | 46 | # session because of an unconditional transaction rollback in our |
|
48 | 47 | # middleware. Therefore we need to add it back here if we want to use it. |
|
49 | 48 | Session().add(pull_request) |
|
50 | 49 | |
|
51 | 50 | expected = 'merge not possible for following reasons: ' \ |
|
52 | 51 | 'Pull request reviewer approval is pending.' |
|
53 | 52 | assert_error(id_, expected, given=response.body) |
|
54 | 53 | |
|
55 | 54 | @pytest.mark.backends("git", "hg") |
|
56 | 55 | def test_api_merge_pull_request_merge_failed_disallowed_state( |
|
57 | 56 | self, pr_util, no_notifications): |
|
58 | 57 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) |
|
59 | 58 | pull_request_id = pull_request.pull_request_id |
|
60 | 59 | pull_request_repo = pull_request.target_repo.repo_name |
|
61 | 60 | |
|
62 | 61 | pr = PullRequest.get(pull_request_id) |
|
63 | 62 | pr.pull_request_state = pull_request.STATE_UPDATING |
|
64 | 63 | Session().add(pr) |
|
65 | 64 | Session().commit() |
|
66 | 65 | |
|
67 | 66 | id_, params = build_data( |
|
68 | 67 | self.apikey, 'merge_pull_request', |
|
69 | 68 | repoid=pull_request_repo, |
|
70 | 69 | pullrequestid=pull_request_id) |
|
71 | 70 | |
|
72 | 71 | response = api_call(self.app, params) |
|
73 | 72 | expected = 'Operation forbidden because pull request is in state {}, '\ |
|
74 | 73 | 'only state {} is allowed.'.format(PullRequest.STATE_UPDATING, |
|
75 | 74 | PullRequest.STATE_CREATED) |
|
76 | 75 | assert_error(id_, expected, given=response.body) |
|
77 | 76 | |
|
78 | 77 | @pytest.mark.backends("git", "hg") |
|
79 | 78 | def test_api_merge_pull_request(self, pr_util, no_notifications): |
|
80 | 79 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) |
|
81 | 80 | author = pull_request.user_id |
|
82 | 81 | repo = pull_request.target_repo.repo_id |
|
83 | 82 | pull_request_id = pull_request.pull_request_id |
|
84 | 83 | pull_request_repo = pull_request.target_repo.repo_name |
|
85 | 84 | |
|
86 | 85 | id_, params = build_data( |
|
87 | 86 | self.apikey, 'comment_pull_request', |
|
88 | 87 | repoid=pull_request_repo, |
|
89 | 88 | pullrequestid=pull_request_id, |
|
90 | 89 | status='approved') |
|
91 | 90 | |
|
92 | 91 | response = api_call(self.app, params) |
|
93 | 92 | expected = { |
|
94 | 93 | 'comment_id': response.json.get('result', {}).get('comment_id'), |
|
95 | 94 | 'pull_request_id': pull_request_id, |
|
96 | 95 | 'status': {'given': 'approved', 'was_changed': True} |
|
97 | 96 | } |
|
98 | 97 | assert_ok(id_, expected, given=response.body) |
|
99 | 98 | |
|
100 | 99 | id_, params = build_data( |
|
101 | 100 | self.apikey, 'merge_pull_request', |
|
102 | 101 | repoid=pull_request_repo, |
|
103 | 102 | pullrequestid=pull_request_id) |
|
104 | 103 | |
|
105 | 104 | response = api_call(self.app, params) |
|
106 | 105 | |
|
107 | 106 | pull_request = PullRequest.get(pull_request_id) |
|
108 | 107 | |
|
109 | 108 | expected = { |
|
110 | 109 | 'executed': True, |
|
111 | 110 | 'failure_reason': 0, |
|
112 | 111 | 'merge_status_message': 'This pull request can be automatically merged.', |
|
113 | 112 | 'possible': True, |
|
114 | 113 | 'merge_commit_id': pull_request.shadow_merge_ref.commit_id, |
|
115 |
'merge_ref': pull_request.shadow_merge_ref. |
|
|
114 | 'merge_ref': pull_request.shadow_merge_ref.asdict() | |
|
116 | 115 | } |
|
117 | 116 | |
|
118 | 117 | assert_ok(id_, expected, response.body) |
|
119 | 118 | |
|
120 | 119 | journal = UserLog.query()\ |
|
121 | 120 | .filter(UserLog.user_id == author)\ |
|
122 | 121 | .filter(UserLog.repository_id == repo) \ |
|
123 | 122 | .order_by(UserLog.user_log_id.asc()) \ |
|
124 | 123 | .all() |
|
125 | 124 | assert journal[-2].action == 'repo.pull_request.merge' |
|
126 | 125 | assert journal[-1].action == 'repo.pull_request.close' |
|
127 | 126 | |
|
128 | 127 | id_, params = build_data( |
|
129 | 128 | self.apikey, 'merge_pull_request', |
|
130 | 129 | repoid=pull_request_repo, pullrequestid=pull_request_id) |
|
131 | 130 | response = api_call(self.app, params) |
|
132 | 131 | |
|
133 | 132 | expected = 'merge not possible for following reasons: This pull request is closed.' |
|
134 | 133 | assert_error(id_, expected, given=response.body) |
|
135 | 134 | |
|
136 | 135 | @pytest.mark.backends("git", "hg") |
|
137 | 136 | def test_api_merge_pull_request_as_another_user_no_perms_to_merge( |
|
138 | 137 | self, pr_util, no_notifications, user_util): |
|
139 | 138 | merge_user = user_util.create_user() |
|
140 | 139 | merge_user_id = merge_user.user_id |
|
141 | 140 | merge_user_username = merge_user.username |
|
142 | 141 | |
|
143 | 142 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) |
|
144 | 143 | |
|
145 | 144 | pull_request_id = pull_request.pull_request_id |
|
146 | 145 | pull_request_repo = pull_request.target_repo.repo_name |
|
147 | 146 | |
|
148 | 147 | id_, params = build_data( |
|
149 | 148 | self.apikey, 'comment_pull_request', |
|
150 | 149 | repoid=pull_request_repo, |
|
151 | 150 | pullrequestid=pull_request_id, |
|
152 | 151 | status='approved') |
|
153 | 152 | |
|
154 | 153 | response = api_call(self.app, params) |
|
155 | 154 | expected = { |
|
156 | 155 | 'comment_id': response.json.get('result', {}).get('comment_id'), |
|
157 | 156 | 'pull_request_id': pull_request_id, |
|
158 | 157 | 'status': {'given': 'approved', 'was_changed': True} |
|
159 | 158 | } |
|
160 | 159 | assert_ok(id_, expected, given=response.body) |
|
161 | 160 | id_, params = build_data( |
|
162 | 161 | self.apikey, 'merge_pull_request', |
|
163 | 162 | repoid=pull_request_repo, |
|
164 | 163 | pullrequestid=pull_request_id, |
|
165 | 164 | userid=merge_user_id |
|
166 | 165 | ) |
|
167 | 166 | |
|
168 | 167 | response = api_call(self.app, params) |
|
169 | 168 | expected = 'merge not possible for following reasons: User `{}` ' \ |
|
170 | 169 | 'not allowed to perform merge.'.format(merge_user_username) |
|
171 | 170 | assert_error(id_, expected, response.body) |
|
172 | 171 | |
|
173 | 172 | @pytest.mark.backends("git", "hg") |
|
174 | 173 | def test_api_merge_pull_request_as_another_user(self, pr_util, no_notifications, user_util): |
|
175 | 174 | merge_user = user_util.create_user() |
|
176 | 175 | merge_user_id = merge_user.user_id |
|
177 | 176 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) |
|
178 | 177 | user_util.grant_user_permission_to_repo( |
|
179 | 178 | pull_request.target_repo, merge_user, 'repository.write') |
|
180 | 179 | author = pull_request.user_id |
|
181 | 180 | repo = pull_request.target_repo.repo_id |
|
182 | 181 | pull_request_id = pull_request.pull_request_id |
|
183 | 182 | pull_request_repo = pull_request.target_repo.repo_name |
|
184 | 183 | |
|
185 | 184 | id_, params = build_data( |
|
186 | 185 | self.apikey, 'comment_pull_request', |
|
187 | 186 | repoid=pull_request_repo, |
|
188 | 187 | pullrequestid=pull_request_id, |
|
189 | 188 | status='approved') |
|
190 | 189 | |
|
191 | 190 | response = api_call(self.app, params) |
|
192 | 191 | expected = { |
|
193 | 192 | 'comment_id': response.json.get('result', {}).get('comment_id'), |
|
194 | 193 | 'pull_request_id': pull_request_id, |
|
195 | 194 | 'status': {'given': 'approved', 'was_changed': True} |
|
196 | 195 | } |
|
197 | 196 | assert_ok(id_, expected, given=response.body) |
|
198 | 197 | |
|
199 | 198 | id_, params = build_data( |
|
200 | 199 | self.apikey, 'merge_pull_request', |
|
201 | 200 | repoid=pull_request_repo, |
|
202 | 201 | pullrequestid=pull_request_id, |
|
203 | 202 | userid=merge_user_id |
|
204 | 203 | ) |
|
205 | 204 | |
|
206 | 205 | response = api_call(self.app, params) |
|
207 | 206 | |
|
208 | 207 | pull_request = PullRequest.get(pull_request_id) |
|
209 | 208 | |
|
210 | 209 | expected = { |
|
211 | 210 | 'executed': True, |
|
212 | 211 | 'failure_reason': 0, |
|
213 | 212 | 'merge_status_message': 'This pull request can be automatically merged.', |
|
214 | 213 | 'possible': True, |
|
215 | 214 | 'merge_commit_id': pull_request.shadow_merge_ref.commit_id, |
|
216 |
'merge_ref': pull_request.shadow_merge_ref. |
|
|
215 | 'merge_ref': pull_request.shadow_merge_ref.asdict() | |
|
217 | 216 | } |
|
218 | 217 | |
|
219 | 218 | assert_ok(id_, expected, response.body) |
|
220 | 219 | |
|
221 | 220 | journal = UserLog.query() \ |
|
222 | 221 | .filter(UserLog.user_id == merge_user_id) \ |
|
223 | 222 | .filter(UserLog.repository_id == repo) \ |
|
224 | 223 | .order_by(UserLog.user_log_id.asc()) \ |
|
225 | 224 | .all() |
|
226 | 225 | assert journal[-2].action == 'repo.pull_request.merge' |
|
227 | 226 | assert journal[-1].action == 'repo.pull_request.close' |
|
228 | 227 | |
|
229 | 228 | id_, params = build_data( |
|
230 | 229 | self.apikey, 'merge_pull_request', |
|
231 | 230 | repoid=pull_request_repo, pullrequestid=pull_request_id, userid=merge_user_id) |
|
232 | 231 | response = api_call(self.app, params) |
|
233 | 232 | |
|
234 | 233 | expected = 'merge not possible for following reasons: This pull request is closed.' |
|
235 | 234 | assert_error(id_, expected, given=response.body) |
|
236 | 235 | |
|
237 | 236 | @pytest.mark.backends("git", "hg") |
|
238 | 237 | def test_api_merge_pull_request_repo_error(self, pr_util): |
|
239 | 238 | pull_request = pr_util.create_pull_request() |
|
240 | 239 | id_, params = build_data( |
|
241 | 240 | self.apikey, 'merge_pull_request', |
|
242 | 241 | repoid=666, pullrequestid=pull_request.pull_request_id) |
|
243 | 242 | response = api_call(self.app, params) |
|
244 | 243 | |
|
245 | 244 | expected = 'repository `666` does not exist' |
|
246 | 245 | assert_error(id_, expected, given=response.body) |
|
247 | 246 | |
|
248 | 247 | @pytest.mark.backends("git", "hg") |
|
249 | 248 | def test_api_merge_pull_request_non_admin_with_userid_error(self, pr_util): |
|
250 | 249 | pull_request = pr_util.create_pull_request(mergeable=True) |
|
251 | 250 | id_, params = build_data( |
|
252 | 251 | self.apikey_regular, 'merge_pull_request', |
|
253 | 252 | repoid=pull_request.target_repo.repo_name, |
|
254 | 253 | pullrequestid=pull_request.pull_request_id, |
|
255 | 254 | userid=TEST_USER_ADMIN_LOGIN) |
|
256 | 255 | response = api_call(self.app, params) |
|
257 | 256 | |
|
258 | 257 | expected = 'userid is not the same as your user' |
|
259 | 258 | assert_error(id_, expected, given=response.body) |
@@ -1,55 +1,54 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import os |
|
22 | 21 | import mock |
|
23 | 22 | import pytest |
|
24 | 23 | |
|
25 | 24 | from rhodecode.tests import TESTS_TMP_PATH |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_ok, assert_error) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestPull(object): |
|
32 | 31 | |
|
33 | 32 | @pytest.mark.backends("git", "hg") |
|
34 | 33 | def test_api_pull(self, backend): |
|
35 | 34 | r = backend.create_repo() |
|
36 | 35 | repo_name = r.repo_name |
|
37 | 36 | clone_uri = os.path.join(TESTS_TMP_PATH, backend.repo_name) |
|
38 | 37 | r.clone_uri = clone_uri |
|
39 | 38 | |
|
40 | 39 | id_, params = build_data(self.apikey, 'pull', repoid=repo_name,) |
|
41 | 40 | with mock.patch('rhodecode.model.scm.url_validator'): |
|
42 | 41 | response = api_call(self.app, params) |
|
43 | 42 | msg = 'Pulled from url `%s` on repo `%s`' % ( |
|
44 | 43 | clone_uri, repo_name) |
|
45 | 44 | expected = {'msg': msg, |
|
46 | 45 | 'repository': repo_name} |
|
47 | 46 | assert_ok(id_, expected, given=response.body) |
|
48 | 47 | |
|
49 | 48 | def test_api_pull_error(self, backend): |
|
50 | 49 | id_, params = build_data( |
|
51 | 50 | self.apikey, 'pull', repoid=backend.repo_name) |
|
52 | 51 | response = api_call(self.app, params) |
|
53 | 52 | |
|
54 | 53 | expected = 'Unable to pull changes from `None`' |
|
55 | 54 | assert_error(id_, expected, given=response.body) |
@@ -1,66 +1,65 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import pytest |
|
22 | 21 | |
|
23 | 22 | from rhodecode.model.db import Repository, RepositoryField |
|
24 | 23 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok |
|
25 | 24 | |
|
26 | 25 | |
|
27 | 26 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | 27 | class TestRemoveFieldFromRepo(object): |
|
29 | 28 | def test_api_remove_field_from_repo(self, backend): |
|
30 | 29 | repo = backend.create_repo() |
|
31 | 30 | repo_name = repo.repo_name |
|
32 | 31 | |
|
33 | 32 | id_, params = build_data( |
|
34 | 33 | self.apikey, 'add_field_to_repo', |
|
35 | 34 | repoid=repo_name, |
|
36 | 35 | key='extra_field', |
|
37 | 36 | label='extra_field_label', |
|
38 | 37 | description='extra_field_desc') |
|
39 | 38 | response = api_call(self.app, params) |
|
40 | 39 | expected = { |
|
41 | 40 | 'msg': 'Added new repository field `extra_field`', |
|
42 | 41 | 'success': True, |
|
43 | 42 | } |
|
44 | 43 | assert_ok(id_, expected, given=response.body) |
|
45 | 44 | |
|
46 | 45 | repo = Repository.get_by_repo_name(repo_name) |
|
47 | 46 | repo_field = RepositoryField.get_by_key_name('extra_field', repo) |
|
48 | 47 | _data = repo_field.get_dict() |
|
49 | 48 | assert _data['field_desc'] == 'extra_field_desc' |
|
50 | 49 | assert _data['field_key'] == 'extra_field' |
|
51 | 50 | assert _data['field_label'] == 'extra_field_label' |
|
52 | 51 | |
|
53 | 52 | id_, params = build_data( |
|
54 | 53 | self.apikey, 'remove_field_from_repo', |
|
55 | 54 | repoid=repo_name, |
|
56 | 55 | key='extra_field') |
|
57 | 56 | response = api_call(self.app, params) |
|
58 | 57 | expected = { |
|
59 | 58 | 'msg': 'Deleted repository field `extra_field`', |
|
60 | 59 | 'success': True, |
|
61 | 60 | } |
|
62 | 61 | assert_ok(id_, expected, given=response.body) |
|
63 | 62 | repo = Repository.get_by_repo_name(repo_name) |
|
64 | 63 | repo_field = RepositoryField.get_by_key_name('extra_field', repo) |
|
65 | 64 | |
|
66 | 65 | assert repo_field is None |
@@ -1,58 +1,57 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.user_group import UserGroupModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_error, assert_ok, crash) |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 29 | class TestRemoveUserFromUserGroup(object): |
|
31 | 30 | def test_api_remove_user_from_user_group(self, user_util): |
|
32 | 31 | user, group = user_util.create_user_with_group() |
|
33 | 32 | user_name = user.username |
|
34 | 33 | group_name = group.users_group_name |
|
35 | 34 | id_, params = build_data( |
|
36 | 35 | self.apikey, 'remove_user_from_user_group', |
|
37 | 36 | usergroupid=group_name, |
|
38 | 37 | userid=user.username) |
|
39 | 38 | response = api_call(self.app, params) |
|
40 | 39 | |
|
41 | 40 | expected = { |
|
42 | 41 | 'msg': 'removed member `%s` from user group `%s`' % ( |
|
43 | 42 | user_name, group_name |
|
44 | 43 | ), |
|
45 | 44 | 'success': True} |
|
46 | 45 | assert_ok(id_, expected, given=response.body) |
|
47 | 46 | |
|
48 | 47 | @mock.patch.object(UserGroupModel, 'remove_user_from_group', crash) |
|
49 | 48 | def test_api_remove_user_from_user_group_exception_occurred( |
|
50 | 49 | self, user_util): |
|
51 | 50 | user, group = user_util.create_user_with_group() |
|
52 | 51 | id_, params = build_data( |
|
53 | 52 | self.apikey, 'remove_user_from_user_group', |
|
54 | 53 | usergroupid=group.users_group_name, userid=user.username) |
|
55 | 54 | response = api_call(self.app, params) |
|
56 | 55 | expected = 'failed to remove member from user group `%s`' % ( |
|
57 | 56 | group.users_group_name) |
|
58 | 57 | assert_error(id_, expected, given=response.body) |
@@ -1,184 +1,183 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import mock |
|
23 | 22 | import pytest |
|
24 | 23 | |
|
25 | 24 | from rhodecode.model.db import Repository |
|
26 | 25 | from rhodecode.model.user import UserModel |
|
27 | 26 | from rhodecode.lib.ext_json import json |
|
28 | 27 | from rhodecode.lib.utils2 import time_to_datetime |
|
29 | 28 | from rhodecode.api.tests.utils import ( |
|
30 | 29 | build_data, api_call, assert_ok, assert_error, crash) |
|
31 | 30 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
32 | 31 | |
|
33 | 32 | |
|
34 | 33 | @pytest.mark.usefixtures("testuser_api", "app") |
|
35 | 34 | class TestLock(object): |
|
36 | 35 | def test_api_lock_repo_lock_aquire(self, backend): |
|
37 | 36 | id_, params = build_data( |
|
38 | 37 | self.apikey, 'lock', |
|
39 | 38 | userid=TEST_USER_ADMIN_LOGIN, |
|
40 | 39 | repoid=backend.repo_name, |
|
41 | 40 | locked=True) |
|
42 | 41 | response = api_call(self.app, params) |
|
43 | 42 | expected = { |
|
44 | 43 | 'repo': backend.repo_name, 'locked': True, |
|
45 | 44 | 'locked_since': response.json['result']['locked_since'], |
|
46 | 45 | 'locked_by': TEST_USER_ADMIN_LOGIN, |
|
47 | 46 | 'lock_state_changed': True, |
|
48 | 47 | 'lock_reason': Repository.LOCK_API, |
|
49 | 48 | 'msg': ('User `%s` set lock state for repo `%s` to `%s`' |
|
50 | 49 | % (TEST_USER_ADMIN_LOGIN, backend.repo_name, True)) |
|
51 | 50 | } |
|
52 | 51 | assert_ok(id_, expected, given=response.body) |
|
53 | 52 | |
|
54 | 53 | def test_repo_lock_aquire_by_non_admin(self, backend): |
|
55 | 54 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) |
|
56 | 55 | repo_name = repo.repo_name |
|
57 | 56 | id_, params = build_data( |
|
58 | 57 | self.apikey_regular, 'lock', |
|
59 | 58 | repoid=repo_name, |
|
60 | 59 | locked=True) |
|
61 | 60 | response = api_call(self.app, params) |
|
62 | 61 | expected = { |
|
63 | 62 | 'repo': repo_name, |
|
64 | 63 | 'locked': True, |
|
65 | 64 | 'locked_since': response.json['result']['locked_since'], |
|
66 | 65 | 'locked_by': self.TEST_USER_LOGIN, |
|
67 | 66 | 'lock_state_changed': True, |
|
68 | 67 | 'lock_reason': Repository.LOCK_API, |
|
69 | 68 | 'msg': ('User `%s` set lock state for repo `%s` to `%s`' |
|
70 | 69 | % (self.TEST_USER_LOGIN, repo_name, True)) |
|
71 | 70 | } |
|
72 | 71 | assert_ok(id_, expected, given=response.body) |
|
73 | 72 | |
|
74 | 73 | def test_api_lock_repo_lock_aquire_non_admin_with_userid(self, backend): |
|
75 | 74 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) |
|
76 | 75 | repo_name = repo.repo_name |
|
77 | 76 | id_, params = build_data( |
|
78 | 77 | self.apikey_regular, 'lock', |
|
79 | 78 | userid=TEST_USER_ADMIN_LOGIN, |
|
80 | 79 | repoid=repo_name, |
|
81 | 80 | locked=True) |
|
82 | 81 | response = api_call(self.app, params) |
|
83 | 82 | expected = 'userid is not the same as your user' |
|
84 | 83 | assert_error(id_, expected, given=response.body) |
|
85 | 84 | |
|
86 | 85 | def test_api_lock_repo_lock_aquire_non_admin_not_his_repo(self, backend): |
|
87 | 86 | id_, params = build_data( |
|
88 | 87 | self.apikey_regular, 'lock', |
|
89 | 88 | repoid=backend.repo_name, |
|
90 | 89 | locked=True) |
|
91 | 90 | response = api_call(self.app, params) |
|
92 | 91 | expected = 'repository `%s` does not exist' % (backend.repo_name, ) |
|
93 | 92 | assert_error(id_, expected, given=response.body) |
|
94 | 93 | |
|
95 | 94 | def test_api_lock_repo_lock_release(self, backend): |
|
96 | 95 | id_, params = build_data( |
|
97 | 96 | self.apikey, 'lock', |
|
98 | 97 | userid=TEST_USER_ADMIN_LOGIN, |
|
99 | 98 | repoid=backend.repo_name, |
|
100 | 99 | locked=False) |
|
101 | 100 | response = api_call(self.app, params) |
|
102 | 101 | expected = { |
|
103 | 102 | 'repo': backend.repo_name, |
|
104 | 103 | 'locked': False, |
|
105 | 104 | 'locked_since': None, |
|
106 | 105 | 'locked_by': TEST_USER_ADMIN_LOGIN, |
|
107 | 106 | 'lock_state_changed': True, |
|
108 | 107 | 'lock_reason': Repository.LOCK_API, |
|
109 | 108 | 'msg': ('User `%s` set lock state for repo `%s` to `%s`' |
|
110 | 109 | % (TEST_USER_ADMIN_LOGIN, backend.repo_name, False)) |
|
111 | 110 | } |
|
112 | 111 | assert_ok(id_, expected, given=response.body) |
|
113 | 112 | |
|
114 | 113 | def test_api_lock_repo_lock_aquire_optional_userid(self, backend): |
|
115 | 114 | id_, params = build_data( |
|
116 | 115 | self.apikey, 'lock', |
|
117 | 116 | repoid=backend.repo_name, |
|
118 | 117 | locked=True) |
|
119 | 118 | response = api_call(self.app, params) |
|
120 | 119 | time_ = response.json['result']['locked_since'] |
|
121 | 120 | expected = { |
|
122 | 121 | 'repo': backend.repo_name, |
|
123 | 122 | 'locked': True, |
|
124 | 123 | 'locked_since': time_, |
|
125 | 124 | 'locked_by': TEST_USER_ADMIN_LOGIN, |
|
126 | 125 | 'lock_state_changed': True, |
|
127 | 126 | 'lock_reason': Repository.LOCK_API, |
|
128 | 127 | 'msg': ('User `%s` set lock state for repo `%s` to `%s`' |
|
129 | 128 | % (TEST_USER_ADMIN_LOGIN, backend.repo_name, True)) |
|
130 | 129 | } |
|
131 | 130 | |
|
132 | 131 | assert_ok(id_, expected, given=response.body) |
|
133 | 132 | |
|
134 | 133 | def test_api_lock_repo_lock_optional_locked(self, backend): |
|
135 | 134 | # TODO: Provide a fixture locked_repository or similar |
|
136 | 135 | repo = Repository.get_by_repo_name(backend.repo_name) |
|
137 | 136 | user = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
138 | 137 | Repository.lock(repo, user.user_id, lock_reason=Repository.LOCK_API) |
|
139 | 138 | |
|
140 | 139 | id_, params = build_data(self.apikey, 'lock', repoid=backend.repo_name) |
|
141 | 140 | response = api_call(self.app, params) |
|
142 | 141 | time_ = response.json['result']['locked_since'] |
|
143 | 142 | expected = { |
|
144 | 143 | 'repo': backend.repo_name, |
|
145 | 144 | 'locked': True, |
|
146 | 145 | 'locked_since': time_, |
|
147 | 146 | 'locked_by': TEST_USER_ADMIN_LOGIN, |
|
148 | 147 | 'lock_state_changed': False, |
|
149 | 148 | 'lock_reason': Repository.LOCK_API, |
|
150 | 149 | 'msg': ('Repo `%s` locked by `%s` on `%s`.' |
|
151 | 150 | % (backend.repo_name, TEST_USER_ADMIN_LOGIN, |
|
152 | 151 | json.dumps(time_to_datetime(time_)))) |
|
153 | 152 | } |
|
154 | 153 | assert_ok(id_, expected, given=response.body) |
|
155 | 154 | |
|
156 | 155 | def test_api_lock_repo_lock_optional_not_locked(self, backend): |
|
157 | 156 | repo = backend.create_repo(cur_user=self.TEST_USER_LOGIN) |
|
158 | 157 | repo_name = repo.repo_name |
|
159 | 158 | assert repo.locked == [None, None, None] |
|
160 | 159 | id_, params = build_data(self.apikey, 'lock', repoid=repo.repo_id) |
|
161 | 160 | response = api_call(self.app, params) |
|
162 | 161 | expected = { |
|
163 | 162 | 'repo': repo_name, |
|
164 | 163 | 'locked': False, |
|
165 | 164 | 'locked_since': None, |
|
166 | 165 | 'locked_by': None, |
|
167 | 166 | 'lock_state_changed': False, |
|
168 | 167 | 'lock_reason': None, |
|
169 | 168 | 'msg': ('Repo `%s` not locked.' % (repo_name,)) |
|
170 | 169 | } |
|
171 | 170 | assert_ok(id_, expected, given=response.body) |
|
172 | 171 | |
|
173 | 172 | @mock.patch.object(Repository, 'lock', crash) |
|
174 | 173 | def test_api_lock_error(self, backend): |
|
175 | 174 | id_, params = build_data( |
|
176 | 175 | self.apikey, 'lock', |
|
177 | 176 | userid=TEST_USER_ADMIN_LOGIN, |
|
178 | 177 | repoid=backend.repo_name, |
|
179 | 178 | locked=True) |
|
180 | 179 | response = api_call(self.app, params) |
|
181 | 180 | |
|
182 | 181 | expected = 'Error occurred locking repository `%s`' % ( |
|
183 | 182 | backend.repo_name,) |
|
184 | 183 | assert_error(id_, expected, given=response.body) |
@@ -1,44 +1,43 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.scm import ScmModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_ok, assert_error, crash) |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 29 | class TestRescanRepos(object): |
|
31 | 30 | def test_api_rescan_repos(self): |
|
32 | 31 | id_, params = build_data(self.apikey, 'rescan_repos') |
|
33 | 32 | response = api_call(self.app, params) |
|
34 | 33 | |
|
35 | 34 | expected = {'added': [], 'removed': []} |
|
36 | 35 | assert_ok(id_, expected, given=response.body) |
|
37 | 36 | |
|
38 | 37 | @mock.patch.object(ScmModel, 'repo_scan', crash) |
|
39 | 38 | def test_api_rescann_error(self): |
|
40 | 39 | id_, params = build_data(self.apikey, 'rescan_repos', ) |
|
41 | 40 | response = api_call(self.app, params) |
|
42 | 41 | |
|
43 | 42 | expected = 'Error occurred during rescan repositories action' |
|
44 | 43 | assert_error(id_, expected, given=response.body) |
@@ -1,67 +1,66 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.repo import RepoModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_error, assert_ok, crash) |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 29 | class TestRevokeUserGroupPermission(object): |
|
31 | 30 | def test_api_revoke_user_group_permission(self, backend, user_util): |
|
32 | 31 | repo = backend.create_repo() |
|
33 | 32 | user_group = user_util.create_user_group() |
|
34 | 33 | user_util.grant_user_group_permission_to_repo( |
|
35 | 34 | repo, user_group, 'repository.read') |
|
36 | 35 | id_, params = build_data( |
|
37 | 36 | self.apikey, |
|
38 | 37 | 'revoke_user_group_permission', |
|
39 | 38 | repoid=backend.repo_name, |
|
40 | 39 | usergroupid=user_group.users_group_name) |
|
41 | 40 | response = api_call(self.app, params) |
|
42 | 41 | |
|
43 | 42 | expected = { |
|
44 | 43 | 'msg': 'Revoked perm for user group: `%s` in repo: `%s`' % ( |
|
45 | 44 | user_group.users_group_name, backend.repo_name |
|
46 | 45 | ), |
|
47 | 46 | 'success': True |
|
48 | 47 | } |
|
49 | 48 | assert_ok(id_, expected, given=response.body) |
|
50 | 49 | |
|
51 | 50 | @mock.patch.object(RepoModel, 'revoke_user_group_permission', crash) |
|
52 | 51 | def test_api_revoke_user_group_permission_exception_when_adding( |
|
53 | 52 | self, backend, user_util): |
|
54 | 53 | user_group = user_util.create_user_group() |
|
55 | 54 | id_, params = build_data( |
|
56 | 55 | self.apikey, |
|
57 | 56 | 'revoke_user_group_permission', |
|
58 | 57 | repoid=backend.repo_name, |
|
59 | 58 | usergroupid=user_group.users_group_name) |
|
60 | 59 | response = api_call(self.app, params) |
|
61 | 60 | |
|
62 | 61 | expected = ( |
|
63 | 62 | 'failed to edit permission for user group: `%s` in repo: `%s`' % ( |
|
64 | 63 | user_group.users_group_name, backend.repo_name |
|
65 | 64 | ) |
|
66 | 65 | ) |
|
67 | 66 | assert_error(id_, expected, given=response.body) |
@@ -1,129 +1,128 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.repo_group import RepoGroupModel |
|
25 | 24 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
26 | 25 | from rhodecode.api.tests.utils import ( |
|
27 | 26 | build_data, api_call, assert_error, assert_ok, crash) |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 30 | class TestRevokeUserGroupPermissionFromRepoGroup(object): |
|
32 | 31 | @pytest.mark.parametrize("name, apply_to_children", [ |
|
33 | 32 | ('none', 'none'), |
|
34 | 33 | ('all', 'all'), |
|
35 | 34 | ('repos', 'repos'), |
|
36 | 35 | ('groups', 'groups'), |
|
37 | 36 | ]) |
|
38 | 37 | def test_api_revoke_user_group_permission_from_repo_group( |
|
39 | 38 | self, name, apply_to_children, user_util): |
|
40 | 39 | user_group = user_util.create_user_group() |
|
41 | 40 | repo_group = user_util.create_repo_group() |
|
42 | 41 | user_util.grant_user_group_permission_to_repo_group( |
|
43 | 42 | repo_group, user_group, 'group.read') |
|
44 | 43 | |
|
45 | 44 | id_, params = build_data( |
|
46 | 45 | self.apikey, 'revoke_user_group_permission_from_repo_group', |
|
47 | 46 | repogroupid=repo_group.name, |
|
48 | 47 | usergroupid=user_group.users_group_name, |
|
49 | 48 | apply_to_children=apply_to_children,) |
|
50 | 49 | response = api_call(self.app, params) |
|
51 | 50 | |
|
52 | 51 | expected = { |
|
53 | 52 | 'msg': ( |
|
54 | 53 | 'Revoked perm (recursive:%s) for user group: `%s`' |
|
55 | 54 | ' in repo group: `%s`' % ( |
|
56 | 55 | apply_to_children, user_group.users_group_name, |
|
57 | 56 | repo_group.name |
|
58 | 57 | ) |
|
59 | 58 | ), |
|
60 | 59 | 'success': True |
|
61 | 60 | } |
|
62 | 61 | assert_ok(id_, expected, given=response.body) |
|
63 | 62 | |
|
64 | 63 | @pytest.mark.parametrize( |
|
65 | 64 | "name, apply_to_children, grant_admin, access_ok", [ |
|
66 | 65 | ('none', 'none', False, False), |
|
67 | 66 | ('all', 'all', False, False), |
|
68 | 67 | ('repos', 'repos', False, False), |
|
69 | 68 | ('groups', 'groups', False, False), |
|
70 | 69 | |
|
71 | 70 | # after granting admin rights |
|
72 | 71 | ('none', 'none', False, False), |
|
73 | 72 | ('all', 'all', False, False), |
|
74 | 73 | ('repos', 'repos', False, False), |
|
75 | 74 | ('groups', 'groups', False, False), |
|
76 | 75 | ] |
|
77 | 76 | ) |
|
78 | 77 | def test_api_revoke_user_group_permission_from_repo_group_by_regular_user( |
|
79 | 78 | self, name, apply_to_children, grant_admin, access_ok, user_util): |
|
80 | 79 | user_group = user_util.create_user_group() |
|
81 | 80 | repo_group = user_util.create_repo_group() |
|
82 | 81 | user_util.grant_user_group_permission_to_repo_group( |
|
83 | 82 | repo_group, user_group, 'group.read') |
|
84 | 83 | |
|
85 | 84 | if grant_admin: |
|
86 | 85 | user_util.grant_user_permission_to_repo_group( |
|
87 | 86 | repo_group.name, self.TEST_USER_LOGIN, 'group.admin') |
|
88 | 87 | |
|
89 | 88 | id_, params = build_data( |
|
90 | 89 | self.apikey_regular, |
|
91 | 90 | 'revoke_user_group_permission_from_repo_group', |
|
92 | 91 | repogroupid=repo_group.name, |
|
93 | 92 | usergroupid=user_group.users_group_name, |
|
94 | 93 | apply_to_children=apply_to_children,) |
|
95 | 94 | response = api_call(self.app, params) |
|
96 | 95 | if access_ok: |
|
97 | 96 | expected = { |
|
98 | 97 | 'msg': ( |
|
99 | 98 | 'Revoked perm (recursive:%s) for user group: `%s`' |
|
100 | 99 | ' in repo group: `%s`' % ( |
|
101 | 100 | apply_to_children, TEST_USER_ADMIN_LOGIN, |
|
102 | 101 | repo_group.name |
|
103 | 102 | ) |
|
104 | 103 | ), |
|
105 | 104 | 'success': True |
|
106 | 105 | } |
|
107 | 106 | assert_ok(id_, expected, given=response.body) |
|
108 | 107 | else: |
|
109 | 108 | expected = 'repository group `%s` does not exist' % ( |
|
110 | 109 | repo_group.name,) |
|
111 | 110 | assert_error(id_, expected, given=response.body) |
|
112 | 111 | |
|
113 | 112 | @mock.patch.object(RepoGroupModel, 'revoke_user_group_permission', crash) |
|
114 | 113 | def test_api_revoke_user_group_permission_from_repo_group_exception_on_add( |
|
115 | 114 | self, user_util): |
|
116 | 115 | user_group = user_util.create_user_group() |
|
117 | 116 | repo_group = user_util.create_repo_group() |
|
118 | 117 | id_, params = build_data( |
|
119 | 118 | self.apikey, 'revoke_user_group_permission_from_repo_group', |
|
120 | 119 | repogroupid=repo_group.name, |
|
121 | 120 | usergroupid=user_group.users_group_name) |
|
122 | 121 | response = api_call(self.app, params) |
|
123 | 122 | |
|
124 | 123 | expected = ( |
|
125 | 124 | 'failed to edit permission for user group: `%s`' |
|
126 | 125 | ' in repo group: `%s`' % ( |
|
127 | 126 | user_group.users_group_name, repo_group.name) |
|
128 | 127 | ) |
|
129 | 128 | assert_error(id_, expected, given=response.body) |
@@ -1,58 +1,57 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import pytest |
|
22 | 21 | |
|
23 | 22 | from rhodecode.model.user import UserModel |
|
24 | 23 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok |
|
25 | 24 | |
|
26 | 25 | |
|
27 | 26 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | 27 | class TestRevokeUserGroupPermissionFromUserGroup(object): |
|
29 | 28 | @pytest.mark.parametrize("name", [ |
|
30 | 29 | ('none',), |
|
31 | 30 | ('all',), |
|
32 | 31 | ('repos',), |
|
33 | 32 | ('groups',), |
|
34 | 33 | ]) |
|
35 | 34 | def test_api_revoke_user_group_permission_from_user_group( |
|
36 | 35 | self, name, user_util): |
|
37 | 36 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
38 | 37 | group = user_util.create_user_group() |
|
39 | 38 | source_group = user_util.create_user_group() |
|
40 | 39 | |
|
41 | 40 | user_util.grant_user_permission_to_user_group( |
|
42 | 41 | group, user, 'usergroup.read') |
|
43 | 42 | user_util.grant_user_group_permission_to_user_group( |
|
44 | 43 | source_group, group, 'usergroup.read') |
|
45 | 44 | |
|
46 | 45 | id_, params = build_data( |
|
47 | 46 | self.apikey, 'revoke_user_group_permission_from_user_group', |
|
48 | 47 | usergroupid=group.users_group_name, |
|
49 | 48 | sourceusergroupid=source_group.users_group_name) |
|
50 | 49 | response = api_call(self.app, params) |
|
51 | 50 | |
|
52 | 51 | expected = { |
|
53 | 52 | 'msg': 'Revoked perm for user group: `%s` in user group: `%s`' % ( |
|
54 | 53 | source_group.users_group_name, group.users_group_name |
|
55 | 54 | ), |
|
56 | 55 | 'success': True |
|
57 | 56 | } |
|
58 | 57 | assert_ok(id_, expected, given=response.body) |
@@ -1,66 +1,65 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.repo import RepoModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_error, assert_ok, crash) |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 29 | class TestRevokeUserPermission(object): |
|
31 | 30 | def test_api_revoke_user_permission(self, backend, user_util): |
|
32 | 31 | repo = backend.create_repo() |
|
33 | 32 | user = user_util.create_user() |
|
34 | 33 | user_util.grant_user_permission_to_repo( |
|
35 | 34 | repo, user, 'repository.read') |
|
36 | 35 | |
|
37 | 36 | id_, params = build_data( |
|
38 | 37 | self.apikey, |
|
39 | 38 | 'revoke_user_permission', |
|
40 | 39 | repoid=repo.repo_name, |
|
41 | 40 | userid=user.username) |
|
42 | 41 | response = api_call(self.app, params) |
|
43 | 42 | |
|
44 | 43 | expected = { |
|
45 | 44 | 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % ( |
|
46 | 45 | user.username, backend.repo_name |
|
47 | 46 | ), |
|
48 | 47 | 'success': True |
|
49 | 48 | } |
|
50 | 49 | assert_ok(id_, expected, given=response.body) |
|
51 | 50 | |
|
52 | 51 | @mock.patch.object(RepoModel, 'revoke_user_permission', crash) |
|
53 | 52 | def test_api_revoke_user_permission_exception_when_adding( |
|
54 | 53 | self, backend, user_util): |
|
55 | 54 | user = user_util.create_user() |
|
56 | 55 | id_, params = build_data( |
|
57 | 56 | self.apikey, |
|
58 | 57 | 'revoke_user_permission', |
|
59 | 58 | repoid=backend.repo_name, |
|
60 | 59 | userid=user.username) |
|
61 | 60 | response = api_call(self.app, params) |
|
62 | 61 | |
|
63 | 62 | expected = 'failed to edit permission for user: `%s` in repo: `%s`' % ( |
|
64 | 63 | user.username, backend.repo_name |
|
65 | 64 | ) |
|
66 | 65 | assert_error(id_, expected, given=response.body) |
@@ -1,126 +1,125 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.repo_group import RepoGroupModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_error, assert_ok, crash) |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 29 | class TestRevokeUserPermissionFromRepoGroup(object): |
|
31 | 30 | @pytest.mark.parametrize("name, apply_to_children", [ |
|
32 | 31 | ('none', 'none'), |
|
33 | 32 | ('all', 'all'), |
|
34 | 33 | ('repos', 'repos'), |
|
35 | 34 | ('groups', 'groups'), |
|
36 | 35 | ]) |
|
37 | 36 | def test_api_revoke_user_permission_from_repo_group( |
|
38 | 37 | self, name, apply_to_children, user_util): |
|
39 | 38 | user = user_util.create_user() |
|
40 | 39 | repo_group = user_util.create_repo_group() |
|
41 | 40 | user_util.grant_user_permission_to_repo_group( |
|
42 | 41 | repo_group, user, 'group.read') |
|
43 | 42 | |
|
44 | 43 | id_, params = build_data( |
|
45 | 44 | self.apikey, |
|
46 | 45 | 'revoke_user_permission_from_repo_group', |
|
47 | 46 | repogroupid=repo_group.name, |
|
48 | 47 | userid=user.username, |
|
49 | 48 | apply_to_children=apply_to_children,) |
|
50 | 49 | response = api_call(self.app, params) |
|
51 | 50 | |
|
52 | 51 | expected = { |
|
53 | 52 | 'msg': ( |
|
54 | 53 | 'Revoked perm (recursive:%s) for user: `%s`' |
|
55 | 54 | ' in repo group: `%s`' % ( |
|
56 | 55 | apply_to_children, user.username, repo_group.name |
|
57 | 56 | ) |
|
58 | 57 | ), |
|
59 | 58 | 'success': True |
|
60 | 59 | } |
|
61 | 60 | assert_ok(id_, expected, given=response.body) |
|
62 | 61 | |
|
63 | 62 | @pytest.mark.parametrize( |
|
64 | 63 | "name, apply_to_children, grant_admin, access_ok", [ |
|
65 | 64 | ('none', 'none', False, False), |
|
66 | 65 | ('all', 'all', False, False), |
|
67 | 66 | ('repos', 'repos', False, False), |
|
68 | 67 | ('groups', 'groups', False, False), |
|
69 | 68 | |
|
70 | 69 | # after granting admin rights |
|
71 | 70 | ('none', 'none', False, False), |
|
72 | 71 | ('all', 'all', False, False), |
|
73 | 72 | ('repos', 'repos', False, False), |
|
74 | 73 | ('groups', 'groups', False, False), |
|
75 | 74 | ] |
|
76 | 75 | ) |
|
77 | 76 | def test_api_revoke_user_permission_from_repo_group_by_regular_user( |
|
78 | 77 | self, name, apply_to_children, grant_admin, access_ok, user_util): |
|
79 | 78 | user = user_util.create_user() |
|
80 | 79 | repo_group = user_util.create_repo_group() |
|
81 | 80 | permission = 'group.admin' if grant_admin else 'group.read' |
|
82 | 81 | user_util.grant_user_permission_to_repo_group( |
|
83 | 82 | repo_group, user, permission) |
|
84 | 83 | |
|
85 | 84 | id_, params = build_data( |
|
86 | 85 | self.apikey_regular, |
|
87 | 86 | 'revoke_user_permission_from_repo_group', |
|
88 | 87 | repogroupid=repo_group.name, |
|
89 | 88 | userid=user.username, |
|
90 | 89 | apply_to_children=apply_to_children,) |
|
91 | 90 | response = api_call(self.app, params) |
|
92 | 91 | if access_ok: |
|
93 | 92 | expected = { |
|
94 | 93 | 'msg': ( |
|
95 | 94 | 'Revoked perm (recursive:%s) for user: `%s`' |
|
96 | 95 | ' in repo group: `%s`' % ( |
|
97 | 96 | apply_to_children, user.username, repo_group.name |
|
98 | 97 | ) |
|
99 | 98 | ), |
|
100 | 99 | 'success': True |
|
101 | 100 | } |
|
102 | 101 | assert_ok(id_, expected, given=response.body) |
|
103 | 102 | else: |
|
104 | 103 | expected = 'repository group `%s` does not exist' % ( |
|
105 | 104 | repo_group.name) |
|
106 | 105 | assert_error(id_, expected, given=response.body) |
|
107 | 106 | |
|
108 | 107 | @mock.patch.object(RepoGroupModel, 'revoke_user_permission', crash) |
|
109 | 108 | def test_api_revoke_user_permission_from_repo_group_exception_when_adding( |
|
110 | 109 | self, user_util): |
|
111 | 110 | user = user_util.create_user() |
|
112 | 111 | repo_group = user_util.create_repo_group() |
|
113 | 112 | id_, params = build_data( |
|
114 | 113 | self.apikey, |
|
115 | 114 | 'revoke_user_permission_from_repo_group', |
|
116 | 115 | repogroupid=repo_group.name, |
|
117 | 116 | userid=user.username |
|
118 | 117 | ) |
|
119 | 118 | response = api_call(self.app, params) |
|
120 | 119 | |
|
121 | 120 | expected = ( |
|
122 | 121 | 'failed to edit permission for user: `%s` in repo group: `%s`' % ( |
|
123 | 122 | user.username, repo_group.name |
|
124 | 123 | ) |
|
125 | 124 | ) |
|
126 | 125 | assert_error(id_, expected, given=response.body) |
@@ -1,112 +1,111 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.user_group import UserGroupModel |
|
25 | 24 | from rhodecode.api.tests.utils import ( |
|
26 | 25 | build_data, api_call, assert_error, assert_ok, crash) |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | @pytest.mark.usefixtures("testuser_api", "app") |
|
30 | 29 | class TestRevokeUserPermissionFromUserGroup(object): |
|
31 | 30 | @pytest.mark.parametrize("name", [ |
|
32 | 31 | ('none',), |
|
33 | 32 | ('all',), |
|
34 | 33 | ('repos',), |
|
35 | 34 | ('groups',), |
|
36 | 35 | ]) |
|
37 | 36 | def test_api_revoke_user_permission_from_user_group(self, name, user_util): |
|
38 | 37 | user = user_util.create_user() |
|
39 | 38 | group = user_util.create_user_group() |
|
40 | 39 | user_util.grant_user_permission_to_user_group( |
|
41 | 40 | group, user, 'usergroup.admin') |
|
42 | 41 | |
|
43 | 42 | id_, params = build_data( |
|
44 | 43 | self.apikey, |
|
45 | 44 | 'revoke_user_permission_from_user_group', |
|
46 | 45 | usergroupid=group.users_group_name, |
|
47 | 46 | userid=user.username) |
|
48 | 47 | response = api_call(self.app, params) |
|
49 | 48 | |
|
50 | 49 | expected = { |
|
51 | 50 | 'msg': 'Revoked perm for user: `%s` in user group: `%s`' % ( |
|
52 | 51 | user.username, group.users_group_name |
|
53 | 52 | ), |
|
54 | 53 | 'success': True |
|
55 | 54 | } |
|
56 | 55 | assert_ok(id_, expected, given=response.body) |
|
57 | 56 | |
|
58 | 57 | @pytest.mark.parametrize("name, grant_admin, access_ok", [ |
|
59 | 58 | ('none', False, False), |
|
60 | 59 | ('all', False, False), |
|
61 | 60 | ('repos', False, False), |
|
62 | 61 | ('groups', False, False), |
|
63 | 62 | |
|
64 | 63 | # after granting admin rights |
|
65 | 64 | ('none', False, False), |
|
66 | 65 | ('all', False, False), |
|
67 | 66 | ('repos', False, False), |
|
68 | 67 | ('groups', False, False), |
|
69 | 68 | ]) |
|
70 | 69 | def test_api_revoke_user_permission_from_user_group_by_regular_user( |
|
71 | 70 | self, name, grant_admin, access_ok, user_util): |
|
72 | 71 | user = user_util.create_user() |
|
73 | 72 | group = user_util.create_user_group() |
|
74 | 73 | permission = 'usergroup.admin' if grant_admin else 'usergroup.read' |
|
75 | 74 | user_util.grant_user_permission_to_user_group(group, user, permission) |
|
76 | 75 | |
|
77 | 76 | id_, params = build_data( |
|
78 | 77 | self.apikey_regular, |
|
79 | 78 | 'revoke_user_permission_from_user_group', |
|
80 | 79 | usergroupid=group.users_group_name, |
|
81 | 80 | userid=user.username) |
|
82 | 81 | response = api_call(self.app, params) |
|
83 | 82 | if access_ok: |
|
84 | 83 | expected = { |
|
85 | 84 | 'msg': 'Revoked perm for user: `%s` in user group: `%s`' % ( |
|
86 | 85 | user.username, group.users_group_name |
|
87 | 86 | ), |
|
88 | 87 | 'success': True |
|
89 | 88 | } |
|
90 | 89 | assert_ok(id_, expected, given=response.body) |
|
91 | 90 | else: |
|
92 | 91 | expected = 'user group `%s` does not exist' % ( |
|
93 | 92 | group.users_group_name) |
|
94 | 93 | assert_error(id_, expected, given=response.body) |
|
95 | 94 | |
|
96 | 95 | @mock.patch.object(UserGroupModel, 'revoke_user_permission', crash) |
|
97 | 96 | def test_api_revoke_user_permission_from_user_group_exception_when_adding( |
|
98 | 97 | self, user_util): |
|
99 | 98 | user = user_util.create_user() |
|
100 | 99 | group = user_util.create_user_group() |
|
101 | 100 | id_, params = build_data( |
|
102 | 101 | self.apikey, |
|
103 | 102 | 'revoke_user_permission_from_user_group', |
|
104 | 103 | usergroupid=group.users_group_name, |
|
105 | 104 | userid=user.username) |
|
106 | 105 | response = api_call(self.app, params) |
|
107 | 106 | |
|
108 | 107 | expected = ( |
|
109 | 108 | 'failed to edit permission for user: `%s` in user group: `%s`' % ( |
|
110 | 109 | user.username, group.users_group_name) |
|
111 | 110 | ) |
|
112 | 111 | assert_error(id_, expected, given=response.body) |
@@ -1,59 +1,58 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.api.tests.utils import build_data, api_call, assert_ok, assert_error |
|
25 | 24 | |
|
26 | 25 | |
|
27 | 26 | @pytest.mark.usefixtures("testuser_api", "app") |
|
28 | 27 | class TestStoreException(object): |
|
29 | 28 | |
|
30 | 29 | def test_store_exception_invalid_json(self): |
|
31 | 30 | id_, params = build_data(self.apikey, 'store_exception', |
|
32 | 31 | exc_data_json='XXX,{') |
|
33 | 32 | response = api_call(self.app, params) |
|
34 | 33 | |
|
35 | 34 | expected = 'Failed to parse JSON data from exc_data_json field. ' \ |
|
36 | 35 | 'Please make sure it contains a valid JSON.' |
|
37 | 36 | assert_error(id_, expected, given=response.body) |
|
38 | 37 | |
|
39 | 38 | def test_store_exception_missing_json_params_json(self): |
|
40 | 39 | id_, params = build_data(self.apikey, 'store_exception', |
|
41 | 40 | exc_data_json='{"foo":"bar"}') |
|
42 | 41 | response = api_call(self.app, params) |
|
43 | 42 | |
|
44 | 43 | expected = "Missing exc_traceback, or exc_type_name in " \ |
|
45 | 44 | "exc_data_json field. Missing: 'exc_traceback'" |
|
46 | 45 | assert_error(id_, expected, given=response.body) |
|
47 | 46 | |
|
48 | 47 | def test_store_exception(self): |
|
49 | 48 | id_, params = build_data( |
|
50 | 49 | self.apikey, 'store_exception', |
|
51 | 50 | exc_data_json='{"exc_traceback": "invalid", "exc_type_name":"ValueError"}') |
|
52 | 51 | response = api_call(self.app, params) |
|
53 | 52 | exc_id = response.json['result']['exc_id'] |
|
54 | 53 | |
|
55 | 54 | expected = { |
|
56 | 55 | 'exc_id': exc_id, |
|
57 | 56 | 'exc_url': 'http://example.com/_admin/settings/exceptions/{}'.format(exc_id) |
|
58 | 57 | } |
|
59 | 58 | assert_ok(id_, expected, given=response.body) |
@@ -1,215 +1,214 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import pytest |
|
22 | 21 | |
|
23 | 22 | from rhodecode.lib.vcs.nodes import FileNode |
|
24 | 23 | from rhodecode.model.db import User |
|
25 | 24 | from rhodecode.model.pull_request import PullRequestModel |
|
26 | 25 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
27 | 26 | from rhodecode.api.tests.utils import ( |
|
28 | 27 | build_data, api_call, assert_ok, assert_error) |
|
29 | 28 | |
|
30 | 29 | |
|
31 | 30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
32 | 31 | class TestUpdatePullRequest(object): |
|
33 | 32 | |
|
34 | 33 | @pytest.mark.backends("git", "hg") |
|
35 | 34 | def test_api_update_pull_request_title_or_description( |
|
36 | 35 | self, pr_util, no_notifications): |
|
37 | 36 | pull_request = pr_util.create_pull_request() |
|
38 | 37 | |
|
39 | 38 | id_, params = build_data( |
|
40 | 39 | self.apikey, 'update_pull_request', |
|
41 | 40 | repoid=pull_request.target_repo.repo_name, |
|
42 | 41 | pullrequestid=pull_request.pull_request_id, |
|
43 | 42 | title='New TITLE OF A PR', |
|
44 | 43 | description='New DESC OF A PR', |
|
45 | 44 | ) |
|
46 | 45 | response = api_call(self.app, params) |
|
47 | 46 | |
|
48 | 47 | expected = { |
|
49 | 48 | "msg": "Updated pull request `{}`".format( |
|
50 | 49 | pull_request.pull_request_id), |
|
51 | 50 | "pull_request": response.json['result']['pull_request'], |
|
52 | 51 | "updated_commits": {"added": [], "common": [], "removed": []}, |
|
53 | 52 | "updated_reviewers": {"added": [], "removed": []}, |
|
54 | 53 | "updated_observers": {"added": [], "removed": []}, |
|
55 | 54 | } |
|
56 | 55 | |
|
57 | 56 | response_json = response.json['result'] |
|
58 | 57 | assert response_json == expected |
|
59 | 58 | pr = response_json['pull_request'] |
|
60 | 59 | assert pr['title'] == 'New TITLE OF A PR' |
|
61 | 60 | assert pr['description'] == 'New DESC OF A PR' |
|
62 | 61 | |
|
63 | 62 | @pytest.mark.backends("git", "hg") |
|
64 | 63 | def test_api_try_update_closed_pull_request( |
|
65 | 64 | self, pr_util, no_notifications): |
|
66 | 65 | pull_request = pr_util.create_pull_request() |
|
67 | 66 | PullRequestModel().close_pull_request( |
|
68 | 67 | pull_request, TEST_USER_ADMIN_LOGIN) |
|
69 | 68 | |
|
70 | 69 | id_, params = build_data( |
|
71 | 70 | self.apikey, 'update_pull_request', |
|
72 | 71 | repoid=pull_request.target_repo.repo_name, |
|
73 | 72 | pullrequestid=pull_request.pull_request_id) |
|
74 | 73 | response = api_call(self.app, params) |
|
75 | 74 | |
|
76 | 75 | expected = 'pull request `{}` update failed, pull request ' \ |
|
77 | 76 | 'is closed'.format(pull_request.pull_request_id) |
|
78 | 77 | |
|
79 | 78 | assert_error(id_, expected, response.body) |
|
80 | 79 | |
|
81 | 80 | @pytest.mark.backends("git", "hg") |
|
82 | 81 | def test_api_update_update_commits(self, pr_util, no_notifications): |
|
83 | 82 | commits = [ |
|
84 | 83 | {'message': 'a'}, |
|
85 | {'message': 'b', 'added': [FileNode('file_b', 'test_content\n')]}, | |
|
86 | {'message': 'c', 'added': [FileNode('file_c', 'test_content\n')]}, | |
|
84 | {'message': 'b', 'added': [FileNode(b'file_b', b'test_content\n')]}, | |
|
85 | {'message': 'c', 'added': [FileNode(b'file_c', b'test_content\n')]}, | |
|
87 | 86 | ] |
|
88 | 87 | pull_request = pr_util.create_pull_request( |
|
89 | 88 | commits=commits, target_head='a', source_head='b', revisions=['b']) |
|
90 | 89 | pr_util.update_source_repository(head='c') |
|
91 | 90 | repo = pull_request.source_repo.scm_instance() |
|
92 | 91 | commits = [x for x in repo.get_commits()] |
|
93 | 92 | |
|
94 | 93 | added_commit_id = commits[-1].raw_id # c commit |
|
95 | 94 | common_commit_id = commits[1].raw_id # b commit is common ancestor |
|
96 | 95 | total_commits = [added_commit_id, common_commit_id] |
|
97 | 96 | |
|
98 | 97 | id_, params = build_data( |
|
99 | 98 | self.apikey, 'update_pull_request', |
|
100 | 99 | repoid=pull_request.target_repo.repo_name, |
|
101 | 100 | pullrequestid=pull_request.pull_request_id, |
|
102 | 101 | update_commits=True |
|
103 | 102 | ) |
|
104 | 103 | response = api_call(self.app, params) |
|
105 | 104 | |
|
106 | 105 | expected = { |
|
107 | 106 | "msg": "Updated pull request `{}`".format( |
|
108 | 107 | pull_request.pull_request_id), |
|
109 | 108 | "pull_request": response.json['result']['pull_request'], |
|
110 | 109 | "updated_commits": {"added": [added_commit_id], |
|
111 | 110 | "common": [common_commit_id], |
|
112 | 111 | "total": total_commits, |
|
113 | 112 | "removed": []}, |
|
114 | 113 | "updated_reviewers": {"added": [], "removed": []}, |
|
115 | 114 | "updated_observers": {"added": [], "removed": []}, |
|
116 | 115 | } |
|
117 | 116 | |
|
118 | 117 | assert_ok(id_, expected, response.body) |
|
119 | 118 | |
|
120 | 119 | @pytest.mark.backends("git", "hg") |
|
121 | 120 | def test_api_update_change_reviewers( |
|
122 | 121 | self, user_util, pr_util, no_notifications): |
|
123 | 122 | a = user_util.create_user() |
|
124 | 123 | b = user_util.create_user() |
|
125 | 124 | c = user_util.create_user() |
|
126 | 125 | new_reviewers = [ |
|
127 | 126 | {'username': b.username, 'reasons': ['updated via API'], |
|
128 | 127 | 'mandatory':False}, |
|
129 | 128 | {'username': c.username, 'reasons': ['updated via API'], |
|
130 | 129 | 'mandatory':False}, |
|
131 | 130 | ] |
|
132 | 131 | |
|
133 | 132 | added = [b.username, c.username] |
|
134 | 133 | removed = [a.username] |
|
135 | 134 | |
|
136 | 135 | pull_request = pr_util.create_pull_request( |
|
137 | 136 | reviewers=[(a.username, ['added via API'], False, 'reviewer', [])]) |
|
138 | 137 | |
|
139 | 138 | id_, params = build_data( |
|
140 | 139 | self.apikey, 'update_pull_request', |
|
141 | 140 | repoid=pull_request.target_repo.repo_name, |
|
142 | 141 | pullrequestid=pull_request.pull_request_id, |
|
143 | 142 | reviewers=new_reviewers) |
|
144 | 143 | response = api_call(self.app, params) |
|
145 | 144 | expected = { |
|
146 | 145 | "msg": "Updated pull request `{}`".format( |
|
147 | 146 | pull_request.pull_request_id), |
|
148 | 147 | "pull_request": response.json['result']['pull_request'], |
|
149 | 148 | "updated_commits": {"added": [], "common": [], "removed": []}, |
|
150 | 149 | "updated_reviewers": {"added": added, "removed": removed}, |
|
151 | 150 | "updated_observers": {"added": [], "removed": []}, |
|
152 | 151 | } |
|
153 | 152 | |
|
154 | 153 | assert_ok(id_, expected, response.body) |
|
155 | 154 | |
|
156 | 155 | @pytest.mark.backends("git", "hg") |
|
157 | 156 | def test_api_update_bad_user_in_reviewers(self, pr_util): |
|
158 | 157 | pull_request = pr_util.create_pull_request() |
|
159 | 158 | |
|
160 | 159 | id_, params = build_data( |
|
161 | 160 | self.apikey, 'update_pull_request', |
|
162 | 161 | repoid=pull_request.target_repo.repo_name, |
|
163 | 162 | pullrequestid=pull_request.pull_request_id, |
|
164 | 163 | reviewers=[{'username': 'bad_name'}]) |
|
165 | 164 | response = api_call(self.app, params) |
|
166 | 165 | |
|
167 | 166 | expected = 'user `bad_name` does not exist' |
|
168 | 167 | |
|
169 | 168 | assert_error(id_, expected, response.body) |
|
170 | 169 | |
|
171 | 170 | @pytest.mark.backends("git", "hg") |
|
172 | 171 | def test_api_update_repo_error(self, pr_util): |
|
173 | 172 | pull_request = pr_util.create_pull_request() |
|
174 | 173 | id_, params = build_data( |
|
175 | 174 | self.apikey, 'update_pull_request', |
|
176 | 175 | repoid='fake', |
|
177 | 176 | pullrequestid=pull_request.pull_request_id, |
|
178 | 177 | reviewers=[{'username': 'bad_name'}]) |
|
179 | 178 | response = api_call(self.app, params) |
|
180 | 179 | |
|
181 | 180 | expected = 'repository `fake` does not exist' |
|
182 | 181 | |
|
183 | 182 | response_json = response.json['error'] |
|
184 | 183 | assert response_json == expected |
|
185 | 184 | |
|
186 | 185 | @pytest.mark.backends("git", "hg") |
|
187 | 186 | def test_api_update_pull_request_error(self, pr_util): |
|
188 | 187 | pull_request = pr_util.create_pull_request() |
|
189 | 188 | |
|
190 | 189 | id_, params = build_data( |
|
191 | 190 | self.apikey, 'update_pull_request', |
|
192 | 191 | repoid=pull_request.target_repo.repo_name, |
|
193 | 192 | pullrequestid=999999, |
|
194 | 193 | reviewers=[{'username': 'bad_name'}]) |
|
195 | 194 | response = api_call(self.app, params) |
|
196 | 195 | |
|
197 | 196 | expected = 'pull request `999999` does not exist' |
|
198 | 197 | assert_error(id_, expected, response.body) |
|
199 | 198 | |
|
200 | 199 | @pytest.mark.backends("git", "hg") |
|
201 | 200 | def test_api_update_pull_request_no_perms_to_update( |
|
202 | 201 | self, user_util, pr_util): |
|
203 | 202 | user = user_util.create_user() |
|
204 | 203 | pull_request = pr_util.create_pull_request() |
|
205 | 204 | |
|
206 | 205 | id_, params = build_data( |
|
207 | 206 | user.api_key, 'update_pull_request', |
|
208 | 207 | repoid=pull_request.target_repo.repo_name, |
|
209 | 208 | pullrequestid=pull_request.pull_request_id,) |
|
210 | 209 | response = api_call(self.app, params) |
|
211 | 210 | |
|
212 | 211 | expected = ('pull request `%s` update failed, ' |
|
213 | 212 | 'no permission to update.') % pull_request.pull_request_id |
|
214 | 213 | |
|
215 | 214 | assert_error(id_, expected, response.body) |
@@ -1,210 +1,209 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.repo import RepoModel |
|
25 | 24 | from rhodecode.model.scm import ScmModel |
|
26 | 25 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_LOGIN |
|
27 | 26 | from rhodecode.api.tests.utils import ( |
|
28 | 27 | build_data, api_call, assert_error, assert_ok, crash, jsonify) |
|
29 | 28 | from rhodecode.tests.fixture import Fixture |
|
30 | 29 | from rhodecode.tests.fixture_mods.fixture_utils import plain_http_host_only_stub |
|
31 | 30 | |
|
32 | 31 | fixture = Fixture() |
|
33 | 32 | |
|
34 | 33 | UPDATE_REPO_NAME = 'api_update_me' |
|
35 | 34 | |
|
36 | 35 | |
|
37 | 36 | class SAME_AS_UPDATES(object): |
|
38 | 37 | """ Constant used for tests below """ |
|
39 | 38 | |
|
40 | 39 | |
|
41 | 40 | @pytest.mark.usefixtures("testuser_api", "app") |
|
42 | 41 | class TestApiUpdateRepo(object): |
|
43 | 42 | |
|
44 | 43 | @pytest.mark.parametrize("updates, expected", [ |
|
45 | 44 | ({'owner': TEST_USER_REGULAR_LOGIN}, |
|
46 | 45 | SAME_AS_UPDATES), |
|
47 | 46 | |
|
48 | 47 | ({'description': 'new description'}, |
|
49 | 48 | SAME_AS_UPDATES), |
|
50 | 49 | |
|
51 | 50 | ({'clone_uri': 'http://foo.com/repo'}, |
|
52 | 51 | SAME_AS_UPDATES), |
|
53 | 52 | |
|
54 | 53 | ({'clone_uri': None}, |
|
55 | 54 | {'clone_uri': ''}), |
|
56 | 55 | |
|
57 | 56 | ({'clone_uri': ''}, |
|
58 | 57 | {'clone_uri': ''}), |
|
59 | 58 | |
|
60 | 59 | ({'clone_uri': 'http://example.com/repo_pull'}, |
|
61 | 60 | {'clone_uri': 'http://example.com/repo_pull'}), |
|
62 | 61 | |
|
63 | 62 | ({'push_uri': ''}, |
|
64 | 63 | {'push_uri': ''}), |
|
65 | 64 | |
|
66 | 65 | ({'push_uri': 'http://example.com/repo_push'}, |
|
67 | 66 | {'push_uri': 'http://example.com/repo_push'}), |
|
68 | 67 | |
|
69 | 68 | ({'landing_rev': None}, # auto-updated based on type of repo |
|
70 | 69 | {'landing_rev': [None, None]}), |
|
71 | 70 | |
|
72 | 71 | ({'enable_statistics': True}, |
|
73 | 72 | SAME_AS_UPDATES), |
|
74 | 73 | |
|
75 | 74 | ({'enable_locking': True}, |
|
76 | 75 | SAME_AS_UPDATES), |
|
77 | 76 | |
|
78 | 77 | ({'enable_downloads': True}, |
|
79 | 78 | SAME_AS_UPDATES), |
|
80 | 79 | |
|
81 | 80 | ({'repo_name': 'new_repo_name'}, |
|
82 | 81 | { |
|
83 | 82 | 'repo_name': 'new_repo_name', |
|
84 | 83 | 'url': 'http://{}/new_repo_name'.format(plain_http_host_only_stub()) |
|
85 | 84 | }), |
|
86 | 85 | |
|
87 | 86 | ({'repo_name': 'test_group_for_update/{}'.format(UPDATE_REPO_NAME), |
|
88 | 87 | '_group': 'test_group_for_update'}, |
|
89 | 88 | { |
|
90 | 89 | 'repo_name': 'test_group_for_update/{}'.format(UPDATE_REPO_NAME), |
|
91 | 90 | 'url': 'http://{}/test_group_for_update/{}'.format( |
|
92 | 91 | plain_http_host_only_stub(), UPDATE_REPO_NAME) |
|
93 | 92 | }), |
|
94 | 93 | ]) |
|
95 | 94 | def test_api_update_repo(self, updates, expected, backend): |
|
96 | 95 | repo_name = UPDATE_REPO_NAME |
|
97 | 96 | repo = fixture.create_repo(repo_name, repo_type=backend.alias) |
|
98 | 97 | if updates.get('_group'): |
|
99 | 98 | fixture.create_repo_group(updates['_group']) |
|
100 | 99 | |
|
101 | 100 | if 'landing_rev' in updates: |
|
102 | 101 | default_landing_ref, _lbl = ScmModel.backend_landing_ref(backend.alias) |
|
103 | 102 | _type, _name = default_landing_ref.split(':') |
|
104 | 103 | updates['landing_rev'] = default_landing_ref |
|
105 | 104 | expected['landing_rev'] = [_type, _name] |
|
106 | 105 | |
|
107 | 106 | expected_api_data = repo.get_api_data(include_secrets=True) |
|
108 | 107 | if expected is SAME_AS_UPDATES: |
|
109 | 108 | expected_api_data.update(updates) |
|
110 | 109 | else: |
|
111 | 110 | expected_api_data.update(expected) |
|
112 | 111 | |
|
113 | 112 | id_, params = build_data( |
|
114 | 113 | self.apikey, 'update_repo', repoid=repo_name, **updates) |
|
115 | 114 | |
|
116 | 115 | with mock.patch('rhodecode.model.validation_schema.validators.url_validator'): |
|
117 | 116 | response = api_call(self.app, params) |
|
118 | 117 | |
|
119 | 118 | if updates.get('repo_name'): |
|
120 | 119 | repo_name = updates['repo_name'] |
|
121 | 120 | |
|
122 | 121 | try: |
|
123 | 122 | expected = { |
|
124 | 123 | 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo_name), |
|
125 | 124 | 'repository': jsonify(expected_api_data) |
|
126 | 125 | } |
|
127 | 126 | assert_ok(id_, expected, given=response.body) |
|
128 | 127 | finally: |
|
129 | 128 | fixture.destroy_repo(repo_name) |
|
130 | 129 | if updates.get('_group'): |
|
131 | 130 | fixture.destroy_repo_group(updates['_group']) |
|
132 | 131 | |
|
133 | 132 | def test_api_update_repo_fork_of_field(self, backend): |
|
134 | 133 | master_repo = backend.create_repo() |
|
135 | 134 | repo = backend.create_repo() |
|
136 | 135 | updates = { |
|
137 | 136 | 'fork_of': master_repo.repo_name, |
|
138 | 137 | 'fork_of_id': master_repo.repo_id |
|
139 | 138 | } |
|
140 | 139 | expected_api_data = repo.get_api_data(include_secrets=True) |
|
141 | 140 | expected_api_data.update(updates) |
|
142 | 141 | |
|
143 | 142 | id_, params = build_data( |
|
144 | 143 | self.apikey, 'update_repo', repoid=repo.repo_name, **updates) |
|
145 | 144 | response = api_call(self.app, params) |
|
146 | 145 | expected = { |
|
147 | 146 | 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo.repo_name), |
|
148 | 147 | 'repository': jsonify(expected_api_data) |
|
149 | 148 | } |
|
150 | 149 | assert_ok(id_, expected, given=response.body) |
|
151 | 150 | result = response.json['result']['repository'] |
|
152 | 151 | assert result['fork_of'] == master_repo.repo_name |
|
153 | 152 | assert result['fork_of_id'] == master_repo.repo_id |
|
154 | 153 | |
|
155 | 154 | def test_api_update_repo_fork_of_not_found(self, backend): |
|
156 | 155 | master_repo_name = 'fake-parent-repo' |
|
157 | 156 | repo = backend.create_repo() |
|
158 | 157 | updates = { |
|
159 | 158 | 'fork_of': master_repo_name |
|
160 | 159 | } |
|
161 | 160 | id_, params = build_data( |
|
162 | 161 | self.apikey, 'update_repo', repoid=repo.repo_name, **updates) |
|
163 | 162 | response = api_call(self.app, params) |
|
164 | 163 | expected = { |
|
165 | 164 | 'repo_fork_of': 'Fork with id `{}` does not exists'.format( |
|
166 | 165 | master_repo_name)} |
|
167 | 166 | assert_error(id_, expected, given=response.body) |
|
168 | 167 | |
|
169 | 168 | def test_api_update_repo_with_repo_group_not_existing(self): |
|
170 | 169 | repo_name = 'admin_owned' |
|
171 | 170 | fake_repo_group = 'test_group_for_update' |
|
172 | 171 | fixture.create_repo(repo_name) |
|
173 | 172 | updates = {'repo_name': '{}/{}'.format(fake_repo_group, repo_name)} |
|
174 | 173 | id_, params = build_data( |
|
175 | 174 | self.apikey, 'update_repo', repoid=repo_name, **updates) |
|
176 | 175 | response = api_call(self.app, params) |
|
177 | 176 | try: |
|
178 | 177 | expected = { |
|
179 | 178 | 'repo_group': 'Repository group `{}` does not exist'.format(fake_repo_group) |
|
180 | 179 | } |
|
181 | 180 | assert_error(id_, expected, given=response.body) |
|
182 | 181 | finally: |
|
183 | 182 | fixture.destroy_repo(repo_name) |
|
184 | 183 | |
|
185 | 184 | def test_api_update_repo_regular_user_not_allowed(self): |
|
186 | 185 | repo_name = 'admin_owned' |
|
187 | 186 | fixture.create_repo(repo_name) |
|
188 | 187 | updates = {'active': False} |
|
189 | 188 | id_, params = build_data( |
|
190 | 189 | self.apikey_regular, 'update_repo', repoid=repo_name, **updates) |
|
191 | 190 | response = api_call(self.app, params) |
|
192 | 191 | try: |
|
193 | 192 | expected = 'repository `%s` does not exist' % (repo_name,) |
|
194 | 193 | assert_error(id_, expected, given=response.body) |
|
195 | 194 | finally: |
|
196 | 195 | fixture.destroy_repo(repo_name) |
|
197 | 196 | |
|
198 | 197 | @mock.patch.object(RepoModel, 'update', crash) |
|
199 | 198 | def test_api_update_repo_exception_occurred(self, backend): |
|
200 | 199 | repo_name = UPDATE_REPO_NAME |
|
201 | 200 | fixture.create_repo(repo_name, repo_type=backend.alias) |
|
202 | 201 | id_, params = build_data( |
|
203 | 202 | self.apikey, 'update_repo', repoid=repo_name, |
|
204 | 203 | owner=TEST_USER_ADMIN_LOGIN,) |
|
205 | 204 | response = api_call(self.app, params) |
|
206 | 205 | try: |
|
207 | 206 | expected = 'failed to update repo `%s`' % (repo_name,) |
|
208 | 207 | assert_error(id_, expected, given=response.body) |
|
209 | 208 | finally: |
|
210 | 209 | fixture.destroy_repo(repo_name) |
@@ -1,150 +1,149 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import os |
|
22 | 21 | |
|
23 | 22 | import pytest |
|
24 | 23 | |
|
25 | 24 | from rhodecode.model.repo_group import RepoGroupModel |
|
26 | 25 | from rhodecode.model.user import UserModel |
|
27 | 26 | from rhodecode.api.tests.utils import ( |
|
28 | 27 | build_data, api_call, assert_error, assert_ok) |
|
29 | 28 | |
|
30 | 29 | |
|
31 | 30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
32 | 31 | class TestApiUpdateRepoGroup(object): |
|
33 | 32 | |
|
34 | 33 | def test_update_group_name(self, user_util): |
|
35 | 34 | new_group_name = 'new-group' |
|
36 | 35 | initial_name = self._update(user_util, group_name=new_group_name) |
|
37 | 36 | assert RepoGroupModel()._get_repo_group(initial_name) is None |
|
38 | 37 | new_group = RepoGroupModel()._get_repo_group(new_group_name) |
|
39 | 38 | assert new_group is not None |
|
40 | 39 | assert new_group.full_path == new_group_name |
|
41 | 40 | |
|
42 | 41 | def test_update_group_name_change_parent(self, user_util): |
|
43 | 42 | |
|
44 | 43 | parent_group = user_util.create_repo_group() |
|
45 | 44 | parent_group_name = parent_group.name |
|
46 | 45 | |
|
47 | 46 | expected_group_name = '{}/{}'.format(parent_group_name, 'new-group') |
|
48 | 47 | initial_name = self._update(user_util, group_name=expected_group_name) |
|
49 | 48 | |
|
50 | 49 | repo_group = RepoGroupModel()._get_repo_group(expected_group_name) |
|
51 | 50 | |
|
52 | 51 | assert repo_group is not None |
|
53 | 52 | assert repo_group.group_name == expected_group_name |
|
54 | 53 | assert repo_group.full_path == expected_group_name |
|
55 | 54 | assert RepoGroupModel()._get_repo_group(initial_name) is None |
|
56 | 55 | |
|
57 | 56 | new_path = os.path.join( |
|
58 | 57 | RepoGroupModel().repos_path, *repo_group.full_path_splitted) |
|
59 | 58 | assert os.path.exists(new_path) |
|
60 | 59 | |
|
61 | 60 | def test_update_enable_locking(self, user_util): |
|
62 | 61 | initial_name = self._update(user_util, enable_locking=True) |
|
63 | 62 | repo_group = RepoGroupModel()._get_repo_group(initial_name) |
|
64 | 63 | assert repo_group.enable_locking is True |
|
65 | 64 | |
|
66 | 65 | def test_update_description(self, user_util): |
|
67 | 66 | description = 'New description' |
|
68 | 67 | initial_name = self._update(user_util, description=description) |
|
69 | 68 | repo_group = RepoGroupModel()._get_repo_group(initial_name) |
|
70 | 69 | assert repo_group.group_description == description |
|
71 | 70 | |
|
72 | 71 | def test_update_owner(self, user_util): |
|
73 | 72 | owner = self.TEST_USER_LOGIN |
|
74 | 73 | initial_name = self._update(user_util, owner=owner) |
|
75 | 74 | repo_group = RepoGroupModel()._get_repo_group(initial_name) |
|
76 | 75 | assert repo_group.user.username == owner |
|
77 | 76 | |
|
78 | 77 | def test_update_group_name_conflict_with_existing(self, user_util): |
|
79 | 78 | group_1 = user_util.create_repo_group() |
|
80 | 79 | group_2 = user_util.create_repo_group() |
|
81 | 80 | repo_group_name_1 = group_1.group_name |
|
82 | 81 | repo_group_name_2 = group_2.group_name |
|
83 | 82 | |
|
84 | 83 | id_, params = build_data( |
|
85 | 84 | self.apikey, 'update_repo_group', repogroupid=repo_group_name_1, |
|
86 | 85 | group_name=repo_group_name_2) |
|
87 | 86 | response = api_call(self.app, params) |
|
88 | 87 | expected = { |
|
89 | 88 | 'unique_repo_group_name': |
|
90 | 89 | 'Repository group with name `{}` already exists'.format( |
|
91 | 90 | repo_group_name_2)} |
|
92 | 91 | assert_error(id_, expected, given=response.body) |
|
93 | 92 | |
|
94 | 93 | def test_api_update_repo_group_by_regular_user_no_permission(self, user_util): |
|
95 | 94 | temp_user = user_util.create_user() |
|
96 | 95 | temp_user_api_key = temp_user.api_key |
|
97 | 96 | parent_group = user_util.create_repo_group() |
|
98 | 97 | repo_group_name = parent_group.group_name |
|
99 | 98 | id_, params = build_data( |
|
100 | 99 | temp_user_api_key, 'update_repo_group', repogroupid=repo_group_name) |
|
101 | 100 | response = api_call(self.app, params) |
|
102 | 101 | expected = 'repository group `%s` does not exist' % (repo_group_name,) |
|
103 | 102 | assert_error(id_, expected, given=response.body) |
|
104 | 103 | |
|
105 | 104 | def test_api_update_repo_group_regular_user_no_root_write_permissions( |
|
106 | 105 | self, user_util): |
|
107 | 106 | temp_user = user_util.create_user() |
|
108 | 107 | temp_user_api_key = temp_user.api_key |
|
109 | 108 | parent_group = user_util.create_repo_group(owner=temp_user.username) |
|
110 | 109 | repo_group_name = parent_group.group_name |
|
111 | 110 | |
|
112 | 111 | id_, params = build_data( |
|
113 | 112 | temp_user_api_key, 'update_repo_group', repogroupid=repo_group_name, |
|
114 | 113 | group_name='at-root-level') |
|
115 | 114 | response = api_call(self.app, params) |
|
116 | 115 | expected = { |
|
117 | 116 | 'repo_group': 'You do not have the permission to store ' |
|
118 | 117 | 'repository groups in the root location.'} |
|
119 | 118 | assert_error(id_, expected, given=response.body) |
|
120 | 119 | |
|
121 | 120 | def _update(self, user_util, **kwargs): |
|
122 | 121 | repo_group = user_util.create_repo_group() |
|
123 | 122 | initial_name = repo_group.name |
|
124 | 123 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
125 | 124 | user_util.grant_user_permission_to_repo_group( |
|
126 | 125 | repo_group, user, 'group.admin') |
|
127 | 126 | |
|
128 | 127 | id_, params = build_data( |
|
129 | 128 | self.apikey, 'update_repo_group', repogroupid=initial_name, |
|
130 | 129 | **kwargs) |
|
131 | 130 | response = api_call(self.app, params) |
|
132 | 131 | |
|
133 | 132 | repo_group = RepoGroupModel.cls.get(repo_group.group_id) |
|
134 | 133 | |
|
135 | 134 | expected = { |
|
136 | 135 | 'msg': 'updated repository group ID:{} {}'.format( |
|
137 | 136 | repo_group.group_id, repo_group.group_name), |
|
138 | 137 | 'repo_group': { |
|
139 | 138 | 'repositories': [], |
|
140 | 139 | 'group_name': repo_group.group_name, |
|
141 | 140 | 'group_description': repo_group.group_description, |
|
142 | 141 | 'owner': repo_group.user.username, |
|
143 | 142 | 'group_id': repo_group.group_id, |
|
144 | 143 | 'parent_group': ( |
|
145 | 144 | repo_group.parent_group.name |
|
146 | 145 | if repo_group.parent_group else None) |
|
147 | 146 | } |
|
148 | 147 | } |
|
149 | 148 | assert_ok(id_, expected, given=response.body) |
|
150 | 149 | return initial_name |
@@ -1,121 +1,120 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.db import User |
|
25 | 24 | from rhodecode.model.user import UserModel |
|
26 | 25 | from rhodecode.tests import TEST_USER_ADMIN_LOGIN |
|
27 | 26 | from rhodecode.api.tests.utils import ( |
|
28 | 27 | build_data, api_call, assert_ok, assert_error, crash, jsonify) |
|
29 | 28 | |
|
30 | 29 | |
|
31 | 30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
32 | 31 | class TestUpdateUser(object): |
|
33 | 32 | @pytest.mark.parametrize("name, expected", [ |
|
34 | 33 | ('firstname', 'new_username'), |
|
35 | 34 | ('lastname', 'new_username'), |
|
36 | 35 | ('email', 'new_username'), |
|
37 | 36 | ('admin', True), |
|
38 | 37 | ('admin', False), |
|
39 | 38 | ('extern_type', 'ldap'), |
|
40 | 39 | ('extern_type', None), |
|
41 | 40 | ('extern_name', 'test'), |
|
42 | 41 | ('extern_name', None), |
|
43 | 42 | ('active', False), |
|
44 | 43 | ('active', True), |
|
45 | 44 | ('password', 'newpass'), |
|
46 | 45 | ('description', 'CTO 4 Life') |
|
47 | 46 | ]) |
|
48 | 47 | def test_api_update_user(self, name, expected, user_util): |
|
49 | 48 | usr = user_util.create_user() |
|
50 | 49 | |
|
51 | 50 | kw = {name: expected, 'userid': usr.user_id} |
|
52 | 51 | id_, params = build_data(self.apikey, 'update_user', **kw) |
|
53 | 52 | response = api_call(self.app, params) |
|
54 | 53 | |
|
55 | 54 | ret = { |
|
56 | 55 | 'msg': 'updated user ID:%s %s' % (usr.user_id, usr.username), |
|
57 | 56 | 'user': jsonify( |
|
58 | 57 | UserModel() |
|
59 | 58 | .get_by_username(usr.username) |
|
60 | 59 | .get_api_data(include_secrets=True) |
|
61 | 60 | ) |
|
62 | 61 | } |
|
63 | 62 | |
|
64 | 63 | expected = ret |
|
65 | 64 | assert_ok(id_, expected, given=response.body) |
|
66 | 65 | |
|
67 | 66 | def test_api_update_user_no_changed_params(self): |
|
68 | 67 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
69 | 68 | ret = jsonify(usr.get_api_data(include_secrets=True)) |
|
70 | 69 | id_, params = build_data( |
|
71 | 70 | self.apikey, 'update_user', userid=TEST_USER_ADMIN_LOGIN) |
|
72 | 71 | |
|
73 | 72 | response = api_call(self.app, params) |
|
74 | 73 | ret = { |
|
75 | 74 | 'msg': 'updated user ID:%s %s' % ( |
|
76 | 75 | usr.user_id, TEST_USER_ADMIN_LOGIN), |
|
77 | 76 | 'user': ret |
|
78 | 77 | } |
|
79 | 78 | expected = ret |
|
80 | 79 | expected['user']['last_activity'] = response.json['result']['user'][ |
|
81 | 80 | 'last_activity'] |
|
82 | 81 | assert_ok(id_, expected, given=response.body) |
|
83 | 82 | |
|
84 | 83 | def test_api_update_user_by_user_id(self): |
|
85 | 84 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
86 | 85 | ret = jsonify(usr.get_api_data(include_secrets=True)) |
|
87 | 86 | id_, params = build_data( |
|
88 | 87 | self.apikey, 'update_user', userid=usr.user_id) |
|
89 | 88 | |
|
90 | 89 | response = api_call(self.app, params) |
|
91 | 90 | ret = { |
|
92 | 91 | 'msg': 'updated user ID:%s %s' % ( |
|
93 | 92 | usr.user_id, TEST_USER_ADMIN_LOGIN), |
|
94 | 93 | 'user': ret |
|
95 | 94 | } |
|
96 | 95 | expected = ret |
|
97 | 96 | expected['user']['last_activity'] = response.json['result']['user'][ |
|
98 | 97 | 'last_activity'] |
|
99 | 98 | assert_ok(id_, expected, given=response.body) |
|
100 | 99 | |
|
101 | 100 | def test_api_update_user_default_user(self): |
|
102 | 101 | usr = User.get_default_user() |
|
103 | 102 | id_, params = build_data( |
|
104 | 103 | self.apikey, 'update_user', userid=usr.user_id) |
|
105 | 104 | |
|
106 | 105 | response = api_call(self.app, params) |
|
107 | 106 | expected = 'editing default user is forbidden' |
|
108 | 107 | assert_error(id_, expected, given=response.body) |
|
109 | 108 | |
|
110 | 109 | @mock.patch.object(UserModel, 'update_user', crash) |
|
111 | 110 | def test_api_update_user_when_exception_happens(self): |
|
112 | 111 | usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
|
113 | 112 | ret = jsonify(usr.get_api_data(include_secrets=True)) |
|
114 | 113 | id_, params = build_data( |
|
115 | 114 | self.apikey, 'update_user', userid=usr.user_id) |
|
116 | 115 | |
|
117 | 116 | response = api_call(self.app, params) |
|
118 | 117 | ret = 'failed to update user `%s`' % (usr.user_id,) |
|
119 | 118 | |
|
120 | 119 | expected = ret |
|
121 | 120 | assert_error(id_, expected, given=response.body) |
@@ -1,125 +1,124 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | import mock |
|
22 | 21 | import pytest |
|
23 | 22 | |
|
24 | 23 | from rhodecode.model.user import UserModel |
|
25 | 24 | from rhodecode.model.user_group import UserGroupModel |
|
26 | 25 | from rhodecode.tests import TEST_USER_ADMIN_EMAIL |
|
27 | 26 | from rhodecode.api.tests.utils import ( |
|
28 | 27 | build_data, api_call, assert_error, assert_ok, crash, jsonify) |
|
29 | 28 | |
|
30 | 29 | |
|
31 | 30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
32 | 31 | class TestUpdateUserGroup(object): |
|
33 | 32 | @pytest.mark.parametrize("changing_attr, updates", [ |
|
34 | 33 | ('group_name', {'group_name': 'new_group_name'}), |
|
35 | 34 | ('group_name', {'group_name': 'test_group_for_update'}), |
|
36 | 35 | # ('owner', {'owner': TEST_USER_REGULAR_LOGIN}), |
|
37 | 36 | ('owner_email', {'owner_email': TEST_USER_ADMIN_EMAIL}), |
|
38 | 37 | ('active', {'active': False}), |
|
39 | 38 | ('active', {'active': True}), |
|
40 | 39 | ('sync', {'sync': False}), |
|
41 | 40 | ('sync', {'sync': True}) |
|
42 | 41 | ]) |
|
43 | 42 | def test_api_update_user_group(self, changing_attr, updates, user_util): |
|
44 | 43 | user_group = user_util.create_user_group() |
|
45 | 44 | group_name = user_group.users_group_name |
|
46 | 45 | expected_api_data = user_group.get_api_data() |
|
47 | 46 | expected_api_data.update(updates) |
|
48 | 47 | |
|
49 | 48 | id_, params = build_data( |
|
50 | 49 | self.apikey, 'update_user_group', usergroupid=group_name, |
|
51 | 50 | **updates) |
|
52 | 51 | response = api_call(self.app, params) |
|
53 | 52 | |
|
54 | 53 | # special case for sync |
|
55 | 54 | if changing_attr == 'sync' and updates['sync'] is False: |
|
56 | 55 | expected_api_data['sync'] = None |
|
57 | 56 | elif changing_attr == 'sync' and updates['sync'] is True: |
|
58 | 57 | expected_api_data['sync'] = 'manual_api' |
|
59 | 58 | |
|
60 | 59 | expected = { |
|
61 | 60 | 'msg': 'updated user group ID:%s %s' % ( |
|
62 | 61 | user_group.users_group_id, user_group.users_group_name), |
|
63 | 62 | 'user_group': jsonify(expected_api_data) |
|
64 | 63 | } |
|
65 | 64 | assert_ok(id_, expected, given=response.body) |
|
66 | 65 | |
|
67 | 66 | @pytest.mark.parametrize("changing_attr, updates", [ |
|
68 | 67 | # TODO: mikhail: decide if we need to test against the commented params |
|
69 | 68 | # ('group_name', {'group_name': 'new_group_name'}), |
|
70 | 69 | # ('group_name', {'group_name': 'test_group_for_update'}), |
|
71 | 70 | # ('owner', {'owner': TEST_USER_REGULAR_LOGIN}), |
|
72 | 71 | ('owner_email', {'owner_email': TEST_USER_ADMIN_EMAIL}), |
|
73 | 72 | ('active', {'active': False}), |
|
74 | 73 | ('active', {'active': True}), |
|
75 | 74 | ('sync', {'sync': False}), |
|
76 | 75 | ('sync', {'sync': True}) |
|
77 | 76 | ]) |
|
78 | 77 | def test_api_update_user_group_regular_user( |
|
79 | 78 | self, changing_attr, updates, user_util): |
|
80 | 79 | user_group = user_util.create_user_group() |
|
81 | 80 | group_name = user_group.users_group_name |
|
82 | 81 | expected_api_data = user_group.get_api_data() |
|
83 | 82 | expected_api_data.update(updates) |
|
84 | 83 | |
|
85 | 84 | # grant permission to this user |
|
86 | 85 | user = UserModel().get_by_username(self.TEST_USER_LOGIN) |
|
87 | 86 | |
|
88 | 87 | user_util.grant_user_permission_to_user_group( |
|
89 | 88 | user_group, user, 'usergroup.admin') |
|
90 | 89 | id_, params = build_data( |
|
91 | 90 | self.apikey_regular, 'update_user_group', |
|
92 | 91 | usergroupid=group_name, **updates) |
|
93 | 92 | response = api_call(self.app, params) |
|
94 | 93 | # special case for sync |
|
95 | 94 | if changing_attr == 'sync' and updates['sync'] is False: |
|
96 | 95 | expected_api_data['sync'] = None |
|
97 | 96 | elif changing_attr == 'sync' and updates['sync'] is True: |
|
98 | 97 | expected_api_data['sync'] = 'manual_api' |
|
99 | 98 | |
|
100 | 99 | expected = { |
|
101 | 100 | 'msg': 'updated user group ID:%s %s' % ( |
|
102 | 101 | user_group.users_group_id, user_group.users_group_name), |
|
103 | 102 | 'user_group': jsonify(expected_api_data) |
|
104 | 103 | } |
|
105 | 104 | assert_ok(id_, expected, given=response.body) |
|
106 | 105 | |
|
107 | 106 | def test_api_update_user_group_regular_user_no_permission(self, user_util): |
|
108 | 107 | user_group = user_util.create_user_group() |
|
109 | 108 | group_name = user_group.users_group_name |
|
110 | 109 | id_, params = build_data( |
|
111 | 110 | self.apikey_regular, 'update_user_group', usergroupid=group_name) |
|
112 | 111 | response = api_call(self.app, params) |
|
113 | 112 | |
|
114 | 113 | expected = 'user group `%s` does not exist' % (group_name) |
|
115 | 114 | assert_error(id_, expected, given=response.body) |
|
116 | 115 | |
|
117 | 116 | @mock.patch.object(UserGroupModel, 'update', crash) |
|
118 | 117 | def test_api_update_user_group_exception_occurred(self, user_util): |
|
119 | 118 | user_group = user_util.create_user_group() |
|
120 | 119 | group_name = user_group.users_group_name |
|
121 | 120 | id_, params = build_data( |
|
122 | 121 | self.apikey, 'update_user_group', usergroupid=group_name) |
|
123 | 122 | response = api_call(self.app, params) |
|
124 | 123 | expected = 'failed to update user group `%s`' % (group_name,) |
|
125 | 124 | assert_error(id_, expected, given=response.body) |
@@ -1,295 +1,297 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import pytest |
|
23 | 22 | from mock import Mock, patch |
|
24 | 23 | |
|
25 | 24 | from rhodecode.api import utils |
|
26 | 25 | from rhodecode.api import JSONRPCError |
|
27 | 26 | from rhodecode.lib.vcs.exceptions import RepositoryError |
|
28 | 27 | |
|
29 | 28 | |
|
30 | 29 | class TestGetCommitOrError(object): |
|
31 | def setup(self): | |
|
30 | ||
|
31 | def setup_method(self): | |
|
32 | 32 | self.commit_hash = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10' |
|
33 | 33 | |
|
34 | 34 | @pytest.mark.parametrize("ref", ['ref', '12345', 'a:b:c:d', 'branch:name']) |
|
35 | 35 | def test_ref_cannot_be_parsed(self, ref): |
|
36 | 36 | repo = Mock() |
|
37 | 37 | with pytest.raises(JSONRPCError) as excinfo: |
|
38 | 38 | utils.get_commit_or_error(ref, repo) |
|
39 | 39 | expected_message = ( |
|
40 | 40 | 'Ref `{ref}` given in a wrong format. Please check the API' |
|
41 | 41 | ' documentation for more details'.format(ref=ref) |
|
42 | 42 | ) |
|
43 | 43 | assert excinfo.value.message == expected_message |
|
44 | 44 | |
|
45 | 45 | def test_success_with_hash_specified(self): |
|
46 | 46 | repo = Mock() |
|
47 | 47 | ref_type = 'branch' |
|
48 | 48 | ref = '{}:master:{}'.format(ref_type, self.commit_hash) |
|
49 | 49 | |
|
50 | 50 | with patch('rhodecode.api.utils.get_commit_from_ref_name') as get_commit: |
|
51 | 51 | result = utils.get_commit_or_error(ref, repo) |
|
52 | 52 | get_commit.assert_called_once_with( |
|
53 | 53 | repo, self.commit_hash) |
|
54 | 54 | assert result == get_commit() |
|
55 | 55 | |
|
56 | 56 | def test_raises_an_error_when_commit_not_found(self): |
|
57 | 57 | repo = Mock() |
|
58 | 58 | ref = 'branch:master:{}'.format(self.commit_hash) |
|
59 | 59 | |
|
60 | 60 | with patch('rhodecode.api.utils.get_commit_from_ref_name') as get_commit: |
|
61 | 61 | get_commit.side_effect = RepositoryError('Commit not found') |
|
62 | 62 | with pytest.raises(JSONRPCError) as excinfo: |
|
63 | 63 | utils.get_commit_or_error(ref, repo) |
|
64 | 64 | expected_message = 'Ref `{}` does not exist'.format(ref) |
|
65 | 65 | assert excinfo.value.message == expected_message |
|
66 | 66 | |
|
67 | 67 | |
|
68 | 68 | class TestResolveRefOrError(object): |
|
69 | def setup(self): | |
|
69 | ||
|
70 | def setup_method(self): | |
|
70 | 71 | self.commit_hash = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10' |
|
71 | 72 | |
|
72 | 73 | def test_success_with_no_hash_specified(self): |
|
73 | 74 | repo = Mock() |
|
74 | 75 | ref_type = 'branch' |
|
75 | 76 | ref_name = 'master' |
|
76 | 77 | ref = '{}:{}'.format(ref_type, ref_name) |
|
77 | 78 | |
|
78 | 79 | with patch('rhodecode.api.utils._get_ref_hash') \ |
|
79 | 80 | as _get_ref_hash: |
|
80 | 81 | _get_ref_hash.return_value = self.commit_hash |
|
81 | 82 | result = utils.resolve_ref_or_error(ref, repo) |
|
82 | 83 | _get_ref_hash.assert_called_once_with(repo, ref_type, ref_name) |
|
83 | 84 | assert result == '{}:{}'.format(ref, self.commit_hash) |
|
84 | 85 | |
|
85 | 86 | def test_non_supported_refs(self): |
|
86 | 87 | repo = Mock() |
|
87 | 88 | ref = 'bookmark:ref' |
|
88 | 89 | with pytest.raises(JSONRPCError) as excinfo: |
|
89 | 90 | utils.resolve_ref_or_error(ref, repo) |
|
90 | 91 | expected_message = ( |
|
91 | 92 | 'The specified value:bookmark:`ref` does not exist, or is not allowed.') |
|
92 | 93 | assert excinfo.value.message == expected_message |
|
93 | 94 | |
|
94 | 95 | def test_branch_is_not_found(self): |
|
95 | 96 | repo = Mock() |
|
96 | 97 | ref = 'branch:non-existing-one' |
|
97 | 98 | with patch('rhodecode.api.utils._get_ref_hash')\ |
|
98 | 99 | as _get_ref_hash: |
|
99 | 100 | _get_ref_hash.side_effect = KeyError() |
|
100 | 101 | with pytest.raises(JSONRPCError) as excinfo: |
|
101 | 102 | utils.resolve_ref_or_error(ref, repo) |
|
102 | 103 | expected_message = ( |
|
103 | 104 | 'The specified value:branch:`non-existing-one` does not exist, or is not allowed.') |
|
104 | 105 | assert excinfo.value.message == expected_message |
|
105 | 106 | |
|
106 | 107 | def test_bookmark_is_not_found(self): |
|
107 | 108 | repo = Mock() |
|
108 | 109 | ref = 'bookmark:non-existing-one' |
|
109 | 110 | with patch('rhodecode.api.utils._get_ref_hash')\ |
|
110 | 111 | as _get_ref_hash: |
|
111 | 112 | _get_ref_hash.side_effect = KeyError() |
|
112 | 113 | with pytest.raises(JSONRPCError) as excinfo: |
|
113 | 114 | utils.resolve_ref_or_error(ref, repo) |
|
114 | 115 | expected_message = ( |
|
115 | 116 | 'The specified value:bookmark:`non-existing-one` does not exist, or is not allowed.') |
|
116 | 117 | assert excinfo.value.message == expected_message |
|
117 | 118 | |
|
118 | 119 | @pytest.mark.parametrize("ref", ['ref', '12345', 'a:b:c:d']) |
|
119 | 120 | def test_ref_cannot_be_parsed(self, ref): |
|
120 | 121 | repo = Mock() |
|
121 | 122 | with pytest.raises(JSONRPCError) as excinfo: |
|
122 | 123 | utils.resolve_ref_or_error(ref, repo) |
|
123 | 124 | expected_message = ( |
|
124 | 125 | 'Ref `{ref}` given in a wrong format. Please check the API' |
|
125 | 126 | ' documentation for more details'.format(ref=ref) |
|
126 | 127 | ) |
|
127 | 128 | assert excinfo.value.message == expected_message |
|
128 | 129 | |
|
129 | 130 | |
|
130 | 131 | class TestGetRefHash(object): |
|
131 | def setup(self): | |
|
132 | ||
|
133 | def setup_method(self): | |
|
132 | 134 | self.commit_hash = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa10' |
|
133 | 135 | self.bookmark_name = 'test-bookmark' |
|
134 | 136 | |
|
135 | 137 | @pytest.mark.parametrize("alias, branch_name", [ |
|
136 | 138 | ("git", "master"), |
|
137 | 139 | ("hg", "default") |
|
138 | 140 | ]) |
|
139 | 141 | def test_returns_hash_by_branch_name(self, alias, branch_name): |
|
140 | 142 | with patch('rhodecode.model.db.Repository') as repo: |
|
141 | 143 | repo.scm_instance().alias = alias |
|
142 | 144 | repo.scm_instance().branches = {branch_name: self.commit_hash} |
|
143 | 145 | result_hash = utils._get_ref_hash(repo, 'branch', branch_name) |
|
144 | 146 | assert result_hash == self.commit_hash |
|
145 | 147 | |
|
146 | 148 | @pytest.mark.parametrize("alias, branch_name", [ |
|
147 | 149 | ("git", "master"), |
|
148 | 150 | ("hg", "default") |
|
149 | 151 | ]) |
|
150 | 152 | def test_raises_error_when_branch_is_not_found(self, alias, branch_name): |
|
151 | 153 | with patch('rhodecode.model.db.Repository') as repo: |
|
152 | 154 | repo.scm_instance().alias = alias |
|
153 | 155 | repo.scm_instance().branches = {} |
|
154 | 156 | with pytest.raises(KeyError): |
|
155 | 157 | utils._get_ref_hash(repo, 'branch', branch_name) |
|
156 | 158 | |
|
157 | 159 | def test_returns_hash_when_bookmark_is_specified_for_hg(self): |
|
158 | 160 | with patch('rhodecode.model.db.Repository') as repo: |
|
159 | 161 | repo.scm_instance().alias = 'hg' |
|
160 | 162 | repo.scm_instance().bookmarks = { |
|
161 | 163 | self.bookmark_name: self.commit_hash} |
|
162 | 164 | result_hash = utils._get_ref_hash( |
|
163 | 165 | repo, 'bookmark', self.bookmark_name) |
|
164 | 166 | assert result_hash == self.commit_hash |
|
165 | 167 | |
|
166 | 168 | def test_raises_error_when_bookmark_is_not_found_in_hg_repo(self): |
|
167 | 169 | with patch('rhodecode.model.db.Repository') as repo: |
|
168 | 170 | repo.scm_instance().alias = 'hg' |
|
169 | 171 | repo.scm_instance().bookmarks = {} |
|
170 | 172 | with pytest.raises(KeyError): |
|
171 | 173 | utils._get_ref_hash(repo, 'bookmark', self.bookmark_name) |
|
172 | 174 | |
|
173 | 175 | def test_raises_error_when_bookmark_is_specified_for_git(self): |
|
174 | 176 | with patch('rhodecode.model.db.Repository') as repo: |
|
175 | 177 | repo.scm_instance().alias = 'git' |
|
176 | 178 | repo.scm_instance().bookmarks = { |
|
177 | 179 | self.bookmark_name: self.commit_hash} |
|
178 | 180 | with pytest.raises(ValueError): |
|
179 | 181 | utils._get_ref_hash(repo, 'bookmark', self.bookmark_name) |
|
180 | 182 | |
|
181 | 183 | |
|
182 | 184 | class TestUserByNameOrError(object): |
|
183 | 185 | def test_user_found_by_id(self): |
|
184 | 186 | fake_user = Mock(id=123) |
|
185 | 187 | |
|
186 | 188 | patcher = patch('rhodecode.model.user.UserModel.get_user') |
|
187 | 189 | with patcher as get_user: |
|
188 | 190 | get_user.return_value = fake_user |
|
189 | 191 | |
|
190 | 192 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') |
|
191 | 193 | with patcher as get_by_username: |
|
192 | 194 | result = utils.get_user_or_error(123) |
|
193 | 195 | assert result == fake_user |
|
194 | 196 | |
|
195 | 197 | def test_user_not_found_by_id_as_str(self): |
|
196 | 198 | fake_user = Mock(id=123) |
|
197 | 199 | |
|
198 | 200 | patcher = patch('rhodecode.model.user.UserModel.get_user') |
|
199 | 201 | with patcher as get_user: |
|
200 | 202 | get_user.return_value = fake_user |
|
201 | 203 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') |
|
202 | 204 | with patcher as get_by_username: |
|
203 | 205 | get_by_username.return_value = None |
|
204 | 206 | |
|
205 | 207 | with pytest.raises(JSONRPCError): |
|
206 | 208 | utils.get_user_or_error('123') |
|
207 | 209 | |
|
208 | 210 | def test_user_found_by_name(self): |
|
209 | 211 | fake_user = Mock(id=123) |
|
210 | 212 | |
|
211 | 213 | patcher = patch('rhodecode.model.user.UserModel.get_user') |
|
212 | 214 | with patcher as get_user: |
|
213 | 215 | get_user.return_value = None |
|
214 | 216 | |
|
215 | 217 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') |
|
216 | 218 | with patcher as get_by_username: |
|
217 | 219 | get_by_username.return_value = fake_user |
|
218 | 220 | |
|
219 | 221 | result = utils.get_user_or_error('test') |
|
220 | 222 | assert result == fake_user |
|
221 | 223 | |
|
222 | 224 | def test_user_not_found_by_id(self): |
|
223 | 225 | patcher = patch('rhodecode.model.user.UserModel.get_user') |
|
224 | 226 | with patcher as get_user: |
|
225 | 227 | get_user.return_value = None |
|
226 | 228 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') |
|
227 | 229 | with patcher as get_by_username: |
|
228 | 230 | get_by_username.return_value = None |
|
229 | 231 | |
|
230 | 232 | with pytest.raises(JSONRPCError) as excinfo: |
|
231 | 233 | utils.get_user_or_error(123) |
|
232 | 234 | |
|
233 | 235 | expected_message = 'user `123` does not exist' |
|
234 | 236 | assert excinfo.value.message == expected_message |
|
235 | 237 | |
|
236 | 238 | def test_user_not_found_by_name(self): |
|
237 | 239 | patcher = patch('rhodecode.model.user.UserModel.get_by_username') |
|
238 | 240 | with patcher as get_by_username: |
|
239 | 241 | get_by_username.return_value = None |
|
240 | 242 | with pytest.raises(JSONRPCError) as excinfo: |
|
241 | 243 | utils.get_user_or_error('test') |
|
242 | 244 | |
|
243 | 245 | expected_message = 'user `test` does not exist' |
|
244 | 246 | assert excinfo.value.message == expected_message |
|
245 | 247 | |
|
246 | 248 | |
|
247 | 249 | class TestGetCommitDict(object): |
|
248 | 250 | @pytest.mark.parametrize('filename, expected', [ |
|
249 | 251 | (b'sp\xc3\xa4cial', u'sp\xe4cial'), |
|
250 | 252 | (b'sp\xa4cial', u'sp\ufffdcial'), |
|
251 | 253 | ]) |
|
252 | 254 | def test_decodes_filenames_to_unicode(self, filename, expected): |
|
253 | 255 | result = utils._get_commit_dict(filename=filename, op='A') |
|
254 | 256 | assert result['filename'] == expected |
|
255 | 257 | |
|
256 | 258 | |
|
257 | 259 | class TestRepoAccess(object): |
|
258 | 260 | def setup_method(self, method): |
|
259 | 261 | |
|
260 | 262 | self.admin_perm_patch = patch( |
|
261 | 263 | 'rhodecode.api.utils.HasPermissionAnyApi') |
|
262 | 264 | self.repo_perm_patch = patch( |
|
263 | 265 | 'rhodecode.api.utils.HasRepoPermissionAnyApi') |
|
264 | 266 | |
|
265 | 267 | def test_has_superadmin_permission_checks_for_admin(self): |
|
266 | 268 | admin_mock = Mock() |
|
267 | 269 | with self.admin_perm_patch as amock: |
|
268 | 270 | amock.return_value = admin_mock |
|
269 | 271 | assert utils.has_superadmin_permission('fake_user') |
|
270 | 272 | amock.assert_called_once_with('hg.admin') |
|
271 | 273 | |
|
272 | 274 | admin_mock.assert_called_once_with(user='fake_user') |
|
273 | 275 | |
|
274 | 276 | def test_has_repo_permissions_checks_for_repo_access(self): |
|
275 | 277 | repo_mock = Mock() |
|
276 | 278 | fake_repo = Mock() |
|
277 | 279 | with self.repo_perm_patch as rmock: |
|
278 | 280 | rmock.return_value = repo_mock |
|
279 | 281 | assert utils.validate_repo_permissions( |
|
280 | 282 | 'fake_user', 'fake_repo_id', fake_repo, |
|
281 | 283 | ['perm1', 'perm2']) |
|
282 | 284 | rmock.assert_called_once_with(*['perm1', 'perm2']) |
|
283 | 285 | |
|
284 | 286 | repo_mock.assert_called_once_with( |
|
285 | 287 | user='fake_user', repo_name=fake_repo.repo_name) |
|
286 | 288 | |
|
287 | 289 | def test_has_repo_permissions_raises_not_found(self): |
|
288 | 290 | repo_mock = Mock(return_value=False) |
|
289 | 291 | fake_repo = Mock() |
|
290 | 292 | with self.repo_perm_patch as rmock: |
|
291 | 293 | rmock.return_value = repo_mock |
|
292 | 294 | with pytest.raises(JSONRPCError) as excinfo: |
|
293 | 295 | utils.validate_repo_permissions( |
|
294 | 296 | 'fake_user', 'fake_repo_id', fake_repo, 'perms') |
|
295 | 297 | assert 'fake_repo_id' in excinfo |
@@ -1,124 +1,123 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
2 | 1 |
|
|
3 | 2 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
4 | 3 | # |
|
5 | 4 | # This program is free software: you can redistribute it and/or modify |
|
6 | 5 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 6 | # (only), as published by the Free Software Foundation. |
|
8 | 7 | # |
|
9 | 8 | # This program is distributed in the hope that it will be useful, |
|
10 | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 11 | # GNU General Public License for more details. |
|
13 | 12 | # |
|
14 | 13 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 15 | # |
|
17 | 16 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 17 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 18 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 19 | |
|
21 | 20 | |
|
22 | 21 | import random |
|
23 | 22 | import pytest |
|
24 | 23 | |
|
25 | 24 | from rhodecode.api.utils import get_origin |
|
26 | 25 | from rhodecode.lib.ext_json import json |
|
27 | 26 | |
|
28 | 27 | |
|
29 | 28 | def jsonify(obj): |
|
30 | 29 | return json.loads(json.dumps(obj)) |
|
31 | 30 | |
|
32 | 31 | |
|
33 | 32 | API_URL = '/_admin/api' |
|
34 | 33 | |
|
35 | 34 | |
|
36 | 35 | def assert_call_ok(id_, given): |
|
37 | 36 | expected = jsonify({ |
|
38 | 37 | 'id': id_, |
|
39 | 38 | 'error': None, |
|
40 | 39 | 'result': None |
|
41 | 40 | }) |
|
42 | 41 | given = json.loads(given) |
|
43 | 42 | |
|
44 | 43 | assert expected['id'] == given['id'] |
|
45 | 44 | assert expected['error'] == given['error'] |
|
46 | 45 | return given['result'] |
|
47 | 46 | |
|
48 | 47 | |
|
49 | 48 | def assert_ok(id_, expected, given): |
|
50 | 49 | given = json.loads(given) |
|
51 | 50 | if given.get('error'): |
|
52 | 51 | err = given['error'] |
|
53 |
pytest.fail( |
|
|
52 | pytest.fail(f"Unexpected ERROR in expected success response: `{err}`") | |
|
54 | 53 | |
|
55 | 54 | expected = jsonify({ |
|
56 | 55 | 'id': id_, |
|
57 | 56 | 'error': None, |
|
58 | 57 | 'result': expected |
|
59 | 58 | }) |
|
60 | 59 | |
|
61 | 60 | assert expected == given |
|
62 | 61 | |
|
63 | 62 | |
|
64 | 63 | def assert_error(id_, expected, given): |
|
65 | 64 | expected = jsonify({ |
|
66 | 65 | 'id': id_, |
|
67 | 66 | 'error': expected, |
|
68 | 67 | 'result': None |
|
69 | 68 | }) |
|
70 | 69 | given = json.loads(given) |
|
71 | 70 | assert expected == given |
|
72 | 71 | |
|
73 | 72 | |
|
74 | 73 | def build_data(apikey, method, **kw): |
|
75 | 74 | """ |
|
76 | 75 | Builds API data with given random ID |
|
77 | 76 | """ |
|
78 | 77 | random_id = random.randrange(1, 9999) |
|
79 | 78 | return random_id, json.dumps({ |
|
80 | 79 | "id": random_id, |
|
81 | 80 | "api_key": apikey, |
|
82 | 81 | "method": method, |
|
83 | 82 | "args": kw |
|
84 | 83 | }) |
|
85 | 84 | |
|
86 | 85 | |
|
87 | 86 | def api_call(app, params, status=None): |
|
88 | 87 | response = app.post( |
|
89 | 88 | API_URL, content_type='application/json', params=params, status=status, |
|
90 | 89 | headers=[('Content-Type', 'application/json')]) |
|
91 | 90 | return response |
|
92 | 91 | |
|
93 | 92 | |
|
94 | 93 | def crash(*args, **kwargs): |
|
95 | 94 | raise Exception('Total Crash !') |
|
96 | 95 | |
|
97 | 96 | |
|
98 | 97 | def expected_permissions(object_with_permissions): |
|
99 | 98 | """ |
|
100 | 99 | Returns the expected permissions structure for the given object. |
|
101 | 100 | |
|
102 | 101 | The object is expected to be a `Repository`, `RepositoryGroup`, |
|
103 | 102 | or `UserGroup`. They all implement the same permission handling |
|
104 | 103 | API. |
|
105 | 104 | """ |
|
106 | 105 | permissions = [] |
|
107 | 106 | for _user in object_with_permissions.permissions(): |
|
108 | 107 | user_data = { |
|
109 | 108 | 'name': _user.username, |
|
110 | 109 | 'permission': _user.permission, |
|
111 | 110 | 'origin': get_origin(_user), |
|
112 | 111 | 'type': "user", |
|
113 | 112 | } |
|
114 | 113 | permissions.append(user_data) |
|
115 | 114 | |
|
116 | 115 | for _user_group in object_with_permissions.permission_user_groups(): |
|
117 | 116 | user_group_data = { |
|
118 | 117 | 'name': _user_group.users_group_name, |
|
119 | 118 | 'permission': _user_group.permission, |
|
120 | 119 | 'origin': get_origin(_user_group), |
|
121 | 120 | 'type': "user_group", |
|
122 | 121 | } |
|
123 | 122 | permissions.append(user_group_data) |
|
124 | 123 | return permissions |
@@ -1,152 +1,152 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
1 | ||
|
2 | 2 | |
|
3 | 3 | # Copyright (C) 2011-2020 RhodeCode GmbH |
|
4 | 4 | # |
|
5 | 5 | # This program is free software: you can redistribute it and/or modify |
|
6 | 6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 7 | # (only), as published by the Free Software Foundation. |
|
8 | 8 | # |
|
9 | 9 | # This program is distributed in the hope that it will be useful, |
|
10 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 12 | # GNU General Public License for more details. |
|
13 | 13 | # |
|
14 | 14 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 16 | # |
|
17 | 17 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 20 | |
|
21 | 21 | |
|
22 | 22 | import logging |
|
23 | 23 | |
|
24 | 24 | from rhodecode.api import jsonrpc_method |
|
25 | 25 | from rhodecode.api.exc import JSONRPCValidationError, JSONRPCForbidden |
|
26 | 26 | from rhodecode.api.utils import Optional, has_superadmin_permission |
|
27 | 27 | from rhodecode.lib.index import searcher_from_config |
|
28 | 28 | from rhodecode.lib.user_log_filter import user_log_filter |
|
29 | 29 | from rhodecode.model import validation_schema |
|
30 | 30 | from rhodecode.model.db import joinedload, UserLog |
|
31 | 31 | from rhodecode.model.validation_schema.schemas import search_schema |
|
32 | 32 | |
|
33 | 33 | log = logging.getLogger(__name__) |
|
34 | 34 | |
|
35 | 35 | |
|
36 | 36 | @jsonrpc_method() |
|
37 | 37 | def search(request, apiuser, search_query, search_type, page_limit=Optional(10), |
|
38 | 38 | page=Optional(1), search_sort=Optional('desc:date'), |
|
39 | 39 | repo_name=Optional(None), repo_group_name=Optional(None)): |
|
40 | 40 | """ |
|
41 | 41 | Fetch Full Text Search results using API. |
|
42 | 42 | |
|
43 | 43 | :param apiuser: This is filled automatically from the |authtoken|. |
|
44 | 44 | :type apiuser: AuthUser |
|
45 | 45 | :param search_query: Search query. |
|
46 | 46 | :type search_query: str |
|
47 | 47 | :param search_type: Search type. The following are valid options: |
|
48 | 48 | * commit |
|
49 | 49 | * content |
|
50 | 50 | * path |
|
51 | 51 | :type search_type: str |
|
52 | 52 | :param page_limit: Page item limit, from 1 to 500. Default 10 items. |
|
53 | 53 | :type page_limit: Optional(int) |
|
54 | 54 | :param page: Page number. Default first page. |
|
55 | 55 | :type page: Optional(int) |
|
56 | 56 | :param search_sort: Search sort order.Must start with asc: or desc: Default desc:date. |
|
57 | 57 | The following are valid options: |
|
58 | 58 | * asc|desc:message.raw |
|
59 | 59 | * asc|desc:date |
|
60 | 60 | * asc|desc:author.email.raw |
|
61 | 61 | * asc|desc:message.raw |
|
62 | 62 | * newfirst (old legacy equal to desc:date) |
|
63 | 63 | * oldfirst (old legacy equal to asc:date) |
|
64 | 64 | |
|
65 | 65 | :type search_sort: Optional(str) |
|
66 | 66 | :param repo_name: Filter by one repo. Default is all. |
|
67 | 67 | :type repo_name: Optional(str) |
|
68 | 68 | :param repo_group_name: Filter by one repo group. Default is all. |
|
69 | 69 | :type repo_group_name: Optional(str) |
|
70 | 70 | """ |
|
71 | 71 | |
|
72 | 72 | data = {'execution_time': ''} |
|
73 | 73 | repo_name = Optional.extract(repo_name) |
|
74 | 74 | repo_group_name = Optional.extract(repo_group_name) |
|
75 | 75 | |
|
76 | 76 | schema = search_schema.SearchParamsSchema() |
|
77 | 77 | |
|
78 | 78 | try: |
|
79 | 79 | search_params = schema.deserialize( |
|
80 | 80 | dict(search_query=search_query, |
|
81 | 81 | search_type=search_type, |
|
82 | 82 | search_sort=Optional.extract(search_sort), |
|
83 | 83 | page_limit=Optional.extract(page_limit), |
|
84 | 84 | requested_page=Optional.extract(page)) |
|
85 | 85 | ) |
|
86 | 86 | except validation_schema.Invalid as err: |
|
87 | 87 | raise JSONRPCValidationError(colander_exc=err) |
|
88 | 88 | |
|
89 | 89 | search_query = search_params.get('search_query') |
|
90 | 90 | search_type = search_params.get('search_type') |
|
91 | 91 | search_sort = search_params.get('search_sort') |
|
92 | 92 | |
|
93 | 93 | if search_params.get('search_query'): |
|
94 | 94 | page_limit = search_params['page_limit'] |
|
95 | 95 | requested_page = search_params['requested_page'] |
|
96 | 96 | |
|
97 | 97 | searcher = searcher_from_config(request.registry.settings) |
|
98 | 98 | |
|
99 | 99 | try: |
|
100 | 100 | search_result = searcher.search( |
|
101 | 101 | search_query, search_type, apiuser, repo_name, repo_group_name, |
|
102 | 102 | requested_page=requested_page, page_limit=page_limit, sort=search_sort) |
|
103 | 103 | |
|
104 | 104 | data.update(dict( |
|
105 | 105 | results=list(search_result['results']), page=requested_page, |
|
106 | 106 | item_count=search_result['count'], |
|
107 | 107 | items_per_page=page_limit)) |
|
108 | 108 | finally: |
|
109 | 109 | searcher.cleanup() |
|
110 | 110 | |
|
111 | 111 | if not search_result['error']: |
|
112 | 112 | data['execution_time'] = '%s results (%.4f seconds)' % ( |
|
113 | 113 | search_result['count'], |
|
114 | 114 | search_result['runtime']) |
|
115 | 115 | else: |
|
116 | 116 | node = schema['search_query'] |
|
117 | 117 | raise JSONRPCValidationError( |
|
118 | 118 | colander_exc=validation_schema.Invalid(node, search_result['error'])) |
|
119 | 119 | |
|
120 | 120 | return data |
|
121 | 121 | |
|
122 | 122 | |
|
123 | 123 | @jsonrpc_method() |
|
124 | 124 | def get_audit_logs(request, apiuser, query): |
|
125 | 125 | """ |
|
126 | 126 | return full audit logs based on the query. |
|
127 | 127 | |
|
128 | 128 | Please see `example query in admin > settings > audit logs` for examples |
|
129 | 129 | |
|
130 | 130 | :param apiuser: This is filled automatically from the |authtoken|. |
|
131 | 131 | :type apiuser: AuthUser |
|
132 | 132 | :param query: filter query, example: action:repo.artifact.add date:[20200401 TO 20200601]" |
|
133 | 133 | :type query: str |
|
134 | 134 | """ |
|
135 | 135 | |
|
136 | 136 | if not has_superadmin_permission(apiuser): |
|
137 | 137 | raise JSONRPCForbidden() |
|
138 | 138 | |
|
139 | 139 | filter_term = query |
|
140 | 140 | ret = [] |
|
141 | 141 | |
|
142 | 142 | # show all user actions |
|
143 | 143 | user_log = UserLog.query() \ |
|
144 | 144 | .options(joinedload(UserLog.user)) \ |
|
145 | 145 | .options(joinedload(UserLog.repository)) \ |
|
146 | 146 | .order_by(UserLog.action_date.desc()) |
|
147 | 147 | |
|
148 | 148 | audit_log = user_log_filter(user_log, filter_term) |
|
149 | 149 | |
|
150 | 150 | for entry in audit_log: |
|
151 | 151 | ret.append(entry) |
|
152 | 152 | return ret |
General Comments 0
You need to be logged in to leave comments.
Login now