def edit_bookmark(username: str, url_uuid: UUID) -> flask.Response:
    owner = get_user_or_fail(db.session, username)
    require_access_or_fail(
        BookmarkAccessObject(user_uuid=owner.user_uuid, url_uuid=url_uuid),
        Access.WRITE,
    )
    form = flask.request.form
    existing_bookmark = get_bookmark_by_url_uuid(db.session, owner.user_uuid,
                                                 url_uuid)
    if existing_bookmark is None:
        raise exc.NotFound()

    updated_bookmark = Bookmark(
        url=existing_bookmark.url,
        created=existing_bookmark.created,
        title=form["title"],
        description=form["description"],
        unread="unread" in form,
        deleted="deleted" in form,
        updated=datetime.utcnow().replace(tzinfo=timezone.utc),
        tag_triples=tag_triples_from_form(
            form, current=existing_bookmark.tag_triples),
    )

    merged_bookmark = updated_bookmark.merge(existing_bookmark)

    set_bookmark(db.session, get_cache(), owner.user_uuid, merged_bookmark)
    db.session.commit()
    flask.flash("Edited: %s" % merged_bookmark.title)
    return flask.make_response("ok")
Exemple #2
0
def test_doubling_issue(session, test_user):
    """Test to check that a row doubling issue between tags and discussions has not been regressed.

    This is for bug #65.
    """
    epoch_start = datetime(2018, 1, 3)
    bm = make_bookmark(
        tag_triples=set([("a", epoch_start, False), ("b", epoch_start, False)])
    )
    set_bookmark(session, test_user.user_uuid, bm)

    discussions = [
        Discussion(
            external_id=str(random_numeric_id()),
            source=DiscussionSource.REDDIT,
            url=bm.url,
            comment_count=1,
            created_at=datetime(2018, 1, 3),
            title="example",
        ),
        Discussion(
            external_id=str(random_numeric_id()),
            source=DiscussionSource.HN,
            url=bm.url,
            comment_count=0,
            created_at=datetime(2018, 1, 3),
            title="example",
        ),
    ]

    upsert_discussions(session, discussions)
    bookmarks = list(f for f in BookmarkViewQueryBuilder(session, test_user).execute())
    assert len(bookmarks) == 1
Exemple #3
0
def test_discussion_digests_no_discussions(session, test_user):
    bm = make_bookmark()
    set_bookmark(session, test_user.user_uuid, bm)

    (bm1_view,) = (f for f in BookmarkViewQueryBuilder(session, test_user).execute())
    assert bm1_view.discussion_digest.comment_count == 0
    assert bm1_view.discussion_digest.discussion_count == 0
    assert bm1_view.discussion_digest.sources == set()
Exemple #4
0
def test_user_tags(session, cache, test_user):
    epoch_start = datetime(1970, 1, 1, tzinfo=timezone.utc)
    bm_1 = make_bookmark(
        tag_triples=frozenset([("a", epoch_start,
                                False), ("b", epoch_start, False)]))
    bm_2 = make_bookmark(
        tag_triples=frozenset([("b", epoch_start,
                                False), ("c", epoch_start, True)]))
    set_bookmark(session, cache, test_user.user_uuid, bm_1)
    set_bookmark(session, cache, test_user.user_uuid, bm_2)

    expected = set(["a", "b"])
    assert set(user_tags(session, test_user)) == expected
Exemple #5
0
def test_links_and_backlinks(session, test_user):
    bm1 = make_bookmark()
    bm2 = make_bookmark()
    bm3 = make_bookmark()
    bm4 = make_bookmark()
    set_bookmark(session, test_user.user_uuid, bm1)
    set_bookmark(session, test_user.user_uuid, bm2)
    set_bookmark(session, test_user.user_uuid, bm3)
    set_bookmark(session, test_user.user_uuid, bm4)
    upsert_links(session, bm1.url, {bm2.url, bm3.url})
    upsert_links(session, bm4.url, {bm1.url})

    (bm1_view,) = (
        f
        for f in BookmarkViewQueryBuilder(session, test_user).execute()
        if f.bookmark == bm1
    )
    assert bm1_view.link_count == 2
    assert bm1_view.backlink_count == 1

    bm1_links = (
        BookmarkViewQueryBuilder(session, test_user).links(bm1.url.url_uuid).execute()
    )
    bm1_links_bvs = {bv.bookmark for bv in bm1_links}
    assert bm1_links_bvs == {bm2, bm3}

    bm1_backlinks = (
        BookmarkViewQueryBuilder(session, test_user)
        .backlinks(bm1.url.url_uuid)
        .execute()
    )
    bm1_links_bvs = {bv.bookmark for bv in bm1_backlinks}
    assert bm1_links_bvs == {bm4}
