Commit ab42ed9e authored by Jason Robinson's avatar Jason Robinson

Make profile default visibility public

This fixes an issue where new profiles can follow others but the
others cannot follow back, since the default was SELF. This makes
little sense as there is only name and picture to fill, which become
public to anyone who the profile communicates with. For now, make
all new profiles public by default. Later the visibility setting should
be moved from the profile to profile fields themselves. Some core
identity will always need to be public but what the profile shares
could be controlled.

Also make remote profiles always locally public to avoid situations
where a user can see the post but can't see the local profile. Any
profile that federates to us is public to some extent since it left
the server.

Closes #515
parent b80ce301
......@@ -50,6 +50,12 @@ Changed
* Streams profile API's have moved to using UUID's instead of ID's.
* Make profile default visibility public (`#515 <https://git.feneas.org/socialhome/socialhome/issues/515>`_)
This fixes an issue where new profiles can follow others but the others cannot follow back, since the default was SELF. For now, make all new profiles public by default. Later the visibility setting should be moved from the profile to profile fields themselves. Some core identity will always need to be public but what the profile shares could be controlled.
Also make remote profiles always locally public to avoid situations where a user can see the post but can't see the local profile. Any profile that federates to us is public to some extent since it left the server.
Fixed
.....
......
......@@ -3,7 +3,8 @@ from django.conf import settings
from socialhome.content.models import Content, OEmbedCache, OpenGraphCache, Tag
from socialhome.enums import Visibility
from socialhome.users.tests.factories import ProfileFactory, UserFactory, PublicProfileFactory
from socialhome.users.tests.factories import ProfileFactory, UserFactory, PublicProfileFactory, SiteProfileFactory, \
LimitedProfileFactory, SelfProfileFactory
class TagFactory(factory.DjangoModelFactory):
......@@ -30,14 +31,17 @@ class PublicContentFactory(ContentFactory):
class LimitedContentFactory(ContentFactory):
visibility = Visibility.LIMITED
author = factory.SubFactory(LimitedProfileFactory)
class SiteContentFactory(ContentFactory):
visibility = Visibility.SITE
author = factory.SubFactory(SiteProfileFactory)
class SelfContentFactory(ContentFactory):
visibility = Visibility.SELF
author = factory.SubFactory(SelfProfileFactory)
class LocalContentFactory(ContentFactory):
......
......@@ -12,11 +12,11 @@ class TestContentQuerySet(SocialhomeTestCase):
@classmethod
def setUpTestData(cls):
super().setUpTestData()
cls.public_content = PublicContentFactory(pinned=True, author=ProfileFactory())
cls.public_content = PublicContentFactory(pinned=True, author=ProfileFactory(visibility=Visibility.SELF))
cls.public_tag_content = PublicContentFactory(text="#foobar")
cls.limited_content = LimitedContentFactory()
cls.limited_content = LimitedContentFactory(author=ProfileFactory(visibility=Visibility.SELF))
cls.tag = Tag.objects.get(name="foobar")
cls.site_content = SiteContentFactory(pinned=True)
cls.site_content = SiteContentFactory(pinned=True, author=ProfileFactory(visibility=Visibility.SELF))
cls.site_tag_content = SiteContentFactory(text="#foobar")
cls.self_user = UserFactory()
cls.self_content = SelfContentFactory(author=cls.self_user.profile, pinned=True)
......
......@@ -14,7 +14,8 @@ from socialhome.federate.tasks import (
from socialhome.tests.utils import SocialhomeTestCase
from socialhome.users.models import Profile
from socialhome.users.tests.factories import (
UserFactory, ProfileFactory, PublicUserFactory, PublicProfileFactory, UserWithKeyFactory, LimitedUserFactory)
UserFactory, ProfileFactory, PublicUserFactory, PublicProfileFactory, UserWithKeyFactory, LimitedUserFactory,
SelfUserFactory)
@patch("socialhome.federate.tasks.process_entities", autospec=True)
......@@ -158,7 +159,7 @@ class TestSendProfileRetraction(SocialhomeTestCase):
cls.public_user = PublicUserFactory()
cls.public_profile = cls.public_user.profile
cls.remote_profile = PublicProfileFactory()
cls.user = UserFactory()
cls.user = SelfUserFactory()
cls.profile = cls.user.profile
cls.limited_user = LimitedUserFactory()
cls.limited_profile = cls.limited_user.profile
......
......@@ -498,7 +498,7 @@ class TestGetSenderProfile(SocialhomeTestCase):
sender_profile = get_sender_profile("https:/example.com/foo/bar")
assert isinstance(sender_profile, Profile)
assert sender_profile.name == "foobar"
assert sender_profile.visibility == Visibility.LIMITED
assert sender_profile.visibility == Visibility.PUBLIC
assert sender_profile.rsa_public_key == "xyz"
assert not sender_profile.rsa_private_key
......
......@@ -13,7 +13,8 @@ from socialhome.search.views import GlobalSearchView
from socialhome.streams.views import TagStreamView
from socialhome.tests.utils import SocialhomeCBVTestCase, SocialhomeTestCase
from socialhome.users.models import Profile
from socialhome.users.tests.factories import ProfileFactory, UserFactory, PublicProfileFactory, BaseProfileFactory
from socialhome.users.tests.factories import (
ProfileFactory, PublicProfileFactory, BaseProfileFactory, SelfUserFactory)
from socialhome.users.views import ProfileAllContentView
......@@ -21,13 +22,13 @@ class TestGlobalSearchViewQuerySet(SocialhomeCBVTestCase):
@classmethod
def setUpTestData(cls):
super().setUpTestData()
cls.staff_user = SelfUserFactory(is_staff=True)
cls.normal_user = SelfUserFactory()
haystack.connections['default'].get_backend().clear()
cls.self_profile = ProfileFactory(visibility=Visibility.SELF)
cls.public_profile = ProfileFactory(visibility=Visibility.PUBLIC)
cls.limited_profile = ProfileFactory(visibility=Visibility.LIMITED)
cls.site_profile = ProfileFactory(visibility=Visibility.SITE)
cls.staff_user = UserFactory(is_staff=True)
cls.normal_user = UserFactory()
def test_profile_visibility_authenticated_user(self):
request = RequestFactory().get('/')
......
# Generated by Django 2.0.13 on 2019-02-28 20:50
from django.db import migrations
import enumfields.fields
import socialhome.enums
class Migration(migrations.Migration):
dependencies = [
('users', '0033_profile_followed_tags'),
]
operations = [
migrations.AlterField(
model_name='profile',
name='visibility',
field=enumfields.fields.EnumIntegerField(default=0, enum=socialhome.enums.Visibility, verbose_name='Profile visibility'),
),
]
......@@ -122,7 +122,7 @@ class Profile(TimeStampedModel):
rsa_public_key = models.TextField(_("RSA public key"), null=True, editable=False)
# Profile visibility
visibility = EnumIntegerField(Visibility, verbose_name=_("Profile visibility"), default=Visibility.SELF)
visibility = EnumIntegerField(Visibility, verbose_name=_("Profile visibility"), default=Visibility.PUBLIC)
# Image urls
image_url_large = models.URLField(_("Image - large"), blank=True)
......@@ -339,7 +339,7 @@ class Profile(TimeStampedModel):
logger.info("from_remote_profile - Create or updating %s", remote_profile)
values = {
"name": safe_text(remote_profile.name),
"visibility": Visibility.PUBLIC if remote_profile.public else Visibility.LIMITED,
"visibility": Visibility.PUBLIC, # Any profile that has been federated has to be public
"image_url_large": Profile.absolute_image_url(remote_profile, "large"),
"image_url_medium": Profile.absolute_image_url(remote_profile, "medium"),
"image_url_small": Profile.absolute_image_url(remote_profile, "small"),
......
from typing import List
from enumfields.drf import EnumField
from rest_framework import serializers
from rest_framework.fields import SerializerMethodField
from rest_framework.serializers import ModelSerializer
......
......@@ -57,6 +57,15 @@ class SiteUserFactory(UserFactory):
return user
class SelfUserFactory(UserFactory):
@classmethod
def _generate(cls, create, attrs):
user = super(UserFactory, cls)._generate(create, attrs)
user.profile.visibility = Visibility.SELF
user.profile.save(update_fields=["visibility"])
return user
class UserWithKeyFactory(UserFactory):
@classmethod
def _generate(cls, create, attrs):
......@@ -118,6 +127,18 @@ class PublicProfileFactory(ProfileFactory):
visibility = Visibility.PUBLIC
class SiteProfileFactory(ProfileFactory):
visibility = Visibility.SITE
class LimitedProfileFactory(ProfileFactory):
visibility = Visibility.LIMITED
class SelfProfileFactory(ProfileFactory):
visibility = Visibility.SELF
class BaseProfileFactory(factory.Factory):
class Meta:
model = base.Profile
......
......@@ -195,7 +195,7 @@ class TestProfile(SocialhomeTestCase):
profile = Profile.from_remote_profile(remote_profile)
self.assertEqual(profile.fid, remote_profile.id)
self.assertEqual(profile.name, remote_profile.name)
self.assertEqual(profile.visibility, Visibility.LIMITED)
self.assertEqual(profile.visibility, Visibility.PUBLIC)
self.assertEqual(profile.image_url_large, remote_profile.image_urls["large"])
self.assertEqual(profile.image_url_medium, remote_profile.image_urls["medium"])
self.assertEqual(profile.image_url_small, remote_profile.image_urls["small"])
......@@ -203,12 +203,6 @@ class TestProfile(SocialhomeTestCase):
self.assertEqual(profile.email, remote_profile.email)
self.assertEqual(profile.rsa_public_key, remote_profile.public_key)
# Update to public
remote_profile_update = BaseProfileFactory(public=True, id=remote_profile.id)
profile = Profile.from_remote_profile(remote_profile_update)
self.assertEqual(profile.fid, remote_profile.id)
self.assertEqual(profile.visibility, Visibility.PUBLIC)
# Make sure public key doesn't get deleted if it doesn't have a value
public_key = profile.rsa_public_key
assert public_key
......
......@@ -13,8 +13,8 @@ class TestProfileQuerySet(SocialhomeTestCase):
cls.public_profile = ProfileFactory(visibility=Visibility.PUBLIC)
cls.site_profile = ProfileFactory(visibility=Visibility.SITE)
cls.limited_profile = ProfileFactory(visibility=Visibility.LIMITED)
cls.profile = ProfileFactory()
cls.profile2 = ProfileFactory()
cls.profile = ProfileFactory(visibility=Visibility.SELF)
cls.profile2 = ProfileFactory(visibility=Visibility.SELF)
cls.public_profile.following.add(cls.site_profile, cls.profile)
def test_visible_for_user_unauthenticated_user(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment