Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
    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())
Exemple #4
0
    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)
Exemple #5
0
    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"
Exemple #6
0
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
Exemple #7
0
    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())
Exemple #8
0
    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())
Exemple #9
0
    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
Exemple #10
0
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
Exemple #11
0
 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")
Exemple #12
0
 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")