def add_collection_to_brainspell_database(collection_name,
                                          description,
                                          api_key,
                                          cold_run=True):
    """ Create a collection in our database if it doesn't exist,
    or return false if the collection already exists. """

    if valid_api_key(api_key):
        user = list(get_user_object_from_api_key(api_key))[0]

        # get the dict of user collections
        if not user.collections:
            user_collections = {}
        else:
            # unfortunately, because malformatted JSON exists in our database,
            # we have to use eval instead of using JSON.decode()
            user_collections = eval(user.collections)

        # if the collection doesn't already exist
        if collection_name not in user_collections:
            # create the collection
            user_collections[collection_name] = {}
            user_collections[collection_name]["description"] = str(description)
            user_collections[collection_name]["pmids"] = []
            if not cold_run:
                q = User.update(
                    collections=json_encode(user_collections)).where(
                        User.username == user.username)
                q.execute()
            return True
    return False
    def get(self):
        # we can append next to the redirect uri, so the user gets the
        # correct URL on login
        redirect_uri = url_concat(self.request.protocol
                                  + "://" + self.request.host
                                  + self.settings["github_callback_path"],
                                  {"next": self.get_argument('next', '/')})

        # if we have a code, we have been authorized so we can log in
        if self.get_argument("code", False):
            user = yield self.get_authenticated_user(
                redirect_uri=redirect_uri,
                client_id=self.settings["github_client_id"],
                client_secret=self.settings["github_client_secret"],
                code=self.get_argument("code"))
            if user:
                log.info('logged in user from github: ' + str(user))
                self.set_secure_cookie("user", json_encode(user))
            else:
                self.clear_cookie("user")
            self.redirect("/token")
            return

        # otherwise we need to request an authorization code
        yield self.authorize_redirect(
            redirect_uri=redirect_uri,
            client_id=self.settings["github_client_id"],
            extra_params={"scope": self.settings['github_scope'], "foo": 1})
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
Ejemplo n.º 4
0
    async def get(self):
        # we can append next to the redirect uri, so the user gets the
        # correct URL on login
        redirect_uri = url_concat(
            self.request.protocol + "://" + self.request.host +
            GITHUB_CALLBACK_PATH, {"next": self.get_argument('next', '/')})

        # if we have a code, we have been authorized so we can log in
        if self.get_argument("code", False):
            user = await self.get_authenticated_user(
                redirect_uri=redirect_uri,
                client_id=self.web_settings.GITHUB_CLIENT_ID,
                client_secret=self.web_settings.GITHUB_CLIENT_SECRET,
                code=self.get_argument("code"),
                callback=None)
            if user:
                logging.info('logged in user from github: %s', user)
                self.set_secure_cookie("user", json_encode(user))
            else:
                self.clear_cookie("user")
            self.redirect(self.get_argument("next", "/"))
            return

        # otherwise we need to request an authorization code
        await self.authorize_redirect(
            redirect_uri=redirect_uri,
            client_id=self.web_settings.GITHUB_CLIENT_ID,
            extra_params={
                "scope": GITHUB_SCOPE,
                "foo": 1
            })
Ejemplo n.º 5
0
    def __create_manifest_file__(self,
                                 name,
                                 access_token,
                                 github_username,
                                 callback=None):

        github_collection_name = "brainspell-collection-{}".format(name)

        initial_manifest_contents = []
        manifest_contents_encoded = b64encode(
            json_encode(initial_manifest_contents).encode("utf-8")).decode(
                'utf-8')

        create_manifest_body = {
            "message": "creating manifest.json file",
            "content": manifest_contents_encoded
        }

        create_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"),
                callback=callback,
                access_token=access_token,
                method="PUT",
                body=create_manifest_body)
        ]

        return create_manifest_ress
Ejemplo n.º 6
0
    async def prepare(self):

        super().prepare()

        # Additionally support GitHub Token Login
        # Mainly for debug and admin purposes

        if 'Authorization' in self.request.headers:
            if self.request.headers['Authorization'].startswith('Bearer '):
                token = self.request.headers['Authorization'].split(' ', 1)[1]
                http_client = AsyncHTTPClient()
                try:
                    response = await http_client.fetch(
                        "https://api.github.com/user",
                        request_timeout=10,
                        headers={'Authorization': 'token ' + token},
                        ca_certs=certifi.where())
                    user = json.loads(response.body)
                except Exception as e:  # TODO
                    logging.warning(e)
                else:
                    if 'login' in user:
                        logging.info('logged in user from github token: %s',
                                     user)
                        self.set_secure_cookie("user", json_encode(user))
                        self.current_user = user
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
Ejemplo n.º 8
0
    def get(self):
        # we can append next to the redirect uri, so the user gets the
        # correct URL on login
        redirect_uri = url_concat(self.request.protocol
                                  + "://" + self.request.host
                                  + self.settings["github_callback_path"],
                                  {"next": self.get_argument('next', '/')})

        # if we have a code, we have been authorized so we can log in
        if self.get_argument("code", False):
            user = yield self.get_authenticated_user(
                redirect_uri=redirect_uri,
                client_id=self.settings["github_client_id"],
                client_secret=self.settings["github_client_secret"],
                code=self.get_argument("code"))
            if user:
                log.info('logged in user from github: ' + str(user))
                self.set_secure_cookie("user", json_encode(user))
            else:
                self.clear_cookie("user")
            self.redirect(self.get_argument("next","/"))
            return

        # otherwise we need to request an authorization code
        self.authorize_redirect(
            redirect_uri=redirect_uri,
            client_id=self.settings["github_client_id"],
            extra_params={"scope": self.settings['github_scope'], "foo":1})
