Exemplo n.º 1
0
    def test_get_and_count(self):
        """Test the get function that gets revisions for the test review ordered by the timestamp
        and the count function that returns the total number of revisions of a review"""

        review_id = self.review.id
        count = revision.get_count(review_id)
        first_revision = revision.get(review_id)[0]
        self.assertEqual(count, 1)
        self.assertEqual(first_revision['text'], "Testing!")
        self.assertEqual(type(first_revision['timestamp']), datetime)
        self.assertEqual(type(first_revision['id']), int)

        self.review.update(text="Testing Again!")
        second_revision = revision.get(review_id)[0]
        count = revision.get_count(review_id)
        self.assertEqual(count, 2)
        self.assertEqual(second_revision['text'], "Testing Again!")
        self.assertEqual(type(second_revision['timestamp']), datetime)
        self.assertEqual(type(second_revision['id']), int)

        self.review.update(text="Testing Once Again!")
        # Testing offset and limit
        first_two_revisions = revision.get(review_id, limit=2, offset=1)
        count = revision.get_count(review_id)
        self.assertEqual(count, 3)
        self.assertEqual(first_two_revisions[1]['text'], "Testing!")
        self.assertEqual(first_two_revisions[0]['text'], "Testing Again!")
Exemplo n.º 2
0
def revisions_more(id):
    review = Review.query.get_or_404(str(id))

    # Not showing review if it isn't published yet and not viewed by author.
    if review.is_draft and not (current_user.is_authenticated
                                and current_user == review.user):
        raise NotFound("Can't find a review with the specified ID.")
    if review.is_hidden and not current_user.is_admin():
        raise NotFound(gettext("Review has been hidden."))

    page = int(request.args.get('page', default=0))
    offset = page * RESULTS_LIMIT
    try:
        count = db_revision.get_count(id)
        revisions = db_revision.get(id, limit=RESULTS_LIMIT, offset=offset)
    except db_exceptions.NoDataFoundException:
        raise NotFound(
            gettext("The revision(s) you are looking for does not exist."))
    votes = db_revision.get_votes(id)
    results = list(
        zip(reversed(range(count - offset - RESULTS_LIMIT, count - offset)),
            revisions))

    template = render_template('review/revision_results.html',
                               review=review,
                               results=results,
                               votes=votes,
                               count=count)
    return jsonify(results=template, more=(count - offset - RESULTS_LIMIT) > 0)
Exemplo n.º 3
0
def entity(id, rev=None):
    review = get_review_or_404(id)
    # Not showing review if it isn't published yet and not viewed by author.
    if review["is_draft"] and not (current_user.is_authenticated
                                   and current_user == review["user"]):
        raise NotFound(gettext("Can't find a review with the specified ID."))
    if review["is_hidden"]:
        if not current_user.is_admin():
            raise Forbidden(
                gettext("Review has been hidden. "
                        "You need to be an administrator to view it."))
        else:
            flash.warn(gettext("Review has been hidden."))

    spotify_mappings = None
    soundcloud_url = None
    if review["entity_type"] == 'release_group':
        spotify_mappings = mbspotify.mappings(str(review["entity_id"]))
        soundcloud_url = soundcloud.get_url(str(review["entity_id"]))
    count = db_revision.get_count(id)
    if not rev:
        rev = count
    if rev < count:
        flash.info(
            gettext(
                'You are viewing an old revision, the review has been updated since then.'
            ))
    elif rev > count:
        raise NotFound(
            gettext("The revision you are looking for does not exist."))

    revision = db_revision.get(id, offset=count - rev)[0]
    if not review[
            "is_draft"] and current_user.is_authenticated:  # if user is logged in, get their vote for this review
        try:
            vote = db_vote.get(user_id=current_user.id,
                               revision_id=revision['id'])
        except db_exceptions.NoDataFoundException:
            vote = None
    else:  # otherwise set vote to None, its value will not be used
        vote = None
    if revision["text"] is None:
        review["text_html"] = None
    else:
        review["text_html"] = markdown(revision['text'], safe_mode="escape")

    user_all_reviews, review_count = db_review.list_reviews(  # pylint: disable=unused-variable
        user_id=review["user_id"],
        sort="random",
        exclude=[review["id"]],
    )
    other_reviews = user_all_reviews[:3]
    avg_rating = get_avg_rating(review["entity_id"], review["entity_type"])
    return render_template('review/entity/%s.html' % review["entity_type"],
                           review=review,
                           spotify_mappings=spotify_mappings,
                           soundcloud_url=soundcloud_url,
                           vote=vote,
                           other_reviews=other_reviews,
                           avg_rating=avg_rating)
