def remove_article_from_brainspell_database_collection(collection,
                                                       pmid,
                                                       api_key,
                                                       cold_run=True):
    """ Remove an article from the Brainspell repo. Do not affect GitHub.

    Takes collection_name *without* "brainspell-collection".

    Similar implementation to add_article_to_brainspell_database_collection. """

    user = get_user_object_from_api_key(api_key)
    if user.count > 0:
        user = list(user)[0]
        if user.collections:
            # assumes collections are well-formed JSON
            target = json_decode(user.collections)
            if collection in target:
                pmids_list = list(
                    map(lambda x: str(x), target[collection]["pmids"]))
                if str(pmid) in pmids_list:
                    pmids_list.remove(str(pmid))
                    target[collection]["pmids"] = pmids_list
                    if not cold_run:
                        q = User.update(collections=json_encode(target)).where(
                            User.password == api_key)
                        q.execute()
                    return True
                else:
                    return False  # article not in collection
            else:
                return False  # collection doesn't exist
        else:
            return False  # user has no collections; violates assumptions
    return False  # user does not exist
def bulk_add_articles_to_brainspell_database_collection(
        collection, pmids, api_key, cold_run=True):
    """ Adds the PMIDs to collection_name, if such a collection exists under
    the given user. Assumes that the collection exists. Does not add repeats.

    Takes collection_name *without* "brainspell-collection".

    Return False if an assumption is violated, True otherwise. """

    user = get_user_object_from_api_key(api_key)
    if user.count > 0:
        user = list(user)[0]
        if user.collections:
            # assumes collections are well-formed JSON
            target = json_decode(user.collections)
            if collection not in target:
                target[collection] = {"description": "None", "pmids": []}

            pmid_set = set(map(lambda x: str(x), target[collection]["pmids"]))
            for pmid in pmids:
                pmid_set.add(str(pmid))

            target[collection]["pmids"] = list(pmid_set)
            if not cold_run:
                q = User.update(collections=json_encode(target)).where(
                    User.password == api_key)
                q.execute()
            return True
        else:
            return False  # user has no collections; violates assumptions
    return False  # user does not exist
示例#3
0
def get_boolean_map_from_article_object(article, width=5):
    """ Return a Brain of 0s and 1s corresponding to if any coordinate exists at that location, in any of the article's experiment tables. """

    brain = Brain()

    try:
        experiments = json_decode(article.experiments)

        for exp in experiments:
            locations = exp["locations"]
            for coord_string in locations:
                coord = coord_string.split(",")
                try:  # assumes that coordinates are well-formed
                    coord_tuple = (int(float(coord[0])), int(float(coord[1])),
                                   int(float(coord[2])))
                    brain.insert_at_location(1, *coord_tuple, width=width)
                except BaseException as e:
                    # malformed coordinate
                    print(e)
                    pass
    except BaseException as e:
        # article not valid, or malformed JSON
        print(e)
        pass

    return brain
示例#4
0
    def __get_current_github_object__(self):
        """
        Return an object representing the user's name, avatar, and
        access_token, or None is the user is not logged in.
        Technically a "private" method; please use the get_current_* methods.
        """

        try:
            return json_decode(self.get_secure_cookie("user"))
        except BaseException:
            return None
def get_brainspell_collections_from_api_key(api_key):
    """
    Return a user's collections from Brainspell's database given an API key.

    May be inconsistent with GitHub.
    """

    response = {}
    if valid_api_key(api_key):
        user = list(get_user_object_from_api_key(api_key))[0]
        if user.collections:
            return json_decode(user.collections)
    return response
示例#6
0
def add_article_to_brainspell_database_collection(
        collection, pmid, api_key, cold_run=True):
    """
    Add a collection to our local database. Do not add to GitHub in this function.

    Assumes that the collection already exists. Assumes that the user exists.

    Takes collection_name *without* "brainspell-collection".
    Returns False if the article is already in the collection, or if an assumption
    is violated.

    This is an O(N) operation with respect to the collection size.
    If you're adding many articles, it's O(N^2). If you're adding multiple articles,
    please use bulk_add_articles_to_brainspell_database_collection.

    Called by AddToCollectionEndpointHandler.
    """

    user = get_user_object_from_api_key(api_key)
    if user.count > 0:
        user = list(user)[0]
        if user.collections:
            # assumes collections are well-formed JSON
            target = json_decode(user.collections)
            if collection not in target:
                target[collection] = {
                    "description": "None",
                    "pmids": []
                }
            pmids_list = set(
                map(lambda x: str(x), target[collection]["pmids"]))
            # provide a check for if the PMID is already in the collection
            if str(pmid) not in pmids_list:
                pmids_list.add(str(pmid))
                target[collection]["pmids"] = list(pmids_list)
                if not cold_run:
                    q = User.update(
                        collections=json_encode(target)).where(
                        User.password == api_key)
                    q.execute()
                return True
            else:
                return False  # article already in collection
        else:
            return False  # user has no collections; violates assumptions
    return False  # user does not exist
