Skip to content

Commit

Permalink
Merge branch 'main' into feat/api/oauth
Browse files Browse the repository at this point in the history
  • Loading branch information
SMillerDev committed Dec 7, 2023
2 parents b7ba6f1 + 193a363 commit 5d09c54
Show file tree
Hide file tree
Showing 38 changed files with 1,182 additions and 96 deletions.
2 changes: 1 addition & 1 deletion bookwyrm/activitypub/base_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ def resolve_remote_id(

def get_representative():
"""Get or create an actor representing the instance
to sign requests to 'secure mastodon' servers"""
to sign outgoing HTTP GET requests"""
username = f"{INSTANCE_ACTOR_USERNAME}@{DOMAIN}"
email = "bookwyrm@localhost"
try:
Expand Down
2 changes: 1 addition & 1 deletion bookwyrm/book_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def search_title_author(

# filter out multiple editions of the same work
list_results = []
for work_id in set(editions_of_work[:30]):
for work_id in editions_of_work[:30]:
result = (
results.filter(parent_work=work_id)
.order_by("-rank", "-edition_rank")
Expand Down
7 changes: 3 additions & 4 deletions bookwyrm/forms/books.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
""" using django model forms """
from django import forms

from file_resubmit.widgets import ResubmitImageWidget

from bookwyrm import models
from bookwyrm.models.fields import ClearableFileInputWithWarning
from .custom_form import CustomForm
from .widgets import ArrayWidget, SelectDateWidget, Select

Expand Down Expand Up @@ -70,9 +71,7 @@ class Meta:
"published_date": SelectDateWidget(
attrs={"aria-describedby": "desc_published_date"}
),
"cover": ClearableFileInputWithWarning(
attrs={"aria-describedby": "desc_cover"}
),
"cover": ResubmitImageWidget(attrs={"aria-describedby": "desc_cover"}),
"physical_format": Select(
attrs={"aria-describedby": "desc_physical_format"}
),
Expand Down
48 changes: 48 additions & 0 deletions bookwyrm/migrations/0186_invite_request_notification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Generated by Django 3.2.20 on 2023-11-14 10:02

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("bookwyrm", "0185_alter_notification_notification_type"),
]

operations = [
migrations.AddField(
model_name="notification",
name="related_invite_requests",
field=models.ManyToManyField(to="bookwyrm.InviteRequest"),
),
migrations.AlterField(
model_name="notification",
name="notification_type",
field=models.CharField(
choices=[
("FAVORITE", "Favorite"),
("BOOST", "Boost"),
("REPLY", "Reply"),
("MENTION", "Mention"),
("TAG", "Tag"),
("FOLLOW", "Follow"),
("FOLLOW_REQUEST", "Follow Request"),
("IMPORT", "Import"),
("ADD", "Add"),
("REPORT", "Report"),
("LINK_DOMAIN", "Link Domain"),
("INVITE_REQUEST", "Invite Request"),
("INVITE", "Invite"),
("ACCEPT", "Accept"),
("JOIN", "Join"),
("LEAVE", "Leave"),
("REMOVE", "Remove"),
("GROUP_PRIVACY", "Group Privacy"),
("GROUP_NAME", "Group Name"),
("GROUP_DESCRIPTION", "Group Description"),
("MOVE", "Move"),
],
max_length=255,
),
),
]
54 changes: 54 additions & 0 deletions bookwyrm/migrations/0187_partial_publication_dates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Generated by Django 3.2.20 on 2023-11-09 16:57

import bookwyrm.models.fields
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("bookwyrm", "0186_invite_request_notification"),
]

operations = [
migrations.AddField(
model_name="book",
name="first_published_date_precision",
field=models.CharField(
blank=True,
choices=[
("DAY", "Day prec."),
("MONTH", "Month prec."),
("YEAR", "Year prec."),
],
editable=False,
max_length=10,
null=True,
),
),
migrations.AddField(
model_name="book",
name="published_date_precision",
field=models.CharField(
blank=True,
choices=[
("DAY", "Day prec."),
("MONTH", "Month prec."),
("YEAR", "Year prec."),
],
editable=False,
max_length=10,
null=True,
),
),
migrations.AlterField(
model_name="book",
name="first_published_date",
field=bookwyrm.models.fields.PartialDateField(blank=True, null=True),
),
migrations.AlterField(
model_name="book",
name="published_date",
field=bookwyrm.models.fields.PartialDateField(blank=True, null=True),
),
]
18 changes: 18 additions & 0 deletions bookwyrm/migrations/0188_theme_loads.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.23 on 2023-11-20 18:02

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("bookwyrm", "0187_partial_publication_dates"),
]

operations = [
migrations.AddField(
model_name="theme",
name="loads",
field=models.BooleanField(blank=True, null=True),
),
]
4 changes: 2 additions & 2 deletions bookwyrm/models/book.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ class Book(BookDataModel):
preview_image = models.ImageField(
upload_to="previews/covers/", blank=True, null=True
)
first_published_date = fields.DateTimeField(blank=True, null=True)
published_date = fields.DateTimeField(blank=True, null=True)
first_published_date = fields.PartialDateField(blank=True, null=True)
published_date = fields.PartialDateField(blank=True, null=True)

objects = InheritanceManager()
field_tracker = FieldTracker(fields=["authors", "title", "subtitle", "cover"])
Expand Down
37 changes: 36 additions & 1 deletion bookwyrm/models/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
from bookwyrm import activitypub
from bookwyrm.connectors import get_image
from bookwyrm.utils.sanitizer import clean
from bookwyrm.utils.partial_date import (
PartialDate,
PartialDateModel,
from_partial_isoformat,
)
from bookwyrm.settings import MEDIA_FULL_URL


Expand Down Expand Up @@ -539,7 +544,6 @@ def field_to_activity(self, value):
def field_from_activity(self, value, allow_external_connections=True):
missing_fields = datetime(1970, 1, 1) # "2022-10" => "2022-10-01"
try:
# TODO(dato): investigate `ignoretz=True` wrt bookwyrm#3028.
date_value = dateutil.parser.parse(value, default=missing_fields)
try:
return timezone.make_aware(date_value)
Expand All @@ -549,6 +553,37 @@ def field_from_activity(self, value, allow_external_connections=True):
return None


class PartialDateField(ActivitypubFieldMixin, PartialDateModel):
"""activitypub-aware partial date field"""

def field_to_activity(self, value) -> str:
return value.partial_isoformat() if value else None

def field_from_activity(self, value, allow_external_connections=True):
# pylint: disable=no-else-return
try:
return from_partial_isoformat(value)
except ValueError:
pass

# fallback to full ISO-8601 parsing
try:
parsed = dateutil.parser.isoparse(value)
except (ValueError, ParserError):
return None

if timezone.is_aware(parsed):
return PartialDate.from_datetime(parsed)
else:
# Should not happen on the wire, but truncate down to date parts.
return PartialDate.from_date_parts(parsed.year, parsed.month, parsed.day)

# FIXME: decide whether to fix timestamps like "2023-09-30T21:00:00-03":
# clearly Oct 1st, not Sep 30th (an unwanted side-effect of USE_TZ). It's
# basically the remnants of #3028; there is a data migration pending (see …)
# but over the wire we might get these for an indeterminate amount of time.


class HtmlField(ActivitypubFieldMixin, models.TextField):
"""a text field for storing html"""

Expand Down
31 changes: 25 additions & 6 deletions bookwyrm/models/notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .base_model import BookWyrmModel
from . import Boost, Favorite, GroupMemberInvitation, ImportJob, LinkDomain
from . import ListItem, Report, Status, User, UserFollowRequest
from .site import InviteRequest


class NotificationType(models.TextChoices):
Expand All @@ -29,6 +30,7 @@ class NotificationType(models.TextChoices):
# Admin
REPORT = "REPORT"
LINK_DOMAIN = "LINK_DOMAIN"
INVITE_REQUEST = "INVITE_REQUEST"

# Groups
INVITE = "INVITE"
Expand Down Expand Up @@ -64,8 +66,9 @@ class Notification(BookWyrmModel):
related_list_items = models.ManyToManyField(
"ListItem", symmetrical=False, related_name="notifications"
)
related_reports = models.ManyToManyField("Report", symmetrical=False)
related_link_domains = models.ManyToManyField("LinkDomain", symmetrical=False)
related_reports = models.ManyToManyField("Report")
related_link_domains = models.ManyToManyField("LinkDomain")
related_invite_requests = models.ManyToManyField("InviteRequest")

@classmethod
@transaction.atomic
Expand Down Expand Up @@ -233,8 +236,7 @@ def notify_admins_on_report(sender, instance, created, *args, **kwargs):
return

# moderators and superusers should be notified
admins = User.admins()
for admin in admins:
for admin in User.admins():
notification, _ = Notification.objects.get_or_create(
user=admin,
notification_type=NotificationType.REPORT,
Expand All @@ -253,8 +255,7 @@ def notify_admins_on_link_domain(sender, instance, created, *args, **kwargs):
return

# moderators and superusers should be notified
admins = User.admins()
for admin in admins:
for admin in User.admins():
notification, _ = Notification.objects.get_or_create(
user=admin,
notification_type=NotificationType.LINK_DOMAIN,
Expand All @@ -263,6 +264,24 @@ def notify_admins_on_link_domain(sender, instance, created, *args, **kwargs):
notification.related_link_domains.add(instance)


@receiver(models.signals.post_save, sender=InviteRequest)
@transaction.atomic
# pylint: disable=unused-argument
def notify_admins_on_invite_request(sender, instance, created, *args, **kwargs):
"""need to handle a new invite request"""
if not created:
return

# moderators and superusers should be notified
for admin in User.admins():
notification, _ = Notification.objects.get_or_create(
user=admin,
notification_type=NotificationType.INVITE_REQUEST,
read=False,
)
notification.related_invite_requests.add(instance)


@receiver(models.signals.post_save, sender=GroupMemberInvitation)
# pylint: disable=unused-argument
def notify_user_on_group_invite(sender, instance, *args, **kwargs):
Expand Down
1 change: 1 addition & 0 deletions bookwyrm/models/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ class Theme(SiteModel):
created_date = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=50, unique=True)
path = models.CharField(max_length=50, unique=True)
loads = models.BooleanField(null=True, blank=True)

def __str__(self):
# pylint: disable=invalid-str-returned
Expand Down
13 changes: 11 additions & 2 deletions bookwyrm/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
"django.contrib.staticfiles",
"django.contrib.humanize",
"oauth2_provider",
"file_resubmit",
"sass_processor",
"bookwyrm",
"celery",
Expand Down Expand Up @@ -243,7 +244,11 @@
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.dummy.DummyCache",
}
},
"file_resubmit": {
"BACKEND": "django.core.cache.backends.dummy.DummyCache",
"LOCATION": "/tmp/file_resubmit_tests/",
},
}
else:
CACHES = {
Expand All @@ -253,7 +258,11 @@
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
}
},
"file_resubmit": {
"BACKEND": "django.core.cache.backends.filebased.FileBasedCache",
"LOCATION": "/tmp/file_resubmit/",
},
}

SESSION_ENGINE = "django.contrib.sessions.backends.cache"
Expand Down
13 changes: 10 additions & 3 deletions bookwyrm/suggested_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from bookwyrm import models
from bookwyrm.redis_store import RedisStore, r
from bookwyrm.settings import INSTANCE_ACTOR_USERNAME
from bookwyrm.tasks import app, SUGGESTED_USERS
from bookwyrm.telemetry import open_telemetry

Expand Down Expand Up @@ -98,9 +99,15 @@ def get_suggestions(self, user, local=False):
for (pk, score) in values
]
# annotate users with mutuals and shared book counts
users = models.User.objects.filter(
is_active=True, bookwyrm_user=True, id__in=[pk for (pk, _) in values]
).annotate(mutuals=Case(*annotations, output_field=IntegerField(), default=0))
users = (
models.User.objects.filter(
is_active=True, bookwyrm_user=True, id__in=[pk for (pk, _) in values]
)
.annotate(
mutuals=Case(*annotations, output_field=IntegerField(), default=0)
)
.exclude(localname=INSTANCE_ACTOR_USERNAME)
)
if local:
users = users.filter(local=True)
return users.order_by("-mutuals")[:5]
Expand Down
20 changes: 20 additions & 0 deletions bookwyrm/templates/403.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load utilities %}

{% block title %}{% trans "Oh no!" %}{% endblock %}

{% block content %}
<div class="block">
<h1 class="title">{% trans "Permission Denied" %}</h1>
<p class="content">
{% blocktrans trimmed with level=request.user|get_user_permission %}
You do not have permission to view this page or perform this action. Your user permission level is <code>{{ level }}</code>.
{% endblocktrans %}
</p>
<p class="content">{% trans "If you think you should have access, please speak to your BookWyrm server administrator." %}
</p>

</div>
{% endblock %}

Loading

0 comments on commit 5d09c54

Please sign in to comment.