moo.core.tests.test_security_queryset

Security tests: QuerySet / RelatedManager access controls.

Covers: QuerySet.model raw ORM path, bulk mutation methods (update/delete/ values/create), ManyToMany parent manipulation, Property.value read guard, Verb.__call__ execute check, ACL enumeration guard, select_related safety (passes 6, 7, 8, 14).

Functions

test_acl_enumeration_allowed_for_wizard(...)

A wizard caller can still access obj.acl, since can_caller('grant') always passes for wizards.

test_acl_enumeration_via_relatedmanager(...)

get_protected_attribute and safe_getattr check can_caller('grant') before returning the acl RelatedManager on AccessibleMixin instances.

test_m2m_parents_add_blocked(t_init, t_wizard)

ManyToManyField.add() issues SQL directly without going through Object.save(), bypassing ACL checks.

test_passthrough_still_works_after_execute_check(...)

passthrough() must not be blocked by the execute check in Verb.__call__().

test_property_value_read_allowed_for_owner(...)

The owner's context can still read Property.value.

test_property_value_read_bypasses_permission_via_relatedmanager(...)

get_protected_attribute and safe_getattr enforce can_caller('read') when verb code accesses prop.value.

test_queryset_delete_bypasses_permission(...)

QuerySet.delete() issues SQL DELETE directly, bypassing model-level permission checks.

test_queryset_model_exposes_orm_via_parents(...)

QuerySet.model is blocked by get_protected_attribute and safe_getattr.

test_queryset_update_bypasses_verb_save_permission(...)

QuerySet.update() issues SQL UPDATE directly, bypassing Verb.save() permission checks.

test_queryset_values_bypasses_property_value_guard(...)

QuerySet.values() returns plain dicts whose 'value' key is not a Property instance, so the isinstance(obj, Property) guard in get_protected_attribute never fires.

test_relatedmanager_create_bypasses_add_verb_permission(...)

RelatedManager.create() routes directly to Verb.save() with pk=None, which previously skipped the write-permission check.

test_select_related_cannot_reach_queryset_model_attr(...)

select_related() returns a QuerySet.

test_select_related_does_not_expose_new_attack_surface(...)

select_related() is in _QUERYSET_ALLOWED and is actively used by verb code (e.g. at_show.py).

test_verb_direct_call_bypasses_execute_permission(...)

Verb.__call__() checks can_caller('execute', self) when an active session is present.