Ejemplo n.º 1
0
def create():
    user: User = get_user_from_app_context()
    attrs = request.json
    attrs["author_id"] = user._id
    q = Question(attrs)
    q.save()
    return json_response({"data": q.api_dict(fields=QUESTION_FIELDS)})
Ejemplo n.º 2
0
def users_subscription():
    user: User = get_user_from_app_context()
    us = user.user_subscription
    users = []
    for user in us.subscribed_to:
        users.append(user.to_dict(fields=USER_FIELDS))
    return json_response({"data": users})
Ejemplo n.º 3
0
def dismiss(event_id):
    user: User = get_user_from_app_context()
    event = Event.get(event_id, "event not found")
    if event.user_id != user._id:
        raise NotFound("event not found")
    if not event.dismissed:
        event.dismiss()
    return json_response({"data": event.api_dict()})
Ejemplo n.º 4
0
 def my_vote(self) -> int:
     if not has_request_context():
         return 0
     u = get_user_from_app_context()
     if u is None:
         return 0
     v = Vote.find_one({"post_id": self._id, "user_id": u._id})
     return v.value if v is not None else 0
Ejemplo n.º 5
0
def dismiss_all():
    user: User = get_user_from_app_context()
    Event.update_many({
        "user_id": user._id,
        "dismissed": False
    }, {"$set": {
        "dismissed": True
    }})
    return json_response({"status": "dismissed"})
Ejemplo n.º 6
0
def accept_answer(question_id, answer_id):
    u: User = get_user_from_app_context()
    q: Optional[Question] = Question.get(question_id, "answer not found")
    a: Optional[Answer] = Answer.get(answer_id, "answer not found")
    if a.parent_id != q._id:
        raise NotFound("answer not found")
    if q.author_id != u._id:
        raise Forbidden("only question's author can accept answers")
    q.set_accepted_answer(a)
    return json_response({"data": a.api_dict(ANSWER_FIELDS)})
Ejemplo n.º 7
0
def create_comment(question_id):
    q = Question.get(question_id, "question not found")
    user: User = get_user_from_app_context()
    attrs = request.json

    if "body" not in attrs:
        raise ApiError("body is missing")

    c = q.create_comment({"body": attrs["body"], "author_id": user._id})
    c.save()
    return json_response({"data": c.api_dict(COMMENT_FIELDS)})
Ejemplo n.º 8
0
def create_answer(question_id):
    q: Optional[Question] = Question.get(question_id, "question not found")
    user: User = get_user_from_app_context()
    attrs = request.json

    if "body" not in attrs:
        raise ApiError("body is missing")

    a = q.create_answer({"author_id": user._id, "body": attrs["body"]})
    a.save()

    return json_response({"data": a.api_dict()})
Ejemplo n.º 9
0
def tags_subscribe():
    user: User = get_user_from_app_context()
    tags = request.json.get("tags")
    if tags is None:
        raise InputDataError("tags field is mandatory")
    tags = list(set(tags))  # make sure tags are unique

    ts = user.tag_subscription
    ts.tags = tags
    ts.save()

    json_response({"data": ts.to_dict(fields=TAG_SUBSCRIPTION_FIELDS)})
Ejemplo n.º 10
0
def revoke_answer(question_id, answer_id):
    u: User = get_user_from_app_context()
    q: Optional[Question] = Question.get(question_id, "answer not found")
    a: Optional[Answer] = Answer.get(answer_id, "answer not found")
    if a.parent_id != q._id:
        raise NotFound("answer not found")
    if q.author_id != u._id:
        raise Forbidden("only question's author can revoke answers")
    if not a.accepted:
        raise NotAccepted("answer is not accepted so can't be revoked")
    q.set_accepted_answer(None)
    a.reload()
    return json_response({"data": a.api_dict(ANSWER_FIELDS)})
Ejemplo n.º 11
0
def create_answer_comment(question_id, answer_id):
    a: Optional[Answer] = Answer.get(answer_id, "answer not found")
    if a.parent_id != resolve_id(question_id):
        raise NotFound("answer not found")
    user: User = get_user_from_app_context()
    attrs = request.json

    if "body" not in attrs:
        raise ApiError("body is missing")

    c = a.create_comment({"body": attrs["body"], "author_id": user._id})
    c.save()
    return json_response({"data": c.api_dict(COMMENT_FIELDS)})
