def get_invitation(invitation_id=None): try: current_user = helpers.get_current_user() invitation = dt.users.get_invitation(current_user, invitation_id) if request.method == 'DELETE': return jsonify(dt.users.delete_invitation(current_user, invitation)) else: return jsonify(invitation.to_dict()) except Exception as e: handle_exception(e)
def upload_external_file(): try: user = get_current_user() # for request from MATLAB client that doesn't support multipart/form-data # file is base64 encoded. new_data = {} try: new_data.update(process_input_dict(request.get_json())) except: new_data.update(process_input_dict(request.form)) if 'file' not in new_data and 'file' not in request.files: raise ValueError('No file uploaded') filename = os.path.join(UPLOADDIR, secure_filename(str(uuid.uuid4()))) if 'file' in request.files: if request.files['file'].filename == '': raise ValueError('No file uploaded') request.files['file'].save(filename) else: with open(filename, 'wb') as file: collection_file_data = base64.b64decode( bytes(new_data['file'], 'utf-8')) file.write(collection_file_data) del new_data['file'] external_file = dt.external_files.upload_external_file( user, filename, new_data) return jsonify(external_file.to_dict()) except Exception as e: return handle_exception(e)
def submit_job(): try: user = get_current_user() body = request.get_json(force=True) return jsonify(dt.jobserver_control.start_job(body['workflow'], body['job'], user, 'analysis').to_dict()) except Exception as e: return handle_exception(e)
def get_sample_group(sample_group_id=None): try: user = get_current_user() sample_group = dt.sample_groups.get_sample_group(user, sample_group_id) if request.method == 'GET': return jsonify({ **sample_group.to_dict(), 'is_write_permitted': dt.users.is_write_permitted(user, sample_group) }) if request.method == 'DELETE': samples_to_delete = [ sample for sample in sample_group.samples if len(sample.sample_groups) < 2 ] data = dt.sample_groups.delete_sample_group(user, sample_group) sample_messages = [] for sample in samples_to_delete: try: sample_messages.append( dt.samples.delete_sample(user, sample)['message']) except AuthException: pass messages = [data['message']] + sample_messages return jsonify({'messages': messages}) if request.method == 'POST': return jsonify( dt.sample_groups.update_sample_group( user, sample_group, request.get_json(force=True)).to_dict()) except Exception as e: return handle_exception(e)
def download_temporary_file(): path = request.args.get('path') if path is None: return handle_exception(ValueError('No path specified!')) if not os.path.isfile(path): print(path) return handle_exception(ValueError('File does not exist!')) # make sure browser does not serve up cached version. response = make_response( send_from_directory(os.path.dirname(path), os.path.basename(path), as_attachment=True)) response.headers[ "Cache-Control"] = "no-cache, no-store, must-revalidate, public, max-age=0" response.headers["Expires"] = 0 response.headers["Pragma"] = "no-cache" return response
def list_users(): try: user = get_current_user() if request.method == 'POST': data = request.get_json(force=True) return jsonify(dt.users.create_user(user, data).to_dict()) return jsonify([target_user.to_dict() for target_user in dt.users.get_users(user)]) except Exception as e: return handle_exception(e)
def list_invitations(): try: current_user = helpers.get_current_user() return jsonify([ invitation.to_dict() for invitation in dt.users.get_invitations(current_user) ]) except Exception as e: return handle_exception(e)
def list_user_groups(): try: user = get_current_user() if request.method == 'GET': return jsonify([user_group.to_dict() for user_group in dt.user_groups.get_user_groups(user)]) if request.method == 'POST': data = request.get_json(force=True) return jsonify(dt.user_groups.create_user_group(user, data).to_dict()) except Exception as e: return handle_exception(e)
def get_user(user_id=None): try: current_user = get_current_user() target_user = dt.users.get_user(current_user, user_id) if request.method == 'GET': return jsonify( {**target_user.to_dict(), 'is_write_permitted': dt.users.is_write_permitted(current_user, target_user)}) if request.method == 'POST': return jsonify(dt.users.update_user(current_user, target_user, request.get_json(force=True)).to_dict()) if request.method == 'DELETE': return jsonify(dt.users.delete_user(current_user, target_user)) except Exception as e: return handle_exception(e)
def download_external_file(external_file_id=None): try: current_user = get_current_user() external_file = dt.external_files.get_external_file( current_user, external_file_id) out = dt.external_files.download_external_file(current_user, external_file) directory = os.path.dirname(external_file.filename) return send_from_directory(directory, out['filename'], as_attachment=True) except Exception as e: return handle_exception(e)
def get_job(job_id=None): try: user = get_current_user() job = dt.jobserver_control.get_job(job_id) if request.method == 'POST': action = request.args.get('action') if action: if action == 'resume': return jsonify(dt.jobserver_control.resume_job(user, job)) if action == 'cancel': return jsonify(dt.jobserver_control.cancel_job(user, job)) return jsonify(job.to_dict()) except Exception as e: return handle_exception(e)
def get_analysis(analysis_id=None): try: user = get_current_user() if request.method == 'GET': analysis = dt.analyses.get_analysis(user, analysis_id) return jsonify(analysis.to_dict()) if request.method == 'POST': analysis = dt.analyses.get_analysis(user, analysis_id) return jsonify(dt.analyses.update_analysis(user, analysis, request.get_json(force=True)).to_dict()) if request.method == 'DELETE': analysis = dt.analyses.get_analysis(user, analysis_id) return jsonify(dt.analyses.delete_analysis(user, analysis)) except Exception as e: return handle_exception(e)
def finalize_job(): try: user = helpers.get_current_user() body = request.get_json(force=True) token = body['wf_token'] path = f'{TMPDIR}/{token}' info = json.load(open(f'{path}/wfdata.json', 'r')) if dt.jobserver_control.check_jobserver_token(token) and ( user.admin or info['owner'] == user.id): shutil.rmtree(f'{TMPDIR}/{token}', ignore_errors=True) return jsonify({'message': f'Removed {path}'}) except Exception as e: print(e) return handle_exception(e)
def list_analyses(): try: user = get_current_user() if request.method == 'POST': new_data = request.get_json(force=True) if 'collection_ids' in new_data: collections = [dt.collections.get_collection(user, collection_id) for collection_id in new_data['collection_ids']] else: collections = None analysis = dt.analyses.create_analysis(user, new_data, collections) return jsonify(analysis.to_dict()) return jsonify([analysis.to_dict() for analysis in dt.analyses.get_analyses(user)]) except Exception as e: return handle_exception(e)
def download_sample(sample_id=None): try: user = get_current_user() sample = dt.samples.get_sample(user, sample_id) if request.args.get('path', ''): path = request.args.get('path', '') out = dt.samples.download_sample_dataset(user, sample, path) response = make_response(out['csv']) response.headers['Content-Disposition'] = out['cd'] response.mimetype = 'text/csv' return response directory, filename = os.path.split(sample.filename) return send_from_directory(directory, filename, as_attachment=True) except Exception as e: return handle_exception(e)
def get_common_attributes(): try: user = get_current_user() data = request.get_json(force=True) samples = [ dt.samples.get_sample(user, sample_id) for sample_id in data['sample_ids'] ] common_keys = [ item for item in samples[0].get_file_metadata().keys() if all([item in sample.get_file_metadata() for sample in samples]) ] return jsonify(common_keys) except Exception as e: return handle_exception(e)
def get_external_file(external_file_id=None): try: current_user = get_current_user() external_file = dt.external_files.get_external_file( current_user, external_file_id) if request.method == 'GET': return jsonify({ **external_file.to_dict(), 'is_write_permitted': dt.users.is_write_permitted(current_user, external_file) }) if request.content_type == 'application/json': new_data = process_input_dict(request.get_json(force=True)) else: new_data = process_input_dict(request.form.to_dict()) if request.method == 'POST': move_file = 'filename' in new_data and 'move_file' in new_data and new_data[ 'move_file'] if 'file' in request.files or 'file' in new_data: filename = os.path.join(UPLOADDIR, secure_filename(str(uuid.uuid4()))) if 'file' in request.files: if request.files['file'].filename == '': raise ValueError('No file uploaded') request.files['file'].save(filename) else: with open(filename, 'wb') as file: external_file_data = base64.b64decode( bytes(new_data['file'], 'utf-8')) file.write(external_file_data) del new_data['file'] return jsonify( dt.external_files.update_external_file( current_user, external_file, new_data, move_file, filename).to_dict()) return jsonify( dt.external_files.update_external_file(current_user, external_file, new_data, move_file).to_dict()) if request.method == 'DELETE': return jsonify( dt.external_files.delete_external_file(current_user, external_file)) except Exception as e: return handle_exception(e)
def create_invitation(): # We use 'GET' even though we're creating a record # we probably shouldn't ? try: current_user = helpers.get_current_user() primary_user_group_id = request.args.get('primary_user_group_id') try: primary_user_group = dt.user_groups.get_user_group( current_user, primary_user_group_id ) if primary_user_group_id is not None else None except dt.util.NotFoundException: primary_user_group = None pass return jsonify( dt.users.create_invitation(current_user, primary_user_group).to_dict()) except Exception as e: return handle_exception(e)
def attach_collection(analysis_id=None): try: user = get_current_user() analysis = dt.analyses.get_analysis(user, analysis_id) data = request.get_json() if 'collection_ids' in data: collections = [dt.collections.get_collection(user, collection_id) for collection_id in data['collection_ids']] for collection in collections: if request.method == 'POST': dt.analyses.attach_collection(user, analysis, collection) if request.method == 'DELETE': dt.analyses.detach_collection(user, analysis, collection) return jsonify({**analysis.to_dict(), 'is_write_permitted': dt.users.is_write_permitted(user, analysis)}) else: raise ValueError('No collection id(s) specified') except Exception as e: return handle_exception(e)
def attach_sample(sample_group_id=None): try: user = get_current_user() sample_group = dt.sample_groups.get_sample_group(user, sample_group_id) data = request.get_json(force=True) print(data) samples = [ dt.samples.get_sample(user, sample_id) for sample_id in data['sample_ids'] ] if request.method == 'POST': for sample in samples: dt.sample_groups.attach_sample(user, sample, sample_group) return jsonify(sample_group.to_dict()) elif request.method == 'DELETE': for sample in samples: dt.sample_groups.detach_sample(user, sample, sample_group) return jsonify(sample_group.to_dict()) except Exception as e: return handle_exception(e)
def list_external_files(): try: current_user = get_current_user() if request.method == 'GET': return jsonify([ external_file.to_dict() for external_file in dt.external_files.get_external_files(current_user) ]) if request.method == 'POST': # this will only create a record. the "upload" route should be used to both create the record and upload data = request.get_json(force=True) if not os.path.isfile( data['filename']) and not request.files.get('file'): Path(data['filename']).touch( ) # should be reachable, trust API users more than browser users to know this return jsonify( dt.external_files.create_external_file( current_user, request.get_json(force=True)).to_dict()) except Exception as e: return handle_exception(e)
def register_user(): try: data = request.get_json(force=True) if 'invitation' not in data: raise ValueError('No invitation code provided.') if request.method == 'POST': change_password = not (data['password1'] == '' and data['password2'] == '') valid_passwords = data['password1'] == data[ 'password2'] if change_password else False if not valid_passwords: raise ValueError('Passwords do not match.') new_user = dt.users.register_user( data['invitation'], { 'email': data['email'], 'password': data['password1'], 'name': data['name'] }) return jsonify(new_user.to_dict()) except Exception as e: return handle_exception(e)
def list_sample_groups(): try: current_user = get_current_user() if request.method == 'POST': new_data = process_input_dict(request.get_json(force=True)) if 'sample_ids' in new_data: new_data['samples'] = [ dt.samples.get_sample(current_user, sample_id) for sample_id in new_data['sample_ids'] ] del new_data['sample_ids'] return jsonify( dt.sample_groups.create_sample_group(current_user, new_data).to_dict()) return jsonify([ sample_group.to_dict() for sample_group in dt.sample_groups.get_sample_groups(get_current_user()) ]) except Exception as e: return handle_exception(e)
def get_user_group(user_group_id=None): try: user = get_current_user() user_group = dt.user_groups.get_user_group(user, user_group_id) if request.method == 'GET': return jsonify( {**user_group.to_dict(), 'is_write_permitted': dt.users.is_write_permitted(user, user_group)}) if request.method == 'POST': new_data = request.get_json(force=True) if 'member_ids' in new_data: users = [dt.users.get_user(user, user_id) for user_id in new_data['member_ids']] dt.user_groups.update_user_attachments(user, user_group, users) if 'admin_ids' in new_data: admin_users = [dt.users.get_user(user, user_id) for user_id in new_data['admin_ids']] dt.user_groups.update_admins(user, user_group, admin_users) for admin_user in admin_users: dt.user_groups.elevate_user(user, admin_user, user_group) return jsonify( dt.user_groups.update_user_group(user, user_group, new_data).to_dict()) if request.method == 'DELETE': return jsonify(dt.user_groups.delete_user_group(user, user_group)) except Exception as e: return handle_exception(e)
def list_samples(): try: user = get_current_user() if request.method == 'POST': filename = os.path.join(UPLOADDIR, secure_filename(str(uuid.uuid4()))) data = request.get_json(force=True) if 'file' in request.files: request.files['file'].save(filename) else: file_contents = data['file'] del data['file'] decoded_file_contents = base64.b64decode(file_contents) with open(filename, 'wb') as file: file.write(decoded_file_contents) workflow_data = dt.sample_creation.create_sample_creation_workflow( user, [filename], data) dt.jobserver_control.start_job(workflow_data['workflow_filename'], workflow_data['job'], user) return redirect(url_for('jobs_api.list_jobs')) return jsonify( [sample.to_dict() for sample in dt.samples.get_samples(user)]) except Exception as e: return handle_exception(e)
def list_jobs(): try: return jsonify([job.to_dict() for job in dt.jobserver_control.get_jobs()]) except Exception as e: return handle_exception(e)