changeset 1793:631caf880b87 beta

implements #329 - api function for adding a users_group into repo - fixed found issues on API with missing params detection - updated docs for api
author Marcin Kuzminski <marcin@python-works.com>
date Wed, 21 Dec 2011 01:53:01 +0200
parents 2afa6b8c2ade
children 58e4dbb5884a
files docs/api/api.rst rhodecode/controllers/api/__init__.py rhodecode/controllers/api/api.py rhodecode/model/repo_permission.py
diffstat 4 files changed, 246 insertions(+), 107 deletions(-) [+]
line wrap: on
line diff
--- a/docs/api/api.rst	Mon Dec 19 19:53:08 2011 +0200
+++ b/docs/api/api.rst	Wed Dec 21 01:53:01 2011 +0200
@@ -223,8 +223,8 @@
             }
     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
@@ -302,14 +302,14 @@
 	                                "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)"
                                   },

                                 ]
@@ -356,10 +356,27 @@
     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
--- a/rhodecode/controllers/api/__init__.py	Mon Dec 19 19:53:08 2011 +0200
+++ b/rhodecode/controllers/api/__init__.py	Wed Dec 21 01:53:01 2011 +0200
@@ -46,6 +46,7 @@
 
 log = logging.getLogger('JSONRPC')
 
+
 class JSONRPCError(BaseException):
 
     def __init__(self, message):
@@ -67,19 +68,18 @@
     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):
@@ -111,7 +111,7 @@
         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)))
 
@@ -120,10 +120,10 @@
             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)
 
@@ -146,13 +146,14 @@
         # 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
@@ -167,21 +168,23 @@
                                  (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
@@ -190,6 +193,7 @@
         status = []
         headers = []
         exc_info = []
+
         def change_content(new_status, new_headers, new_exc_info=None):
             status.append(new_status)
             headers.extend(new_headers)
--- a/rhodecode/controllers/api/api.py	Mon Dec 19 19:53:08 2011 +0200
+++ b/rhodecode/controllers/api/api.py	Wed Dec 21 01:53:01 2011 +0200
@@ -60,41 +60,47 @@
         """"
         Get a user by username
 
-        :param apiuser
-        :param username
+        :param apiuser:
+        :param username:
         """
 
         user = User.get_by_username(username)
         if not user:
             return None
 
-        return dict(id=user.user_id,
+        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,
                     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,
-                                username=user.username,
-                                firstname=user.name,
-                                lastname=user.lastname,
-                                email=user.email,
-                                active=user.active,
-                                admin=user.admin,
-                                ldap=user.ldap_dn))
+                    ldap=user.ldap_dn
+                )
+            )
         return result
 
     @HasPermissionAllDecorator('hg.admin')
@@ -131,8 +137,8 @@
         """"
         Get users group by name
 
-        :param apiuser
-        :param group_name
+        :param apiuser:
+        :param group_name:
         """
 
         users_group = UsersGroup.get_by_group_name(group_name)
@@ -161,7 +167,7 @@
         """"
         Get all users groups
 
-        :param apiuser
+        :param apiuser:
         """
 
         result = []
@@ -210,9 +216,9 @@
         """"
         Add a user to a group
 
-        :param apiuser
-        :param group_name
-        :param user_name
+        :param apiuser:
+        :param group_name:
+        :param user_name:
         """
 
         try:
@@ -238,8 +244,8 @@
         """"
         Get repository by name
 
-        :param apiuser
-        :param repo_name
+        :param apiuser:
+        :param repo_name:
         """
 
         repo = Repository.get_by_repo_name(repo_name)
@@ -250,45 +256,59 @@
         for user in repo.repo_to_perm:
             perm = user.permission.permission_name
             user = user.user
-            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))
+            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
+                )
+            )
         for users_group in repo.users_group_to_perm:
             perm = users_group.permission.permission_name
             users_group = users_group.users_group
-            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))
+            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
+                )
+            )
 
