[cubification] moved CWPermission handling into a localperms cube. closes #1914011 stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 13 Sep 2011 14:48:24 +0200
branchstable
changeset 7780 a1d5365fefc1
parent 7779 3826d8480a68
child 7781 e95cfd5eca61
[cubification] moved CWPermission handling into a localperms cube. closes #1914011 keeping bw compat provided the cube is available (else user should be warned he has to install it).
__pkginfo__.py
devtools/testlib.py
doc/book/en/devrepo/datamodel/baseschema.rst
doc/book/en/devrepo/datamodel/definition.rst
entities/authobjs.py
entities/schemaobjs.py
misc/migration/bootstrapmigration_repository.py
misc/migration/postcreate.py
schema.py
schemas/__init__.py
schemas/base.py
schemas/workflow.py
server/migractions.py
server/repository.py
server/session.py
server/test/data/bootstrap_cubes
test/data/bootstrap_cubes
web/views/actions.py
web/views/autoform.py
web/views/management.py
web/views/primary.py
web/views/schema.py
--- a/__pkginfo__.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/__pkginfo__.py	Tue Sep 13 14:48:24 2011 +0200
@@ -22,7 +22,7 @@
 
 modname = distname = "cubicweb"
 
-numversion = (3, 13, 5)
+numversion = (3, 14, 0)
 version = '.'.join(str(num) for num in numversion)
 
 description = "a repository of entities / relations for knowledge management"
--- a/devtools/testlib.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/devtools/testlib.py	Tue Sep 13 14:48:24 2011 +0200
@@ -387,31 +387,6 @@
                 req.cnx.commit()
         return user
 
-    @iclassmethod # XXX turn into a class method
-    def grant_permission(self, session, entity, group, pname=None, plabel=None):
-        """insert a permission on an entity. Will have to commit the main
-        connection to be considered
-        """
-        if not isinstance(session, Session):
-            warn('[3.12] grant_permission arguments are now (session, entity, group, pname[, plabel])',
-                 DeprecationWarning, stacklevel=2)
-            plabel = pname
-            pname = group
-            group = entity
-            entity = session
-            assert not isinstance(self, type)
-            session = self.session
-        pname = unicode(pname)
-        plabel = plabel and unicode(plabel) or unicode(group)
-        e = getattr(entity, 'eid', entity)
-        with security_enabled(session, False, False):
-            peid = session.execute(
-            'INSERT CWPermission X: X name %(pname)s, X label %(plabel)s,'
-            'X require_group G, E require_permission X '
-            'WHERE G name %(group)s, E eid %(e)s',
-            locals())[0][0]
-        return peid
-
     def login(self, login, **kwargs):
         """return a connection for the given login/password"""
         if login == self.admlogin:
--- a/doc/book/en/devrepo/datamodel/baseschema.rst	Tue Sep 13 14:41:53 2011 +0200
+++ b/doc/book/en/devrepo/datamodel/baseschema.rst	Tue Sep 13 14:48:24 2011 +0200
@@ -19,7 +19,6 @@
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * _`CWUser`, system users
 * _`CWGroup`, users groups
-* _`CWPermission`, used to configure the security of the instance
 
 Entity types used to manage workflows
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--- a/doc/book/en/devrepo/datamodel/definition.rst	Tue Sep 13 14:41:53 2011 +0200
+++ b/doc/book/en/devrepo/datamodel/definition.rst	Tue Sep 13 14:48:24 2011 +0200
@@ -646,68 +646,7 @@
   RelationType declaration which offers some advantages in the context
   of reusable cubes.
 
