##// END OF EJS Templates
Updated boolean checks in API permissions calls
marcink -
r3898:c9f5a397 beta
parent child Browse files
Show More
@@ -1,1109 +1,1110 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.api
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 API controller for RhodeCode
7 7
8 8 :created_on: Aug 20, 2011
9 9 :author: marcink
10 10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software; you can redistribute it and/or
14 14 # modify it under the terms of the GNU General Public License
15 15 # as published by the Free Software Foundation; version 2
16 16 # of the License or (at your opinion) any later version of the license.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program; if not, write to the Free Software
25 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 26 # MA 02110-1301, USA.
27 27
28 28 import time
29 29 import traceback
30 30 import logging
31 31
32 32 from rhodecode.controllers.api import JSONRPCController, JSONRPCError
33 33 from rhodecode.lib.auth import PasswordGenerator, AuthUser, \
34 34 HasPermissionAllDecorator, HasPermissionAnyDecorator, \
35 35 HasPermissionAnyApi, HasRepoPermissionAnyApi
36 36 from rhodecode.lib.utils import map_groups, repo2db_mapper
37 37 from rhodecode.lib.utils2 import str2bool, time_to_datetime, safe_int
38 38 from rhodecode.lib import helpers as h
39 39 from rhodecode.model.meta import Session
40 40 from rhodecode.model.scm import ScmModel
41 41 from rhodecode.model.repo import RepoModel
42 42 from rhodecode.model.user import UserModel
43 43 from rhodecode.model.users_group import UserGroupModel
44 44 from rhodecode.model.db import Repository, RhodeCodeSetting, UserIpMap,\
45 45 Permission, User, Gist
46 46 from rhodecode.lib.compat import json
47 47 from rhodecode.lib.exceptions import DefaultUserException
48 48 from rhodecode.model.gist import GistModel
49 49
50 50 log = logging.getLogger(__name__)
51 51
52 52
53 53 class OptionalAttr(object):
54 54 """
55 55 Special Optional Option that defines other attribute
56 56 """
57 57 def __init__(self, attr_name):
58 58 self.attr_name = attr_name
59 59
60 60 def __repr__(self):
61 61 return '<OptionalAttr:%s>' % self.attr_name
62 62
63 63 def __call__(self):
64 64 return self
65 65 #alias
66 66 OAttr = OptionalAttr
67 67
68 68
69 69 class Optional(object):
70 70 """
71 71 Defines an optional parameter::
72 72
73 73 param = param.getval() if isinstance(param, Optional) else param
74 74 param = param() if isinstance(param, Optional) else param
75 75
76 76 is equivalent of::
77 77
78 78 param = Optional.extract(param)
79 79
80 80 """
81 81 def __init__(self, type_):
82 82 self.type_ = type_
83 83
84 84 def __repr__(self):
85 85 return '<Optional:%s>' % self.type_.__repr__()
86 86
87 87 def __call__(self):
88 88 return self.getval()
89 89
90 90 def getval(self):
91 91 """
92 92 returns value from this Optional instance
93 93 """
94 94 return self.type_
95 95
96 96 @classmethod
97 97 def extract(cls, val):
98 98 if isinstance(val, cls):
99 99 return val.getval()
100 100 return val
101 101
102 102
103 103 def get_user_or_error(userid):
104 104 """
105 105 Get user by id or name or return JsonRPCError if not found
106 106
107 107 :param userid:
108 108 """
109 109 user = UserModel().get_user(userid)
110 110 if user is None:
111 111 raise JSONRPCError("user `%s` does not exist" % userid)
112 112 return user
113 113
114 114
115 115 def get_repo_or_error(repoid):
116 116 """
117 117 Get repo by id or name or return JsonRPCError if not found
118 118
119 :param userid:
119 :param repoid:
120 120 """
121 121 repo = RepoModel().get_repo(repoid)
122 122 if repo is None:
123 123 raise JSONRPCError('repository `%s` does not exist' % (repoid))
124 124 return repo
125 125
126 126
127 127 def get_users_group_or_error(usersgroupid):
128 128 """
129 129 Get user group by id or name or return JsonRPCError if not found
130 130
131 131 :param userid:
132 132 """
133 133 users_group = UserGroupModel().get_group(usersgroupid)
134 134 if users_group is None:
135 135 raise JSONRPCError('user group `%s` does not exist' % usersgroupid)
136 136 return users_group
137 137
138 138
139 139 def get_perm_or_error(permid):
140 140 """
141 141 Get permission by id or name or return JsonRPCError if not found
142 142
143 143 :param userid:
144 144 """
145 145 perm = Permission.get_by_key(permid)
146 146 if perm is None:
147 147 raise JSONRPCError('permission `%s` does not exist' % (permid))
148 148 return perm
149 149
150 150
151 151 class ApiController(JSONRPCController):
152 152 """
153 153 API Controller
154 154
155 155
156 156 Each method needs to have USER as argument this is then based on given
157 157 API_KEY propagated as instance of user object
158 158
159 159 Preferably this should be first argument also
160 160
161 161
162 162 Each function should also **raise** JSONRPCError for any
163 163 errors that happens
164 164
165 165 """
166 166
167 167 @HasPermissionAllDecorator('hg.admin')
168 168 def pull(self, apiuser, repoid):
169 169 """
170 170 Dispatch pull action on given repo
171 171
172 172 :param apiuser:
173 173 :param repoid:
174 174 """
175 175
176 176 repo = get_repo_or_error(repoid)
177 177
178 178 try:
179 179 ScmModel().pull_changes(repo.repo_name,
180 180 self.rhodecode_user.username)
181 181 return 'Pulled from `%s`' % repo.repo_name
182 182 except Exception:
183 183 log.error(traceback.format_exc())
184 184 raise JSONRPCError(
185 185 'Unable to pull changes from `%s`' % repo.repo_name
186 186 )
187 187
188 188 @HasPermissionAllDecorator('hg.admin')
189 189 def rescan_repos(self, apiuser, remove_obsolete=Optional(False)):
190 190 """
191 191 Dispatch rescan repositories action. If remove_obsolete is set
192 192 than also delete repos that are in database but not in the filesystem.
193 193 aka "clean zombies"
194 194
195 195 :param apiuser:
196 196 :param remove_obsolete:
197 197 """
198 198
199 199 try:
200 200 rm_obsolete = Optional.extract(remove_obsolete)
201 201 added, removed = repo2db_mapper(ScmModel().repo_scan(),
202 202 remove_obsolete=rm_obsolete)
203 203 return {'added': added, 'removed': removed}
204 204 except Exception:
205 205 log.error(traceback.format_exc())
206 206 raise JSONRPCError(
207 207 'Error occurred during rescan repositories action'
208 208 )
209 209
210 210 def invalidate_cache(self, apiuser, repoid):
211 211 """
212 212 Dispatch cache invalidation action on given repo
213 213
214 214 :param apiuser:
215 215 :param repoid:
216 216 """
217 217 repo = get_repo_or_error(repoid)
218 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
218 if not HasPermissionAnyApi('hg.admin')(user=apiuser):
219 219 # check if we have admin permission for this repo !
220 220 if HasRepoPermissionAnyApi('repository.admin',
221 221 'repository.write')(user=apiuser,
222 222 repo_name=repo.repo_name) is False:
223 223 raise JSONRPCError('repository `%s` does not exist' % (repoid))
224 224
225 225 try:
226 226 ScmModel().mark_for_invalidation(repo.repo_name)
227 227 return ('Caches of repository `%s` was invalidated' % repoid)
228 228 except Exception:
229 229 log.error(traceback.format_exc())
230 230 raise JSONRPCError(
231 231 'Error occurred during cache invalidation action'
232 232 )
233 233
234 # permission check inside
234 235 def lock(self, apiuser, repoid, locked=Optional(None),
235 236 userid=Optional(OAttr('apiuser'))):
236 237 """
237 238 Set locking state on particular repository by given user, if
238 239 this command is runned by non-admin account userid is set to user
239 240 who is calling this method
240 241
241 242 :param apiuser:
242 243 :param repoid:
243 244 :param userid:
244 245 :param locked:
245 246 """
246 247 repo = get_repo_or_error(repoid)
247 248 if HasPermissionAnyApi('hg.admin')(user=apiuser):
248 249 pass
249 250 elif HasRepoPermissionAnyApi('repository.admin',
250 251 'repository.write')(user=apiuser,
251 252 repo_name=repo.repo_name):
252 253 #make sure normal user does not pass someone else userid,
253 254 #he is not allowed to do that
254 255 if not isinstance(userid, Optional) and userid != apiuser.user_id:
255 256 raise JSONRPCError(
256 257 'userid is not the same as your user'
257 258 )
258 259 else:
259 260 raise JSONRPCError('repository `%s` does not exist' % (repoid))
260 261
261 262 if isinstance(userid, Optional):
262 263 userid = apiuser.user_id
263 264
264 265 user = get_user_or_error(userid)
265 266
266 267 if isinstance(locked, Optional):
267 268 lockobj = Repository.getlock(repo)
268 269
269 270 if lockobj[0] is None:
270 271 _d = {
271 272 'repo': repo.repo_name,
272 273 'locked': False,
273 274 'locked_since': None,
274 275 'locked_by': None,
275 276 'msg': 'Repo `%s` not locked.' % repo.repo_name
276 277 }
277 278 return _d
278 279 else:
279 280 userid, time_ = lockobj
280 281 lock_user = get_user_or_error(userid)
281 282 _d = {
282 283 'repo': repo.repo_name,
283 284 'locked': True,
284 285 'locked_since': time_,
285 286 'locked_by': lock_user.username,
286 287 'msg': ('Repo `%s` locked by `%s`. '
287 288 % (repo.repo_name,
288 289 json.dumps(time_to_datetime(time_))))
289 290 }
290 291 return _d
291 292
292 293 # force locked state through a flag
293 294 else:
294 295 locked = str2bool(locked)
295 296 try:
296 297 if locked:
297 298 lock_time = time.time()
298 299 Repository.lock(repo, user.user_id, lock_time)
299 300 else:
300 301 lock_time = None
301 302 Repository.unlock(repo)
302 303 _d = {
303 304 'repo': repo.repo_name,
304 305 'locked': locked,
305 306 'locked_since': lock_time,
306 307 'locked_by': user.username,
307 308 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
308 309 % (user.username, repo.repo_name, locked))
309 310 }
310 311 return _d
311 312 except Exception:
312 313 log.error(traceback.format_exc())
313 314 raise JSONRPCError(
314 315 'Error occurred locking repository `%s`' % repo.repo_name
315 316 )
316 317
317 318 def get_locks(self, apiuser, userid=Optional(OAttr('apiuser'))):
318 319 """
319 320 Get all locks for given userid, if
320 321 this command is runned by non-admin account userid is set to user
321 322 who is calling this method, thus returning locks for himself
322 323
323 324 :param apiuser:
324 325 :param userid:
325 326 """
326 if HasPermissionAnyApi('hg.admin')(user=apiuser):
327 pass
328 else:
327
328 if not HasPermissionAnyApi('hg.admin')(user=apiuser):
329 329 #make sure normal user does not pass someone else userid,
330 330 #he is not allowed to do that
331 331 if not isinstance(userid, Optional) and userid != apiuser.user_id:
332 332 raise JSONRPCError(
333 333 'userid is not the same as your user'
334 334 )
335 335 ret = []
336 336 if isinstance(userid, Optional):
337 337 user = None
338 338 else:
339 339 user = get_user_or_error(userid)
340 340
341 341 #show all locks
342 342 for r in Repository.getAll():
343 343 userid, time_ = r.locked
344 344 if time_:
345 345 _api_data = r.get_api_data()
346 346 # if we use userfilter just show the locks for this user
347 347 if user:
348 348 if safe_int(userid) == user.user_id:
349 349 ret.append(_api_data)
350 350 else:
351 351 ret.append(_api_data)
352 352
353 353 return ret
354 354
355 355 @HasPermissionAllDecorator('hg.admin')
356 356 def show_ip(self, apiuser, userid):
357 357 """
358 358 Shows IP address as seen from RhodeCode server, together with all
359 359 defined IP addresses for given user
360 360
361 361 :param apiuser:
362 362 :param userid:
363 363 """
364 364 user = get_user_or_error(userid)
365 365 ips = UserIpMap.query().filter(UserIpMap.user == user).all()
366 366 return dict(
367 367 ip_addr_server=self.ip_addr,
368 368 user_ips=ips
369 369 )
370 370
371 371 def get_user(self, apiuser, userid=Optional(OAttr('apiuser'))):
372 372 """"
373 373 Get a user by username, or userid, if userid is given
374 374
375 375 :param apiuser:
376 376 :param userid:
377 377 """
378 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
378 if not HasPermissionAnyApi('hg.admin')(user=apiuser):
379 379 #make sure normal user does not pass someone else userid,
380 380 #he is not allowed to do that
381 381 if not isinstance(userid, Optional) and userid != apiuser.user_id:
382 382 raise JSONRPCError(
383 383 'userid is not the same as your user'
384 384 )
385 385
386 386 if isinstance(userid, Optional):
387 387 userid = apiuser.user_id
388 388
389 389 user = get_user_or_error(userid)
390 390 data = user.get_api_data()
391 391 data['permissions'] = AuthUser(user_id=user.user_id).permissions
392 392 return data
393 393
394 394 @HasPermissionAllDecorator('hg.admin')
395 395 def get_users(self, apiuser):
396 396 """"
397 397 Get all users
398 398
399 399 :param apiuser:
400 400 """
401 401
402 402 result = []
403 403 users_list = User.query().order_by(User.username)\
404 404 .filter(User.username != User.DEFAULT_USER)\
405 405 .all()
406 406 for user in users_list:
407 407 result.append(user.get_api_data())
408 408 return result
409 409
410 410 @HasPermissionAllDecorator('hg.admin')
411 411 def create_user(self, apiuser, username, email, password=Optional(None),
412 412 firstname=Optional(None), lastname=Optional(None),
413 413 active=Optional(True), admin=Optional(False),
414 414 ldap_dn=Optional(None)):
415 415 """
416 416 Create new user
417 417
418 418 :param apiuser:
419 419 :param username:
420 420 :param email:
421 421 :param password:
422 422 :param firstname:
423 423 :param lastname:
424 424 :param active:
425 425 :param admin:
426 426 :param ldap_dn:
427 427 """
428 428
429 429 if UserModel().get_by_username(username):
430 430 raise JSONRPCError("user `%s` already exist" % username)
431 431
432 432 if UserModel().get_by_email(email, case_insensitive=True):
433 433 raise JSONRPCError("email `%s` already exist" % email)
434 434
435 435 if Optional.extract(ldap_dn):
436 436 # generate temporary password if ldap_dn
437 437 password = PasswordGenerator().gen_password(length=8)
438 438
439 439 try:
440 440 user = UserModel().create_or_update(
441 441 username=Optional.extract(username),
442 442 password=Optional.extract(password),
443 443 email=Optional.extract(email),
444 444 firstname=Optional.extract(firstname),
445 445 lastname=Optional.extract(lastname),
446 446 active=Optional.extract(active),
447 447 admin=Optional.extract(admin),
448 448 ldap_dn=Optional.extract(ldap_dn)
449 449 )
450 450 Session().commit()
451 451 return dict(
452 452 msg='created new user `%s`' % username,
453 453 user=user.get_api_data()
454 454 )
455 455 except Exception:
456 456 log.error(traceback.format_exc())
457 457 raise JSONRPCError('failed to create user `%s`' % username)
458 458
459 459 @HasPermissionAllDecorator('hg.admin')
460 460 def update_user(self, apiuser, userid, username=Optional(None),
461 461 email=Optional(None), firstname=Optional(None),
462 462 lastname=Optional(None), active=Optional(None),
463 463 admin=Optional(None), ldap_dn=Optional(None),
464 464 password=Optional(None)):
465 465 """
466 466 Updates given user
467 467
468 468 :param apiuser:
469 469 :param userid:
470 470 :param username:
471 471 :param email:
472 472 :param firstname:
473 473 :param lastname:
474 474 :param active:
475 475 :param admin:
476 476 :param ldap_dn:
477 477 :param password:
478 478 """
479 479
480 480 user = get_user_or_error(userid)
481 481
482 482 # call function and store only updated arguments
483 483 updates = {}
484 484
485 485 def store_update(attr, name):
486 486 if not isinstance(attr, Optional):
487 487 updates[name] = attr
488 488
489 489 try:
490 490
491 491 store_update(username, 'username')
492 492 store_update(password, 'password')
493 493 store_update(email, 'email')
494 494 store_update(firstname, 'name')
495 495 store_update(lastname, 'lastname')
496 496 store_update(active, 'active')
497 497 store_update(admin, 'admin')
498 498 store_update(ldap_dn, 'ldap_dn')
499 499
500 500 user = UserModel().update_user(user, **updates)
501 501 Session().commit()
502 502 return dict(
503 503 msg='updated user ID:%s %s' % (user.user_id, user.username),
504 504 user=user.get_api_data()
505 505 )
506 506 except DefaultUserException:
507 507 log.error(traceback.format_exc())
508 508 raise JSONRPCError('editing default user is forbidden')
509 509 except Exception:
510 510 log.error(traceback.format_exc())
511 511 raise JSONRPCError('failed to update user `%s`' % userid)
512 512
513 513 @HasPermissionAllDecorator('hg.admin')
514 514 def delete_user(self, apiuser, userid):
515 515 """"
516 516 Deletes an user
517 517
518 518 :param apiuser:
519 519 :param userid:
520 520 """
521 521 user = get_user_or_error(userid)
522 522
523 523 try:
524 524 UserModel().delete(userid)
525 525 Session().commit()
526 526 return dict(
527 527 msg='deleted user ID:%s %s' % (user.user_id, user.username),
528 528 user=None
529 529 )
530 530 except Exception:
531 531 log.error(traceback.format_exc())
532 532 raise JSONRPCError('failed to delete ID:%s %s' % (user.user_id,
533 533 user.username))
534 534
535 535 @HasPermissionAllDecorator('hg.admin')
536 536 def get_users_group(self, apiuser, usersgroupid):
537 537 """"
538 538 Get user group by name or id
539 539
540 540 :param apiuser:
541 541 :param usersgroupid:
542 542 """
543 543 users_group = get_users_group_or_error(usersgroupid)
544 544
545 545 data = users_group.get_api_data()
546 546
547 547 members = []
548 548 for user in users_group.members:
549 549 user = user.user
550 550 members.append(user.get_api_data())
551 551 data['members'] = members
552 552 return data
553 553
554 554 @HasPermissionAllDecorator('hg.admin')
555 555 def get_users_groups(self, apiuser):
556 556 """"
557 557 Get all user groups
558 558
559 559 :param apiuser:
560 560 """
561 561
562 562 result = []
563 563 for users_group in UserGroupModel().get_all():
564 564 result.append(users_group.get_api_data())
565 565 return result
566 566
567 567 @HasPermissionAllDecorator('hg.admin')
568 568 def create_users_group(self, apiuser, group_name,
569 569 owner=Optional(OAttr('apiuser')),
570 570 active=Optional(True)):
571 571 """
572 572 Creates an new usergroup
573 573
574 574 :param apiuser:
575 575 :param group_name:
576 576 :param owner:
577 577 :param active:
578 578 """
579 579
580 580 if UserGroupModel().get_by_name(group_name):
581 581 raise JSONRPCError("user group `%s` already exist" % group_name)
582 582
583 583 try:
584 584 if isinstance(owner, Optional):
585 585 owner = apiuser.user_id
586 586
587 587 owner = get_user_or_error(owner)
588 588 active = Optional.extract(active)
589 589 ug = UserGroupModel().create(name=group_name,
590 590 owner=owner,
591 591 active=active)
592 592 Session().commit()
593 593 return dict(
594 594 msg='created new user group `%s`' % group_name,
595 595 users_group=ug.get_api_data()
596 596 )
597 597 except Exception:
598 598 log.error(traceback.format_exc())
599 599 raise JSONRPCError('failed to create group `%s`' % group_name)
600 600
601 601 @HasPermissionAllDecorator('hg.admin')
602 602 def add_user_to_users_group(self, apiuser, usersgroupid, userid):
603 603 """"
604 604 Add a user to a user group
605 605
606 606 :param apiuser:
607 607 :param usersgroupid:
608 608 :param userid:
609 609 """
610 610 user = get_user_or_error(userid)
611 611 users_group = get_users_group_or_error(usersgroupid)
612 612
613 613 try:
614 614 ugm = UserGroupModel().add_user_to_group(users_group, user)
615 615 success = True if ugm != True else False
616 616 msg = 'added member `%s` to user group `%s`' % (
617 617 user.username, users_group.users_group_name
618 618 )
619 619 msg = msg if success else 'User is already in that group'
620 620 Session().commit()
621 621
622 622 return dict(
623 623 success=success,
624 624 msg=msg
625 625 )
626 626 except Exception:
627 627 log.error(traceback.format_exc())
628 628 raise JSONRPCError(
629 629 'failed to add member to user group `%s`' % (
630 630 users_group.users_group_name
631 631 )
632 632 )
633 633
634 634 @HasPermissionAllDecorator('hg.admin')
635 635 def remove_user_from_users_group(self, apiuser, usersgroupid, userid):
636 636 """
637 637 Remove user from a group
638 638
639 639 :param apiuser:
640 640 :param usersgroupid:
641 641 :param userid:
642 642 """
643 643 user = get_user_or_error(userid)
644 644 users_group = get_users_group_or_error(usersgroupid)
645 645
646 646 try:
647 647 success = UserGroupModel().remove_user_from_group(users_group,
648 648 user)
649 649 msg = 'removed member `%s` from user group `%s`' % (
650 650 user.username, users_group.users_group_name
651 651 )
652 652 msg = msg if success else "User wasn't in group"
653 653 Session().commit()
654 654 return dict(success=success, msg=msg)
655 655 except Exception:
656 656 log.error(traceback.format_exc())
657 657 raise JSONRPCError(
658 658 'failed to remove member from user group `%s`' % (
659 659 users_group.users_group_name
660 660 )
661 661 )
662 662
663 663 def get_repo(self, apiuser, repoid):
664 664 """"
665 665 Get repository by name
666 666
667 667 :param apiuser:
668 668 :param repoid:
669 669 """
670 670 repo = get_repo_or_error(repoid)
671 671
672 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
672 if not HasPermissionAnyApi('hg.admin')(user=apiuser):
673 673 # check if we have admin permission for this repo !
674 if HasRepoPermissionAnyApi('repository.admin')(user=apiuser,
675 repo_name=repo.repo_name) is False:
674 if not HasRepoPermissionAnyApi('repository.admin')(user=apiuser,
675 repo_name=repo.repo_name):
676 676 raise JSONRPCError('repository `%s` does not exist' % (repoid))
677 677
678 678 members = []
679 679 followers = []
680 680 for user in repo.repo_to_perm:
681 681 perm = user.permission.permission_name
682 682 user = user.user
683 683 user_data = user.get_api_data()
684 684 user_data['type'] = "user"
685 685 user_data['permission'] = perm
686 686 members.append(user_data)
687 687
688 688 for users_group in repo.users_group_to_perm:
689 689 perm = users_group.permission.permission_name
690 690 users_group = users_group.users_group
691 691 users_group_data = users_group.get_api_data()
692 692 users_group_data['type'] = "users_group"
693 693 users_group_data['permission'] = perm
694 694 members.append(users_group_data)
695 695
696 696 for user in repo.followers:
697 697 followers.append(user.user.get_api_data())
698 698
699 699 data = repo.get_api_data()
700 700 data['members'] = members
701 701 data['followers'] = followers
702 702 return data
703 703
704 # permission check inside
704 705 def get_repos(self, apiuser):
705 706 """"
706 707 Get all repositories
707 708
708 709 :param apiuser:
709 710 """
710 711 result = []
711 712 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
712 713 repos = RepoModel().get_all_user_repos(user=apiuser)
713 714 else:
714 715 repos = RepoModel().get_all()
715 716
716 717 for repo in repos:
717 718 result.append(repo.get_api_data())
718 719 return result
719 720
720 721 @HasPermissionAllDecorator('hg.admin')
721 722 def get_repo_nodes(self, apiuser, repoid, revision, root_path,
722 723 ret_type='all'):
723 724 """
724 725 returns a list of nodes and it's children
725 726 for a given path at given revision. It's possible to specify ret_type
726 727 to show only files or dirs
727 728
728 729 :param apiuser:
729 730 :param repoid: name or id of repository
730 731 :param revision: revision for which listing should be done
731 732 :param root_path: path from which start displaying
732 733 :param ret_type: return type 'all|files|dirs' nodes
733 734 """
734 735 repo = get_repo_or_error(repoid)
735 736 try:
736 737 _d, _f = ScmModel().get_nodes(repo, revision, root_path,
737 738 flat=False)
738 739 _map = {
739 740 'all': _d + _f,
740 741 'files': _f,
741 742 'dirs': _d,
742 743 }
743 744 return _map[ret_type]
744 745 except KeyError:
745 746 raise JSONRPCError('ret_type must be one of %s' % _map.keys())
746 747 except Exception:
747 748 log.error(traceback.format_exc())
748 749 raise JSONRPCError(
749 750 'failed to get repo: `%s` nodes' % repo.repo_name
750 751 )
751 752
752 753 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
753 754 def create_repo(self, apiuser, repo_name, owner=Optional(OAttr('apiuser')),
754 755 repo_type=Optional('hg'),
755 756 description=Optional(''), private=Optional(False),
756 757 clone_uri=Optional(None), landing_rev=Optional('tip'),
757 758 enable_statistics=Optional(False),
758 759 enable_locking=Optional(False),
759 760 enable_downloads=Optional(False)):
760 761 """
761 762 Create repository, if clone_url is given it makes a remote clone
762 763 if repo_name is within a group name the groups will be created
763 764 automatically if they aren't present
764 765
765 766 :param apiuser:
766 767 :param repo_name:
767 768 :param onwer:
768 769 :param repo_type:
769 770 :param description:
770 771 :param private:
771 772 :param clone_uri:
772 773 :param landing_rev:
773 774 """
774 775 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
775 776 if not isinstance(owner, Optional):
776 777 #forbid setting owner for non-admins
777 778 raise JSONRPCError(
778 779 'Only RhodeCode admin can specify `owner` param'
779 780 )
780 781 if isinstance(owner, Optional):
781 782 owner = apiuser.user_id
782 783
783 784 owner = get_user_or_error(owner)
784 785
785 786 if RepoModel().get_by_repo_name(repo_name):
786 787 raise JSONRPCError("repo `%s` already exist" % repo_name)
787 788
788 789 defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
789 790 if isinstance(private, Optional):
790 791 private = defs.get('repo_private') or Optional.extract(private)
791 792 if isinstance(repo_type, Optional):
792 793 repo_type = defs.get('repo_type')
793 794 if isinstance(enable_statistics, Optional):
794 795 enable_statistics = defs.get('repo_enable_statistics')
795 796 if isinstance(enable_locking, Optional):
796 797 enable_locking = defs.get('repo_enable_locking')
797 798 if isinstance(enable_downloads, Optional):
798 799 enable_downloads = defs.get('repo_enable_downloads')
799 800
800 801 clone_uri = Optional.extract(clone_uri)
801 802 description = Optional.extract(description)
802 803 landing_rev = Optional.extract(landing_rev)
803 804
804 805 try:
805 806 # create structure of groups and return the last group
806 807 group = map_groups(repo_name)
807 808
808 809 repo = RepoModel().create_repo(
809 810 repo_name=repo_name,
810 811 repo_type=repo_type,
811 812 description=description,
812 813 owner=owner,
813 814 private=private,
814 815 clone_uri=clone_uri,
815 816 repos_group=group,
816 817 landing_rev=landing_rev,
817 818 enable_statistics=enable_statistics,
818 819 enable_downloads=enable_downloads,
819 820 enable_locking=enable_locking
820 821 )
821 822
822 823 Session().commit()
823 824 return dict(
824 825 msg="Created new repository `%s`" % (repo.repo_name),
825 826 repo=repo.get_api_data()
826 827 )
827 828 except Exception:
828 829 log.error(traceback.format_exc())
829 830 raise JSONRPCError('failed to create repository `%s`' % repo_name)
830 831
831 832 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
832 833 def fork_repo(self, apiuser, repoid, fork_name, owner=Optional(OAttr('apiuser')),
833 834 description=Optional(''), copy_permissions=Optional(False),
834 835 private=Optional(False), landing_rev=Optional('tip')):
835 836 repo = get_repo_or_error(repoid)
836 837 repo_name = repo.repo_name
837 838
838 839 _repo = RepoModel().get_by_repo_name(fork_name)
839 840 if _repo:
840 841 type_ = 'fork' if _repo.fork else 'repo'
841 842 raise JSONRPCError("%s `%s` already exist" % (type_, fork_name))
842 843
843 844 if HasPermissionAnyApi('hg.admin')(user=apiuser):
844 845 pass
845 846 elif HasRepoPermissionAnyApi('repository.admin',
846 847 'repository.write',
847 848 'repository.read')(user=apiuser,
848 849 repo_name=repo.repo_name):
849 850 if not isinstance(owner, Optional):
850 851 #forbid setting owner for non-admins
851 852 raise JSONRPCError(
852 853 'Only RhodeCode admin can specify `owner` param'
853 854 )
854 855 else:
855 856 raise JSONRPCError('repository `%s` does not exist' % (repoid))
856 857
857 858 if isinstance(owner, Optional):
858 859 owner = apiuser.user_id
859 860
860 861 owner = get_user_or_error(owner)
861 862
862 863 try:
863 864 # create structure of groups and return the last group
864 865 group = map_groups(fork_name)
865 866
866 867 form_data = dict(
867 868 repo_name=fork_name,
868 869 repo_name_full=fork_name,
869 870 repo_group=group,
870 871 repo_type=repo.repo_type,
871 872 description=Optional.extract(description),
872 873 private=Optional.extract(private),
873 874 copy_permissions=Optional.extract(copy_permissions),
874 875 landing_rev=Optional.extract(landing_rev),
875 876 update_after_clone=False,
876 877 fork_parent_id=repo.repo_id,
877 878 )
878 879 RepoModel().create_fork(form_data, cur_user=owner)
879 880 return dict(
880 881 msg='Created fork of `%s` as `%s`' % (repo.repo_name,
881 882 fork_name),
882 883 success=True # cannot return the repo data here since fork
883 884 # cann be done async
884 885 )
885 886 except Exception:
886 887 log.error(traceback.format_exc())
887 888 raise JSONRPCError(
888 889 'failed to fork repository `%s` as `%s`' % (repo_name,
889 890 fork_name)
890 891 )
891 892
892 893 # perms handled inside
893 894 def delete_repo(self, apiuser, repoid, forks=Optional(None)):
894 895 """
895 896 Deletes a given repository
896 897
897 898 :param apiuser:
898 899 :param repoid:
899 900 :param forks: detach or delete, what do do with attached forks for repo
900 901 """
901 902 repo = get_repo_or_error(repoid)
902 903
903 904 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
904 905 # check if we have admin permission for this repo !
905 906 if HasRepoPermissionAnyApi('repository.admin')(user=apiuser,
906 907 repo_name=repo.repo_name) is False:
907 908 raise JSONRPCError('repository `%s` does not exist' % (repoid))
908 909
909 910 try:
910 911 handle_forks = Optional.extract(forks)
911 912 _forks_msg = ''
912 913 _forks = [f for f in repo.forks]
913 914 if handle_forks == 'detach':
914 915 _forks_msg = ' ' + 'Detached %s forks' % len(_forks)
915 916 elif handle_forks == 'delete':
916 917 _forks_msg = ' ' + 'Deleted %s forks' % len(_forks)
917 918 elif _forks:
918 919 raise JSONRPCError(
919 920 'Cannot delete `%s` it still contains attached forks'
920 921 % repo.repo_name
921 922 )
922 923
923 924 RepoModel().delete(repo, forks=forks)
924 925 Session().commit()
925 926 return dict(
926 927 msg='Deleted repository `%s`%s' % (repo.repo_name, _forks_msg),
927 928 success=True
928 929 )
929 930 except Exception:
930 931 log.error(traceback.format_exc())
931 932 raise JSONRPCError(
932 933 'failed to delete repository `%s`' % repo.repo_name
933 934 )
934 935
935 936 @HasPermissionAllDecorator('hg.admin')
936 937 def grant_user_permission(self, apiuser, repoid, userid, perm):
937 938 """
938 939 Grant permission for user on given repository, or update existing one
939 940 if found
940 941
941 942 :param repoid:
942 943 :param userid:
943 944 :param perm:
944 945 """
945 946 repo = get_repo_or_error(repoid)
946 947 user = get_user_or_error(userid)
947 948 perm = get_perm_or_error(perm)
948 949
949 950 try:
950 951
951 952 RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)
952 953
953 954 Session().commit()
954 955 return dict(
955 956 msg='Granted perm: `%s` for user: `%s` in repo: `%s`' % (
956 957 perm.permission_name, user.username, repo.repo_name
957 958 ),
958 959 success=True
959 960 )
960 961 except Exception:
961 962 log.error(traceback.format_exc())
962 963 raise JSONRPCError(
963 964 'failed to edit permission for user: `%s` in repo: `%s`' % (
964 965 userid, repoid
965 966 )
966 967 )
967 968
968 969 @HasPermissionAllDecorator('hg.admin')
969 970 def revoke_user_permission(self, apiuser, repoid, userid):
970 971 """
971 972 Revoke permission for user on given repository
972 973
973 974 :param apiuser:
974 975 :param repoid:
975 976 :param userid:
976 977 """
977 978
978 979 repo = get_repo_or_error(repoid)
979 980 user = get_user_or_error(userid)
980 981 try:
981 982
982 983 RepoModel().revoke_user_permission(repo=repo, user=user)
983 984
984 985 Session().commit()
985 986 return dict(
986 987 msg='Revoked perm for user: `%s` in repo: `%s`' % (
987 988 user.username, repo.repo_name
988 989 ),
989 990 success=True
990 991 )
991 992 except Exception:
992 993 log.error(traceback.format_exc())
993 994 raise JSONRPCError(
994 995 'failed to edit permission for user: `%s` in repo: `%s`' % (
995 996 userid, repoid
996 997 )
997 998 )
998 999
999 1000 @HasPermissionAllDecorator('hg.admin')
1000 1001 def grant_users_group_permission(self, apiuser, repoid, usersgroupid,
1001 1002 perm):
1002 1003 """
1003 1004 Grant permission for user group on given repository, or update
1004 1005 existing one if found
1005 1006
1006 1007 :param apiuser:
1007 1008 :param repoid:
1008 1009 :param usersgroupid:
1009 1010 :param perm:
1010 1011 """
1011 1012 repo = get_repo_or_error(repoid)
1012 1013 perm = get_perm_or_error(perm)
1013 1014 users_group = get_users_group_or_error(usersgroupid)
1014 1015
1015 1016 try:
1016 1017 RepoModel().grant_users_group_permission(repo=repo,
1017 1018 group_name=users_group,
1018 1019 perm=perm)
1019 1020
1020 1021 Session().commit()
1021 1022 return dict(
1022 1023 msg='Granted perm: `%s` for user group: `%s` in '
1023 1024 'repo: `%s`' % (
1024 1025 perm.permission_name, users_group.users_group_name,
1025 1026 repo.repo_name
1026 1027 ),
1027 1028 success=True
1028 1029 )
1029 1030 except Exception:
1030 1031 log.error(traceback.format_exc())
1031 1032 raise JSONRPCError(
1032 1033 'failed to edit permission for user group: `%s` in '
1033 1034 'repo: `%s`' % (
1034 1035 usersgroupid, repo.repo_name
1035 1036 )
1036 1037 )
1037 1038
1038 1039 @HasPermissionAllDecorator('hg.admin')
1039 1040 def revoke_users_group_permission(self, apiuser, repoid, usersgroupid):
1040 1041 """
1041 1042 Revoke permission for user group on given repository
1042 1043
1043 1044 :param apiuser:
1044 1045 :param repoid:
1045 1046 :param usersgroupid:
1046 1047 """
1047 1048 repo = get_repo_or_error(repoid)
1048 1049 users_group = get_users_group_or_error(usersgroupid)
1049 1050
1050 1051 try:
1051 1052 RepoModel().revoke_users_group_permission(repo=repo,
1052 1053 group_name=users_group)
1053 1054
1054 1055 Session().commit()
1055 1056 return dict(
1056 1057 msg='Revoked perm for user group: `%s` in repo: `%s`' % (
1057 1058 users_group.users_group_name, repo.repo_name
1058 1059 ),
1059 1060 success=True
1060 1061 )
1061 1062 except Exception:
1062 1063 log.error(traceback.format_exc())
1063 1064 raise JSONRPCError(
1064 1065 'failed to edit permission for user group: `%s` in '
1065 1066 'repo: `%s`' % (
1066 1067 users_group.users_group_name, repo.repo_name
1067 1068 )
1068 1069 )
1069 1070
1070 1071 def create_gist(self, apiuser, files, owner=Optional(OAttr('apiuser')),
1071 1072 gist_type=Optional(Gist.GIST_PUBLIC),
1072 1073 gist_lifetime=Optional(-1),
1073 1074 gist_description=Optional('')):
1074 1075
1075 1076 try:
1076 1077 if isinstance(owner, Optional):
1077 1078 owner = apiuser.user_id
1078 1079
1079 1080 owner = get_user_or_error(owner)
1080 1081 description = Optional.extract(gist_description)
1081 1082 gist_type = Optional.extract(gist_type)
1082 1083 gist_lifetime = Optional.extract(gist_lifetime)
1083 1084
1084 1085 # files: {
1085 1086 # 'filename': {'content':'...', 'lexer': null},
1086 1087 # 'filename2': {'content':'...', 'lexer': null}
1087 1088 #}
1088 1089 gist = GistModel().create(description=description,
1089 1090 owner=owner,
1090 1091 gist_mapping=files,
1091 1092 gist_type=gist_type,
1092 1093 lifetime=gist_lifetime)
1093 1094 Session().commit()
1094 1095 return dict(
1095 1096 msg='created new gist',
1096 1097 gist_url=gist.gist_url(),
1097 1098 gist_id=gist.gist_access_id,
1098 1099 gist_type=gist.gist_type,
1099 1100 files=files.keys()
1100 1101 )
1101 1102 except Exception:
1102 1103 log.error(traceback.format_exc())
1103 1104 raise JSONRPCError('failed to create gist')
1104 1105
1105 1106 def update_gist(self, apiuser):
1106 1107 pass
1107 1108
1108 1109 def delete_gist(self, apiuser):
1109 1110 pass
General Comments 0
You need to be logged in to leave comments. Login now