Skip to content

Commit 0cab750

Browse files
committed
Fix transitive property check in REST API
Checking Search permissin on a displayed property is wrong, we now check *View* Permission on each component of a transitive prop.
1 parent c8d78c4 commit 0cab750

File tree

1 file changed

+23
-22
lines changed

1 file changed

+23
-22
lines changed

roundup/rest.py

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -473,39 +473,40 @@ def prop_from_arg(self, cl, key, value, itemid=None):
473473
def transitive_props (self, class_name, props):
474474
"""Construct a list of transitive properties from the given
475475
argument, and return it after permission check. Raises
476-
Unauthorised if no permission. Permission is checked by checking
477-
search-permission on the path (delimited by '.') excluding the
478-
last component and then checking View permission on the last
479-
component. We do not allow to traverse multilinks -- the last
480-
item of an expansion *may* be a multilink but in the middle of a
481-
transitive prop.
476+
Unauthorised if no permission. Permission is checked by
477+
checking View permission on each component. We do not allow to
478+
traverse multilinks -- the last item of an expansion *may* be a
479+
multilink but in the middle of a transitive prop.
482480
"""
483481
checked_props = []
484482
uid = self.db.getuid()
485483
for p in props:
486484
pn = p
487485
cn = class_name
488486
if '.' in p:
489-
path, lc = p.rsplit('.', 1)
490-
if not self.db.security.hasSearchPermission(uid, class_name, p):
491-
raise (Unauthorised
492-
('User does not have permission on "%s.%s"'
493-
% (class_name, p)))
494-
prev = prop = None
495-
# This shouldn't raise any errors, otherwise the search
496-
# permission check above would have failed
497-
for pn in path.split('.'):
487+
prop = None
488+
for pn in p.split('.'):
489+
# Tried to dereference a non-Link property
490+
if cn is None:
491+
raise AttributeError("Unknown: %s" % p)
498492
cls = self.db.getclass(cn)
499-
prop = cls.getprops(protected=True)[pn]
493+
# This raises a KeyError for unknown prop:
494+
try:
495+
prop = cls.getprops(protected=True)[pn]
496+
except KeyError:
497+
raise AttributeError("Unknown: %s" % p)
500498
if isinstance(prop, hyperdb.Multilink):
501499
raise UsageError(
502500
'Multilink Traversal not allowed: %s' % p)
503-
cn = prop.classname
504-
cls = self.db.getclass(cn)
505-
# Now we have the classname in cn and the prop name in pn.
506-
if not self.db.security.hasPermission('View', uid, cn, pn):
507-
raise(Unauthorised
508-
('User does not have permission on "%s.%s"' % (cn, pn)))
501+
# Now we have the classname in cn and the prop name in pn.
502+
if not self.db.security.hasPermission('View', uid, cn, pn):
503+
raise(Unauthorised
504+
('User does not have permission on "%s.%s"'
505+
% (cn, pn)))
506+
try:
507+
cn = prop.classname
508+
except AttributeError:
509+
cn = None
509510
checked_props.append (p)
510511
return checked_props
511512

0 commit comments

Comments
 (0)