-Definition of permissions
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-The entity type `CWPermission` from the standard library
-allows to build very complex and dynamic security architectures. The schema of
-this entity type is as follow:
-
-.. sourcecode:: python
-
-    class CWPermission(EntityType):
-        """entity type that may be used to construct some advanced security configuration
-        """
-        name = String(required=True, indexed=True, internationalizable=True, maxsize=100)
-        require_group = SubjectRelation('CWGroup', cardinality='+*',
-                                        description=_('groups to which the permission is granted'))
-        require_state = SubjectRelation('State',
-                                        description=_("entity's state in which the permission is applicable"))
-        # can be used on any entity
-        require_permission = ObjectRelation('**', cardinality='*1', composite='subject',
-                                            description=_("link a permission to the entity. This "
-                                                          "permission should be used in the security "
-                                                          "definition of the entity's type to be useful."))
-
-
-Example of configuration:
-
-.. sourcecode:: python
-
-    class Version(EntityType):
-        """a version is defining the content of a particular project's release"""
-
-        __permissions__ = {'read':   ('managers', 'users', 'guests',),
-                           'update': ('managers', 'logilab', 'owners',),
-                           'delete': ('managers', ),
-                           'add':    ('managers', 'logilab',
-                                       ERQLExpression('X version_of PROJ, U in_group G,'
-                                                 'PROJ require_permission P, P name "add_version",'
-                                                 'P require_group G'),)}
-
-
-    class version_of(RelationType):
-        """link a version to its project. A version is necessarily linked to one and only one project.
-        """
-        __permissions__ = {'read':   ('managers', 'users', 'guests',),
-                           'delete': ('managers', ),
-                           'add':    ('managers', 'logilab',
-                                  RRQLExpression('O require_permission P, P name "add_version",'
-                                                 'U in_group G, P require_group G'),)
-                       }
-        inlined = True
-
-
-This configuration indicates that an entity `CWPermission` named
-"add_version" can be associated to a project and provides rights to create
-new versions on this project to specific groups. It is important to notice that:
-
-* in such case, we have to protect both the entity type "Version" and the relation
-  associating a version to a project ("version_of")
-
-* because of the genericity of the entity type `CWPermission`, we have to execute
-  a unification with the groups and/or the states if necessary in the expression
-  ("U in_group G, P require_group G" in the above example)
-
+  
 
 
 Handling schema changes
--- a/entities/authobjs.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/entities/authobjs.py	Tue Sep 13 14:48:24 2011 +0200
@@ -29,22 +29,6 @@
     fetch_attrs, fetch_order = fetch_config(['name'])
     fetch_unrelated_order = fetch_order
 
-    def grant_permission(self, entity, pname, plabel=None):
-        """grant local `pname` permission on `entity` to this group using
-        :class:`CWPermission`.
-
-        If a similar permission already exists, add the group to it, else create
-        a new one.
-        """
-        if not self._cw.execute(
-            'SET X require_group G WHERE E eid %(e)s, G eid %(g)s, '
-            'E require_permission X, X name %(name)s, X label %(label)s',
-            {'e': entity.eid, 'g': self.eid,
-             'name': pname, 'label': plabel}):
-            self._cw.create_entity('CWPermission', name=pname, label=plabel,
-                                   require_group=self,
-                                   reverse_require_permission=entity)
-
 
 class CWUser(AnyEntity):
     __regid__ = 'CWUser'
@@ -139,18 +123,6 @@
             return False
     owns = cached(owns, keyarg=1)
 
-    def has_permission(self, pname, contexteid=None):
-        rql = 'Any P WHERE P is CWPermission, U eid %(u)s, U in_group G, '\
-              'P name %(pname)s, P require_group G'
-        kwargs = {'pname': pname, 'u': self.eid}
-        if contexteid is not None:
-            rql += ', X require_permission P, X eid %(x)s'
-            kwargs['x'] = contexteid
-        try:
-            return self._cw.execute(rql, kwargs)
-        except Unauthorized:
-            return False
-
     # presentation utilities ##################################################
 
     def name(self):
--- a/entities/schemaobjs.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/entities/schemaobjs.py	Tue Sep 13 14:48:24 2011 +0200
@@ -176,13 +176,3 @@
 
     def check_expression(self, *args, **kwargs):
         return self._rqlexpr().check(*args, **kwargs)
-
-
-class CWPermission(AnyEntity):
-    __regid__ = 'CWPermission'
-    fetch_attrs, fetch_order = fetch_config(['name', 'label'])
-
-    def dc_title(self):
-        if self.label:
-            return '%s (%s)' % (self._cw._(self.name), self.label)
-        return self._cw._(self.name)
--- a/misc/migration/bootstrapmigration_repository.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/misc/migration/bootstrapmigration_repository.py	Tue Sep 13 14:48:24 2011 +0200
@@ -41,6 +41,15 @@
         'FROM cw_CWSource, cw_source_relation '
         'WHERE entities.eid=cw_source_relation.eid_from AND cw_source_relation.eid_to=cw_CWSource.cw_eid')
 
