changeset 3788:d9b89874edf9 beta

UserGroup on UserGroup permissions implementation. - user group can have another usergroup assigned - it's impossible to assign usergroup on the same usergroup
author Marcin Kuzminski <marcin@python-works.com>
date Tue, 23 Apr 2013 02:18:31 +0200
parents a3b1016855f8
children 32f66c839c54
files rhodecode/controllers/admin/users_groups.py rhodecode/lib/exceptions.py rhodecode/lib/vcs/exceptions.py rhodecode/model/db.py rhodecode/model/user.py rhodecode/model/users_group.py rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html rhodecode/templates/admin/users_groups/user_group_edit_perms.html
diffstat 8 files changed, 125 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/controllers/admin/users_groups.py	Tue Apr 23 00:56:04 2013 +0200
+++ b/rhodecode/controllers/admin/users_groups.py	Tue Apr 23 02:18:31 2013 +0200
@@ -33,7 +33,8 @@
 from pylons.i18n.translation import _
 
 from rhodecode.lib import helpers as h
-from rhodecode.lib.exceptions import UserGroupsAssignedException
+from rhodecode.lib.exceptions import UserGroupsAssignedException,\
+    RepoGroupAssignmentError
 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator,\
     HasUserGroupPermissionAnyDecorator, HasPermissionAnyDecorator
@@ -94,10 +95,7 @@
                                      key=lambda u: u[1].lower())
         repo_model = RepoModel()
         c.users_array = repo_model.get_users_js()
-
-        # commented out due to not now supporting assignment for user group
-        # on user group
-        c.users_groups_array = "[]"  # repo_model.get_users_groups_js()
+        c.users_groups_array = repo_model.get_users_groups_js()
         c.available_permissions = config['available_permissions']
 
     def __load_defaults(self, user_group_id):
@@ -125,6 +123,10 @@
             data.update({'u_perm_%s' % p.user.username:
                              p.permission.permission_name})
 
+        for p in user_group.user_group_user_group_to_perm:
+            data.update({'g_perm_%s' % p.user_group.users_group_name:
+                             p.permission.permission_name})
+
         return data
 
     def index(self, format='html'):
@@ -261,8 +263,12 @@
         form = UserGroupPermsForm()().to_python(request.POST)
 
         # set the permissions !
-        UserGroupModel()._update_permissions(user_group, form['perms_new'],
-                                            form['perms_updates'])
+        try:
+            UserGroupModel()._update_permissions(user_group, form['perms_new'],
+                                                 form['perms_updates'])
+        except RepoGroupAssignmentError:
+            h.flash(_('Target group cannot be the same'), category='error')
+            return redirect(url('edit_users_group', id=id))
         #TODO: implement this
         #action_logger(self.rhodecode_user, 'admin_changed_repo_permissions',
         #              repo_name, self.ip_addr, self.sa)
@@ -294,7 +300,8 @@
                 UserGroupModel().revoke_user_permission(user_group=id,
                                                         user=obj_id)
             elif obj_type == 'user_group':
-                pass
+                UserGroupModel().revoke_users_group_permission(target_user_group=id,
+                                                               user_group=obj_id)
             Session().commit()
         except Exception:
             log.error(traceback.format_exc())
--- a/rhodecode/lib/exceptions.py	Tue Apr 23 00:56:04 2013 +0200
+++ b/rhodecode/lib/exceptions.py	Tue Apr 23 02:18:31 2013 +0200
@@ -62,6 +62,10 @@
     pass
 
 
