def authenticate(auth_code, orcid_id): user_data = mongo.get_user(orcid_id) if 'figshare_token' not in user_data and auth_code is not None: params = { 'client_id': config.get('DEFAULT', 'FIGSHARE_CLIENT_ID'), 'client_secret': config.get('DEFAULT', 'FIGSHARE_SECRET'), 'grant_type': 'authorization_code', 'code': auth_code } data = urllib.parse.urlencode(params) data = data.encode('ascii') req = urllib.request.Request(config.get('DEFAULT', 'FIGSHARE_TOKEN_URL'), data=data, headers={'Accept': 'application/json'}) req.get_method = lambda: "POST" response = urllib.request.urlopen(req).read() figshare_token = json.loads(response) user_data['figshare_token'] = figshare_token mongo.update_user(orcid_id, user_data) elif 'figshare_token' in user_data: figshare_token = user_data['figshare_token'] else: figshare_token = None return figshare_token['access_token']
def get_works(user_token, orcid_id): api = orcid.PublicAPI(config.get("DEFAULT", "ORCID_CLIENT_ID"), config.get("DEFAULT", "ORCID_SECRET")) summary = api.read_record_public(orcid_id, "works", user_token) metadata = [] for work in summary["group"]: work_summary = work["work-summary"][0] work_metadata = dict() work_metadata["id"] = work_summary["put-code"] work_metadata["title"] = work_summary["title"]["title"]["value"] work_metadata["last-modified-date"] = work_summary[ "last-modified-date"]["value"] work_metadata["type"] = work_summary["type"] work_metadata["publication-year"] = work_summary["publication-date"][ "year"]["value"] work_metadata["owner"] = orcid_id for ext_id in work_summary["external-ids"]["external-id"]: if ext_id["external-id-type"] == "doi": work_metadata["doi"] = ext_id["external-id-value"] if ext_id["external-id-type"] == "pmid": work_metadata["pmid"] = ext_id["external-id-value"] if ext_id["external-id-type"] == "pmc": work_metadata["pmcid"] = ext_id["external-id-value"] metadata.append(work_metadata) return metadata
def harvest_file(user, research_object): tmp_dir = config.get("DEFAULT", "TMP_DIR") file_name = research_object["source"] + "_" + research_object["name"] logger.info(f"Harvesting files for research object: ${file_name}") if research_object["source"] == "github": downloads_url = research_object["ro"]["archive_url"] downloads_url = downloads_url.replace("{archive_format}", "zipball") downloads_url = downloads_url.replace("{/ref}", "/master") logger.info( f"Downloading Github zip files for research object: ${file_name}") ro_content = github.download_zip_file( downloads_url, user["github_token"]["access_token"]) file_name += ".zip" with open(tmp_dir + file_name, "wb") as f: f.write(ro_content) elif research_object["source"] == "figshare": file_name += ".zip" logger.info( f"Downloading Figshare files for research object: ${file_name}") figshare.download_files( research_object["ro"], user["figshare_token"]["access_token"], tmp_dir + file_name, ) else: logger.info( f"Generating Orcid JSON file for research object: ${file_name}") ro_content = str(research_object["ro"]).encode("utf-8") file_name += ".json" with open(tmp_dir + file_name, "wb") as f: f.write(ro_content) return file_name
def authenticate(auth_code, orcid_id): user_data = mongo.get_user(orcid_id) if 'github_token' not in user_data: params = {'client_id': config.get('DEFAULT', 'GITHUB_CLIENT_ID'), 'client_secret': config.get('DEFAULT', 'GITHUB_SECRET'), 'code': auth_code } data = urllib.parse.urlencode(params) data = data.encode('ascii') req = urllib.request.Request('https://github.com/login/oauth/access_token', data, headers={'Accept': 'application/json'}) response = urllib.request.urlopen(req).read() github_token = json.loads(response) user_data['github_token'] = github_token mongo.update_user(orcid_id, user_data) else: github_token = user_data['github_token'] return github_token['access_token']
def research_object_exist(source, research_object): composer_url = config.get("DEFAULT", "HYPERLEDGER_COMPOSER_URL") research_object_url = (research_object[SOURCE_URL_FIELD_MAP[source]] if SOURCE_URL_FIELD_MAP[source] in research_object else research_object["id"]) req = requests.get(f"{composer_url}/ResearchOJ/{research_object_url}") if req.status_code == 404: return False return True
def create_researcher(user): composer_url = config.get("DEFAULT", "HYPERLEDGER_COMPOSER_URL") researcher = { "$class": "org.bforos.Researcher", "researcherId": f"{user['orcid']}", "firstName": user["first_name"], "lastName": user["last_name"], "email": f"{user['orcid']}@b4os.com", } req = requests.post(f"{composer_url}/api/Researcher", researcher) return True
def claim_research_object(orcid_id, source, research_object): composer_url = config.get("DEFAULT", "HYPERLEDGER_COMPOSER_URL") research_object_url = (research_object[SOURCE_URL_FIELD_MAP[source]] if SOURCE_URL_FIELD_MAP[source] in research_object else research_object["id"]) claim_op = { "$class": "org.bforos.ClaimRO", "researchObjId": f"resource:org.bforos.ResearchOJ#{research_object_url}", "claimer": f"resource:org.bforos.Researcher#{orcid_id}", } req = requests.post(f"{composer_url}/api/CreateResearchOJ", claim_op) return True
def update_disco(orcid_id, disco_id, disco_name, research_object_urls): composer_url = config.get("DEFAULT", "HYPERLEDGER_COMPOSER_URL") bforos_ros = [ f"resource:org.bforos.ResearchOJ#{url}" for url in research_object_urls ] create_disco_op = { "$class": "org.bforos.Disco", "discoId": disco_id, "title": disco_name, "researchObjs": bforos_ros, "owner": f"org.bforos.Researcher#{orcid_id}", } req = requests.put(f"{composer_url}/api/Disco", create_disco_op) return True
def create_reaserch_object(orcid_id, source, research_object): ro_type = SOURCE_TYPE_MAP[source] if source in SOURCE_TYPE_MAP else "OTHER" research_object_url = (research_object[SOURCE_URL_FIELD_MAP[source]] if SOURCE_URL_FIELD_MAP[source] in research_object else research_object["id"]) composer_url = config.get("DEFAULT", "HYPERLEDGER_COMPOSER_URL") create_op = { "$class": "org.bforos.CreateResearchOJ", "typeRO": ro_type, "uri": research_object_url, "creator": f"org.bforos.Researcher#{orcid_id}", "researchObjId": research_object_url, } req = requests.post(f"{composer_url}/api/CreateResearchOJ", create_op) return True
def create_disco(orcid_id, disco_id, disco_name, research_object_urls): composer_url = config.get("DEFAULT", "HYPERLEDGER_COMPOSER_URL") bforos_ros = [ f"resource:org.bforos.ResearchOJ#{url}" for url in research_object_urls ] create_disco_op = { "$class": "org.bforos.Disco", "discoId": disco_id, "title": disco_name, "researchObjs": bforos_ros, "owner": f"org.bforos.Researcher#{orcid_id}", "collectors": [f"org.bforos.Researcher#{orcid_id}"], } logger.info(create_disco_op) headers = {"Content-Type": "application/json"} req = requests.post(f"{composer_url}/api/Disco", json.dumps(create_disco_op), headers=headers) logger.info(req.text) return True
from scholarly_wallet import config from scholarly_wallet import mongo_access as mongo, github_api as github from scholarly_wallet import figshare_api as figshare from scholarly_wallet import zenodo_api as zenodo from flask_jwt_extended import ( JWTManager, jwt_required, create_access_token, get_jwt_identity, ) from scholarly_wallet import hyperledger_api as hyperledger from threading import Thread app = Flask(__name__) app.config["JWT_SECRET_KEY"] = config.get("DEFAULT", "JWT_SECRET") app.config["JWT_ACCESS_TOKEN_EXPIRES"] = int(config.get("DEFAULT", "JWT_EXPIRES")) jwt = JWTManager(app) DEFAULT_SORT = {"orcid": "title", "github": "full_name", "figshare": "title"} @app.route("/api/auth/orcid", methods=["GET", "OPTIONS"]) def signin(): auth_code = request.args.get("orcid_auth_code") user_data = orcid.authenticate(auth_code) if user_data is None: return jsonify({"msg": "Failed authetication with Orcid"}), 403 access_token = create_access_token(identity=user_data) return jsonify(access_token=access_token), 200
def publish_to_zenodo(author, disco): turtle = get_rmap_rdf(author, disco) zenodo_url = config.get("DEFAULT", "ZENODO_REPOSITIONS_URL") zenodo_token = config.get("DEFAULT", "ZENODO_ACCESS_TOKEN") headers = {"Content-Type": "application/json"} r = requests.post(zenodo_url, params={"access_token": zenodo_token}, json={}, headers=headers) r = r.json() deposition_id = r["id"] deposition_doi = r["metadata"]["prereserve_doi"]["doi"] file_name_base = deposition_doi.replace("/", "_") tmp_dir = config.get("DEFAULT", "TMP_DIR") with open(tmp_dir + file_name_base + ".rdf", "w+") as t_file: t_file.write(turtle.decode("utf-8")) turtle_file = open(tmp_dir + deposition_doi.replace("/", "_") + ".rdf", "rb") data = {"filename": deposition_doi + ".rdf"} files = {"file": turtle_file} r = requests.post( f"{zenodo_url}/{deposition_id}/files", params={"access_token": zenodo_token}, data=data, files=files, ) img_data = base64.b64decode(disco["thumb"].split(",")[1]) png_file = f"{file_name_base}.png" with open(tmp_dir + png_file, "wb") as f: f.write(img_data) png_file = open(tmp_dir + png_file, "rb") data = {"filename": deposition_doi.replace("/", "_") + ".png"} files = {"file": png_file} r = requests.post( f"{zenodo_url}/{deposition_id}/files", params={"access_token": zenodo_token}, data=data, files=files, ) for research_object in disco["diagram"]["elements"]["nodes"]: research_object = research_object["data"] file_name = harvest_file(author, research_object) ro_file = open(tmp_dir + file_name, "rb") data = {"filename": file_name} files = {"file": ro_file} logger.info(f"Uploading ${file_name} to Zenodo") r = requests.post( f"{zenodo_url}/{deposition_id}/files", params={"access_token": zenodo_token}, data=data, files=files, ) notes = "" # TODO Design a implement a queue for publication2zenodo data = { "metadata": { "title": disco["name"], "upload_type": "dataset", "publication_type": "milestone", "description": disco["description"] if disco["description"] else disco["name"], "creators": [{ "name": author["name"], "orcid": author["orcid"] }], "keywords": ["disco", "scholarly wallet", "bundle"], "notes": notes, "access_right": "open", "communities": [{ "identifier": "b4ossw" }], } } r = requests.put( f"{zenodo_url}/{deposition_id}", params={"access_token": zenodo_token}, data=json.dumps(data), headers=headers, ) r = requests.post( f"{zenodo_url}/{deposition_id}/actions/publish", params={"access_token": zenodo_token}, ) mongo.update_disco( author["orcid"], disco["_id"], { "doi": deposition_doi, "zenodo_id": deposition_id, "status": "published" }, ) return dumps({"doi": deposition_doi, "zenodo_id": deposition_id})
def authenticate(auth_code): params = { "client_id": config.get("DEFAULT", "ORCID_CLIENT_ID"), "client_secret": config.get("DEFAULT", "ORCID_SECRET"), "grant_type": "authorization_code", "code": auth_code, "redirect_uri": config.get("DEFAULT", "CLIENT_URL"), } data = urllib.parse.urlencode(params) data = data.encode("ascii") req = urllib.request.Request( config.get("DEFAULT", "ORCID_AUTH_URL"), data, headers={"Accept": "application/json"}, ) try: response = urllib.request.urlopen(req).read() user_data: Dict = json.loads(response) orcid_token = { "access_token": user_data.pop("access_token"), "token_type": user_data.pop("token_type"), "refresh_token": user_data.pop("refresh_token"), "expires_in": user_data.pop("expires_in"), "scope": user_data.pop("scope"), } user_data["orcid_token"] = orcid_token if not mongo.user_exists(user_data["orcid"]): req = urllib.request.Request( config.get("DEFAULT", "ORCID_API_URL") + "/" + user_data["orcid"] + "/person", data, headers={ "Accept": "application/json", "Authorization": f'Bearer {orcid_token["access_token"]}', }, ) response = urllib.request.urlopen(req).read() user_profile_data: Dict = json.loads(response) first_name = user_profile_data["name"]["given-names"]["value"] last_name = user_profile_data["name"]["family-name"]["value"] user_data["first_name"] = first_name user_data["last_name"] = last_name mongo.create_user(user_data) thread_user = Thread(target=hyperledger.create_researcher, args=(user_data, )) thread_user.start() user_data.pop("_id") else: mongo.update_user(user_data["orcid"], user_data) works = get_works(user_data["orcid_token"]["access_token"], user_data["orcid"]) for work in works: if not mongo.work_exists(work["id"], user_data["orcid"]): mongo.save_ros([work], "orcid") thread_works = Thread(target=hyperledger.claim_ros, args=(user_data["orcid"], "orcid", works)) thread_works.start() for field_name in user_data.keys(): if field_name.endswith("_token"): user_data[field_name.replace("_token", "_access")] = True user_data.pop(field_name) return user_data except urllib.error.HTTPError as e: return None