コード例 #1
0
ファイル: post_views.py プロジェクト: michaellzc/hyperion
def get_request_user_foaf_post(request_user_full_id):
    result = []
    try:
        # in this case request_user_id should be foreign user id
        request_user_host_name = "{uri.scheme}://{uri.netloc}".format(
            uri=urlparse(request_user_full_id)
        )
        foreign_server = Server.objects.get(url=request_user_host_name)
        request_user_id = request_user_full_id.split("/author/")[-1]
        # print(request_user_id, "request_user_id")

        # fetch friendlist
        resp = ForeignServerHttpUtils.get(foreign_server, "/author/" + request_user_id + "/friends")
        if resp.status_code != 200:
            raise Exception("failed getting the friend_list")
        request_user_friend_list = resp.json()["authors"]
        # request_user_friend_list = [friend["id"] for friend in resp.json()["authors"]]
        # print(request_user_friend_list)

        local_users = UserProfile.objects.filter(host=None)
        # print(local_users)
        for local_user in local_users:
            local_author_friend_list = list(local_user.get_friends().values_list("url", flat=True))
            intersection_friends = list(
                set(request_user_friend_list) & set(local_author_friend_list)
            )
            if len(intersection_friends) > 0:
                result.extend(
                    list(Post.objects.filter(author=local_user, unlisted=False, visibility="FOAF"))
                )
        # print(result)
        return result
    except Exception as some_error:
        print(some_error, "foaf1 error")
        return result
コード例 #2
0
    def check_remote_foaf_relationship(self, remote_user_full_id):
        try:
            # find the server first
            remote_user_host_name = "{uri.scheme}://{uri.netloc}".format(
                uri=urlparse(remote_user_full_id))
            foreign_server = Server.objects.get(url=remote_user_host_name)
            remote_user_id = remote_user_full_id.split("/author/")[-1]

            # fetch friendlist
            resp = ForeignServerHttpUtils.get(
                foreign_server, "/author/" + remote_user_id + "/friends")
            if resp.status_code != 200:
                raise Exception("failed getting the friend_list")
            remote_user_friend_list = resp.json()["authors"]
            # remote_user_friend_list = [friend["id"] for friend in resp.json()["authors"]]
            # print(remote_user_friend_list)

            own_friend_list = list(self.get_friends().values_list("url",
                                                                  flat=True))
            intersection_friends = list(
                set(remote_user_friend_list) & set(own_friend_list))

            return len(intersection_friends) > 0

        except Exception as some_error:
            # print(remote_user_full_id)
            # print(remote_user_host_name)
            print(some_error, "error in check_remote_foaf_relationship")
            return False
コード例 #3
0
ファイル: post_views.py プロジェクト: michaellzc/hyperion
    def list(self, request):
        """
        GET /posts
        """
        is_local = False

        try:
            # check if authenticated user is a server or local user
            request.user.server
        except User.server.RelatedObjectDoesNotExist:  # pylint: disable=no-member
            # local user shoud not have an one-to-one relationship with Server
            is_local = True

        posts = self.queryset.filter(visibility="PUBLIC")
        serializer = PostSerializer(posts, many=True)
        data = serializer.data

        foreign_public_posts = []
        if is_local:
            # handle local user request
            # also include foreign public posts
            for server in Server.objects.all():
                try:
                    posts_response = ForeignServerHttpUtils.get(server, "/posts")
                    foreign_public_posts += posts_response.json().get("posts", [])
                except requests.exceptions.RequestException as exception:
                    print(exception)
        else:
            pass
        data += foreign_public_posts
        return Response({"query": "posts", "count": len(data), "posts": data}, status=200)
