def sender_key_fetcher(handle): """Return the RSA public key for a handle, if found. Fetches the key first from a local Profile and if not found, looks for a remote Profile over the network. :param handle: Handle of profile :type handle: str :returns: RSA public key or None :rtype: str """ logging.debug("sender_key_fetcher - Checking for handle '%s'", handle) try: profile = Profile.objects.get(handle=handle, user__isnull=True) logging.debug( "sender_key_fetcher - Handle %s already exists as a profile", handle) except Profile.DoesNotExist: logging.debug( "sender_key_fetcher - Handle %s was not found, fetching from remote", handle) remote_profile = retrieve_remote_profile(handle) if not remote_profile: logger.warning( "Remote profile %s for sender key not found locally or remotely.", handle) return None # We might as well create the profile locally here since we'll need it again soon logging.debug("sender_key_fetcher - Creating %s from remote profile", handle) Profile.from_remote_profile(remote_profile) return remote_profile.public_key else: return profile.rsa_public_key
def get_sender_profile(sender): """Get or create sender profile. Fetch it from federation layer if necessary or if the public key is empty for some reason. """ try: sender_profile = Profile.objects.exclude(rsa_public_key="").get( handle=sender) except Profile.DoesNotExist: logger.debug( "get_sender_profile - Handle %s was not found, fetching from remote", sender) remote_profile = retrieve_remote_profile(sender) if not remote_profile: logger.warning( "get_sender_profile - Remote profile %s not found locally or remotely.", sender) return sender_profile = Profile.from_remote_profile(remote_profile) else: if sender_profile.is_local: logger.warning("get_sender_profile - Handle %s is local! Skip.", sender) return return sender_profile
def get(self, request, *args, **kwargs): """See if we have a direct match. If so redirect, if not, search. Try fetching a remote profile if the search term is a handle. """ q = safe_text(request.GET.get("q")) if q: q = q.strip().lower() if validate_handle(q): profile = None try: profile = Profile.objects.visible_for_user( request.user).get(handle=q) except Profile.DoesNotExist: # Try a remote search try: remote_profile = retrieve_remote_profile(q) except (AttributeError, ValueError, xml.parsers.expat.ExpatError): # Catch various errors parsing the remote profile return super().get(request, *args, **kwargs) if remote_profile: profile = Profile.from_remote_profile(remote_profile) if profile: return redirect( reverse("users:profile-detail", kwargs={"guid": profile.guid})) try: return super().get(request, *args, **kwargs) except QueryError: # Re-render the form messages.warning( self.request, _("Search string is invalid, please try another one.")) return HttpResponseRedirect(self.get_success_url())
def get(self, request, *args, **kwargs): """See if we have a direct match. If so redirect, if not, search. Try fetching a remote profile if the search term is a handle. """ try: q = safe_text(request.GET.get("q")) if q: q = q.strip().lower() validate_email(q) except ValidationError: pass else: profile = None try: profile = Profile.objects.visible_for_user( request.user).get(handle=q) except Profile.DoesNotExist: # Try a remote search remote_profile = retrieve_remote_profile(q) if remote_profile: profile = Profile.from_remote_profile(remote_profile) if profile: return redirect( reverse("users:profile-detail", kwargs={"guid": profile.guid})) return super().get(request, *args, **kwargs)
def test_calls_diaspora_retrieve_and_parse_profile(self, mock_import): class MockRetrieve(Mock): def retrieve_and_parse_profile(self, handle): return "called with %s" % handle mock_retrieve = MockRetrieve() mock_import.return_value = mock_retrieve assert retrieve_remote_profile("foo@bar") == "called with foo@bar"
def get_sender_profile(sender): """Get or create sender profile. Fetch it from federation layer if necessary. """ try: sender_profile = Profile.objects.get(handle=sender) except Profile.DoesNotExist: remote_profile = retrieve_remote_profile(sender) if not remote_profile: logger.warning("Remote profile %s not found locally or remotely.", sender) return sender_profile = Profile.from_remote_profile(remote_profile) return sender_profile
def get(self, request, *args, **kwargs): """See if we have a direct match. If so redirect, if not, search. Try fetching a remote profile if the search term is a handle or fid. """ q = safe_text(request.GET.get("q")) if q: q = q.strip().lower() self.q = q # Check if direct tag matches if q.startswith('#'): try: tag = Tag.objects.filter(name=q[1:]).annotate( content_count=Count('contents')).filter( content_count__gt=0).get() except Tag.DoesNotExist: pass else: return redirect(tag.get_absolute_url()) # Check if profile matches profile = None try: profile = Profile.objects.visible_for_user( request.user).fed(q).get() except Profile.DoesNotExist: # Try a remote search # TODO currently only if diaspora handle if validate_handle(q): try: remote_profile = retrieve_remote_profile(q) except (AttributeError, ValueError, xml.parsers.expat.ExpatError): # Catch various errors parsing the remote profile return super().get(request, *args, **kwargs) if remote_profile: profile = Profile.from_remote_profile(remote_profile) if profile: return redirect( reverse("users:profile-detail", kwargs={"uuid": profile.uuid})) try: return super().get(request, *args, **kwargs) except QueryError: # Re-render the form messages.warning( self.request, _("Search string is invalid, please try another one.")) return HttpResponseRedirect(self.get_success_url())
def get(self, request, *args, **kwargs): """See if we have a direct match. If so redirect, if not, search. Try fetching a remote profile if the search term is a handle or fid. """ q = safe_text(request.GET.get("q")) if q: q = q.strip().lower() self.q = q # Check if direct tag matches if q.startswith('#'): try: tag = Tag.objects.filter( name=q[1:] ).annotate( content_count=Count('contents') ).filter( content_count__gt=0 ).get() except Tag.DoesNotExist: pass else: return redirect(tag.get_absolute_url()) # Check if profile matches profile = None try: profile = Profile.objects.visible_for_user(request.user).fed(q).get() except Profile.DoesNotExist: # Try a remote search # TODO currently only if diaspora handle if validate_handle(q): try: remote_profile = retrieve_remote_profile(q) except (AttributeError, ValueError, xml.parsers.expat.ExpatError): # Catch various errors parsing the remote profile return super().get(request, *args, **kwargs) if remote_profile: profile = Profile.from_remote_profile(remote_profile) if profile: return redirect(reverse("users:profile-detail", kwargs={"uuid": profile.uuid})) try: return super().get(request, *args, **kwargs) except QueryError: # Re-render the form messages.warning(self.request, _("Search string is invalid, please try another one.")) return HttpResponseRedirect(self.get_success_url())
def get_profile(identifier): """Get or create remote profile. Fetch it from federation layer if necessary or if the public key is empty for some reason. """ try: sender_profile = Profile.get(Profile.identifier == identifier) if not sender_profile.public_key: raise DoesNotExist except DoesNotExist: remote_profile = retrieve_remote_profile(identifier) if not remote_profile: logging.warning( "Remote profile %s not found locally or remotely.", identifier) return sender_profile = Profile.from_remote_profile(remote_profile) return sender_profile
def get_sender_profile(sender: str) -> Optional[Profile]: """Get or create sender profile. Fetch it from federation layer if necessary or if the public key is empty for some reason. """ try: logger.debug("get_sender_profile - looking from local db using %s", sender) sender_profile = Profile.objects.fed(sender).exclude(rsa_public_key="").get() except Profile.DoesNotExist: logger.debug("get_sender_profile - %s was not found, fetching from remote", sender) remote_profile = retrieve_remote_profile(sender) if not remote_profile: logger.warning("get_sender_profile - Remote profile %s not found locally or remotely.", sender) return sender_profile = Profile.from_remote_profile(remote_profile) else: if sender_profile.is_local: logger.warning("get_sender_profile - %s is local! Skip.", sender) return return sender_profile
def test_calls_diaspora_retrieve_and_parse_profile(self, mock_import): mock_retrieve = Mock() mock_import.return_value = mock_retrieve retrieve_remote_profile("foo@bar") mock_retrieve.retrieve_and_parse_profile.assert_called_once_with( "foo@bar")
def test_retrieve_remote_profile__url_calls_activitypub_retrieve(self, mock_identify, mock_validate, mock_import): mock_utils = Mock() mock_import.return_value = mock_utils retrieve_remote_profile("https://example.com/foo") mock_import.assert_called_once_with("federation.utils.activitypub") mock_utils.retrieve_and_parse_profile.assert_called_once_with("https://example.com/foo")