Exemple #6
0
def test_discussion_digests(session, test_user):
    bm = make_bookmark()
    set_bookmark(session, test_user.user_uuid, bm)

    discussions = [
        Discussion(
            external_id=str(random_numeric_id()),
            source=DiscussionSource.HN,
            url=bm.url,
            comment_count=1,
            created_at=datetime(2018, 1, 3),
            title="example",
        ),
        Discussion(
            external_id=str(random_numeric_id()),
            source=DiscussionSource.HN,
            url=bm.url,
            comment_count=0,
            created_at=datetime(2018, 1, 3),
            title="example",
        ),
        Discussion(
            external_id=str(random_numeric_id()),
            source=DiscussionSource.HN,
            url=bm.url,
            comment_count=100,
            created_at=datetime(2018, 1, 3),
            title="example",
        ),
        Discussion(
            external_id=str(random_numeric_id()),
            source=DiscussionSource.REDDIT,
            url=bm.url,
            comment_count=1,
            created_at=datetime(2018, 1, 3),
            title="example",
        ),
    ]

    upsert_discussions(session, discussions)
    (bm1_view,) = (f for f in BookmarkViewQueryBuilder(session, test_user).execute())
    assert bm1_view.discussion_digest.comment_count == 102
    assert bm1_view.discussion_digest.discussion_count == 4
    assert bm1_view.discussion_digest.sources == {
        DiscussionSource.HN,
        DiscussionSource.REDDIT,
    }
def test_quick_add_tag(session, cache, signed_in_client, test_user):
    bm = make_bookmark()
    set_bookmark(session, cache, test_user.user_uuid, bm)

    response = signed_in_client.post(
        flask.url_for(
            "quarchive.quick_add_tag",
            username=test_user.username,
            url_uuid=bm.url.url_uuid,
        ),
        data={"tag": "test-tag"},
    )
    assert response.status_code == 303

    new_bm = get_bookmark_by_url_uuid(session, test_user.user_uuid,
                                      bm.url.url_uuid)
    assert new_bm is not None
    assert "test-tag" in new_bm.current_tags()
def quick_add_tag(username: str, url_uuid: UUID) -> flask.Response:
    owner = get_user_or_fail(db.session, username)
    require_access_or_fail(
        BookmarkAccessObject(user_uuid=owner.user_uuid, url_uuid=url_uuid),
        Access.WRITE)
    bookmark = get_bookmark_by_url_uuid_or_fail(db.session, owner.user_uuid,
                                                url_uuid)
    tag = flask.request.form["tag"]
    set_bookmark(db.session, owner.user_uuid, bookmark.with_tag(tag))
    db.session.commit()
    flask.flash(f"Tagged '{bookmark.title}' with '{tag}'")
    response = flask.make_response("Redirecting...", 303)
    response.headers["Location"] = flask.url_for(
        "quarchive.edit_bookmark_form",
        url_uuid=url_uuid,
        username=owner.username,
    )
    return response
Exemple #9
0
def test_icon_uuids_url_icon(session, test_user, canonical_url):
    bm1 = make_bookmark()
    set_bookmark(session, test_user.user_uuid, bm1)
    if canonical_url:
        canonical_url = bm1.url.follow("canonical.html")
        upsert_url(session, canonical_url)
        session.add(
            CanonicalUrl(
                non_canonical_url_uuid=bm1.url.url_uuid,
                canonical_url_uuid=canonical_url.url_uuid,
            )
        )

    icon_url = URL.from_string("http://example.com/" + random_string() + "/icon.png")
    upsert_url(session, icon_url)
    random_hash = random_bytes(64)
    icon_uuid = record_page_icon(session, icon_url, bm1.url, random_hash)

    (bm1_view,) = (f for f in BookmarkViewQueryBuilder(session, test_user).execute())
    assert bm1_view.icon_uuid == icon_uuid
