Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Privelege to list & view unsafe posts #714

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions server/config.yaml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ privileges:
'posts:create:anonymous': regular
'posts:create:identified': regular
'posts:list': anonymous
'posts:list:unsafe': regular
'posts:reverse_search': regular
'posts:view': anonymous
'posts:view:featured': anonymous
'posts:view:unsafe': regular
'posts:edit:content': power
'posts:edit:flags': regular
'posts:edit:notes': regular
Expand Down
2 changes: 2 additions & 0 deletions server/szurubooru/api/post_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ def create_snapshots_for_post(
def get_post(ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
auth.verify_privilege(ctx.user, "posts:view")
post = _get_post(params)
if post.safety == model.Post.SAFETY_UNSAFE:
auth.verify_privilege(ctx.user, "posts:view:unsafe")
return _serialize_post(ctx, post)


Expand Down
27 changes: 20 additions & 7 deletions server/szurubooru/search/configs/post_search_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import sqlalchemy as sa

from szurubooru import db, errors, model
from szurubooru.func import util
from szurubooru.func import auth, util
from szurubooru.search import criteria, tokens
from szurubooru.search.configs import util as search_util
from szurubooru.search.configs.base_search_config import (
Expand Down Expand Up @@ -150,6 +150,15 @@ def _category_filter(
return query.filter(expr)


def _safety_filter(
query: SaQuery, criterion: Optional[criteria.BaseCriterion], negated: bool
) -> SaQuery:
assert criterion
return search_util.create_str_filter(
model.Post.safety, _safety_transformer
)(query, criterion, negated)


class PostSearchConfig(BaseSearchConfig):
def __init__(self) -> None:
self.user = None # type: Optional[model.User]
Expand Down Expand Up @@ -208,6 +217,15 @@ def create_count_query(self, _disable_eager_loads: bool) -> SaQuery:
return db.session.query(model.Post)

def finalize_query(self, query: SaQuery) -> SaQuery:
if self.user and not auth.has_privilege(self.user, "posts:list:unsafe"):
# exclude unsafe posts:
query = _safety_filter(
query,
criteria.PlainCriterion(
model.Post.SAFETY_UNSAFE, model.Post.SAFETY_UNSAFE
),
negated=True,
)
return query.order_by(model.Post.post_id.desc())

@property
Expand Down Expand Up @@ -363,12 +381,7 @@ def named_filters(self) -> Dict[str, Filter]:
model.Post.last_feature_time
),
),
(
["safety", "rating"],
search_util.create_str_filter(
model.Post.safety, _safety_transformer
),
),
(["safety", "rating"], _safety_filter),
(["note-text"], _note_filter),
(
["flag"],
Expand Down
27 changes: 26 additions & 1 deletion server/szurubooru/tests/api/test_post_retrieving.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ def inject_config(config_injector):
"privileges": {
"posts:list": model.User.RANK_REGULAR,
"posts:view": model.User.RANK_REGULAR,
"posts:view:unsafe": model.User.RANK_REGULAR,
"posts:list:unsafe": model.User.RANK_REGULAR,
},
}
)
Expand Down Expand Up @@ -73,7 +75,10 @@ def test_trying_to_use_special_tokens_without_logging_in(
):
config_injector(
{
"privileges": {"posts:list": "anonymous"},
"privileges": {
"posts:list": "anonymous",
"posts:list:unsafe": "regular",
},
}
)
with pytest.raises(errors.SearchError):
Expand Down Expand Up @@ -125,3 +130,23 @@ def test_trying_to_retrieve_single_without_privileges(
context_factory(user=user_factory(rank=model.User.RANK_ANONYMOUS)),
{"post_id": 999},
)


def test_trying_to_retrieve_unsafe_without_privileges(
user_factory, context_factory, post_factory, config_injector
):
config_injector(
{
"privileges": {
"posts:view": "anonymous",
"posts:view:unsafe": "regular",
},
}
)
db.session.add(post_factory(id=1, safety=model.Post.SAFETY_UNSAFE))
db.session.flush()
with pytest.raises(errors.AuthError):
api.post_api.get_post(
context_factory(user=user_factory(rank=model.User.RANK_ANONYMOUS)),
{"post_id": 1},
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
import pytest

from szurubooru import db, errors, model, search
from szurubooru.func import cache


@pytest.fixture(autouse=True)
def purge_cache():
cache.purge()


@pytest.fixture
Expand Down Expand Up @@ -54,7 +60,15 @@ def executor():


@pytest.fixture
def auth_executor(executor, user_factory):
def auth_executor(executor, user_factory, config_injector):
config_injector(
{
"privileges": {
"posts:list:unsafe": model.User.RANK_REGULAR,
}
}
)

def wrapper():
auth_user = user_factory()
db.session.add(auth_user)
Expand Down Expand Up @@ -915,3 +929,28 @@ def test_search_by_tag_category(
)
db.session.flush()
verify_unpaged(input, expected_post_ids)


def test_filter_unsafe_without_privilege(
auth_executor,
verify_unpaged,
post_factory,
):
post1 = post_factory(id=1)
post2 = post_factory(id=2, safety=model.Post.SAFETY_SKETCHY)
post3 = post_factory(id=3, safety=model.Post.SAFETY_UNSAFE)
db.session.add_all([post1, post2, post3])
db.session.flush()
user = auth_executor()
user.rank = model.User.RANK_ANONYMOUS
verify_unpaged("", [1, 2])
verify_unpaged("safety:safe", [1])
verify_unpaged("safety:safe,sketchy", [1, 2])
verify_unpaged("safety:safe,sketchy,unsafe", [1, 2])
# adjust user's rank and retry
user.rank = model.User.RANK_REGULAR
cache.purge()
verify_unpaged("", [1, 2, 3])
verify_unpaged("safety:safe", [1])
verify_unpaged("safety:safe,sketchy", [1, 2])
verify_unpaged("safety:safe,sketchy,unsafe", [1, 2, 3])
11 changes: 10 additions & 1 deletion server/szurubooru/tests/search/test_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@

import pytest

from szurubooru import search
from szurubooru import search, model
from szurubooru.func import cache


@pytest.fixture(autouse=True)
def inject_config(config_injector):
config_injector(
{
"privileges": {"posts:list:unsafe": model.User.RANK_REGULAR},
}
)


def test_retrieving_from_cache():
config = unittest.mock.MagicMock()
with unittest.mock.patch("szurubooru.func.cache.has"), unittest.mock.patch(
Expand Down
Loading