コード例 #4
0
ファイル: post_views.py プロジェクト: michaellzc/hyperion
    def get_auth_posts(self, request):
        """
        GET /author/posts
        """
        # check if local user
        foreign_posts = []
        result = []
        try:
            request.user.server
        except User.server.RelatedObjectDoesNotExist:  # pylint: disable=no-member
            # local user
            result = list(
                self.queryset.filter(
                    Q(visibility="PUBLIC")
                    | Q(author=request.user.profile)
                    | Q(visibility="SERVERONLY")
                )
            ) + Post.not_own_posts_visible_to_me(request.user.profile)

            # fetch foreign posts concurrently
            foreign_reqs = []
            for server in Server.objects.all():
                local_url = request.user.profile.get_url()
                headers = {"X-Request-User-ID": str(local_url)}
                foreign_reqs.append(
                    ForeignServerHttpUtils.parallel_get(
                        server, "/author/posts", headers=headers, timeout=5
                    )
                )

            responses = grequests.map(foreign_reqs, exception_handler=self._exception_handler)
            for response in responses:
                if not response:
                    continue
                if response.status_code == 200:
                    body = response.json()
                    if isinstance(body, dict):
                        posts = body.get("posts", [])
                        foreign_posts += posts
        else:
            # foreign user
            # grab request user information from request header
            try:
                foreign_user_url = request.META["HTTP_X_REQUEST_USER_ID"]
                # foreign user in our db, get all public posts and posts that
                # are visible to or such posts' firends to this foreign user profile
                foreign_user_profile = UserProfile.objects.get(url=foreign_user_url)
                result = list(
                    self.queryset.filter(visibility="PUBLIC")
                ) + Post.not_own_posts_visible_to_me(foreign_user_profile)
                result = result + get_request_user_foaf_post(foreign_user_url)
            except UserProfile.DoesNotExist:
                # foreign user is not in our db
                # directly return public
                result = list(self.queryset.filter(visibility="PUBLIC"))
                result = result + get_request_user_foaf_post(foreign_user_url)
            except KeyError:
                return Response(
                    {"query": "posts", "success": False, "message": "No X-Request-User-ID"},
                    status=status.HTTP_400_BAD_REQUEST,
                )

        result = list(set(result))  # remove duplication
        serializer = PostSerializer(result, many=True)
        data = serializer.data + foreign_posts
        return Response({"query": "posts", "count": len(data), "posts": data})
コード例 #5
0
ファイル: post_views.py プロジェクト: michaellzc/hyperion
    def get_author_id_posts(self, request, pk):
        """
        GET /author/{author_id}/posts
        """
        # target_posts are posts created by author with id = pk
        target_posts = None

        # check if local user
        is_local = False
        try:
            request.user.server
        except User.server.RelatedObjectDoesNotExist:  # pylint: disable=no-member
            is_local = True

        result = []
        if is_local:
            if pk.isdigit():
                # local user
                # find all PUBLIC and SERVERONLY post create by this author with id=pk
                # add not_own_posts_visible_to_me posts
                pk = User.objects.get(pk=pk).profile.id
                if int(request.user.profile.id) == int(pk):
                    # add unlisted posts
                    result = Post.objects.filter(author=pk)
                else:
                    target_posts = self.queryset.filter(author=pk)
                    result = list(
                        target_posts.filter(Q(visibility="PUBLIC") | Q(visibility="SERVERONLY"))
                    ) + Post.not_own_posts_visible_to_me(
                        request.user.profile, queryset=target_posts
                    )
            else:
                # foreign user
                try:
                    parsed_url = urlparse(pk)
                    foreign_server = Server.objects.get(
                        url="{}://{}".format(parsed_url.scheme, parsed_url.netloc)
                    )
                    foreign_post_id = parsed_url.path.split("/")[-1]
                    response = ForeignServerHttpUtils.get(
                        foreign_server,
                        "/author/{}/posts".format(foreign_post_id),
                        headers={"X-Request-User-ID": request.user.profile.get_url()},
                    )
                    if response.status_code == 200:
                        return Response(response.json())
                    else:
                        return Response(
                            {
                                "query": "getAuthorPost",
                                "success": False,
                                "message": "Foreign server error",
                                "error": json.dumps(response.json()),
                            },
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                        )
                except Server.DoesNotExist:
                    return Response(
                        {"succcess": False, "message": "Foreign server does not exist."},
                        status=status.HTTP_400_BAD_REQUEST,
                    )
        else:
            # foreign user
            # grab request user information from request header
            # print(request.META)
            pk = User.objects.get(pk=pk).profile.id
            target_posts = self.queryset.filter(author=pk)
            try:
                foreign_user_url = request.META["HTTP_X_REQUEST_USER_ID"]
                # foreign user in our db, get all public posts created by author with id=pk
                foreign_user_profile = UserProfile.objects.get(url=foreign_user_url)
                result = list(
                    target_posts.filter(Q(visibility="PUBLIC"))
                ) + Post.not_own_posts_visible_to_me(foreign_user_profile, queryset=target_posts)
                # plus remote foaf
                result = result + get_request_user_foaf_post_belong_local_author(
                    foreign_user_url, pk
                )
            except UserProfile.DoesNotExist:
                # foreign user is not in our db
                # directly return public
                result = list(target_posts.filter(visibility="PUBLIC"))
                result = result + get_request_user_foaf_post_belong_local_author(
                    foreign_user_url, pk
                )
            except KeyError:
                return Response(
                    {"query": "posts", "success": False, "message": "No X-Request-User-ID"},
                    status=status.HTTP_400_BAD_REQUEST,
                )

        result = list(set(result))  # remove duplication
        serializer = PostSerializer(result, many=True)
        data = serializer.data
        return Response({"query": "posts", "count": len(data), "posts": data})
