diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py index 527d2f425..5ccd9f91d 100644 --- a/bookwyrm/connectors/abstract_connector.py +++ b/bookwyrm/connectors/abstract_connector.py @@ -216,11 +216,7 @@ def get_data(url): raise ConnectorException() if not resp.ok: - try: - resp.raise_for_status() - except requests.exceptions.HTTPError as e: - logger.exception(e) - raise ConnectorException() + raise ConnectorException() try: data = resp.json() except ValueError as e: diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py index 84293725f..d934681e0 100644 --- a/bookwyrm/models/activitypub_mixin.py +++ b/bookwyrm/models/activitypub_mixin.py @@ -282,7 +282,7 @@ class OrderedCollectionPageMixin(ObjectMixin): def to_ordered_collection(self, queryset, \ remote_id=None, page=False, collection_only=False, **kwargs): - ''' an ordered collection of whatevers ''' + 'pure=pure, '' an ordered collection of whatevers ''' if not queryset.ordered: raise RuntimeError('queryset must be ordered') @@ -472,7 +472,7 @@ def sign_and_send(sender, data, destination): # pylint: disable=unused-argument def to_ordered_collection_page( - queryset, remote_id, id_only=False, page=1, **kwargs): + queryset, remote_id, id_only=False, page=1, pure=False, **kwargs): ''' serialize and pagiante a queryset ''' paginated = Paginator(queryset, PAGE_LENGTH) @@ -480,7 +480,7 @@ def to_ordered_collection_page( if id_only: items = [s.remote_id for s in activity_page.object_list] else: - items = [s.to_activity() for s in activity_page.object_list] + items = [s.to_activity(pure=pure) for s in activity_page.object_list] prev_page = next_page = None if activity_page.has_next(): diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index a65317fa3..9a6e6d665 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -9,7 +9,7 @@ from django.db import models from django.utils import timezone from bookwyrm import activitypub -from bookwyrm.connectors import get_data +from bookwyrm.connectors import get_data, ConnectorException from bookwyrm.models.shelf import Shelf from bookwyrm.models.status import Status, Review from bookwyrm.settings import DOMAIN @@ -112,6 +112,16 @@ class User(OrderedCollectionPageMixin, AbstractUser): activity_serializer = activitypub.Person + @classmethod + def viewer_aware_objects(cls, viewer): + ''' the user queryset filtered for the context of the logged in user ''' + queryset = cls.objects.filter(is_active=True) + if viewer.is_authenticated: + queryset = queryset.exclude( + blocks=viewer + ) + return queryset + def to_outbox(self, filter_type=None, **kwargs): ''' an ordered collection of statuses ''' if filter_type: @@ -319,7 +329,7 @@ def set_remote_server(user_id): actor_parts = urlparse(user.remote_id) user.federated_server = \ get_or_create_remote_server(actor_parts.netloc) - user.save() + user.save(broadcast=False) if user.bookwyrm_user: get_remote_reviews.delay(user.outbox) @@ -333,19 +343,24 @@ def get_or_create_remote_server(domain): except FederatedServer.DoesNotExist: pass - data = get_data('https://%s/.well-known/nodeinfo' % domain) - try: - nodeinfo_url = data.get('links')[0].get('href') - except (TypeError, KeyError): - return None + data = get_data('https://%s/.well-known/nodeinfo' % domain) + try: + nodeinfo_url = data.get('links')[0].get('href') + except (TypeError, KeyError): + raise ConnectorException() + + data = get_data(nodeinfo_url) + application_type = data.get('software', {}).get('name') + application_version = data.get('software', {}).get('version') + except ConnectorException: + application_type = application_version = None - data = get_data(nodeinfo_url) server = FederatedServer.objects.create( server_name=domain, - application_type=data['software']['name'], - application_version=data['software']['version'], + application_type=application_type, + application_version=application_version, ) return server diff --git a/bookwyrm/static/css/format.css b/bookwyrm/static/css/format.css index 50ce101eb..9d4b3105f 100644 --- a/bookwyrm/static/css/format.css +++ b/bookwyrm/static/css/format.css @@ -100,9 +100,6 @@ .cover-container.is-medium { height: 100px; } - .cover-container.is-small { - height: 70px; - } } .cover-container.is-medium .no-cover div { diff --git a/bookwyrm/templates/about.html b/bookwyrm/templates/about.html deleted file mode 100644 index aa7426cad..000000000 --- a/bookwyrm/templates/about.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends 'layout.html' %} -{% block content %} - -
-
- {% include 'snippets/about.html' %} -
- -
-

Code of Conduct

-
- {{ site.code_of_conduct | safe }} -
-
-
-{% endblock %} diff --git a/bookwyrm/templates/author.html b/bookwyrm/templates/author.html index a875ad78a..9f2054d0a 100644 --- a/bookwyrm/templates/author.html +++ b/bookwyrm/templates/author.html @@ -2,7 +2,7 @@ {% load bookwyrm_tags %} {% block content %}
-
+

{{ author.name }}

