mirror of
https://github.com/boostorg/website-v2.git
synced 2026-01-19 04:42:17 +00:00
245 lines
8.8 KiB
Python
245 lines
8.8 KiB
Python
import pytest
|
|
from datetime import datetime, timezone
|
|
from model_bakery import baker
|
|
|
|
from ..acl import (
|
|
author_needs_moderation,
|
|
can_approve,
|
|
can_delete,
|
|
can_edit,
|
|
can_view,
|
|
moderators,
|
|
)
|
|
from ..models import NEWS_MODELS
|
|
|
|
|
|
def test_moderators_empty():
|
|
assert list(moderators().order_by("id")) == []
|
|
|
|
|
|
def test_moderators_superuser(superuser):
|
|
assert list(moderators()) == [superuser]
|
|
|
|
|
|
def test_moderators_user_with_perms(make_user):
|
|
user = make_user(perms=["news.change_entry"])
|
|
p = baker.make(
|
|
"Permission",
|
|
content_type=baker.make("ContentType", app_label="foo"),
|
|
codename="change_entry",
|
|
)
|
|
assert p.content_type.app_label == "foo"
|
|
make_user(perms=[p]) # ignored due to incorrect app_label
|
|
assert list(moderators()) == [user]
|
|
|
|
|
|
def test_moderators_user_with_group(make_user):
|
|
user = make_user(groups={"moderator": ["news.change_entry"]})
|
|
assert list(moderators()) == [user]
|
|
|
|
|
|
def test_moderators_user_inactive(regular_user, moderator_user, superuser):
|
|
moderator_user.is_active = False
|
|
moderator_user.save()
|
|
assert list(moderators()) == [superuser]
|
|
|
|
|
|
def test_moderators_many_users(regular_user, moderator_user, superuser):
|
|
baker.make("users.User", _quantity=3) # make other users
|
|
assert list(moderators().order_by("id")) == [moderator_user, superuser]
|
|
|
|
|
|
def test_moderators_complex(tp, make_user, moderator_user, superuser):
|
|
p = baker.make(
|
|
"Permission",
|
|
content_type=baker.make("ContentType", app_label="foo"),
|
|
codename="change_entry",
|
|
)
|
|
expected = [
|
|
moderator_user,
|
|
superuser,
|
|
make_user(groups={"moderator": ["news.change_entry"], "other": ["users.*"]}),
|
|
make_user(perms=["news.change_entry"]),
|
|
make_user(perms=["news.*"]),
|
|
# exercise .distinct() by having a user with perms and group
|
|
make_user(groups={"genius": ["news.change_entry"]}, perms=["news.*"]),
|
|
]
|
|
# not moderators
|
|
make_user(groups={"different": ["users.*"]})
|
|
make_user(perms=[p])
|
|
make_user(perms=[p, "news.delete_entry", "news.view_entry", "news.add_entry"])
|
|
make_user(is_staff=True)
|
|
make_user(perms=["news.change_entry"], is_active=False)
|
|
|
|
with tp.assertNumQueriesLessThan(2, verbose=True):
|
|
actual = list(moderators().order_by("id"))
|
|
|
|
assert actual == expected
|
|
|
|
|
|
@pytest.mark.parametrize("model_class", NEWS_MODELS)
|
|
@pytest.mark.parametrize("approved", [False, True])
|
|
def test_entry_permissions_author(make_entry, model_class, approved):
|
|
entry = make_entry(model_class, approved=approved)
|
|
|
|
assert can_view(entry.author, entry) is True
|
|
assert can_edit(entry.author, entry) is not approved
|
|
assert can_delete(entry.author, entry) is False
|
|
assert can_approve(entry.author, entry) is False
|
|
|
|
|
|
@pytest.mark.parametrize("model_class", NEWS_MODELS)
|
|
@pytest.mark.parametrize("approved", [False, True])
|
|
def test_entry_permissions_no_user(make_entry, model_class, approved):
|
|
entry = make_entry(model_class, approved=approved)
|
|
|
|
assert can_view(None, entry) is approved
|
|
assert can_edit(None, entry) is False
|
|
assert can_delete(None, entry) is False
|
|
assert can_approve(None, entry) is False
|
|
|
|
|
|
@pytest.mark.parametrize("model_class", NEWS_MODELS)
|
|
@pytest.mark.parametrize("approved", [False, True])
|
|
def test_entry_permissions_regular_user(
|
|
make_entry, regular_user, model_class, approved
|
|
):
|
|
entry = make_entry(model_class, approved=approved)
|
|
|
|
assert can_view(regular_user, entry) is approved
|
|
assert can_edit(regular_user, entry) is False
|
|
assert can_delete(regular_user, entry) is False
|
|
assert can_approve(regular_user, entry) is False
|
|
|
|
|
|
@pytest.mark.parametrize("model_class", NEWS_MODELS)
|
|
@pytest.mark.parametrize("approved", [False, True])
|
|
def test_entry_permissions_superuser(make_entry, superuser, model_class, approved):
|
|
entry = make_entry(model_class, approved=approved)
|
|
|
|
assert can_view(superuser, entry) is True
|
|
assert can_edit(superuser, entry) is True
|
|
assert can_delete(superuser, entry) is True
|
|
assert can_approve(superuser, entry) is True
|
|
|
|
|
|
@pytest.mark.parametrize("model_class", NEWS_MODELS)
|
|
@pytest.mark.parametrize("approved", [False, True])
|
|
def test_entry_permissions_other_users(make_user, make_entry, model_class, approved):
|
|
entry = make_entry(model_class, approved=approved)
|
|
|
|
user_with_add_perm = make_user(perms=["news.add_entry"])
|
|
assert can_view(user_with_add_perm, entry) is approved
|
|
assert can_edit(user_with_add_perm, entry) is False
|
|
assert can_delete(user_with_add_perm, entry) is False
|
|
assert can_approve(user_with_add_perm, entry) is False
|
|
|
|
user_with_change_perm = make_user(perms=["news.change_entry"])
|
|
assert can_view(user_with_change_perm, entry) is approved
|
|
assert can_edit(user_with_change_perm, entry) is True
|
|
assert can_delete(user_with_change_perm, entry) is False
|
|
assert can_approve(user_with_change_perm, entry) is True
|
|
|
|
user_with_delete_perm = make_user(perms=["news.delete_entry"])
|
|
assert can_view(user_with_delete_perm, entry) is approved
|
|
assert can_edit(user_with_delete_perm, entry) is False
|
|
assert can_delete(user_with_delete_perm, entry) is True
|
|
assert can_approve(user_with_delete_perm, entry) is False
|
|
|
|
user_with_view_perm = make_user(perms=["news.view_entry"])
|
|
assert can_view(user_with_view_perm, entry) is True
|
|
assert can_edit(user_with_view_perm, entry) is False
|
|
assert can_delete(user_with_view_perm, entry) is False
|
|
assert can_approve(user_with_view_perm, entry) is False
|
|
|
|
|
|
def test_entry_author_needs_moderation_basic(make_entry):
|
|
entry = make_entry()
|
|
|
|
assert entry.author_needs_moderation() is True
|
|
|
|
|
|
def test_entry_author_needs_moderation_moderator(make_entry, moderator_user):
|
|
entry = make_entry(author=moderator_user)
|
|
|
|
assert author_needs_moderation(entry) is False
|
|
|
|
|
|
def test_entry_author_needs_moderation_allowlist(make_entry, make_user, settings):
|
|
user = make_user()
|
|
entry = make_entry(author=user)
|
|
|
|
settings.NEWS_MODERATION_ALLOWLIST = []
|
|
assert author_needs_moderation(entry) is True
|
|
|
|
settings.NEWS_MODERATION_ALLOWLIST = [user.email]
|
|
assert author_needs_moderation(entry) is False
|
|
|
|
settings.NEWS_MODERATION_ALLOWLIST = [user.pk]
|
|
assert author_needs_moderation(entry) is False
|
|
|
|
|
|
# Tests for soft delete functionality (deleted_at field)
|
|
|
|
|
|
@pytest.mark.parametrize("model_class", NEWS_MODELS)
|
|
def test_can_view_published_entry_not_deleted(make_entry, regular_user, model_class):
|
|
"""Test that published, non-deleted entries are viewable by public."""
|
|
entry = make_entry(model_class, approved=True, deleted_at=None)
|
|
|
|
assert can_view(None, entry) is True
|
|
assert can_view(regular_user, entry) is True
|
|
|
|
|
|
@pytest.mark.parametrize("model_class", NEWS_MODELS)
|
|
def test_can_view_published_entry_deleted_public(make_entry, regular_user, model_class):
|
|
"""Test that published but deleted entries are NOT viewable by public."""
|
|
deleted_time = datetime.now(timezone.utc)
|
|
entry = make_entry(model_class, approved=True, deleted_at=deleted_time)
|
|
|
|
assert can_view(None, entry) is False
|
|
assert can_view(regular_user, entry) is False
|
|
|
|
|
|
@pytest.mark.parametrize("model_class", NEWS_MODELS)
|
|
def test_can_view_deleted_entry_by_author(make_entry, model_class):
|
|
"""Test that authors can still view their deleted entries."""
|
|
deleted_time = datetime.now(timezone.utc)
|
|
entry = make_entry(model_class, approved=True, deleted_at=deleted_time)
|
|
|
|
assert can_view(entry.author, entry) is True
|
|
|
|
|
|
@pytest.mark.parametrize("model_class", NEWS_MODELS)
|
|
def test_can_view_deleted_entry_by_moderator(make_entry, make_user, model_class):
|
|
"""Test that users with view permission can view deleted entries."""
|
|
deleted_time = datetime.now(timezone.utc)
|
|
entry = make_entry(model_class, approved=True, deleted_at=deleted_time)
|
|
|
|
user_with_view_perm = make_user(perms=["news.view_entry"])
|
|
|
|
assert can_view(user_with_view_perm, entry) is True
|
|
|
|
|
|
@pytest.mark.parametrize("model_class", NEWS_MODELS)
|
|
def test_can_view_deleted_entry_by_superuser(make_entry, superuser, model_class):
|
|
"""Test that superusers can view deleted entries."""
|
|
deleted_time = datetime.now(timezone.utc)
|
|
entry = make_entry(model_class, approved=True, deleted_at=deleted_time)
|
|
|
|
# Superuser can view deleted entries
|
|
assert can_view(superuser, entry) is True
|
|
|
|
|
|
@pytest.mark.parametrize("model_class", NEWS_MODELS)
|
|
@pytest.mark.parametrize("deleted_at_value", [None, datetime.now(timezone.utc)])
|
|
def test_can_view_unpublished_entry_with_deletion(
|
|
make_entry, regular_user, model_class, deleted_at_value
|
|
):
|
|
"""Test that unpublished entries follow same rules regardless of deletion status."""
|
|
entry = make_entry(model_class, approved=False, deleted_at=deleted_at_value)
|
|
|
|
assert can_view(None, entry) is False
|
|
assert can_view(regular_user, entry) is False
|
|
assert can_view(entry.author, entry) is True
|