+class RepoGroupAssignmentError(Exception):
+    pass
+
+
 class HTTPLockedRC(HTTPClientError):
     """
     Special Exception For locked Repos in RhodeCode, the return code can
--- a/rhodecode/lib/vcs/exceptions.py	Tue Apr 23 00:56:04 2013 +0200
+++ b/rhodecode/lib/vcs/exceptions.py	Tue Apr 23 02:18:31 2013 +0200
@@ -89,5 +89,6 @@
 class ImproperArchiveTypeError(VCSError):
     pass
 
+
 class CommandError(VCSError):
     pass
--- a/rhodecode/model/db.py	Tue Apr 23 00:56:04 2013 +0200
+++ b/rhodecode/model/db.py	Tue Apr 23 02:18:31 2013 +0200
@@ -639,6 +639,8 @@
     users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
     users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
     user_user_group_to_perm = relationship('UserUserGroupToPerm ', cascade='all')
+    user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
+
     user = relationship('User')
 
     def __unicode__(self):
@@ -1617,24 +1619,24 @@
         return n
 
     def __unicode__(self):
-        return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
+        return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
 
 
-#TODO; not sure if this will be ever used
 class UserGroupUserGroupToPerm(Base, BaseModel):
     __tablename__ = 'user_group_user_group_to_perm'
     __table_args__ = (
-        UniqueConstraint('user_group_id', 'user_group_id', 'permission_id'),
+        UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
+        CheckConstraint('target_user_group_id != user_group_id'),
         {'extend_existing': True, 'mysql_engine': 'InnoDB',
          'mysql_charset': 'utf8'}
     )
-    user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
-    target_user_group_id = Column("target_users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
+    user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
+    target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
     permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
     user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
-    target_user_group = relationship('UserGroup', remote_side=target_user_group_id, primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
-    user_group = relationship('UserGroup', remote_side=user_group_id, primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
+    target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
+    user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
     permission = relationship('Permission')
 
     @classmethod
@@ -1647,7 +1649,7 @@
         return n
 
     def __unicode__(self):
-        return u'<UserGroup:%s => %s >' % (self.target_user_group, self.user_group)
+        return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
 
 
 class UserGroupToPerm(Base, BaseModel):
--- a/rhodecode/model/user.py	Tue Apr 23 00:56:04 2013 +0200
+++ b/rhodecode/model/user.py	Tue Apr 23 02:18:31 2013 +0200
@@ -39,7 +39,7 @@
 from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \
     UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \
     Notification, RepoGroup, UserRepoGroupToPerm, UserGroupRepoGroupToPerm, \
-    UserEmailMap, UserIpMap
+    UserEmailMap, UserIpMap, UserGroupUserGroupToPerm, UserGroup
 from rhodecode.lib.exceptions import DefaultUserException, \
     UserOwnsReposException
 from rhodecode.model.meta import Session
@@ -570,7 +570,6 @@
                 user.permissions[GLOBAL].add(perm.permission.permission_name)
         ## END GLOBAL PERMISSIONS
 
-
         #======================================================================
         # !! PERMISSIONS FOR REPOSITORIES !!
         #======================================================================
@@ -664,6 +663,28 @@
         #======================================================================
         # !! PERMISSIONS FOR USER GROUPS !!
         #======================================================================
+        # user group for user group permissions
+        user_group_user_groups_perms = \
+         self.sa.query(UserGroupUserGroupToPerm, Permission, UserGroup)\
+         .join((UserGroup, UserGroupUserGroupToPerm.target_user_group_id
+                == UserGroup.users_group_id))\
+         .join((Permission, UserGroupUserGroupToPerm.permission_id
+                == Permission.permission_id))\
+         .join((UserGroupMember, UserGroupUserGroupToPerm.user_group_id
+                == UserGroupMember.users_group_id))\
+         .filter(UserGroupMember.user_id == uid)\
+         .all()
+
+        multiple_counter = collections.defaultdict(int)
+        for perm in user_group_user_groups_perms:
+            g_k = perm.UserGroupUserGroupToPerm.target_user_group.users_group_name
+            multiple_counter[g_k] += 1
+            p = perm.Permission.permission_name
+            cur_perm = user.permissions[UK][g_k]
+            if multiple_counter[g_k] > 1:
+                p = _choose_perm(p, cur_perm)
+            user.permissions[UK][g_k] = p
+
         #user explicit permission for user groups
         user_user_groups_perms = Permission.get_default_user_group_perms(uid)
         for perm in user_user_groups_perms:
--- a/rhodecode/model/users_group.py	Tue Apr 23 00:56:04 2013 +0200
+++ b/rhodecode/model/users_group.py	Tue Apr 23 02:18:31 2013 +0200
@@ -29,8 +29,10 @@
 
 from rhodecode.model import BaseModel
 from rhodecode.model.db import UserGroupMember, UserGroup,\
-    UserGroupRepoToPerm, Permission, UserGroupToPerm, User, UserUserGroupToPerm
-from rhodecode.lib.exceptions import UserGroupsAssignedException
+    UserGroupRepoToPerm, Permission, UserGroupToPerm, User, UserUserGroupToPerm,\
+    UserGroupUserGroupToPerm
+from rhodecode.lib.exceptions import UserGroupsAssignedException,\
+    RepoGroupAssignmentError
 
 log = logging.getLogger(__name__)
 
@@ -75,7 +77,7 @@
                 )
             else:
                 self.grant_users_group_permission(
-                    user_group=user_group, group_name=member, perm=perm
+                    target_user_group=user_group, user_group=member, perm=perm
                 )
         # set new permissions
         for member, perm, member_type in perms_new:
@@ -85,7 +87,7 @@
                 )
             else:
                 self.grant_users_group_permission(
-                    user_group=user_group, group_name=member, perm=perm
+                    target_user_group=user_group, user_group=member, perm=perm
                 )
 
     def get(self, users_group_id, cache=False):
@@ -292,8 +294,50 @@
             self.sa.delete(obj)
             log.debug('Revoked perm on %s on %s' % (user_group, user))
 
-    def grant_users_group_permission(self, user_group, group_name, perm):
-        raise NotImplementedError()
+    def grant_users_group_permission(self, target_user_group, user_group, perm):
+        """
+        Grant user group permission for given target_user_group
+
+        :param target_user_group:
+        :param user_group:
+        :param perm:
+        """
+        target_user_group = self._get_user_group(target_user_group)
+        user_group = self._get_user_group(user_group)
+        permission = self._get_perm(perm)
+        # forbid assigning same user group to itself
+        if target_user_group == user_group:
+            raise RepoGroupAssignmentError('target repo:%s cannot be '
+                                           'assigned to itself' % target_user_group)
 
-    def revoke_users_group_permission(self, user_group, group_name):
-        raise NotImplementedError()
+        # check if we have that permission already
+        obj = self.sa.query(UserGroupUserGroupToPerm)\
+            .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
+            .filter(UserGroupUserGroupToPerm.user_group == user_group)\
+            .scalar()
+        if obj is None:
+            # create new !
+            obj = UserGroupUserGroupToPerm()
+        obj.user_group = user_group
+        obj.target_user_group = target_user_group
+        obj.permission = permission
+        self.sa.add(obj)
+        log.debug('Granted perm %s to %s on %s' % (perm, target_user_group, user_group))
+
+    def revoke_users_group_permission(self, target_user_group, user_group):
+        """
+        Revoke user group permission for given target_user_group
+
+        :param target_user_group:
+        :param user_group:
+        """
+        target_user_group = self._get_user_group(target_user_group)
+        user_group = self._get_user_group(user_group)
+
+        obj = self.sa.query(UserGroupUserGroupToPerm)\
+            .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
+            .filter(UserGroupUserGroupToPerm.user_group == user_group)\
+            .scalar()
+        if obj:
+            self.sa.delete(obj)
+            log.debug('Revoked perm on %s on %s' % (target_user_group, user_group))
--- a/rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html	Tue Apr 23 00:56:04 2013 +0200
+++ b/rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html	Tue Apr 23 02:18:31 2013 +0200
@@ -57,7 +57,8 @@
             </td>
         </tr>
     %endfor
-<%
+
+    <%
     _tmpl = h.literal("""' \
         <td><input type="radio" value="group.none" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
         <td><input type="radio" value="group.read" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