コード例 #6
0
ファイル: friend_views.py プロジェクト: michaellzc/hyperion
def unfollow_request(request):
    # so far only local user can do unfriend action
    try:
        body = json.loads(request.body.decode("utf-8"))

        if body["query"] != "unfollow":
            raise Exception("query should be unfollow")

        # get the host from url to compare with host attribute
        # https://stackoverflow.com/questions/9626535/get-protocol-host-name-from-url
        # host_name = "{uri.scheme}://{uri.netloc}".format(uri=urlparse(body["author"]["id"]))
        # if host_name != body["author"]["host"]:
        #     raise Exception("we can't save the profile which host != url.host")

        friend_host_name = "{uri.scheme}://{uri.netloc}".format(
            uri=urlparse(body["friend"]["id"]))

        is_local = False
        try:
            _ = request.user.server
        except User.server.RelatedObjectDoesNotExist:  # pylint: disable=no-member
            is_local = True

        if is_local:  # the request user is local
            author_id = int(body["author"]["id"].split("/")[-1])
            if request.user.id != author_id:
                raise Exception("request user is not the author")
            author_profile = User.objects.get(pk=author_id).profile

            # check if the friend is local or remote
            if friend_host_name == settings.HYPERION_HOSTNAME:  # friend is local
                friend_profile = User.objects.get(
                    pk=int(body["friend"]["id"].split("/")[-1])).profile
            else:  # friend is remote
                friend_profile = UserProfile.objects.get(
                    url=body["friend"]["id"])

                # send unfollow request to remote server
                unfollow_body = {
                    "query":
                    "unfollow",
                    "author":
                    UserProfileSerializer(
                        author_profile,
                        context={
                            "fields": ["id", "host", "display_name", "url"]
                        }).data,
                    "friend":
                    UserProfileSerializer(
                        friend_profile,
                        context={
                            "fields": ["id", "host", "display_name", "url"]
                        }).data,
                }
                foreign_server = Server.objects.get(url=friend_host_name)
                resp = ForeignServerHttpUtils.post(foreign_server,
                                                   "/unfollow",
                                                   json=unfollow_body)
                if resp.status_code != 200:
                    raise Exception(
                        "send unfollow to remote server failed, reason={}".
                        format(resp.content))
        else:  # if the author is remote
            author_profile = UserProfile.objects.get(url=body["author"]["id"])
            friend_profile = User.objects.get(
                pk=int(body["friend"]["id"].split("/")[-1])).profile

        # if not is_local:
        #     raise Exception("so far, only can handle local user request")

        # # check if the unfriend person exist on our server
        # friend_url = body["friend"]["id"]
        # friend_profile = UserProfile.objects.get(url=friend_url)
        #
        # # check and get author profile
        # author_url = body["author"]["id"]
        # author_profile = UserProfile.objects.get(url=author_url)
        #

        # check if the request user does friend with aim person
        qs1 = Friend.objects.filter(profile1=friend_profile,
                                    profile2=author_profile)
        qs2 = Friend.objects.filter(profile1=author_profile,
                                    profile2=friend_profile)
        if (not qs1.exists()) and (not qs2.exists()):
            raise Exception("they are not friend")
        else:
            qs1.delete()
            qs2.delete()

        content = {
            "query": "unfollow",
            "success": True,
            "message": "unfollow succeed"
        }
        return Response(content, status=status.HTTP_200_OK)

    except Exception as some_error:
        return Response(
            _get_error_response("unfollow", False, str(some_error)),
            status=status.HTTP_400_BAD_REQUEST,
        )