Ejemplo n.º 12
0
def vote_question(question_id):
    q: Optional[Question] = Question.get(question_id, "question not found")
    u: User = get_user_from_app_context()
    if q.author_id == u._id:
        raise Forbidden("you can't vote for your own question")

    attrs = request.json

    if "value" not in attrs:
        raise ApiError("value field is mandatory")

    Vote.vote(q._id, u._id, attrs["value"])
    q.reload()
    return json_response({"data": q.api_dict(fields=QUESTION_FIELDS)})
Ejemplo n.º 13
0
def vote_answer(question_id, answer_id):
    a: Optional[Answer] = Answer.get(answer_id, "answer not found")
    if a.parent_id != resolve_id(question_id):
        raise NotFound("answer not found")
    u: User = get_user_from_app_context()
    if a.author_id == u._id:
        raise Forbidden("you can't vote for your own answers")

    attrs = request.json

    if "value" not in attrs:
        raise ApiError("value field is mandatory")

    Vote.vote(a._id, u._id, attrs["value"])
    a.reload()
    return json_response({"data": a.api_dict(fields=ANSWER_FIELDS)})
Ejemplo n.º 14
0
def vote_comment(question_id, comment_id):
    c: Optional[Comment] = Comment.get(comment_id, "comment not found")
    if c.parent_id != resolve_id(question_id):
        raise NotFound("comment not found")
    u: User = get_user_from_app_context()
    if c.author_id == u._id:
        raise Forbidden("you can't vote for your own comments")

    attrs = request.json

    if "value" not in attrs:
        raise ApiError("value field is mandatory")

    Vote.vote(c._id, u._id, attrs["value"])
    c.reload()
    return json_response({"data": c.api_dict(fields=COMMENT_FIELDS)})
Ejemplo n.º 15
0
    def get(cls, expression, raise_if_none=None):
        post: Optional[BasePost] = super().get(expression, raise_if_none)
        if post and post.deleted:
            if has_request_context():
                user: User = get_user_from_app_context()
                # if user logged in and he is moderator or post.author
                # he can view deleted post
                if not user or (user._id != post.author_id
                                and not user.moderator):
                    post = None

        if post is None and raise_if_none:
            if isinstance(raise_if_none, str):
                raise NotFound(raise_if_none)
            else:
                raise raise_if_none
        return post
Ejemplo n.º 16
0
def index():
    u: User = get_user_from_app_context()

    if "_sort" in request.values:
        srt = request.values["_sort"]
    else:
        srt = "rating"

    sortExpr = SORT_MAP.get(srt)
    if sortExpr is None:
        raise ApiError(f"unknown sort operator \"{srt}\"")

    if get_boolean_request_param("_mine"):
        if u:
            # only mine posts
            query = {"author_id": u._id}
        else:
            # nothing to show, user is not logged in
            query = {"_id": NilObjectId}
    else:
        # otherwise show all not deleted posts
        query = {
            "$or": [
                {
                    "deleted": False
                },
            ]
        }
        if u:
            # if user is logged in, he can view his own deleted posts
            query["$or"].append({"author_id": u._id})

    questions = Question.find(query).sort(sortExpr)
    results = paginated(
        questions, transform=default_transform(fields=QUESTION_LIST_FIELDS))
    author_ids = set()
    for q in results["data"]:
        author_ids.add(resolve_id(q["author_id"]))
    authors = User.find({"_id": {"$in": list(author_ids)}})
    return json_response({"questions": results, "authors": {"data": authors}})
Ejemplo n.º 17
0
 def update_allowed(self) -> bool:
     user: User = get_user_from_app_context()
     return self.author_id == user._id or user.moderator
Ejemplo n.º 18
0
def users_unsubscribe(user_id):
    current: User = get_user_from_app_context()
    user = User.get(user_id, "user not found")
    current.unsubscribe_from_user(user)
    return users_subscription()
Ejemplo n.º 19
0
 def is_mine(self):
     if not has_request_context():
         return True
     user = get_user_from_app_context()
     return user._id == self.author_id