Exemplo n.º 4
0
def compare(id):
    review = get_review_or_404(id)
    if review["is_draft"] and not (current_user.is_authenticated and
                                   current_user == review["user"]):
        raise NotFound(gettext("Can't find a review with the specified ID."))
    if review["is_hidden"] and not current_user.is_admin():
        raise NotFound(gettext("Review has been hidden."))
    count = db_revision.get_count(id)
    old, new = int(request.args.get('old') or count - 1), int(request.args.get('new') or count)
    if old > count or new > count:
        raise NotFound(gettext("The revision(s) you are looking for does not exist."))
    if old > new:
        return redirect(url_for('.compare', id=id, old=new, new=old))
    left = db_revision.get(id, offset=count - old)[0]
    right = db_revision.get(id, offset=count - new)[0]
    left['number'], right['number'] = old, new
    left['text'], right['text'] = side_by_side_diff(left['text'], right['text'])
    return render_template('review/compare.html', review=review, left=left, right=right)
Exemplo n.º 5
0
    def test_get_all_votes(self):
        """Test to get the number of votes on revisions of a review"""

        review_id = self.review["id"]
        revision.get_count(review_id)
        first_revision = revision.get(review_id)[0]
        vote.submit(self.user_1.id, first_revision['id'], True)
        vote.submit(self.user_2.id, first_revision['id'], False)
        votes = revision.get_all_votes(review_id)
        votes_first_revision = votes[first_revision['id']]
        self.assertDictEqual(votes_first_revision, {
            "positive": 1,
            "negative": 1
        })
Exemplo n.º 6
0
def revisions(id):
    review = get_review_or_404(id)
    # Not showing review if it isn't published yet and not viewed by author.
    if review["is_draft"] and not (current_user.is_authenticated and
                                   current_user == review["user"]):
        raise NotFound("Can't find a review with the specified ID.")
    if review["is_hidden"] and not current_user.is_admin():
        raise NotFound(gettext("Review has been hidden."))
    try:
        count = db_revision.get_count(id)
        revisions = db_revision.get(id, limit=RESULTS_LIMIT)
    except db_exceptions.NoDataFoundException:
        raise NotFound(gettext("The revision(s) you are looking for does not exist."))
    votes = db_revision.get_all_votes(id)
    results = list(zip(reversed(range(count - RESULTS_LIMIT, count)), revisions))
    return render_template('review/revisions.html', review=review, results=results,
                           count=count, limit=RESULTS_LIMIT, votes=votes)
Exemplo n.º 7
0
def review_revision_entity_handler(review_id, rev):
    """Get a particular revisions of review with a specified UUID.

    **Request Example:**

    .. code-block:: bash

        $ curl https://critiquebrainz.org/ws/1/review/b7575c23-13d5-4adc-ac09-2f55a647d3de/revisions/1 \\
               -X GET

    **Response Example:**

    .. code-block:: json

        {
          "revision": {
            "id": 1,
            "review_id": "b7575c23-13d5-4adc-ac09-2f55a647d3de",
            "text": "TEXT CONTENT OF REVIEW",
            "rating": 5,
            "timestamp": "Tue, 10 Aug 2010 00:00:00 GMT",
            "votes_negative": 0,
            "votes_positive": 0
          }
        }

    :statuscode 200: no error
    :statuscode 404: review not found

    :resheader Content-Type: *application/json*
    """
    review = get_review_or_404(review_id)
    if review["is_hidden"]:
        raise NotFound("Review has been hidden.")

    count = db_revision.get_count(review["id"])
    if rev > count:
        raise NotFound("Can't find the revision you are looking for.")

    revision = db_revision.get(review_id, offset=count - rev)[0]
    revision.update(id=rev)
    return jsonify(revision=revision)