コード例 #7
0
ファイル: friend_views.py プロジェクト: michaellzc/hyperion
def action_friend_request(request, friendrequest_id):
    try:
        body_unicode = request.body.decode("utf-8")
        body = json.loads(body_unicode)

        # get the friend request first
        friend_request_obj = FriendRequest.objects.get(pk=friendrequest_id)

        # check if the request user is the user being friend
        if request.user.id != friend_request_obj.to_profile.author.id:
            raise Exception(
                "the request user doesn't have permission to do action in this friend request"
            )

        if body["query"] != "friendrequestAction":
            raise Exception("query should be friendrequestAction")

        # check the accepted information
        if body["accepted"]:
            # if the friend request author is remote user
            parsed_friend_uri = urlparse(friend_request_obj.from_profile.url)
            author_host_name = "{uri.scheme}://{uri.netloc}".format(
                uri=parsed_friend_uri)
            # print("asfsdf", author_host_name)
            if author_host_name != settings.HYPERION_HOSTNAME:
                # send friendrequest(reverse edition)
                friend_request_reverse_body = {
                    "query":
                    "friendrequest",
                    "author":
                    UserProfileSerializer(
                        friend_request_obj.to_profile,
                        context={
                            "fields": ["id", "host", "display_name", "url"]
                        },
                    ).data,
                    "friend":
                    UserProfileSerializer(
                        friend_request_obj.from_profile,
                        context={
                            "fields": ["id", "host", "display_name", "url"]
                        },
                    ).data,
                }
                # print(friend_request_reverse_body["friend"]["host"])
                foreign_server = Server.objects.get(
                    url=friend_request_reverse_body["friend"]["host"])
                resp = ForeignServerHttpUtils.post(
                    foreign_server,
                    "/friendrequest",
                    json=friend_request_reverse_body)
                if resp.status_code != 200:
                    raise Exception(
                        "send back friendrequest to remote server failed, reason={}"
                        .format(resp.content))

            friend_request_obj.to_profile.accept_friend_request(
                friend_request_obj.from_profile)
            msg = "accept the friend request"
            accepted = True
        else:
            friend_request_obj.to_profile.decline_friend_request(
                friend_request_obj.from_profile)
            msg = "decline the friend request"
            accepted = False

        serializer = FriendRequestSerializer(
            friend_request_obj,
            context={"user_fields": ["id", "host", "display_name", "url"]})
        content = {
            "query": "friendrequestAction",
            "friendrequest": serializer.data,
            "accepted": accepted,
            "success": True,
            "message": msg,
        }
        return Response(content, status=status.HTTP_200_OK)

    except FriendRequest.DoesNotExist:
        return Response(
            _get_error_response("friendrequestAction", False,
                                "friend request is not exist"),
            status=status.HTTP_400_BAD_REQUEST,
        )

    except Exception as some_error:
        return Response(
            _get_error_response("friendrequestAction", False, str(some_error)),
            status=status.HTTP_400_BAD_REQUEST,
        )
