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")
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
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()
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
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}
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
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
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
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
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
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