Changeset - 702e29ce1e9b
[Not reviewed]
default
0 3 0
Marcin Kuzminski - 14 years ago 2011-12-21 01:05:31
marcin@python-works.com
backporting #329 into stable
3 files changed with 107 insertions and 37 deletions:
0 comments (0 inline, 0 general)
docs/api/api.rst
Show inline comments
 
@@ -11,7 +11,7 @@ with JSON protocol both ways. An url to 
 
<your_server>/_admin/api
 

	
 

	
 
All clients need to send JSON data in such format::
 
All clients are required to send JSON-RPC spec JSON data::
 

	
 
    {
 
        "api_key":"<api_key>",
 
@@ -32,7 +32,7 @@ Simply provide
 
    api_key can be found in your user account page
 

	
 

	
 
RhodeCode API will return always a JSON formatted answer::
 
RhodeCode API will return always a JSON-RPC response::
 

	
 
    {
 
        "result": "<result>",
 
@@ -220,8 +220,8 @@ OUTPUT::
 
            }
 
    error:  null
 

	
 
add_user_to_users_groups
 
------------------------
 
add_user_to_users_group
 
-----------------------
 

	
 
Adds a user to a users group. This command can be executed only using api_key
 
belonging to user with admin rights
 
@@ -299,14 +299,14 @@ OUTPUT::
 
	                                "active" :     "<bool>",
 
	                                "admin" :      "<bool>",
 
	                                "ldap" :       "<ldap_dn>",
 
	                                "permission" : "repository_(read|write|admin)"
 
	                                "permission" : "repository.(read|write|admin)"
 
	                              },
 
 
                                  {
 
                                    "id" :       "<usersgroupid>",
 
                                    "name" :     "<usersgroupname>",
 
                                    "active":    "<bool>",
 
                                    "permission" : "repository_(read|write|admin)"
 
                                    "permission" : "repository.(read|write|admin)"
 
                                  },
 
 
                                ]
 
@@ -353,10 +353,27 @@ INPUT::
 
    args:     {
 
                "repo_name" :  "<reponame>",
 
                "user_name" :  "<username>",
 
                "perm" :       "(None|repository_(read|write|admin))",
 
                "perm" :       "(None|repository.(read|write|admin))",
 
              }
 

	
 
OUTPUT::
 

	
 
    result: None
 
    error:  null
 

	
 
add_users_group_to_repo
 
-----------------------
 

	
 
Add a users group to a repository. This command can be executed only using 
 
api_key belonging to user with admin rights. If "perm" is None, group will 
 
be removed from the repository.
 

	
 
INPUT::
 

	
 
    api_key : "<api_key>"
 
    method :  "add_users_group_to_repo"
 
    args:     {
 
                "repo_name" :  "<reponame>",
 
                "group_name" :  "<groupname>",
 
                "perm" :       "(None|repository.(read|write|admin))",
 
              }
 
\ No newline at end of file
rhodecode/controllers/api/__init__.py
Show inline comments
 
@@ -4,7 +4,7 @@
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    JSON RPC controller
 
    
 

	
 
    :created_on: Aug 20, 2011
 
    :author: marcink
 
    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
 
@@ -36,7 +36,7 @@ from rhodecode.lib.compat import izip_lo
 
from paste.response import replace_header
 

	
 
from pylons.controllers import WSGIController
 
from pylons.controllers.util import Response
 

	
 

	
 
from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
 
HTTPBadRequest, HTTPError
 
@@ -46,33 +46,40 @@ from rhodecode.lib.auth import AuthUser
 

	
 
log = logging.getLogger('JSONRPC')
 

	
 

	
 
class JSONRPCError(BaseException):
 

	
 
    def __init__(self, message):
 
        self.message = message
 
        super(JSONRPCError, self).__init__()
 

	
 
    def __str__(self):
 
        return str(self.message)
 

	
 

	
 
