Creates Privacy field that handles setting to/cc
This commit is contained in:
parent
c470aeb3ce
commit
b6907f39e9
|
@ -17,13 +17,6 @@ from bookwyrm.settings import DOMAIN, PAGE_LENGTH
|
||||||
from .fields import ImageField, ManyToManyField, RemoteIdField
|
from .fields import ImageField, ManyToManyField, RemoteIdField
|
||||||
|
|
||||||
|
|
||||||
PrivacyLevels = models.TextChoices('Privacy', [
|
|
||||||
'public',
|
|
||||||
'unlisted',
|
|
||||||
'followers',
|
|
||||||
'direct'
|
|
||||||
])
|
|
||||||
|
|
||||||
class BookWyrmModel(models.Model):
|
class BookWyrmModel(models.Model):
|
||||||
''' shared fields '''
|
''' shared fields '''
|
||||||
created_date = models.DateTimeField(auto_now_add=True)
|
created_date = models.DateTimeField(auto_now_add=True)
|
||||||
|
@ -84,6 +77,9 @@ class ActivitypubMixin:
|
||||||
else:
|
else:
|
||||||
self.simple_fields.append(field)
|
self.simple_fields.append(field)
|
||||||
|
|
||||||
|
self.activity_fields = self.image_fields + \
|
||||||
|
self.many_to_many_fields + self.simple_fields
|
||||||
|
|
||||||
self.deserialize_reverse_fields = self.deserialize_reverse_fields \
|
self.deserialize_reverse_fields = self.deserialize_reverse_fields \
|
||||||
if hasattr(self, 'deserialize_reverse_fields') else []
|
if hasattr(self, 'deserialize_reverse_fields') else []
|
||||||
self.serialize_reverse_fields = self.serialize_reverse_fields \
|
self.serialize_reverse_fields = self.serialize_reverse_fields \
|
||||||
|
@ -139,19 +135,8 @@ class ActivitypubMixin:
|
||||||
def to_activity(self):
|
def to_activity(self):
|
||||||
''' convert from a model to an activity '''
|
''' convert from a model to an activity '''
|
||||||
activity = {}
|
activity = {}
|
||||||
for field in self._meta.get_fields():
|
for field in self.activity_fields:
|
||||||
if not hasattr(field, 'field_to_activity'):
|
field.set_activity_from_field(activity, self)
|
||||||
continue
|
|
||||||
value = field.field_to_activity(getattr(self, field.name))
|
|
||||||
if value is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
key = field.get_activitypub_field()
|
|
||||||
if key in activity and isinstance(activity[key], list):
|
|
||||||
# handles tags on status, which accumulate across fields
|
|
||||||
activity[key] += value
|
|
||||||
else:
|
|
||||||
activity[key] = value
|
|
||||||
|
|
||||||
if hasattr(self, 'serialize_reverse_fields'):
|
if hasattr(self, 'serialize_reverse_fields'):
|
||||||
# for example, editions of a work
|
# for example, editions of a work
|
||||||
|
|
|
@ -49,6 +49,20 @@ class ActivitypubFieldMixin:
|
||||||
setattr(instance, self.name, formatted)
|
setattr(instance, self.name, formatted)
|
||||||
|
|
||||||
|
|
||||||
|
def set_activity_from_field(self, activity, instance):
|
||||||
|
''' update the json object '''
|
||||||
|
value = getattr(instance, self.name)
|
||||||
|
formatted = self.field_to_activity(value)
|
||||||
|
if formatted is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
key = self.get_activitypub_field()
|
||||||
|
if isinstance(activity.get(key), list):
|
||||||
|
activity[key] += formatted
|
||||||
|
else:
|
||||||
|
activity[key] = value
|
||||||
|
|
||||||
|
|
||||||
def field_to_activity(self, value):
|
def field_to_activity(self, value):
|
||||||
''' formatter to convert a model value into activitypub '''
|
''' formatter to convert a model value into activitypub '''
|
||||||
if hasattr(self, 'activitypub_wrapper'):
|
if hasattr(self, 'activitypub_wrapper'):
|
||||||
|
@ -134,6 +148,52 @@ class UsernameField(ActivitypubFieldMixin, models.CharField):
|
||||||
return value.split('@')[0]
|
return value.split('@')[0]
|
||||||
|
|
||||||
|
|
||||||
|
PrivacyLevels = models.TextChoices('Privacy', [
|
||||||
|
'public',
|
||||||
|
'unlisted',
|
||||||
|
'followers',
|
||||||
|
'direct'
|
||||||
|
])
|
||||||
|
|
||||||
|
class PrivacyField(ActivitypubFieldMixin, models.CharField):
|
||||||
|
''' this maps to two differente activitypub fields '''
|
||||||
|
public = 'https://www.w3.org/ns/activitystreams#Public'
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(
|
||||||
|
*args, max_length=255,
|
||||||
|
choices=PrivacyLevels.choices, default='public')
|
||||||
|
|
||||||
|
def set_field_from_activity(self, instance, data):
|
||||||
|
to = data.to
|
||||||
|
cc = data.cc
|
||||||
|
if to == [self.public]:
|
||||||
|
setattr(instance, self.name, 'public')
|
||||||
|
elif cc == []:
|
||||||
|
setattr(instance, self.name, 'direct')
|
||||||
|
elif self.public in cc:
|
||||||
|
setattr(instance, self.name, 'unlisted')
|
||||||
|
else:
|
||||||
|
setattr(instance, self.name, 'followers')
|
||||||
|
|
||||||
|
def set_activity_from_field(self, activity, instance):
|
||||||
|
mentions = [u.remote_id for u in instance.mention_users.all()]
|
||||||
|
# this is a link to the followers list
|
||||||
|
followers = instance.user.__class__._meta.get_field('followers')\
|
||||||
|
.field_to_activity(instance.user.followers)
|
||||||
|
if self.privacy == 'public':
|
||||||
|
activity['to'] = [self.public]
|
||||||
|
activity['cc'] = [followers] + mentions
|
||||||
|
elif self.privacy == 'unlisted':
|
||||||
|
activity['to'] = [followers]
|
||||||
|
activity['cc'] = [self.public] + mentions
|
||||||
|
elif self.privacy == 'followers':
|
||||||
|
activity['to'] = [followers]
|
||||||
|
activity['cc'] = mentions
|
||||||
|
if self.privacy == 'direct':
|
||||||
|
activity['to'] = mentions
|
||||||
|
activity['cc'] = []
|
||||||
|
|
||||||
|
|
||||||
class ForeignKey(ActivitypubRelatedFieldMixin, models.ForeignKey):
|
class ForeignKey(ActivitypubRelatedFieldMixin, models.ForeignKey):
|
||||||
''' activitypub-aware foreign key field '''
|
''' activitypub-aware foreign key field '''
|
||||||
def field_to_activity(self, value):
|
def field_to_activity(self, value):
|
||||||
|
|
|
@ -8,7 +8,7 @@ from django.utils import timezone
|
||||||
|
|
||||||
from bookwyrm import books_manager
|
from bookwyrm import books_manager
|
||||||
from bookwyrm.models import ReadThrough, User, Book
|
from bookwyrm.models import ReadThrough, User, Book
|
||||||
from .base_model import PrivacyLevels
|
from .fields import PrivacyLevels
|
||||||
|
|
||||||
|
|
||||||
# Mapping goodreads -> bookwyrm shelf titles.
|
# Mapping goodreads -> bookwyrm shelf titles.
|
||||||
|
|
|
@ -4,7 +4,7 @@ from django.db import models
|
||||||
|
|
||||||
from bookwyrm import activitypub
|
from bookwyrm import activitypub
|
||||||
from .base_model import BookWyrmModel
|
from .base_model import BookWyrmModel
|
||||||
from .base_model import OrderedCollectionMixin, PrivacyLevels
|
from .base_model import OrderedCollectionMixin
|
||||||
from . import fields
|
from . import fields
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class Shelf(OrderedCollectionMixin, BookWyrmModel):
|
||||||
privacy = fields.CharField(
|
privacy = fields.CharField(
|
||||||
max_length=255,
|
max_length=255,
|
||||||
default='public',
|
default='public',
|
||||||
choices=PrivacyLevels.choices
|
choices=fields.PrivacyLevels.choices
|
||||||
)
|
)
|
||||||
books = models.ManyToManyField(
|
books = models.ManyToManyField(
|
||||||
'Edition',
|
'Edition',
|
||||||
|
|
|
@ -6,7 +6,7 @@ from model_utils.managers import InheritanceManager
|
||||||
|
|
||||||
from bookwyrm import activitypub
|
from bookwyrm import activitypub
|
||||||
from .base_model import ActivitypubMixin, OrderedCollectionPageMixin
|
from .base_model import ActivitypubMixin, OrderedCollectionPageMixin
|
||||||
from .base_model import BookWyrmModel, PrivacyLevels
|
from .base_model import BookWyrmModel
|
||||||
from . import fields
|
from . import fields
|
||||||
from .fields import image_serializer
|
from .fields import image_serializer
|
||||||
|
|
||||||
|
@ -18,11 +18,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
||||||
mention_users = fields.TagField('User', related_name='mention_user')
|
mention_users = fields.TagField('User', related_name='mention_user')
|
||||||
mention_books = fields.TagField('Edition', related_name='mention_book')
|
mention_books = fields.TagField('Edition', related_name='mention_book')
|
||||||
local = models.BooleanField(default=True)
|
local = models.BooleanField(default=True)
|
||||||
privacy = models.CharField(
|
privacy = fields.PrivacyField(max_length=255)
|
||||||
max_length=255,
|
|
||||||
default='public',
|
|
||||||
choices=PrivacyLevels.choices
|
|
||||||
)
|
|
||||||
sensitive = fields.BooleanField(default=False)
|
sensitive = fields.BooleanField(default=False)
|
||||||
# created date is different than publish date because of federated posts
|
# created date is different than publish date because of federated posts
|
||||||
published_date = fields.DateTimeField(
|
published_date = fields.DateTimeField(
|
||||||
|
@ -48,7 +44,6 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
||||||
serialize_reverse_fields = [('attachments', 'attachment')]
|
serialize_reverse_fields = [('attachments', 'attachment')]
|
||||||
deserialize_reverse_fields = [('attachments', 'attachment')]
|
deserialize_reverse_fields = [('attachments', 'attachment')]
|
||||||
|
|
||||||
#----- replies collection activitypub ----#
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def replies(cls, status):
|
def replies(cls, status):
|
||||||
''' load all replies to a status. idk if there's a better way
|
''' load all replies to a status. idk if there's a better way
|
||||||
|
@ -82,25 +77,6 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
||||||
activity = ActivitypubMixin.to_activity(self)
|
activity = ActivitypubMixin.to_activity(self)
|
||||||
activity['replies'] = self.to_replies()
|
activity['replies'] = self.to_replies()
|
||||||
|
|
||||||
# privacy controls
|
|
||||||
public = 'https://www.w3.org/ns/activitystreams#Public'
|
|
||||||
mentions = [u.remote_id for u in self.mention_users.all()]
|
|
||||||
# this is a link to the followers list:
|
|
||||||
followers = self.user.__class__._meta.get_field('followers')\
|
|
||||||
.field_to_activity(self.user.followers)
|
|
||||||
if self.privacy == 'public':
|
|
||||||
activity['to'] = [public]
|
|
||||||
activity['cc'] = [followers] + mentions
|
|
||||||
elif self.privacy == 'unlisted':
|
|
||||||
activity['to'] = [followers]
|
|
||||||
activity['cc'] = [public] + mentions
|
|
||||||
elif self.privacy == 'followers':
|
|
||||||
activity['to'] = [followers]
|
|
||||||
activity['cc'] = mentions
|
|
||||||
if self.privacy == 'direct':
|
|
||||||
activity['to'] = mentions
|
|
||||||
activity['cc'] = []
|
|
||||||
|
|
||||||
# "pure" serialization for non-bookwyrm instances
|
# "pure" serialization for non-bookwyrm instances
|
||||||
if pure:
|
if pure:
|
||||||
activity['content'] = self.pure_content
|
activity['content'] = self.pure_content
|
||||||
|
|
Loading…
Reference in New Issue