-        return dict(id=repo.repo_id,
-                    name=repo.repo_name,
-                    type=repo.repo_type,
-                    description=repo.description,
-                    members=members)
+        return dict(
+            id=repo.repo_id,
+            name=repo.repo_name,
+            type=repo.repo_type,
+            description=repo.description,
+            members=members
+        )
 
     @HasPermissionAnyDecorator('hg.admin')
     def get_repos(self, apiuser):
         """"
         Get all repositories
 
-        :param apiuser
+        :param apiuser:
         """
 
         result = []
         for repository in Repository.getAll():
-            result.append(dict(id=repository.repo_id,
-                                name=repository.repo_name,
-                                type=repository.repo_type,
-                                description=repository.description))
+            result.append(
+                dict(
+                    id=repository.repo_id,
+                    name=repository.repo_name,
+                    type=repository.repo_type,
+                    description=repository.description
+                )
+            )
         return result
 
     @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
@@ -297,12 +317,12 @@
         """
         Create a repository
 
-        :param apiuser
-        :param name
-        :param description
-        :param type
-        :param private
-        :param owner_name
+        :param apiuser:
+        :param name:
+        :param description:
+        :param type:
+        :param private:
+        :param owner_name:
         """
 
         try:
@@ -321,18 +341,27 @@
             for g in groups:
                 group = RepoGroup.get_by_group_name(g)
                 if not group:
-                    group = ReposGroupModel().create(dict(group_name=g,
-                                                  group_description='',
-                                                  group_parent_id=parent_id))
+                    group = ReposGroupModel().create(
+                        dict(
+                            group_name=g,
+                            group_description='',
+                            group_parent_id=parent_id
+                        )
+                    )
                 parent_id = group.group_id
 
-            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)
+            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
+            )
             Session.commit()
         except Exception:
             log.error(traceback.format_exc())
@@ -343,16 +372,16 @@
         """
         Add permission for a user to a repository
 
-        :param apiuser
-        :param repo_name
-        :param user_name
-        :param perm
+        :param apiuser:
+        :param repo_name:
+        :param user_name:
+        :param perm:
         """
 
         try:
             repo = Repository.get_by_repo_name(repo_name)
             if repo is None:
-                raise JSONRPCError('unknown repository %s' % repo)            
+                raise JSONRPCError('unknown repository %s' % repo)
 
             try:
                 user = User.get_by_username(user_name)
@@ -362,8 +391,54 @@
             RepositoryPermissionModel()\
                 .update_or_delete_user_permission(repo, user, perm)
             Session.commit()
+
+            return dict(
+                msg='Added perm: %s for %s in repo: %s' % (
+                    perm, user_name, repo_name
+                )
+            )
         except Exception:
             log.error(traceback.format_exc())
-            raise JSONRPCError('failed to edit permission %(repo)s for %(user)s'
-                            % dict(user=user_name, repo=repo_name))
+            raise JSONRPCError(
+                'failed to edit permission %(repo)s for %(user)s' % dict(
+                    user=user_name, repo=repo_name
+                )
+            )
+
+    @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)
 
+            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
+                )
+            )
--- a/rhodecode/model/repo_permission.py	Mon Dec 19 19:53:08 2011 +0200
+++ b/rhodecode/model/repo_permission.py	Wed Dec 21 01:53:01 2011 +0200
@@ -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
@@ -25,7 +26,7 @@
 
 import logging
 from rhodecode.model import BaseModel
-from rhodecode.model.db import UserRepoToPerm, Permission
+from rhodecode.model.db import UserRepoToPerm, UsersGroupRepoToPerm, Permission
 
 log = logging.getLogger(__name__)
 
@@ -39,6 +40,15 @@
                 .scalar()
 
     def update_user_permission(self, repository, user, permission):
+        
+        #TODO: REMOVE THIS !!
+        ################################
+        import ipdb;ipdb.set_trace()
+        print 'setting ipdb debuggin for rhodecode.model.repo_permission.RepositoryPermissionModel.update_user_permission'
+        ################################
+        
+
+        
         permission = Permission.get_by_key(permission)
         current = self.get_user_permission(repository, user)
         if current:
@@ -56,8 +66,41 @@
         if current:
             self.sa.delete(current)
 
+    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)
+
+    def delete_users_group_permission(self, repository, users_group):
+        current = self.get_users_group_permission(repository, users_group)
+        if current:
+            self.sa.delete(current)
+
     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)
\ No newline at end of file