def jsonrpc_error(message, code=None):
 
    """Generate a Response object with a JSON-RPC error body"""
 
    return Response(body=json.dumps(dict(result=None,
 
                                         error=message)))
 
    """
 
    Generate a Response object with a JSON-RPC error body
 
    """
 
    from pylons.controllers.util import Response
 
    resp = Response(body=json.dumps(dict(result=None, error=message)),
 
                    status=code,
 
                    content_type='application/json')
 
    return resp
 

	
 

	
 
class JSONRPCController(WSGIController):
 
    """
 
     A WSGI-speaking JSON-RPC controller class
 
    
 

	
 
     See the specification:
 
     <http://json-rpc.org/wiki/specification>`.
 
   
 

	
 
     Valid controller return values should be json-serializable objects.
 
    
 

	
 
     Sub-classes should catch their exceptions and raise JSONRPCError
 
     if they want to pass meaningful errors to the client.
 
    
 

	
 
     """
 

	
 
    def _get_method_args(self):
 
@@ -104,24 +111,27 @@ class JSONRPCController(WSGIController):
 
        try:
 
            json_body = json.loads(urllib.unquote_plus(raw_body))
 
        except ValueError, e:
 
            #catch JSON errors Here
 
            # catch JSON errors Here
 
            return jsonrpc_error(message="JSON parse error ERR:%s RAW:%r" \
 
                                 % (e, urllib.unquote_plus(raw_body)))
 

	
 
        #check AUTH based on API KEY
 
        # check AUTH based on API KEY
 
        try:
 
            self._req_api_key = json_body['api_key']
 
            self._req_id = json_body['id']
 
            self._req_method = json_body['method']
 
            self._req_params = json_body['args']
 
            self._request_params = json_body['args']
 
            log.debug('method: %s, params: %s',
 
                      self._req_method,
 
                      self._req_params)
 
                      self._request_params)
 
        except KeyError, e:
 
            return jsonrpc_error(message='Incorrect JSON query missing %s' % e)
 

	
 
        #check if we can find this session using api_key
 
        # check if we can find this session using api_key
 
        try:
 
            u = User.get_by_api_key(self._req_api_key)
 
            if u is None:
 
                return jsonrpc_error(message='Invalid API KEY')
 
            auth_u = AuthUser(u.user_id, self._req_api_key)
 
        except Exception, e:
 
            return jsonrpc_error(message='Invalid API KEY')
 
@@ -136,13 +146,14 @@ class JSONRPCController(WSGIController):
 
        # self.kargs and dispatch control to WGIController
 
        argspec = inspect.getargspec(self._func)
 
        arglist = argspec[0][1:]
 
        defaults = argspec[3] or []
 
        defaults = map(type, argspec[3] or [])
 
        default_empty = types.NotImplementedType
 

	
 
        kwarglist = list(izip_longest(reversed(arglist), reversed(defaults),
 
                                fillvalue=default_empty))
 
        # kw arguments required by this method
 
        func_kwargs = dict(izip_longest(reversed(arglist), reversed(defaults),
 
                                        fillvalue=default_empty))
 

	
 
        # this is little trick to inject logged in user for 
 
        # this is little trick to inject logged in user for
 
        # perms decorators to work they expect the controller class to have
 
        # rhodecode_user attribute set
 
        self.rhodecode_user = auth_u
 
