comparison rhodecode/controllers/api/api.py @ 3700:3563bb7b4b82

merge with rc1
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 07 Apr 2013 18:37:22 +0200
parents cd50d1b5f35b b44979649915
children e3857cbb6d10
comparison
equal deleted inserted replaced
3525:0cef54d34605 3700:3563bb7b4b82
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA. 26 # MA 02110-1301, USA.
27 27
28 import traceback 28 import traceback
29 import logging 29 import logging
30 from pylons.controllers.util import abort
31 30
32 from rhodecode.controllers.api import JSONRPCController, JSONRPCError 31 from rhodecode.controllers.api import JSONRPCController, JSONRPCError
33 from rhodecode.lib.auth import PasswordGenerator, AuthUser, \ 32 from rhodecode.lib.auth import PasswordGenerator, AuthUser, \
34 HasPermissionAllDecorator, HasPermissionAnyDecorator, \ 33 HasPermissionAllDecorator, HasPermissionAnyDecorator, \
35 HasPermissionAnyApi, HasRepoPermissionAnyApi 34 HasPermissionAnyApi, HasRepoPermissionAnyApi
36 from rhodecode.lib.utils import map_groups, repo2db_mapper 35 from rhodecode.lib.utils import map_groups, repo2db_mapper
36 from rhodecode.lib.utils2 import str2bool, time_to_datetime, safe_int
37 from rhodecode.lib import helpers as h
37 from rhodecode.model.meta import Session 38 from rhodecode.model.meta import Session
38 from rhodecode.model.scm import ScmModel 39 from rhodecode.model.scm import ScmModel
39 from rhodecode.model.repo import RepoModel 40 from rhodecode.model.repo import RepoModel
40 from rhodecode.model.user import UserModel 41 from rhodecode.model.user import UserModel
41 from rhodecode.model.users_group import UsersGroupModel 42 from rhodecode.model.users_group import UserGroupModel
42 from rhodecode.model.permission import PermissionModel 43 from rhodecode.model.permission import PermissionModel
43 from rhodecode.model.db import Repository, RhodeCodeSetting, UserIpMap 44 from rhodecode.model.db import Repository, RhodeCodeSetting, UserIpMap
45 from rhodecode.lib.compat import json
44 46
45 log = logging.getLogger(__name__) 47 log = logging.getLogger(__name__)
46 48
47 49
48 class OptionalAttr(object): 50 class OptionalAttr(object):
119 return repo 121 return repo
120 122
121 123
122 def get_users_group_or_error(usersgroupid): 124 def get_users_group_or_error(usersgroupid):
123 """ 125 """
124 Get users group by id or name or return JsonRPCError if not found 126 Get user group by id or name or return JsonRPCError if not found
125 127
126 :param userid: 128 :param userid:
127 """ 129 """
128 users_group = UsersGroupModel().get_group(usersgroupid) 130 users_group = UserGroupModel().get_group(usersgroupid)
129 if users_group is None: 131 if users_group is None:
130 raise JSONRPCError('users group `%s` does not exist' % usersgroupid) 132 raise JSONRPCError('user group `%s` does not exist' % usersgroupid)
131 return users_group 133 return users_group
132 134
133 135
134 def get_perm_or_error(permid): 136 def get_perm_or_error(permid):
135 """ 137 """
200 log.error(traceback.format_exc()) 202 log.error(traceback.format_exc())
201 raise JSONRPCError( 203 raise JSONRPCError(
202 'Error occurred during rescan repositories action' 204 'Error occurred during rescan repositories action'
203 ) 205 )
204 206
205 def lock(self, apiuser, repoid, locked, userid=Optional(OAttr('apiuser'))): 207 def invalidate_cache(self, apiuser, repoid):
208 """
209 Dispatch cache invalidation action on given repo
210
211 :param apiuser:
212 :param repoid:
213 """
214 repo = get_repo_or_error(repoid)
215 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
216 # check if we have admin permission for this repo !
217 if HasRepoPermissionAnyApi('repository.admin',
218 'repository.write')(user=apiuser,
219 repo_name=repo.repo_name) is False:
220 raise JSONRPCError('repository `%s` does not exist' % (repoid))
221
222 try:
223 invalidated_keys = ScmModel().mark_for_invalidation(repo.repo_name)
224 Session().commit()
225 return ('Cache for repository `%s` was invalidated: '
226 'invalidated cache keys: %s' % (repoid, invalidated_keys))
227 except Exception:
228 log.error(traceback.format_exc())
229 raise JSONRPCError(
230 'Error occurred during cache invalidation action'
231 )
232
233 def lock(self, apiuser, repoid, locked=Optional(None),
234 userid=Optional(OAttr('apiuser'))):
206 """ 235 """
207 Set locking state on particular repository by given user, if 236 Set locking state on particular repository by given user, if
208 this command is runned by non-admin account userid is set to user 237 this command is runned by non-admin account userid is set to user
209 who is calling this method 238 who is calling this method
210 239
228 else: 257 else:
229 raise JSONRPCError('repository `%s` does not exist' % (repoid)) 258 raise JSONRPCError('repository `%s` does not exist' % (repoid))
230 259
231 if isinstance(userid, Optional): 260 if isinstance(userid, Optional):
232 userid = apiuser.user_id 261 userid = apiuser.user_id
262
233 user = get_user_or_error(userid) 263 user = get_user_or_error(userid)
234 locked = bool(locked) 264
235 try: 265 if isinstance(locked, Optional):
236 if locked: 266 lockobj = Repository.getlock(repo)
237 Repository.lock(repo, user.user_id) 267
268 if lockobj[0] is None:
269 return ('Repo `%s` not locked. Locked=`False`.'
270 % (repo.repo_name))
238 else: 271 else:
239 Repository.unlock(repo) 272 userid, time_ = lockobj
240 273 user = get_user_or_error(userid)
241 return ('User `%s` set lock state for repo `%s` to `%s`' 274
242 % (user.username, repo.repo_name, locked)) 275 return ('Repo `%s` locked by `%s`. Locked=`True`. '
243 except Exception: 276 'Locked since: `%s`'
244 log.error(traceback.format_exc()) 277 % (repo.repo_name, user.username,
245 raise JSONRPCError( 278 json.dumps(time_to_datetime(time_))))
246 'Error occurred locking repository `%s`' % repo.repo_name 279
247 ) 280 else:
281 locked = str2bool(locked)
282 try:
283 if locked:
284 Repository.lock(repo, user.user_id)
285 else:
286 Repository.unlock(repo)
287
288 return ('User `%s` set lock state for repo `%s` to `%s`'
289 % (user.username, repo.repo_name, locked))
290 except Exception:
291 log.error(traceback.format_exc())
292 raise JSONRPCError(
293 'Error occurred locking repository `%s`' % repo.repo_name
294 )
295
296 def get_locks(self, apiuser, userid=Optional(OAttr('apiuser'))):
297 """
298 Get all locks for given userid, if
299 this command is runned by non-admin account userid is set to user
300 who is calling this method, thus returning locks for himself
301
302 :param apiuser:
303 :param userid:
304 """
305 if HasPermissionAnyApi('hg.admin')(user=apiuser):
306 pass
307 else:
308 #make sure normal user does not pass someone else userid,
309 #he is not allowed to do that
310 if not isinstance(userid, Optional) and userid != apiuser.user_id:
311 raise JSONRPCError(
312 'userid is not the same as your user'
313 )
314 ret = []
315 if isinstance(userid, Optional):
316 user = None
317 else:
318 user = get_user_or_error(userid)
319
320 #show all locks
321 for r in Repository.getAll():
322 userid, time_ = r.locked
323 if time_:
324 _api_data = r.get_api_data()
325 # if we use userfilter just show the locks for this user
326 if user:
327 if safe_int(userid) == user.user_id:
328 ret.append(_api_data)
329 else:
330 ret.append(_api_data)
331
332 return ret
248 333
249 @HasPermissionAllDecorator('hg.admin') 334 @HasPermissionAllDecorator('hg.admin')
250 def show_ip(self, apiuser, userid): 335 def show_ip(self, apiuser, userid):
251 """ 336 """
252 Shows IP address as seen from RhodeCode server, together with all 337 Shows IP address as seen from RhodeCode server, together with all
421 user.username)) 506 user.username))
422 507
423 @HasPermissionAllDecorator('hg.admin') 508 @HasPermissionAllDecorator('hg.admin')
424 def get_users_group(self, apiuser, usersgroupid): 509 def get_users_group(self, apiuser, usersgroupid):
425 """" 510 """"
426 Get users group by name or id 511 Get user group by name or id
427 512
428 :param apiuser: 513 :param apiuser:
429 :param usersgroupid: 514 :param usersgroupid:
430 """ 515 """
431 users_group = get_users_group_or_error(usersgroupid) 516 users_group = get_users_group_or_error(usersgroupid)
440 return data 525 return data
441 526
442 @HasPermissionAllDecorator('hg.admin') 527 @HasPermissionAllDecorator('hg.admin')
443 def get_users_groups(self, apiuser): 528 def get_users_groups(self, apiuser):
444 """" 529 """"
445 Get all users groups 530 Get all user groups
446 531
447 :param apiuser: 532 :param apiuser:
448 """ 533 """
449 534
450 result = [] 535 result = []
451 for users_group in UsersGroupModel().get_all(): 536 for users_group in UserGroupModel().get_all():
452 result.append(users_group.get_api_data()) 537 result.append(users_group.get_api_data())
453 return result 538 return result
454 539
455 @HasPermissionAllDecorator('hg.admin') 540 @HasPermissionAllDecorator('hg.admin')
456 def create_users_group(self, apiuser, group_name, active=Optional(True)): 541 def create_users_group(self, apiuser, group_name, active=Optional(True)):
460 :param apiuser: 545 :param apiuser:
461 :param group_name: 546 :param group_name:
462 :param active: 547 :param active:
463 """ 548 """
464 549
465 if UsersGroupModel().get_by_name(group_name): 550 if UserGroupModel().get_by_name(group_name):
466 raise JSONRPCError("users group `%s` already exist" % group_name) 551 raise JSONRPCError("user group `%s` already exist" % group_name)
467 552
468 try: 553 try:
469 active = Optional.extract(active) 554 active = Optional.extract(active)
470 ug = UsersGroupModel().create(name=group_name, active=active) 555 ug = UserGroupModel().create(name=group_name, active=active)
471 Session().commit() 556 Session().commit()
472 return dict( 557 return dict(
473 msg='created new users group `%s`' % group_name, 558 msg='created new user group `%s`' % group_name,
474 users_group=ug.get_api_data() 559 users_group=ug.get_api_data()
475 ) 560 )
476 except Exception: 561 except Exception:
477 log.error(traceback.format_exc()) 562 log.error(traceback.format_exc())
478 raise JSONRPCError('failed to create group `%s`' % group_name) 563 raise JSONRPCError('failed to create group `%s`' % group_name)
479 564
480 @HasPermissionAllDecorator('hg.admin') 565 @HasPermissionAllDecorator('hg.admin')
481 def add_user_to_users_group(self, apiuser, usersgroupid, userid): 566 def add_user_to_users_group(self, apiuser, usersgroupid, userid):
482 """" 567 """"
483 Add a user to a users group 568 Add a user to a user group
484 569
485 :param apiuser: 570 :param apiuser:
486 :param usersgroupid: 571 :param usersgroupid:
487 :param userid: 572 :param userid:
488 """ 573 """
489 user = get_user_or_error(userid) 574 user = get_user_or_error(userid)
490 users_group = get_users_group_or_error(usersgroupid) 575 users_group = get_users_group_or_error(usersgroupid)
491 576
492 try: 577 try:
493 ugm = UsersGroupModel().add_user_to_group(users_group, user) 578 ugm = UserGroupModel().add_user_to_group(users_group, user)
494 success = True if ugm != True else False 579 success = True if ugm != True else False
495 msg = 'added member `%s` to users group `%s`' % ( 580 msg = 'added member `%s` to user group `%s`' % (
496 user.username, users_group.users_group_name 581 user.username, users_group.users_group_name
497 ) 582 )
498 msg = msg if success else 'User is already in that group' 583 msg = msg if success else 'User is already in that group'
499 Session().commit() 584 Session().commit()
500 585
503 msg=msg 588 msg=msg
504 ) 589 )
505 except Exception: 590 except Exception:
506 log.error(traceback.format_exc()) 591 log.error(traceback.format_exc())
507 raise JSONRPCError( 592 raise JSONRPCError(
508 'failed to add member to users group `%s`' % ( 593 'failed to add member to user group `%s`' % (
509 users_group.users_group_name 594 users_group.users_group_name
510 ) 595 )
511 ) 596 )
512 597
513 @HasPermissionAllDecorator('hg.admin') 598 @HasPermissionAllDecorator('hg.admin')
521 """ 606 """
522 user = get_user_or_error(userid) 607 user = get_user_or_error(userid)
523 users_group = get_users_group_or_error(usersgroupid) 608 users_group = get_users_group_or_error(usersgroupid)
524 609
525 try: 610 try:
526 success = UsersGroupModel().remove_user_from_group(users_group, 611 success = UserGroupModel().remove_user_from_group(users_group,
527 user) 612 user)
528 msg = 'removed member `%s` from users group `%s`' % ( 613 msg = 'removed member `%s` from user group `%s`' % (
529 user.username, users_group.users_group_name 614 user.username, users_group.users_group_name
530 ) 615 )
531 msg = msg if success else "User wasn't in group" 616 msg = msg if success else "User wasn't in group"
532 Session().commit() 617 Session().commit()
533 return dict(success=success, msg=msg) 618 return dict(success=success, msg=msg)
534 except Exception: 619 except Exception:
535 log.error(traceback.format_exc()) 620 log.error(traceback.format_exc())
536 raise JSONRPCError( 621 raise JSONRPCError(
537 'failed to remove member from users group `%s`' % ( 622 'failed to remove member from user group `%s`' % (
538 users_group.users_group_name 623 users_group.users_group_name
539 ) 624 )
540 ) 625 )
541 626
542 def get_repo(self, apiuser, repoid): 627 def get_repo(self, apiuser, repoid):
553 if HasRepoPermissionAnyApi('repository.admin')(user=apiuser, 638 if HasRepoPermissionAnyApi('repository.admin')(user=apiuser,
554 repo_name=repo.repo_name) is False: 639 repo_name=repo.repo_name) is False:
555 raise JSONRPCError('repository `%s` does not exist' % (repoid)) 640 raise JSONRPCError('repository `%s` does not exist' % (repoid))
556 641
557 members = [] 642 members = []
643 followers = []
558 for user in repo.repo_to_perm: 644 for user in repo.repo_to_perm:
559 perm = user.permission.permission_name 645 perm = user.permission.permission_name
560 user = user.user 646 user = user.user
561 user_data = user.get_api_data() 647 user_data = user.get_api_data()
562 user_data['type'] = "user" 648 user_data['type'] = "user"
569 users_group_data = users_group.get_api_data() 655 users_group_data = users_group.get_api_data()
570 users_group_data['type'] = "users_group" 656 users_group_data['type'] = "users_group"
571 users_group_data['permission'] = perm 657 users_group_data['permission'] = perm
572 members.append(users_group_data) 658 members.append(users_group_data)
573 659
660 for user in repo.followers:
661 followers.append(user.user.get_api_data())
662
574 data = repo.get_api_data() 663 data = repo.get_api_data()
575 data['members'] = members 664 data['members'] = members
665 data['followers'] = followers
576 return data 666 return data
577 667
578 def get_repos(self, apiuser): 668 def get_repos(self, apiuser):
579 """" 669 """"
580 Get all repositories 670 Get all repositories
761 raise JSONRPCError( 851 raise JSONRPCError(
762 'failed to fork repository `%s` as `%s`' % (repo_name, 852 'failed to fork repository `%s` as `%s`' % (repo_name,
763 fork_name) 853 fork_name)
764 ) 854 )
765 855
766 def delete_repo(self, apiuser, repoid): 856 def delete_repo(self, apiuser, repoid, forks=Optional(None)):
767 """ 857 """
768 Deletes a given repository 858 Deletes a given repository
769 859
770 :param apiuser: 860 :param apiuser:
771 :param repoid: 861 :param repoid:
862 :param forks: detach or delete, what do do with attached forks for repo
772 """ 863 """
773 repo = get_repo_or_error(repoid) 864 repo = get_repo_or_error(repoid)
774 865
775 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False: 866 if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
776 # check if we have admin permission for this repo ! 867 # check if we have admin permission for this repo !
777 if HasRepoPermissionAnyApi('repository.admin')(user=apiuser, 868 if HasRepoPermissionAnyApi('repository.admin')(user=apiuser,
778 repo_name=repo.repo_name) is False: 869 repo_name=repo.repo_name) is False:
779 raise JSONRPCError('repository `%s` does not exist' % (repoid)) 870 raise JSONRPCError('repository `%s` does not exist' % (repoid))
780 871
781 try: 872 try:
782 RepoModel().delete(repo) 873 handle_forks = Optional.extract(forks)
783 Session().commit() 874 _forks_msg = ''
784 return dict( 875 _forks = [f for f in repo.forks]
785 msg='Deleted repository `%s`' % repo.repo_name, 876 if handle_forks == 'detach':
877 _forks_msg = ' ' + _('Detached %s forks') % len(_forks)
878 elif handle_forks == 'delete':
879 _forks_msg = ' ' + _('Deleted %s forks') % len(_forks)
880 elif _forks:
881 raise JSONRPCError(
882 'Cannot delete `%s` it still contains attached forks'
883 % repo.repo_name
884 )
885
886 RepoModel().delete(repo, forks=forks)
887 Session().commit()
888 return dict(
889 msg='Deleted repository `%s`%s' % (repo.repo_name, _forks_msg),
786 success=True 890 success=True
787 ) 891 )
788 except Exception: 892 except Exception:
789 log.error(traceback.format_exc()) 893 log.error(traceback.format_exc())
790 raise JSONRPCError( 894 raise JSONRPCError(
857 961
858 @HasPermissionAllDecorator('hg.admin') 962 @HasPermissionAllDecorator('hg.admin')
859 def grant_users_group_permission(self, apiuser, repoid, usersgroupid, 963 def grant_users_group_permission(self, apiuser, repoid, usersgroupid,
860 perm): 964 perm):
861 """ 965 """
862 Grant permission for users group on given repository, or update 966 Grant permission for user group on given repository, or update
863 existing one if found 967 existing one if found
864 968
865 :param apiuser: 969 :param apiuser:
866 :param repoid: 970 :param repoid:
867 :param usersgroupid: 971 :param usersgroupid:
876 group_name=users_group, 980 group_name=users_group,
877 perm=perm) 981 perm=perm)
878 982
879 Session().commit() 983 Session().commit()
880 return dict( 984 return dict(
881 msg='Granted perm: `%s` for users group: `%s` in ' 985 msg='Granted perm: `%s` for user group: `%s` in '
882 'repo: `%s`' % ( 986 'repo: `%s`' % (
883 perm.permission_name, users_group.users_group_name, 987 perm.permission_name, users_group.users_group_name,
884 repo.repo_name 988 repo.repo_name
885 ), 989 ),
886 success=True 990 success=True
887 ) 991 )
888 except Exception: 992 except Exception:
889 log.error(traceback.format_exc()) 993 log.error(traceback.format_exc())
890 raise JSONRPCError( 994 raise JSONRPCError(
891 'failed to edit permission for users group: `%s` in ' 995 'failed to edit permission for user group: `%s` in '
892 'repo: `%s`' % ( 996 'repo: `%s`' % (
893 usersgroupid, repo.repo_name 997 usersgroupid, repo.repo_name
894 ) 998 )
895 ) 999 )
896 1000
897 @HasPermissionAllDecorator('hg.admin') 1001 @HasPermissionAllDecorator('hg.admin')
898 def revoke_users_group_permission(self, apiuser, repoid, usersgroupid): 1002 def revoke_users_group_permission(self, apiuser, repoid, usersgroupid):
899 """ 1003 """
900 Revoke permission for users group on given repository 1004 Revoke permission for user group on given repository
901 1005
902 :param apiuser: 1006 :param apiuser:
903 :param repoid: 1007 :param repoid:
904 :param usersgroupid: 1008 :param usersgroupid:
905 """ 1009 """
910 RepoModel().revoke_users_group_permission(repo=repo, 1014 RepoModel().revoke_users_group_permission(repo=repo,
911 group_name=users_group) 1015 group_name=users_group)
912 1016
913 Session().commit() 1017 Session().commit()
914 return dict( 1018 return dict(
915 msg='Revoked perm for users group: `%s` in repo: `%s`' % ( 1019 msg='Revoked perm for user group: `%s` in repo: `%s`' % (
916 users_group.users_group_name, repo.repo_name 1020 users_group.users_group_name, repo.repo_name
917 ), 1021 ),
918 success=True 1022 success=True
919 ) 1023 )
920 except Exception: 1024 except Exception:
921 log.error(traceback.format_exc()) 1025 log.error(traceback.format_exc())
922 raise JSONRPCError( 1026 raise JSONRPCError(
923 'failed to edit permission for users group: `%s` in ' 1027 'failed to edit permission for user group: `%s` in '
924 'repo: `%s`' % ( 1028 'repo: `%s`' % (
925 users_group.users_group_name, repo.repo_name 1029 users_group.users_group_name, repo.repo_name
926 ) 1030 )
927 ) 1031 )