コード例 #8
0
ファイル: friend_views.py プロジェクト: michaellzc/hyperion
def friend_request(request):

    if request.method == "GET":
        # get all friend request which to_friend would be request.user
        friend_request_list = FriendRequest.objects.filter(
            to_profile=request.user.profile)

        content = {
            "query":
            "friendrequests",
            "frinedrequests":
            FriendRequestSerializer(
                friend_request_list,
                many=True,
                context={
                    "user_fields": ["id", "host", "display_name", "url"]
                },
            ).data,
        }

        return Response(content,
                        content_type="application/json",
                        status=status.HTTP_200_OK)

    elif request.method == "POST":
        try:
            body = json.loads(request.body.decode("utf-8"))
            if body["query"] != "friendrequest":
                raise Exception("query should be friendrequest")

            # get the host from url to compare with host attribute
            # https://stackoverflow.com/questions/9626535/get-protocol-host-name-from-url
            # host_name = "{uri.scheme}://{uri.netloc}".format(uri=urlparse(body["author"]["id"]))
            #
            # if host_name != body["author"]["host"]:
            #     raise Exception("we can't save the profile which host != url.host")

            friend_host_name = "{uri.scheme}://{uri.netloc}".format(
                uri=urlparse(body["friend"]["id"]))

            # check if the request user is local or remote
            is_local = False
            try:
                server = request.user.server
            except User.server.RelatedObjectDoesNotExist:  # pylint: disable=no-member
                is_local = True

            if is_local:  # if author is local
                # get the author profile
                author_profile = User.objects.get(
                    pk=int(body["author"]["id"].split("/")[-1])).profile
                # check if the to_friend is local or remote
                if friend_host_name == settings.HYPERION_HOSTNAME:  # friend is local
                    friend_profile = User.objects.get(
                        pk=int(body["friend"]["id"].split("/")[-1])).profile
                else:  # friend is remote
                    # check if the friend profile exists
                    try:
                        friend_profile = UserProfile.objects.get(
                            url=body["friend"]["id"])
                    except UserProfile.DoesNotExist:
                        remote_server_user = User.objects.get(
                            profile__url=friend_host_name)
                        friend_profile = UserProfile.objects.create(
                            # TO DO what's the default value of display_name
                            display_name=body["friend"].get("displayName", ""),
                            host=remote_server_user.server,
                            url=body["friend"]["id"],
                        )

                    # send friend request to remote server
                    friend_request_body = {
                        "query":
                        "friendrequest",
                        "author":
                        UserProfileSerializer(
                            author_profile,
                            context={
                                "fields":
                                ["id", "host", "display_name", "url"]
                            },
                        ).data,
                        "friend":
                        UserProfileSerializer(
                            friend_profile,
                            context={
                                "fields":
                                ["id", "host", "display_name", "url"]
                            },
                        ).data,
                    }
                    foreign_server = Server.objects.get(url=friend_host_name)
                    resp = ForeignServerHttpUtils.post(
                        foreign_server,
                        "/friendrequest",
                        json=friend_request_body)
                    if resp.status_code != 200:
                        raise Exception(
                            "send friendrequest to remote server failed, reason={}"
                            .format(resp.content))

            else:  # if author is remote
                # check if the author profile exists
                try:
                    author_profile = UserProfile.objects.get(
                        url=body["author"]["id"])
                except UserProfile.DoesNotExist:
                    author_profile = UserProfile.objects.create(
                        display_name=body["author"].get("displayName", ""),
                        host=server,
                        url=body["author"]["id"],
                    )
                # friend must be local
                friend_profile = User.objects.get(
                    pk=int(body["friend"]["id"].split("/")[-1])).profile

            # if there are already friend => return 204
            try:
                author_profile.send_friend_request(friend_profile)
            except FriendAlreadyExist:
                return Response(status=status.HTTP_204_NO_CONTENT)

            # check if already get reverse edition friend request
            reverse_friend_request = FriendRequest.objects.filter(
                from_profile=friend_profile, to_profile=author_profile)
            if reverse_friend_request.exists():
                Friend.objects.create(profile1=author_profile,
                                      profile2=friend_profile)
                FriendRequest.objects.filter(
                    from_profile=author_profile,
                    to_profile=friend_profile).delete()
                FriendRequest.objects.filter(
                    from_profile=friend_profile,
                    to_profile=author_profile).delete()

                return Response(
                    {
                        "query": "friendrequest",
                        "success": True,
                        "message": "Two way friendrequests create friendship",
                    },
                    status=status.HTTP_200_OK,
                )

            return Response(
                {
                    "query": "friendrequest",
                    "success": True,
                    "message": "friendrequest sent"
                },
                status=status.HTTP_200_OK,
            )

        except Exception as some_error:
            # template = "An exception of type {0} occurred. Arguments:\n{1!r}"
            # message = template.format(type(some_error).__name__, some_error.args)
            # print(message)
            return Response(
                _get_error_response("friendrequest", False, str(some_error)),
                status=status.HTTP_400_BAD_REQUEST,
            )