@@ -157,21 +168,23 @@ class JSONRPCController(WSGIController):
 
                                 (self._func.__name__, USER_SESSION_ATTR))
 

	
 
        # get our arglist and check if we provided them as args
 
        for arg, default in kwarglist:
 
        for arg, default in func_kwargs.iteritems():
 
            if arg == USER_SESSION_ATTR:
 
                # USER_SESSION_ATTR is something translated from api key and 
 
                # USER_SESSION_ATTR is something translated from api key and
 
                # this is checked before so we don't need validate it
 
                continue
 

	
 
            # skip the required param check if it's default value is 
 
            # skip the required param check if it's default value is
 
            # NotImplementedType (default_empty)
 
            if not self._req_params or (type(default) == default_empty
 
                                        and arg not in self._req_params):
 
                return jsonrpc_error(message=('Missing non optional %s arg '
 
                                              'in JSON DATA') % arg)
 
            if (default == default_empty and arg not in self._request_params):
 
                return jsonrpc_error(
 
                    message=(
 
                        'Missing non optional `%s` arg in JSON DATA' % arg
 
                    )
 
                )
 

	
 
        self._rpc_args = {USER_SESSION_ATTR:u}
 
        self._rpc_args.update(self._req_params)
 
        self._rpc_args = {USER_SESSION_ATTR: u}
 
        self._rpc_args.update(self._request_params)
 

	
 
        self._rpc_args['action'] = self._req_method
 
        self._rpc_args['environ'] = environ
 
@@ -180,6 +193,7 @@ class JSONRPCController(WSGIController):
 
        status = []
 
        headers = []
 
        exc_info = []
 

	
 
        def change_content(new_status, new_headers, new_exc_info=None):
 
            status.append(new_status)
 
            headers.extend(new_headers)
 
@@ -212,7 +226,8 @@ class JSONRPCController(WSGIController):
 
        if self._error is not None:
 
            raw_response = None
 

	
 
        response = dict(result=raw_response, error=self._error)
 
        response = dict(result=raw_response,
 
                        error=self._error)
 

	
 
        try:
 
            return json.dumps(response)
rhodecode/model/repo_permission.py
Show inline comments
 
@@ -6,8 +6,9 @@
 
    repository permission model for RhodeCode
 

	
 
    :created_on: Oct 1, 2011
 
    :author: nvinot
 
    :author: nvinot, marcink
 
    :copyright: (C) 2011-2011 Nicolas Vinot <aeris@imirhil.fr>
 
    :copyright: (C) 2009-2011 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
 
@@ -24,11 +25,13 @@
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 

	
 
import logging
 
from rhodecode.model.db import BaseModel, RepoToPerm, Permission
 
from rhodecode.model.db import BaseModel, RepoToPerm, Permission,\
 
    UsersGroupRepoToPerm
 
from rhodecode.model.meta import Session
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class RepositoryPermissionModel(BaseModel):
 
    def get_user_permission(self, repository, user):
 
        return RepoToPerm.query() \
 
@@ -56,8 +59,43 @@ class RepositoryPermissionModel(BaseMode
 
            Session.delete(current)
 
            Session.commit()
 

	
 
    def get_users_group_permission(self, repository, users_group):
 
        return UsersGroupRepoToPerm.query() \
 
                .filter(UsersGroupRepoToPerm.users_group == users_group) \
 
                .filter(UsersGroupRepoToPerm.repository == repository) \
 
                .scalar()
 

	
 
    def update_users_group_permission(self, repository, users_group,
 
                                      permission):
 
        permission = Permission.get_by_key(permission)
 
        current = self.get_users_group_permission(repository, users_group)
 
        if current:
 
            if not current.permission is permission:
 
                current.permission = permission
 
        else:
 
            p = UsersGroupRepoToPerm()
 
            p.users_group = users_group
 
            p.repository = repository
 
            p.permission = permission
 
            self.sa.add(p)
 
        Session.commit()
 

	
 
    def delete_users_group_permission(self, repository, users_group):
 
        current = self.get_users_group_permission(repository, users_group)
 
        if current:
 
            self.sa.delete(current)
 
        Session.commit()
 

	
 
    def update_or_delete_user_permission(self, repository, user, permission):
 
        if permission:
 
            self.update_user_permission(repository, user, permission)
 
        else:
 
            self.delete_user_permission(repository, user)
 

	
 
    def update_or_delete_users_group_permission(self, repository, user_group,
 
                                              permission):
 
        if permission:
 
            self.update_users_group_permission(repository, user_group,
 
                                               permission)
 
        else:
 
            self.delete_users_group_permission(repository, user_group)
0 comments (0 inline, 0 general)