Exemple #10
0
def test_most_recent_successful_crawls(session, cache, test_user):
    # Crawl 1 is an old crawl of url 1 (should not be present)
    # Crawl 2 is a more recent crawl of url 1
    # Crawl 3 is a crawl of url 3 that didn't get a response
    # Crawl 4 is a crawl that of url 4 returned a non-2xx status code
    # Only crawl 2 should be present

    url_1 = SQLAUrl.from_url(
        URL.from_string(f"http://example.com/{random_string()}"))
    bm_1 = make_bookmark(url=url_1.to_url())
    set_bookmark(session, cache, test_user.user_uuid, bm_1)
    crawl_req_1 = CrawlRequest(  # type: ignore
        crawl_uuid=uuid4(),
        requested=datetime(2018, 1, 3),
        got_response=True,
        url_uuid=url_1.url_uuid,
        response_obj=CrawlResponse(body_uuid=uuid4(),
                                   headers={},
                                   status_code=200),
    )
    crawl_req_2 = CrawlRequest(  # type: ignore
        crawl_uuid=uuid4(),
        requested=datetime(2018, 1, 4),
        got_response=True,
        url_uuid=url_1.url_uuid,
        response_obj=CrawlResponse(body_uuid=uuid4(),
                                   headers={},
                                   status_code=200),
    )
    url_3 = SQLAUrl.from_url(
        URL.from_string(f"http://example.com/{random_string()}"))
    bm_3 = make_bookmark(url=url_3.to_url())
    set_bookmark(session, cache, test_user.user_uuid, bm_3)
    crawl_req_3 = CrawlRequest(
        crawl_uuid=uuid4(),
        requested=datetime(2018, 1, 3),
        got_response=False,
        url_uuid=url_3.url_uuid,
    )
    url_4 = SQLAUrl.from_url(
        URL.from_string(f"http://example.com/{random_string()}"))
    bm_4 = make_bookmark(url=url_3.to_url())
    set_bookmark(session, cache, test_user.user_uuid, bm_4)
    crawl_req_4 = CrawlRequest(  # type: ignore
        crawl_uuid=uuid4(),
        requested=datetime(2018, 1, 3),
        got_response=False,
        url_uuid=url_3.url_uuid,
        response_obj=CrawlResponse(body_uuid=uuid4(),
                                   headers={},
                                   status_code=404),
    )
    session.add_all([crawl_req_1, crawl_req_2, crawl_req_3, crawl_req_4])
    session.commit()

    rv = set(most_recent_successful_bookmark_crawls(session))
    assert crawl_req_1.crawl_uuid not in rv
    assert crawl_req_2.crawl_uuid in rv
    assert crawl_req_3.crawl_uuid not in rv
    assert crawl_req_3.crawl_uuid not in rv
Exemple #11
0
def test_discussions(signed_in_client, test_user, session):
    bm = make_bookmark()
    set_bookmark(session, test_user.user_uuid, bm)

    discussions = [
        Discussion(
            external_id=str(random_numeric_id()),
            source=DiscussionSource.HN,
            url=bm.url,
            comment_count=1,
            created_at=datetime(2018, 1, 3),
            title="HN discussion 1",
        )
    ]

    upsert_discussions(session, discussions)

    response = signed_in_client.get(
        flask.url_for(
            "quarchive.discussions",
            username=test_user.username,
            url_uuid=bm.url.url_uuid,
        ))
    assert response.status_code == 200
def create_bookmark(username: str) -> flask.Response:
    owner = get_user_or_fail(db.session, username)
    # FIXME: sort out optional url_uuid
    require_access_or_fail(
        UserBookmarksAccessObject(user_uuid=owner.user_uuid),
        Access.WRITE,
    )
    form = flask.request.form
    creation_time = datetime.utcnow().replace(tzinfo=timezone.utc)
    tag_triples = tag_triples_from_form(form)

    url_str = form["url"]
    try:
        # As it's a user entering this url, help them along with getting a
        # sufficiently canonicalised url
        url = URL.from_string(url_str, coerce_canonicalisation=True)
    except DisallowedSchemeException:
        log.warning("user tried to create url: %s (disallowed scheme)",
                    url_str)
        flask.abort(400, "invalid url (disallowed scheme)")

    bookmark = Bookmark(
        url=url,
        title=form["title"],
        description=form["description"],
        unread="unread" in form,
        deleted=False,
        updated=creation_time,
        created=creation_time,
        tag_triples=tag_triples,
    )
    url_uuid = set_bookmark(db.session, get_cache(), owner.user_uuid, bookmark)
    db.session.commit()
    publish_message(
        message_lib.BookmarkCreated(user_uuid=owner.user_uuid,
                                    url_uuid=url.url_uuid),
        environ["QM_RABBITMQ_BG_WORKER_TOPIC"],
    )
    flask.flash("Bookmarked: %s" % bookmark.title)
    response = flask.make_response("Redirecting...", 303)
    response.headers["Location"] = flask.url_for(
        "quarchive.edit_bookmark_form",
        url_uuid=url_uuid,
        username=owner.username,
    )
    return response
Exemple #13
0
def create_bookmark() -> flask.Response:
    form = flask.request.form
    creation_time = datetime.utcnow().replace(tzinfo=timezone.utc)
    tag_triples = tag_triples_from_form(form)
    bookmark = Bookmark(
        url=URL.from_string(form["url"]),
        title=form["title"],
        description=form["description"],
        unread="unread" in form,
        deleted=False,
        updated=creation_time,
        created=creation_time,
        tag_triples=tag_triples,
    )
    url_uuid = set_bookmark(db.session, get_current_user().user_uuid, bookmark)
    db.session.commit()
    flask.flash("Bookmarked: %s" % bookmark.title)
    response = flask.make_response("Redirecting...", 303)
    response.headers["Location"] = flask.url_for(
        "quarchive.edit_bookmark_form", url_uuid=url_uuid
    )
    return response
Exemple #14
0
def test_simple_bookmark(session, test_user):
    bm = make_bookmark()
    set_bookmark(session, test_user.user_uuid, bm)

    (found,) = list(BookmarkViewQueryBuilder(session, test_user).execute())
    assert found.bookmark == bm