示例#7
0
def register_github_user(user_dict):
    """ Add a GitHub user to our database. """

    user_dict = json_decode(user_dict)

    # if the user doesn't already exist
    if (User.select().where(User.username ==
                            user_dict["login"]).execute().count == 0):
        username = user_dict["login"]
        email = user_dict["email"]
        hasher = hashlib.sha1()
        # password (a.k.a. API key) is a hash of the Github ID
        hasher.update(str(user_dict["id"]).encode('utf-8'))
        password = hasher.hexdigest()
        User.create(username=username, emailaddress=email, password=password)
        return True
    else:
        return False  # user already exists
示例#8
0
 def get_current_user(self):
     user_json = self.get_secure_cookie("user")
     if not user_json:
         return None
     return json_decode(user_json)
示例#9
0
 def get_current_user(self):
     user_json = self.get_secure_cookie("user")
     if not user_json:
         return None
     return json_decode(user_json)
    def process(self, response, args):
        collection = args["name"]
        pmid = args["pmid"]

        if remove_article_from_brainspell_database_collection(
                collection, pmid, args["key"]):
            github_username = get_github_username_from_api_key(args["key"])
            github_collection_name = "brainspell-collection-{}".format(
                collection)
            try:
                content_data = yield torngithub.github_request(
                    self.get_auth_http_client(),
                    '/repos/{owner}/{repo}/contents/{path}'.format(
                        owner=github_username,
                        repo=github_collection_name,
                        path="manifest.json"),
                    access_token=args["github_access_token"],
                    method="GET")
                content = content_data["body"]["content"]
                # get the SHA so we can update this file
                manifest_sha = content_data["body"]["sha"]
                # parse the manifest.json file for the collection
                collection_contents = json_decode(
                    b64decode(content.encode('utf-8')).decode('utf-8'))

                collection_contents = [
                    c for c in collection_contents if str(c["pmid"]) != pmid
                ]

                manifest_contents_encoded = b64encode(
                    json_encode(collection_contents).encode("utf-8")).decode(
                        'utf-8')

                update_manifest_body = {
                    "message": "creating manifest.json file",
                    "content": manifest_contents_encoded,
                    "sha": manifest_sha
                }

                update_manifest_ress = yield [
                    torngithub.github_request(
                        self.get_auth_http_client(),
                        '/repos/{owner}/{repo}/contents/{path}'.format(
                            owner=github_username,
                            repo=github_collection_name,
                            path="manifest.json"),
                        access_token=args["github_access_token"],
                        method="PUT",
                        body=update_manifest_body)
                ]
            except Exception as e:
                print(e)
                response["success"] = 0
                response[
                    "description"] = "There was some failure in communicating with GitHub."
            finally:
                if response["success"] != 0:
                    # only remove from Brainspell collection if the GitHub
                    # operation succeeded
                    remove_article_from_brainspell_database_collection(
                        collection, pmid, args["key"], False)
        else:
            response["success"] = 0
            response[
                "description"] = "That article doesn't exist in that collection."

        self.finish_async(response)
        def callback_function(github_response=None):
            # check if the article is already in this collection
            # doesn't matter if we're bulk adding
            if args["bulk_add"] == 1 or add_article_to_brainspell_database_collection(
                    name, args["pmid"], args["key"]):
                pmid = args["pmid"]
                # idempotent operation to create the Brainspell collection
                # if it doesn't already exist (guaranteed that it exists on
                # GitHub)
                add_collection_to_brainspell_database(name, "None",
                                                      args["key"], False)

                # make a single PMID into a list so we can treat it the same
                # way
                if args["bulk_add"] == 0:
                    pmid = "[" + pmid + "]"
                pmid_list = json_decode(pmid)

                # add all of the PMIDs to GitHub, then insert to Brainspell

                github_username = get_github_username_from_api_key(args["key"])
                github_collection_name = "brainspell-collection-{}".format(
                    name)
                content_data = yield torngithub.github_request(
                    self.get_auth_http_client(),
                    '/repos/{owner}/{repo}/contents/{path}'.format(
                        owner=github_username,
                        repo=github_collection_name,
                        path="manifest.json"),
                    access_token=args["github_access_token"],
                    method="GET")
                content = content_data["body"]["content"]
                # get the SHA so we can update this file
                manifest_sha = content_data["body"]["sha"]
                # parse the manifest.json file for the collection
                collection_contents = json_decode(
                    b64decode(content.encode('utf-8')).decode('utf-8'))
                article_set = set([c["pmid"] for c in collection_contents])

                for p in pmid_list:
                    if p not in article_set:
                        # create the entry to add to the GitHub repo
                        article = list(get_article_object(p))[0]
                        article_entry = {
                            "pmid": p,
                            "title": article.title,
                            "reference": article.reference,
                            "doi": article.doi,
                            "notes": "Here are my notes on this article."
                        }
                        collection_contents.append(article_entry)
                        article_set.add(p)

                manifest_contents_encoded = b64encode(
                    json_encode(collection_contents).encode("utf-8")).decode(
                        'utf-8')

                update_manifest_body = {
                    "message": "creating manifest.json file",
                    "content": manifest_contents_encoded,
                    "sha": manifest_sha
                }

                update_manifest_ress = yield [
                    torngithub.github_request(
                        self.get_auth_http_client(),
                        '/repos/{owner}/{repo}/contents/{path}'.format(
                            owner=github_username,
                            repo=github_collection_name,
                            path="manifest.json"),
                        access_token=args["github_access_token"],
                        method="PUT",
                        body=update_manifest_body)
                ]

                # actually add the article(s) if the request succeeds
                bulk_add_articles_to_brainspell_database_collection(
                    name, pmid_list, args["key"], False)
            else:
                response["success"] = 0
                response[
                    "description"] = "That article already exists in that collection."
            self.finish_async(response)
    def process(self, response, args):
        collections_list = []

        # get all repos for an authenticated user using GitHub
        # need to use GitHub, because not storing "contributors_url" in
        # Brainspell's database
        data = yield get_user_repos(self.get_auth_http_client(),
                                    args["github_access_token"])
        repos = [
            d for d in data if d["name"].startswith("brainspell-collection-")
        ]

        if args["force_github_refresh"] == 1:
            remove_all_brainspell_database_collections(args["key"])

        # get all repos using the Brainspell database
        brainspell_cache = get_brainspell_collections_from_api_key(args["key"])

        # for each repo
        for repo_contents in repos:
            # guaranteed that the name starts with "brainspell-collection"
            # (from above)
            collection_name = repo_contents["name"][
                len("brainspell-collection-"):]
            repo = {
                # take the "brainspell-collection" off of the name
                "name": collection_name,
                "description": repo_contents["description"]
            }

            # get the contributor info for this collection
            contributor_info = yield torngithub.github_request(
                self.get_auth_http_client(),
                repo_contents["contributors_url"].replace(
                    "https://api.github.com", ""),
                access_token=args["github_access_token"],
                method="GET")
            repo["contributors"] = []
            if contributor_info["body"]:
                repo["contributors"] = contributor_info["body"]

            # get the PMIDs in the collection

            description = repo_contents["description"]
            valid_collection = True

            # if there's a new GitHub collection added to the user's profile,
            # then add it
            if collection_name not in brainspell_cache:
                try:
                    # fetch the PMIDs from GitHub
                    github_username = get_github_username_from_api_key(
                        args["key"])
                    content_data = yield torngithub.github_request(
                        self.get_auth_http_client(),
                        '/repos/{owner}/{repo}/contents/{path}'.format(
                            owner=github_username,
                            repo=repo_contents["name"],
                            path="manifest.json"),
                        access_token=args["github_access_token"],
                        method="GET")
                    content = content_data["body"]["content"]
                    # parse the manifest.json file for the collection
                    collection_contents = json_decode(
                        b64decode(content.encode('utf-8')).decode('utf-8'))
                    pmids = [c["pmid"] for c in collection_contents]

                    add_collection_to_brainspell_database(
                        collection_name, description, args["key"], False)
                    brainspell_cache[collection_name] = {
                        "description": description,
                        "pmids": pmids
                    }
                    if len(pmids) != 0:
                        # if PMIDs were fetched from GitHub
                        bulk_add_articles_to_brainspell_database_collection(
                            collection_name, pmids, args["key"], False)

                except BaseException:
                    # some error occurred with GitHub
                    # there was potentially no manifest file
                    valid_collection = False

            if valid_collection:
                # accounts for malformed collections, and excludes them
                pmids = brainspell_cache[collection_name]["pmids"]

                # determine if the pmid (if given) is in this collection
                repo["in_collection"] = any(
                    [str(pmid) == args["pmid"] for pmid in pmids])

                # convert PeeWee article object to dict
                def parse_article_object(article_object):
                    return {
                        "title": article_object.title,
                        "reference": article_object.reference,
                        "pmid": article_object.pmid
                    }

                # get article information from each pmid from the database
                repo["contents"] = [
                    parse_article_object(next(get_article_object(p)))
                    for p in pmids
                ]

                collections_list.append(repo)
        response["collections"] = collections_list
        self.finish_async(response)
示例#13
0
 def get_oauth_login_info(self):
     try:
         user_json = self.get_secure_cookie("user")
         return json_decode(user_json)
     except Exception:
         return None