##// END OF EJS Templates
tests: api: add test for pulling from a custom remote...
Thomas De Schampheleire -
r7065:30209433 default
parent child Browse files
Show More
@@ -1,2628 +1,2645 b''
1 1 # -*- coding: utf-8 -*-
2 2 # This program is free software: you can redistribute it and/or modify
3 3 # it under the terms of the GNU General Public License as published by
4 4 # the Free Software Foundation, either version 3 of the License, or
5 5 # (at your option) any later version.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14
15 15 """
16 16 Tests for the JSON-RPC web api.
17 17 """
18 18
19 19 import os
20 20 import random
21 21 import mock
22 22 import re
23 23
24 24 from kallithea.tests.base import *
25 25 from kallithea.tests.fixture import Fixture
26 26 from kallithea.lib.compat import json
27 27 from kallithea.lib.auth import AuthUser
28 28 from kallithea.model.user import UserModel
29 29 from kallithea.model.user_group import UserGroupModel
30 30 from kallithea.model.repo import RepoModel
31 31 from kallithea.model.repo_group import RepoGroupModel
32 32 from kallithea.model.meta import Session
33 33 from kallithea.model.scm import ScmModel
34 34 from kallithea.model.gist import GistModel
35 35 from kallithea.model.changeset_status import ChangesetStatusModel
36 36 from kallithea.model.db import Repository, User, Setting, Ui, PullRequest, ChangesetStatus
37 37 from kallithea.lib.utils2 import time_to_datetime
38 38
39 39
40 40 API_URL = '/_admin/api'
41 41 TEST_USER_GROUP = u'test_user_group'
42 42 TEST_REPO_GROUP = u'test_repo_group'
43 43
44 44 fixture = Fixture()
45 45
46 46
47 47 def _build_data(apikey, method, **kw):
48 48 """
49 49 Builds API data with given random ID
50 50
51 51 :param random_id:
52 52 """
53 53 random_id = random.randrange(1, 9999)
54 54 return random_id, json.dumps({
55 55 "id": random_id,
56 56 "api_key": apikey,
57 57 "method": method,
58 58 "args": kw
59 59 })
60 60
61 61
62 62 jsonify = lambda obj: json.loads(json.dumps(obj))
63 63
64 64
65 65 def crash(*args, **kwargs):
66 66 raise Exception('Total Crash !')
67 67
68 68
69 69 def api_call(test_obj, params):
70 70 response = test_obj.app.post(API_URL, content_type='application/json',
71 71 params=params)
72 72 return response
73 73
74 74
75 75 ## helpers
76 76 def make_user_group(name=TEST_USER_GROUP):
77 77 gr = fixture.create_user_group(name, cur_user=TEST_USER_ADMIN_LOGIN)
78 78 UserGroupModel().add_user_to_group(user_group=gr,
79 79 user=TEST_USER_ADMIN_LOGIN)
80 80 Session().commit()
81 81 return gr
82 82
83 83
84 84 def make_repo_group(name=TEST_REPO_GROUP):
85 85 gr = fixture.create_repo_group(name, cur_user=TEST_USER_ADMIN_LOGIN)
86 86 Session().commit()
87 87 return gr
88 88
89 89
90 90 class _BaseTestApi(object):
91 91 REPO = None
92 92 REPO_TYPE = None
93 93
94 94 @classmethod
95 95 def setup_class(cls):
96 96 cls.usr = User.get_by_username(TEST_USER_ADMIN_LOGIN)
97 97 cls.apikey = cls.usr.api_key
98 98 cls.test_user = UserModel().create_or_update(
99 99 username='test-api',
100 100 password='test',
101 101 email='test@example.com',
102 102 firstname=u'first',
103 103 lastname=u'last'
104 104 )
105 105 Session().commit()
106 106 cls.TEST_USER_LOGIN = cls.test_user.username
107 107 cls.apikey_regular = cls.test_user.api_key
108 108
109 109 @classmethod
110 110 def teardown_class(cls):
111 111 pass
112 112
113 113 def setup_method(self, method):
114 114 make_user_group()
115 115 make_repo_group()
116 116
117 117 def teardown_method(self, method):
118 118 fixture.destroy_user_group(TEST_USER_GROUP)
119 119 fixture.destroy_gists()
120 120 fixture.destroy_repo_group(TEST_REPO_GROUP)
121 121
122 122 def _compare_ok(self, id_, expected, given):
123 123 expected = jsonify({
124 124 'id': id_,
125 125 'error': None,
126 126 'result': expected
127 127 })
128 128 given = json.loads(given)
129 129 assert expected == given
130 130
131 131 def _compare_error(self, id_, expected, given):
132 132 expected = jsonify({
133 133 'id': id_,
134 134 'error': expected,
135 135 'result': None
136 136 })
137 137 given = json.loads(given)
138 138 assert expected == given
139 139
140 140 def test_Optional_object(self):
141 141 from kallithea.controllers.api.api import Optional
142 142
143 143 option1 = Optional(None)
144 144 assert '<Optional:%s>' % None == repr(option1)
145 145 assert option1() is None
146 146
147 147 assert 1 == Optional.extract(Optional(1))
148 148 assert 'trololo' == Optional.extract('trololo')
149 149
150 150 def test_Optional_OAttr(self):
151 151 from kallithea.controllers.api.api import Optional, OAttr
152 152
153 153 option1 = Optional(OAttr('apiuser'))
154 154 assert 'apiuser' == Optional.extract(option1)
155 155
156 156 def test_OAttr_object(self):
157 157 from kallithea.controllers.api.api import OAttr
158 158
159 159 oattr1 = OAttr('apiuser')
160 160 assert '<OptionalAttr:apiuser>' == repr(oattr1)
161 161 assert oattr1() == oattr1
162 162
163 163 def test_api_wrong_key(self):
164 164 id_, params = _build_data('trololo', 'get_user')
165 165 response = api_call(self, params)
166 166
167 167 expected = 'Invalid API key'
168 168 self._compare_error(id_, expected, given=response.body)
169 169
170 170 def test_api_missing_non_optional_param(self):
171 171 id_, params = _build_data(self.apikey, 'get_repo')
172 172 response = api_call(self, params)
173 173
174 174 expected = 'Missing non optional `repoid` arg in JSON DATA'
175 175 self._compare_error(id_, expected, given=response.body)
176 176
177 177 def test_api_missing_non_optional_param_args_null(self):
178 178 id_, params = _build_data(self.apikey, 'get_repo')
179 179 params = params.replace('"args": {}', '"args": null')
180 180 response = api_call(self, params)
181 181
182 182 expected = 'Missing non optional `repoid` arg in JSON DATA'
183 183 self._compare_error(id_, expected, given=response.body)
184 184
185 185 def test_api_missing_non_optional_param_args_bad(self):
186 186 id_, params = _build_data(self.apikey, 'get_repo')
187 187 params = params.replace('"args": {}', '"args": 1')
188 188 response = api_call(self, params)
189 189
190 190 expected = 'Missing non optional `repoid` arg in JSON DATA'
191 191 self._compare_error(id_, expected, given=response.body)
192 192
193 193 def test_api_args_is_null(self):
194 194 id_, params = _build_data(self.apikey, 'get_users', )
195 195 params = params.replace('"args": {}', '"args": null')
196 196 response = api_call(self, params)
197 197 assert response.status == '200 OK'
198 198
199 199 def test_api_args_is_bad(self):
200 200 id_, params = _build_data(self.apikey, 'get_users', )
201 201 params = params.replace('"args": {}', '"args": 1')
202 202 response = api_call(self, params)
203 203 assert response.status == '200 OK'
204 204
205 205 def test_api_args_different_args(self):
206 206 import string
207 207 expected = {
208 208 'ascii_letters': string.ascii_letters,
209 209 'ws': string.whitespace,
210 210 'printables': string.printable
211 211 }
212 212 id_, params = _build_data(self.apikey, 'test', args=expected)
213 213 response = api_call(self, params)
214 214 assert response.status == '200 OK'
215 215 self._compare_ok(id_, expected, response.body)
216 216
217 217 def test_api_get_users(self):
218 218 id_, params = _build_data(self.apikey, 'get_users', )
219 219 response = api_call(self, params)
220 220 ret_all = []
221 221 _users = User.query().filter_by(is_default_user=False) \
222 222 .order_by(User.username).all()
223 223 for usr in _users:
224 224 ret = usr.get_api_data()
225 225 ret_all.append(jsonify(ret))
226 226 expected = ret_all
227 227 self._compare_ok(id_, expected, given=response.body)
228 228
229 229 def test_api_get_user(self):
230 230 id_, params = _build_data(self.apikey, 'get_user',
231 231 userid=TEST_USER_ADMIN_LOGIN)
232 232 response = api_call(self, params)
233 233
234 234 usr = User.get_by_username(TEST_USER_ADMIN_LOGIN)
235 235 ret = usr.get_api_data()
236 236 ret['permissions'] = AuthUser(dbuser=usr).permissions
237 237
238 238 expected = ret
239 239 self._compare_ok(id_, expected, given=response.body)
240 240
241 241 def test_api_get_user_that_does_not_exist(self):
242 242 id_, params = _build_data(self.apikey, 'get_user',
243 243 userid='trololo')
244 244 response = api_call(self, params)
245 245
246 246 expected = "user `%s` does not exist" % 'trololo'
247 247 self._compare_error(id_, expected, given=response.body)
248 248
249 249 def test_api_get_user_without_giving_userid(self):
250 250 id_, params = _build_data(self.apikey, 'get_user')
251 251 response = api_call(self, params)
252 252
253 253 usr = User.get_by_username(TEST_USER_ADMIN_LOGIN)
254 254 ret = usr.get_api_data()
255 255 ret['permissions'] = AuthUser(dbuser=usr).permissions
256 256
257 257 expected = ret
258 258 self._compare_ok(id_, expected, given=response.body)
259 259
260 260 def test_api_get_user_without_giving_userid_non_admin(self):
261 261 id_, params = _build_data(self.apikey_regular, 'get_user')
262 262 response = api_call(self, params)
263 263
264 264 usr = User.get_by_username(self.TEST_USER_LOGIN)
265 265 ret = usr.get_api_data()
266 266 ret['permissions'] = AuthUser(dbuser=usr).permissions
267 267
268 268 expected = ret
269 269 self._compare_ok(id_, expected, given=response.body)
270 270
271 271 def test_api_get_user_with_giving_userid_non_admin(self):
272 272 id_, params = _build_data(self.apikey_regular, 'get_user',
273 273 userid=self.TEST_USER_LOGIN)
274 274 response = api_call(self, params)
275 275
276 276 expected = 'userid is not the same as your user'
277 277 self._compare_error(id_, expected, given=response.body)
278 278
279 279 def test_api_pull_remote(self):
280 280 repo_name = u'test_pull'
281 281 r = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
282 282 r.clone_uri = os.path.join(Ui.get_by_key('paths', '/').ui_value, self.REPO)
283 283 Session().commit()
284 284
285 285 id_, params = _build_data(self.apikey, 'pull',
286 286 repoid=repo_name,)
287 287 response = api_call(self, params)
288 288
289 289 expected = {'msg': 'Pulled from `%s`' % repo_name,
290 290 'repository': repo_name}
291 291 self._compare_ok(id_, expected, given=response.body)
292 292
293 293 fixture.destroy_repo(repo_name)
294 294
295 295 def test_api_pull_fork(self):
296 296 fork_name = u'fork'
297 297 fixture.create_fork(self.REPO, fork_name)
298 298 id_, params = _build_data(self.apikey, 'pull',
299 299 repoid=fork_name,)
300 300 response = api_call(self, params)
301 301
302 302 expected = {'msg': 'Pulled from `%s`' % fork_name,
303 303 'repository': fork_name}
304 304 self._compare_ok(id_, expected, given=response.body)
305 305
306 306 fixture.destroy_repo(fork_name)
307 307
308 308 def test_api_pull_error_no_remote_no_fork(self):
309 309 # should fail because no clone_uri is set
310 310 id_, params = _build_data(self.apikey, 'pull',
311 311 repoid=self.REPO, )
312 312 response = api_call(self, params)
313 313
314 314 expected = 'Unable to pull changes from `%s`' % self.REPO
315 315 self._compare_error(id_, expected, given=response.body)
316 316
317 def test_api_pull_custom_remote(self):
318 repo_name = u'test_pull_custom_remote'
319 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
320
321 custom_remote_path = os.path.join(Ui.get_by_key('paths', '/').ui_value, self.REPO)
322
323 id_, params = _build_data(self.apikey, 'pull',
324 repoid=repo_name,
325 clone_uri=custom_remote_path)
326 response = api_call(self, params)
327
328 expected = {'msg': 'Pulled from `%s`' % repo_name,
329 'repository': repo_name}
330 self._compare_ok(id_, expected, given=response.body)
331
332 fixture.destroy_repo(repo_name)
333
317 334 def test_api_rescan_repos(self):
318 335 id_, params = _build_data(self.apikey, 'rescan_repos')
319 336 response = api_call(self, params)
320 337
321 338 expected = {'added': [], 'removed': []}
322 339 self._compare_ok(id_, expected, given=response.body)
323 340
324 341 @mock.patch.object(ScmModel, 'repo_scan', crash)
325 342 def test_api_rescann_error(self):
326 343 id_, params = _build_data(self.apikey, 'rescan_repos', )
327 344 response = api_call(self, params)
328 345
329 346 expected = 'Error occurred during rescan repositories action'
330 347 self._compare_error(id_, expected, given=response.body)
331 348
332 349 def test_api_invalidate_cache(self):
333 350 repo = RepoModel().get_by_repo_name(self.REPO)
334 351 repo.scm_instance_cached() # seed cache
335 352
336 353 id_, params = _build_data(self.apikey, 'invalidate_cache',
337 354 repoid=self.REPO)
338 355 response = api_call(self, params)
339 356
340 357 expected = {
341 358 'msg': "Cache for repository `%s` was invalidated" % (self.REPO,),
342 359 'repository': self.REPO
343 360 }
344 361 self._compare_ok(id_, expected, given=response.body)
345 362
346 363 @mock.patch.object(ScmModel, 'mark_for_invalidation', crash)
347 364 def test_api_invalidate_cache_error(self):
348 365 id_, params = _build_data(self.apikey, 'invalidate_cache',
349 366 repoid=self.REPO)
350 367 response = api_call(self, params)
351 368
352 369 expected = 'Error occurred during cache invalidation action'
353 370 self._compare_error(id_, expected, given=response.body)
354 371
355 372 def test_api_invalidate_cache_regular_user_no_permission(self):
356 373 repo = RepoModel().get_by_repo_name(self.REPO)
357 374 repo.scm_instance_cached() # seed cache
358 375
359 376 id_, params = _build_data(self.apikey_regular, 'invalidate_cache',
360 377 repoid=self.REPO)
361 378 response = api_call(self, params)
362 379
363 380 expected = "repository `%s` does not exist" % (self.REPO,)
364 381 self._compare_error(id_, expected, given=response.body)
365 382
366 383 def test_api_lock_repo_lock_acquire(self):
367 384 id_, params = _build_data(self.apikey, 'lock',
368 385 userid=TEST_USER_ADMIN_LOGIN,
369 386 repoid=self.REPO,
370 387 locked=True)
371 388 response = api_call(self, params)
372 389 expected = {
373 390 'repo': self.REPO, 'locked': True,
374 391 'locked_since': response.json['result']['locked_since'],
375 392 'locked_by': TEST_USER_ADMIN_LOGIN,
376 393 'lock_state_changed': True,
377 394 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
378 395 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
379 396 }
380 397 self._compare_ok(id_, expected, given=response.body)
381 398
382 399 def test_api_lock_repo_lock_acquire_by_non_admin(self):
383 400 repo_name = u'api_delete_me'
384 401 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
385 402 cur_user=self.TEST_USER_LOGIN)
386 403 try:
387 404 id_, params = _build_data(self.apikey_regular, 'lock',
388 405 repoid=repo_name,
389 406 locked=True)
390 407 response = api_call(self, params)
391 408 expected = {
392 409 'repo': repo_name,
393 410 'locked': True,
394 411 'locked_since': response.json['result']['locked_since'],
395 412 'locked_by': self.TEST_USER_LOGIN,
396 413 'lock_state_changed': True,
397 414 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
398 415 % (self.TEST_USER_LOGIN, repo_name, True))
399 416 }
400 417 self._compare_ok(id_, expected, given=response.body)
401 418 finally:
402 419 fixture.destroy_repo(repo_name)
403 420
404 421 def test_api_lock_repo_lock_acquire_non_admin_with_userid(self):
405 422 repo_name = u'api_delete_me'
406 423 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
407 424 cur_user=self.TEST_USER_LOGIN)
408 425 try:
409 426 id_, params = _build_data(self.apikey_regular, 'lock',
410 427 userid=TEST_USER_ADMIN_LOGIN,
411 428 repoid=repo_name,
412 429 locked=True)
413 430 response = api_call(self, params)
414 431 expected = 'userid is not the same as your user'
415 432 self._compare_error(id_, expected, given=response.body)
416 433 finally:
417 434 fixture.destroy_repo(repo_name)
418 435
419 436 def test_api_lock_repo_lock_acquire_non_admin_not_his_repo(self):
420 437 id_, params = _build_data(self.apikey_regular, 'lock',
421 438 repoid=self.REPO,
422 439 locked=True)
423 440 response = api_call(self, params)
424 441 expected = 'repository `%s` does not exist' % (self.REPO)
425 442 self._compare_error(id_, expected, given=response.body)
426 443
427 444 def test_api_lock_repo_lock_release(self):
428 445 id_, params = _build_data(self.apikey, 'lock',
429 446 userid=TEST_USER_ADMIN_LOGIN,
430 447 repoid=self.REPO,
431 448 locked=False)
432 449 response = api_call(self, params)
433 450 expected = {
434 451 'repo': self.REPO,
435 452 'locked': False,
436 453 'locked_since': None,
437 454 'locked_by': TEST_USER_ADMIN_LOGIN,
438 455 'lock_state_changed': True,
439 456 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
440 457 % (TEST_USER_ADMIN_LOGIN, self.REPO, False))
441 458 }
442 459 self._compare_ok(id_, expected, given=response.body)
443 460
444 461 def test_api_lock_repo_lock_acquire_optional_userid(self):
445 462 id_, params = _build_data(self.apikey, 'lock',
446 463 repoid=self.REPO,
447 464 locked=True)
448 465 response = api_call(self, params)
449 466 time_ = response.json['result']['locked_since']
450 467 expected = {
451 468 'repo': self.REPO,
452 469 'locked': True,
453 470 'locked_since': time_,
454 471 'locked_by': TEST_USER_ADMIN_LOGIN,
455 472 'lock_state_changed': True,
456 473 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
457 474 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
458 475 }
459 476
460 477 self._compare_ok(id_, expected, given=response.body)
461 478
462 479 def test_api_lock_repo_lock_optional_locked(self):
463 480 try:
464 481 id_, params = _build_data(self.apikey, 'lock',
465 482 repoid=self.REPO)
466 483 response = api_call(self, params)
467 484 time_ = response.json['result']['locked_since']
468 485 expected = {
469 486 'repo': self.REPO,
470 487 'locked': True,
471 488 'locked_since': time_,
472 489 'locked_by': TEST_USER_ADMIN_LOGIN,
473 490 'lock_state_changed': False,
474 491 'msg': ('Repo `%s` locked by `%s` on `%s`.'
475 492 % (self.REPO, TEST_USER_ADMIN_LOGIN,
476 493 json.dumps(time_to_datetime(time_))))
477 494 }
478 495 self._compare_ok(id_, expected, given=response.body)
479 496 finally:
480 497 # cleanup
481 498 Repository.unlock(RepoModel().get_by_repo_name(self.REPO))
482 499
483 500 def test_api_lock_repo_lock_optional_not_locked(self):
484 501 repo_name = u'api_not_locked'
485 502 repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
486 503 cur_user=self.TEST_USER_LOGIN)
487 504 assert repo.locked == [None, None]
488 505 try:
489 506 id_, params = _build_data(self.apikey, 'lock',
490 507 repoid=repo.repo_id)
491 508 response = api_call(self, params)
492 509 expected = {
493 510 'repo': repo_name,
494 511 'locked': False,
495 512 'locked_since': None,
496 513 'locked_by': None,
497 514 'lock_state_changed': False,
498 515 'msg': ('Repo `%s` not locked.' % (repo_name,))
499 516 }
500 517 self._compare_ok(id_, expected, given=response.body)
501 518 finally:
502 519 fixture.destroy_repo(repo_name)
503 520
504 521 @mock.patch.object(Repository, 'lock', crash)
505 522 def test_api_lock_error(self):
506 523 id_, params = _build_data(self.apikey, 'lock',
507 524 userid=TEST_USER_ADMIN_LOGIN,
508 525 repoid=self.REPO,
509 526 locked=True)
510 527 response = api_call(self, params)
511 528
512 529 expected = 'Error occurred locking repository `%s`' % self.REPO
513 530 self._compare_error(id_, expected, given=response.body)
514 531
515 532 def test_api_get_locks_regular_user(self):
516 533 id_, params = _build_data(self.apikey_regular, 'get_locks')
517 534 response = api_call(self, params)
518 535 expected = []
519 536 self._compare_ok(id_, expected, given=response.body)
520 537
521 538 def test_api_get_locks_with_userid_regular_user(self):
522 539 id_, params = _build_data(self.apikey_regular, 'get_locks',
523 540 userid=TEST_USER_ADMIN_LOGIN)
524 541 response = api_call(self, params)
525 542 expected = 'userid is not the same as your user'
526 543 self._compare_error(id_, expected, given=response.body)
527 544
528 545 def test_api_get_locks(self):
529 546 id_, params = _build_data(self.apikey, 'get_locks')
530 547 response = api_call(self, params)
531 548 expected = []
532 549 self._compare_ok(id_, expected, given=response.body)
533 550
534 551 def test_api_get_locks_with_one_locked_repo(self):
535 552 repo_name = u'api_delete_me'
536 553 repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
537 554 cur_user=self.TEST_USER_LOGIN)
538 555 Repository.lock(repo, User.get_by_username(self.TEST_USER_LOGIN).user_id)
539 556 try:
540 557 id_, params = _build_data(self.apikey, 'get_locks')
541 558 response = api_call(self, params)
542 559 expected = [repo.get_api_data()]
543 560 self._compare_ok(id_, expected, given=response.body)
544 561 finally:
545 562 fixture.destroy_repo(repo_name)
546 563
547 564 def test_api_get_locks_with_one_locked_repo_for_specific_user(self):
548 565 repo_name = u'api_delete_me'
549 566 repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
550 567 cur_user=self.TEST_USER_LOGIN)
551 568 Repository.lock(repo, User.get_by_username(self.TEST_USER_LOGIN).user_id)
552 569 try:
553 570 id_, params = _build_data(self.apikey, 'get_locks',
554 571 userid=self.TEST_USER_LOGIN)
555 572 response = api_call(self, params)
556 573 expected = [repo.get_api_data()]
557 574 self._compare_ok(id_, expected, given=response.body)
558 575 finally:
559 576 fixture.destroy_repo(repo_name)
560 577
561 578 def test_api_get_locks_with_userid(self):
562 579 id_, params = _build_data(self.apikey, 'get_locks',
563 580 userid=TEST_USER_REGULAR_LOGIN)
564 581 response = api_call(self, params)
565 582 expected = []
566 583 self._compare_ok(id_, expected, given=response.body)
567 584
568 585 def test_api_create_existing_user(self):
569 586 id_, params = _build_data(self.apikey, 'create_user',
570 587 username=TEST_USER_ADMIN_LOGIN,
571 588 email='test@example.com',
572 589 password='trololo')
573 590 response = api_call(self, params)
574 591
575 592 expected = "user `%s` already exist" % TEST_USER_ADMIN_LOGIN
576 593 self._compare_error(id_, expected, given=response.body)
577 594
578 595 def test_api_create_user_with_existing_email(self):
579 596 id_, params = _build_data(self.apikey, 'create_user',
580 597 username=TEST_USER_ADMIN_LOGIN + 'new',
581 598 email=TEST_USER_REGULAR_EMAIL,
582 599 password='trololo')
583 600 response = api_call(self, params)
584 601
585 602 expected = "email `%s` already exist" % TEST_USER_REGULAR_EMAIL
586 603 self._compare_error(id_, expected, given=response.body)
587 604
588 605 def test_api_create_user(self):
589 606 username = 'test_new_api_user'
590 607 email = username + "@example.com"
591 608
592 609 id_, params = _build_data(self.apikey, 'create_user',
593 610 username=username,
594 611 email=email,
595 612 password='trololo')
596 613 response = api_call(self, params)
597 614
598 615 usr = User.get_by_username(username)
599 616 ret = dict(
600 617 msg='created new user `%s`' % username,
601 618 user=jsonify(usr.get_api_data())
602 619 )
603 620
604 621 try:
605 622 expected = ret
606 623 self._compare_ok(id_, expected, given=response.body)
607 624 finally:
608 625 fixture.destroy_user(usr.user_id)
609 626
610 627 def test_api_create_user_without_password(self):
611 628 username = 'test_new_api_user_passwordless'
612 629 email = username + "@example.com"
613 630
614 631 id_, params = _build_data(self.apikey, 'create_user',
615 632 username=username,
616 633 email=email)
617 634 response = api_call(self, params)
618 635
619 636 usr = User.get_by_username(username)
620 637 ret = dict(
621 638 msg='created new user `%s`' % username,
622 639 user=jsonify(usr.get_api_data())
623 640 )
624 641 try:
625 642 expected = ret
626 643 self._compare_ok(id_, expected, given=response.body)
627 644 finally:
628 645 fixture.destroy_user(usr.user_id)
629 646
630 647 def test_api_create_user_with_extern_name(self):
631 648 username = 'test_new_api_user_passwordless'
632 649 email = username + "@example.com"
633 650
634 651 id_, params = _build_data(self.apikey, 'create_user',
635 652 username=username,
636 653 email=email, extern_name='internal')
637 654 response = api_call(self, params)
638 655
639 656 usr = User.get_by_username(username)
640 657 ret = dict(
641 658 msg='created new user `%s`' % username,
642 659 user=jsonify(usr.get_api_data())
643 660 )
644 661 try:
645 662 expected = ret
646 663 self._compare_ok(id_, expected, given=response.body)
647 664 finally:
648 665 fixture.destroy_user(usr.user_id)
649 666
650 667 @mock.patch.object(UserModel, 'create_or_update', crash)
651 668 def test_api_create_user_when_exception_happened(self):
652 669
653 670 username = 'test_new_api_user'
654 671 email = username + "@example.com"
655 672
656 673 id_, params = _build_data(self.apikey, 'create_user',
657 674 username=username,
658 675 email=email,
659 676 password='trololo')
660 677 response = api_call(self, params)
661 678 expected = 'failed to create user `%s`' % username
662 679 self._compare_error(id_, expected, given=response.body)
663 680
664 681 def test_api_delete_user(self):
665 682 usr = UserModel().create_or_update(username=u'test_user',
666 683 password=u'qweqwe',
667 684 email=u'u232@example.com',
668 685 firstname=u'u1', lastname=u'u1')
669 686 Session().commit()
670 687 username = usr.username
671 688 email = usr.email
672 689 usr_id = usr.user_id
673 690 ## DELETE THIS USER NOW
674 691
675 692 id_, params = _build_data(self.apikey, 'delete_user',
676 693 userid=username, )
677 694 response = api_call(self, params)
678 695
679 696 ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username),
680 697 'user': None}
681 698 expected = ret
682 699 self._compare_ok(id_, expected, given=response.body)
683 700
684 701 @mock.patch.object(UserModel, 'delete', crash)
685 702 def test_api_delete_user_when_exception_happened(self):
686 703 usr = UserModel().create_or_update(username=u'test_user',
687 704 password=u'qweqwe',
688 705 email=u'u232@example.com',
689 706 firstname=u'u1', lastname=u'u1')
690 707 Session().commit()
691 708 username = usr.username
692 709
693 710 id_, params = _build_data(self.apikey, 'delete_user',
694 711 userid=username, )
695 712 response = api_call(self, params)
696 713 ret = 'failed to delete user ID:%s %s' % (usr.user_id,
697 714 usr.username)
698 715 expected = ret
699 716 self._compare_error(id_, expected, given=response.body)
700 717
701 718 @parametrize('name,expected', [
702 719 ('firstname', 'new_username'),
703 720 ('lastname', 'new_username'),
704 721 ('email', 'new_username'),
705 722 ('admin', True),
706 723 ('admin', False),
707 724 ('extern_type', 'ldap'),
708 725 ('extern_type', None),
709 726 ('extern_name', 'test'),
710 727 ('extern_name', None),
711 728 ('active', False),
712 729 ('active', True),
713 730 ('password', 'newpass'),
714 731 ])
715 732 def test_api_update_user(self, name, expected):
716 733 usr = User.get_by_username(self.TEST_USER_LOGIN)
717 734 kw = {name: expected,
718 735 'userid': usr.user_id}
719 736 id_, params = _build_data(self.apikey, 'update_user', **kw)
720 737 response = api_call(self, params)
721 738
722 739 ret = {
723 740 'msg': 'updated user ID:%s %s' % (
724 741 usr.user_id, self.TEST_USER_LOGIN),
725 742 'user': jsonify(User \
726 743 .get_by_username(self.TEST_USER_LOGIN) \
727 744 .get_api_data())
728 745 }
729 746
730 747 expected = ret
731 748 self._compare_ok(id_, expected, given=response.body)
732 749
733 750 def test_api_update_user_no_changed_params(self):
734 751 usr = User.get_by_username(TEST_USER_ADMIN_LOGIN)
735 752 ret = jsonify(usr.get_api_data())
736 753 id_, params = _build_data(self.apikey, 'update_user',
737 754 userid=TEST_USER_ADMIN_LOGIN)
738 755
739 756 response = api_call(self, params)
740 757 ret = {
741 758 'msg': 'updated user ID:%s %s' % (
742 759 usr.user_id, TEST_USER_ADMIN_LOGIN),
743 760 'user': ret
744 761 }
745 762 expected = ret
746 763 self._compare_ok(id_, expected, given=response.body)
747 764
748 765 def test_api_update_user_by_user_id(self):
749 766 usr = User.get_by_username(TEST_USER_ADMIN_LOGIN)
750 767 ret = jsonify(usr.get_api_data())
751 768 id_, params = _build_data(self.apikey, 'update_user',
752 769 userid=usr.user_id)
753 770
754 771 response = api_call(self, params)
755 772 ret = {
756 773 'msg': 'updated user ID:%s %s' % (
757 774 usr.user_id, TEST_USER_ADMIN_LOGIN),
758 775 'user': ret
759 776 }
760 777 expected = ret
761 778 self._compare_ok(id_, expected, given=response.body)
762 779
763 780 def test_api_update_user_default_user(self):
764 781 usr = User.get_default_user()
765 782 id_, params = _build_data(self.apikey, 'update_user',
766 783 userid=usr.user_id)
767 784
768 785 response = api_call(self, params)
769 786 expected = 'editing default user is forbidden'
770 787 self._compare_error(id_, expected, given=response.body)
771 788
772 789 @mock.patch.object(UserModel, 'update_user', crash)
773 790 def test_api_update_user_when_exception_happens(self):
774 791 usr = User.get_by_username(TEST_USER_ADMIN_LOGIN)
775 792 ret = jsonify(usr.get_api_data())
776 793 id_, params = _build_data(self.apikey, 'update_user',
777 794 userid=usr.user_id)
778 795
779 796 response = api_call(self, params)
780 797 ret = 'failed to update user `%s`' % usr.user_id
781 798
782 799 expected = ret
783 800 self._compare_error(id_, expected, given=response.body)
784 801
785 802 def test_api_get_repo(self):
786 803 new_group = u'some_new_group'
787 804 make_user_group(new_group)
788 805 RepoModel().grant_user_group_permission(repo=self.REPO,
789 806 group_name=new_group,
790 807 perm='repository.read')
791 808 Session().commit()
792 809 id_, params = _build_data(self.apikey, 'get_repo',
793 810 repoid=self.REPO)
794 811 response = api_call(self, params)
795 812 assert u"tags" not in response.json[u'result']
796 813 assert u'pull_requests' not in response.json[u'result']
797 814
798 815 repo = RepoModel().get_by_repo_name(self.REPO)
799 816 ret = repo.get_api_data()
800 817
801 818 members = []
802 819 followers = []
803 820 for user in repo.repo_to_perm:
804 821 perm = user.permission.permission_name
805 822 user = user.user
806 823 user_data = {'name': user.username, 'type': "user",
807 824 'permission': perm}
808 825 members.append(user_data)
809 826
810 827 for user_group in repo.users_group_to_perm:
811 828 perm = user_group.permission.permission_name
812 829 user_group = user_group.users_group
813 830 user_group_data = {'name': user_group.users_group_name,
814 831 'type': "user_group", 'permission': perm}
815 832 members.append(user_group_data)
816 833
817 834 for user in repo.followers:
818 835 followers.append(user.user.get_api_data())
819 836
820 837 ret['members'] = members
821 838 ret['followers'] = followers
822 839
823 840 expected = ret
824 841 self._compare_ok(id_, expected, given=response.body)
825 842 fixture.destroy_user_group(new_group)
826 843
827 844 id_, params = _build_data(self.apikey, 'get_repo', repoid=self.REPO,
828 845 with_revision_names=True,
829 846 with_pullrequests=True)
830 847 response = api_call(self, params)
831 848 assert u"v0.2.0" in response.json[u'result'][u'tags']
832 849 assert u'pull_requests' in response.json[u'result']
833 850
834 851 @parametrize('grant_perm', [
835 852 ('repository.admin'),
836 853 ('repository.write'),
837 854 ('repository.read'),
838 855 ])
839 856 def test_api_get_repo_by_non_admin(self, grant_perm):
840 857 RepoModel().grant_user_permission(repo=self.REPO,
841 858 user=self.TEST_USER_LOGIN,
842 859 perm=grant_perm)
843 860 Session().commit()
844 861 id_, params = _build_data(self.apikey_regular, 'get_repo',
845 862 repoid=self.REPO)
846 863 response = api_call(self, params)
847 864
848 865 repo = RepoModel().get_by_repo_name(self.REPO)
849 866 ret = repo.get_api_data()
850 867
851 868 members = []
852 869 followers = []
853 870 assert 2 == len(repo.repo_to_perm)
854 871 for user in repo.repo_to_perm:
855 872 perm = user.permission.permission_name
856 873 user_obj = user.user
857 874 user_data = {'name': user_obj.username, 'type': "user",
858 875 'permission': perm}
859 876 members.append(user_data)
860 877
861 878 for user_group in repo.users_group_to_perm:
862 879 perm = user_group.permission.permission_name
863 880 user_group_obj = user_group.users_group
864 881 user_group_data = {'name': user_group_obj.users_group_name,
865 882 'type': "user_group", 'permission': perm}
866 883 members.append(user_group_data)
867 884
868 885 for user in repo.followers:
869 886 followers.append(user.user.get_api_data())
870 887
871 888 ret['members'] = members
872 889 ret['followers'] = followers
873 890
874 891 expected = ret
875 892 try:
876 893 self._compare_ok(id_, expected, given=response.body)
877 894 finally:
878 895 RepoModel().revoke_user_permission(self.REPO, self.TEST_USER_LOGIN)
879 896
880 897 def test_api_get_repo_by_non_admin_no_permission_to_repo(self):
881 898 RepoModel().grant_user_permission(repo=self.REPO,
882 899 user=self.TEST_USER_LOGIN,
883 900 perm='repository.none')
884 901
885 902 id_, params = _build_data(self.apikey_regular, 'get_repo',
886 903 repoid=self.REPO)
887 904 response = api_call(self, params)
888 905
889 906 expected = 'repository `%s` does not exist' % (self.REPO)
890 907 self._compare_error(id_, expected, given=response.body)
891 908
892 909 def test_api_get_repo_that_doesn_not_exist(self):
893 910 id_, params = _build_data(self.apikey, 'get_repo',
894 911 repoid='no-such-repo')
895 912 response = api_call(self, params)
896 913
897 914 ret = 'repository `%s` does not exist' % 'no-such-repo'
898 915 expected = ret
899 916 self._compare_error(id_, expected, given=response.body)
900 917
901 918 def test_api_get_repos(self):
902 919 id_, params = _build_data(self.apikey, 'get_repos')
903 920 response = api_call(self, params)
904 921
905 922 expected = jsonify([
906 923 repo.get_api_data()
907 924 for repo in Repository.query()
908 925 ])
909 926
910 927 self._compare_ok(id_, expected, given=response.body)
911 928
912 929 def test_api_get_repos_non_admin(self):
913 930 id_, params = _build_data(self.apikey_regular, 'get_repos')
914 931 response = api_call(self, params)
915 932
916 933 expected = jsonify([
917 934 repo.get_api_data()
918 935 for repo in RepoModel().get_all_user_repos(self.TEST_USER_LOGIN)
919 936 ])
920 937
921 938 self._compare_ok(id_, expected, given=response.body)
922 939
923 940 @parametrize('name,ret_type', [
924 941 ('all', 'all'),
925 942 ('dirs', 'dirs'),
926 943 ('files', 'files'),
927 944 ])
928 945 def test_api_get_repo_nodes(self, name, ret_type):
929 946 rev = 'tip'
930 947 path = '/'
931 948 id_, params = _build_data(self.apikey, 'get_repo_nodes',
932 949 repoid=self.REPO, revision=rev,
933 950 root_path=path,
934 951 ret_type=ret_type)
935 952 response = api_call(self, params)
936 953
937 954 # we don't the actual return types here since it's tested somewhere
938 955 # else
939 956 expected = response.json['result']
940 957 self._compare_ok(id_, expected, given=response.body)
941 958
942 959 def test_api_get_repo_nodes_bad_revisions(self):
943 960 rev = 'i-dont-exist'
944 961 path = '/'
945 962 id_, params = _build_data(self.apikey, 'get_repo_nodes',
946 963 repoid=self.REPO, revision=rev,
947 964 root_path=path, )
948 965 response = api_call(self, params)
949 966
950 967 expected = 'failed to get repo: `%s` nodes' % self.REPO
951 968 self._compare_error(id_, expected, given=response.body)
952 969
953 970 def test_api_get_repo_nodes_bad_path(self):
954 971 rev = 'tip'
955 972 path = '/idontexits'
956 973 id_, params = _build_data(self.apikey, 'get_repo_nodes',
957 974 repoid=self.REPO, revision=rev,
958 975 root_path=path, )
959 976 response = api_call(self, params)
960 977
961 978 expected = 'failed to get repo: `%s` nodes' % self.REPO
962 979 self._compare_error(id_, expected, given=response.body)
963 980
964 981 def test_api_get_repo_nodes_bad_ret_type(self):
965 982 rev = 'tip'
966 983 path = '/'
967 984 ret_type = 'error'
968 985 id_, params = _build_data(self.apikey, 'get_repo_nodes',
969 986 repoid=self.REPO, revision=rev,
970 987 root_path=path,
971 988 ret_type=ret_type)
972 989 response = api_call(self, params)
973 990
974 991 expected = ('ret_type must be one of %s'
975 992 % (','.join(['files', 'dirs', 'all'])))
976 993 self._compare_error(id_, expected, given=response.body)
977 994
978 995 @parametrize('name,ret_type,grant_perm', [
979 996 ('all', 'all', 'repository.write'),
980 997 ('dirs', 'dirs', 'repository.admin'),
981 998 ('files', 'files', 'repository.read'),
982 999 ])
983 1000 def test_api_get_repo_nodes_by_regular_user(self, name, ret_type, grant_perm):
984 1001 RepoModel().grant_user_permission(repo=self.REPO,
985 1002 user=self.TEST_USER_LOGIN,
986 1003 perm=grant_perm)
987 1004 Session().commit()
988 1005
989 1006 rev = 'tip'
990 1007 path = '/'
991 1008 id_, params = _build_data(self.apikey_regular, 'get_repo_nodes',
992 1009 repoid=self.REPO, revision=rev,
993 1010 root_path=path,
994 1011 ret_type=ret_type)
995 1012 response = api_call(self, params)
996 1013
997 1014 # we don't the actual return types here since it's tested somewhere
998 1015 # else
999 1016 expected = response.json['result']
1000 1017 try:
1001 1018 self._compare_ok(id_, expected, given=response.body)
1002 1019 finally:
1003 1020 RepoModel().revoke_user_permission(self.REPO, self.TEST_USER_LOGIN)
1004 1021
1005 1022 def test_api_create_repo(self):
1006 1023 repo_name = u'api-repo'
1007 1024 id_, params = _build_data(self.apikey, 'create_repo',
1008 1025 repo_name=repo_name,
1009 1026 owner=TEST_USER_ADMIN_LOGIN,
1010 1027 repo_type=self.REPO_TYPE,
1011 1028 )
1012 1029 response = api_call(self, params)
1013 1030
1014 1031 repo = RepoModel().get_by_repo_name(repo_name)
1015 1032 assert repo is not None
1016 1033 ret = {
1017 1034 'msg': 'Created new repository `%s`' % repo_name,
1018 1035 'success': True,
1019 1036 'task': None,
1020 1037 }
1021 1038 expected = ret
1022 1039 self._compare_ok(id_, expected, given=response.body)
1023 1040 fixture.destroy_repo(repo_name)
1024 1041
1025 1042 def test_api_create_repo_and_repo_group(self):
1026 1043 repo_name = u'my_gr/api-repo'
1027 1044 id_, params = _build_data(self.apikey, 'create_repo',
1028 1045 repo_name=repo_name,
1029 1046 owner=TEST_USER_ADMIN_LOGIN,
1030 1047 repo_type=self.REPO_TYPE,)
1031 1048 response = api_call(self, params)
1032 1049 print params
1033 1050 repo = RepoModel().get_by_repo_name(repo_name)
1034 1051 assert repo is not None
1035 1052 ret = {
1036 1053 'msg': 'Created new repository `%s`' % repo_name,
1037 1054 'success': True,
1038 1055 'task': None,
1039 1056 }
1040 1057 expected = ret
1041 1058 self._compare_ok(id_, expected, given=response.body)
1042 1059 fixture.destroy_repo(repo_name)
1043 1060 fixture.destroy_repo_group(u'my_gr')
1044 1061
1045 1062 def test_api_create_repo_in_repo_group_without_permission(self):
1046 1063 repo_group_name = u'%s/api-repo-repo' % TEST_REPO_GROUP
1047 1064 repo_name = u'%s/api-repo' % repo_group_name
1048 1065
1049 1066 rg = fixture.create_repo_group(repo_group_name)
1050 1067 Session().commit()
1051 1068 RepoGroupModel().grant_user_permission(repo_group_name,
1052 1069 self.TEST_USER_LOGIN,
1053 1070 'group.none')
1054 1071 Session().commit()
1055 1072
1056 1073 id_, params = _build_data(self.apikey_regular, 'create_repo',
1057 1074 repo_name=repo_name,
1058 1075 repo_type=self.REPO_TYPE,
1059 1076 )
1060 1077 response = api_call(self, params)
1061 1078
1062 1079 # Current result when API access control is different from Web:
1063 1080 ret = {
1064 1081 'msg': 'Created new repository `%s`' % repo_name,
1065 1082 'success': True,
1066 1083 'task': None,
1067 1084 }
1068 1085 expected = ret
1069 1086 self._compare_ok(id_, expected, given=response.body)
1070 1087 fixture.destroy_repo(repo_name)
1071 1088
1072 1089 # Expected and arguably more correct result:
1073 1090 #expected = 'failed to create repository `%s`' % repo_name
1074 1091 #self._compare_error(id_, expected, given=response.body)
1075 1092
1076 1093 fixture.destroy_repo_group(repo_group_name)
1077 1094
1078 1095 def test_api_create_repo_unknown_owner(self):
1079 1096 repo_name = u'api-repo'
1080 1097 owner = 'i-dont-exist'
1081 1098 id_, params = _build_data(self.apikey, 'create_repo',
1082 1099 repo_name=repo_name,
1083 1100 owner=owner,
1084 1101 repo_type=self.REPO_TYPE,
1085 1102 )
1086 1103 response = api_call(self, params)
1087 1104 expected = 'user `%s` does not exist' % owner
1088 1105 self._compare_error(id_, expected, given=response.body)
1089 1106
1090 1107 def test_api_create_repo_dont_specify_owner(self):
1091 1108 repo_name = u'api-repo'
1092 1109 owner = 'i-dont-exist'
1093 1110 id_, params = _build_data(self.apikey, 'create_repo',
1094 1111 repo_name=repo_name,
1095 1112 repo_type=self.REPO_TYPE,
1096 1113 )
1097 1114 response = api_call(self, params)
1098 1115
1099 1116 repo = RepoModel().get_by_repo_name(repo_name)
1100 1117 assert repo is not None
1101 1118 ret = {
1102 1119 'msg': 'Created new repository `%s`' % repo_name,
1103 1120 'success': True,
1104 1121 'task': None,
1105 1122 }
1106 1123 expected = ret
1107 1124 self._compare_ok(id_, expected, given=response.body)
1108 1125 fixture.destroy_repo(repo_name)
1109 1126
1110 1127 def test_api_create_repo_by_non_admin(self):
1111 1128 repo_name = u'api-repo'
1112 1129 owner = 'i-dont-exist'
1113 1130 id_, params = _build_data(self.apikey_regular, 'create_repo',
1114 1131 repo_name=repo_name,
1115 1132 repo_type=self.REPO_TYPE,
1116 1133 )
1117 1134 response = api_call(self, params)
1118 1135
1119 1136 repo = RepoModel().get_by_repo_name(repo_name)
1120 1137 assert repo is not None
1121 1138 ret = {
1122 1139 'msg': 'Created new repository `%s`' % repo_name,
1123 1140 'success': True,
1124 1141 'task': None,
1125 1142 }
1126 1143 expected = ret
1127 1144 self._compare_ok(id_, expected, given=response.body)
1128 1145 fixture.destroy_repo(repo_name)
1129 1146
1130 1147 def test_api_create_repo_by_non_admin_specify_owner(self):
1131 1148 repo_name = u'api-repo'
1132 1149 owner = 'i-dont-exist'
1133 1150 id_, params = _build_data(self.apikey_regular, 'create_repo',
1134 1151 repo_name=repo_name,
1135 1152 repo_type=self.REPO_TYPE,
1136 1153 owner=owner)
1137 1154 response = api_call(self, params)
1138 1155
1139 1156 expected = 'Only Kallithea admin can specify `owner` param'
1140 1157 self._compare_error(id_, expected, given=response.body)
1141 1158 fixture.destroy_repo(repo_name)
1142 1159
1143 1160 def test_api_create_repo_exists(self):
1144 1161 repo_name = self.REPO
1145 1162 id_, params = _build_data(self.apikey, 'create_repo',
1146 1163 repo_name=repo_name,
1147 1164 owner=TEST_USER_ADMIN_LOGIN,
1148 1165 repo_type=self.REPO_TYPE,)
1149 1166 response = api_call(self, params)
1150 1167 expected = "repo `%s` already exist" % repo_name
1151 1168 self._compare_error(id_, expected, given=response.body)
1152 1169
1153 1170 @mock.patch.object(RepoModel, 'create', crash)
1154 1171 def test_api_create_repo_exception_occurred(self):
1155 1172 repo_name = u'api-repo'
1156 1173 id_, params = _build_data(self.apikey, 'create_repo',
1157 1174 repo_name=repo_name,
1158 1175 owner=TEST_USER_ADMIN_LOGIN,
1159 1176 repo_type=self.REPO_TYPE,)
1160 1177 response = api_call(self, params)
1161 1178 expected = 'failed to create repository `%s`' % repo_name
1162 1179 self._compare_error(id_, expected, given=response.body)
1163 1180
1164 1181 @parametrize('changing_attr,updates', [
1165 1182 ('owner', {'owner': TEST_USER_REGULAR_LOGIN}),
1166 1183 ('description', {'description': u'new description'}),
1167 1184 ('clone_uri', {'clone_uri': 'http://example.com/repo'}),
1168 1185 ('clone_uri', {'clone_uri': None}),
1169 1186 ('landing_rev', {'landing_rev': 'branch:master'}),
1170 1187 ('enable_statistics', {'enable_statistics': True}),
1171 1188 ('enable_locking', {'enable_locking': True}),
1172 1189 ('enable_downloads', {'enable_downloads': True}),
1173 1190 ('name', {'name': u'new_repo_name'}),
1174 1191 ('repo_group', {'group': u'test_group_for_update'}),
1175 1192 ])
1176 1193 def test_api_update_repo(self, changing_attr, updates):
1177 1194 repo_name = u'api_update_me'
1178 1195 repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1179 1196 if changing_attr == 'repo_group':
1180 1197 fixture.create_repo_group(updates['group'])
1181 1198
1182 1199 id_, params = _build_data(self.apikey, 'update_repo',
1183 1200 repoid=repo_name, **updates)
1184 1201 response = api_call(self, params)
1185 1202 if changing_attr == 'name':
1186 1203 repo_name = updates['name']
1187 1204 if changing_attr == 'repo_group':
1188 1205 repo_name = u'/'.join([updates['group'], repo_name])
1189 1206 try:
1190 1207 expected = {
1191 1208 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo_name),
1192 1209 'repository': repo.get_api_data()
1193 1210 }
1194 1211 self._compare_ok(id_, expected, given=response.body)
1195 1212 finally:
1196 1213 fixture.destroy_repo(repo_name)
1197 1214 if changing_attr == 'repo_group':
1198 1215 fixture.destroy_repo_group(updates['group'])
1199 1216
1200 1217 @parametrize('changing_attr,updates', [
1201 1218 ('owner', {'owner': TEST_USER_REGULAR_LOGIN}),
1202 1219 ('description', {'description': u'new description'}),
1203 1220 ('clone_uri', {'clone_uri': 'http://example.com/repo'}),
1204 1221 ('clone_uri', {'clone_uri': None}),
1205 1222 ('landing_rev', {'landing_rev': 'branch:master'}),
1206 1223 ('enable_statistics', {'enable_statistics': True}),
1207 1224 ('enable_locking', {'enable_locking': True}),
1208 1225 ('enable_downloads', {'enable_downloads': True}),
1209 1226 ('name', {'name': u'new_repo_name'}),
1210 1227 ('repo_group', {'group': u'test_group_for_update'}),
1211 1228 ])
1212 1229 def test_api_update_group_repo(self, changing_attr, updates):
1213 1230 group_name = u'lololo'
1214 1231 fixture.create_repo_group(group_name)
1215 1232 repo_name = u'%s/api_update_me' % group_name
1216 1233 repo = fixture.create_repo(repo_name, repo_group=group_name, repo_type=self.REPO_TYPE)
1217 1234 if changing_attr == 'repo_group':
1218 1235 fixture.create_repo_group(updates['group'])
1219 1236
1220 1237 id_, params = _build_data(self.apikey, 'update_repo',
1221 1238 repoid=repo_name, **updates)
1222 1239 response = api_call(self, params)
1223 1240 if changing_attr == 'name':
1224 1241 repo_name = u'%s/%s' % (group_name, updates['name'])
1225 1242 if changing_attr == 'repo_group':
1226 1243 repo_name = u'/'.join([updates['group'], repo_name.rsplit('/', 1)[-1]])
1227 1244 try:
1228 1245 expected = {
1229 1246 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo_name),
1230 1247 'repository': repo.get_api_data()
1231 1248 }
1232 1249 self._compare_ok(id_, expected, given=response.body)
1233 1250 finally:
1234 1251 fixture.destroy_repo(repo_name)
1235 1252 if changing_attr == 'repo_group':
1236 1253 fixture.destroy_repo_group(updates['group'])
1237 1254 fixture.destroy_repo_group(group_name)
1238 1255
1239 1256 def test_api_update_repo_repo_group_does_not_exist(self):
1240 1257 repo_name = u'admin_owned'
1241 1258 fixture.create_repo(repo_name)
1242 1259 updates = {'group': 'test_group_for_update'}
1243 1260 id_, params = _build_data(self.apikey, 'update_repo',
1244 1261 repoid=repo_name, **updates)
1245 1262 response = api_call(self, params)
1246 1263 try:
1247 1264 expected = 'repository group `%s` does not exist' % updates['group']
1248 1265 self._compare_error(id_, expected, given=response.body)
1249 1266 finally:
1250 1267 fixture.destroy_repo(repo_name)
1251 1268
1252 1269 def test_api_update_repo_regular_user_not_allowed(self):
1253 1270 repo_name = u'admin_owned'
1254 1271 fixture.create_repo(repo_name)
1255 1272 updates = {'description': 'something else'}
1256 1273 id_, params = _build_data(self.apikey_regular, 'update_repo',
1257 1274 repoid=repo_name, **updates)
1258 1275 response = api_call(self, params)
1259 1276 try:
1260 1277 expected = 'repository `%s` does not exist' % repo_name
1261 1278 self._compare_error(id_, expected, given=response.body)
1262 1279 finally:
1263 1280 fixture.destroy_repo(repo_name)
1264 1281
1265 1282 @mock.patch.object(RepoModel, 'update', crash)
1266 1283 def test_api_update_repo_exception_occurred(self):
1267 1284 repo_name = u'api_update_me'
1268 1285 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1269 1286 id_, params = _build_data(self.apikey, 'update_repo',
1270 1287 repoid=repo_name, owner=TEST_USER_ADMIN_LOGIN,)
1271 1288 response = api_call(self, params)
1272 1289 try:
1273 1290 expected = 'failed to update repo `%s`' % repo_name
1274 1291 self._compare_error(id_, expected, given=response.body)
1275 1292 finally:
1276 1293 fixture.destroy_repo(repo_name)
1277 1294
1278 1295 def test_api_update_repo_regular_user_change_repo_name(self):
1279 1296 repo_name = u'admin_owned'
1280 1297 new_repo_name = u'new_repo_name'
1281 1298 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1282 1299 RepoModel().grant_user_permission(repo=repo_name,
1283 1300 user=self.TEST_USER_LOGIN,
1284 1301 perm='repository.admin')
1285 1302 UserModel().revoke_perm('default', 'hg.create.repository')
1286 1303 UserModel().grant_perm('default', 'hg.create.none')
1287 1304 updates = {'name': new_repo_name}
1288 1305 id_, params = _build_data(self.apikey_regular, 'update_repo',
1289 1306 repoid=repo_name, **updates)
1290 1307 response = api_call(self, params)
1291 1308 try:
1292 1309 expected = 'no permission to create (or move) repositories'
1293 1310 self._compare_error(id_, expected, given=response.body)
1294 1311 finally:
1295 1312 fixture.destroy_repo(repo_name)
1296 1313 fixture.destroy_repo(new_repo_name)
1297 1314
1298 1315 def test_api_update_repo_regular_user_change_repo_name_allowed(self):
1299 1316 repo_name = u'admin_owned'
1300 1317 new_repo_name = u'new_repo_name'
1301 1318 repo = fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1302 1319 RepoModel().grant_user_permission(repo=repo_name,
1303 1320 user=self.TEST_USER_LOGIN,
1304 1321 perm='repository.admin')
1305 1322 UserModel().revoke_perm('default', 'hg.create.none')
1306 1323 UserModel().grant_perm('default', 'hg.create.repository')
1307 1324 updates = {'name': new_repo_name}
1308 1325 id_, params = _build_data(self.apikey_regular, 'update_repo',
1309 1326 repoid=repo_name, **updates)
1310 1327 response = api_call(self, params)
1311 1328 try:
1312 1329 expected = {
1313 1330 'msg': 'updated repo ID:%s %s' % (repo.repo_id, new_repo_name),
1314 1331 'repository': repo.get_api_data()
1315 1332 }
1316 1333 self._compare_ok(id_, expected, given=response.body)
1317 1334 finally:
1318 1335 fixture.destroy_repo(repo_name)
1319 1336 fixture.destroy_repo(new_repo_name)
1320 1337
1321 1338 def test_api_update_repo_regular_user_change_owner(self):
1322 1339 repo_name = u'admin_owned'
1323 1340 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1324 1341 RepoModel().grant_user_permission(repo=repo_name,
1325 1342 user=self.TEST_USER_LOGIN,
1326 1343 perm='repository.admin')
1327 1344 updates = {'owner': TEST_USER_ADMIN_LOGIN}
1328 1345 id_, params = _build_data(self.apikey_regular, 'update_repo',
1329 1346 repoid=repo_name, **updates)
1330 1347 response = api_call(self, params)
1331 1348 try:
1332 1349 expected = 'Only Kallithea admin can specify `owner` param'
1333 1350 self._compare_error(id_, expected, given=response.body)
1334 1351 finally:
1335 1352 fixture.destroy_repo(repo_name)
1336 1353
1337 1354 def test_api_delete_repo(self):
1338 1355 repo_name = u'api_delete_me'
1339 1356 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1340 1357
1341 1358 id_, params = _build_data(self.apikey, 'delete_repo',
1342 1359 repoid=repo_name, )
1343 1360 response = api_call(self, params)
1344 1361
1345 1362 ret = {
1346 1363 'msg': 'Deleted repository `%s`' % repo_name,
1347 1364 'success': True
1348 1365 }
1349 1366 try:
1350 1367 expected = ret
1351 1368 self._compare_ok(id_, expected, given=response.body)
1352 1369 finally:
1353 1370 fixture.destroy_repo(repo_name)
1354 1371
1355 1372 def test_api_delete_repo_by_non_admin(self):
1356 1373 repo_name = u'api_delete_me'
1357 1374 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE,
1358 1375 cur_user=self.TEST_USER_LOGIN)
1359 1376 id_, params = _build_data(self.apikey_regular, 'delete_repo',
1360 1377 repoid=repo_name, )
1361 1378 response = api_call(self, params)
1362 1379
1363 1380 ret = {
1364 1381 'msg': 'Deleted repository `%s`' % repo_name,
1365 1382 'success': True
1366 1383 }
1367 1384 try:
1368 1385 expected = ret
1369 1386 self._compare_ok(id_, expected, given=response.body)
1370 1387 finally:
1371 1388 fixture.destroy_repo(repo_name)
1372 1389
1373 1390 def test_api_delete_repo_by_non_admin_no_permission(self):
1374 1391 repo_name = u'api_delete_me'
1375 1392 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1376 1393 try:
1377 1394 id_, params = _build_data(self.apikey_regular, 'delete_repo',
1378 1395 repoid=repo_name, )
1379 1396 response = api_call(self, params)
1380 1397 expected = 'repository `%s` does not exist' % (repo_name)
1381 1398 self._compare_error(id_, expected, given=response.body)
1382 1399 finally:
1383 1400 fixture.destroy_repo(repo_name)
1384 1401
1385 1402 def test_api_delete_repo_exception_occurred(self):
1386 1403 repo_name = u'api_delete_me'
1387 1404 fixture.create_repo(repo_name, repo_type=self.REPO_TYPE)
1388 1405 try:
1389 1406 with mock.patch.object(RepoModel, 'delete', crash):
1390 1407 id_, params = _build_data(self.apikey, 'delete_repo',
1391 1408 repoid=repo_name, )
1392 1409 response = api_call(self, params)
1393 1410
1394 1411 expected = 'failed to delete repository `%s`' % repo_name
1395 1412 self._compare_error(id_, expected, given=response.body)
1396 1413 finally:
1397 1414 fixture.destroy_repo(repo_name)
1398 1415
1399 1416 def test_api_fork_repo(self):
1400 1417 fork_name = u'api-repo-fork'
1401 1418 id_, params = _build_data(self.apikey, 'fork_repo',
1402 1419 repoid=self.REPO,
1403 1420 fork_name=fork_name,
1404 1421 owner=TEST_USER_ADMIN_LOGIN,
1405 1422 )
1406 1423 response = api_call(self, params)
1407 1424
1408 1425 ret = {
1409 1426 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
1410 1427 fork_name),
1411 1428 'success': True,
1412 1429 'task': None,
1413 1430 }
1414 1431 expected = ret
1415 1432 self._compare_ok(id_, expected, given=response.body)
1416 1433 fixture.destroy_repo(fork_name)
1417 1434
1418 1435 @parametrize('fork_name', [
1419 1436 u'api-repo-fork',
1420 1437 u'%s/api-repo-fork' % TEST_REPO_GROUP,
1421 1438 ])
1422 1439 def test_api_fork_repo_non_admin(self, fork_name):
1423 1440 id_, params = _build_data(self.apikey_regular, 'fork_repo',
1424 1441 repoid=self.REPO,
1425 1442 fork_name=fork_name,
1426 1443 )
1427 1444 response = api_call(self, params)
1428 1445
1429 1446 ret = {
1430 1447 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
1431 1448 fork_name),
1432 1449 'success': True,
1433 1450 'task': None,
1434 1451 }
1435 1452 expected = ret
1436 1453 self._compare_ok(id_, expected, given=response.body)
1437 1454 fixture.destroy_repo(fork_name)
1438 1455
1439 1456 def test_api_fork_repo_non_admin_specify_owner(self):
1440 1457 fork_name = u'api-repo-fork'
1441 1458 id_, params = _build_data(self.apikey_regular, 'fork_repo',
1442 1459 repoid=self.REPO,
1443 1460 fork_name=fork_name,
1444 1461 owner=TEST_USER_ADMIN_LOGIN,
1445 1462 )
1446 1463 response = api_call(self, params)
1447 1464 expected = 'Only Kallithea admin can specify `owner` param'
1448 1465 self._compare_error(id_, expected, given=response.body)
1449 1466 fixture.destroy_repo(fork_name)
1450 1467
1451 1468 def test_api_fork_repo_non_admin_no_permission_to_fork(self):
1452 1469 RepoModel().grant_user_permission(repo=self.REPO,
1453 1470 user=self.TEST_USER_LOGIN,
1454 1471 perm='repository.none')
1455 1472 fork_name = u'api-repo-fork'
1456 1473 id_, params = _build_data(self.apikey_regular, 'fork_repo',
1457 1474 repoid=self.REPO,
1458 1475 fork_name=fork_name,
1459 1476 )
1460 1477 response = api_call(self, params)
1461 1478 expected = 'repository `%s` does not exist' % (self.REPO)
1462 1479 self._compare_error(id_, expected, given=response.body)
1463 1480 fixture.destroy_repo(fork_name)
1464 1481
1465 1482 @parametrize('name,perm', [
1466 1483 ('read', 'repository.read'),
1467 1484 ('write', 'repository.write'),
1468 1485 ('admin', 'repository.admin'),
1469 1486 ])
1470 1487 def test_api_fork_repo_non_admin_no_create_repo_permission(self, name, perm):
1471 1488 fork_name = u'api-repo-fork'
1472 1489 # regardless of base repository permission, forking is disallowed
1473 1490 # when repository creation is disabled
1474 1491 RepoModel().grant_user_permission(repo=self.REPO,
1475 1492 user=self.TEST_USER_LOGIN,
1476 1493 perm=perm)
1477 1494 UserModel().revoke_perm('default', 'hg.create.repository')
1478 1495 UserModel().grant_perm('default', 'hg.create.none')
1479 1496 id_, params = _build_data(self.apikey_regular, 'fork_repo',
1480 1497 repoid=self.REPO,
1481 1498 fork_name=fork_name,
1482 1499 )
1483 1500 response = api_call(self, params)
1484 1501 expected = 'no permission to create repositories'
1485 1502 self._compare_error(id_, expected, given=response.body)
1486 1503 fixture.destroy_repo(fork_name)
1487 1504
1488 1505 def test_api_fork_repo_unknown_owner(self):
1489 1506 fork_name = u'api-repo-fork'
1490 1507 owner = 'i-dont-exist'
1491 1508 id_, params = _build_data(self.apikey, 'fork_repo',
1492 1509 repoid=self.REPO,
1493 1510 fork_name=fork_name,
1494 1511 owner=owner,
1495 1512 )
1496 1513 response = api_call(self, params)
1497 1514 expected = 'user `%s` does not exist' % owner
1498 1515 self._compare_error(id_, expected, given=response.body)
1499 1516
1500 1517 def test_api_fork_repo_fork_exists(self):
1501 1518 fork_name = u'api-repo-fork'
1502 1519 fixture.create_fork(self.REPO, fork_name)
1503 1520
1504 1521 try:
1505 1522 fork_name = u'api-repo-fork'
1506 1523
1507 1524 id_, params = _build_data(self.apikey, 'fork_repo',
1508 1525 repoid=self.REPO,
1509 1526 fork_name=fork_name,
1510 1527 owner=TEST_USER_ADMIN_LOGIN,
1511 1528 )
1512 1529 response = api_call(self, params)
1513 1530
1514 1531 expected = "fork `%s` already exist" % fork_name
1515 1532 self._compare_error(id_, expected, given=response.body)
1516 1533 finally:
1517 1534 fixture.destroy_repo(fork_name)
1518 1535
1519 1536 def test_api_fork_repo_repo_exists(self):
1520 1537 fork_name = self.REPO
1521 1538
1522 1539 id_, params = _build_data(self.apikey, 'fork_repo',
1523 1540 repoid=self.REPO,
1524 1541 fork_name=fork_name,
1525 1542 owner=TEST_USER_ADMIN_LOGIN,
1526 1543 )
1527 1544 response = api_call(self, params)
1528 1545
1529 1546 expected = "repo `%s` already exist" % fork_name
1530 1547 self._compare_error(id_, expected, given=response.body)
1531 1548
1532 1549 @mock.patch.object(RepoModel, 'create_fork', crash)
1533 1550 def test_api_fork_repo_exception_occurred(self):
1534 1551 fork_name = u'api-repo-fork'
1535 1552 id_, params = _build_data(self.apikey, 'fork_repo',
1536 1553 repoid=self.REPO,
1537 1554 fork_name=fork_name,
1538 1555 owner=TEST_USER_ADMIN_LOGIN,
1539 1556 )
1540 1557 response = api_call(self, params)
1541 1558
1542 1559 expected = 'failed to fork repository `%s` as `%s`' % (self.REPO,
1543 1560 fork_name)
1544 1561 self._compare_error(id_, expected, given=response.body)
1545 1562
1546 1563 def test_api_get_user_group(self):
1547 1564 id_, params = _build_data(self.apikey, 'get_user_group',
1548 1565 usergroupid=TEST_USER_GROUP)
1549 1566 response = api_call(self, params)
1550 1567
1551 1568 user_group = UserGroupModel().get_group(TEST_USER_GROUP)
1552 1569 members = []
1553 1570 for user in user_group.members:
1554 1571 user = user.user
1555 1572 members.append(user.get_api_data())
1556 1573
1557 1574 ret = user_group.get_api_data()
1558 1575 ret['members'] = members
1559 1576 expected = ret
1560 1577 self._compare_ok(id_, expected, given=response.body)
1561 1578
1562 1579 def test_api_get_user_groups(self):
1563 1580 gr_name = u'test_user_group2'
1564 1581 make_user_group(gr_name)
1565 1582
1566 1583 try:
1567 1584 id_, params = _build_data(self.apikey, 'get_user_groups', )
1568 1585 response = api_call(self, params)
1569 1586
1570 1587 expected = []
1571 1588 for gr_name in [TEST_USER_GROUP, u'test_user_group2']:
1572 1589 user_group = UserGroupModel().get_group(gr_name)
1573 1590 ret = user_group.get_api_data()
1574 1591 expected.append(ret)
1575 1592 self._compare_ok(id_, expected, given=response.body)
1576 1593 finally:
1577 1594 fixture.destroy_user_group(gr_name)
1578 1595
1579 1596 def test_api_create_user_group(self):
1580 1597 group_name = u'some_new_group'
1581 1598 id_, params = _build_data(self.apikey, 'create_user_group',
1582 1599 group_name=group_name)
1583 1600 response = api_call(self, params)
1584 1601
1585 1602 ret = {
1586 1603 'msg': 'created new user group `%s`' % group_name,
1587 1604 'user_group': jsonify(UserGroupModel() \
1588 1605 .get_by_name(group_name) \
1589 1606 .get_api_data())
1590 1607 }
1591 1608 expected = ret
1592 1609 self._compare_ok(id_, expected, given=response.body)
1593 1610
1594 1611 fixture.destroy_user_group(group_name)
1595 1612
1596 1613 def test_api_get_user_group_that_exist(self):
1597 1614 id_, params = _build_data(self.apikey, 'create_user_group',
1598 1615 group_name=TEST_USER_GROUP)
1599 1616 response = api_call(self, params)
1600 1617
1601 1618 expected = "user group `%s` already exist" % TEST_USER_GROUP
1602 1619 self._compare_error(id_, expected, given=response.body)
1603 1620
1604 1621 @mock.patch.object(UserGroupModel, 'create', crash)
1605 1622 def test_api_get_user_group_exception_occurred(self):
1606 1623 group_name = u'exception_happens'
1607 1624 id_, params = _build_data(self.apikey, 'create_user_group',
1608 1625 group_name=group_name)
1609 1626 response = api_call(self, params)
1610 1627
1611 1628 expected = 'failed to create group `%s`' % group_name
1612 1629 self._compare_error(id_, expected, given=response.body)
1613 1630
1614 1631 @parametrize('changing_attr,updates', [
1615 1632 ('group_name', {'group_name': u'new_group_name'}),
1616 1633 ('group_name', {'group_name': u'test_group_for_update'}),
1617 1634 ('owner', {'owner': TEST_USER_REGULAR_LOGIN}),
1618 1635 ('active', {'active': False}),
1619 1636 ('active', {'active': True}),
1620 1637 ])
1621 1638 def test_api_update_user_group(self, changing_attr, updates):
1622 1639 gr_name = u'test_group_for_update'
1623 1640 user_group = fixture.create_user_group(gr_name)
1624 1641 try:
1625 1642 id_, params = _build_data(self.apikey, 'update_user_group',
1626 1643 usergroupid=gr_name, **updates)
1627 1644 response = api_call(self, params)
1628 1645 expected = {
1629 1646 'msg': 'updated user group ID:%s %s' % (user_group.users_group_id,
1630 1647 user_group.users_group_name),
1631 1648 'user_group': user_group.get_api_data()
1632 1649 }
1633 1650 self._compare_ok(id_, expected, given=response.body)
1634 1651 finally:
1635 1652 if changing_attr == 'group_name':
1636 1653 # switch to updated name for proper cleanup
1637 1654 gr_name = updates['group_name']
1638 1655 fixture.destroy_user_group(gr_name)
1639 1656
1640 1657 @mock.patch.object(UserGroupModel, 'update', crash)
1641 1658 def test_api_update_user_group_exception_occurred(self):
1642 1659 gr_name = u'test_group'
1643 1660 fixture.create_user_group(gr_name)
1644 1661 try:
1645 1662 id_, params = _build_data(self.apikey, 'update_user_group',
1646 1663 usergroupid=gr_name)
1647 1664 response = api_call(self, params)
1648 1665 expected = 'failed to update user group `%s`' % gr_name
1649 1666 self._compare_error(id_, expected, given=response.body)
1650 1667 finally:
1651 1668 fixture.destroy_user_group(gr_name)
1652 1669
1653 1670 def test_api_add_user_to_user_group(self):
1654 1671 gr_name = u'test_group'
1655 1672 fixture.create_user_group(gr_name)
1656 1673 try:
1657 1674 id_, params = _build_data(self.apikey, 'add_user_to_user_group',
1658 1675 usergroupid=gr_name,
1659 1676 userid=TEST_USER_ADMIN_LOGIN)
1660 1677 response = api_call(self, params)
1661 1678 expected = {
1662 1679 'msg': 'added member `%s` to user group `%s`' % (
1663 1680 TEST_USER_ADMIN_LOGIN, gr_name),
1664 1681 'success': True
1665 1682 }
1666 1683 self._compare_ok(id_, expected, given=response.body)
1667 1684 finally:
1668 1685 fixture.destroy_user_group(gr_name)
1669 1686
1670 1687 def test_api_add_user_to_user_group_that_doesnt_exist(self):
1671 1688 id_, params = _build_data(self.apikey, 'add_user_to_user_group',
1672 1689 usergroupid='false-group',
1673 1690 userid=TEST_USER_ADMIN_LOGIN)
1674 1691 response = api_call(self, params)
1675 1692
1676 1693 expected = 'user group `%s` does not exist' % 'false-group'
1677 1694 self._compare_error(id_, expected, given=response.body)
1678 1695
1679 1696 @mock.patch.object(UserGroupModel, 'add_user_to_group', crash)
1680 1697 def test_api_add_user_to_user_group_exception_occurred(self):
1681 1698 gr_name = u'test_group'
1682 1699 fixture.create_user_group(gr_name)
1683 1700 try:
1684 1701 id_, params = _build_data(self.apikey, 'add_user_to_user_group',
1685 1702 usergroupid=gr_name,
1686 1703 userid=TEST_USER_ADMIN_LOGIN)
1687 1704 response = api_call(self, params)
1688 1705 expected = 'failed to add member to user group `%s`' % gr_name
1689 1706 self._compare_error(id_, expected, given=response.body)
1690 1707 finally:
1691 1708 fixture.destroy_user_group(gr_name)
1692 1709
1693 1710 def test_api_remove_user_from_user_group(self):
1694 1711 gr_name = u'test_group_3'
1695 1712 gr = fixture.create_user_group(gr_name)
1696 1713 UserGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1697 1714 Session().commit()
1698 1715 try:
1699 1716 id_, params = _build_data(self.apikey, 'remove_user_from_user_group',
1700 1717 usergroupid=gr_name,
1701 1718 userid=TEST_USER_ADMIN_LOGIN)
1702 1719 response = api_call(self, params)
1703 1720 expected = {
1704 1721 'msg': 'removed member `%s` from user group `%s`' % (
1705 1722 TEST_USER_ADMIN_LOGIN, gr_name
1706 1723 ),
1707 1724 'success': True}
1708 1725 self._compare_ok(id_, expected, given=response.body)
1709 1726 finally:
1710 1727 fixture.destroy_user_group(gr_name)
1711 1728
1712 1729 @mock.patch.object(UserGroupModel, 'remove_user_from_group', crash)
1713 1730 def test_api_remove_user_from_user_group_exception_occurred(self):
1714 1731 gr_name = u'test_group_3'
1715 1732 gr = fixture.create_user_group(gr_name)
1716 1733 UserGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1717 1734 Session().commit()
1718 1735 try:
1719 1736 id_, params = _build_data(self.apikey, 'remove_user_from_user_group',
1720 1737 usergroupid=gr_name,
1721 1738 userid=TEST_USER_ADMIN_LOGIN)
1722 1739 response = api_call(self, params)
1723 1740 expected = 'failed to remove member from user group `%s`' % gr_name
1724 1741 self._compare_error(id_, expected, given=response.body)
1725 1742 finally:
1726 1743 fixture.destroy_user_group(gr_name)
1727 1744
1728 1745 def test_api_delete_user_group(self):
1729 1746 gr_name = u'test_group'
1730 1747 ugroup = fixture.create_user_group(gr_name)
1731 1748 gr_id = ugroup.users_group_id
1732 1749 try:
1733 1750 id_, params = _build_data(self.apikey, 'delete_user_group',
1734 1751 usergroupid=gr_name)
1735 1752 response = api_call(self, params)
1736 1753 expected = {
1737 1754 'user_group': None,
1738 1755 'msg': 'deleted user group ID:%s %s' % (gr_id, gr_name)
1739 1756 }
1740 1757 self._compare_ok(id_, expected, given=response.body)
1741 1758 finally:
1742 1759 if UserGroupModel().get_by_name(gr_name):
1743 1760 fixture.destroy_user_group(gr_name)
1744 1761
1745 1762 def test_api_delete_user_group_that_is_assigned(self):
1746 1763 gr_name = u'test_group'
1747 1764 ugroup = fixture.create_user_group(gr_name)
1748 1765 gr_id = ugroup.users_group_id
1749 1766
1750 1767 ugr_to_perm = RepoModel().grant_user_group_permission(self.REPO, gr_name, 'repository.write')
1751 1768 msg = 'User Group assigned to %s' % ugr_to_perm.repository.repo_name
1752 1769
1753 1770 try:
1754 1771 id_, params = _build_data(self.apikey, 'delete_user_group',
1755 1772 usergroupid=gr_name)
1756 1773 response = api_call(self, params)
1757 1774 expected = msg
1758 1775 self._compare_error(id_, expected, given=response.body)
1759 1776 finally:
1760 1777 if UserGroupModel().get_by_name(gr_name):
1761 1778 fixture.destroy_user_group(gr_name)
1762 1779
1763 1780 def test_api_delete_user_group_exception_occurred(self):
1764 1781 gr_name = u'test_group'
1765 1782 ugroup = fixture.create_user_group(gr_name)
1766 1783 gr_id = ugroup.users_group_id
1767 1784 id_, params = _build_data(self.apikey, 'delete_user_group',
1768 1785 usergroupid=gr_name)
1769 1786
1770 1787 try:
1771 1788 with mock.patch.object(UserGroupModel, 'delete', crash):
1772 1789 response = api_call(self, params)
1773 1790 expected = 'failed to delete user group ID:%s %s' % (gr_id, gr_name)
1774 1791 self._compare_error(id_, expected, given=response.body)
1775 1792 finally:
1776 1793 fixture.destroy_user_group(gr_name)
1777 1794
1778 1795 @parametrize('name,perm', [
1779 1796 ('none', 'repository.none'),
1780 1797 ('read', 'repository.read'),
1781 1798 ('write', 'repository.write'),
1782 1799 ('admin', 'repository.admin'),
1783 1800 ])
1784 1801 def test_api_grant_user_permission(self, name, perm):
1785 1802 id_, params = _build_data(self.apikey,
1786 1803 'grant_user_permission',
1787 1804 repoid=self.REPO,
1788 1805 userid=TEST_USER_ADMIN_LOGIN,
1789 1806 perm=perm)
1790 1807 response = api_call(self, params)
1791 1808
1792 1809 ret = {
1793 1810 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % (
1794 1811 perm, TEST_USER_ADMIN_LOGIN, self.REPO
1795 1812 ),
1796 1813 'success': True
1797 1814 }
1798 1815 expected = ret
1799 1816 self._compare_ok(id_, expected, given=response.body)
1800 1817
1801 1818 def test_api_grant_user_permission_wrong_permission(self):
1802 1819 perm = 'haha.no.permission'
1803 1820 id_, params = _build_data(self.apikey,
1804 1821 'grant_user_permission',
1805 1822 repoid=self.REPO,
1806 1823 userid=TEST_USER_ADMIN_LOGIN,
1807 1824 perm=perm)
1808 1825 response = api_call(self, params)
1809 1826
1810 1827 expected = 'permission `%s` does not exist' % perm
1811 1828 self._compare_error(id_, expected, given=response.body)
1812 1829
1813 1830 @mock.patch.object(RepoModel, 'grant_user_permission', crash)
1814 1831 def test_api_grant_user_permission_exception_when_adding(self):
1815 1832 perm = 'repository.read'
1816 1833 id_, params = _build_data(self.apikey,
1817 1834 'grant_user_permission',
1818 1835 repoid=self.REPO,
1819 1836 userid=TEST_USER_ADMIN_LOGIN,
1820 1837 perm=perm)
1821 1838 response = api_call(self, params)
1822 1839
1823 1840 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
1824 1841 TEST_USER_ADMIN_LOGIN, self.REPO
1825 1842 )
1826 1843 self._compare_error(id_, expected, given=response.body)
1827 1844
1828 1845 def test_api_revoke_user_permission(self):
1829 1846 id_, params = _build_data(self.apikey,
1830 1847 'revoke_user_permission',
1831 1848 repoid=self.REPO,
1832 1849 userid=TEST_USER_ADMIN_LOGIN, )
1833 1850 response = api_call(self, params)
1834 1851
1835 1852 expected = {
1836 1853 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
1837 1854 TEST_USER_ADMIN_LOGIN, self.REPO
1838 1855 ),
1839 1856 'success': True
1840 1857 }
1841 1858 self._compare_ok(id_, expected, given=response.body)
1842 1859
1843 1860 @mock.patch.object(RepoModel, 'revoke_user_permission', crash)
1844 1861 def test_api_revoke_user_permission_exception_when_adding(self):
1845 1862 id_, params = _build_data(self.apikey,
1846 1863 'revoke_user_permission',
1847 1864 repoid=self.REPO,
1848 1865 userid=TEST_USER_ADMIN_LOGIN, )
1849 1866 response = api_call(self, params)
1850 1867
1851 1868 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
1852 1869 TEST_USER_ADMIN_LOGIN, self.REPO
1853 1870 )
1854 1871 self._compare_error(id_, expected, given=response.body)
1855 1872
1856 1873 @parametrize('name,perm', [
1857 1874 ('none', 'repository.none'),
1858 1875 ('read', 'repository.read'),
1859 1876 ('write', 'repository.write'),
1860 1877 ('admin', 'repository.admin'),
1861 1878 ])
1862 1879 def test_api_grant_user_group_permission(self, name, perm):
1863 1880 id_, params = _build_data(self.apikey,
1864 1881 'grant_user_group_permission',
1865 1882 repoid=self.REPO,
1866 1883 usergroupid=TEST_USER_GROUP,
1867 1884 perm=perm)
1868 1885 response = api_call(self, params)
1869 1886
1870 1887 ret = {
1871 1888 'msg': 'Granted perm: `%s` for user group: `%s` in repo: `%s`' % (
1872 1889 perm, TEST_USER_GROUP, self.REPO
1873 1890 ),
1874 1891 'success': True
1875 1892 }
1876 1893 expected = ret
1877 1894 self._compare_ok(id_, expected, given=response.body)
1878 1895
1879 1896 def test_api_grant_user_group_permission_wrong_permission(self):
1880 1897 perm = 'haha.no.permission'
1881 1898 id_, params = _build_data(self.apikey,
1882 1899 'grant_user_group_permission',
1883 1900 repoid=self.REPO,
1884 1901 usergroupid=TEST_USER_GROUP,
1885 1902 perm=perm)
1886 1903 response = api_call(self, params)
1887 1904
1888 1905 expected = 'permission `%s` does not exist' % perm
1889 1906 self._compare_error(id_, expected, given=response.body)
1890 1907
1891 1908 @mock.patch.object(RepoModel, 'grant_user_group_permission', crash)
1892 1909 def test_api_grant_user_group_permission_exception_when_adding(self):
1893 1910 perm = 'repository.read'
1894 1911 id_, params = _build_data(self.apikey,
1895 1912 'grant_user_group_permission',
1896 1913 repoid=self.REPO,
1897 1914 usergroupid=TEST_USER_GROUP,
1898 1915 perm=perm)
1899 1916 response = api_call(self, params)
1900 1917
1901 1918 expected = 'failed to edit permission for user group: `%s` in repo: `%s`' % (
1902 1919 TEST_USER_GROUP, self.REPO
1903 1920 )
1904 1921 self._compare_error(id_, expected, given=response.body)
1905 1922
1906 1923 def test_api_revoke_user_group_permission(self):
1907 1924 RepoModel().grant_user_group_permission(repo=self.REPO,
1908 1925 group_name=TEST_USER_GROUP,
1909 1926 perm='repository.read')
1910 1927 Session().commit()
1911 1928 id_, params = _build_data(self.apikey,
1912 1929 'revoke_user_group_permission',
1913 1930 repoid=self.REPO,
1914 1931 usergroupid=TEST_USER_GROUP, )
1915 1932 response = api_call(self, params)
1916 1933
1917 1934 expected = {
1918 1935 'msg': 'Revoked perm for user group: `%s` in repo: `%s`' % (
1919 1936 TEST_USER_GROUP, self.REPO
1920 1937 ),
1921 1938 'success': True
1922 1939 }
1923 1940 self._compare_ok(id_, expected, given=response.body)
1924 1941
1925 1942 @mock.patch.object(RepoModel, 'revoke_user_group_permission', crash)
1926 1943 def test_api_revoke_user_group_permission_exception_when_adding(self):
1927 1944 id_, params = _build_data(self.apikey,
1928 1945 'revoke_user_group_permission',
1929 1946 repoid=self.REPO,
1930 1947 usergroupid=TEST_USER_GROUP, )
1931 1948 response = api_call(self, params)
1932 1949
1933 1950 expected = 'failed to edit permission for user group: `%s` in repo: `%s`' % (
1934 1951 TEST_USER_GROUP, self.REPO
1935 1952 )
1936 1953 self._compare_error(id_, expected, given=response.body)
1937 1954
1938 1955 @parametrize('name,perm,apply_to_children', [
1939 1956 ('none', 'group.none', 'none'),
1940 1957 ('read', 'group.read', 'none'),
1941 1958 ('write', 'group.write', 'none'),
1942 1959 ('admin', 'group.admin', 'none'),
1943 1960
1944 1961 ('none', 'group.none', 'all'),
1945 1962 ('read', 'group.read', 'all'),
1946 1963 ('write', 'group.write', 'all'),
1947 1964 ('admin', 'group.admin', 'all'),
1948 1965
1949 1966 ('none', 'group.none', 'repos'),
1950 1967 ('read', 'group.read', 'repos'),
1951 1968 ('write', 'group.write', 'repos'),
1952 1969 ('admin', 'group.admin', 'repos'),
1953 1970
1954 1971 ('none', 'group.none', 'groups'),
1955 1972 ('read', 'group.read', 'groups'),
1956 1973 ('write', 'group.write', 'groups'),
1957 1974 ('admin', 'group.admin', 'groups'),
1958 1975 ])
1959 1976 def test_api_grant_user_permission_to_repo_group(self, name, perm, apply_to_children):
1960 1977 id_, params = _build_data(self.apikey,
1961 1978 'grant_user_permission_to_repo_group',
1962 1979 repogroupid=TEST_REPO_GROUP,
1963 1980 userid=TEST_USER_ADMIN_LOGIN,
1964 1981 perm=perm, apply_to_children=apply_to_children)
1965 1982 response = api_call(self, params)
1966 1983
1967 1984 ret = {
1968 1985 'msg': 'Granted perm: `%s` (recursive:%s) for user: `%s` in repo group: `%s`' % (
1969 1986 perm, apply_to_children, TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
1970 1987 ),
1971 1988 'success': True
1972 1989 }
1973 1990 expected = ret
1974 1991 self._compare_ok(id_, expected, given=response.body)
1975 1992
1976 1993 @parametrize('name,perm,apply_to_children,grant_admin,access_ok', [
1977 1994 ('none_fails', 'group.none', 'none', False, False),
1978 1995 ('read_fails', 'group.read', 'none', False, False),
1979 1996 ('write_fails', 'group.write', 'none', False, False),
1980 1997 ('admin_fails', 'group.admin', 'none', False, False),
1981 1998
1982 1999 # with granted perms
1983 2000 ('none_ok', 'group.none', 'none', True, True),
1984 2001 ('read_ok', 'group.read', 'none', True, True),
1985 2002 ('write_ok', 'group.write', 'none', True, True),
1986 2003 ('admin_ok', 'group.admin', 'none', True, True),
1987 2004 ])
1988 2005 def test_api_grant_user_permission_to_repo_group_by_regular_user(
1989 2006 self, name, perm, apply_to_children, grant_admin, access_ok):
1990 2007 if grant_admin:
1991 2008 RepoGroupModel().grant_user_permission(TEST_REPO_GROUP,
1992 2009 self.TEST_USER_LOGIN,
1993 2010 'group.admin')
1994 2011 Session().commit()
1995 2012
1996 2013 id_, params = _build_data(self.apikey_regular,
1997 2014 'grant_user_permission_to_repo_group',
1998 2015 repogroupid=TEST_REPO_GROUP,
1999 2016 userid=TEST_USER_ADMIN_LOGIN,
2000 2017 perm=perm, apply_to_children=apply_to_children)
2001 2018 response = api_call(self, params)
2002 2019 if access_ok:
2003 2020 ret = {
2004 2021 'msg': 'Granted perm: `%s` (recursive:%s) for user: `%s` in repo group: `%s`' % (
2005 2022 perm, apply_to_children, TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
2006 2023 ),
2007 2024 'success': True
2008 2025 }
2009 2026 expected = ret
2010 2027 self._compare_ok(id_, expected, given=response.body)
2011 2028 else:
2012 2029 expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP
2013 2030 self._compare_error(id_, expected, given=response.body)
2014 2031
2015 2032 def test_api_grant_user_permission_to_repo_group_wrong_permission(self):
2016 2033 perm = 'haha.no.permission'
2017 2034 id_, params = _build_data(self.apikey,
2018 2035 'grant_user_permission_to_repo_group',
2019 2036 repogroupid=TEST_REPO_GROUP,
2020 2037 userid=TEST_USER_ADMIN_LOGIN,
2021 2038 perm=perm)
2022 2039 response = api_call(self, params)
2023 2040
2024 2041 expected = 'permission `%s` does not exist' % perm
2025 2042 self._compare_error(id_, expected, given=response.body)
2026 2043
2027 2044 @mock.patch.object(RepoGroupModel, 'grant_user_permission', crash)
2028 2045 def test_api_grant_user_permission_to_repo_group_exception_when_adding(self):
2029 2046 perm = 'group.read'
2030 2047 id_, params = _build_data(self.apikey,
2031 2048 'grant_user_permission_to_repo_group',
2032 2049 repogroupid=TEST_REPO_GROUP,
2033 2050 userid=TEST_USER_ADMIN_LOGIN,
2034 2051 perm=perm)
2035 2052 response = api_call(self, params)
2036 2053
2037 2054 expected = 'failed to edit permission for user: `%s` in repo group: `%s`' % (
2038 2055 TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
2039 2056 )
2040 2057 self._compare_error(id_, expected, given=response.body)
2041 2058
2042 2059 @parametrize('name,apply_to_children', [
2043 2060 ('none', 'none'),
2044 2061 ('all', 'all'),
2045 2062 ('repos', 'repos'),
2046 2063 ('groups', 'groups'),
2047 2064 ])
2048 2065 def test_api_revoke_user_permission_from_repo_group(self, name, apply_to_children):
2049 2066 RepoGroupModel().grant_user_permission(repo_group=TEST_REPO_GROUP,
2050 2067 user=TEST_USER_ADMIN_LOGIN,
2051 2068 perm='group.read',)
2052 2069 Session().commit()
2053 2070
2054 2071 id_, params = _build_data(self.apikey,
2055 2072 'revoke_user_permission_from_repo_group',
2056 2073 repogroupid=TEST_REPO_GROUP,
2057 2074 userid=TEST_USER_ADMIN_LOGIN,
2058 2075 apply_to_children=apply_to_children,)
2059 2076 response = api_call(self, params)
2060 2077
2061 2078 expected = {
2062 2079 'msg': 'Revoked perm (recursive:%s) for user: `%s` in repo group: `%s`' % (
2063 2080 apply_to_children, TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
2064 2081 ),
2065 2082 'success': True
2066 2083 }
2067 2084 self._compare_ok(id_, expected, given=response.body)
2068 2085
2069 2086 @parametrize('name,apply_to_children,grant_admin,access_ok', [
2070 2087 ('none', 'none', False, False),
2071 2088 ('all', 'all', False, False),
2072 2089 ('repos', 'repos', False, False),
2073 2090 ('groups', 'groups', False, False),
2074 2091
2075 2092 # after granting admin rights
2076 2093 ('none', 'none', False, False),
2077 2094 ('all', 'all', False, False),
2078 2095 ('repos', 'repos', False, False),
2079 2096 ('groups', 'groups', False, False),
2080 2097 ])
2081 2098 def test_api_revoke_user_permission_from_repo_group_by_regular_user(
2082 2099 self, name, apply_to_children, grant_admin, access_ok):
2083 2100 RepoGroupModel().grant_user_permission(repo_group=TEST_REPO_GROUP,
2084 2101 user=TEST_USER_ADMIN_LOGIN,
2085 2102 perm='group.read',)
2086 2103 Session().commit()
2087 2104
2088 2105 if grant_admin:
2089 2106 RepoGroupModel().grant_user_permission(TEST_REPO_GROUP,
2090 2107 self.TEST_USER_LOGIN,
2091 2108 'group.admin')
2092 2109 Session().commit()
2093 2110
2094 2111 id_, params = _build_data(self.apikey_regular,
2095 2112 'revoke_user_permission_from_repo_group',
2096 2113 repogroupid=TEST_REPO_GROUP,
2097 2114 userid=TEST_USER_ADMIN_LOGIN,
2098 2115 apply_to_children=apply_to_children,)
2099 2116 response = api_call(self, params)
2100 2117 if access_ok:
2101 2118 expected = {
2102 2119 'msg': 'Revoked perm (recursive:%s) for user: `%s` in repo group: `%s`' % (
2103 2120 apply_to_children, TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
2104 2121 ),
2105 2122 'success': True
2106 2123 }
2107 2124 self._compare_ok(id_, expected, given=response.body)
2108 2125 else:
2109 2126 expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP
2110 2127 self._compare_error(id_, expected, given=response.body)
2111 2128
2112 2129 @mock.patch.object(RepoGroupModel, 'revoke_user_permission', crash)
2113 2130 def test_api_revoke_user_permission_from_repo_group_exception_when_adding(self):
2114 2131 id_, params = _build_data(self.apikey,
2115 2132 'revoke_user_permission_from_repo_group',
2116 2133 repogroupid=TEST_REPO_GROUP,
2117 2134 userid=TEST_USER_ADMIN_LOGIN, )
2118 2135 response = api_call(self, params)
2119 2136
2120 2137 expected = 'failed to edit permission for user: `%s` in repo group: `%s`' % (
2121 2138 TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
2122 2139 )
2123 2140 self._compare_error(id_, expected, given=response.body)
2124 2141
2125 2142 @parametrize('name,perm,apply_to_children', [
2126 2143 ('none', 'group.none', 'none'),
2127 2144 ('read', 'group.read', 'none'),
2128 2145 ('write', 'group.write', 'none'),
2129 2146 ('admin', 'group.admin', 'none'),
2130 2147
2131 2148 ('none', 'group.none', 'all'),
2132 2149 ('read', 'group.read', 'all'),
2133 2150 ('write', 'group.write', 'all'),
2134 2151 ('admin', 'group.admin', 'all'),
2135 2152
2136 2153 ('none', 'group.none', 'repos'),
2137 2154 ('read', 'group.read', 'repos'),
2138 2155 ('write', 'group.write', 'repos'),
2139 2156 ('admin', 'group.admin', 'repos'),
2140 2157
2141 2158 ('none', 'group.none', 'groups'),
2142 2159 ('read', 'group.read', 'groups'),
2143 2160 ('write', 'group.write', 'groups'),
2144 2161 ('admin', 'group.admin', 'groups'),
2145 2162 ])
2146 2163 def test_api_grant_user_group_permission_to_repo_group(self, name, perm, apply_to_children):
2147 2164 id_, params = _build_data(self.apikey,
2148 2165 'grant_user_group_permission_to_repo_group',
2149 2166 repogroupid=TEST_REPO_GROUP,
2150 2167 usergroupid=TEST_USER_GROUP,
2151 2168 perm=perm,
2152 2169 apply_to_children=apply_to_children,)
2153 2170 response = api_call(self, params)
2154 2171
2155 2172 ret = {
2156 2173 'msg': 'Granted perm: `%s` (recursive:%s) for user group: `%s` in repo group: `%s`' % (
2157 2174 perm, apply_to_children, TEST_USER_GROUP, TEST_REPO_GROUP
2158 2175 ),
2159 2176 'success': True
2160 2177 }
2161 2178 expected = ret
2162 2179 self._compare_ok(id_, expected, given=response.body)
2163 2180
2164 2181 @parametrize('name,perm,apply_to_children,grant_admin,access_ok', [
2165 2182 ('none_fails', 'group.none', 'none', False, False),
2166 2183 ('read_fails', 'group.read', 'none', False, False),
2167 2184 ('write_fails', 'group.write', 'none', False, False),
2168 2185 ('admin_fails', 'group.admin', 'none', False, False),
2169 2186
2170 2187 # with granted perms
2171 2188 ('none_ok', 'group.none', 'none', True, True),
2172 2189 ('read_ok', 'group.read', 'none', True, True),
2173 2190 ('write_ok', 'group.write', 'none', True, True),
2174 2191 ('admin_ok', 'group.admin', 'none', True, True),
2175 2192 ])
2176 2193 def test_api_grant_user_group_permission_to_repo_group_by_regular_user(
2177 2194 self, name, perm, apply_to_children, grant_admin, access_ok):
2178 2195 if grant_admin:
2179 2196 RepoGroupModel().grant_user_permission(TEST_REPO_GROUP,
2180 2197 self.TEST_USER_LOGIN,
2181 2198 'group.admin')
2182 2199 Session().commit()
2183 2200
2184 2201 id_, params = _build_data(self.apikey_regular,
2185 2202 'grant_user_group_permission_to_repo_group',
2186 2203 repogroupid=TEST_REPO_GROUP,
2187 2204 usergroupid=TEST_USER_GROUP,
2188 2205 perm=perm,
2189 2206 apply_to_children=apply_to_children,)
2190 2207 response = api_call(self, params)
2191 2208 if access_ok:
2192 2209 ret = {
2193 2210 'msg': 'Granted perm: `%s` (recursive:%s) for user group: `%s` in repo group: `%s`' % (
2194 2211 perm, apply_to_children, TEST_USER_GROUP, TEST_REPO_GROUP
2195 2212 ),
2196 2213 'success': True
2197 2214 }
2198 2215 expected = ret
2199 2216 self._compare_ok(id_, expected, given=response.body)
2200 2217 else:
2201 2218 expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP
2202 2219 self._compare_error(id_, expected, given=response.body)
2203 2220
2204 2221 def test_api_grant_user_group_permission_to_repo_group_wrong_permission(self):
2205 2222 perm = 'haha.no.permission'
2206 2223 id_, params = _build_data(self.apikey,
2207 2224 'grant_user_group_permission_to_repo_group',
2208 2225 repogroupid=TEST_REPO_GROUP,
2209 2226 usergroupid=TEST_USER_GROUP,
2210 2227 perm=perm)
2211 2228 response = api_call(self, params)
2212 2229
2213 2230 expected = 'permission `%s` does not exist' % perm
2214 2231 self._compare_error(id_, expected, given=response.body)
2215 2232
2216 2233 @mock.patch.object(RepoGroupModel, 'grant_user_group_permission', crash)
2217 2234 def test_api_grant_user_group_permission_exception_when_adding_to_repo_group(self):
2218 2235 perm = 'group.read'
2219 2236 id_, params = _build_data(self.apikey,
2220 2237 'grant_user_group_permission_to_repo_group',
2221 2238 repogroupid=TEST_REPO_GROUP,
2222 2239 usergroupid=TEST_USER_GROUP,
2223 2240 perm=perm)
2224 2241 response = api_call(self, params)
2225 2242
2226 2243 expected = 'failed to edit permission for user group: `%s` in repo group: `%s`' % (
2227 2244 TEST_USER_GROUP, TEST_REPO_GROUP
2228 2245 )
2229 2246 self._compare_error(id_, expected, given=response.body)
2230 2247
2231 2248 @parametrize('name,apply_to_children', [
2232 2249 ('none', 'none'),
2233 2250 ('all', 'all'),
2234 2251 ('repos', 'repos'),
2235 2252 ('groups', 'groups'),
2236 2253 ])
2237 2254 def test_api_revoke_user_group_permission_from_repo_group(self, name, apply_to_children):
2238 2255 RepoGroupModel().grant_user_group_permission(repo_group=TEST_REPO_GROUP,
2239 2256 group_name=TEST_USER_GROUP,
2240 2257 perm='group.read',)
2241 2258 Session().commit()
2242 2259 id_, params = _build_data(self.apikey,
2243 2260 'revoke_user_group_permission_from_repo_group',
2244 2261 repogroupid=TEST_REPO_GROUP,
2245 2262 usergroupid=TEST_USER_GROUP,
2246 2263 apply_to_children=apply_to_children,)
2247 2264 response = api_call(self, params)
2248 2265
2249 2266 expected = {
2250 2267 'msg': 'Revoked perm (recursive:%s) for user group: `%s` in repo group: `%s`' % (
2251 2268 apply_to_children, TEST_USER_GROUP, TEST_REPO_GROUP
2252 2269 ),
2253 2270 'success': True
2254 2271 }
2255 2272 self._compare_ok(id_, expected, given=response.body)
2256 2273
2257 2274 @parametrize('name,apply_to_children,grant_admin,access_ok', [
2258 2275 ('none', 'none', False, False),
2259 2276 ('all', 'all', False, False),
2260 2277 ('repos', 'repos', False, False),
2261 2278 ('groups', 'groups', False, False),
2262 2279
2263 2280 # after granting admin rights
2264 2281 ('none', 'none', False, False),
2265 2282 ('all', 'all', False, False),
2266 2283 ('repos', 'repos', False, False),
2267 2284 ('groups', 'groups', False, False),
2268 2285 ])
2269 2286 def test_api_revoke_user_group_permission_from_repo_group_by_regular_user(
2270 2287 self, name, apply_to_children, grant_admin, access_ok):
2271 2288 RepoGroupModel().grant_user_permission(repo_group=TEST_REPO_GROUP,
2272 2289 user=TEST_USER_ADMIN_LOGIN,
2273 2290 perm='group.read',)
2274 2291 Session().commit()
2275 2292
2276 2293 if grant_admin:
2277 2294 RepoGroupModel().grant_user_permission(TEST_REPO_GROUP,
2278 2295 self.TEST_USER_LOGIN,
2279 2296 'group.admin')
2280 2297 Session().commit()
2281 2298
2282 2299 id_, params = _build_data(self.apikey_regular,
2283 2300 'revoke_user_group_permission_from_repo_group',
2284 2301 repogroupid=TEST_REPO_GROUP,
2285 2302 usergroupid=TEST_USER_GROUP,
2286 2303 apply_to_children=apply_to_children,)
2287 2304 response = api_call(self, params)
2288 2305 if access_ok:
2289 2306 expected = {
2290 2307 'msg': 'Revoked perm (recursive:%s) for user group: `%s` in repo group: `%s`' % (
2291 2308 apply_to_children, TEST_USER_ADMIN_LOGIN, TEST_REPO_GROUP
2292 2309 ),
2293 2310 'success': True
2294 2311 }
2295 2312 self._compare_ok(id_, expected, given=response.body)
2296 2313 else:
2297 2314 expected = 'repository group `%s` does not exist' % TEST_REPO_GROUP
2298 2315 self._compare_error(id_, expected, given=response.body)
2299 2316
2300 2317 @mock.patch.object(RepoGroupModel, 'revoke_user_group_permission', crash)
2301 2318 def test_api_revoke_user_group_permission_from_repo_group_exception_when_adding(self):
2302 2319 id_, params = _build_data(self.apikey, 'revoke_user_group_permission_from_repo_group',
2303 2320 repogroupid=TEST_REPO_GROUP,
2304 2321 usergroupid=TEST_USER_GROUP,)
2305 2322 response = api_call(self, params)
2306 2323
2307 2324 expected = 'failed to edit permission for user group: `%s` in repo group: `%s`' % (
2308 2325 TEST_USER_GROUP, TEST_REPO_GROUP
2309 2326 )
2310 2327 self._compare_error(id_, expected, given=response.body)
2311 2328
2312 2329 def test_api_get_gist(self):
2313 2330 gist = fixture.create_gist()
2314 2331 gist_id = gist.gist_access_id
2315 2332 gist_created_on = gist.created_on
2316 2333 id_, params = _build_data(self.apikey, 'get_gist',
2317 2334 gistid=gist_id, )
2318 2335 response = api_call(self, params)
2319 2336
2320 2337 expected = {
2321 2338 'access_id': gist_id,
2322 2339 'created_on': gist_created_on,
2323 2340 'description': 'new-gist',
2324 2341 'expires': -1.0,
2325 2342 'gist_id': int(gist_id),
2326 2343 'type': 'public',
2327 2344 'url': 'http://localhost:80/_admin/gists/%s' % gist_id
2328 2345 }
2329 2346
2330 2347 self._compare_ok(id_, expected, given=response.body)
2331 2348
2332 2349 def test_api_get_gist_that_does_not_exist(self):
2333 2350 id_, params = _build_data(self.apikey_regular, 'get_gist',
2334 2351 gistid='12345', )
2335 2352 response = api_call(self, params)
2336 2353 expected = 'gist `%s` does not exist' % ('12345',)
2337 2354 self._compare_error(id_, expected, given=response.body)
2338 2355
2339 2356 def test_api_get_gist_private_gist_without_permission(self):
2340 2357 gist = fixture.create_gist()
2341 2358 gist_id = gist.gist_access_id
2342 2359 gist_created_on = gist.created_on
2343 2360 id_, params = _build_data(self.apikey_regular, 'get_gist',
2344 2361 gistid=gist_id, )
2345 2362 response = api_call(self, params)
2346 2363
2347 2364 expected = 'gist `%s` does not exist' % gist_id
2348 2365 self._compare_error(id_, expected, given=response.body)
2349 2366
2350 2367 def test_api_get_gists(self):
2351 2368 fixture.create_gist()
2352 2369 fixture.create_gist()
2353 2370
2354 2371 id_, params = _build_data(self.apikey, 'get_gists')
2355 2372 response = api_call(self, params)
2356 2373 expected = response.json
2357 2374 assert len(response.json['result']) == 2
2358 2375 #self._compare_ok(id_, expected, given=response.body)
2359 2376
2360 2377 def test_api_get_gists_regular_user(self):
2361 2378 # by admin
2362 2379 fixture.create_gist()
2363 2380 fixture.create_gist()
2364 2381
2365 2382 # by reg user
2366 2383 fixture.create_gist(owner=self.TEST_USER_LOGIN)
2367 2384 fixture.create_gist(owner=self.TEST_USER_LOGIN)
2368 2385 fixture.create_gist(owner=self.TEST_USER_LOGIN)
2369 2386
2370 2387 id_, params = _build_data(self.apikey_regular, 'get_gists')
2371 2388 response = api_call(self, params)
2372 2389 expected = response.json
2373 2390 assert len(response.json['result']) == 3
2374 2391 #self._compare_ok(id_, expected, given=response.body)
2375 2392
2376 2393 def test_api_get_gists_only_for_regular_user(self):
2377 2394 # by admin
2378 2395 fixture.create_gist()
2379 2396 fixture.create_gist()
2380 2397
2381 2398 # by reg user
2382 2399 fixture.create_gist(owner=self.TEST_USER_LOGIN)
2383 2400 fixture.create_gist(owner=self.TEST_USER_LOGIN)
2384 2401 fixture.create_gist(owner=self.TEST_USER_LOGIN)
2385 2402
2386 2403 id_, params = _build_data(self.apikey, 'get_gists',
2387 2404 userid=self.TEST_USER_LOGIN)
2388 2405 response = api_call(self, params)
2389 2406 expected = response.json
2390 2407 assert len(response.json['result']) == 3
2391 2408 #self._compare_ok(id_, expected, given=response.body)
2392 2409
2393 2410 def test_api_get_gists_regular_user_with_different_userid(self):
2394 2411 id_, params = _build_data(self.apikey_regular, 'get_gists',
2395 2412 userid=TEST_USER_ADMIN_LOGIN)
2396 2413 response = api_call(self, params)
2397 2414 expected = 'userid is not the same as your user'
2398 2415 self._compare_error(id_, expected, given=response.body)
2399 2416
2400 2417 def test_api_create_gist(self):
2401 2418 id_, params = _build_data(self.apikey_regular, 'create_gist',
2402 2419 lifetime=10,
2403 2420 description='foobar-gist',
2404 2421 gist_type='public',
2405 2422 files={'foobar': {'content': 'foo'}})
2406 2423 response = api_call(self, params)
2407 2424 response_json = response.json
2408 2425 expected = {
2409 2426 'gist': {
2410 2427 'access_id': response_json['result']['gist']['access_id'],
2411 2428 'created_on': response_json['result']['gist']['created_on'],
2412 2429 'description': 'foobar-gist',
2413 2430 'expires': response_json['result']['gist']['expires'],
2414 2431 'gist_id': response_json['result']['gist']['gist_id'],
2415 2432 'type': 'public',
2416 2433 'url': response_json['result']['gist']['url']
2417 2434 },
2418 2435 'msg': 'created new gist'
2419 2436 }
2420 2437 self._compare_ok(id_, expected, given=response.body)
2421 2438
2422 2439 @mock.patch.object(GistModel, 'create', crash)
2423 2440 def test_api_create_gist_exception_occurred(self):
2424 2441 id_, params = _build_data(self.apikey_regular, 'create_gist',
2425 2442 files={})
2426 2443 response = api_call(self, params)
2427 2444 expected = 'failed to create gist'
2428 2445 self._compare_error(id_, expected, given=response.body)
2429 2446
2430 2447 def test_api_delete_gist(self):
2431 2448 gist_id = fixture.create_gist().gist_access_id
2432 2449 id_, params = _build_data(self.apikey, 'delete_gist',
2433 2450 gistid=gist_id)
2434 2451 response = api_call(self, params)
2435 2452 expected = {'gist': None, 'msg': 'deleted gist ID:%s' % gist_id}
2436 2453 self._compare_ok(id_, expected, given=response.body)
2437 2454
2438 2455 def test_api_delete_gist_regular_user(self):
2439 2456 gist_id = fixture.create_gist(owner=self.TEST_USER_LOGIN).gist_access_id
2440 2457 id_, params = _build_data(self.apikey_regular, 'delete_gist',
2441 2458 gistid=gist_id)
2442 2459 response = api_call(self, params)
2443 2460 expected = {'gist': None, 'msg': 'deleted gist ID:%s' % gist_id}
2444 2461 self._compare_ok(id_, expected, given=response.body)
2445 2462
2446 2463 def test_api_delete_gist_regular_user_no_permission(self):
2447 2464 gist_id = fixture.create_gist().gist_access_id
2448 2465 id_, params = _build_data(self.apikey_regular, 'delete_gist',
2449 2466 gistid=gist_id)
2450 2467 response = api_call(self, params)
2451 2468 expected = 'gist `%s` does not exist' % (gist_id,)
2452 2469 self._compare_error(id_, expected, given=response.body)
2453 2470
2454 2471 @mock.patch.object(GistModel, 'delete', crash)
2455 2472 def test_api_delete_gist_exception_occurred(self):
2456 2473 gist_id = fixture.create_gist().gist_access_id
2457 2474 id_, params = _build_data(self.apikey, 'delete_gist',
2458 2475 gistid=gist_id)
2459 2476 response = api_call(self, params)
2460 2477 expected = 'failed to delete gist ID:%s' % (gist_id,)
2461 2478 self._compare_error(id_, expected, given=response.body)
2462 2479
2463 2480 def test_api_get_ip(self):
2464 2481 id_, params = _build_data(self.apikey, 'get_ip')
2465 2482 response = api_call(self, params)
2466 2483 expected = {
2467 2484 'server_ip_addr': '0.0.0.0',
2468 2485 'user_ips': []
2469 2486 }
2470 2487 self._compare_ok(id_, expected, given=response.body)
2471 2488
2472 2489 def test_api_get_server_info(self):
2473 2490 id_, params = _build_data(self.apikey, 'get_server_info')
2474 2491 response = api_call(self, params)
2475 2492 expected = Setting.get_server_info()
2476 2493 self._compare_ok(id_, expected, given=response.body)
2477 2494
2478 2495 def test_api_get_changesets(self):
2479 2496 id_, params = _build_data(self.apikey, 'get_changesets',
2480 2497 repoid=self.REPO, start=0, end=2)
2481 2498 response = api_call(self, params)
2482 2499 result = json.loads(response.body)["result"]
2483 2500 assert len(result) == 3
2484 2501 assert 'message' in result[0]
2485 2502 assert 'added' not in result[0]
2486 2503
2487 2504 def test_api_get_changesets_with_file_list(self):
2488 2505 id_, params = _build_data(self.apikey, 'get_changesets',
2489 2506 repoid=self.REPO, start_date="2010-04-07T23:30:30", end_date="2010-04-08T00:31:14", with_file_list=True)
2490 2507 response = api_call(self, params)
2491 2508 result = json.loads(response.body)["result"]
2492 2509 assert len(result) == 3
2493 2510 assert 'message' in result[0]
2494 2511 assert 'added' in result[0]
2495 2512
2496 2513 def test_api_get_changeset(self):
2497 2514 review = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved")
2498 2515 id_, params = _build_data(self.apikey, 'get_changeset',
2499 2516 repoid=self.REPO, raw_id=self.TEST_REVISION)
2500 2517 response = api_call(self, params)
2501 2518 result = json.loads(response.body)["result"]
2502 2519 assert result["raw_id"] == self.TEST_REVISION
2503 2520 assert "reviews" not in result
2504 2521
2505 2522 def test_api_get_changeset_with_reviews(self):
2506 2523 reviewobjs = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved")
2507 2524 id_, params = _build_data(self.apikey, 'get_changeset',
2508 2525 repoid=self.REPO, raw_id=self.TEST_REVISION,
2509 2526 with_reviews=True)
2510 2527 response = api_call(self, params)
2511 2528 result = json.loads(response.body)["result"]
2512 2529 assert result["raw_id"] == self.TEST_REVISION
2513 2530 assert "reviews" in result
2514 2531 assert len(result["reviews"]) == 1
2515 2532 review = result["reviews"][0]
2516 2533 expected = {
2517 2534 'status': 'approved',
2518 2535 'modified_at': reviewobjs[0].modified_at.replace(microsecond=0).isoformat(),
2519 2536 'reviewer': 'test_admin',
2520 2537 }
2521 2538 assert review == expected
2522 2539
2523 2540 def test_api_get_changeset_that_does_not_exist(self):
2524 2541 """ Fetch changeset status for non-existant changeset.
2525 2542 revision id is the above git hash used in the test above with the
2526 2543 last 3 nibbles replaced with 0xf. Should not exist for git _or_ hg.
2527 2544 """
2528 2545 id_, params = _build_data(self.apikey, 'get_changeset',
2529 2546 repoid=self.REPO, raw_id = '7ab37bc680b4aa72c34d07b230c866c28e9fcfff')
2530 2547 response = api_call(self, params)
2531 2548 expected = u'Changeset %s does not exist' % ('7ab37bc680b4aa72c34d07b230c866c28e9fcfff',)
2532 2549 self._compare_error(id_, expected, given=response.body)
2533 2550
2534 2551 def test_api_get_changeset_without_permission(self):
2535 2552 review = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved")
2536 2553 RepoModel().revoke_user_permission(repo=self.REPO, user=self.TEST_USER_LOGIN)
2537 2554 RepoModel().revoke_user_permission(repo=self.REPO, user="default")
2538 2555 id_, params = _build_data(self.apikey_regular, 'get_changeset',
2539 2556 repoid=self.REPO, raw_id=self.TEST_REVISION)
2540 2557 response = api_call(self, params)
2541 2558 expected = u'Access denied to repo %s' % self.REPO
2542 2559 self._compare_error(id_, expected, given=response.body)
2543 2560
2544 2561 def test_api_get_pullrequest(self):
2545 2562 pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u'get test')
2546 2563 random_id = random.randrange(1, 9999)
2547 2564 params = json.dumps({
2548 2565 "id": random_id,
2549 2566 "api_key": self.apikey,
2550 2567 "method": 'get_pullrequest',
2551 2568 "args": {"pullrequest_id": pull_request_id},
2552 2569 })
2553 2570 response = api_call(self, params)
2554 2571 pullrequest = PullRequest().get(pull_request_id)
2555 2572 expected = {
2556 2573 "status": "new",
2557 2574 "pull_request_id": pull_request_id,
2558 2575 "description": "No description",
2559 2576 "url": "/%s/pull-request/%s/_/%s" % (self.REPO, pull_request_id, "stable"),
2560 2577 "reviewers": [{"username": "test_regular"}],
2561 2578 "org_repo_url": "http://localhost:80/%s" % self.REPO,
2562 2579 "org_ref_parts": ["branch", "stable", self.TEST_PR_SRC],
2563 2580 "other_ref_parts": ["branch", "default", self.TEST_PR_DST],
2564 2581 "comments": [{"username": TEST_USER_ADMIN_LOGIN, "text": "",
2565 2582 "comment_id": pullrequest.comments[0].comment_id}],
2566 2583 "owner": TEST_USER_ADMIN_LOGIN,
2567 2584 "statuses": [{"status": "under_review", "reviewer": TEST_USER_ADMIN_LOGIN, "modified_at": "2000-01-01T00:00:00"} for i in range(0, len(self.TEST_PR_REVISIONS))],
2568 2585 "title": "get test",
2569 2586 "revisions": self.TEST_PR_REVISIONS,
2570 2587 }
2571 2588 self._compare_ok(random_id, expected,
2572 2589 given=re.sub("\d\d\d\d\-\d\d\-\d\dT\d\d\:\d\d\:\d\d",
2573 2590 "2000-01-01T00:00:00", response.body))
2574 2591
2575 2592 def test_api_close_pullrequest(self):
2576 2593 pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u'close test')
2577 2594 random_id = random.randrange(1, 9999)
2578 2595 params = json.dumps({
2579 2596 "id": random_id,
2580 2597 "api_key": self.apikey,
2581 2598 "method": "comment_pullrequest",
2582 2599 "args": {"pull_request_id": pull_request_id, "close_pr": True},
2583 2600 })
2584 2601 response = api_call(self, params)
2585 2602 self._compare_ok(random_id, True, given=response.body)
2586 2603 pullrequest = PullRequest().get(pull_request_id)
2587 2604 assert pullrequest.comments[-1].text == ''
2588 2605 assert pullrequest.status == PullRequest.STATUS_CLOSED
2589 2606 assert pullrequest.is_closed() == True
2590 2607
2591 2608 def test_api_status_pullrequest(self):
2592 2609 pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u"status test")
2593 2610
2594 2611 random_id = random.randrange(1, 9999)
2595 2612 params = json.dumps({
2596 2613 "id": random_id,
2597 2614 "api_key": User.get_by_username(TEST_USER_REGULAR2_LOGIN).api_key,
2598 2615 "method": "comment_pullrequest",
2599 2616 "args": {"pull_request_id": pull_request_id, "status": ChangesetStatus.STATUS_APPROVED},
2600 2617 })
2601 2618 response = api_call(self, params)
2602 2619 pullrequest = PullRequest().get(pull_request_id)
2603 2620 self._compare_error(random_id, "No permission to change pull request status. User needs to be admin, owner or reviewer.", given=response.body)
2604 2621 assert ChangesetStatus.STATUS_UNDER_REVIEW == ChangesetStatusModel().calculate_pull_request_result(pullrequest)[2]
2605 2622 params = json.dumps({
2606 2623 "id": random_id,
2607 2624 "api_key": User.get_by_username(TEST_USER_REGULAR_LOGIN).api_key,
2608 2625 "method": "comment_pullrequest",
2609 2626 "args": {"pull_request_id": pull_request_id, "status": ChangesetStatus.STATUS_APPROVED},
2610 2627 })
2611 2628 response = api_call(self, params)
2612 2629 self._compare_ok(random_id, True, given=response.body)
2613 2630 pullrequest = PullRequest().get(pull_request_id)
2614 2631 assert ChangesetStatus.STATUS_APPROVED == ChangesetStatusModel().calculate_pull_request_result(pullrequest)[2]
2615 2632
2616 2633 def test_api_comment_pullrequest(self):
2617 2634 pull_request_id = fixture.create_pullrequest(self, self.REPO, self.TEST_PR_SRC, self.TEST_PR_DST, u"comment test")
2618 2635 random_id = random.randrange(1, 9999)
2619 2636 params = json.dumps({
2620 2637 "id": random_id,
2621 2638 "api_key": self.apikey,
2622 2639 "method": "comment_pullrequest",
2623 2640 "args": {"pull_request_id": pull_request_id, "comment_msg": "Looks good to me"},
2624 2641 })
2625 2642 response = api_call(self, params)
2626 2643 self._compare_ok(random_id, True, given=response.body)
2627 2644 pullrequest = PullRequest().get(pull_request_id)
2628 2645 assert pullrequest.comments[-1].text == u'Looks good to me'
General Comments 0
You need to be logged in to leave comments. Login now