diff roundup/rest.py @ 6554:576d630fc908

Fix error status for invalid props Some places were raising AttributeError which results in a 405 (bad method) not a 400. Replace with UsageError or KeyError. Make rest.py::transitive_props run aginst a prop that has no transitive elements as well. So it will verify that assignedto exists even though it has no period like assignedto.name would. These should check properties in @fields and @sort. Also validate fields that are used as search params: ?assignedto=1 If the search prop was mispelled or incorrect, the search element was ignored as though it had not been specified. Now it returns a 400 to notify sender they sent an incorrect filter. Also remove unused statements that were originally for finding invalid props before we supported transitive props.
author John Rouillard <rouilj@ieee.org>
date Sat, 11 Dec 2021 21:41:49 -0500
parents 9aa8df0b4426
children 178705fbeaa8
line wrap: on
line diff
--- a/roundup/rest.py	Sat Dec 11 21:26:46 2021 -0500
+++ b/roundup/rest.py	Sat Dec 11 21:41:49 2021 -0500
@@ -563,13 +563,13 @@
                 for pn in p.split('.'):
                     # Tried to dereference a non-Link property
                     if cn is None:
-                        raise AttributeError("Unknown: %s" % p)
+                        raise UsageError("Property %(base)s can not be dereferenced in %(p)s." % { "base": p[:-(len(pn)+1)], "p": p})
                     cls = self.db.getclass(cn)
                     # This raises a KeyError for unknown prop:
                     try:
                         prop = cls.getprops(protected=True)[pn]
                     except KeyError:
-                        raise AttributeError("Unknown: %s" % p)
+                        raise KeyError("Unknown property: %s" % p)
                     if isinstance(prop, hyperdb.Multilink):
                         raise UsageError(
                             'Multilink Traversal not allowed: %s' % p)
@@ -582,6 +582,13 @@
                         cn = prop.classname
                     except AttributeError:
                         cn = None
+            else:
+                cls = self.db.getclass(cn)
+                # This raises a KeyError for unknown prop:
+                try:
+                    prop = cls.getprops(protected=True)[pn]
+                except KeyError:
+                    raise KeyError("Unknown property: %s" % pn)
             checked_props.append (p)
         return checked_props
 
@@ -802,11 +809,9 @@
                 f = value.split(",")
                 if len(f) == 1:
                     f = value.split(":")
-                allprops = class_obj.getprops(protected=True)
                 display_props.update(self.transitive_props(class_name, f))
             elif key == "@sort":
                 f = value.split(",")
-                allprops = class_obj.getprops(protected=True)
                 for p in f:
                     if not p:
                         raise UsageError("Empty property "
@@ -845,6 +850,8 @@
                 except KeyError:
                     raise UsageError("Field %s is not valid for %s class." %
                                      (p, class_name))
+                # Call this for the side effect of validating the key
+                _ = self.transitive_props(class_name, [ key ])
                 # We drop properties without search permission silently
                 # This reflects the current behavior of other roundup
                 # interfaces
@@ -1024,7 +1031,6 @@
                 f = value.split(",")
                 if len(f) == 1:
                     f = value.split(":")
-                allprops = class_obj.getprops(protected=True)
                 props.update(self.transitive_props(class_name, f))
             elif key == "@protected":
                 # allow client to request read only

Roundup Issue Tracker: http://roundup-tracker.org/