Merge branch 'main' into production

This commit is contained in:
Mouse Reeve 2020-10-27 12:18:46 -07:00
commit 7dd1deb438
12 changed files with 78 additions and 25 deletions

View file

@ -44,10 +44,9 @@ class ActivityObject:
type: str
def __init__(self, **kwargs):
''' this lets you pass in an object with fields
that aren't in the dataclass, which it ignores.
Any field in the dataclass is required or has a
default value '''
''' this lets you pass in an object with fields that aren't in the
dataclass, which it ignores. Any field in the dataclass is required or
has a default value '''
for field in fields(self):
try:
value = kwargs[field.name]
@ -59,7 +58,7 @@ class ActivityObject:
def to_model(self, model, instance=None):
''' convert from an activity to a model '''
''' convert from an activity to a model instance '''
if not isinstance(self, model.activity_serializer):
raise TypeError('Wrong activity type for model')

View file

@ -52,7 +52,6 @@ class Work(Book):
type: str = 'Work'
@dataclass(init=False)
class Author(ActivityObject):
''' author of a book '''

View file

@ -6,6 +6,7 @@ from .base_activity import ActivityObject, Image
@dataclass(init=False)
class Tombstone(ActivityObject):
''' the placeholder for a deleted status '''
url: str
published: str
deleted: str
@ -23,7 +24,6 @@ class Note(ActivityObject):
cc: List[str]
content: str
replies: Dict
# TODO: this is wrong???
attachment: List[Image] = field(default=lambda: [])
sensitive: bool = False
type: str = 'Note'

View file

@ -13,7 +13,6 @@ def get_public_recipients(user, software=None):
''' everybody and their public inboxes '''
followers = user.followers.filter(local=False)
if software:
# TODO: eventually we may want to handle particular software differently
followers = followers.filter(bookwyrm_user=(software == 'bookwyrm'))
# we want shared inboxes when available
@ -36,7 +35,6 @@ def broadcast(sender, activity, software=None, \
# start with parsing the direct recipients
recipients = [u.inbox for u in direct_recipients or []]
# and then add any other recipients
# TODO: other kinds of privacy
if privacy == 'public':
recipients += get_public_recipients(sender, software=software)
broadcast_task.delay(
@ -55,7 +53,6 @@ def broadcast_task(sender_id, activity, recipients):
try:
sign_and_send(sender, activity, recipient)
except requests.exceptions.HTTPError as e:
# TODO: maybe keep track of users who cause errors
errors.append({
'error': str(e),
'recipient': recipient,

View file

@ -6,7 +6,6 @@ from bookwyrm.tasks import app
def password_reset_email(reset_code):
''' generate a password reset email '''
# TODO; this should be tempalted
site = models.SiteSettings.get()
send_email.delay(
reset_code.user.email,

View file

@ -68,7 +68,7 @@ def shared_inbox(request):
'Like': handle_unfavorite,
},
'Update': {
'Person': None,# TODO: handle_update_user
'Person': handle_update_user,
'Document': handle_update_book,
},
}
@ -308,6 +308,20 @@ def handle_tag(activity):
status_builder.create_tag(user, book, activity['object']['name'])
@app.task
def handle_update_user(activity):
''' receive an updated user Person activity object '''
try:
user = models.User.objects.get(remote_id=activity['object']['id'])
except models.User.DoesNotExist:
# who is this person? who cares
return
activitypub.Person(
**activity['object']
).to_model(models.User, instance=user)
# model save() happens in the to_model function
@app.task
def handle_update_book(activity):
''' a remote instance changed a book (Document) '''

View file

@ -0,0 +1,18 @@
# Generated by Django 3.0.7 on 2020-10-21 01:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bookwyrm', '0055_merge_20201017_0011'),
]
operations = [
migrations.AlterField(
model_name='status',
name='deleted_date',
field=models.DateTimeField(blank=True, null=True),
),
]

View file

@ -23,7 +23,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
# the created date can't be this, because of receiving federated posts
published_date = models.DateTimeField(default=timezone.now)
deleted = models.BooleanField(default=False)
deleted_date = models.DateTimeField()
deleted_date = models.DateTimeField(blank=True, null=True)
favorites = models.ManyToManyField(
'User',
symmetrical=False,

View file

@ -15,9 +15,6 @@
<div class="control">
{{ login_form.username }}
</div>
{% for error in login_form.username.errors %}
<p class="help is-danger">{{ error | escape }}</p>
{% endfor %}
</div>
<div class="field">
<label class="label" for="id_password">Password:</label>

View file

@ -0,0 +1,30 @@
import json
import pathlib
from django.test import TestCase
from bookwyrm import models, incoming
class UpdateUser(TestCase):
def setUp(self):
self.user = models.User.objects.create_user(
'mouse', 'mouse@mouse.com', 'mouseword',
remote_id='https://example.com/user/mouse',
local=False,
localname='mouse'
)
datafile = pathlib.Path(__file__).parent.joinpath(
'../data/ap_user.json'
)
self.user_data = json.loads(datafile.read_bytes())
def test_handle_update_user(self):
self.assertIsNone(self.user.name)
self.assertEqual(self.user.localname, 'mouse')
incoming.handle_update_user({'object': self.user_data})
self.user = models.User.objects.get(id=self.user.id)
self.assertEqual(self.user.name, 'MOUSE?? MOUSE!!')
self.assertEqual(self.user.localname, 'mouse')

View file

@ -11,7 +11,14 @@ localname_regex = r'(?P<username>[\w\-_]+)'
user_path = r'^user/%s' % username_regex
local_user_path = r'^user/%s' % localname_regex
status_types = ['status', 'review', 'comment', 'quotation', 'boost', 'generatedstatus']
status_types = [
'status',
'review',
'comment',
'quotation',
'boost',
'generatedstatus'
]
status_path = r'%s/(%s)/(?P<status_id>\d+)' % \
(local_user_path, '|'.join(status_types))

View file

@ -24,14 +24,6 @@ def user_login(request):
return redirect('/login')
login_form = forms.LoginForm(request.POST)
register_form = forms.RegisterForm()
if not login_form.is_valid():
data = {
'site_settings': models.SiteSettings.get(),
'login_form': login_form,
'register_form': register_form
}
return TemplateResponse(request, 'login.html', data)
username = login_form.data['username']
username = '%s@%s' % (username, DOMAIN)
@ -42,6 +34,7 @@ def user_login(request):
return redirect(request.GET.get('next', '/'))
login_form.non_field_errors = 'Username or password are incorrect'
register_form = forms.RegisterForm()
data = {
'site_settings': models.SiteSettings.get(),
'login_form': login_form,