"""The core's owner filters, each held by a second account whose rows must not count, show or change. Every one of these reads or writes a user-owned table through `userscope.owned_by`; the fence holds the form (no inline `Model.user_id == …`), these hold that the filter is there at all. Each test gives a second account the same kind of rows, so a filter that went missing answers with theirs. DB lane. """ from datetime import datetime, timedelta, timezone from sqlalchemy import func, select from app import debugsession, notifications, quota from app.models import DebugScreenshot, DebugSession, Notification, QuotaEvent from app.routes import tokens as tokens_routes from app.routes.auth import RESET_TTL, _issue_token def _notify(db, user, n=1, *, read=False): for i in range(n): db.add(Notification(user_id=user.id, type="t", title=f"n{i}", read=read)) db.commit() def _visible(db, user) -> int: return db.scalar( select(func.count()) .select_from(Notification) .where(Notification.user_id == user.id, Notification.dismissed.is_(False)) ) def test_the_notification_list_shows_only_mine(db, make_user, as_user): me, other = make_user(), make_user() _notify(db, me) _notify(db, other, 2) body = as_user(me).get("/api/me/notifications").json() assert (body["total"], len(body["items"])) == (1, 1) def test_the_unread_count_counts_only_mine(db, make_user, as_user): me, other = make_user(), make_user() _notify(db, me) _notify(db, other, 2) assert as_user(me).get("/api/me/notifications/unread_count").json() == {"count": 1} def test_reading_all_reads_only_mine(db, make_user, as_user): me, other = make_user(), make_user() _notify(db, me) _notify(db, other, 2) assert as_user(me).post("/api/me/notifications/read_all").status_code == 200 assert as_user(other).get("/api/me/notifications/unread_count").json() == {"count": 2} def test_clearing_all_dismisses_only_mine(db, make_user, as_user): me, other = make_user(), make_user() _notify(db, me) _notify(db, other, 2) assert as_user(me).post("/api/me/notifications/clear").status_code == 200 db.expire_all() assert (_visible(db, me), _visible(db, other)) == (0, 2) def test_trimming_read_notifications_trims_only_mine(db, make_user): me, other = make_user(), make_user() _notify(db, me, 3, read=True) _notify(db, other, 3, read=True) assert notifications.trim_read(db, me.id, cap=1) == 2 db.commit() assert _visible(db, other) == 3 def test_todays_actions_count_only_mine(db, make_user): me, other = make_user(), make_user() quota.log_action(me.id, quota.QuotaAction.VIDEOS_SEARCH) quota.log_action(other.id, quota.QuotaAction.VIDEOS_SEARCH) quota.log_action(other.id, quota.QuotaAction.VIDEOS_SEARCH) assert quota.actions_today(db, me.id, quota.QuotaAction.VIDEOS_SEARCH) == 1 def test_my_usage_sums_only_mine(db, make_user, as_user): me, other = make_user(), make_user() db.add_all( [ QuotaEvent(user_id=me.id, action="videos.list", units=5), QuotaEvent(user_id=other.id, action="videos.list", units=7), ] ) db.commit() body = as_user(me).get("/api/quota/my-usage").json() assert (body["today"], body["all_time"], body["by_action"]) == (5, 5, {"videos.list": 5}) def test_the_token_ceiling_counts_only_mine(db, make_user, as_user, monkeypatch): monkeypatch.setattr(tokens_routes, "MAX_TOKENS", 1) me, other = make_user(), make_user() first = as_user(other).post("/api/tokens", json={"name": "theirs", "preset": "hub"}) assert first.status_code == 200, first.text r = as_user(me).post("/api/tokens", json={"name": "mine", "preset": "hub"}) assert r.status_code == 200, r.text def test_a_reset_burns_only_my_other_links(client, db, make_user): me, other = make_user(), make_user() mine = _issue_token(db, me, "reset", RESET_TTL) theirs = _issue_token(db, other, "reset", RESET_TTL) db.commit() r = client.post( "/auth/password-reset/confirm", json={"token": mine, "password": "a brand new passphrase"} ) assert r.json() == {"ok": True} assert client.post("/auth/password-reset/check", json={"token": theirs}).json() == {"ok": True} def test_screenshot_storage_counts_only_mine(db, make_user): me, other = make_user(), make_user() now = datetime.now(timezone.utc) for i, (user, size) in enumerate([(me, 10), (other, 1000)]): db.add( DebugSession( id=f"s{i}", user_id=user.id, level="DEBUG", started_at=now, until=now + timedelta(hours=1), ) ) db.flush() db.add( DebugScreenshot( session_id=f"s{i}", created_at=now, mime="image/png", size=size, data=b"x" * size ) ) db.commit() assert debugsession.stored_screenshot_bytes(db, me.id) == 10