mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-07-29 07:14:56 +00:00
fix(profiling): assign realistic document ownership so seed data exercises the guardian permission path
This commit is contained in:
+32
-17
@@ -10,6 +10,7 @@ from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.models import User
|
||||
from guardian.shortcuts import assign_perm
|
||||
|
||||
from documents.models import Document
|
||||
from documents.tests.factories import CorrespondentFactory
|
||||
from documents.tests.factories import DocumentFactory
|
||||
from documents.tests.factories import DocumentTypeFactory
|
||||
@@ -18,13 +19,17 @@ from documents.tests.factories import TagFactory
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from documents.models import Correspondent
|
||||
from documents.models import Document
|
||||
from documents.models import DocumentType
|
||||
from documents.models import StoragePath
|
||||
from documents.models import Tag
|
||||
|
||||
ScaleProfile = Literal["medium", "large"]
|
||||
|
||||
# Fraction of seeded documents given a real owner; the remainder stays
|
||||
# owner=None, mirroring a real install's mix of owned and legacy/imported
|
||||
# unowned documents.
|
||||
_OWNED_FRACTION = 0.9
|
||||
|
||||
|
||||
class _ScaleCounts:
|
||||
__slots__ = (
|
||||
@@ -140,7 +145,20 @@ def seed_permission_dataset(
|
||||
for user in users:
|
||||
user.groups.add(rng.choice(groups))
|
||||
|
||||
documents = tuple(DocumentFactory.create_batch(counts.documents))
|
||||
documents = list(DocumentFactory.create_batch(counts.documents))
|
||||
|
||||
# Assign realistic ownership -- without this, every document stays
|
||||
# owner=None and the "owned or unowned" visibility clause is trivially
|
||||
# true for every row, so no guardian permission check ever needs to run
|
||||
# (see the amendment note above this code block).
|
||||
owned_documents = []
|
||||
for document in documents:
|
||||
if rng.random() < _OWNED_FRACTION:
|
||||
document.owner = rng.choice(users)
|
||||
owned_documents.append(document)
|
||||
Document.objects.bulk_update(owned_documents, ["owner"], batch_size=2_000)
|
||||
documents = tuple(documents)
|
||||
|
||||
tags = tuple(TagFactory.create_batch(counts.tags))
|
||||
correspondents = tuple(CorrespondentFactory.create_batch(counts.correspondents))
|
||||
document_types = tuple(DocumentTypeFactory.create_batch(counts.document_types))
|
||||
@@ -149,29 +167,26 @@ def seed_permission_dataset(
|
||||
n_user_perms = round(counts.documents * _USER_PERM_ROWS_PER_DOC)
|
||||
n_group_perms = round(counts.documents * _GROUP_PERM_ROWS_PER_DOC)
|
||||
|
||||
# guardian's assign_perm is a get_or_create on the (subject, object,
|
||||
# permission) triple, so drawing (subject, document) pairs *with*
|
||||
# replacement -- rng.choice/rng.choice in a loop -- collides far more
|
||||
# than the raw draw count suggests once the subject pool is small
|
||||
# relative to the number of draws (a birthday-paradox effect): e.g. at
|
||||
# medium scale, 45,387 draws over only 5 groups x 20,000 documents =
|
||||
# 100,000 slots yields ~36,500 *distinct* pairs, not ~45,387. Sampling
|
||||
# distinct pairs up front guarantees the seeded row counts actually
|
||||
# land on the real-install ratios the scale profiles are derived from.
|
||||
for user_idx, doc_idx in _sample_distinct_pairs(
|
||||
# Grant permissions only on OWNED documents -- a grant on an already-
|
||||
# unowned document is a no-op for visibility (unowned documents are
|
||||
# visible to everyone regardless), so restricting the pool here is what
|
||||
# makes each assign_perm() call actually matter for someone, and is
|
||||
# what exercises the guardian-permission-join code path this profiling
|
||||
# effort exists to measure.
|
||||
for user_idx, owned_idx in _sample_distinct_pairs(
|
||||
rng,
|
||||
len(users),
|
||||
len(documents),
|
||||
len(owned_documents),
|
||||
n_user_perms,
|
||||
):
|
||||
assign_perm("view_document", users[user_idx], documents[doc_idx])
|
||||
for group_idx, doc_idx in _sample_distinct_pairs(
|
||||
assign_perm("view_document", users[user_idx], owned_documents[owned_idx])
|
||||
for group_idx, owned_idx in _sample_distinct_pairs(
|
||||
rng,
|
||||
len(groups),
|
||||
len(documents),
|
||||
len(owned_documents),
|
||||
n_group_perms,
|
||||
):
|
||||
assign_perm("view_document", groups[group_idx], documents[doc_idx])
|
||||
assign_perm("view_document", groups[group_idx], owned_documents[owned_idx])
|
||||
|
||||
return SeededData(
|
||||
users=users,
|
||||
|
||||
Reference in New Issue
Block a user