def invalidate_cache(self, apiuser, repoid): """ Dispatch cache invalidation action on given repo :param apiuser: :param repoid: """ repo = get_repo_or_error(repoid) if HasPermissionAnyApi('hg.admin')(user=apiuser) is False: # check if we have admin permission for this repo ! if HasRepoPermissionAnyApi('repository.admin', 'repository.write')(user=apiuser, repo_name=repo.repo_name) is False: raise JSONRPCError('repository `%s` does not exist' % (repoid)) try: invalidated_keys = ScmModel().mark_for_invalidation(repo.repo_name) Session().commit() return ('Cache for repository `%s` was invalidated: ' 'invalidated cache keys: %s' % (repoid, invalidated_keys)) except Exception: log.error(traceback.format_exc()) raise JSONRPCError( 'Error occurred during cache invalidation action' )
def get_locks(self, apiuser, userid=Optional(OAttr('apiuser'))): """ Get all locks for given userid, if this command is runned by non-admin account userid is set to user who is calling this method, thus returning locks for himself :param apiuser: :param userid: """ if not HasPermissionAnyApi('hg.admin')(user=apiuser): #make sure normal user does not pass someone else userid, #he is not allowed to do that if not isinstance(userid, Optional) and userid != apiuser.user_id: raise JSONRPCError('userid is not the same as your user') ret = [] if isinstance(userid, Optional): user = None else: user = get_user_or_error(userid) #show all locks for r in Repository.getAll(): userid, time_ = r.locked if time_: _api_data = r.get_api_data() # if we use userfilter just show the locks for this user if user: if safe_int(userid) == user.user_id: ret.append(_api_data) else: ret.append(_api_data) return ret
def fork_repo(self, apiuser, repoid, fork_name, owner=Optional(OAttr('apiuser')), description=Optional(''), copy_permissions=Optional(False), private=Optional(False), landing_rev=Optional('tip')): repo = get_repo_or_error(repoid) repo_name = repo.repo_name _repo = RepoModel().get_by_repo_name(fork_name) if _repo: type_ = 'fork' if _repo.fork else 'repo' raise JSONRPCError("%s `%s` already exist" % (type_, fork_name)) if HasPermissionAnyApi('hg.admin')(user=apiuser): pass elif HasRepoPermissionAnyApi('repository.admin', 'repository.write', 'repository.read')(user=apiuser, repo_name=repo.repo_name): if not isinstance(owner, Optional): #forbid setting owner for non-admins raise JSONRPCError( 'Only RhodeCode admin can specify `owner` param' ) else: raise JSONRPCError('repository `%s` does not exist' % (repoid)) if isinstance(owner, Optional): owner = apiuser.user_id owner = get_user_or_error(owner) try: # create structure of groups and return the last group group = map_groups(fork_name) form_data = dict( repo_name=fork_name, repo_name_full=fork_name, repo_group=group, repo_type=repo.repo_type, description=Optional.extract(description), private=Optional.extract(private), copy_permissions=Optional.extract(copy_permissions), landing_rev=Optional.extract(landing_rev), update_after_clone=False, fork_parent_id=repo.repo_id, ) RepoModel().create_fork(form_data, cur_user=owner) return dict( msg='Created fork of `%s` as `%s`' % (repo.repo_name, fork_name), success=True # cannot return the repo data here since fork # cann be done async ) except Exception: log.error(traceback.format_exc()) raise JSONRPCError( 'failed to fork repository `%s` as `%s`' % (repo_name, fork_name) )
def has_superadmin_permission(apiuser): """ Return True if apiuser is admin or return False :param apiuser: """ if HasPermissionAnyApi('hg.admin')(user=apiuser): return True return False
def get_repos(self, apiuser): """" Get all repositories :param apiuser: """ result = [] if HasPermissionAnyApi('hg.admin')(user=apiuser) is False: repos = RepoModel().get_all_user_repos(user=apiuser) else: repos = RepoModel().get_all() for repo in repos: result.append(repo.get_api_data()) return result
def get_user(self, apiuser, userid=Optional(OAttr('apiuser'))): """" Get a user by username, or userid, if userid is given :param apiuser: :param userid: """ if not HasPermissionAnyApi('hg.admin')(user=apiuser): #make sure normal user does not pass someone else userid, #he is not allowed to do that if not isinstance(userid, Optional) and userid != apiuser.user_id: raise JSONRPCError('userid is not the same as your user') if isinstance(userid, Optional): userid = apiuser.user_id user = get_user_or_error(userid) data = user.get_api_data() data['permissions'] = AuthUser(user_id=user.user_id).permissions return data
def delete_repo(self, apiuser, repoid, forks=Optional(None)): """ Deletes a given repository :param apiuser: :param repoid: :param forks: detach or delete, what do do with attached forks for repo """ repo = get_repo_or_error(repoid) if HasPermissionAnyApi('hg.admin')(user=apiuser) is False: # check if we have admin permission for this repo ! if HasRepoPermissionAnyApi('repository.admin')(user=apiuser, repo_name=repo.repo_name) is False: raise JSONRPCError('repository `%s` does not exist' % (repoid)) try: handle_forks = Optional.extract(forks) _forks_msg = '' _forks = [f for f in repo.forks] if handle_forks == 'detach': _forks_msg = ' ' + _('Detached %s forks') % len(_forks) elif handle_forks == 'delete': _forks_msg = ' ' + _('Deleted %s forks') % len(_forks) elif _forks: raise JSONRPCError( 'Cannot delete `%s` it still contains attached forks' % repo.repo_name ) RepoModel().delete(repo, forks=forks) Session().commit() return dict( msg='Deleted repository `%s`%s' % (repo.repo_name, _forks_msg), success=True ) except Exception: log.error(traceback.format_exc()) raise JSONRPCError( 'failed to delete repository `%s`' % repo.repo_name )
def get_repo(self, apiuser, repoid): """" Get repository by name :param apiuser: :param repoid: """ repo = get_repo_or_error(repoid) if HasPermissionAnyApi('hg.admin')(user=apiuser) is False: # check if we have admin permission for this repo ! if HasRepoPermissionAnyApi('repository.admin')(user=apiuser, repo_name=repo.repo_name) is False: raise JSONRPCError('repository `%s` does not exist' % (repoid)) members = [] followers = [] for user in repo.repo_to_perm: perm = user.permission.permission_name user = user.user user_data = user.get_api_data() user_data['type'] = "user" user_data['permission'] = perm members.append(user_data) for users_group in repo.users_group_to_perm: perm = users_group.permission.permission_name users_group = users_group.users_group users_group_data = users_group.get_api_data() users_group_data['type'] = "users_group" users_group_data['permission'] = perm members.append(users_group_data) for user in repo.followers: followers.append(user.user.get_api_data()) data = repo.get_api_data() data['members'] = members data['followers'] = followers return data
def create_user_group( request, apiuser, group_name, description=Optional(''), owner=Optional(OAttr('apiuser')), active=Optional(True)): """ Creates a new user group. This command can only be run using an |authtoken| with admin rights to the specified repository. This command takes the following options: :param apiuser: This is filled automatically from the |authtoken|. :type apiuser: AuthUser :param group_name: Set the name of the new user group. :type group_name: str :param description: Give a description of the new user group. :type description: str :param owner: Set the owner of the new user group. If not set, the owner is the |authtoken| user. :type owner: Optional(str or int) :param active: Set this group as active. :type active: Optional(``True`` | ``False``) Example output: .. code-block:: bash id : <id_given_in_input> result: { "msg": "created new user group `<groupname>`", "user_group": <user_group_object> } error: null Example error output: .. code-block:: bash id : <id_given_in_input> result : null error : { "user group `<group name>` already exist" or "failed to create group `<group name>`" } """ if not has_superadmin_permission(apiuser): if not HasPermissionAnyApi('hg.usergroup.create.true')(user=apiuser): raise JSONRPCForbidden() if UserGroupModel().get_by_name(group_name): raise JSONRPCError("user group `%s` already exist" % (group_name,)) try: if isinstance(owner, Optional): owner = apiuser.user_id owner = get_user_or_error(owner) active = Optional.extract(active) description = Optional.extract(description) ug = UserGroupModel().create( name=group_name, description=description, owner=owner, active=active) Session().commit() return { 'msg': 'created new user group `%s`' % group_name, 'user_group': ug.get_api_data() } except Exception: log.exception("Error occurred during creation of user group") raise JSONRPCError('failed to create group `%s`' % (group_name,))
def create_repo_group(request, apiuser, group_name, description=Optional(''), owner=Optional(OAttr('apiuser')), copy_permissions=Optional(False)): """ Creates a repository group. * If the repository group name contains "/", all the required repository groups will be created. For example "foo/bar/baz" will create |repo| groups "foo" and "bar" (with "foo" as parent). It will also create the "baz" repository with "bar" as |repo| group. This command can only be run using an |authtoken| with admin permissions. :param apiuser: This is filled automatically from the |authtoken|. :type apiuser: AuthUser :param group_name: Set the repository group name. :type group_name: str :param description: Set the |repo| group description. :type description: str :param owner: Set the |repo| group owner. :type owner: str :param copy_permissions: :type copy_permissions: Example output: .. code-block:: bash id : <id_given_in_input> result : { "msg": "Created new repo group `<repo_group_name>`" "repo_group": <repogroup_object> } error : null Example error output: .. code-block:: bash id : <id_given_in_input> result : null error : { failed to create repo group `<repogroupid>` } """ schema = RepoGroupSchema() try: data = schema.deserialize({ 'group_name': group_name }) except colander.Invalid as e: raise JSONRPCError("Validation failed: %s" % (e.asdict(),)) group_name = data['group_name'] if isinstance(owner, Optional): owner = apiuser.user_id group_description = Optional.extract(description) copy_permissions = Optional.extract(copy_permissions) # get by full name with parents, check if it already exist if RepoGroup.get_by_group_name(group_name): raise JSONRPCError("repo group `%s` already exist" % (group_name,)) (group_name_cleaned, parent_group_name) = RepoGroupModel()._get_group_name_and_parent( group_name) parent_group = None if parent_group_name: parent_group = get_repo_group_or_error(parent_group_name) if not HasPermissionAnyApi( 'hg.admin', 'hg.repogroup.create.true')(user=apiuser): # check if we have admin permission for this parent repo group ! # users without admin or hg.repogroup.create can only create other # groups in groups they own so this is a required, but can be empty parent_group = getattr(parent_group, 'group_name', '') _perms = ('group.admin',) if not HasRepoGroupPermissionAnyApi(*_perms)( user=apiuser, group_name=parent_group): raise JSONRPCForbidden() try: repo_group = RepoGroupModel().create( group_name=group_name, group_description=group_description, owner=owner, copy_permissions=copy_permissions) Session().commit() return { 'msg': 'Created new repo group `%s`' % group_name, 'repo_group': repo_group.get_api_data() } except Exception: log.exception("Exception occurred while trying create repo group") raise JSONRPCError( 'failed to create repo group `%s`' % (group_name,))
def create_repo(self, apiuser, repo_name, owner=Optional(OAttr('apiuser')), repo_type=Optional('hg'), description=Optional(''), private=Optional(False), clone_uri=Optional(None), landing_rev=Optional('tip'), enable_statistics=Optional(False), enable_locking=Optional(False), enable_downloads=Optional(False)): """ Create repository, if clone_url is given it makes a remote clone if repo_name is within a group name the groups will be created automatically if they aren't present :param apiuser: :param repo_name: :param onwer: :param repo_type: :param description: :param private: :param clone_uri: :param landing_rev: """ if HasPermissionAnyApi('hg.admin')(user=apiuser) is False: if not isinstance(owner, Optional): #forbid setting owner for non-admins raise JSONRPCError( 'Only RhodeCode admin can specify `owner` param' ) if isinstance(owner, Optional): owner = apiuser.user_id owner = get_user_or_error(owner) if RepoModel().get_by_repo_name(repo_name): raise JSONRPCError("repo `%s` already exist" % repo_name) defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True) if isinstance(private, Optional): private = defs.get('repo_private') or Optional.extract(private) if isinstance(repo_type, Optional): repo_type = defs.get('repo_type') if isinstance(enable_statistics, Optional): enable_statistics = defs.get('repo_enable_statistics') if isinstance(enable_locking, Optional): enable_locking = defs.get('repo_enable_locking') if isinstance(enable_downloads, Optional): enable_downloads = defs.get('repo_enable_downloads') clone_uri = Optional.extract(clone_uri) description = Optional.extract(description) landing_rev = Optional.extract(landing_rev) try: # create structure of groups and return the last group group = map_groups(repo_name) repo = RepoModel().create_repo( repo_name=repo_name, repo_type=repo_type, description=description, owner=owner, private=private, clone_uri=clone_uri, repos_group=group, landing_rev=landing_rev, enable_statistics=enable_statistics, enable_downloads=enable_downloads, enable_locking=enable_locking ) Session().commit() return dict( msg="Created new repository `%s`" % (repo.repo_name), repo=repo.get_api_data() ) except Exception: log.error(traceback.format_exc()) raise JSONRPCError('failed to create repository `%s`' % repo_name)
def lock(self, apiuser, repoid, locked=Optional(None), userid=Optional(OAttr('apiuser'))): """ Set locking state on particular repository by given user, if this command is runned by non-admin account userid is set to user who is calling this method :param apiuser: :param repoid: :param userid: :param locked: """ repo = get_repo_or_error(repoid) if HasPermissionAnyApi('hg.admin')(user=apiuser): pass elif HasRepoPermissionAnyApi('repository.admin', 'repository.write')(user=apiuser, repo_name=repo.repo_name): #make sure normal user does not pass someone else userid, #he is not allowed to do that if not isinstance(userid, Optional) and userid != apiuser.user_id: raise JSONRPCError( 'userid is not the same as your user' ) else: raise JSONRPCError('repository `%s` does not exist' % (repoid)) if isinstance(userid, Optional): userid = apiuser.user_id user = get_user_or_error(userid) if isinstance(locked, Optional): lockobj = Repository.getlock(repo) if lockobj[0] is None: return ('Repo `%s` not locked. Locked=`False`.' % (repo.repo_name)) else: userid, time_ = lockobj user = get_user_or_error(userid) return ('Repo `%s` locked by `%s`. Locked=`True`. ' 'Locked since: `%s`' % (repo.repo_name, user.username, json.dumps(time_to_datetime(time_)))) else: locked = str2bool(locked) try: if locked: Repository.lock(repo, user.user_id) else: Repository.unlock(repo) return ('User `%s` set lock state for repo `%s` to `%s`' % (user.username, repo.repo_name, locked)) except Exception: log.error(traceback.format_exc()) raise JSONRPCError( 'Error occurred locking repository `%s`' % repo.repo_name )
def update_repo(self, apiuser, repoid, name=Optional(None), owner=Optional(OAttr('apiuser')), group=Optional(None), description=Optional(''), private=Optional(False), clone_uri=Optional(None), landing_rev=Optional('tip'), enable_statistics=Optional(False), enable_locking=Optional(False), enable_downloads=Optional(False)): """ Updates repo :param apiuser: filled automatically from apikey :type apiuser: AuthUser :param repoid: repository name or repository id :type repoid: str or int :param name: :param owner: :param group: :param description: :param private: :param clone_uri: :param landing_rev: :param enable_statistics: :param enable_locking: :param enable_downloads: """ repo = get_repo_or_error(repoid) if not HasPermissionAnyApi('hg.admin')(user=apiuser): # check if we have admin permission for this repo ! if not HasRepoPermissionAnyApi('repository.admin')( user=apiuser, repo_name=repo.repo_name): raise JSONRPCError('repository `%s` does not exist' % (repoid, )) updates = { # update function requires this. 'repo_name': repo.repo_name } repo_group = group if not isinstance(repo_group, Optional): repo_group = get_repo_group_or_error(repo_group) repo_group = repo_group.group_id try: store_update(updates, name, 'repo_name') store_update(updates, repo_group, 'repo_group') store_update(updates, owner, 'user') store_update(updates, description, 'repo_description') store_update(updates, private, 'repo_private') store_update(updates, clone_uri, 'clone_uri') store_update(updates, landing_rev, 'repo_landing_rev') store_update(updates, enable_statistics, 'repo_enable_statistics') store_update(updates, enable_locking, 'repo_enable_locking') store_update(updates, enable_downloads, 'repo_enable_downloads') RepoModel().update(repo, **updates) Session().commit() return dict(msg='updated repo ID:%s %s' % (repo.repo_id, repo.repo_name), repository=repo.get_api_data()) except Exception: log.error(traceback.format_exc()) raise JSONRPCError('failed to update repo `%s`' % repoid)