Mercurial > p > roundup > code
comparison roundup/cgi/templating.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 | b358da7c89e5 |
| children | 2a7c3eeaf167 |
comparison
equal
deleted
inserted
replaced
| 8125:b358da7c89e5 | 8126:f7bd22bdef9d |
|---|---|
| 3419 """ % (self._client.client_nonce, self.base) | 3419 """ % (self._client.client_nonce, self.base) |
| 3420 | 3420 |
| 3421 def batch(self, permission='View'): | 3421 def batch(self, permission='View'): |
| 3422 """ Return a batch object for results from the "current search" | 3422 """ Return a batch object for results from the "current search" |
| 3423 """ | 3423 """ |
| 3424 sec = self._client.db.security | 3424 check = self._client.db.security.hasPermission |
| 3425 check = sec.hasPermission | |
| 3426 userid = self._client.userid | 3425 userid = self._client.userid |
| 3427 if not check('Web Access', userid): | 3426 if not check('Web Access', userid): |
| 3428 return Batch(self.client, [], self.pagesize, self.startwith, | 3427 return Batch(self.client, [], self.pagesize, self.startwith, |
| 3429 classname=self.classname) | 3428 classname=self.classname) |
| 3430 | 3429 |
| 3431 filterspec = self.filterspec | 3430 fspec = self.filterspec |
| 3432 sort = self.sort | 3431 sort = self.sort |
| 3433 group = self.group | 3432 group = self.group |
| 3434 | 3433 |
| 3435 # get the list of ids we're batching over | 3434 # get the list of ids we're batching over |
| 3436 klass = self.client.db.getclass(self.classname) | 3435 klass = self.client.db.getclass(self.classname) |
| 3452 )], klass) | 3451 )], klass) |
| 3453 else: | 3452 else: |
| 3454 matches = None | 3453 matches = None |
| 3455 | 3454 |
| 3456 # filter for visibility | 3455 # filter for visibility |
| 3457 item_ids = klass.filter(matches, filterspec, sort, group) | 3456 allowed = klass.filter_with_permissions( |
| 3458 cn = self.classname | 3457 matches, fspec, sort, group, permission=permission, userid=userid |
| 3459 if check(permission, userid, cn, only_no_check = True): | 3458 ) |
| 3460 allowed = item_ids | |
| 3461 else: | |
| 3462 # Note that is_filterable returns True if no permissions are | |
| 3463 # found. This makes it fail early (with an empty allowed list) | |
| 3464 # instead of running through all ids with an empty | |
| 3465 # permission list. | |
| 3466 if sec.is_filterable(permission, userid, cn): | |
| 3467 new_ids = set(item_ids) | |
| 3468 confirmed = set() | |
| 3469 for perm in sec.filter_iter(permission, userid, cn): | |
| 3470 fargs = perm.filter(self._client.db, userid, klass) | |
| 3471 for farg in fargs: | |
| 3472 farg.update(sort=sort, group=group, retired=False) | |
| 3473 result = klass.filter(list(new_ids), **farg) | |
| 3474 new_ids.difference_update(result) | |
| 3475 confirmed.update(result) | |
| 3476 # all allowed? | |
| 3477 if not new_ids: | |
| 3478 break | |
| 3479 # all allowed? | |
| 3480 if not new_ids: | |
| 3481 break | |
| 3482 allowed = list(confirmed) | |
| 3483 else: | |
| 3484 allowed = [id for id in item_ids | |
| 3485 if check(permission, userid, cn, itemid=id)] | |
| 3486 | 3459 |
| 3487 # return the batch object, using IDs only | 3460 # return the batch object, using IDs only |
| 3488 return Batch(self.client, allowed, self.pagesize, self.startwith, | 3461 return Batch(self.client, allowed, self.pagesize, self.startwith, |
| 3489 classname=self.classname) | 3462 classname=self.classname) |
| 3490 | 3463 |