Exemplo n.º 8
0
def review_revisions_handler(review_id):
    """Get revisions of review with a specified UUID.

    **Request Example:**

    .. code-block:: bash

        $ curl https://critiquebrainz.org/ws/1/review/b7575c23-13d5-4adc-ac09-2f55a647d3de/revisions \\
               -X GET

    **Response Example:**

    .. code-block:: json

        {
          "revisions": [
            {
              "id": 1,
              "review_id": "b7575c23-13d5-4adc-ac09-2f55a647d3de",
              "text": "TEXT CONTENT OF REVIEW",
              "rating": 5,
              "timestamp": "Tue, 10 Aug 2010 00:00:00 GMT",
              "votes_negative": 0,
              "votes_positive": 0
            }
          ]
        }

    :statuscode 200: no error
    :statuscode 404: review not found

    :resheader Content-Type: *application/json*
    """
    review = get_review_or_404(review_id)
    if review["is_hidden"]:
        raise NotFound("Review has been hidden.")
    revisions = db_revision.get(review_id, limit=None)
    count = len(revisions)
    for i, r in enumerate(revisions):
        r.update(id=count - i)
    return jsonify(revisions=revisions)
Exemplo n.º 9
0
def has_voted(user_id, review_id):
    """Check if a user has already voted on the last revision of a review.

    Args:
        user_id(uuid): ID of the user.
        review_id(uuid): ID of the review.

    Returns:
        (bool): True if has voted else False.
    """
    last_revision = db_revision.get(review_id, limit=1)[0]
    with db.engine.connect() as connection:
        result = connection.execute(sqlalchemy.text("""
            SELECT count(*)
              FROM vote
             WHERE revision_id = :revision_id
               AND user_id = :user_id
            """), {
                "revision_id": last_revision['id'],
                "user_id": user_id
            })
        count = result.fetchone()[0]
    return count > 0
Exemplo n.º 10
0
    def test_update(self):
        review = db_review.create(
            user_id=self.user.id,
            entity_id="e7aad618-fa86-3983-9e77-405e21796eca",
            entity_type="release_group",
            text="Testing",
            rating=5,
            is_draft=True,
            license_id=self.license["id"],
        )
        another_license = db_license.create(
            id="License-2",
            full_name="Another License",
        )
        # Update review to only rating
        db_review.update(
            review_id=review["id"],
            drafted=review["is_draft"],
            rating=4,
            is_draft=False,
            license_id=another_license["id"],
            language="es",
        )
        # Checking if contents are updated
        retrieved_review = db_review.list_reviews()[0][0]
        self.assertEqual(retrieved_review["text"], None)
        self.assertEqual(retrieved_review["rating"], 4)
        self.assertFalse(retrieved_review["is_draft"])
        self.assertEqual(retrieved_review["license_id"], another_license["id"])
        self.assertEqual(retrieved_review["language"], "es")
        # Update review to only text
        db_review.update(
            review_id=review["id"],
            drafted=review["is_draft"],
            text="Testing update",
            is_draft=False,
            license_id=another_license["id"],
            language="es",
        )
        # Checking if contents are updated
        retrieved_review = db_review.list_reviews()[0][0]
        self.assertEqual(retrieved_review["text"], "Testing update")
        self.assertEqual(retrieved_review["rating"], None)

        # Updating should create a new revision.
        revisions = db_revision.get(retrieved_review["id"], limit=None)
        self.assertEqual(len(revisions), 3)
        self.assertEqual(revisions[0]["timestamp"],
                         retrieved_review["last_revision"]["timestamp"])
        self.assertEqual(revisions[0]["text"], retrieved_review["text"])
        self.assertEqual(revisions[0]["rating"], retrieved_review["rating"])

        # Checking things that shouldn't be allowed
        with self.assertRaises(db_exceptions.BadDataException):
            db_review.update(
                review_id=retrieved_review["id"],
                drafted=retrieved_review["is_draft"],
                text="Sucks!",
                license_id=self.license["id"],
            )
        review = db_review.get_by_id(review["id"])
        with self.assertRaises(db_exceptions.BadDataException):
            db_review.update(
                review_id=review["id"],
                drafted=review["is_draft"],
                text="Sucks!",
                is_draft=True,
            )