+if applcubicwebversion <= (3, 14, 0) and cubicwebversion >= (3, 14, 0):
+    if 'require_permission' in schema and not 'localperms'in repo.config.cubes():
+        from cubicweb import ExecutionError
+        try:
+            add_cube('localperms', update_database=False)
+        except ImportError:
+            raise ExecutionError('In cubicweb 3.14, CWPermission and related stuff '
+                                 'has been moved to cube localperms. Install it first.')
+
 if applcubicwebversion == (3, 6, 0) and cubicwebversion >= (3, 6, 0):
     CSTRMAP = dict(rql('Any T, X WHERE X is CWConstraintType, X name T',
                        ask_confirm=False))
--- a/misc/migration/postcreate.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/misc/migration/postcreate.py	Tue Sep 13 14:48:24 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -69,10 +69,3 @@
             if value != default:
                 rql('INSERT CWProperty X: X pkey %(k)s, X value %(v)s',
                     {'k': key, 'v': value})
-
-# add PERM_USE_TEMPLATE_FORMAT permission
-from cubicweb.schema import PERM_USE_TEMPLATE_FORMAT
-usetmplperm = create_entity('CWPermission', name=PERM_USE_TEMPLATE_FORMAT,
-                            label=_('use template languages'))
-rql('SET X require_group G WHERE G name "managers", X eid %(x)s',
-    {'x': usetmplperm.eid})
--- a/schema.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/schema.py	Tue Sep 13 14:48:24 2011 +0200
@@ -59,12 +59,11 @@
                            'from_state', 'to_state', 'condition',
                            'subworkflow', 'subworkflow_state', 'subworkflow_exit',
                            ))
-SYSTEM_RTYPES = set(('in_group', 'require_group', 'require_permission',
+SYSTEM_RTYPES = set(('in_group', 'require_group',
                      # cwproperty
                      'for_user',
                      )) | WORKFLOW_RTYPES
 NO_I18NCONTEXT = META_RTYPES | WORKFLOW_RTYPES
-NO_I18NCONTEXT.add('require_permission')
 
 SKIP_COMPOSITE_RELS = [('cw_source', 'subject')]
 
@@ -85,7 +84,7 @@
                       'WorkflowTransition', 'BaseTransition',
                       'SubWorkflowExitPoint'))
 
