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
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 })
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
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
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()
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"})
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()
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()
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()
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
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
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']
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 return_json(self, data): _json_data = json_encode(data) self.set_header("Content-Type", "application/json; charset=UTF-8") self.write(_json_data)
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)