コード例 #9
0
ファイル: comment_views.py プロジェクト: michaellzc/hyperion
    def new_comment(self, request, pk=None):  # pylint: disable=invalid-name
        """
        POST /posts/{post_id}/comments
        """
        is_local = False

        try:
            # check if authenticated user is a server or local user
            request.user.server
        except User.server.RelatedObjectDoesNotExist:  # pylint: disable=no-member
            # local user shoud not have an one-to-one relationship with Server
            is_local = True

        body = request.data
        comment_data = body.get("comment", None)
        author = comment_data.get("author", None)
        author_id = author.get("id", None)
        post_id = body.get("post", None)
        post_url = urlparse(post_id)
        author_profile = None
        is_foaf = False

        if is_local:
            # handle local author request
            post_url_host = "{}://{}".format(post_url.scheme, post_url.netloc)
            if post_url_host == settings.HYPERION_HOSTNAME:
                # comment on local post
                post_pk = post_url.path.split("/")[-1]
                comment_data["post"] = post_pk
                author_profile = request.user.profile
                comment_data["author"] = str(author_profile.id)
            else:
                # comment on foreign post
                try:
                    foreign_server = Server.objects.get(url=post_url_host)
                    post_pk = post_url.path.split("/")[-1]
                    resp = ForeignServerHttpUtils.post(foreign_server,
                                                       "/posts/1/comments",
                                                       json=body)
                    if resp.status_code != 200:
                        return Response(
                            {
                                "query": "addComment",
                                "success": False,
                                "message": resp.content
                            },
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                        )
                    return Response({
                        "query": "addComment",
                        "success": True,
                        "message": "Comment Created"
                    })
                except RequestException as exception:
                    return Response(
                        {
                            "query": "addComment",
                            "success": False,
                            "message": "Not my fault.",
                            "error": exception,
                        },
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                    )
                except Server.DoesNotExist:
                    return Response(
                        {
                            "query": "addComment",
                            "success": False,
                            "message": "Target foreign server is not support",
                        },
                        status=status.HTTP_400_BAD_REQUEST,
                    )
        else:
            # handle foreign server request
            server = request.user.server
            author_profile, _ = UserProfile.objects.filter(
                Q(url=author_id)).get_or_create(url=author_id,
                                                display_name=author.get(
                                                    "display_name", None),
                                                host=server)

            post_pk = post_url.path.split("/")[-1]
            comment_data["post"] = post_pk
            comment_data["author"] = str(author_profile.id)

            # check if they are foaf
            is_foaf = Post.objects.get(
                pk=post_pk).author.check_remote_foaf_relationship(author_id)

        post_data = get_object_or_404(Post, pk=post_pk)
        accessible = post_data.is_accessible(post_data, author_profile)

        # validate query name
        if body.get("query", None) != "addComment":
            return Response(
                {
                    "query": "addComment",
                    "success": False,
                    "message": "Bad Request"
                },
                status=status.HTTP_422_UNPROCESSABLE_ENTITY,
            )

        # validate accessibility
        if not accessible and not is_foaf:
            return Response(
                {
                    "query": "addComment",
                    "success": False,
                    "message": "Forbidden access"
                },
                status=status.HTTP_403_FORBIDDEN,
            )

        serializer = CommentSerializer(data=comment_data)
        if serializer.is_valid():
            serializer.save()
        else:
            return Response(
                {
                    "query": "addComment",
                    "success": False,
                    "message": serializer.errors
                },
                status=status.HTTP_422_UNPROCESSABLE_ENTITY,
            )

        return Response({
            "query": "addComment",
            "success": True,
            "message": "Comment Created"
        })