Ejemplo n.º 20
0
    def everything(self, user: Union['User', None] = None) -> Dict[str, Any]:
        if user is None:
            user = get_user_from_app_context()

        user_id = user._id if user else None

        qa_pipeline = [{
            "$match": {
                "$or": [
                    {
                        "_id": self._id
                    },
                    {
                        "parent_id": self._id,
                        "submodel": "answer"
                    },
                ]
            }
        }, {
            "$sort": {
                "accepted": -1,
                "created_at": -1
            },
        }, {
            "$lookup": {
                "from":
                "votes",
                "let": {
                    "post_id": "$_id"
                },
                "pipeline": [{
                    "$match": {
                        "$expr": {
                            "$and": [{
                                "$eq": ["$post_id", "$$post_id"]
                            }, {
                                "$eq": ["$user_id", user_id]
                            }]
                        }
                    }
                }, {
                    "$project": {
                        "_id": 0,
                        "value": 1
                    }
                }],
                "as":
                "votes",
            }
        }]

        results = {
            "question": None,
            "answers": [],
            "comments": [],
            "authors": []
        }
        author_ids = set()
        doc_ids = []

        for doc in BasePost.aggregate(qa_pipeline):
            doc["my_vote"] = doc["votes"][0]["value"] if doc["votes"] else 0
            del doc["votes"]

            doc_ids.append(doc["_id"])
            if doc["submodel"] == "question":
                results["question"] = doc
            elif doc["submodel"] == "answer":
                if doc["deleted"]:
                    # skip deleted answers unless user is the author or a moderator
                    if user or (not user.moderator
                                and user._id != doc["author_id"]):
                        continue
                results["answers"].append(doc)
            author_ids.add(doc["author_id"])

        c_pipeline = [{
            "$match": {
                "parent_id": {
                    "$in": doc_ids
                },
                "submodel": "comment"
            },
        }, {
            "$sort": {
                "created_at": 1
            },
        }, {
            "$lookup": {
                "from":
                "votes",
                "let": {
                    "post_id": "$_id"
                },
                "pipeline": [{
                    "$match": {
                        "$expr": {
                            "$and": [{
                                "$eq": ["$post_id", "$$post_id"]
                            }, {
                                "$eq": ["$user_id", user_id]
                            }]
                        }
                    }
                }, {
                    "$project": {
                        "_id": 0,
                        "value": 1
                    }
                }],
                "as":
                "votes",
            }
        }]

        for doc in BasePost.aggregate(c_pipeline):
            doc["my_vote"] = doc["votes"][0]["value"] if doc["votes"] else 0
            del doc["votes"]
            if doc["deleted"]:
                # skip deleted answers unless user is the author or a moderator
                if not user or (not user.moderator
                                and user._id != doc["author_id"]):
                    continue
            results["comments"].append(doc)
            author_ids.add(doc["author_id"])

        results["authors"] = (User.find({"_id": {"$in": list(author_ids)}}))

        return results
Ejemplo n.º 21
0
def delete_post(post):
    if not post.delete_allowed:
        raise Forbidden("you can't delete this post")
    user = get_user_from_app_context()
    post.delete_by(user)
Ejemplo n.º 22
0
def replace_subscription():
    if "tags" not in request.json:
        raise ApiError("tags field is mandatory")
    user: User = get_user_from_app_context()
    user.replace_tags(request.json["tags"])
    return json_response({"data": user.tag_subscription.to_dict()})
Ejemplo n.º 23
0
def me():
    user = get_user_from_app_context()
    return json_response({
        "data": account_dict(user),
        "providers": BaseProvider.list_provider_info()
    })
Ejemplo n.º 24
0
def update_settings():
    user: User = get_user_from_app_context()
    user.update(request.json)
    return json_response({
        "data": account_dict(user),
    })
Ejemplo n.º 25
0
def index():
    user: User = get_user_from_app_context()
    events = user.get_new_events().sort("created_at", -1)
    return json_response(
        paginated(events, limit=5, transform=lambda event: event.api_dict()))
Ejemplo n.º 26
0
 def wrapper(*args, **kwargs):
     u = get_user_from_app_context()
     if u is None:
         raise AuthenticationError()
     return func(*args, **kwargs)
Ejemplo n.º 27
0
def unsubscribe(tagname):
    Tag.get(tagname, "tag not found")
    user: User = get_user_from_app_context()
    user.unsubscribe_from_tag(tagname)
    return json_response({"data": user.tag_subscription.to_dict()})
Ejemplo n.º 28
0
 def delete_allowed(self) -> bool:
     user: User = get_user_from_app_context()
     # print(user, user.moderator)
     return self.author_id == user._id or user.moderator
Ejemplo n.º 29
0
 def restore_allowed(self) -> bool:
     user: User = get_user_from_app_context()
     return user._id == self.deleted_by_id
Ejemplo n.º 30
0
def update_post(post):
    if not post.update_allowed:
        raise Forbidden("you can't edit this post")
    attrs = request.json
    user = get_user_from_app_context()
    post.update_by(user, attrs)