aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Kuzminski <marcin@python-works.com>2013-01-14 00:38:24 +0100
committerMarcin Kuzminski <marcin@python-works.com>2013-01-14 00:38:24 +0100
commita9283163661e1c7f4a8a66ee882b009a4718c809 (patch)
tree0158e50813b7d275e7eba75cbdb5e233515c1e91
parent411ca69291ea9c2466fa4ec83bfe1223c9da0890 (diff)
API methods create_repo, fork_repo, delete_repo, get_repo, get_repos
can be executed by non-admin users ref #539 --HG-- branch : beta
-rw-r--r--docs/api/api.rst38
-rw-r--r--rhodecode/controllers/api/__init__.py6
-rw-r--r--rhodecode/controllers/api/api.py85
-rw-r--r--rhodecode/model/repo.py16
-rw-r--r--rhodecode/tests/api/api_base.py255
5 files changed, 352 insertions, 48 deletions
diff --git a/docs/api/api.rst b/docs/api/api.rst
index 2718a11c..d7b63b1d 100644
--- a/docs/api/api.rst
+++ b/docs/api/api.rst
@@ -218,7 +218,7 @@ get_user
Get's an user by username or user_id, Returns empty result if user is not found.
If userid param is skipped it is set to id of user who is calling this method.
This command can be executed only using api_key belonging to user with admin
-rights, or regular users which cannot specify userid parameter.
+rights, or regular users that cannot specify different userid than theirs
INPUT::
@@ -574,8 +574,9 @@ get_repo
--------
Gets an existing repository by it's name or repository_id. Members will return
-either users_group or user associated to that repository. This command can
-be executed only using api_key belonging to user with admin rights.
+either users_group or user associated to that repository. This command can be
+executed only using api_key belonging to user with admin
+rights or regular user that have at least read access to repository.
INPUT::
@@ -637,8 +638,9 @@ OUTPUT::
get_repos
---------
-Lists all existing repositories. This command can be executed only using api_key
-belonging to user with admin rights
+Lists all existing repositories. This command can be executed only using
+api_key belonging to user with admin rights or regular user that have
+admin, write or read access to repository.
INPUT::
@@ -709,11 +711,12 @@ OUTPUT::
create_repo
-----------
-Creates a repository. This command can be executed only using api_key
-belonging to user with admin rights.
-If repository name contains "/", all needed repository groups will be created.
-For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent),
-and create "baz" repository with "bar" as group.
+Creates a repository. If repository name contains "/", all needed repository
+groups will be created. For example "foo/bar/baz" will create groups
+"foo", "bar" (with "foo" as parent), and create "baz" repository with
+"bar" as group. This command can be executed only using api_key belonging to user with admin
+rights or regular user that have create repository permission. Regular users
+cannot specify owner parameter
INPUT::
@@ -723,7 +726,7 @@ INPUT::
method : "create_repo"
args: {
"repo_name" : "<reponame>",
- "owner" : "<onwer_name_or_id>",
+ "owner" : "<onwer_name_or_id = Optional(=apiuser)>",
"repo_type" : "<repo_type> = Optional('hg')",
"description" : "<description> = Optional('')",
"private" : "<bool> = Optional(False)",
@@ -761,10 +764,11 @@ OUTPUT::
fork_repo
---------
-Creates a fork of given repo. This command can be executed only using api_key
-belonging to user with admin rights. In case of using celery this will
+Creates a fork of given repo. In case of using celery this will
immidiatelly return success message, while fork is going to be created
-asynchronous
+asynchronous. This command can be executed only using api_key belonging to
+user with admin rights or regular user that have fork permission, and at least
+read access to forking repository. Regular users cannot specify owner parameter.
INPUT::
@@ -775,7 +779,7 @@ INPUT::
args: {
"repoid" : "<reponame or repo_id>",
"fork_name": "<forkname>",
- "owner": "<username or user_id>",
+ "owner": "<username or user_id = Optional(=apiuser)>",
"description": "<description>",
"copy_permissions": "<bool>",
"private": "<bool>",
@@ -796,8 +800,8 @@ OUTPUT::
delete_repo
-----------
-Deletes a repository. This command can be executed only using api_key
-belonging to user with admin rights.
+Deletes a repository. This command can be executed only using api_key belonging to user with admin
+rights or regular user that have admin access to repository.
INPUT::
diff --git a/rhodecode/controllers/api/__init__.py b/rhodecode/controllers/api/__init__.py
index b72cc2a4..c4d6c11f 100644
--- a/rhodecode/controllers/api/__init__.py
+++ b/rhodecode/controllers/api/__init__.py
@@ -32,17 +32,15 @@ import urllib
import traceback
import time
-from rhodecode.lib.compat import izip_longest, json
-
from paste.response import replace_header
-
from pylons.controllers import WSGIController
-
from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
HTTPBadRequest, HTTPError
from rhodecode.model.db import User
+from rhodecode.model import meta
+from rhodecode.lib.compat import izip_longest, json
from rhodecode.lib.auth import AuthUser
from rhodecode.lib.base import _get_ip_addr, _get_access_path
from rhodecode.lib.utils2 import safe_unicode
diff --git a/rhodecode/controllers/api/api.py b/rhodecode/controllers/api/api.py
index 9786302b..a4b94a7f 100644
--- a/rhodecode/controllers/api/api.py
+++ b/rhodecode/controllers/api/api.py
@@ -219,13 +219,15 @@ class ApiController(JSONRPCController):
elif HasRepoPermissionAnyApi('repository.admin',
'repository.write')(user=apiuser,
repo_name=repo.repo_name):
- #make sure normal user does not pass userid, he is not allowed to do that
- if not isinstance(userid, Optional):
+ #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(
- 'Only RhodeCode admin can specify `userid` param'
+ 'userid is not the same as your user'
)
else:
- return abort(403)
+ raise JSONRPCError('repository `%s` does not exist' % (repoid))
+
if isinstance(userid, Optional):
userid = apiuser.user_id
user = get_user_or_error(userid)
@@ -267,13 +269,15 @@ class ApiController(JSONRPCController):
:param apiuser:
:param userid:
"""
- if HasPermissionAnyApi('hg.admin')(user=apiuser):
- pass
- else:
- if not isinstance(userid, Optional):
+ if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
+ #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(
- 'Only RhodeCode admin can specify `userid` params'
+ 'userid is not the same as your user'
)
+
+ if isinstance(userid, Optional):
userid = apiuser.user_id
user = get_user_or_error(userid)
@@ -535,7 +539,6 @@ class ApiController(JSONRPCController):
)
)
- @HasPermissionAllDecorator('hg.admin')
def get_repo(self, apiuser, repoid):
""""
Get repository by name
@@ -545,6 +548,12 @@ class ApiController(JSONRPCController):
"""
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 = []
for user in repo.repo_to_perm:
perm = user.permission.permission_name
@@ -566,16 +575,19 @@ class ApiController(JSONRPCController):
data['members'] = members
return data
- @HasPermissionAllDecorator('hg.admin')
def get_repos(self, apiuser):
""""
Get all repositories
:param apiuser:
"""
-
result = []
- for repo in RepoModel().get_all():
+ 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
@@ -612,7 +624,8 @@ class ApiController(JSONRPCController):
)
@HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
- def create_repo(self, apiuser, repo_name, owner, repo_type=Optional('hg'),
+ 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),
@@ -620,7 +633,7 @@ class ApiController(JSONRPCController):
enable_downloads=Optional(False)):
"""
Create repository, if clone_url is given it makes a remote clone
- if repo_name is withina group name the groups will be created
+ if repo_name is within a group name the groups will be created
automatically if they aren't present
:param apiuser:
@@ -632,6 +645,15 @@ class ApiController(JSONRPCController):
: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):
@@ -672,29 +694,45 @@ class ApiController(JSONRPCController):
)
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)
- @HasPermissionAllDecorator('hg.admin')
- def fork_repo(self, apiuser, repoid, fork_name, owner,
+ @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
+ 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
- owner = get_user_or_error(owner)
_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)
@@ -725,7 +763,6 @@ class ApiController(JSONRPCController):
fork_name)
)
- @HasPermissionAllDecorator('hg.admin')
def delete_repo(self, apiuser, repoid):
"""
Deletes a given repository
@@ -735,6 +772,12 @@ class ApiController(JSONRPCController):
"""
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:
RepoModel().delete(repo)
Session().commit()
diff --git a/rhodecode/model/repo.py b/rhodecode/model/repo.py
index 76592b49..18db88ce 100644
--- a/rhodecode/model/repo.py
+++ b/rhodecode/model/repo.py
@@ -90,6 +90,22 @@ class RepoModel(BaseModel):
"get_repo_%s" % repo_name))
return repo.scalar()
+ def get_all_user_repos(self, user):
+ """
+ Get's all repositories that user have at least read access
+
+ :param user:
+ :type user:
+ """
+ from rhodecode.lib.auth import AuthUser
+ user = self._get_user(user)
+ repos = AuthUser(user_id=user.user_id).permissions['repositories']
+ access_check = lambda r: r[1] in ['repository.read',
+ 'repository.write',
+ 'repository.admin']
+ repos = [x[0] for x in filter(access_check, repos.items())]
+ return Repository.query().filter(Repository.repo_name.in_(repos))
+
def get_users_js(self):
users = self.sa.query(User).filter(User.active == True).all()
return json.dumps([
diff --git a/rhodecode/tests/api/api_base.py b/rhodecode/tests/api/api_base.py
index 5d0b5c60..92d702d5 100644
--- a/rhodecode/tests/api/api_base.py
+++ b/rhodecode/tests/api/api_base.py
@@ -59,13 +59,13 @@ def destroy_users_group(name=TEST_USERS_GROUP):
Session().commit()
-def create_repo(repo_name, repo_type):
+def create_repo(repo_name, repo_type, owner=None):
# create new repo
form_data = _get_repo_create_params(
repo_name_full=repo_name,
repo_description='description %s' % repo_name,
)
- cur_user = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
+ cur_user = UserModel().get_by_username(owner or TEST_USER_ADMIN_LOGIN)
r = RepoModel().create(form_data, cur_user)
Session().commit()
return r
@@ -93,7 +93,7 @@ class BaseTestApi(object):
def setUpClass(self):
self.usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
self.apikey = self.usr.api_key
- self.TEST_USER = UserModel().create_or_update(
+ self.test_user = UserModel().create_or_update(
username='test-api',
password='test',
email='test@api.rhodecode.org',
@@ -101,7 +101,8 @@ class BaseTestApi(object):
lastname='last'
)
Session().commit()
- self.TEST_USER_LOGIN = self.TEST_USER.username
+ self.TEST_USER_LOGIN = self.test_user.username
+ self.apikey_regular = self.test_user.api_key
@classmethod
def teardownClass(self):
@@ -148,10 +149,10 @@ class BaseTestApi(object):
self._compare_error(id_, expected, given=response.body)
def test_api_missing_non_optional_param(self):
- id_, params = _build_data(self.apikey, 'get_user')
+ id_, params = _build_data(self.apikey, 'get_repo')
response = api_call(self, params)
- expected = 'Missing non optional `userid` arg in JSON DATA'
+ expected = 'Missing non optional `repoid` arg in JSON DATA'
self._compare_error(id_, expected, given=response.body)
def test_api_get_users(self):
@@ -184,6 +185,36 @@ class BaseTestApi(object):
expected = "user `%s` does not exist" % 'trololo'
self._compare_error(id_, expected, given=response.body)
+ def test_api_get_user_without_giving_userid(self):
+ id_, params = _build_data(self.apikey, 'get_user')
+ response = api_call(self, params)
+
+ usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
+ ret = usr.get_api_data()
+ ret['permissions'] = AuthUser(usr.user_id).permissions
+
+ expected = ret
+ self._compare_ok(id_, expected, given=response.body)
+
+ def test_api_get_user_without_giving_userid_non_admin(self):
+ id_, params = _build_data(self.apikey_regular, 'get_user')
+ response = api_call(self, params)
+
+ usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
+ ret = usr.get_api_data()
+ ret['permissions'] = AuthUser(usr.user_id).permissions
+
+ expected = ret
+ self._compare_ok(id_, expected, given=response.body)
+
+ def test_api_get_user_with_giving_userid_non_admin(self):
+ id_, params = _build_data(self.apikey_regular, 'get_user',
+ userid=self.TEST_USER_LOGIN)
+ response = api_call(self, params)
+
+ expected = 'userid is not the same as your user'
+ self._compare_error(id_, expected, given=response.body)
+
def test_api_pull(self):
#TODO: issues with rhodecode_extras here.. not sure why !
pass
@@ -237,6 +268,42 @@ class BaseTestApi(object):
% (TEST_USER_ADMIN_LOGIN, self.REPO, True))
self._compare_ok(id_, expected, given=response.body)
+ def test_api_lock_repo_lock_aquire_by_non_admin(self):
+ repo_name = 'api_delete_me'
+ create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
+ try:
+ id_, params = _build_data(self.apikey_regular, 'lock',
+ repoid=repo_name,
+ locked=True)
+ response = api_call(self, params)
+ expected = ('User `%s` set lock state for repo `%s` to `%s`'
+ % (self.TEST_USER_LOGIN, repo_name, True))
+ self._compare_ok(id_, expected, given=response.body)
+ finally:
+ destroy_repo(repo_name)
+
+ def test_api_lock_repo_lock_aquire_non_admin_with_userid(self):
+ repo_name = 'api_delete_me'
+ create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
+ try:
+ id_, params = _build_data(self.apikey_regular, 'lock',
+ userid=TEST_USER_ADMIN_LOGIN,
+ repoid=repo_name,
+ locked=True)
+ response = api_call(self, params)
+ expected = 'userid is not the same as your user'
+ self._compare_error(id_, expected, given=response.body)
+ finally:
+ destroy_repo(repo_name)
+
+ def test_api_lock_repo_lock_aquire_non_admin_not_his_repo(self):
+ id_, params = _build_data(self.apikey_regular, 'lock',
+ repoid=self.REPO,
+ locked=True)
+ response = api_call(self, params)
+ expected = 'repository `%s` does not exist' % (self.REPO)
+ self._compare_error(id_, expected, given=response.body)
+
def test_api_lock_repo_lock_release(self):
id_, params = _build_data(self.apikey, 'lock',
userid=TEST_USER_ADMIN_LOGIN,
@@ -466,6 +533,48 @@ class BaseTestApi(object):
self._compare_ok(id_, expected, given=response.body)
destroy_users_group(new_group)
+ def test_api_get_repo_by_non_admin(self):
+ id_, params = _build_data(self.apikey, 'get_repo',
+ repoid=self.REPO)
+ response = api_call(self, params)
+
+ repo = RepoModel().get_by_repo_name(self.REPO)
+ ret = repo.get_api_data()
+
+ members = []
+ 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)
+
+ ret['members'] = members
+
+ expected = ret
+ self._compare_ok(id_, expected, given=response.body)
+
+ def test_api_get_repo_by_non_admin_no_permission_to_repo(self):
+ RepoModel().grant_user_permission(repo=self.REPO,
+ user=self.TEST_USER_LOGIN,
+ perm='repository.none')
+
+ id_, params = _build_data(self.apikey_regular, 'get_repo',
+ repoid=self.REPO)
+ response = api_call(self, params)
+
+ expected = 'repository `%s` does not exist' % (self.REPO)
+ self._compare_error(id_, expected, given=response.body)
+
def test_api_get_repo_that_doesn_not_exist(self):
id_, params = _build_data(self.apikey, 'get_repo',
repoid='no-such-repo')
@@ -487,6 +596,18 @@ class BaseTestApi(object):
expected = ret
self._compare_ok(id_, expected, given=response.body)
+ def test_api_get_repos_non_admin(self):
+ id_, params = _build_data(self.apikey_regular, 'get_repos')
+ response = api_call(self, params)
+
+ result = []
+ for repo in RepoModel().get_all_user_repos(self.TEST_USER_LOGIN):
+ result.append(repo.get_api_data())
+ ret = jsonify(result)
+
+ expected = ret
+ self._compare_ok(id_, expected, given=response.body)
+
@parameterized.expand([('all', 'all'),
('dirs', 'dirs'),
('files', 'files'), ])
@@ -569,6 +690,56 @@ class BaseTestApi(object):
expected = 'user `%s` does not exist' % owner
self._compare_error(id_, expected, given=response.body)
+ def test_api_create_repo_dont_specify_owner(self):
+ repo_name = 'api-repo'
+ owner = 'i-dont-exist'
+ id_, params = _build_data(self.apikey, 'create_repo',
+ repo_name=repo_name,
+ repo_type='hg',
+ )
+ response = api_call(self, params)
+
+ repo = RepoModel().get_by_repo_name(repo_name)
+ ret = {
+ 'msg': 'Created new repository `%s`' % repo_name,
+ 'repo': jsonify(repo.get_api_data())
+ }
+ expected = ret
+ self._compare_ok(id_, expected, given=response.body)
+ destroy_repo(repo_name)
+
+ def test_api_create_repo_by_non_admin(self):
+ repo_name = 'api-repo'
+ owner = 'i-dont-exist'
+ id_, params = _build_data(self.apikey_regular, 'create_repo',
+ repo_name=repo_name,
+ repo_type='hg',
+ )
+ response = api_call(self, params)
+
+ repo = RepoModel().get_by_repo_name(repo_name)
+ ret = {
+ 'msg': 'Created new repository `%s`' % repo_name,
+ 'repo': jsonify(repo.get_api_data())
+ }
+ expected = ret
+ self._compare_ok(id_, expected, given=response.body)
+ destroy_repo(repo_name)
+
+ def test_api_create_repo_by_non_admin_specify_owner(self):
+ repo_name = 'api-repo'
+ owner = 'i-dont-exist'
+ id_, params = _build_data(self.apikey_regular, 'create_repo',
+ repo_name=repo_name,
+ repo_type='hg',
+ owner=owner
+ )
+ response = api_call(self, params)
+
+ expected = 'Only RhodeCode admin can specify `owner` param'
+ self._compare_error(id_, expected, given=response.body)
+ destroy_repo(repo_name)
+
def test_api_create_repo_exists(self):
repo_name = self.REPO
id_, params = _build_data(self.apikey, 'create_repo',
@@ -607,6 +778,35 @@ class BaseTestApi(object):
expected = ret
self._compare_ok(id_, expected, given=response.body)
+ def test_api_delete_repo_by_non_admin(self):
+ repo_name = 'api_delete_me'
+ create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
+ try:
+ id_, params = _build_data(self.apikey_regular, 'delete_repo',
+ repoid=repo_name,)
+ response = api_call(self, params)
+
+ ret = {
+ 'msg': 'Deleted repository `%s`' % repo_name,
+ 'success': True
+ }
+ expected = ret
+ self._compare_ok(id_, expected, given=response.body)
+ finally:
+ destroy_repo(repo_name)
+
+ def test_api_delete_repo_by_non_admin_no_permission(self):
+ repo_name = 'api_delete_me'
+ create_repo(repo_name, self.REPO_TYPE)
+ try:
+ id_, params = _build_data(self.apikey_regular, 'delete_repo',
+ repoid=repo_name,)
+ response = api_call(self, params)
+ expected = 'repository `%s` does not exist' % (repo_name)
+ self._compare_error(id_, expected, given=response.body)
+ finally:
+ destroy_repo(repo_name)
+
def test_api_delete_repo_exception_occurred(self):
repo_name = 'api_delete_me'
create_repo(repo_name, self.REPO_TYPE)
@@ -639,6 +839,49 @@ class BaseTestApi(object):
self._compare_ok(id_, expected, given=response.body)
destroy_repo(fork_name)
+ def test_api_fork_repo_non_admin(self):
+ fork_name = 'api-repo-fork'
+ id_, params = _build_data(self.apikey_regular, 'fork_repo',
+ repoid=self.REPO,
+ fork_name=fork_name,
+ )
+ response = api_call(self, params)
+
+ ret = {
+ 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
+ fork_name),
+ 'success': True
+ }
+ expected = ret
+ self._compare_ok(id_, expected, given=response.body)
+ destroy_repo(fork_name)
+
+ def test_api_fork_repo_non_admin_specify_owner(self):
+ fork_name = 'api-repo-fork'
+ id_, params = _build_data(self.apikey_regular, 'fork_repo',
+ repoid=self.REPO,
+ fork_name=fork_name,
+ owner=TEST_USER_ADMIN_LOGIN,
+ )
+ response = api_call(self, params)
+ expected = 'Only RhodeCode admin can specify `owner` param'
+ self._compare_error(id_, expected, given=response.body)
+ destroy_repo(fork_name)
+
+ def test_api_fork_repo_non_admin_no_permission_to_fork(self):
+ RepoModel().grant_user_permission(repo=self.REPO,
+ user=self.TEST_USER_LOGIN,
+ perm='repository.none')
+ fork_name = 'api-repo-fork'
+ id_, params = _build_data(self.apikey_regular, 'fork_repo',
+ repoid=self.REPO,
+ fork_name=fork_name,
+ )
+ response = api_call(self, params)
+ expected = 'repository `%s` does not exist' % (self.REPO)
+ self._compare_error(id_, expected, given=response.body)
+ destroy_repo(fork_name)
+
def test_api_fork_repo_unknown_owner(self):
fork_name = 'api-repo-fork'
owner = 'i-dont-exist'