Fetch limit records of ResourceAccessMixin models when they are available
Closes #14788 (grafted from 5e7086dc7cc483868eca8852f4728557224c6980) --HG-- branch : 8.0
This commit is contained in:
@@ -77,7 +77,12 @@ class ResourceAccessMixin(ModelStorage):
|
||||
result = super().search(
|
||||
domain, offset=offset, limit=limit, order=order,
|
||||
count=False if enforce_access else count, query=query)
|
||||
if enforce_access:
|
||||
if not enforce_access:
|
||||
return result
|
||||
|
||||
loop = 0
|
||||
fetched = []
|
||||
while True:
|
||||
records = result
|
||||
resources = defaultdict(set)
|
||||
allowed = set()
|
||||
@@ -93,15 +98,27 @@ class ResourceAccessMixin(ModelStorage):
|
||||
('id', 'in', ids),
|
||||
]))
|
||||
|
||||
records = [
|
||||
fetched.extend([
|
||||
r for r in records
|
||||
if not r.resource or r.resource in allowed]
|
||||
if count:
|
||||
result = len(records)
|
||||
else:
|
||||
# re-browse to have same context
|
||||
result = cls.browse(records)
|
||||
return result
|
||||
if not r.resource or r.resource in allowed])
|
||||
|
||||
if limit is None or len(fetched) >= limit:
|
||||
if limit is not None:
|
||||
fetched = fetched[:limit]
|
||||
break
|
||||
|
||||
loop += 1
|
||||
result = super().search(
|
||||
domain, offset=offset + loop * limit, limit=limit, order=order,
|
||||
count=False, query=False)
|
||||
if not result:
|
||||
break
|
||||
|
||||
if count:
|
||||
return len(fetched)
|
||||
else:
|
||||
# re-browse to have same context
|
||||
return cls.browse(fetched)
|
||||
|
||||
@classmethod
|
||||
def read(cls, ids, fields_names):
|
||||
|
||||
@@ -235,3 +235,28 @@ class ResourceTestCase(TestCase):
|
||||
Note.read([note.id], ['message'])
|
||||
with self.assertRaises(AccessError):
|
||||
Note.delete([note])
|
||||
|
||||
@with_transaction()
|
||||
def test_resources_search_limit(self):
|
||||
"Test resource search limit work as expected"
|
||||
pool = Pool()
|
||||
Note = pool.get('ir.note')
|
||||
Warning_ = pool.get('res.user.warning')
|
||||
|
||||
warning1 = Warning_(user=0, name="root")
|
||||
warning1.save()
|
||||
warning2 = Warning_(user=1, name="admin")
|
||||
warning2.save()
|
||||
for i in range(100):
|
||||
note = Note(resource=warning2 if i % 3 else warning1)
|
||||
note.save()
|
||||
|
||||
with Transaction().set_context(_check_access=True):
|
||||
notes = Note.search([], limit=10, offset=0)
|
||||
self.assertEqual(len(notes), 10)
|
||||
|
||||
notes = Note.search([], limit=200, offset=0)
|
||||
self.assertEqual(len(notes), 66)
|
||||
|
||||
notes = Note.search([])
|
||||
self.assertEqual(len(notes), 66)
|
||||
|
||||
Reference in New Issue
Block a user