--- a/rhodecode/templates/admin/users_groups/user_group_edit_perms.html	Tue Apr 23 00:56:04 2013 +0200
+++ b/rhodecode/templates/admin/users_groups/user_group_edit_perms.html	Tue Apr 23 02:18:31 2013 +0200
@@ -40,6 +40,24 @@
         </tr>
     %endfor
 
+    ## USER GROUPS
+    %for g2p in c.users_group.user_group_user_group_to_perm:
+        <tr id="id${id(g2p.user_group.users_group_name)}">
+            <td>${h.radio('g_perm_%s' % g2p.user_group.users_group_name,'usergroup.none')}</td>
+            <td>${h.radio('g_perm_%s' % g2p.user_group.users_group_name,'usergroup.read')}</td>
+            <td>${h.radio('g_perm_%s' % g2p.user_group.users_group_name,'usergroup.write')}</td>
+            <td>${h.radio('g_perm_%s' % g2p.user_group.users_group_name,'usergroup.admin')}</td>
+            <td style="white-space: nowrap;">
+                <img class="perm-gravatar" src="${h.url('/images/icons/group.png')}"/>${g2p.user_group.users_group_name}
+            </td>
+            <td>
+                <span class="delete_icon action_button" onclick="ajaxActionRevoke(${g2p.user_group.users_group_id}, 'user_group', '${'id%s'%id(g2p.user_group.users_group_name)}')">
+                ${_('revoke')}
+                </span>
+            </td>
+        </tr>
+    %endfor
+
     <%
     _tmpl = h.literal("""' \
         <td><input type="radio" value="usergroup.none" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \