api.py
784 lines
| 24.6 KiB
| text/x-python
|
PythonLexer
r1824 | # -*- coding: utf-8 -*- | |||
""" | ||||
rhodecode.controllers.api | ||||
~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
API controller for RhodeCode | ||||
:created_on: Aug 20, 2011 | ||||
:author: marcink | ||||
:copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com> | ||||
:license: GPLv3, see COPYING for more details. | ||||
""" | ||||
# This program is free software; you can redistribute it and/or | ||||
# modify it under the terms of the GNU General Public License | ||||
# as published by the Free Software Foundation; version 2 | ||||
# of the License or (at your opinion) any later version of the license. | ||||
# | ||||
# This program is distributed in the hope that it will be useful, | ||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
# GNU General Public License for more details. | ||||
# | ||||
# You should have received a copy of the GNU General Public License | ||||
# along with this program; if not, write to the Free Software | ||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | ||||
# MA 02110-1301, USA. | ||||
r1500 | import traceback | |||
import logging | ||||
r1445 | from rhodecode.controllers.api import JSONRPCController, JSONRPCError | |||
r1594 | from rhodecode.lib.auth import HasPermissionAllDecorator, \ | |||
r2151 | HasPermissionAnyDecorator, PasswordGenerator, AuthUser | |||
r2697 | from rhodecode.lib.utils import map_groups, repo2db_mapper | |||
r1734 | from rhodecode.model.meta import Session | |||
r1445 | from rhodecode.model.scm import ScmModel | |||
Nicolas VINOT
|
r1584 | from rhodecode.model.repo import RepoModel | ||
Nicolas VINOT
|
r1586 | from rhodecode.model.user import UserModel | ||
from rhodecode.model.users_group import UsersGroupModel | ||||
r2526 | from rhodecode.model.permission import PermissionModel | |||
r1734 | ||||
Nicolas VINOT
|
r1593 | log = logging.getLogger(__name__) | ||
r1500 | ||||
r1445 | ||||
r2526 | class Optional(object): | |||
""" | ||||
Defines an optional parameter:: | ||||
param = param.getval() if isinstance(param, Optional) else param | ||||
param = param() if isinstance(param, Optional) else param | ||||
is equivalent of:: | ||||
param = Optional.extract(param) | ||||
""" | ||||
def __init__(self, type_): | ||||
self.type_ = type_ | ||||
def __repr__(self): | ||||
return '<Optional:%s>' % self.type_.__repr__() | ||||
def __call__(self): | ||||
return self.getval() | ||||
def getval(self): | ||||
""" | ||||
returns value from this Optional instance | ||||
""" | ||||
return self.type_ | ||||
@classmethod | ||||
def extract(cls, val): | ||||
if isinstance(val, cls): | ||||
return val.getval() | ||||
return val | ||||
def get_user_or_error(userid): | ||||
""" | ||||
Get user by id or name or return JsonRPCError if not found | ||||
:param userid: | ||||
""" | ||||
user = UserModel().get_user(userid) | ||||
if user is None: | ||||
raise JSONRPCError("user `%s` does not exist" % userid) | ||||
return user | ||||
def get_repo_or_error(repoid): | ||||
""" | ||||
Get repo by id or name or return JsonRPCError if not found | ||||
:param userid: | ||||
""" | ||||
repo = RepoModel().get_repo(repoid) | ||||
if repo is None: | ||||
raise JSONRPCError('repository `%s` does not exist' % (repoid)) | ||||
return repo | ||||
def get_users_group_or_error(usersgroupid): | ||||
""" | ||||
Get users group by id or name or return JsonRPCError if not found | ||||
:param userid: | ||||
""" | ||||
users_group = UsersGroupModel().get_group(usersgroupid) | ||||
if users_group is None: | ||||
raise JSONRPCError('users group `%s` does not exist' % usersgroupid) | ||||
return users_group | ||||
def get_perm_or_error(permid): | ||||
""" | ||||
Get permission by id or name or return JsonRPCError if not found | ||||
:param userid: | ||||
""" | ||||
perm = PermissionModel().get_permission_by_name(permid) | ||||
if perm is None: | ||||
raise JSONRPCError('permission `%s` does not exist' % (permid)) | ||||
return perm | ||||
Nicolas VINOT
|
r1593 | class ApiController(JSONRPCController): | ||
r1445 | """ | |||
API Controller | ||||
Nicolas VINOT
|
r1584 | |||
r1445 | Each method needs to have USER as argument this is then based on given | |||
API_KEY propagated as instance of user object | ||||
Nicolas VINOT
|
r1584 | |||
r1445 | Preferably this should be first argument also | |||
Nicolas VINOT
|
r1584 | |||
Each function should also **raise** JSONRPCError for any | ||||
r1445 | errors that happens | |||
Nicolas VINOT
|
r1584 | |||
r1445 | """ | |||
Nicolas VINOT
|
r1593 | @HasPermissionAllDecorator('hg.admin') | ||
r2526 | def pull(self, apiuser, repoid): | |||
r1445 | """ | |||
Dispatch pull action on given repo | ||||
Nicolas VINOT
|
r1584 | |||
r2526 | :param apiuser: | |||
:param repoid: | ||||
r1445 | """ | |||
r2526 | repo = get_repo_or_error(repoid) | |||
Nicolas VINOT
|
r1587 | |||
r1445 | try: | |||
r2526 | ScmModel().pull_changes(repo.repo_name, | |||
self.rhodecode_user.username) | ||||
return 'Pulled from `%s`' % repo.repo_name | ||||
r1445 | except Exception: | |||
r2526 | log.error(traceback.format_exc()) | |||
raise JSONRPCError( | ||||
'Unable to pull changes from `%s`' % repo.repo_name | ||||
) | ||||
r1445 | ||||
Nicolas VINOT
|
r1593 | @HasPermissionAllDecorator('hg.admin') | ||
r2697 | def rescan_repos(self, apiuser, remove_obsolete=Optional(False)): | |||
""" | ||||
Dispatch rescan repositories action. If remove_obsolete is set | ||||
than also delete repos that are in database but not in the filesystem. | ||||
aka "clean zombies" | ||||
:param apiuser: | ||||
:param remove_obsolete: | ||||
""" | ||||
try: | ||||
rm_obsolete = Optional.extract(remove_obsolete) | ||||
added, removed = repo2db_mapper(ScmModel().repo_scan(), | ||||
remove_obsolete=rm_obsolete) | ||||
return {'added': added, 'removed': removed} | ||||
except Exception: | ||||
log.error(traceback.format_exc()) | ||||
raise JSONRPCError( | ||||
'Unable to rescan repositories' | ||||
) | ||||
@HasPermissionAllDecorator('hg.admin') | ||||
r2010 | def get_user(self, apiuser, userid): | |||
Nicolas VINOT
|
r1587 | """" | ||
Get a user by username | ||||
r1793 | :param apiuser: | |||
r2526 | :param userid: | |||
Nicolas VINOT
|
r1587 | """ | ||
r1445 | ||||
r2526 | user = get_user_or_error(userid) | |||
data = user.get_api_data() | ||||
data['permissions'] = AuthUser(user_id=user.user_id).permissions | ||||
return data | ||||
r1793 | ||||
@HasPermissionAllDecorator('hg.admin') | ||||
def get_users(self, apiuser): | ||||
"""" | ||||
Get all users | ||||
:param apiuser: | ||||
""" | ||||
result = [] | ||||
r2526 | for user in UserModel().get_all(): | |||
result.append(user.get_api_data()) | ||||
Nicolas VINOT
|
r1586 | return result | ||
Nicolas VINOT
|
r1593 | @HasPermissionAllDecorator('hg.admin') | ||
r2526 | def create_user(self, apiuser, username, email, password, | |||
firstname=Optional(None), lastname=Optional(None), | ||||
active=Optional(True), admin=Optional(False), | ||||
ldap_dn=Optional(None)): | ||||
r1500 | """ | |||
r2002 | Create new user | |||
Nicolas VINOT
|
r1584 | |||
r1500 | :param apiuser: | |||
:param username: | ||||
r2526 | :param email: | |||
r1500 | :param password: | |||
r2526 | :param firstname: | |||
r1500 | :param lastname: | |||
Nicolas VINOT
|
r1584 | :param active: | ||
:param admin: | ||||
:param ldap_dn: | ||||
r1500 | """ | |||
Nicolas VINOT
|
r1589 | |||
r2526 | if UserModel().get_by_username(username): | |||
raise JSONRPCError("user `%s` already exist" % username) | ||||
if UserModel().get_by_email(email, case_insensitive=True): | ||||
raise JSONRPCError("email `%s` already exist" % email) | ||||
r2008 | ||||
if ldap_dn: | ||||
# generate temporary password if ldap_dn | ||||
password = PasswordGenerator().gen_password(length=8) | ||||
r1500 | try: | |||
r2365 | user = UserModel().create_or_update( | |||
r2526 | username=Optional.extract(username), | |||
password=Optional.extract(password), | ||||
email=Optional.extract(email), | ||||
firstname=Optional.extract(firstname), | ||||
lastname=Optional.extract(lastname), | ||||
active=Optional.extract(active), | ||||
admin=Optional.extract(admin), | ||||
ldap_dn=Optional.extract(ldap_dn) | ||||
r1843 | ) | |||
r2526 | Session().commit() | |||
r1843 | return dict( | |||
r2526 | msg='created new user `%s`' % username, | |||
user=user.get_api_data() | ||||
r1843 | ) | |||
r1500 | except Exception: | |||
Nicolas VINOT
|
r1593 | log.error(traceback.format_exc()) | ||
r2526 | raise JSONRPCError('failed to create user `%s`' % username) | |||
Nicolas VINOT
|
r1587 | |||
Nicolas VINOT
|
r1593 | @HasPermissionAllDecorator('hg.admin') | ||
r2526 | def update_user(self, apiuser, userid, username=Optional(None), | |||
email=Optional(None), firstname=Optional(None), | ||||
lastname=Optional(None), active=Optional(None), | ||||
admin=Optional(None), ldap_dn=Optional(None), | ||||
password=Optional(None)): | ||||
r2002 | """ | |||
Updates given user | ||||
:param apiuser: | ||||
r2526 | :param userid: | |||
r2002 | :param username: | |||
:param email: | ||||
r2526 | :param firstname: | |||
r2002 | :param lastname: | |||
:param active: | ||||
:param admin: | ||||
:param ldap_dn: | ||||
r2526 | :param password: | |||
r2002 | """ | |||
r2526 | ||||
user = get_user_or_error(userid) | ||||
r2657 | # call function and store only updated arguments | |||
updates = {} | ||||
def store_update(attr, name): | ||||
if not isinstance(attr, Optional): | ||||
updates[name] = attr | ||||
r2002 | ||||
try: | ||||
r2526 | ||||
r2657 | store_update(username, 'username') | |||
store_update(password, 'password') | ||||
store_update(email, 'email') | ||||
store_update(firstname, 'name') | ||||
store_update(lastname, 'lastname') | ||||
store_update(active, 'active') | ||||
store_update(admin, 'admin') | ||||
store_update(ldap_dn, 'ldap_dn') | ||||
user = UserModel().update_user(user, **updates) | ||||
r2526 | Session().commit() | |||
r2002 | return dict( | |||
r2507 | msg='updated user ID:%s %s' % (user.user_id, user.username), | |||
r2526 | user=user.get_api_data() | |||
r2002 | ) | |||
except Exception: | ||||
log.error(traceback.format_exc()) | ||||
r2526 | raise JSONRPCError('failed to update user `%s`' % userid) | |||
r2365 | ||||
@HasPermissionAllDecorator('hg.admin') | ||||
def delete_user(self, apiuser, userid): | ||||
"""" | ||||
Deletes an user | ||||
:param apiuser: | ||||
r2526 | :param userid: | |||
r2365 | """ | |||
r2526 | user = get_user_or_error(userid) | |||
r2365 | ||||
try: | ||||
UserModel().delete(userid) | ||||
r2526 | Session().commit() | |||
r2365 | return dict( | |||
r2526 | msg='deleted user ID:%s %s' % (user.user_id, user.username), | |||
user=None | ||||
r2365 | ) | |||
except Exception: | ||||
log.error(traceback.format_exc()) | ||||
r2526 | raise JSONRPCError('failed to delete ID:%s %s' % (user.user_id, | |||
user.username)) | ||||
r2002 | ||||
@HasPermissionAllDecorator('hg.admin') | ||||
r2526 | def get_users_group(self, apiuser, usersgroupid): | |||
Nicolas VINOT
|
r1587 | """" | ||
r2526 | Get users group by name or id | |||
Nicolas VINOT
|
r1587 | |||
r1793 | :param apiuser: | |||
r2526 | :param usersgroupid: | |||
Nicolas VINOT
|
r1587 | """ | ||
r2526 | users_group = get_users_group_or_error(usersgroupid) | |||
Nicolas VINOT
|
r1587 | |||
r2526 | data = users_group.get_api_data() | |||
r1445 | ||||
Nicolas VINOT
|
r1587 | members = [] | ||
for user in users_group.members: | ||||
user = user.user | ||||
r2526 | members.append(user.get_api_data()) | |||
data['members'] = members | ||||
return data | ||||
Nicolas VINOT
|
r1587 | |||
Nicolas VINOT
|
r1593 | @HasPermissionAllDecorator('hg.admin') | ||
def get_users_groups(self, apiuser): | ||||
Nicolas VINOT
|
r1584 | """" | ||
Nicolas VINOT
|
r1587 | Get all users groups | ||
Nicolas VINOT
|
r1584 | |||
r1793 | :param apiuser: | |||
Nicolas VINOT
|
r1584 | """ | ||
Nicolas VINOT
|
r1586 | |||
Nicolas VINOT
|
r1584 | result = [] | ||
r2526 | for users_group in UsersGroupModel().get_all(): | |||
result.append(users_group.get_api_data()) | ||||
Nicolas VINOT
|
r1584 | return result | ||
Nicolas VINOT
|
r1593 | @HasPermissionAllDecorator('hg.admin') | ||
r2526 | def create_users_group(self, apiuser, group_name, active=Optional(True)): | |||
r1500 | """ | |||
Creates an new usergroup | ||||
Nicolas VINOT
|
r1584 | |||
r2526 | :param apiuser: | |||
r1843 | :param group_name: | |||
r1500 | :param active: | |||
""" | ||||
Nicolas VINOT
|
r1586 | |||
r2526 | if UsersGroupModel().get_by_name(group_name): | |||
raise JSONRPCError("users group `%s` already exist" % group_name) | ||||
Nicolas VINOT
|
r1589 | |||
r1500 | try: | |||
r2526 | active = Optional.extract(active) | |||
r1843 | ug = UsersGroupModel().create(name=group_name, active=active) | |||
r2526 | Session().commit() | |||
return dict( | ||||
msg='created new users group `%s`' % group_name, | ||||
users_group=ug.get_api_data() | ||||
) | ||||
r1500 | except Exception: | |||
Nicolas VINOT
|
r1593 | log.error(traceback.format_exc()) | ||
r2526 | raise JSONRPCError('failed to create group `%s`' % group_name) | |||
Nicolas VINOT
|
r1584 | |||
Nicolas VINOT
|
r1593 | @HasPermissionAllDecorator('hg.admin') | ||
r2526 | def add_user_to_users_group(self, apiuser, usersgroupid, userid): | |||
Nicolas VINOT
|
r1584 | """" | ||
r2146 | Add a user to a users group | |||
Nicolas VINOT
|
r1584 | |||
r1793 | :param apiuser: | |||
r2526 | :param usersgroupid: | |||
:param userid: | ||||
Nicolas VINOT
|
r1584 | """ | ||
r2526 | user = get_user_or_error(userid) | |||
users_group = get_users_group_or_error(usersgroupid) | ||||
Nicolas VINOT
|
r1584 | |||
Nicolas VINOT
|
r1586 | try: | ||
Nicolas VINOT
|
r1593 | ugm = UsersGroupModel().add_user_to_group(users_group, user) | ||
r1989 | success = True if ugm != True else False | |||
r2526 | msg = 'added member `%s` to users group `%s`' % ( | |||
user.username, users_group.users_group_name | ||||
) | ||||
r1989 | msg = msg if success else 'User is already in that group' | |||
r2526 | Session().commit() | |||
r1989 | ||||
return dict( | ||||
success=success, | ||||
msg=msg | ||||
) | ||||
Nicolas VINOT
|
r1587 | except Exception: | ||
Nicolas VINOT
|
r1593 | log.error(traceback.format_exc()) | ||
r2526 | raise JSONRPCError( | |||
'failed to add member to users group `%s`' % ( | ||||
users_group.users_group_name | ||||
) | ||||
) | ||||
r1989 | ||||
@HasPermissionAllDecorator('hg.admin') | ||||
r2526 | def remove_user_from_users_group(self, apiuser, usersgroupid, userid): | |||
r1989 | """ | |||
Remove user from a group | ||||
r2526 | :param apiuser: | |||
:param usersgroupid: | ||||
:param userid: | ||||
r1989 | """ | |||
r2526 | user = get_user_or_error(userid) | |||
users_group = get_users_group_or_error(usersgroupid) | ||||
r1989 | ||||
try: | ||||
r2526 | success = UsersGroupModel().remove_user_from_group(users_group, | |||
user) | ||||
msg = 'removed member `%s` from users group `%s`' % ( | ||||
user.username, users_group.users_group_name | ||||
) | ||||
r1989 | msg = msg if success else "User wasn't in group" | |||
r2526 | Session().commit() | |||
r1989 | return dict(success=success, msg=msg) | |||
except Exception: | ||||
log.error(traceback.format_exc()) | ||||
r2526 | raise JSONRPCError( | |||
'failed to remove member from users group `%s`' % ( | ||||
users_group.users_group_name | ||||
) | ||||
) | ||||
Nicolas VINOT
|
r1587 | |||
Nicolas VINOT
|
r1593 | @HasPermissionAnyDecorator('hg.admin') | ||
r2010 | def get_repo(self, apiuser, repoid): | |||
Nicolas VINOT
|
r1587 | """" | ||
Get repository by name | ||||
r1793 | :param apiuser: | |||
r2526 | :param repoid: | |||
Nicolas VINOT
|
r1587 | """ | ||
r2526 | repo = get_repo_or_error(repoid) | |||
Nicolas VINOT
|
r1584 | |||
Nicolas VINOT
|
r1587 | members = [] | ||
for user in repo.repo_to_perm: | ||||
perm = user.permission.permission_name | ||||
user = user.user | ||||
r2526 | user_data = user.get_api_data() | |||
user_data['type'] = "user" | ||||
user_data['permission'] = perm | ||||
members.append(user_data) | ||||
Nicolas VINOT
|
r1587 | for users_group in repo.users_group_to_perm: | ||
perm = users_group.permission.permission_name | ||||
users_group = users_group.users_group | ||||
r2526 | users_group_data = users_group.get_api_data() | |||
users_group_data['type'] = "users_group" | ||||
users_group_data['permission'] = perm | ||||
members.append(users_group_data) | ||||
Nicolas VINOT
|
r1584 | |||
r2526 | data = repo.get_api_data() | |||
data['members'] = members | ||||
return data | ||||
Nicolas VINOT
|
r1587 | |||
Nicolas VINOT
|
r1593 | @HasPermissionAnyDecorator('hg.admin') | ||
def get_repos(self, apiuser): | ||||
Nicolas VINOT
|
r1586 | """" | ||
Nicolas VINOT
|
r1587 | Get all repositories | ||
Nicolas VINOT
|
r1586 | |||
r1793 | :param apiuser: | |||
Nicolas VINOT
|
r1586 | """ | ||
Nicolas VINOT
|
r1587 | |||
Nicolas VINOT
|
r1586 | result = [] | ||
r2526 | for repo in RepoModel().get_all(): | |||
result.append(repo.get_api_data()) | ||||
Nicolas VINOT
|
r1586 | return result | ||
r1810 | @HasPermissionAnyDecorator('hg.admin') | |||
r2526 | def get_repo_nodes(self, apiuser, repoid, revision, root_path, | |||
r1810 | ret_type='all'): | |||
""" | ||||
returns a list of nodes and it's children | ||||
for a given path at given revision. It's possible to specify ret_type | ||||
to show only files or dirs | ||||
:param apiuser: | ||||
r2526 | :param repoid: name or id of repository | |||
r1810 | :param revision: revision for which listing should be done | |||
:param root_path: path from which start displaying | ||||
:param ret_type: return type 'all|files|dirs' nodes | ||||
""" | ||||
r2526 | repo = get_repo_or_error(repoid) | |||
r1810 | try: | |||
r2526 | _d, _f = ScmModel().get_nodes(repo, revision, root_path, | |||
r1810 | flat=False) | |||
_map = { | ||||
'all': _d + _f, | ||||
'files': _f, | ||||
'dirs': _d, | ||||
} | ||||
return _map[ret_type] | ||||
except KeyError: | ||||
raise JSONRPCError('ret_type must be one of %s' % _map.keys()) | ||||
r2526 | except Exception: | |||
log.error(traceback.format_exc()) | ||||
raise JSONRPCError( | ||||
'failed to get repo: `%s` nodes' % repo.repo_name | ||||
) | ||||
r1810 | ||||
Nicolas VINOT
|
r1593 | @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository') | ||
r2526 | def create_repo(self, apiuser, repo_name, owner, repo_type, | |||
description=Optional(''), private=Optional(False), | ||||
clone_uri=Optional(None), landing_rev=Optional('tip')): | ||||
Nicolas VINOT
|
r1584 | """ | ||
r2006 | Create repository, if clone_url is given it makes a remote clone | |||
r2526 | if repo_name is withina group name the groups will be created | |||
automatically if they aren't present | ||||
Nicolas VINOT
|
r1584 | |||
r1793 | :param apiuser: | |||
r1843 | :param repo_name: | |||
r2526 | :param onwer: | |||
:param repo_type: | ||||
r1793 | :param description: | |||
:param private: | ||||
r2006 | :param clone_uri: | |||
r2526 | :param landing_rev: | |||
Nicolas VINOT
|
r1584 | """ | ||
r2526 | owner = get_user_or_error(owner) | |||
if RepoModel().get_by_repo_name(repo_name): | ||||
raise JSONRPCError("repo `%s` already exist" % repo_name) | ||||
private = Optional.extract(private) | ||||
clone_uri = Optional.extract(clone_uri) | ||||
description = Optional.extract(description) | ||||
landing_rev = Optional.extract(landing_rev) | ||||
Nicolas VINOT
|
r1584 | |||
Nicolas VINOT
|
r1586 | try: | ||
r2526 | # create structure of groups and return the last group | |||
r2120 | group = map_groups(repo_name) | |||
Nicolas VINOT
|
r1589 | |||
r2526 | 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, | ||||
r1793 | ) | |||
r2526 | ||||
Session().commit() | ||||
r1843 | ||||
return dict( | ||||
r2526 | msg="Created new repository `%s`" % (repo.repo_name), | |||
repo=repo.get_api_data() | ||||
r1843 | ) | |||
Nicolas VINOT
|
r1584 | except Exception: | ||
Nicolas VINOT
|
r1593 | log.error(traceback.format_exc()) | ||
r2526 | raise JSONRPCError('failed to create repository `%s`' % repo_name) | |||
r2653 | @HasPermissionAnyDecorator('hg.admin') | |||
def fork_repo(self, apiuser, repoid, fork_name, owner, | ||||
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)) | ||||
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) | ||||
) | ||||
Nicolas VINOT
|
r1584 | |||
Nicolas VINOT
|
r1593 | @HasPermissionAnyDecorator('hg.admin') | ||
r2526 | def delete_repo(self, apiuser, repoid): | |||
r2003 | """ | |||
Deletes a given repository | ||||
r2526 | :param apiuser: | |||
:param repoid: | ||||
r2003 | """ | |||
r2526 | repo = get_repo_or_error(repoid) | |||
r2003 | try: | |||
r2526 | RepoModel().delete(repo) | |||
Session().commit() | ||||
r2003 | return dict( | |||
r2526 | msg='Deleted repository `%s`' % repo.repo_name, | |||
success=True | ||||
r2003 | ) | |||
except Exception: | ||||
log.error(traceback.format_exc()) | ||||
r2526 | raise JSONRPCError( | |||
'failed to delete repository `%s`' % repo.repo_name | ||||
) | ||||
r2003 | ||||
@HasPermissionAnyDecorator('hg.admin') | ||||
r2526 | def grant_user_permission(self, apiuser, repoid, userid, perm): | |||
Nicolas VINOT
|
r1586 | """ | ||
r1982 | Grant permission for user on given repository, or update existing one | |||
if found | ||||
Nicolas VINOT
|
r1584 | |||
r2526 | :param repoid: | |||
:param userid: | ||||
r1793 | :param perm: | |||
Nicolas VINOT
|
r1586 | """ | ||
r2526 | repo = get_repo_or_error(repoid) | |||
user = get_user_or_error(userid) | ||||
perm = get_perm_or_error(perm) | ||||
Nicolas VINOT
|
r1586 | |||
try: | ||||
r1982 | RepoModel().grant_user_permission(repo=repo, user=user, perm=perm) | |||
r2526 | Session().commit() | |||
r1793 | return dict( | |||
r2526 | msg='Granted perm: `%s` for user: `%s` in repo: `%s`' % ( | |||
perm.permission_name, user.username, repo.repo_name | ||||
), | ||||
success=True | ||||
r1793 | ) | |||
Nicolas VINOT
|
r1586 | except Exception: | ||
Nicolas VINOT
|
r1593 | log.error(traceback.format_exc()) | ||
r1793 | raise JSONRPCError( | |||
r2526 | 'failed to edit permission for user: `%s` in repo: `%s`' % ( | |||
userid, repoid | ||||
r1793 | ) | |||
) | ||||
@HasPermissionAnyDecorator('hg.admin') | ||||
r2526 | def revoke_user_permission(self, apiuser, repoid, userid): | |||
r1982 | """ | |||
Revoke permission for user on given repository | ||||
r2526 | :param apiuser: | |||
:param repoid: | ||||
:param userid: | ||||
r1793 | """ | |||
r1982 | ||||
r2526 | repo = get_repo_or_error(repoid) | |||
user = get_user_or_error(userid) | ||||
r1982 | try: | |||
r2526 | ||||
RepoModel().revoke_user_permission(repo=repo, user=user) | ||||
r1982 | ||||
r2526 | Session().commit() | |||
r1982 | return dict( | |||
r2526 | msg='Revoked perm for user: `%s` in repo: `%s`' % ( | |||
user.username, repo.repo_name | ||||
), | ||||
success=True | ||||
r1982 | ) | |||
except Exception: | ||||
log.error(traceback.format_exc()) | ||||
raise JSONRPCError( | ||||
r2526 | 'failed to edit permission for user: `%s` in repo: `%s`' % ( | |||
userid, repoid | ||||
r1982 | ) | |||
) | ||||
@HasPermissionAnyDecorator('hg.admin') | ||||
r2526 | def grant_users_group_permission(self, apiuser, repoid, usersgroupid, | |||
perm): | ||||
r1982 | """ | |||
Grant permission for users group on given repository, or update | ||||
existing one if found | ||||
r2526 | :param apiuser: | |||
:param repoid: | ||||
:param usersgroupid: | ||||
r1793 | :param perm: | |||
""" | ||||
r2526 | repo = get_repo_or_error(repoid) | |||
perm = get_perm_or_error(perm) | ||||
users_group = get_users_group_or_error(usersgroupid) | ||||
r1793 | ||||
try: | ||||
r2526 | RepoModel().grant_users_group_permission(repo=repo, | |||
group_name=users_group, | ||||
r1982 | perm=perm) | |||
r2526 | Session().commit() | |||
r1793 | return dict( | |||
r2526 | msg='Granted perm: `%s` for users group: `%s` in ' | |||
'repo: `%s`' % ( | ||||
perm.permission_name, users_group.users_group_name, | ||||
repo.repo_name | ||||
), | ||||
success=True | ||||
) | ||||
except Exception: | ||||
print traceback.format_exc() | ||||
log.error(traceback.format_exc()) | ||||
raise JSONRPCError( | ||||
'failed to edit permission for users group: `%s` in ' | ||||
'repo: `%s`' % ( | ||||
usersgroupid, repo.repo_name | ||||
r1793 | ) | |||
) | ||||
r2526 | ||||
@HasPermissionAnyDecorator('hg.admin') | ||||
def revoke_users_group_permission(self, apiuser, repoid, usersgroupid): | ||||
""" | ||||
Revoke permission for users group on given repository | ||||
:param apiuser: | ||||
:param repoid: | ||||
:param usersgroupid: | ||||
""" | ||||
repo = get_repo_or_error(repoid) | ||||
users_group = get_users_group_or_error(usersgroupid) | ||||
try: | ||||
RepoModel().revoke_users_group_permission(repo=repo, | ||||
group_name=users_group) | ||||
Session().commit() | ||||
return dict( | ||||
msg='Revoked perm for users group: `%s` in repo: `%s`' % ( | ||||
users_group.users_group_name, repo.repo_name | ||||
), | ||||
success=True | ||||
) | ||||
r1793 | except Exception: | |||
log.error(traceback.format_exc()) | ||||
raise JSONRPCError( | ||||
r2526 | 'failed to edit permission for users group: `%s` in ' | |||
'repo: `%s`' % ( | ||||
users_group.users_group_name, repo.repo_name | ||||
r1793 | ) | |||
) | ||||