diff --git a/bookwyrm/templates/book.html b/bookwyrm/templates/book.html index 0bef2856b..dc7d4ce83 100644 --- a/bookwyrm/templates/book.html +++ b/bookwyrm/templates/book.html @@ -4,7 +4,7 @@ {% block content %}
-
+

{{ book.title }}{% if book.subtitle %}: @@ -42,26 +42,10 @@

Add cover

{% csrf_token %} -
-
-
- -
-
-
- -
-
+ +
{% endif %} @@ -242,7 +226,7 @@
{% for review in reviews %}
- {% include 'snippets/status.html' with status=review hide_book=True depth=1 %} + {% include 'snippets/status/status.html' with status=review hide_book=True depth=1 %}
{% endfor %} diff --git a/bookwyrm/templates/discover/about.html b/bookwyrm/templates/discover/about.html new file mode 100644 index 000000000..091158070 --- /dev/null +++ b/bookwyrm/templates/discover/about.html @@ -0,0 +1,22 @@ +{% extends 'layout.html' %} +{% block content %} + +
+

{{ site.name }}

+

{{ site.instance_tagline }}

+
+ +{% include 'discover/icons.html' %} + +
+ {% include 'snippets/about.html' %} +
+ +
+

Code of Conduct

+
+ {{ site.code_of_conduct | safe }} +
+
+ +{% endblock %} diff --git a/bookwyrm/templates/discover.html b/bookwyrm/templates/discover/discover.html similarity index 62% rename from bookwyrm/templates/discover.html rename to bookwyrm/templates/discover/discover.html index 27e26e539..5a808bf7d 100644 --- a/bookwyrm/templates/discover.html +++ b/bookwyrm/templates/discover/discover.html @@ -1,33 +1,14 @@ {% extends 'layout.html' %} {% block content %} -{% if not request.user.is_authenticated %}

{{ site.name }}

{{ site.instance_tagline }}

-
-
-
-

-

Decentralized

-
-
-
-
-

-

Friendly

-
-
-
-
-

-

Anti-Corporate

-
-
-
+{% include 'discover/icons.html' %} +{% if not request.user.is_authenticated %}
@@ -49,10 +30,6 @@
-{% else %} -
-

Discover

-
{% endif %}
@@ -63,18 +40,18 @@
- {% include 'snippets/discover/large-book.html' with book=books.0 %} + {% include 'discover/large-book.html' with book=books.0 %}
- {% include 'snippets/discover/small-book.html' with book=books.1 %} + {% include 'discover/small-book.html' with book=books.1 %}
- {% include 'snippets/discover/small-book.html' with book=books.2 %} + {% include 'discover/small-book.html' with book=books.2 %}
@@ -83,18 +60,18 @@
- {% include 'snippets/discover/small-book.html' with book=books.3 %} + {% include 'discover/small-book.html' with book=books.3 %}
- {% include 'snippets/discover/small-book.html' with book=books.4 %} + {% include 'discover/small-book.html' with book=books.4 %}
- {% include 'snippets/discover/large-book.html' with book=books.5 %} + {% include 'discover/large-book.html' with book=books.5 %}
diff --git a/bookwyrm/templates/discover/icons.html b/bookwyrm/templates/discover/icons.html new file mode 100644 index 000000000..a40862824 --- /dev/null +++ b/bookwyrm/templates/discover/icons.html @@ -0,0 +1,21 @@ +
+
+
+

+

Decentralized

+
+
+
+
+

+

Friendly

+
+
+
+
+

+

Anti-Corporate

+
+
+
+ diff --git a/bookwyrm/templates/snippets/discover/large-book.html b/bookwyrm/templates/discover/large-book.html similarity index 85% rename from bookwyrm/templates/snippets/discover/large-book.html rename to bookwyrm/templates/discover/large-book.html index 37b359478..401411a11 100644 --- a/bookwyrm/templates/snippets/discover/large-book.html +++ b/bookwyrm/templates/discover/large-book.html @@ -2,7 +2,7 @@ {% if book %}
- {% include 'snippets/book_cover.html' with book=book size="large" %} + {% include 'snippets/book_cover.html' with book=book size="large" %} {% include 'snippets/stars.html' with rating=ratings|dict_key:book.id %}
diff --git a/bookwyrm/templates/snippets/discover/small-book.html b/bookwyrm/templates/discover/small-book.html similarity index 79% rename from bookwyrm/templates/snippets/discover/small-book.html rename to bookwyrm/templates/discover/small-book.html index be399df66..d1676b6b1 100644 --- a/bookwyrm/templates/snippets/discover/small-book.html +++ b/bookwyrm/templates/discover/small-book.html @@ -1,6 +1,6 @@ {% load bookwyrm_tags %} {% if book %} -{% include 'snippets/book_cover.html' with book=book %} +{% include 'snippets/book_cover.html' with book=book %} {% if ratings %} {% include 'snippets/stars.html' with rating=ratings|dict_key:book.id %} {% endif %} diff --git a/bookwyrm/templates/edit_book.html b/bookwyrm/templates/edit_book.html index 6e7e434e8..fb0bb81c3 100644 --- a/bookwyrm/templates/edit_book.html +++ b/bookwyrm/templates/edit_book.html @@ -62,7 +62,7 @@

