##// END OF EJS Templates
changeset: styling a bit
changeset: styling a bit

File last commit:

r1843:0771f0f5 beta
r1858:609ec28b beta
Show More
api.py
499 lines | 15.6 KiB | text/x-python | PythonLexer
2012 copyrights
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.
Extended API...
r1500 import traceback
import logging
another major refactoring with session management
r1734 from sqlalchemy.orm.exc import NoResultFound
Beginning of API implementation for rhodecode
r1445 from rhodecode.controllers.api import JSONRPCController, JSONRPCError
fixes #288...
r1594 from rhodecode.lib.auth import HasPermissionAllDecorator, \
HasPermissionAnyDecorator
another major refactoring with session management
r1734
from rhodecode.model.meta import Session
Beginning of API implementation for rhodecode
r1445 from rhodecode.model.scm import ScmModel
refactoring of models names for repoGroup permissions
r1633 from rhodecode.model.db import User, UsersGroup, RepoGroup, Repository
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 from rhodecode.model.repo import RepoModel
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 from rhodecode.model.user import UserModel
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 from rhodecode.model.repo_permission import RepositoryPermissionModel
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 from rhodecode.model.users_group import UsersGroupModel
Nicolas VINOT
[API] Create groups needed when creating repo
r1589 from rhodecode.model.repos_group import ReposGroupModel
another major refactoring with session management
r1734
Extended API...
r1500
Nicolas VINOT
Correct code style
r1593 log = logging.getLogger(__name__)
Extended API...
r1500
Beginning of API implementation for rhodecode
r1445
Nicolas VINOT
Correct code style
r1593 class ApiController(JSONRPCController):
Beginning of API implementation for rhodecode
r1445 """
API Controller
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Beginning of API implementation for rhodecode
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
Improve API with user/group/repo CRUD methods
r1584
Beginning of API implementation for rhodecode
r1445 Preferably this should be first argument also
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Each function should also **raise** JSONRPCError for any
Beginning of API implementation for rhodecode
r1445 errors that happens
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Beginning of API implementation for rhodecode
r1445 """
Nicolas VINOT
Correct code style
r1593 @HasPermissionAllDecorator('hg.admin')
def pull(self, apiuser, repo):
Beginning of API implementation for rhodecode
r1445 """
Dispatch pull action on given repo
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Extended API...
r1500 :param user:
:param repo:
Beginning of API implementation for rhodecode
r1445 """
Nicolas VINOT
Correct code style
r1593 if Repository.is_valid(repo) is False:
raise JSONRPCError('Unknown repo "%s"' % repo)
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
Beginning of API implementation for rhodecode
r1445 try:
Nicolas VINOT
Correct code style
r1593 ScmModel().pull_changes(repo, self.rhodecode_user.username)
Beginning of API implementation for rhodecode
r1445 return 'Pulled from %s' % repo
except Exception:
Nicolas VINOT
Correct code style
r1593 raise JSONRPCError('Unable to pull changes from "%s"' % repo)
Beginning of API implementation for rhodecode
r1445
Nicolas VINOT
Correct code style
r1593 @HasPermissionAllDecorator('hg.admin')
def get_user(self, apiuser, username):
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 """"
Get a user by username
implements #329...
r1793 :param apiuser:
:param username:
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 """
Beginning of API implementation for rhodecode
r1445
Nicolas VINOT
Correct code style
r1593 user = User.get_by_username(username)
Nicolas VINOT
Merge with upstream
r1591 if not user:
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 return None
implements #329...
r1793 return dict(
id=user.user_id,
username=user.username,
firstname=user.name,
lastname=user.lastname,
email=user.email,
active=user.active,
admin=user.admin,
ldap=user.ldap_dn
)
@HasPermissionAllDecorator('hg.admin')
def get_users(self, apiuser):
""""
Get all users
:param apiuser:
"""
result = []
for user in User.getAll():
result.append(
dict(
id=user.user_id,
notification to commit author + gardening
r1716 username=user.username,
firstname=user.name,
lastname=user.lastname,
email=user.email,
active=user.active,
admin=user.admin,
implements #329...
r1793 ldap=user.ldap_dn
)
)
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 return result
Nicolas VINOT
Correct code style
r1593 @HasPermissionAllDecorator('hg.admin')
def create_user(self, apiuser, username, password, firstname,
fixes #288...
r1594 lastname, email, active=True, admin=False, ldap_dn=None):
Extended API...
r1500 """
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 Create new user
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Extended API...
r1500 :param apiuser:
:param username:
:param password:
:param name:
:param lastname:
:param email:
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 :param active:
:param admin:
:param ldap_dn:
Extended API...
r1500 """
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
notification to commit author + gardening
r1716 if User.get_by_username(username):
Nicolas VINOT
Correct code style
r1593 raise JSONRPCError("user %s already exist" % username)
Nicolas VINOT
[API] Create groups needed when creating repo
r1589
Extended API...
r1500 try:
another major refactoring with session management
r1734 UserModel().create_or_update(username, password, email, firstname,
API create user use UserModel new method
r1649 lastname, active, admin, ldap_dn)
commit less models...
r1749 Session.commit()
fixes #288...
r1594 return dict(msg='created new user %s' % username)
Extended API...
r1500 except Exception:
Nicolas VINOT
Correct code style
r1593 log.error(traceback.format_exc())
raise JSONRPCError('failed to create user %s' % username)
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
Nicolas VINOT
Correct code style
r1593 @HasPermissionAllDecorator('hg.admin')
def get_users_group(self, apiuser, group_name):
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 """"
Get users group by name
implements #329...
r1793 :param apiuser:
:param group_name:
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 """
Nicolas VINOT
Correct code style
r1593 users_group = UsersGroup.get_by_group_name(group_name)
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 if not users_group:
return None
Beginning of API implementation for rhodecode
r1445
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 members = []
for user in users_group.members:
user = user.user
fixes #288...
r1594 members.append(dict(id=user.user_id,
username=user.username,
firstname=user.name,
lastname=user.lastname,
email=user.email,
active=user.active,
admin=user.admin,
ldap=user.ldap_dn))
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
fixes #288...
r1594 return dict(id=users_group.users_group_id,
name=users_group.users_group_name,
active=users_group.users_group_active,
members=members)
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
Nicolas VINOT
Correct code style
r1593 @HasPermissionAllDecorator('hg.admin')
def get_users_groups(self, apiuser):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 """"
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 Get all users groups
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
implements #329...
r1793 :param apiuser:
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 """
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 result = []
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 for users_group in UsersGroup.getAll():
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 members = []
for user in users_group.members:
user = user.user
fixes #288...
r1594 members.append(dict(id=user.user_id,
username=user.username,
firstname=user.name,
lastname=user.lastname,
email=user.email,
active=user.active,
admin=user.admin,
ldap=user.ldap_dn))
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
fixes #288...
r1594 result.append(dict(id=users_group.users_group_id,
name=users_group.users_group_name,
active=users_group.users_group_active,
members=members))
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 return result
Nicolas VINOT
Correct code style
r1593 @HasPermissionAllDecorator('hg.admin')
fixes #288...
r1594 def create_users_group(self, apiuser, name, active=True):
Extended API...
r1500 """
Creates an new usergroup
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Extended API...
r1500 :param name:
:param active:
"""
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586
Nicolas VINOT
Correct code style
r1593 if self.get_users_group(apiuser, name):
raise JSONRPCError("users group %s already exist" % name)
Nicolas VINOT
[API] Create groups needed when creating repo
r1589
Extended API...
r1500 try:
another major refactoring with session management
r1734 ug = UsersGroupModel().create(name=name, active=active)
commit less models...
r1749 Session.commit()
fixes #288...
r1594 return dict(id=ug.users_group_id,
msg='created new users group %s' % name)
Extended API...
r1500 except Exception:
Nicolas VINOT
Correct code style
r1593 log.error(traceback.format_exc())
raise JSONRPCError('failed to create group %s' % name)
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Nicolas VINOT
Correct code style
r1593 @HasPermissionAllDecorator('hg.admin')
implements #330 api method for listing nodes at particular revision...
r1810 def add_user_to_users_group(self, apiuser, group_name, username):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 """"
Add a user to a group
implements #329...
r1793 :param apiuser:
:param group_name:
implements #330 api method for listing nodes at particular revision...
r1810 :param username:
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 """
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 try:
Nicolas VINOT
Correct code style
r1593 users_group = UsersGroup.get_by_group_name(group_name)
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 if not users_group:
Nicolas VINOT
Correct code style
r1593 raise JSONRPCError('unknown users group %s' % group_name)
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
Nicolas VINOT
[API] Create groups needed when creating repo
r1589 try:
implements #330 api method for listing nodes at particular revision...
r1810 user = User.get_by_username(username)
Nicolas VINOT
[API] Create groups needed when creating repo
r1589 except NoResultFound:
implements #330 api method for listing nodes at particular revision...
r1810 raise JSONRPCError('unknown user %s' % username)
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
Nicolas VINOT
Correct code style
r1593 ugm = UsersGroupModel().add_user_to_group(users_group, user)
commit less models...
r1749 Session.commit()
fixes #288...
r1594 return dict(id=ugm.users_group_member_id,
msg='created new users group member')
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 except Exception:
Nicolas VINOT
Correct code style
r1593 log.error(traceback.format_exc())
raise JSONRPCError('failed to create users group member')
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
Nicolas VINOT
Correct code style
r1593 @HasPermissionAnyDecorator('hg.admin')
def get_repo(self, apiuser, repo_name):
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 """"
Get repository by name
implements #329...
r1793 :param apiuser:
:param repo_name:
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 """
commit less models...
r1749 repo = Repository.get_by_repo_name(repo_name)
if repo is None:
raise JSONRPCError('unknown repository %s' % repo)
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 members = []
for user in repo.repo_to_perm:
perm = user.permission.permission_name
user = user.user
implements #329...
r1793 members.append(
dict(
type_="user",
id=user.user_id,
username=user.username,
firstname=user.name,
lastname=user.lastname,
email=user.email,
active=user.active,
admin=user.admin,
ldap=user.ldap_dn,
permission=perm
)
)
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 for users_group in repo.users_group_to_perm:
perm = users_group.permission.permission_name
users_group = users_group.users_group
implements #329...
r1793 members.append(
dict(
type_="users_group",
id=users_group.users_group_id,
name=users_group.users_group_name,
active=users_group.users_group_active,
permission=perm
)
)
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
implements #329...
r1793 return dict(
id=repo.repo_id,
name=repo.repo_name,
type=repo.repo_type,
description=repo.description,
members=members
)
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
Nicolas VINOT
Correct code style
r1593 @HasPermissionAnyDecorator('hg.admin')
def get_repos(self, apiuser):
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 """"
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 Get all repositories
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586
implements #329...
r1793 :param apiuser:
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 """
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 result = []
for repository in Repository.getAll():
implements #329...
r1793 result.append(
dict(
id=repository.repo_id,
name=repository.repo_name,
type=repository.repo_type,
description=repository.description
)
)
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 return result
implements #330 api method for listing nodes at particular revision...
r1810 @HasPermissionAnyDecorator('hg.admin')
def get_repo_nodes(self, apiuser, repo_name, revision, root_path,
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:
:param repo_name: name of repository
: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
"""
try:
_d, _f = ScmModel().get_nodes(repo_name, revision, root_path,
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())
except Exception, e:
raise JSONRPCError(e)
Nicolas VINOT
Correct code style
r1593 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
another major refactoring with session management
r1734 def create_repo(self, apiuser, name, owner_name, description='',
fixes #288...
r1594 repo_type='hg', private=False):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 """
Create a repository
implements #329...
r1793 :param apiuser:
:param name:
:param description:
:param type:
:param private:
:param owner_name:
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 """
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 try:
Nicolas VINOT
[API] Create groups needed when creating repo
r1589 try:
Nicolas VINOT
Correct code style
r1593 owner = User.get_by_username(owner_name)
Nicolas VINOT
[API] Create groups needed when creating repo
r1589 except NoResultFound:
Nicolas VINOT
Correct code style
r1593 raise JSONRPCError('unknown user %s' % owner)
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Nicolas VINOT
Correct code style
r1593 if self.get_repo(apiuser, name):
raise JSONRPCError("repo %s already exist" % name)
Nicolas VINOT
[API] Create groups needed when creating repo
r1589
Nicolas VINOT
Correct code style
r1593 groups = name.split('/')
Nicolas VINOT
[API] Create groups needed when creating repo
r1589 real_name = groups[-1]
groups = groups[:-1]
parent_id = None
for g in groups:
refactoring of models names for repoGroup permissions
r1633 group = RepoGroup.get_by_group_name(g)
Nicolas VINOT
[API] Create groups needed when creating repo
r1589 if not group:
implements #329...
r1793 group = ReposGroupModel().create(
dict(
group_name=g,
group_description='',
group_parent_id=parent_id
)
)
Nicolas VINOT
[API] Create groups needed when creating repo
r1589 parent_id = group.group_id
implements #329...
r1793 RepoModel().create(
dict(
repo_name=real_name,
repo_name_full=name,
description=description,
private=private,
repo_type=repo_type,
repo_group=parent_id,
clone_uri=None
),
owner
)
commit less models...
r1749 Session.commit()
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 except Exception:
Nicolas VINOT
Correct code style
r1593 log.error(traceback.format_exc())
raise JSONRPCError('failed to create repository %s' % name)
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Nicolas VINOT
Correct code style
r1593 @HasPermissionAnyDecorator('hg.admin')
implements #330 api method for listing nodes at particular revision...
r1810 def add_user_to_repo(self, apiuser, repo_name, username, perm):
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 """
Add permission for a user to a repository
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
implements #329...
r1793 :param apiuser:
:param repo_name:
implements #330 api method for listing nodes at particular revision...
r1810 :param username:
implements #329...
r1793 :param perm:
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 """
try:
commit less models...
r1749 repo = Repository.get_by_repo_name(repo_name)
if repo is None:
implements #329...
r1793 raise JSONRPCError('unknown repository %s' % repo)
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586
Nicolas VINOT
[API] Create groups needed when creating repo
r1589 try:
implements #330 api method for listing nodes at particular revision...
r1810 user = User.get_by_username(username)
Nicolas VINOT
[API] Create groups needed when creating repo
r1589 except NoResultFound:
Nicolas VINOT
Correct code style
r1593 raise JSONRPCError('unknown user %s' % user)
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586
fixes #288...
r1594 RepositoryPermissionModel()\
.update_or_delete_user_permission(repo, user, perm)
commit less models...
r1749 Session.commit()
implements #329...
r1793
return dict(
msg='Added perm: %s for %s in repo: %s' % (
implements #330 api method for listing nodes at particular revision...
r1810 perm, username, repo_name
implements #329...
r1793 )
)
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586 except Exception:
Nicolas VINOT
Correct code style
r1593 log.error(traceback.format_exc())
implements #329...
r1793 raise JSONRPCError(
'failed to edit permission %(repo)s for %(user)s' % dict(
implements #330 api method for listing nodes at particular revision...
r1810 user=username, repo=repo_name
implements #329...
r1793 )
)
@HasPermissionAnyDecorator('hg.admin')
def add_users_group_to_repo(self, apiuser, repo_name, group_name, perm):
"""
Add permission for a users group to a repository
:param apiuser:
:param repo_name:
:param group_name:
:param perm:
"""
try:
repo = Repository.get_by_repo_name(repo_name)
if repo is None:
raise JSONRPCError('unknown repository %s' % repo)
Nicolas VINOT
Add API for repositories and groups (creation, permission)
r1586
implements #329...
r1793 try:
user_group = UsersGroup.get_by_group_name(group_name)
except NoResultFound:
raise JSONRPCError('unknown users group %s' % user_group)
RepositoryPermissionModel()\
.update_or_delete_users_group_permission(repo, user_group,
perm)
Session.commit()
return dict(
msg='Added perm: %s for %s in repo: %s' % (
perm, group_name, repo_name
)
)
except Exception:
log.error(traceback.format_exc())
raise JSONRPCError(
'failed to edit permission %(repo)s for %(usergr)s' % dict(
usergr=group_name, repo=repo_name
)
)