def analyisis_job_handler_get_request(analysis_id, user): """Returns the job information of the analysis Parameters ---------- analysis_id: int The analysis id user : qiita_db.user.User The user performing the request Returns ------- dict with the jobs information """ analysis = Analysis(analysis_id) # Check if the user actually has access to the analysis check_analysis_access(user, analysis) return { j.id: { 'status': j.status, 'step': j.step, 'error': j.log.msg if j.log else "" } for j in analysis.jobs }
def analyisis_graph_handler_get_request(analysis_id, user): """Returns the graph information of the analysis Parameters ---------- analysis_id : int The analysis id user : qiita_db.user.User The user performing the request Returns ------- dict with the graph information """ analysis = Analysis(analysis_id) # Check if the user actually has access to the analysis check_analysis_access(user, analysis) # A user has full access to the analysis if it is one of its private # analyses, the analysis has been shared with the user or the user is a # superuser or admin full_access = (analysis in (user.private_analyses | user.shared_analyses) or user.level in {'superuser', 'admin'}) nodes = set() edges = set() # Loop through all the initial artifacts of the analysis for a in analysis.artifacts: g = a.descendants_with_jobs # Loop through all the nodes in artifact descendants graph for n in g.nodes(): # Get if the object is an artifact or a job obj_type = n[0] # Get the actual object obj = n[1] if obj_type == 'job': name = obj.command.name elif not full_access and not obj.visibility == 'public': # The object is an artifact, it is not public and the user # doesn't have full access, so we don't include it in the # graph continue else: name = '%s - %s' % (obj.name, obj.artifact_type) nodes.add((obj_type, obj.id, name)) edges.update({(s[1].id, t[1].id) for s, t in g.edges()}) # Nodes and Edges are sets, but the set object can't be serialized using # JSON. Transforming them to lists so when this is returned to the GUI # over HTTP can be JSONized. return {'edges': list(edges), 'nodes': list(nodes)}
def analyisis_graph_handler_get_request(analysis_id, user): """Returns the graph information of the analysis Parameters ---------- analysis_id : int The analysis id user : qiita_db.user.User The user performing the request Returns ------- dict with the graph information Raises ------ ValueError If there is more than one workflow in a single analysis """ analysis = Analysis(analysis_id) # Check if the user actually has access to the analysis check_analysis_access(user, analysis) # A user has full access to the analysis if it is one of its private # analyses, the analysis has been shared with the user or the user is a # superuser or admin full_access = (analysis in (user.private_analyses | user.shared_analyses) or user.level in {'superuser', 'admin'}) nodes = [] edges = [] wf_id = None # Loop through all the initial artifacts of the analysis for a in analysis.artifacts: if a.processing_parameters is None: g = a.descendants_with_jobs nodes, edges, a_wf_id = get_network_nodes_edges(g, full_access, nodes=nodes, edges=edges) if wf_id is None: wf_id = a_wf_id elif a_wf_id is not None and wf_id != a_wf_id: # This should never happen, but worth having a useful message raise ValueError('More than one workflow in a single analysis') return {'edges': edges, 'nodes': nodes, 'workflow': wf_id}
def post(self): analysis_id = int(self.get_argument('analysis_id')) user = self.current_user check_analysis_access(user, Analysis(analysis_id)) qiita_plugin = Software.from_name_and_version('Qiita', 'alpha') cmd = qiita_plugin.get_command('delete_analysis') params = Parameters.load(cmd, values_dict={'analysis_id': analysis_id}) job = ProcessingJob.create(user, params, True) # Store the job id attaching it to the sample template id r_client.set('analysis_delete_%d' % analysis_id, dumps({'job_id': job.id})) job.submit() self.redirect("%s/analysis/list/" % (qiita_config.portal_dir))
def analysis_description_handler_get_request(analysis_id, user): """Returns the analysis information Parameters ---------- analysis_id : int The analysis id user : qiita_db.user.User The user performing the request """ analysis = Analysis(analysis_id) check_analysis_access(user, analysis) job_info = r_client.get("analysis_%s" % analysis.id) alert_type = 'info' alert_msg = '' if job_info: job_info = loads(job_info) job_id = job_info['job_id'] if job_id: r_payload = r_client.get(job_id) if r_payload: redis_info = loads(r_client.get(job_id)) if redis_info['status_msg'] == 'running': alert_msg = ('An artifact is being deleted from this ' 'analysis') elif redis_info['return'] is not None: alert_type = redis_info['return']['status'] alert_msg = redis_info['return']['message'].replace( '\n', '</br>') artifacts = {} for aid, samples in analysis.samples.items(): artifact = Artifact(aid) study = artifact.study artifacts[aid] = (study.id, study.title, artifact.merging_scheme, samples) return { 'analysis_name': analysis.name, 'analysis_id': analysis.id, 'analysis_is_public': analysis.is_public, 'analysis_description': analysis.description, 'analysis_mapping_id': analysis.mapping_file, 'alert_type': alert_type, 'artifacts': artifacts, 'alert_msg': alert_msg }
def analyisis_graph_handler_get_request(analysis_id, user): """Returns the graph information of the analysis Parameters ---------- analysis_id : int The analysis id user : qiita_db.user.User The user performing the request Returns ------- dict with the graph information Raises ------ ValueError If there is more than one workflow in a single analysis """ analysis = Analysis(analysis_id) # Check if the user actually has access to the analysis check_analysis_access(user, analysis) # A user has full access to the analysis if it is one of its private # analyses, the analysis has been shared with the user or the user is a # superuser or admin full_access = (analysis in (user.private_analyses | user.shared_analyses) or user.level in {'superuser', 'admin'}) nodes = [] edges = [] wf_id = None # Loop through all the initial artifacts of the analysis for a in analysis.artifacts: if a.processing_parameters is None: g = a.descendants_with_jobs nodes, edges, a_wf_id = get_network_nodes_edges( g, full_access, nodes=nodes, edges=edges) if wf_id is None: wf_id = a_wf_id elif a_wf_id is not None and wf_id != a_wf_id: # This should never happen, but worth having a useful message raise ValueError('More than one workflow in a single analysis') return {'edges': edges, 'nodes': nodes, 'workflow': wf_id}
def analysis_description_handler_get_request(analysis_id, user): """Returns the analysis information Parameters ---------- analysis_id : int The analysis id user : qiita_db.user.User The user performing the request """ analysis = Analysis(analysis_id) check_analysis_access(user, analysis) job_info = r_client.get("analysis_%s" % analysis.id) alert_type = 'info' alert_msg = '' if job_info: job_info = loads(job_info) job_id = job_info['job_id'] if job_id: r_payload = r_client.get(job_id) if r_payload: redis_info = loads(r_client.get(job_id)) if redis_info['status_msg'] == 'running': alert_msg = ('An artifact is being deleted from this ' 'analysis') elif redis_info['return'] is not None: alert_type = redis_info['return']['status'] alert_msg = redis_info['return']['message'].replace( '\n', '</br>') artifacts = {} for aid, samples in analysis.samples.items(): artifact = Artifact(aid) study = artifact.study artifacts[aid] = ( study.id, study.title, artifact.merging_scheme, samples) return {'analysis_name': analysis.name, 'analysis_id': analysis.id, 'analysis_is_public': analysis.is_public, 'analysis_description': analysis.description, 'analysis_mapping_id': analysis.mapping_file, 'alert_type': alert_type, 'artifacts': artifacts, 'alert_msg': alert_msg}
def post(self, analysis_id): analysis = Analysis(analysis_id) check_analysis_access(self.current_user, analysis) message = '' try: Analysis(analysis_id).make_public() except Exception as e: message = str(e) res = analysis_description_handler_get_request( analysis_id, self.current_user) if message: # this will display the error message in the main banner res['level'] = 'danger' res['message'] = message self.render("analysis_description.html", **res)
def analyisis_job_handler_get_request(analysis_id, user): """Returns the job information of the analysis Parameters ---------- analysis_id: int The analysis id user : qiita_db.user.User The user performing the request Returns ------- dict with the jobs information """ analysis = Analysis(analysis_id) # Check if the user actually has access to the analysis check_analysis_access(user, analysis) return { j.id: {'status': j.status, 'step': j.step, 'error': j.log.msg if j.log else ""} for j in analysis.jobs}
def analysis_description_handler_get_request(analysis_id, user): """Returns the analysis information Parameters ---------- analysis_id : int The analysis id user : qiita_db.user.User The user performing the request """ analysis = Analysis(analysis_id) check_analysis_access(user, analysis) job_info = r_client.get("analysis_%s" % analysis.id) alert_type = 'info' alert_msg = '' if job_info: job_info = loads(job_info) job_id = job_info['job_id'] if job_id: r_payload = r_client.get(job_id) if r_payload: redis_info = loads(r_client.get(job_id)) if redis_info['status_msg'] == 'running': alert_msg = ('An artifact is being deleted from this ' 'analysis') elif redis_info['return'] is not None: alert_type = redis_info['return']['status'] alert_msg = redis_info['return']['message'].replace( '\n', '</br>') return { 'analysis_name': analysis.name, 'analysis_id': analysis.id, 'analysis_description': analysis.description, 'alert_type': alert_type, 'alert_msg': alert_msg }
def post(self): analysis_id = int(self.get_argument('analysis_id')) analysis = Analysis(analysis_id) analysis_name = analysis.name.decode('utf-8') check_analysis_access(self.current_user, analysis) try: Analysis.delete(analysis_id) msg = ("Analysis <b><i>%s</i></b> has been deleted." % (analysis_name)) level = "success" except Exception as e: e = str(e) msg = ("Couldn't remove <b><i>%s</i></b> analysis: %s" % (analysis_name, e)) level = "danger" LogEntry.create( 'Runtime', "Couldn't remove analysis ID %d: %s" % (analysis_id, e)) self.redirect(u"%s/analysis/list/?level=%s&message=%s" % (qiita_config.portal_dir, level, msg))
def test_check_analysis_access(self): # Has access, so it allows execution u = User('*****@*****.**') a = Analysis(1) check_analysis_access(u, a) # Admin has access to everything u = User('*****@*****.**') check_analysis_access(u, a) # Raises an error because it doesn't have access u = User('*****@*****.**') with self.assertRaises(HTTPError): check_analysis_access(u, a)