Cover

-

{{ form.cover }}

+

{{ form.cover }}

{% for error in form.cover.errors %}

{{ error | escape }}

{% endfor %} diff --git a/bookwyrm/templates/feed/direct_messages.html b/bookwyrm/templates/feed/direct_messages.html index 8c53cbeb1..f3102ee7e 100644 --- a/bookwyrm/templates/feed/direct_messages.html +++ b/bookwyrm/templates/feed/direct_messages.html @@ -16,7 +16,7 @@ {% endif %} {% for activity in activities %}
- {% include 'snippets/status.html' with status=activity %} + {% include 'snippets/status/status.html' with status=activity %}
{% endfor %} diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index 8d6152e2c..7029fd695 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -32,7 +32,7 @@ {% endif %} {% for activity in activities %}
-{% include 'snippets/status.html' with status=activity %} +{% include 'snippets/status/status.html' with status=activity %}
{% endfor %} diff --git a/bookwyrm/templates/feed/thread.html b/bookwyrm/templates/feed/thread.html index aa67d5bb5..18ab6ea38 100644 --- a/bookwyrm/templates/feed/thread.html +++ b/bookwyrm/templates/feed/thread.html @@ -8,7 +8,7 @@ {% endwith %} {% endif %} -{% include 'snippets/status.html' with status=status main=is_root %} +{% include 'snippets/status/status.html' with status=status main=is_root %} {% if depth <= max_depth and direction >= 0 %} {% for reply in status|replies %} diff --git a/bookwyrm/templates/lists/list.html b/bookwyrm/templates/lists/list.html index 5f9baa038..c5aef6062 100644 --- a/bookwyrm/templates/lists/list.html +++ b/bookwyrm/templates/lists/list.html @@ -19,7 +19,7 @@ {% for item in items %}
  • -
    +
    @@ -73,7 +73,7 @@ {% endif %} {% for book in suggested_books %} {% if book %} -
    +
    diff --git a/bookwyrm/templates/lists/list_layout.html b/bookwyrm/templates/lists/list_layout.html index d3ff2c48d..f5855f272 100644 --- a/bookwyrm/templates/lists/list_layout.html +++ b/bookwyrm/templates/lists/list_layout.html @@ -2,7 +2,7 @@ {% load bookwyrm_tags %} {% block content %} -
    +

    {{ list.name }} {% include 'snippets/privacy-icons.html' with item=list %}

    Created {% if list.curation != 'open' %} and curated{% endif %} by {% include 'snippets/username.html' with user=list.user %}

    diff --git a/bookwyrm/templates/lists/lists.html b/bookwyrm/templates/lists/lists.html index 71d372509..259d08203 100644 --- a/bookwyrm/templates/lists/lists.html +++ b/bookwyrm/templates/lists/lists.html @@ -5,7 +5,7 @@

    Lists

    {% if request.user.is_authenticated and not lists.has_previous %} -
    +

    Your lists

    diff --git a/bookwyrm/templates/settings/manage_invites.html b/bookwyrm/templates/settings/manage_invites.html index 03b68b202..086615a92 100644 --- a/bookwyrm/templates/settings/manage_invites.html +++ b/bookwyrm/templates/settings/manage_invites.html @@ -2,28 +2,6 @@ {% block header %}Invites{% endblock %} {% load humanize %} {% block panel %} -
    - - - - - - - - {% if not invites %} - - {% endif %} - {% for invite in invites %} - - - - - - - {% endfor %} -
    LinkExpiresMax usesTimes used
    No active invites
    {{ invite.link }}{{ invite.expiry|naturaltime }}{{ invite.use_limit }}{{ invite.times_used }}
    -
    -

    Generate New Invite

    @@ -47,4 +25,27 @@
    + +
    + + + + + + + + {% if not invites %} + + {% endif %} + {% for invite in invites %} + + + + + + + {% endfor %} +
    LinkExpiresMax usesTimes used
    No active invites
    {{ invite.link }}{{ invite.expiry|naturaltime }}{{ invite.use_limit }}{{ invite.times_used }}
    + {% include 'snippets/pagination.html' with page=invites path=request.path %} +
    {% endblock %} diff --git a/bookwyrm/templates/snippets/boost_button.html b/bookwyrm/templates/snippets/boost_button.html index 08daae643..bf9143796 100644 --- a/bookwyrm/templates/snippets/boost_button.html +++ b/bookwyrm/templates/snippets/boost_button.html @@ -11,7 +11,7 @@
    {% csrf_token %} -
    +{% elif user in request.user.blocks.all %} +{% include 'snippets/block_button.html' %} {% else %} - - {% csrf_token %} - - {% if user.manually_approves_followers %} - - {% else %} - - {% endif %} - - +
    +
    + + +
    +
    + {% include 'snippets/user_options.html' with user=user class="is-small" %} +
    +
    {% endif %} diff --git a/bookwyrm/templates/snippets/rate_action.html b/bookwyrm/templates/snippets/rate_action.html index 833f2b88b..cc94f6757 100644 --- a/bookwyrm/templates/snippets/rate_action.html +++ b/bookwyrm/templates/snippets/rate_action.html @@ -9,7 +9,7 @@ -
    +
    {% for i in '12345'|make_list %} diff --git a/bookwyrm/templates/snippets/shelf.html b/bookwyrm/templates/snippets/shelf.html index 006bb4ea7..0e4e9a08f 100644 --- a/bookwyrm/templates/snippets/shelf.html +++ b/bookwyrm/templates/snippets/shelf.html @@ -1,6 +1,7 @@ {% load humanize %} {% load bookwyrm_tags %} {% if books|length > 0 %} +
    @@ -74,6 +75,7 @@ {% endfor %}
    +
    {% else %}

    This shelf is empty.

    {% if shelf.editable %} diff --git a/bookwyrm/templates/snippets/stars.html b/bookwyrm/templates/snippets/stars.html index 7d5b63d73..d15768077 100644 --- a/bookwyrm/templates/snippets/stars.html +++ b/bookwyrm/templates/snippets/stars.html @@ -1,7 +1,7 @@

    {% if rating %}{{ rating|floatformat }} star{{ rating|floatformat | pluralize }}{% else %}No rating{% endif %} {% for i in '12345'|make_list %} -

    diff --git a/bookwyrm/templates/snippets/book_preview.html b/bookwyrm/templates/snippets/status/book_preview.html similarity index 86% rename from bookwyrm/templates/snippets/book_preview.html rename to bookwyrm/templates/snippets/status/book_preview.html index 0c75f9b15..920b9f538 100644 --- a/bookwyrm/templates/snippets/book_preview.html +++ b/bookwyrm/templates/snippets/status/book_preview.html @@ -3,6 +3,7 @@
    {% include 'snippets/book_cover.html' with book=book %} + {% include 'snippets/stars.html' with rating=book|rating:request.user %} {% include 'snippets/shelve_button/shelve_button.html' with book=book %}
    diff --git a/bookwyrm/templates/snippets/status.html b/bookwyrm/templates/snippets/status/status.html similarity index 63% rename from bookwyrm/templates/snippets/status.html rename to bookwyrm/templates/snippets/status/status.html index 13d5ee7c5..162fad97f 100644 --- a/bookwyrm/templates/snippets/status.html +++ b/bookwyrm/templates/snippets/status/status.html @@ -4,8 +4,8 @@ {% include 'snippets/avatar.html' with user=status.user %} {% include 'snippets/username.html' with user=status.user %} boosted - {% include 'snippets/status_body.html' with status=status|boosted_status %} + {% include 'snippets/status/status_body.html' with status=status|boosted_status %} {% else %} - {% include 'snippets/status_body.html' with status=status %} + {% include 'snippets/status/status_body.html' with status=status %} {% endif %} {% endif %} diff --git a/bookwyrm/templates/snippets/status_body.html b/bookwyrm/templates/snippets/status/status_body.html similarity index 89% rename from bookwyrm/templates/snippets/status_body.html rename to bookwyrm/templates/snippets/status/status_body.html index 00ae54605..dfc0ac68e 100644 --- a/bookwyrm/templates/snippets/status_body.html +++ b/bookwyrm/templates/snippets/status/status_body.html @@ -5,13 +5,13 @@ {% block card-header %}

    - {% include 'snippets/status_header.html' with status=status %} + {% include 'snippets/status/status_header.html' with status=status %}

    {% endblock %} {% block card-content %} - {% include 'snippets/status_content.html' with status=status %} + {% include 'snippets/status/status_content.html' with status=status %} {% endblock %} @@ -55,7 +55,7 @@ {{ status.published_date | post_date }}
    {% endblock %} diff --git a/bookwyrm/templates/snippets/status_content.html b/bookwyrm/templates/snippets/status/status_content.html similarity index 93% rename from bookwyrm/templates/snippets/status_content.html rename to bookwyrm/templates/snippets/status/status_content.html index d6dd5ef59..0f59f7fcb 100644 --- a/bookwyrm/templates/snippets/status_content.html +++ b/bookwyrm/templates/snippets/status/status_content.html @@ -54,9 +54,9 @@ {% if status.book or status.mention_books.count %}
    {% if status.book %} - {% include 'snippets/book_preview.html' with book=status.book %} + {% include 'snippets/status/book_preview.html' with book=status.book %} {% elif status.mention_books.count %} - {% include 'snippets/book_preview.html' with book=status.mention_books.first %} + {% include 'snippets/status/book_preview.html' with book=status.mention_books.first %} {% endif %}
    {% endif %} diff --git a/bookwyrm/templates/snippets/status_header.html b/bookwyrm/templates/snippets/status/status_header.html similarity index 100% rename from bookwyrm/templates/snippets/status_header.html rename to bookwyrm/templates/snippets/status/status_header.html diff --git a/bookwyrm/templates/snippets/status_options.html b/bookwyrm/templates/snippets/status/status_options.html similarity index 100% rename from bookwyrm/templates/snippets/status_options.html rename to bookwyrm/templates/snippets/status/status_options.html diff --git a/bookwyrm/templates/user/followers.html b/bookwyrm/templates/user/followers.html index 42b8cfb03..da6fc3208 100644 --- a/bookwyrm/templates/user/followers.html +++ b/bookwyrm/templates/user/followers.html @@ -15,17 +15,13 @@

    Followers

    {% for followers in followers %} -
    -
    -
    - {% include 'snippets/avatar.html' with user=followers %} -
    -
    - {% include 'snippets/username.html' with user=followers show_full=True %} -
    -
    - {% include 'snippets/follow_button.html' with user=followers %} -
    +
    +
    + {% include 'snippets/avatar.html' with user=followers %} + {% include 'snippets/username.html' with user=followers show_full=True %} +
    +
    + {% include 'snippets/follow_button.html' with user=followers %}
    {% endfor %} diff --git a/bookwyrm/templates/user/following.html b/bookwyrm/templates/user/following.html index 9e42b783f..d734b0dcc 100644 --- a/bookwyrm/templates/user/following.html +++ b/bookwyrm/templates/user/following.html @@ -15,17 +15,13 @@

    Following

    {% for follower in user.following.all %} -
    -
    -
    - {% include 'snippets/avatar.html' with user=follower %} -
    -
    - {% include 'snippets/username.html' with user=follower show_full=True %} -
    -
    - {% include 'snippets/follow_button.html' with user=follower %} -
    +
    +
    + {% include 'snippets/avatar.html' with user=follower %} + {% include 'snippets/username.html' with user=follower show_full=True %} +
    +
    + {% include 'snippets/follow_button.html' with user=follower %}
    {% endfor %} diff --git a/bookwyrm/templates/user/lists.html b/bookwyrm/templates/user/lists.html index a006c92b1..45e4806f2 100644 --- a/bookwyrm/templates/user/lists.html +++ b/bookwyrm/templates/user/lists.html @@ -1,7 +1,7 @@ {% extends 'user/user_layout.html' %} {% block header %} -
    +

    {% if is_self %}Your diff --git a/bookwyrm/templates/user/shelf.html b/bookwyrm/templates/user/shelf.html index 5e2f532f1..e62e22184 100644 --- a/bookwyrm/templates/user/shelf.html +++ b/bookwyrm/templates/user/shelf.html @@ -38,7 +38,7 @@ {% include 'user/create_shelf_form.html' with controls_text='create-shelf-form' %}

    -
    +

    {{ shelf.name }} diff --git a/bookwyrm/templates/user/user.html b/bookwyrm/templates/user/user.html index c7f6d3b57..7c8cb8aaf 100644 --- a/bookwyrm/templates/user/user.html +++ b/bookwyrm/templates/user/user.html @@ -1,7 +1,7 @@ {% extends 'user/user_layout.html' %} {% block header %} -
    +

    User profile

    @@ -54,7 +54,7 @@ {% endif %}
    - {% if not is_self and request.user.is_authenticated %} -
    -
    - {% include 'snippets/follow_button.html' with user=user %} -
    -
    - {% include 'snippets/user_options.html' with user=user class="is-small" %} -
    -
    + {% include 'snippets/follow_button.html' with user=user %} {% endif %} {% if is_self and user.follower_requests.all %} diff --git a/bookwyrm/tests/models/test_user_model.py b/bookwyrm/tests/models/test_user_model.py index a10c89b85..ed3ad41a5 100644 --- a/bookwyrm/tests/models/test_user_model.py +++ b/bookwyrm/tests/models/test_user_model.py @@ -1,16 +1,18 @@ ''' testing models ''' from unittest.mock import patch from django.test import TestCase +import responses from bookwyrm import models from bookwyrm.settings import DOMAIN - +# pylint: disable=missing-class-docstring +# pylint: disable=missing-function-docstring class User(TestCase): def setUp(self): self.user = models.User.objects.create_user( 'mouse@%s' % DOMAIN, 'mouse@mouse.mouse', 'mouseword', - local=True, localname='mouse', name='hi') + local=True, localname='mouse', name='hi', bookwyrm_user=False) def test_computed_fields(self): ''' username instead of id here ''' @@ -28,7 +30,7 @@ class User(TestCase): 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') + remote_id='https://example.com/dfjkg', bookwyrm_user=False) self.assertEqual(user.username, 'rat@example.com') @@ -62,7 +64,7 @@ class User(TestCase): 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'], True) + self.assertEqual(activity['bookwyrmUser'], False) self.assertEqual(activity['discoverable'], True) self.assertEqual(activity['type'], 'Person') @@ -71,3 +73,83 @@ class User(TestCase): self.assertEqual(activity['type'], 'OrderedCollection') self.assertEqual(activity['id'], self.user.outbox) self.assertEqual(activity['totalItems'], 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, + 'https://%s/.well-known/nodeinfo' % DOMAIN, + 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) + 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, + 'https://%s/.well-known/nodeinfo' % DOMAIN, + status=404 + ) + + server = models.user.get_or_create_remote_server(DOMAIN) + 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, + 'https://%s/.well-known/nodeinfo' % DOMAIN, + 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) + 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, + 'https://%s/.well-known/nodeinfo' % DOMAIN, + 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) + self.assertEqual(server.server_name, DOMAIN) + self.assertIsNone(server.application_type) + self.assertIsNone(server.application_version) diff --git a/bookwyrm/tests/views/test_helpers.py b/bookwyrm/tests/views/test_helpers.py index b75d61d55..10221933c 100644 --- a/bookwyrm/tests/views/test_helpers.py +++ b/bookwyrm/tests/views/test_helpers.py @@ -56,12 +56,14 @@ class ViewsHelpers(TestCase): def test_get_user_from_username(self): ''' works for either localname or username ''' self.assertEqual( - views.helpers.get_user_from_username('mouse'), self.local_user) + views.helpers.get_user_from_username( + self.local_user, 'mouse'), self.local_user) self.assertEqual( views.helpers.get_user_from_username( - 'mouse@local.com'), self.local_user) + self.local_user, 'mouse@local.com'), self.local_user) with self.assertRaises(models.User.DoesNotExist): - views.helpers.get_user_from_username('mojfse@example.com') + views.helpers.get_user_from_username( + self.local_user, 'mojfse@example.com') def test_is_api_request(self): @@ -188,18 +190,18 @@ class ViewsHelpers(TestCase): def test_is_bookwyrm_request(self): ''' checks if a request came from a bookwyrm instance ''' request = self.factory.get('', {'q': 'Test Book'}) - self.assertFalse(views.helpers.is_bookworm_request(request)) + self.assertFalse(views.helpers.is_bookwyrm_request(request)) request = self.factory.get( '', {'q': 'Test Book'}, HTTP_USER_AGENT=\ "http.rb/4.4.1 (Mastodon/3.3.0; +https://mastodon.social/)" ) - self.assertFalse(views.helpers.is_bookworm_request(request)) + self.assertFalse(views.helpers.is_bookwyrm_request(request)) request = self.factory.get( '', {'q': 'Test Book'}, HTTP_USER_AGENT=USER_AGENT) - self.assertTrue(views.helpers.is_bookworm_request(request)) + self.assertTrue(views.helpers.is_bookwyrm_request(request)) def test_existing_user(self): diff --git a/bookwyrm/tests/views/test_outbox.py b/bookwyrm/tests/views/test_outbox.py index d59f028c5..7986dea61 100644 --- a/bookwyrm/tests/views/test_outbox.py +++ b/bookwyrm/tests/views/test_outbox.py @@ -7,6 +7,7 @@ from django.test import TestCase from django.test.client import RequestFactory from bookwyrm import models, views +from bookwyrm.settings import USER_AGENT # pylint: disable=too-many-public-methods @@ -90,3 +91,39 @@ class OutboxView(TestCase): data = json.loads(result.content) self.assertEqual(data['type'], 'OrderedCollection') self.assertEqual(data['totalItems'], 1) + + def test_outbox_bookwyrm_request_true(self): + ''' should differentiate between bookwyrm and outside requests ''' + with patch('bookwyrm.models.activitypub_mixin.broadcast_task.delay'): + models.Review.objects.create( + name='hi', + content='look at this', + user=self.local_user, + book=self.book, + privacy='public', + ) + + request = self.factory.get('', {'page': 1}, HTTP_USER_AGENT=USER_AGENT) + result = views.Outbox.as_view()(request, 'mouse') + + data = json.loads(result.content) + self.assertEqual(len(data['orderedItems']), 1) + self.assertEqual(data['orderedItems'][0]['type'], 'Review') + + def test_outbox_bookwyrm_request_false(self): + ''' should differentiate between bookwyrm and outside requests ''' + with patch('bookwyrm.models.activitypub_mixin.broadcast_task.delay'): + models.Review.objects.create( + name='hi', + content='look at this', + user=self.local_user, + book=self.book, + privacy='public', + ) + + request = self.factory.get('', {'page': 1}) + result = views.Outbox.as_view()(request, 'mouse') + + data = json.loads(result.content) + self.assertEqual(len(data['orderedItems']), 1) + self.assertEqual(data['orderedItems'][0]['type'], 'Article') diff --git a/bookwyrm/tests/views/test_rss_feed.py b/bookwyrm/tests/views/test_rss_feed.py index 2b5e415e7..3d5bec49a 100644 --- a/bookwyrm/tests/views/test_rss_feed.py +++ b/bookwyrm/tests/views/test_rss_feed.py @@ -41,6 +41,7 @@ class RssFeedView(TestCase): ''' load an rss feed ''' view = rss_feed.RssFeed() request = self.factory.get('/user/rss_user/rss') + request.user = self.user with patch("bookwyrm.models.SiteSettings.objects.get") as site: site.return_value = self.site result = view(request, username=self.user.username) diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index 0e550f0c8..c229b7c9e 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -13,7 +13,7 @@ from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.settings import PAGE_LENGTH from .helpers import get_activity_feed from .helpers import get_user_from_username -from .helpers import is_api_request, is_bookworm_request, object_visible_to_user +from .helpers import is_api_request, is_bookwyrm_request, object_visible_to_user # pylint: disable= no-self-use @@ -65,7 +65,7 @@ class DirectMessage(View): user = None if username: try: - user = get_user_from_username(username) + user = get_user_from_username(request.user, username) except models.User.DoesNotExist: pass if user: @@ -91,7 +91,7 @@ class Status(View): def get(self, request, username, status_id): ''' display a particular status (and replies, etc) ''' try: - user = get_user_from_username(username) + user = get_user_from_username(request.user, username) status = models.Status.objects.select_subclasses().get( id=status_id, deleted=False) except ValueError: @@ -107,7 +107,7 @@ class Status(View): if is_api_request(request): return ActivitypubResponse( - status.to_activity(pure=not is_bookworm_request(request))) + status.to_activity(pure=not is_bookwyrm_request(request))) data = {**feed_page_data(request.user), **{ 'title': 'Status by %s' % user.username, diff --git a/bookwyrm/views/follow.py b/bookwyrm/views/follow.py index c59f2e6d2..e1b1a0bbd 100644 --- a/bookwyrm/views/follow.py +++ b/bookwyrm/views/follow.py @@ -13,7 +13,7 @@ def follow(request): ''' follow another user, here or abroad ''' username = request.POST['user'] try: - to_follow = get_user_from_username(username) + to_follow = get_user_from_username(request.user, username) except models.User.DoesNotExist: return HttpResponseBadRequest() @@ -33,7 +33,7 @@ def unfollow(request): ''' unfollow a user ''' username = request.POST['user'] try: - to_unfollow = get_user_from_username(username) + to_unfollow = get_user_from_username(request.user, username) except models.User.DoesNotExist: return HttpResponseBadRequest() @@ -52,7 +52,7 @@ def accept_follow_request(request): ''' a user accepts a follow request ''' username = request.POST['user'] try: - requester = get_user_from_username(username) + requester = get_user_from_username(request.user, username) except models.User.DoesNotExist: return HttpResponseBadRequest() @@ -75,7 +75,7 @@ def delete_follow_request(request): ''' a user rejects a follow request ''' username = request.POST['user'] try: - requester = get_user_from_username(username) + requester = get_user_from_username(request.user, username) except models.User.DoesNotExist: return HttpResponseBadRequest() diff --git a/bookwyrm/views/goal.py b/bookwyrm/views/goal.py index 4f2d1b6f4..97f139136 100644 --- a/bookwyrm/views/goal.py +++ b/bookwyrm/views/goal.py @@ -18,7 +18,7 @@ class Goal(View): ''' track books for the year ''' def get(self, request, username, year): ''' reading goal page ''' - user = get_user_from_username(username) + user = get_user_from_username(request.user, username) year = int(year) goal = models.AnnualGoal.objects.filter( year=year, user=user @@ -42,7 +42,7 @@ class Goal(View): def post(self, request, username, year): ''' update or create an annual goal ''' - user = get_user_from_username(username) + user = get_user_from_username(request.user, username) if user != request.user: return HttpResponseNotFound() diff --git a/bookwyrm/views/helpers.py b/bookwyrm/views/helpers.py index 842b8d1c4..fac3ab0c6 100644 --- a/bookwyrm/views/helpers.py +++ b/bookwyrm/views/helpers.py @@ -9,13 +9,13 @@ from bookwyrm.status import create_generated_note from bookwyrm.utils import regex -def get_user_from_username(username): +def get_user_from_username(viewer, username): ''' helper function to resolve a localname or a username to a user ''' # raises DoesNotExist if user is now found try: - return models.User.objects.get(localname=username) + return models.User.viewer_aware_objects(viewer).get(localname=username) except models.User.DoesNotExist: - return models.User.objects.get(username=username) + return models.User.viewer_aware_objects(viewer).get(username=username) def is_api_request(request): @@ -24,8 +24,8 @@ def is_api_request(request): request.path[-5:] == '.json' -def is_bookworm_request(request): - ''' check if the request is coming from another bookworm instance ''' +def is_bookwyrm_request(request): + ''' check if the request is coming from another bookwyrm instance ''' user_agent = request.headers.get('User-Agent') if user_agent is None or \ re.search(regex.bookwyrm_user_agent, user_agent) is None: diff --git a/bookwyrm/views/invite.py b/bookwyrm/views/invite.py index bd0715a0b..6b3611fc1 100644 --- a/bookwyrm/views/invite.py +++ b/bookwyrm/views/invite.py @@ -1,5 +1,6 @@ ''' invites when registration is closed ''' from django.contrib.auth.decorators import login_required, permission_required +from django.core.paginator import Paginator from django.http import HttpResponseBadRequest from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse @@ -7,6 +8,7 @@ from django.utils.decorators import method_decorator from django.views import View from bookwyrm import forms, models +from bookwyrm.settings import PAGE_LENGTH # pylint: disable= no-self-use @@ -18,10 +20,18 @@ class ManageInvites(View): ''' create invites ''' def get(self, request): ''' invite management page ''' + try: + page = int(request.GET.get('page', 1)) + except ValueError: + page = 1 + + paginated = Paginator(models.SiteInvite.objects.filter( + user=request.user + ).order_by('-created_date'), PAGE_LENGTH) + data = { 'title': 'Invitations', - 'invites': models.SiteInvite.objects.filter( - user=request.user).order_by('-created_date'), + 'invites': paginated.page(page), 'form': forms.CreateInviteForm(), } return TemplateResponse(request, 'settings/manage_invites.html', data) @@ -36,7 +46,15 @@ class ManageInvites(View): invite.user = request.user invite.save() - return redirect('/settings/invites') + paginated = Paginator(models.SiteInvite.objects.filter( + user=request.user + ).order_by('-created_date'), PAGE_LENGTH) + data = { + 'title': 'Invitations', + 'invites': paginated.page(1), + 'form': form + } + return TemplateResponse(request, 'settings/manage_invites.html', data) class Invite(View): diff --git a/bookwyrm/views/landing.py b/bookwyrm/views/landing.py index 0d841ef04..3be3eb312 100644 --- a/bookwyrm/views/landing.py +++ b/bookwyrm/views/landing.py @@ -16,7 +16,7 @@ class About(View): data = { 'title': 'About', } - return TemplateResponse(request, 'about.html', data) + return TemplateResponse(request, 'discover/about.html', data) class Home(View): ''' discover page or home feed depending on auth ''' @@ -56,4 +56,4 @@ class Discover(View): 'books': list(set(books)), 'ratings': ratings } - return TemplateResponse(request, 'discover.html', data) + return TemplateResponse(request, 'discover/discover.html', data) diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index cfdf6d769..7286bfb4f 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -65,7 +65,7 @@ class UserLists(View): page = int(request.GET.get('page', 1)) except ValueError: page = 1 - user = get_user_from_username(username) + user = get_user_from_username(request.user, username) lists = models.List.objects.filter(user=user).all() lists = privacy_filter( request.user, lists, ['public', 'followers', 'unlisted']) diff --git a/bookwyrm/views/outbox.py b/bookwyrm/views/outbox.py index 8bfc3b3d4..5df9d1999 100644 --- a/bookwyrm/views/outbox.py +++ b/bookwyrm/views/outbox.py @@ -4,6 +4,7 @@ from django.shortcuts import get_object_or_404 from django.views import View from bookwyrm import activitypub, models +from .helpers import is_bookwyrm_request # pylint: disable= no-self-use @@ -17,6 +18,10 @@ class Outbox(View): filter_type = None return JsonResponse( - user.to_outbox(**request.GET, filter_type=filter_type), + user.to_outbox( + **request.GET, + filter_type=filter_type, + pure=not is_bookwyrm_request(request) + ), encoder=activitypub.ActivityEncoder ) diff --git a/bookwyrm/views/rss_feed.py b/bookwyrm/views/rss_feed.py index 496689ff1..aad227bff 100644 --- a/bookwyrm/views/rss_feed.py +++ b/bookwyrm/views/rss_feed.py @@ -11,7 +11,7 @@ class RssFeed(Feed): def get_object(self, request, username): ''' the user who's posts get serialized ''' - return get_user_from_username(username) + return get_user_from_username(request.user, username) def link(self, obj): diff --git a/bookwyrm/views/search.py b/bookwyrm/views/search.py index a4cd73374..98be166f4 100644 --- a/bookwyrm/views/search.py +++ b/bookwyrm/views/search.py @@ -33,7 +33,7 @@ class Search(View): handle_remote_webfinger(query) # do a user search - user_results = models.User.objects.annotate( + user_results = models.User.viewer_aware_objects(request.user).annotate( similarity=Greatest( TrigramSimilarity('username', query), TrigramSimilarity('localname', query), diff --git a/bookwyrm/views/shelf.py b/bookwyrm/views/shelf.py index 02502ff64..70d3d1dea 100644 --- a/bookwyrm/views/shelf.py +++ b/bookwyrm/views/shelf.py @@ -19,7 +19,7 @@ class Shelf(View): def get(self, request, username, shelf_identifier): ''' display a shelf ''' try: - user = get_user_from_username(username) + user = get_user_from_username(request.user, username) except models.User.DoesNotExist: return HttpResponseNotFound() diff --git a/bookwyrm/views/user.py b/bookwyrm/views/user.py index 4da0fdac1..7a238ce7c 100644 --- a/bookwyrm/views/user.py +++ b/bookwyrm/views/user.py @@ -26,7 +26,7 @@ class User(View): def get(self, request, username): ''' profile page for a user ''' try: - user = get_user_from_username(username) + user = get_user_from_username(request.user, username) except models.User.DoesNotExist: return HttpResponseNotFound() @@ -96,7 +96,7 @@ class Followers(View): def get(self, request, username): ''' list of followers ''' try: - user = get_user_from_username(username) + user = get_user_from_username(request.user, username) except models.User.DoesNotExist: return HttpResponseNotFound() @@ -121,7 +121,7 @@ class Following(View): def get(self, request, username): ''' list of followers ''' try: - user = get_user_from_username(username) + user = get_user_from_username(request.user, username) except models.User.DoesNotExist: return HttpResponseNotFound()