comparison roundup/hyperdb.py @ 8126:f7bd22bdef9d permission-performance

Move permission check code to hyperdb Now the hyperdb has a method filter_with_permissions that performs the permission checks before (for filtering on sort/group/filterspec arguments) and after a call to hyperdb.filter. This also fixes possible problems on the unfiltered sort/group/filterspec arguments in roundup/rest.py and roundup/cgi/templating.py
author Ralf Schlatterbeck <rsc@runtux.com>
date Mon, 21 Oct 2024 18:12:03 +0200
parents b8dc16d9624a
children 627871650f4f
comparison
equal deleted inserted replaced
8125:b358da7c89e5 8126:f7bd22bdef9d
1794 # cache for each id returned. Note that the filter_iter doesn't 1794 # cache for each id returned. Note that the filter_iter doesn't
1795 # promise to correctly sort by multilink (which isn't sane to do 1795 # promise to correctly sort by multilink (which isn't sane to do
1796 # anyway). 1796 # anyway).
1797 filter_iter = filter 1797 filter_iter = filter
1798 1798
1799 def filter_with_permissions(self, search_matches, filterspec, sort=[],
1800 group=[], retired=False, exact_match_spec={},
1801 limit=None, offset=None,
1802 permission='View', userid=None):
1803 """ Do the same as filter but return only the items the user is
1804 entitled to see, running the results through security checks.
1805 The userid defaults to the current database user.
1806 """
1807 if userid is None:
1808 userid = self.db.getuid()
1809 cn = self.classname
1810 sec = self.db.security
1811 filterspec = sec.filterFilterspec(userid, cn, filterspec)
1812 sort = sec.filterSortspec(userid, cn, sort)
1813 group = sec.filterSortspec(userid, cn, group)
1814 item_ids = self.filter(search_matches, filterspec, sort, group,
1815 retired, exact_match_spec, limit, offset)
1816 check = sec.hasPermission
1817 if check(permission, userid, cn, only_no_check = True):
1818 allowed = item_ids
1819 else:
1820 # Note that is_filterable returns True if no permissions are
1821 # found. This makes it fail early (with an empty allowed list)
1822 # instead of running through all ids with an empty
1823 # permission list.
1824 if sec.is_filterable(permission, userid, cn):
1825 new_ids = set(item_ids)
1826 confirmed = set()
1827 for perm in sec.filter_iter(permission, userid, cn):
1828 fargs = perm.filter(self._client.db, userid, klass)
1829 for farg in fargs:
1830 farg.update(sort=[], group=[], retired=None)
1831 result = klass.filter(list(new_ids), **farg)
1832 new_ids.difference_update(result)
1833 confirmed.update(result)
1834 # all allowed?
1835 if not new_ids:
1836 break
1837 # all allowed?
1838 if not new_ids:
1839 break
1840 # Need to sort again in database
1841 allowed = self.filter(confirmed, {}, sort=sort, group=group,
1842 retired=None)
1843 else: # Last resort: filter in python
1844 allowed = [id for id in item_ids
1845 if check(permission, userid, cn, itemid=id)]
1846 return allowed
1847
1848
1799 def count(self): 1849 def count(self):
1800 """Get the number of nodes in this class. 1850 """Get the number of nodes in this class.
1801 1851
1802 If the returned integer is 'numnodes', the ids of all the nodes 1852 If the returned integer is 'numnodes', the ids of all the nodes
1803 in this class run from 1 to numnodes, and numnodes+1 will be the 1853 in this class run from 1 to numnodes, and numnodes+1 will be the

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