bookwyrm/bookwyrm/tests/models/test_user_model.py
2024-04-24 15:35:19 +02:00

334 lines
13 KiB
Python

""" testing models """
import json
from unittest.mock import patch
from django.contrib.auth.models import Group
from django.db import IntegrityError
from django.test import TestCase
import responses
from bookwyrm import models
from bookwyrm.management.commands import initdb
from bookwyrm.settings import DOMAIN, BASE_URL
# pylint: disable=missing-class-docstring
# pylint: disable=missing-function-docstring
class User(TestCase):
@classmethod
def setUpTestData(cls):
with (
patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"),
patch("bookwyrm.activitystreams.populate_stream_task.delay"),
patch("bookwyrm.lists_stream.populate_lists_task.delay"),
):
cls.user = models.User.objects.create_user(
f"mouse@{DOMAIN}",
"mouse@mouse.mouse",
"mouseword",
local=True,
localname="mouse",
name="hi",
summary="a summary",
bookwyrm_user=False,
)
cls.another_user = models.User.objects.create_user(
f"nutria@{DOMAIN}",
"nutria@nutria.nutria",
"nutriaword",
local=True,
localname="nutria",
name="hi",
bookwyrm_user=False,
)
initdb.init_groups()
initdb.init_permissions()
def test_computed_fields(self):
"""username instead of id here"""
expected_id = f"{BASE_URL}/user/mouse"
self.assertEqual(self.user.remote_id, expected_id)
self.assertEqual(self.user.username, f"mouse@{DOMAIN}")
self.assertEqual(self.user.localname, "mouse")
self.assertEqual(self.user.shared_inbox, f"{BASE_URL}/inbox")
self.assertEqual(self.user.inbox, f"{expected_id}/inbox")
self.assertEqual(self.user.outbox, f"{expected_id}/outbox")
self.assertEqual(self.user.followers_url, f"{expected_id}/followers")
self.assertIsNotNone(self.user.key_pair.private_key)
self.assertIsNotNone(self.user.key_pair.public_key)
def test_remote_user(self):
with patch("bookwyrm.models.user.set_remote_server.delay"):
user = models.User.objects.create_user(
"rat",
"rat@rat.rat",
"ratword",
local=False,
remote_id="https://example.com/dfjkg",
bookwyrm_user=False,
)
self.assertEqual(user.username, "rat@example.com")
def test_user_shelves(self):
shelves = models.Shelf.objects.filter(user=self.user).all()
self.assertEqual(len(shelves), 4)
names = [s.name for s in shelves]
self.assertTrue("To Read" in names)
self.assertTrue("Currently Reading" in names)
self.assertTrue("Read" in names)
self.assertTrue("Stopped Reading" in names)
ids = [s.identifier for s in shelves]
self.assertTrue("to-read" in ids)
self.assertTrue("reading" in ids)
self.assertTrue("read" in ids)
self.assertTrue("stopped-reading" in ids)
def test_activitypub_serialize(self):
activity = self.user.to_activity()
self.assertEqual(activity["id"], self.user.remote_id)
self.assertEqual(
activity["@context"],
[
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"PropertyValue": "schema:PropertyValue",
"alsoKnownAs": {"@id": "as:alsoKnownAs", "@type": "@id"},
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
"movedTo": {"@id": "as:movedTo", "@type": "@id"},
"schema": "http://schema.org#",
"value": "schema:value",
},
],
)
self.assertEqual(activity["preferredUsername"], self.user.localname)
self.assertEqual(activity["name"], self.user.name)
self.assertEqual(activity["inbox"], self.user.inbox)
self.assertEqual(activity["outbox"], self.user.outbox)
self.assertEqual(activity["bookwyrmUser"], False)
self.assertEqual(activity["discoverable"], False)
self.assertEqual(activity["type"], "Person")
def test_activitypub_outbox(self):
activity = self.user.to_outbox()
self.assertEqual(activity["type"], "OrderedCollection")
self.assertEqual(activity["id"], self.user.outbox)
self.assertEqual(activity["totalItems"], 0)
def test_save_auth_group(self):
user_attrs = {"local": True}
site = models.SiteSettings.get()
site.default_user_auth_group = Group.objects.get(name="editor")
site.save()
with (
patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"),
patch("bookwyrm.activitystreams.populate_stream_task.delay"),
patch("bookwyrm.lists_stream.populate_lists_task.delay"),
):
user = models.User.objects.create_user(
"test2",
"test2@bookwyrm.test",
localname="test2",
**user_attrs,
)
self.assertEqual(list(user.groups.all()), [Group.objects.get(name="editor")])
site.default_user_auth_group = None
site.save()
with (
patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"),
patch("bookwyrm.activitystreams.populate_stream_task.delay"),
patch("bookwyrm.lists_stream.populate_lists_task.delay"),
):
user = models.User.objects.create_user(
"test1",
"test1@bookwyrm.test",
localname="test1",
**user_attrs,
)
self.assertEqual(len(user.groups.all()), 0)
def test_set_remote_server(self):
server = models.FederatedServer.objects.create(
server_name=DOMAIN, application_type="test type", application_version=3
)
models.user.set_remote_server(self.user.id)
self.user.refresh_from_db()
self.assertEqual(self.user.federated_server, server)
@responses.activate
def test_get_or_create_remote_server(self):
responses.add(
responses.GET,
f"https://{DOMAIN}/.well-known/nodeinfo",
json={"links": [{"href": "http://www.example.com"}, {}]},
)
responses.add(
responses.GET,
"http://www.example.com",
json={"software": {"name": "hi", "version": "2"}},
)
server = models.user.get_or_create_remote_server(
DOMAIN, allow_external_connections=True
)
self.assertEqual(server.server_name, DOMAIN)
self.assertEqual(server.application_type, "hi")
self.assertEqual(server.application_version, "2")
@responses.activate
def test_get_or_create_remote_server_no_wellknown(self):
responses.add(
responses.GET, f"https://{DOMAIN}/.well-known/nodeinfo", status=404
)
server = models.user.get_or_create_remote_server(
DOMAIN, allow_external_connections=True
)
self.assertEqual(server.server_name, DOMAIN)
self.assertIsNone(server.application_type)
self.assertIsNone(server.application_version)
@responses.activate
def test_get_or_create_remote_server_no_links(self):
responses.add(
responses.GET,
f"https://{DOMAIN}/.well-known/nodeinfo",
json={"links": [{"href": "http://www.example.com"}, {}]},
)
responses.add(responses.GET, "http://www.example.com", status=404)
server = models.user.get_or_create_remote_server(
DOMAIN, allow_external_connections=True
)
self.assertEqual(server.server_name, DOMAIN)
self.assertIsNone(server.application_type)
self.assertIsNone(server.application_version)
@responses.activate
def test_get_or_create_remote_server_unknown_format(self):
responses.add(
responses.GET,
f"https://{DOMAIN}/.well-known/nodeinfo",
json={"links": [{"href": "http://www.example.com"}, {}]},
)
responses.add(responses.GET, "http://www.example.com", json={"fish": "salmon"})
server = models.user.get_or_create_remote_server(
DOMAIN, allow_external_connections=True
)
self.assertEqual(server.server_name, DOMAIN)
self.assertIsNone(server.application_type)
self.assertIsNone(server.application_version)
@patch("bookwyrm.suggested_users.remove_user_task.delay")
def test_delete_user(self, _):
"""permanently delete a user"""
self.assertTrue(self.user.is_active)
self.assertEqual(self.user.name, "hi")
self.assertEqual(self.user.summary, "a summary")
self.assertEqual(self.user.email, "mouse@mouse.mouse")
with (
patch(
"bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
) as broadcast_mock,
patch(
"bookwyrm.models.user.User.erase_user_statuses"
) as erase_statuses_mock,
):
self.user.delete()
self.assertEqual(erase_statuses_mock.call_count, 1)
# make sure the deletion is broadcast
self.assertEqual(broadcast_mock.call_count, 1)
activity = json.loads(broadcast_mock.call_args[1]["args"][1])
self.assertEqual(activity["type"], "Delete")
self.assertEqual(activity["object"], self.user.remote_id)
self.user.refresh_from_db()
# the user's account data should be deleted
self.assertIsNone(self.user.name)
self.assertIsNone(self.user.summary)
self.assertNotEqual(self.user.email, "mouse@mouse.mouse")
self.assertFalse(self.user.is_active)
@patch("bookwyrm.suggested_users.remove_user_task.delay")
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.add_status_task.delay")
@patch("bookwyrm.activitystreams.remove_status_task.delay")
def test_delete_user_erase_statuses(self, *_):
"""erase user statuses when user is deleted"""
status = models.Status.objects.create(user=self.user, content="hello")
self.assertFalse(status.deleted)
self.assertIsNotNone(status.content)
self.assertIsNone(status.deleted_date)
self.user.delete()
status.refresh_from_db()
self.assertTrue(status.deleted)
self.assertIsNone(status.content)
self.assertIsNotNone(status.deleted_date)
@patch("bookwyrm.suggested_users.remove_user_task.delay")
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
@patch("bookwyrm.activitystreams.add_status_task.delay")
def test_delete_user_erase_statuses_invalid(self, *_):
"""erase user statuses when user is deleted"""
status = models.Status.objects.create(user=self.user, content="hello")
self.assertFalse(status.deleted)
self.assertIsNotNone(status.content)
self.assertIsNone(status.deleted_date)
self.user.deactivate()
with self.assertRaises(IntegrityError):
self.user.erase_user_statuses()
status.refresh_from_db()
self.assertFalse(status.deleted)
self.assertIsNotNone(status.content)
self.assertIsNone(status.deleted_date)
def test_admins_no_admins(self):
"""list of admins"""
result = models.User.admins()
self.assertFalse(result.exists())
def test_admins_superuser(self):
"""list of admins"""
self.user.is_superuser = True
self.user.save(broadcast=False, update_fields=["is_superuser"])
result = models.User.admins()
self.assertEqual(result.count(), 1)
self.assertEqual(result.first(), self.user)
def test_admins_superuser_and_mod(self):
"""list of admins"""
self.user.is_superuser = True
self.user.save(broadcast=False, update_fields=["is_superuser"])
group = Group.objects.get(name="moderator")
self.another_user.groups.set([group])
results = models.User.admins()
self.assertEqual(results.count(), 2)
self.assertTrue(results.filter(id=self.user.id).exists())
self.assertTrue(results.filter(id=self.another_user.id).exists())
def test_admins_deleted_mod(self):
"""list of admins"""
self.user.is_superuser = True
self.user.save(broadcast=False, update_fields=["is_superuser"])
group = Group.objects.get(name="moderator")
self.another_user.groups.set([group])
self.another_user.is_active = False
self.another_user.save(broadcast=False, update_fields=None)
results = models.User.admins()
self.assertEqual(results.count(), 1)
self.assertEqual(results.first(), self.user)