-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New field on `Webmention`: `has_been_read: bool = False` - New context processor `mentions.context_processors.unread_webmentions` adds `unread_webmentions` field to template context. - Added admin actions for marking as read/unread. New objects manager for Webmention with some common filters.
- Loading branch information
Showing
15 changed files
with
298 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from mentions import contract | ||
from mentions.models import Webmention | ||
|
||
|
||
def unread_webmentions(request) -> dict: | ||
if not request.user.has_perm("mentions.change_webmention"): | ||
return {} | ||
|
||
return { | ||
contract.CONTEXT_UNREAD_WEBMENTIONS: Webmention.objects.filter_unread(), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Generated by Django 4.0.8 on 2023-05-07 16:49 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('mentions', '0012_alter_hcard_options_and_more'), | ||
] | ||
|
||
operations = [ | ||
migrations.AddField( | ||
model_name='webmention', | ||
name='has_been_read', | ||
field=models.BooleanField(default=False, verbose_name='Read'), | ||
), | ||
] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
from typing import cast | ||
|
||
from django.db.models import QuerySet | ||
|
||
|
||
class WebmentionQuerySet(QuerySet): | ||
def filter(self, *args, **kwargs) -> "WebmentionQuerySet": | ||
return cast(WebmentionQuerySet, super().filter(*args, **kwargs)) | ||
|
||
def filter_unread(self) -> "WebmentionQuerySet": | ||
return self.filter(has_been_read=False) | ||
|
||
def mark_as_read(self) -> int: | ||
return self.update(has_been_read=True) | ||
|
||
def mark_as_unread(self) -> int: | ||
return self.update(has_been_read=False) | ||
|
||
def filter_approved(self) -> "WebmentionQuerySet": | ||
return self.filter(approved=True) | ||
|
||
def mark_as_approved(self) -> int: | ||
return self.update(approved=True) | ||
|
||
def mark_as_unapproved(self) -> int: | ||
return self.update(approved=False) | ||
|
||
def filter_validated(self) -> "WebmentionQuerySet": | ||
return self.filter(validated=True) | ||
|
||
def filter_public(self) -> "WebmentionQuerySet": | ||
return self.filter_approved().filter_validated() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
from django.contrib import admin | ||
from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME | ||
from django.contrib.auth.models import User | ||
from django.test.utils import override_settings | ||
from django.urls import path, reverse | ||
|
||
from mentions import permissions | ||
from mentions.models import Webmention | ||
from tests.config.urls import core_urlpatterns | ||
from tests.tests.util import testfunc | ||
from tests.tests.util.testcase import WebmentionTestCase | ||
|
||
urlpatterns = [ | ||
*core_urlpatterns, | ||
path("test-admin/", admin.site.urls), | ||
] | ||
|
||
|
||
@override_settings(ROOT_URLCONF=__name__) | ||
class AdminActionTests(WebmentionTestCase): | ||
"""Tests for Webmention admin actions `approve_webmention` and `disapprove_webmention`.""" | ||
|
||
def setUp(self) -> None: | ||
super().setUp() | ||
|
||
user_allowed = User.objects.create_user("allowed", is_staff=True) | ||
permissions.can_change_webmention.grant(user_allowed) | ||
|
||
User.objects.create_user("not_allowed", is_staff=True) | ||
|
||
def post_action(self, action: str, *pks): | ||
return self.client.post( | ||
reverse("admin:mentions_webmention_changelist"), | ||
{ | ||
"action": action, | ||
ACTION_CHECKBOX_NAME: [str(pk) for pk in pks], | ||
}, | ||
) | ||
|
||
|
||
class ApprovalActionTests(AdminActionTests): | ||
def setUp(self) -> None: | ||
super().setUp() | ||
self.pks = [ | ||
x.pk | ||
for x in [ | ||
testfunc.create_webmention(approved=True, quote="approved"), | ||
testfunc.create_webmention(approved=False, quote="not approved"), | ||
] | ||
] | ||
|
||
action_approve = "mark_webmention_approved" | ||
action_unapprove = "mark_webmention_unapproved" | ||
|
||
def _assert(self, username: str, action, should_be_approved: int): | ||
self.client.force_login(User.objects.get(username=username)) | ||
self.post_action(action, *self.pks) | ||
|
||
self.assertEqual( | ||
Webmention.objects.filter(approved=True).count(), | ||
should_be_approved, | ||
) | ||
|
||
def test_action_approve_webmention_with_permission(self): | ||
self._assert( | ||
username="allowed", | ||
action=self.action_approve, | ||
should_be_approved=2, | ||
) | ||
|
||
def test_action_approve_webmention_without_permission(self): | ||
self._assert( | ||
username="not_allowed", | ||
action=self.action_approve, | ||
should_be_approved=1, | ||
) | ||
|
||
def test_action_disapprove_webmention_with_permission(self): | ||
self._assert( | ||
username="allowed", | ||
action=self.action_unapprove, | ||
should_be_approved=0, | ||
) | ||
|
||
def test_action_disapprove_webmention_without_permission(self): | ||
self._assert( | ||
username="not_allowed", | ||
action=self.action_unapprove, | ||
should_be_approved=1, | ||
) | ||
|
||
|
||
class UnreadActionTests(AdminActionTests): | ||
def setUp(self) -> None: | ||
super().setUp() | ||
self.pks = [ | ||
x.pk | ||
for x in [ | ||
testfunc.create_webmention(has_been_read=True, quote="read"), | ||
testfunc.create_webmention(has_been_read=False, quote="unread"), | ||
] | ||
] | ||
|
||
action_read = "mark_webmention_read" | ||
action_unread = "mark_webmention_unread" | ||
|
||
def _assert(self, username: str, action, should_be_approved: int): | ||
self.client.force_login(User.objects.get(username=username)) | ||
self.post_action(action, *self.pks) | ||
|
||
self.assertEqual( | ||
Webmention.objects.filter(has_been_read=True).count(), | ||
should_be_approved, | ||
) | ||
|
||
def test_action_read_with_permission(self): | ||
self._assert( | ||
username="allowed", | ||
action=self.action_read, | ||
should_be_approved=2, | ||
) | ||
|
||
def test_action_read_without_permission(self): | ||
self._assert( | ||
username="not_allowed", | ||
action=self.action_read, | ||
should_be_approved=1, | ||
) | ||
|
||
def test_action_disapprove_with_permission(self): | ||
self._assert( | ||
username="allowed", | ||
action=self.action_unread, | ||
should_be_approved=0, | ||
) | ||
|
||
def test_action_disapprove_without_permission(self): | ||
self._assert( | ||
username="not_allowed", | ||
action=self.action_unread, | ||
should_be_approved=1, | ||
) |
Oops, something went wrong.