Skip to content
Snippets Groups Projects
Commit ecbfe6b2 authored by Jean-Baptiste Pasquier's avatar Jean-Baptiste Pasquier
Browse files

Merge branch 'get-or-create-external' into 'master'

bugfix: Model.get_or_create_external

See merge request !145
parents 272d0160 37d13648
No related branches found
No related tags found
1 merge request!145bugfix: Model.get_or_create_external
Pipeline #6615 passed
...@@ -210,7 +210,6 @@ class ActivityPubService(object): ...@@ -210,7 +210,6 @@ class ActivityPubService(object):
for field_name, relation_info in info.relations.items(): for field_name, relation_info in info.relations.items():
if not relation_info.to_many: if not relation_info.to_many:
value = getattr(instance, field_name, None) value = getattr(instance, field_name, None)
logger.debug('[Sender] model has relation ' + str(value))
if value is not None and Model.is_external(value): if value is not None and Model.is_external(value):
target_type = Model.get_model_rdf_type(type(value)) target_type = Model.get_model_rdf_type(type(value))
...@@ -218,6 +217,7 @@ class ActivityPubService(object): ...@@ -218,6 +217,7 @@ class ActivityPubService(object):
continue continue
targets.add(value.urlid) targets.add(value.urlid)
logger.debug('[Sender] model has external relation ' + str(value.urlid))
return targets return targets
......
...@@ -192,6 +192,16 @@ class Model(models.Model): ...@@ -192,6 +192,16 @@ class Model(models.Model):
field_tuples['username'] = str(uuid.uuid4()) field_tuples['username'] = str(uuid.uuid4())
return model.objects.create(urlid=urlid, is_backlink=True, **field_tuples) return model.objects.create(urlid=urlid, is_backlink=True, **field_tuples)
@classonlymethod
def get_or_create_external(cls, model, urlid, **kwargs):
'''
checks that the parameterised urlid is external and then returns the result of Model.get_or_create
:raises ObjectDoesNotExist: if the urlid is not external and the object doesn't exist
'''
if not Model.is_external(urlid) and not model.objects.filter(urlid=urlid).exists():
raise ObjectDoesNotExist
return Model.get_or_create(model, urlid, **kwargs)
@classonlymethod @classonlymethod
def get_model_rdf_type(cls, model): def get_model_rdf_type(cls, model):
if model is get_user_model(): if model is get_user_model():
...@@ -234,9 +244,15 @@ class Model(models.Model): ...@@ -234,9 +244,15 @@ class Model(models.Model):
@classmethod @classmethod
def is_external(cls, value): def is_external(cls, value):
'''returns True if the urlid of the value passed is from an external source''' '''
:param value: string urlid or an instance with urlid field
:return: True if the urlid is external to the server, False otherwise
'''
try: try:
return value.urlid is not None and not value.urlid.startswith(settings.SITE_URL) if not isinstance(value, str):
value = value.urlid
return value is not None and not value.startswith(settings.SITE_URL)
except: except:
return False return False
......
...@@ -627,7 +627,7 @@ class LDPSerializer(HyperlinkedModelSerializer): ...@@ -627,7 +627,7 @@ class LDPSerializer(HyperlinkedModelSerializer):
model, sub_inst = Model.resolve(field_dict['urlid']) model, sub_inst = Model.resolve(field_dict['urlid'])
# remote resource - get backlinked copy # remote resource - get backlinked copy
elif hasattr(field_model, 'urlid'): elif hasattr(field_model, 'urlid'):
sub_inst = Model.get_or_create(field_model, field_dict['urlid']) sub_inst = Model.get_or_create_external(field_model, field_dict['urlid'])
# try slug field, assuming that this is a local resource # try slug field, assuming that this is a local resource
elif slug_field in field_dict: elif slug_field in field_dict:
kwargs = {slug_field: field_dict[slug_field]} kwargs = {slug_field: field_dict[slug_field]}
......
import json import json
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.conf import settings
from django.db import IntegrityError from django.db import IntegrityError
from rest_framework.test import APIClient, APITestCase from rest_framework.test import APIClient, APITestCase
from djangoldp.tests.models import Circle, CircleMember, Project, UserProfile, DateModel, DateChild from djangoldp.tests.models import Circle, CircleMember, Project, UserProfile, DateModel, DateChild
...@@ -75,6 +76,29 @@ class TestsInbox(APITestCase): ...@@ -75,6 +76,29 @@ class TestsInbox(APITestCase):
self.assertEqual(circles[0].owner, self.user) self.assertEqual(circles[0].owner, self.user)
self._assert_activity_created(response) self._assert_activity_created(response)
# sender has sent a circle with a local user that doesn't exist
def test_create_activity_circle_local(self):
urlid = '{}{}'.format(settings.SITE_URL, 'someonewhodoesntexist')
obj = {
"@type": "hd:circle",
"@id": "https://distant.com/circles/1/",
"owner": {
"@type": "foaf:user",
"@id": urlid
}
}
payload = self._get_activity_request_template("Create", obj)
prior_users_length = get_user_model().objects.count()
response = self.client.post('/inbox/',
data=json.dumps(payload), content_type='application/ld+json')
self.assertEqual(response.status_code, 404)
# assert that the circle was not created neither a backlinked user
self.assertEquals(Circle.objects.count(), 0)
self.assertEquals(get_user_model().objects.count(), prior_users_length)
# #
# ADD ACTIVITIES # ADD ACTIVITIES
# #
......
...@@ -4,7 +4,7 @@ from django.apps import apps ...@@ -4,7 +4,7 @@ from django.apps import apps
from django.conf import settings from django.conf import settings
from django.conf.urls import url, include from django.conf.urls import url, include
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.exceptions import FieldDoesNotExist from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist
from django.core.urlresolvers import get_resolver from django.core.urlresolvers import get_resolver
from django.db import IntegrityError, transaction from django.db import IntegrityError, transaction
from django.http import JsonResponse, Http404 from django.http import JsonResponse, Http404
...@@ -157,7 +157,10 @@ class InboxView(APIView): ...@@ -157,7 +157,10 @@ class InboxView(APIView):
branches[item[0]] = backlink branches[item[0]] = backlink
# get or create the backlink # get or create the backlink
return Model.get_or_create(object_model, obj['@id'], update=update, **branches) try:
return Model.get_or_create_external(object_model, obj['@id'], update=update, **branches)
except ObjectDoesNotExist:
raise Http404()
# TODO: a fallback here? Saving the backlink as Object or similar # TODO: a fallback here? Saving the backlink as Object or similar
def _get_subclass_with_rdf_type_or_404(self, rdf_type): def _get_subclass_with_rdf_type_or_404(self, rdf_type):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment