--- a/entity.py Tue Sep 15 15:01:41 2009 +0200
+++ b/entity.py Thu Sep 17 15:16:53 2009 +0200
@@ -14,6 +14,7 @@
from logilab.common.decorators import cached
from logilab.mtconverter import TransformData, TransformError, xml_escape
+from rql import parse
from rql.utils import rqlvar_maker
from cubicweb import Unauthorized
@@ -21,6 +22,7 @@
from cubicweb.selectors import yes
from cubicweb.appobject import AppObject
from cubicweb.schema import RQLVocabularyConstraint, RQLConstraint
+from cubicweb.rqlrewrite import RQLRewriter
from cubicweb.common.uilib import printable_value, soup2xhtml
from cubicweb.common.mixins import MI_REL_TRIGGERS
@@ -616,7 +618,10 @@
def unrelated_rql(self, rtype, targettype, role, ordermethod=None,
vocabconstraints=True):
"""build a rql to fetch `targettype` entities unrelated to this entity
- using (rtype, role) relation
+ using (rtype, role) relation.
+
+ Consider relation permissions so that returned entities may be actually
+ linked by `rtype`.
"""
ordermethod = ordermethod or 'fetch_unrelated_order'
if isinstance(rtype, basestring):
@@ -629,8 +634,17 @@
objtype, subjtype = self.e_schema, targettype
if self.has_eid():
restriction = ['NOT S %s O' % rtype, '%s eid %%(x)s' % evar]
+ args = {'x': self.eid}
+ if role == 'subject':
+ securitycheck_args = {'fromeid': self.eid}
+ else:
+ securitycheck_args = {'toeid': self.eid}
else:
restriction = []
+ args = {}
+ securitycheck_args = {}
+ insertsecurity = (rtype.has_local_role('add') and not
+ rtype.has_perm(self.req, 'add', **securitycheck_args))
constraints = rtype.rproperty(subjtype, objtype, 'constraints')
if vocabconstraints:
# RQLConstraint is a subclass for RQLVocabularyConstraint, so they
@@ -647,20 +661,29 @@
if not ' ORDERBY ' in rql:
before, after = rql.split(' WHERE ', 1)
rql = '%s ORDERBY %s WHERE %s' % (before, searchedvar, after)
- return rql
+ if insertsecurity:
+ rqlexprs = rtype.get_rqlexprs('add')
+ rewriter = RQLRewriter(self.req)
+ rqlst = self.req.vreg.parse(self.req, rql, args)
+ for select in rqlst.children:
+ rewriter.rewrite(select, [((searchedvar, searchedvar), rqlexprs)],
+ select.solutions, args)
+ rql = rqlst.as_string()
+ return rql, args
def unrelated(self, rtype, targettype, role='subject', limit=None,
ordermethod=None):
"""return a result set of target type objects that may be related
by a given relation, with self as subject or object
"""
- rql = self.unrelated_rql(rtype, targettype, role, ordermethod)
+ try:
+ rql, args = self.unrelated_rql(rtype, targettype, role, ordermethod)
+ except Unauthorized:
+ return self.req.empty_rset()
if limit is not None:
before, after = rql.split(' WHERE ', 1)
rql = '%s LIMIT %s WHERE %s' % (before, limit, after)
- if self.has_eid():
- return self.req.execute(rql, {'x': self.eid})
- return self.req.execute(rql)
+ return self.req.execute(rql, args, tuple(args))
# relations cache handling ################################################
@@ -816,6 +839,20 @@
words += entity.get_words()
return words
+ @deprecated('[3.2] see new form api')
+ def vocabulary(self, rtype, role='subject', limit=None):
+ """vocabulary functions must return a list of couples
+ (label, eid) that will typically be used to fill the
+ edition view's combobox.
+
+ If `eid` is None in one of these couples, it should be
+ interpreted as a separator in case vocabulary results are grouped
+ """
+ from logilab.common.testlib import mock_object
+ form = self.vreg.select('forms', 'edition', self.req, entity=self)
+ field = mock_object(name=rtype, role=role)
+ return form.form_field_vocabulary(field, limit)
+
# attribute and relation descriptors ##########################################