-INTERNAL_TYPES = set(('CWProperty', 'CWPermission', 'CWCache', 'ExternalUri',
+INTERNAL_TYPES = set(('CWProperty', 'CWCache', 'ExternalUri',
                       'CWSource', 'CWSourceHostConfig', 'CWSourceSchemaConfig'))
 
 
@@ -1174,7 +1173,7 @@
 
 # _() is just there to add messages to the catalog, don't care about actual
 # translation
-PERM_USE_TEMPLATE_FORMAT = _('use_template_format')
+MAY_USE_TEMPLATE_FORMAT = set(('managers',))
 NEED_PERM_FORMATS = [_('text/cubicweb-page-template')]
 
 @monkeypatch(FormatConstraint)
@@ -1189,9 +1188,9 @@
             # cw is a server session
             hasperm = not cw.write_security or \
                       not cw.is_hook_category_activated('integrity') or \
-                      cw.user.has_permission(PERM_USE_TEMPLATE_FORMAT)
+                      cw.user.matching_groups(MAY_USE_TEMPLATE_FORMAT)
         else:
-            hasperm = cw.user.has_permission(PERM_USE_TEMPLATE_FORMAT)
+            hasperm = cw.user.matching_groups(MAY_USE_TEMPLATE_FORMAT)
         if hasperm:
             return self.regular_formats + tuple(NEED_PERM_FORMATS)
     return self.regular_formats
--- a/schemas/__init__.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/schemas/__init__.py	Tue Sep 13 14:48:24 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -15,12 +15,10 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""some utilities to define schema permissions
+"""some constants and classes to define schema permissions"""
 
-"""
 __docformat__ = "restructuredtext en"
 
-from rql.utils import quote
 from cubicweb.schema import RO_REL_PERMS, RO_ATTR_PERMS, \
      PUB_SYSTEM_ENTITY_PERMS, PUB_SYSTEM_REL_PERMS, \
      ERQLExpression, RRQLExpression
@@ -35,59 +33,19 @@
 # execute, readable by anyone
 HOOKS_RTYPE_PERMS = RO_REL_PERMS # XXX deprecates
 
-def _perm(names):
-    if isinstance(names, (list, tuple)):
-        if len(names) == 1:
-            names = quote(names[0])
-        else:
-            names = 'IN (%s)' % (','.join(quote(name) for name in names))
-    else:
-        names = quote(names)
-    #return u' require_permission P, P name %s, U in_group G, P require_group G' % names
-    return u' require_permission P, P name %s, U has_group_permission P' % names
 
-
-def xperm(*names):
-    return 'X' + _perm(names)
-
-def xexpr(*names):
-    return ERQLExpression(xperm(*names))
-
-def xrexpr(relation, *names):
-    return ERQLExpression('X %s Y, Y %s' % (relation, _perm(names)))
-
-def xorexpr(relation, etype, *names):
-    return ERQLExpression('Y %s X, X is %s, Y %s' % (relation, etype, _perm(names)))
-
-
-def sexpr(*names):
-    return RRQLExpression('S' + _perm(names), 'S')
+from logilab.common.modutils import LazyObject
+from logilab.common.deprecation import deprecated
+class MyLazyObject(LazyObject):
 
-def restricted_sexpr(restriction, *names):
-    rql = '%s, %s' % (restriction, 'S' + _perm(names))
-    return RRQLExpression(rql, 'S')
-
-def restricted_oexpr(restriction, *names):
-    rql = '%s, %s' % (restriction, 'O' + _perm(names))
-    return RRQLExpression(rql, 'O')
-
-def oexpr(*names):
-    return RRQLExpression('O' + _perm(names), 'O')
-
+    def _getobj(self):
+        try:
+            return super(MyLazyObject, self)._getobj()
+        except ImportError:
+            raise ImportError('In cubicweb 3.14, function %s has been moved to '
+                              'cube localperms. Install it first.' % self.obj)
 
-# def supdate_perm():
-#     return RRQLExpression('U has_update_permission S', 'S')
-
-# def oupdate_perm():
-#     return RRQLExpression('U has_update_permission O', 'O')
-
-def relxperm(rel, role, *names):
-    assert role in ('subject', 'object')
-    if role == 'subject':
-        zxrel = ', X %s Z' % rel
-    else:
-        zxrel = ', Z %s X' % rel
-    return 'Z' + _perm(names) + zxrel
-
-def relxexpr(rel, role, *names):
-    return ERQLExpression(relxperm(rel, role, *names))
+for name in ('xperm', 'xexpr', 'xrexpr', 'xorexpr', 'sexpr', 'restricted_sexpr',
+             'restricted_oexpr', 'oexpr', 'relxperm', 'relxexpr', '_perm'):
+    msg = '[3.14] import %s from cubes.localperms' % name
+    globals()[name] = deprecated(msg)(MyLazyObject('cubes.localperms', name))
--- a/schemas/base.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/schemas/base.py	Tue Sep 13 14:48:24 2011 +0200
@@ -180,31 +180,6 @@
     cardinality = '?*'
 
 
-class CWPermission(EntityType):
-    """entity type that may be used to construct some advanced security configuration
-    """
-    __permissions__ = PUB_SYSTEM_ENTITY_PERMS
-
-    name = String(required=True, indexed=True, internationalizable=True, maxsize=100,
-                  description=_('name or identifier of the permission'))
-    label = String(required=True, internationalizable=True, maxsize=100,
-                   description=_('distinct label to distinguate between other '
-                                 'permission entity of the same name'))
-    require_group = SubjectRelation('CWGroup',
-                                    description=_('groups to which the permission is granted'))
-
-# explicitly add X require_permission CWPermission for each entity that should have
-# configurable security
-class require_permission(RelationType):
-    """link a permission to the entity. This permission should be used in the
-    security definition of the entity's type to be useful.
-    """
-    __permissions__ = PUB_SYSTEM_REL_PERMS
-
-class require_group(RelationType):
-    """used to grant a permission to a group"""
-    __permissions__ = PUB_SYSTEM_REL_PERMS
-
 
 class ExternalUri(EntityType):
     """a URI representing an object in external data store"""
@@ -382,3 +357,5 @@
         'add':    ('managers', RRQLExpression('U has_update_permission S'),),
         'delete': ('managers', RRQLExpression('U has_update_permission S'),),
         }
+
+
--- a/schemas/workflow.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/schemas/workflow.py	Tue Sep 13 14:48:24 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -21,14 +21,15 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
-from yams.buildobjs import (EntityType, RelationType, SubjectRelation,
+from yams.buildobjs import (EntityType, RelationType, RelationDefinition,
+                            SubjectRelation,
                             RichString, String, Int)
 from cubicweb.schema import RQLConstraint, RQLUniqueConstraint
-from cubicweb.schemas import (META_ETYPE_PERMS, META_RTYPE_PERMS,
-                              HOOKS_RTYPE_PERMS)
+from cubicweb.schemas import (PUB_SYSTEM_ENTITY_PERMS, PUB_SYSTEM_REL_PERMS,
+                              RO_REL_PERMS)
 
 class Workflow(EntityType):
-    __permissions__ = META_ETYPE_PERMS
+    __permissions__ = PUB_SYSTEM_ENTITY_PERMS
 
     name = String(required=True, indexed=True, internationalizable=True,
                   maxsize=256)
@@ -47,7 +48,7 @@
 
 class default_workflow(RelationType):
     """default workflow for an entity type"""
-    __permissions__ = META_RTYPE_PERMS
+    __permissions__ = PUB_SYSTEM_REL_PERMS
 
     subject = 'CWEType'
     object = 'Workflow'
@@ -60,7 +61,7 @@
     """used to associate simple states to an entity type and/or to define
     workflows
     """
-    __permissions__ = META_ETYPE_PERMS
+    __permissions__ = PUB_SYSTEM_ENTITY_PERMS
 
     name = String(required=True, indexed=True, internationalizable=True,
                   maxsize=256,
@@ -83,7 +84,7 @@
 
 class BaseTransition(EntityType):
     """abstract base class for transitions"""
-    __permissions__ = META_ETYPE_PERMS
+    __permissions__ = PUB_SYSTEM_ENTITY_PERMS
 
     name = String(required=True, indexed=True, internationalizable=True,
                   maxsize=256,
@@ -91,22 +92,34 @@
                                                    _('workflow already have a transition of that name'))])
     type = String(vocabulary=(_('normal'), _('auto')), default='normal')
     description = RichString(description=_('semantic description of this transition'))
-    condition = SubjectRelation('RQLExpression', cardinality='*?', composite='subject',
-                                description=_('a RQL expression which should return some results, '
-                                              'else the transition won\'t be available. '
-                                              'This query may use X and U variables '
-                                              'that will respectivly represents '
-                                              'the current entity and the current user'))
 
-    require_group = SubjectRelation('CWGroup', cardinality='**',
-                                    description=_('group in which a user should be to be '
-                                                  'allowed to pass this transition'))
     transition_of = SubjectRelation('Workflow', cardinality='1*', composite='object',
                                     description=_('workflow to which this transition belongs'),
                                     constraints=[RQLUniqueConstraint('S name N, Y transition_of O, Y name N', 'Y',
                                                                      _('workflow already have a transition of that name'))])
 
 
+class require_group(RelationDefinition):
+    """group in which a user should be to be allowed to pass this transition"""
+    __permissions__ = PUB_SYSTEM_REL_PERMS
+    subject = 'BaseTransition'
+    object = 'CWGroup'
+
+
+class condition(RelationDefinition):
+    """a RQL expression which should return some results, else the transition
+    won't be available.
+
+    This query may use X and U variables that will respectivly represents the
+    current entity and the current user.
+    """
+    __permissions__ = PUB_SYSTEM_REL_PERMS
+    subject = 'BaseTransition'
+    object = 'RQLExpression'
+    cardinality = '*?'
+    composite = 'subject'
+
+
 class Transition(BaseTransition):
     """use to define a transition from one or multiple states to a destination
     states in workflow's definitions. Transition without destination state will
@@ -177,11 +190,11 @@
     # get actor and date time using owned_by and creation_date
 
 class from_state(RelationType):
-    __permissions__ = HOOKS_RTYPE_PERMS.copy()
+    __permissions__ = RO_REL_PERMS.copy()
     inlined = True
 
 class to_state(RelationType):
-    __permissions__ = HOOKS_RTYPE_PERMS.copy()
+    __permissions__ = RO_REL_PERMS.copy()
     inlined = True
 
 class by_transition(RelationType):
@@ -196,60 +209,52 @@
 
 class workflow_of(RelationType):
     """link a workflow to one or more entity type"""
-    __permissions__ = META_RTYPE_PERMS
+    __permissions__ = PUB_SYSTEM_REL_PERMS
 
 class state_of(RelationType):
     """link a state to one or more workflow"""
-    __permissions__ = META_RTYPE_PERMS
+    __permissions__ = PUB_SYSTEM_REL_PERMS
     inlined = True
 
 class transition_of(RelationType):
     """link a transition to one or more workflow"""
-    __permissions__ = META_RTYPE_PERMS
+    __permissions__ = PUB_SYSTEM_REL_PERMS
     inlined = True
 
 class destination_state(RelationType):
     """destination state of a transition"""
-    __permissions__ = META_RTYPE_PERMS
+    __permissions__ = PUB_SYSTEM_REL_PERMS
     inlined = True
 
 class allowed_transition(RelationType):
     """allowed transitions from this state"""
-    __permissions__ = META_RTYPE_PERMS
+    __permissions__ = PUB_SYSTEM_REL_PERMS
 
 class initial_state(RelationType):
     """indicate which state should be used by default when an entity using
     states is created
     """
-    __permissions__ = META_RTYPE_PERMS
+    __permissions__ = PUB_SYSTEM_REL_PERMS
     inlined = True
 
 
 class subworkflow(RelationType):
-    __permissions__ = META_RTYPE_PERMS
+    __permissions__ = PUB_SYSTEM_REL_PERMS
     inlined = True
 
 class exit_point(RelationType):
-    __permissions__ = META_RTYPE_PERMS
+    __permissions__ = PUB_SYSTEM_REL_PERMS
 
 class subworkflow_state(RelationType):
-    __permissions__ = META_RTYPE_PERMS
+    __permissions__ = PUB_SYSTEM_REL_PERMS
     inlined = True
 
 
-class condition(RelationType):
-    __permissions__ = META_RTYPE_PERMS
-
-# already defined in base.py
-# class require_group(RelationType):
-#     __permissions__ = META_RTYPE_PERMS
-
-
 # "abstract" relations, set by WorkflowableEntityType ##########################
 
 class custom_workflow(RelationType):
     """allow to set a specific workflow for an entity"""
-    __permissions__ = META_RTYPE_PERMS
+    __permissions__ = PUB_SYSTEM_REL_PERMS
 
     cardinality = '?*'
     constraints = [RQLConstraint('S is ET, O workflow_of ET',
@@ -275,7 +280,7 @@
 
 class in_state(RelationType):
     """indicate the current state of an entity"""
-    __permissions__ = HOOKS_RTYPE_PERMS
+    __permissions__ = RO_REL_PERMS
 
     # not inlined intentionnaly since when using ldap sources, user'state
     # has to be stored outside the CWUser table
--- a/server/migractions.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/server/migractions.py	Tue Sep 13 14:48:24 2011 +0200
@@ -117,7 +117,15 @@
             # which is called on regular start
             repo.hm.call_hooks('server_maintenance', repo=repo)
         if not schema and not getattr(config, 'quick_start', False):
-            schema = config.load_schema(expand_cubes=True)
+            insert_lperms = self.repo.get_versions()['cubicweb'] < (3, 14, 0) and 'localperms' in config.available_cubes()
+            if insert_lperms:
+                cubes = config._cubes
+                config._cubes += ('localperms',)
+            try:
+                schema = config.load_schema(expand_cubes=True)
+            finally:
+                if insert_lperms:
+                    config._cubes = cubes
         self.fs_schema = schema
         self._synchronized = set()
 
--- a/server/repository.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/server/repository.py	Tue Sep 13 14:48:24 2011 +0200
@@ -60,8 +60,7 @@
      security_enabled
 from cubicweb.server.ssplanner import EditedEntity
 
-NO_CACHE_RELATIONS = set( [('require_permission', 'object'),
-                           ('owned_by', 'object'),
+NO_CACHE_RELATIONS = set( [('owned_by', 'object'),
                            ('created_by', 'object'),
                            ('cw_source', 'object'),
                            ])
--- a/server/session.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/server/session.py	Tue Sep 13 14:48:24 2011 +0200
@@ -1319,9 +1319,6 @@
     def owns(self, eid):
         return True
 
-    def has_permission(self, pname, contexteid=None):
-        return True
-
     def property_value(self, key):
         if key == 'ui.language':
             return 'en'
--- a/server/test/data/bootstrap_cubes	Tue Sep 13 14:41:53 2011 +0200
+++ b/server/test/data/bootstrap_cubes	Tue Sep 13 14:48:24 2011 +0200
@@ -1,1 +1,1 @@
-card,comment,folder,tag,basket,email,file
+card,comment,folder,tag,basket,email,file,localperms
--- a/test/data/bootstrap_cubes	Tue Sep 13 14:41:53 2011 +0200
+++ b/test/data/bootstrap_cubes	Tue Sep 13 14:48:24 2011 +0200
@@ -1,1 +1,1 @@
-card, file, tag
+card, file, tag, localperms
--- a/web/views/actions.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/web/views/actions.py	Tue Sep 13 14:48:24 2011 +0200
@@ -182,15 +182,6 @@
     category = 'moreactions'
     order = 15
 
-    @classmethod
-    def __registered__(cls, reg):
-        if 'require_permission' in reg.schema:
-            cls.__select__ = (one_line_rset() & non_final_entity() &
-                              (match_user_groups('managers')
-                               | relation_possible('require_permission', 'subject', 'CWPermission',
-                                                   action='add')))
-        return super(ManagePermissionsAction, cls).__registered__(reg)
-
     def url(self):
         return self.cw_rset.get_entity(self.cw_row or 0, self.cw_col or 0).absolute_url(vid='security')
 
@@ -436,7 +427,6 @@
 ## default actions ui configuration ###########################################
 
 addmenu = uicfg.actionbox_appearsin_addmenu
-addmenu.tag_subject_of(('*', 'require_permission', '*'), False)
 addmenu.tag_object_of(('*', 'relation_type', 'CWRType'), True)
 addmenu.tag_object_of(('*', 'from_entity', 'CWEType'), False)
 addmenu.tag_object_of(('*', 'to_entity', 'CWEType'), False)
--- a/web/views/autoform.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/web/views/autoform.py	Tue Sep 13 14:48:24 2011 +0200
@@ -920,7 +920,6 @@
               'owned_by', 'created_by', 'cw_source'):
     _AFS.tag_subject_of(('*', rtype, '*'), 'main', 'metadata')
 
-_AFS.tag_subject_of(('*', 'require_permission', '*'), 'main', 'hidden')
 _AFS.tag_subject_of(('*', 'by_transition', '*'), 'main', 'attributes')
 _AFS.tag_subject_of(('*', 'by_transition', '*'), 'muledit', 'attributes')
 _AFS.tag_object_of(('*', 'by_transition', '*'), 'main', 'hidden')
@@ -929,8 +928,6 @@
 _AFS.tag_subject_of(('*', 'wf_info_for', '*'), 'main', 'attributes')
 _AFS.tag_subject_of(('*', 'wf_info_for', '*'), 'muledit', 'attributes')
 _AFS.tag_object_of(('*', 'wf_info_for', '*'), 'main', 'hidden')
-_AFS.tag_subject_of(('CWPermission', 'require_group', '*'), 'main', 'attributes')
-_AFS.tag_subject_of(('CWPermission', 'require_group', '*'), 'muledit', 'attributes')
 _AFS.tag_attribute(('CWEType', 'final'), 'main', 'hidden')
 _AFS.tag_attribute(('CWRType', 'final'), 'main', 'hidden')
 _AFS.tag_attribute(('CWUser', 'firstname'), 'main', 'attributes')
--- a/web/views/management.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/web/views/management.py	Tue Sep 13 14:48:24 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -45,10 +45,9 @@
         self.w(u'<div id="progress">%s</div>' % self._cw._('validating...'))
         super(SecurityManagementView, self).call()
 
-    def cell_call(self, row, col):
+    def entity_call(self, entity):
         self._cw.add_js('cubicweb.edition.js')
         self._cw.add_css('cubicweb.acl.css')
-        entity = self.cw_rset.get_entity(row, col)
         w = self.w
         _ = self._cw._
         w(u'<h1><span class="etype">%s</span> <a href="%s">%s</a></h1>'
@@ -65,13 +64,6 @@
             self.owned_by_edit_form(entity)
         else:
             self.owned_by_information(entity)
-        # cwpermissions
-        if 'require_permission' in entity.e_schema.subject_relations():
-            w('<h3>%s</h3>' % _('permissions for this entity'))
-            reqpermschema = self._cw.vreg.schema.rschema('require_permission')
-            self.require_permission_information(entity, reqpermschema)
-            if reqpermschema.has_perm(self._cw, 'add', fromeid=entity.eid):
-                self.require_permission_edit_form(entity)
 
     def owned_by_edit_form(self, entity):
         self.w('<h3>%s</h3>' % self._cw._('ownership'))
@@ -97,65 +89,6 @@
         # else we don't know if this is because entity has no owner or becayse
         # user as no access to owner users entities
 
-    def require_permission_information(self, entity, reqpermschema):
-        if entity.require_permission:
-            w = self.w
-            _ = self._cw._
-            if reqpermschema.has_perm(self._cw, 'delete', fromeid=entity.eid):
-                delurl = self._cw.build_url('edit', __redirectvid='security',
-                                            __redirectpath=entity.rest_path())
-                delurl = delurl.replace('%', '%%')
-                # don't give __delete value to build_url else it will be urlquoted
-                # and this will replace %s by %25s
-                delurl += '&__delete=%s:require_permission:%%s' % entity.eid
-                dellinktempl = u'[<a href="%s" title="%s">-</a>]&#160;' % (
-                    xml_escape(delurl), _('delete this permission'))
-            else:
-                dellinktempl = None
-            w(u'<table class="schemaInfo">')
-            w(u'<tr><th>%s</th><th>%s</th></tr>' % (_("permission"),
-                                                    _('granted to groups')))
-            for cwperm in entity.require_permission:
-                w(u'<tr>')
-                if dellinktempl:
-                    w(u'<td>%s%s</td>' % (dellinktempl % cwperm.eid,
-                                          cwperm.view('oneline')))
-                else:
-                    w(u'<td>%s</td>' % cwperm.view('oneline'))
-                w(u'<td>%s</td>' % self._cw.view('csv', cwperm.related('require_group'), 'null'))
-                w(u'</tr>\n')
-            w(u'</table>')
-        else:
-            self.w(self._cw._('no associated permissions'))
-
-    def require_permission_edit_form(self, entity):
-        newperm = self._cw.vreg['etypes'].etype_class('CWPermission')(self._cw)
-        newperm.eid = self._cw.varmaker.next()
-        self.w(u'<p>%s</p>' % self._cw._('add a new permission'))
-        form = self._cw.vreg['forms'].select('base', self._cw, entity=newperm,
-                                         form_buttons=[wdgs.SubmitButton()],
-                                         domid='reqperm%s' % entity.eid,
-                                         __redirectvid='security',
-                                         __redirectpath=entity.rest_path())
-        form.add_hidden('require_permission', entity.eid, role='object',
-                        eidparam=True)
-        permnames = getattr(entity, '__permissions__', None)
-        cwpermschema = newperm.e_schema
-        if permnames is not None:
-            field = guess_field(cwpermschema, self._cw.vreg.schema.rschema('name'),
-                                widget=wdgs.Select({'size': 1}),
-                                choices=permnames)
-        else:
-            field = guess_field(cwpermschema, self._cw.vreg.schema.rschema('name'))
-        form.append_field(field)
-        field = guess_field(cwpermschema, self._cw.vreg.schema.rschema('label'))
-        form.append_field(field)
-        field = guess_field(cwpermschema, self._cw.vreg.schema.rschema('require_group'))
-        form.append_field(field)
-        renderer = self._cw.vreg['formrenderers'].select(
-            'htable', self._cw, rset=None, display_progress_div=False)
-        form.render(w=self.w, renderer=renderer)
-
 
 class ErrorView(AnyRsetView):
     """default view when no result has been found"""
--- a/web/views/primary.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/web/views/primary.py	Tue Sep 13 14:48:24 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -396,5 +396,3 @@
 for rtype in META_RTYPES:
     _pvs.tag_subject_of(('*', rtype, '*'), 'hidden')
     _pvs.tag_object_of(('*', rtype, '*'), 'hidden')
-_pvs.tag_subject_of(('*', 'require_permission', '*'), 'hidden')
-_pvs.tag_object_of(('*', 'require_permission', '*'), 'hidden')
--- a/web/views/schema.py	Tue Sep 13 14:41:53 2011 +0200
+++ b/web/views/schema.py	Tue Sep 13 14:48:24 2011 +0200
@@ -676,14 +676,6 @@
     def parent_entity(self):
         return self.entity.expression_of
 
-class CWPermissionIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
-    __select__ = is_instance('CWPermission')
-    def parent_entity(self):
-        # XXX useless with permission propagation
-        permissionof = getattr(self.entity, 'reverse_require_permission', ())
-        if len(permissionof) == 1:
-            return permissionof[0]
-
 
 # misc: facets, actions ########################################################