Exemplo n.º 11
0
def list_reports(**kwargs):
    """Returns the list of reports submitted by users on reviews.

    Args:
        inc_archived(bool, optional): True if archived spam reports to be included.
        review_id(uuid, optional): Specify review ID to list all its spam reports.
        user_id(uuid, optional): Specify user ID to list all spam report by a user.
        offset(int, optional): The number of spam reports to skip from top.
        limit(int, optional): The number of spam reports to select.

    Returns:
        List of dictionaries of spam reports with the following structure:
        {
            "user_id": (uuid),
            "reason": (str),
            "revision_id": (int),
            "reported_at": (datetime),
            "is_archived": (bool)
            "review": (dict containing id, entity_id, user, last_revision)
            "user": (dict containing id, display_name)
        }
        and the number of spam reports after applying the specified filters.
    """
    filters = []
    filter_data = {}

    if "inc_archived" in kwargs:
        inc_archived = kwargs.pop("inc_archived")
        if not inc_archived:
            filters.append("is_archived = :is_archived")
            filter_data["is_archived"] = inc_archived

    if "review_id" in kwargs:
        review_id = kwargs.pop("review_id")
        filters.append("revision_id IN :revision_ids")
        filter_data["revision_ids"] = tuple([
            revision['id']
            for revision in db_revision.get(review_id, limit=None)
        ])

    if "user_id" in kwargs:
        filters.append("user_id = :user_id")
        filter_data["user_id"] = kwargs.pop("user_id")

    filter_data["offset"] = kwargs.pop("offet", None)
    filter_data["limit"] = kwargs.pop("limit", None)
    if kwargs:
        raise TypeError('Unexpected **kwargs: %r' % kwargs)

    filterstr = "AND ".join(filters)

    if filterstr:
        # Use WHERE only when there is data to filter.
        filterstr = "WHERE " + filterstr

    query = sqlalchemy.text("""
        SELECT "user".id as reporter_id,
               "user".display_name as reporter_name,
               user_id,
               reason,
               revision_id,
               reported_at,
               is_archived,
               review_uuid,
               review_user_id,
               entity_id,
               review_user_display_name
          FROM "user"
    INNER JOIN (spam_report
               INNER JOIN (revision
                           INNER JOIN (
                           SELECT review.id as review_uuid,
                                  "user".id as review_user_id,
                                  review.entity_id,
                                  "user".display_name as review_user_display_name
                             FROM review
                       INNER JOIN "user"
                               ON "user".id = review.user_id)
                               AS review_detail
                               ON review_id = review_detail.review_uuid)
                       ON spam_report.revision_id = revision.id)
            ON spam_report.user_id = "user".id
            {}
        OFFSET :offset
         LIMIT :limit
    """.format(filterstr))

    with db.engine.connect() as connection:
        result = connection.execute(query, filter_data)
        spam_reports = result.fetchall()
        if spam_reports:
            spam_reports = [dict(spam_report) for spam_report in spam_reports]
            for spam_report in spam_reports:

                spam_report["review"] = {
                    "user": {
                        "id":
                        spam_report.pop("review_user_id"),
                        "display_name":
                        spam_report.pop("review_user_display_name"),
                    },
                    "id":
                    spam_report["review_uuid"],
                    "entity_id":
                    spam_report.pop("entity_id"),
                    "last_revision":
                    db_revision.get(spam_report.pop("review_uuid"))[0],
                }

                spam_report["user"] = {
                    "id": spam_report.pop("reporter_id"),
                    "display_name": spam_report.pop("reporter_name"),
                }
    return spam_reports, len(spam_reports)