diff --git a/qiita_db/study.py b/qiita_db/study.py index 367b846a1..3c4989f3b 100644 --- a/qiita_db/study.py +++ b/qiita_db/study.py @@ -1175,17 +1175,37 @@ def has_access(self, user, no_public=False): Whether user has access to study or not """ with qdb.sql_connection.TRN: - # if admin or superuser, just return true + # return True if the user is one of the admins if user.level in {'superuser', 'admin'}: return True - if no_public: - study_set = user.user_studies | user.shared_studies - else: - study_set = user.user_studies | user.shared_studies | \ - self.get_by_status('public') + # if no_public is False then just check if the study is public + # and return True + if not no_public and self.status == 'public': + return True + + # let's check if the study belongs to this user or has been + # shared with them + sql = """SELECT EXISTS ( + SELECT study_id + FROM qiita.study + JOIN qiita.study_portal USING (study_id) + JOIN qiita.portal_type USING (portal_type_id) + WHERE email = %s AND portal = %s AND study_id = %s + UNION + SELECT study_id + FROM qiita.study_users + JOIN qiita.study_portal USING (study_id) + JOIN qiita.portal_type USING (portal_type_id) + WHERE email = %s AND portal = %s AND study_id = %s + ) + """ + qdb.sql_connection.TRN.add( + sql, [user.email, qiita_config.portal, self.id, + user.email, qiita_config.portal, self.id]) + result = qdb.sql_connection.TRN.execute_fetchlast() - return self in study_set + return result def can_edit(self, user): """Returns whether the given user can edit the study diff --git a/qiita_pet/handlers/api_proxy/studies.py b/qiita_pet/handlers/api_proxy/studies.py index 431583c57..547c7621f 100644 --- a/qiita_pet/handlers/api_proxy/studies.py +++ b/qiita_pet/handlers/api_proxy/studies.py @@ -11,6 +11,8 @@ from qiita_core.exceptions import IncompetentQiitaDeveloperError from qiita_core.util import execute_as_transaction from qiita_core.qiita_settings import r_client +from qiita_db.artifact import Artifact +from qiita_db.sql_connection import TRN from qiita_db.user import User from qiita_db.study import Study from qiita_db.exceptions import QiitaDBColumnError, QiitaDBLookupError @@ -114,8 +116,8 @@ def study_get_req(study_id, user_id): study_info['has_access_to_raw_data'] = study.has_access( User(user_id), True) or study.public_raw_download - study_info['show_biom_download_button'] = 'BIOM' in [ - a.artifact_type for a in study.artifacts()] + study_info['show_biom_download_button'] = len( + study.artifacts(artifact_type='BIOM')) != 0 study_info['show_raw_download_button'] = any([ True for pt in study.prep_templates() if pt.artifact is not None]) @@ -201,53 +203,71 @@ def study_prep_get_req(study_id, user_id): access_error = check_access(study_id, user_id) if access_error: return access_error - # Can only pass ids over API, so need to instantiate object + study = Study(int(study_id)) - prep_info = defaultdict(list) + prep_info = {dtype: [] for dtype in study.data_types} editable = study.can_edit(User(user_id)) - for dtype in study.data_types: - dtype_infos = list() - for prep in study.prep_templates(dtype): - if prep.status != 'public' and not editable: + with TRN: + sql = """SELECT prep_template_id, pt.name as name, data_type, + artifact_id, + creation_timestamp, modification_timestamp, visibility, + (SELECT COUNT(sample_id) + FROM qiita.prep_template_sample + WHERE prep_template_id = spt.prep_template_id) + as total_samples, + (SELECT COUNT(sample_id) + FROM qiita.prep_template_sample + WHERE prep_template_id = spt.prep_template_id + AND ebi_experiment_accession != '') + as ebi_experiment + FROM qiita.study_prep_template spt + LEFT JOIN qiita.prep_template pt USING (prep_template_id) + LEFT JOIN qiita.data_type USING (data_type_id) + LEFT JOIN qiita.artifact USING (artifact_id) + LEFT JOIN qiita.visibility USING (visibility_id) + WHERE study_id = %s + GROUP BY prep_template_id, pt.name, data_type, artifact_id, + creation_timestamp, modification_timestamp, + visibility + ORDER BY creation_timestamp""" + + TRN.add(sql, [study_id]) + for row in TRN.execute_fetchindex(): + row = dict(row) + if row['visibility'] != 'public' and not editable: continue - start_artifact = prep.artifact + # for those preps that have no artifact + if row['visibility'] is None: + row['visibility'] = 'sandbox' + info = { - 'name': prep.name, - 'id': prep.id, - 'status': prep.status, - 'total_samples': len(prep), - 'creation_timestamp': prep.creation_timestamp, - 'modification_timestamp': prep.modification_timestamp + 'name': row['name'], + 'id': row['prep_template_id'], + 'status': row['visibility'], + 'total_samples': row['total_samples'], + 'creation_timestamp': row['creation_timestamp'], + 'modification_timestamp': row['modification_timestamp'], + 'start_artifact': None, + 'start_artifact_id': None, + 'youngest_artifact': None, + 'num_artifact_children': 0, + 'youngest_artifact_name': None, + 'youngest_artifact_type': None, + 'ebi_experiment': row['ebi_experiment'] } - if start_artifact is not None: - youngest_artifact = prep.artifact.youngest_artifact + if row['artifact_id'] is not None: + start_artifact = Artifact(row['artifact_id']) + youngest_artifact = start_artifact.youngest_artifact info['start_artifact'] = start_artifact.artifact_type - info['start_artifact_id'] = start_artifact.id + info['start_artifact_id'] = row['artifact_id'] info['num_artifact_children'] = len(start_artifact.children) info['youngest_artifact_name'] = youngest_artifact.name info['youngest_artifact_type'] = \ youngest_artifact.artifact_type info['youngest_artifact'] = '%s - %s' % ( youngest_artifact.name, youngest_artifact.artifact_type) - info['ebi_experiment'] = len( - [v for _, v in prep.ebi_experiment_accessions.items() - if v is not None]) - else: - info['start_artifact'] = None - info['start_artifact_id'] = None - info['youngest_artifact'] = None - info['num_artifact_children'] = 0 - info['youngest_artifact_name'] = None - info['youngest_artifact_type'] = None - info['ebi_experiment'] = 0 - - dtype_infos.append(info) - - # default sort is in ascending order of creation timestamp - sorted_info = sorted(dtype_infos, - key=lambda k: k['creation_timestamp'], - reverse=False) - prep_info[dtype] = sorted_info + + prep_info[row['data_type']].append(info) return {'status': 'success', 'message': '', diff --git a/qiita_pet/handlers/api_proxy/tests/test_studies.py b/qiita_pet/handlers/api_proxy/tests/test_studies.py index ec938099f..4c574ecfd 100644 --- a/qiita_pet/handlers/api_proxy/tests/test_studies.py +++ b/qiita_pet/handlers/api_proxy/tests/test_studies.py @@ -229,8 +229,7 @@ def test_study_prep_get_req_failed_EBI(self): # actual test obs = study_prep_get_req(study.id, user_email) - temp_info = defaultdict(list) - temp_info['16S'] = [ + temp_info = {'16S': [ {"status": 'sandbox', 'name': 'Prep information %d' % pt.id, 'start_artifact': None, 'youngest_artifact': None, @@ -241,7 +240,7 @@ def test_study_prep_get_req_failed_EBI(self): 'num_artifact_children': 0, 'youngest_artifact_name': None, 'youngest_artifact_type': None, - 'total_samples': 3}] + 'total_samples': 3}]} exp = { 'info': temp_info,