def remove_all_brainspell_database_collections(api_key):
    """ Dangerous! Drops all of a user's Brainspell collections
    from our local database. Does not affect GitHub.

    Called from CollectionsEndpointHandler."""

    if valid_api_key(api_key):
        q = User.update(collections=json_encode({})).where(
            User.password == api_key)
        q.execute()
Ejemplo n.º 10
0
    def get(self):
        # Heroku does not accurately give self.request.protocol
        if self.request.host[0:9] == "localhost":
            protocol = "http"
        else:
            protocol = "https"

        redirect_uri = url_concat(
            protocol + "://" + self.request.host + "/oauth",
            {"redirect_uri": self.get_argument('redirect_uri', '/')})

        # if we have a code, we have been authorized so we can log in
        if self.get_argument("code", False):
            user = yield self.get_authenticated_user(
                redirect_uri=redirect_uri,
                client_id=settings["github_client_id"],
                client_secret=settings["github_client_secret"],
                code=self.get_argument("code"))

            # if the user is valid
            if user:
                self.set_secure_cookie("user", json_encode(user))
                # idempotent operation to make sure GitHub user is in our
                # database
                register_github_user(json_encode(user))
                # generate a Brainspell API key
                hasher = hashlib.sha1()
                hasher.update(str(user["id"]).encode('utf-8'))
                api_key = hasher.hexdigest()
                self.set_secure_cookie("api_key", api_key)
            else:
                self.clear_cookie("user")
            self.redirect(self.get_argument("redirect_uri", "/"))
            return

        # otherwise we need to request an authorization code
        yield self.authorize_redirect(redirect_uri=redirect_uri,
                                      client_id=settings["github_client_id"],
                                      extra_params={"scope": "repo"})
Ejemplo n.º 11
0
    def get(self):
        starttime = time.time()
        log.info(starttime)

        data = yield get_my_stars(self.get_auth_http_client(),
                                  self.current_user['access_token'])

        endtime = time.time()
        log.info(endtime)
        log.info(endtime - starttime)

        self.write(json_encode(data))
        self.finish()
Ejemplo n.º 12
0
    def get(self):
        starttime = time.time()
        log.info(starttime)

        data = yield get_my_starts(self.get_auth_http_client(),
                                   self.current_user['access_token'])

        endtime = time.time()
        log.info(endtime)
        log.info(endtime - starttime)

        self.write(json_encode(data))
        self.finish()
Ejemplo n.º 13
0
def add_coordinate_row(pmid, exp, coords, row_number=-1):
    """ Add a coordinate row to the end of a table.

    Take a list of three or four coordinates.
    Take a row number. -1 will add to the end of the list. """

    target = next(get_article_object(pmid))
    experiments = eval(target.experiments)
    elem = experiments[int(exp)]
    row_list = ",".join([str(c) for c in coords])
    if row_number == -1:
        elem["locations"].append(row_list)
    else:
        elem["locations"].insert(row_number, row_list)
    Articles.update(experiments=json_encode(experiments)).where(
        Articles.pmid == pmid).execute()
Ejemplo n.º 14
0
 def post_status_code(self, url, body, status_code):
     ''' make an authenticated POST request and return json if the status codes match '''
     cookie_name, cookie_value = 'user', {'login': '******'}
     secure_cookie = create_signed_value(COOKIE_SECRET, cookie_name,
                                         json_encode(cookie_value))
     headers = {
         'Content-type': 'application/x-www-form-urlencoded',
         'Cookie': '='.join((cookie_name, secure_cookie.decode()))
     }
     res = self.fetch(url,
                      method='POST',
                      body=json.dumps(body),
                      headers=headers)
     assert res.code == status_code, "status {} != {} for url: {}\nparams: {}".format(
         res.code, status_code, url, body)
     return res.body
Ejemplo n.º 15
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
Ejemplo n.º 16
0
    async def prepare(self):

        user_json = self.get_secure_cookie("user")

        if user_json:
            self.current_user = json_decode(user_json).get('login')

        elif 'Authorization' in self.request.headers:
            if self.request.headers['Authorization'].startswith('Bearer '):
                token = self.request.headers['Authorization'].split(' ', 1)[1]
                http_client = AsyncHTTPClient()
                try:
                    response = await http_client.fetch(
                        "https://api.github.com/user", request_timeout=3,
                        headers={'Authorization': 'token ' + token})
                    user = json.loads(response.body)
                except Exception as e:
                    logging.warning(e)
                else:
                    if 'login' in user:
                        logging.info('logged in user from github token: %s', user)
                        self.set_secure_cookie("user", json_encode(user))
                        self.current_user = user['login']
Ejemplo n.º 17
0
    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)
Ejemplo n.º 18
0
 def return_json(self, data):
     _json_data = json_encode(data)
     self.set_header("Content-Type", "application/json; charset=UTF-8")
     self.write(_json_data)
Ejemplo n.º 19
0
        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)