diff --git a/qiita_db/artifact.py b/qiita_db/artifact.py
index 8d14ea595..9bc553a53 100644
--- a/qiita_db/artifact.py
+++ b/qiita_db/artifact.py
@@ -571,6 +571,10 @@ def delete(cls, artifact_id):
sql = "DELETE FROM qiita.study_artifact WHERE artifact_id = %s"
qdb.sql_connection.TRN.add(sql, [artifact_id])
+ # Detach the artifact from the analysis_artifact table
+ sql = "DELETE FROM qiita.analysis_artifact WHERE artifact_id = %s"
+ qdb.sql_connection.TRN.add(sql, [artifact_id])
+
# Delete the row in the artifact table
sql = "DELETE FROM qiita.artifact WHERE artifact_id = %s"
qdb.sql_connection.TRN.add(sql, [artifact_id])
diff --git a/qiita_db/test/test_artifact.py b/qiita_db/test/test_artifact.py
index a9173440e..89b13c661 100644
--- a/qiita_db/test/test_artifact.py
+++ b/qiita_db/test/test_artifact.py
@@ -919,6 +919,21 @@ def test_delete(self):
with self.assertRaises(qdb.exceptions.QiitaDBUnknownIDError):
qdb.artifact.Artifact(test.id)
+ # Analysis artifact
+ parameters = qdb.software.Parameters.from_default_params(
+ qdb.software.DefaultParameters(1), {'input_data': 1})
+ test = qdb.artifact.Artifact.create(
+ self.filepaths_processed, "Demultiplexed",
+ parents=[qdb.artifact.Artifact(9)],
+ processing_parameters=parameters)
+
+ self._clean_up_files.extend(
+ [join(uploads_fp, basename(fp)) for _, fp, _ in test.filepaths])
+ qdb.artifact.Artifact.delete(test.id)
+
+ with self.assertRaises(qdb.exceptions.QiitaDBUnknownIDError):
+ qdb.artifact.Artifact(test.id)
+
def test_delete_with_html(self):
fd, html_fp = mkstemp(suffix=".html")
close(fd)
diff --git a/qiita_pet/handlers/analysis_handlers/base_handlers.py b/qiita_pet/handlers/analysis_handlers/base_handlers.py
index cc23847eb..52c00a852 100644
--- a/qiita_pet/handlers/analysis_handlers/base_handlers.py
+++ b/qiita_pet/handlers/analysis_handlers/base_handlers.py
@@ -6,7 +6,10 @@
# The full license is in the file LICENSE, distributed with this software.
# -----------------------------------------------------------------------------
+from json import loads
+
from tornado.web import authenticated
+from moi import r_client
from qiita_core.util import execute_as_transaction
from qiita_core.qiita_settings import qiita_config
@@ -29,16 +32,49 @@ def post(self):
% (qiita_config.portal_dir, analysis.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:
+ 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', '')
+
+ return {'analysis_name': analysis.name,
+ 'analysis_id': analysis.id,
+ 'analysis_description': analysis.description,
+ 'alert_type': alert_type,
+ 'alert_msg': alert_msg}
+
+
class AnalysisDescriptionHandler(BaseHandler):
@authenticated
@execute_as_transaction
def get(self, analysis_id):
- analysis = Analysis(analysis_id)
- check_analysis_access(self.current_user, analysis)
+ res = analysis_description_handler_get_request(analysis_id,
+ self.current_user)
- self.render("analysis_description.html", analysis_name=analysis.name,
- analysis_id=analysis_id,
- analysis_description=analysis.description)
+ self.render("analysis_description.html", **res)
def analyisis_graph_handler_get_request(analysis_id, user):
diff --git a/qiita_pet/handlers/analysis_handlers/tests/test_base_handlers.py b/qiita_pet/handlers/analysis_handlers/tests/test_base_handlers.py
index 9203f79dd..81810a045 100644
--- a/qiita_pet/handlers/analysis_handlers/tests/test_base_handlers.py
+++ b/qiita_pet/handlers/analysis_handlers/tests/test_base_handlers.py
@@ -7,20 +7,56 @@
# -----------------------------------------------------------------------------
from unittest import TestCase, main
-from json import loads
+from json import loads, dumps
from tornado.web import HTTPError
+from moi import r_client
from qiita_core.util import qiita_test_checker
from qiita_db.user import User
from qiita_db.analysis import Analysis
from qiita_pet.test.tornado_test_base import TestHandlerBase
from qiita_pet.handlers.analysis_handlers.base_handlers import (
- analyisis_graph_handler_get_request)
+ analyisis_graph_handler_get_request,
+ analysis_description_handler_get_request)
@qiita_test_checker()
class TestBaseHandlersUtils(TestCase):
+ def tearDown(self):
+ r_client.flushdb()
+
+ def test_analysis_description_handler_get_request(self):
+ obs = analysis_description_handler_get_request(1, User('test@foo.bar'))
+ exp = {'analysis_name': 'SomeAnalysis',
+ 'analysis_id': 1,
+ 'analysis_description': 'A test analysis',
+ 'alert_type': 'info',
+ 'alert_msg': ''}
+ self.assertEqual(obs, exp)
+
+ r_client.set('analysis_1', dumps({'job_id': 'job_id'}))
+ r_client.set('job_id', dumps({'status_msg': 'running'}))
+ obs = analysis_description_handler_get_request(1, User('test@foo.bar'))
+ exp = {'analysis_name': 'SomeAnalysis',
+ 'analysis_id': 1,
+ 'analysis_description': 'A test analysis',
+ 'alert_type': 'info',
+ 'alert_msg': 'An artifact is being deleted from this analysis'}
+ self.assertEqual(obs, exp)
+
+ r_client.set('job_id', dumps(
+ {'status_msg': 'Success',
+ 'return': {'status': 'danger',
+ 'message': 'Error deleting artifact'}}))
+ obs = analysis_description_handler_get_request(1, User('test@foo.bar'))
+ exp = {'analysis_name': 'SomeAnalysis',
+ 'analysis_id': 1,
+ 'analysis_description': 'A test analysis',
+ 'alert_type': 'danger',
+ 'alert_msg': 'Error deleting artifact'}
+ self.assertEqual(obs, exp)
+
def test_analyisis_graph_handler_get_request(self):
obs = analyisis_graph_handler_get_request(1, User('test@foo.bar'))
# The job id is randomly generated in the test environment. Gather
diff --git a/qiita_pet/handlers/artifact_handlers/base_handlers.py b/qiita_pet/handlers/artifact_handlers/base_handlers.py
index b93e75f89..3ba92e0ab 100644
--- a/qiita_pet/handlers/artifact_handlers/base_handlers.py
+++ b/qiita_pet/handlers/artifact_handlers/base_handlers.py
@@ -7,16 +7,24 @@
# -----------------------------------------------------------------------------
from os.path import basename
+from json import dumps
from tornado.web import authenticated
+from moi import r_client
from qiita_core.qiita_settings import qiita_config
from qiita_pet.handlers.base_handlers import BaseHandler
from qiita_pet.handlers.util import safe_execution
from qiita_pet.exceptions import QiitaHTTPError
+from qiita_ware.context import safe_submit
+from qiita_ware.dispatchable import delete_artifact
from qiita_db.artifact import Artifact
from qiita_db.software import Command, Parameters
from qiita_db.processing_job import ProcessingJob
+from qiita_db.util import get_visibilities
+
+
+PREP_TEMPLATE_KEY_FORMAT = 'prep_template_%s'
def check_artifact_access(user, artifact):
@@ -131,7 +139,7 @@ def artifact_summary_get_request(user, artifact_id):
# If the artifact is part of an analysis, we don't require admin
# approval, and the artifact can be made public only if all the
# artifacts used to create the initial artifact set are public
- if analysis.can_be_publicized:
+ if analysis.can_be_publicized and visibility != 'public':
buttons.append(btn_base % ('make public', 'public', 'Make public'))
else:
@@ -145,13 +153,12 @@ def artifact_summary_get_request(user, artifact_id):
buttons.append(
btn_base % ('request approval for', 'awaiting_approval',
'Request approval'))
-
- elif user.level == 'admin' and visibility == 'awaiting_approval':
- # The approve artifact button only appears if the user is an admin
- # the artifact is waiting to be approvaed and the qiita config
- # requires artifact approval
- buttons.append(btn_base % ('approve', 'private',
- 'Approve artifact'))
+ elif user.level == 'admin' and visibility == 'awaiting_approval':
+ # The approve artifact button only appears if the user is an
+ # admin the artifact is waiting to be approvaed and the qiita
+ # config requires artifact approval
+ buttons.append(btn_base % ('approve', 'private',
+ 'Approve artifact'))
if visibility == 'private':
# The make public button only appears if the artifact is private
@@ -206,8 +213,7 @@ def artifact_summary_get_request(user, artifact_id):
'processing_jobs': processing_jobs,
'summary': summary,
'job': job_info,
- 'errored_jobs': errored_jobs
- }
+ 'errored_jobs': errored_jobs}
def artifact_summary_post_request(user, artifact_id):
@@ -311,6 +317,23 @@ def artifact_patch_request(user, artifact_id, req_op, req_path, req_value=None,
if attribute == 'name':
artifact.name = req_value
return
+ elif attribute == 'visibility':
+ if req_value not in get_visibilities():
+ raise QiitaHTTPError(400, 'Unknown visibility value: %s'
+ % req_value)
+ # Set the approval to private if needs approval and admin
+ if req_value == 'private':
+ if not qiita_config.require_approval:
+ artifact.visibility = 'private'
+ # Set the approval to private if approval not required
+ elif user.level == 'admin':
+ artifact.visibility = 'private'
+ # Trying to set approval without admin privileges
+ else:
+ raise QiitaHTTPError(403, 'User does not have permissions '
+ 'to approve change')
+ else:
+ artifact.visibility = req_value
else:
# We don't understand the attribute so return an error
raise QiitaHTTPError(404, 'Attribute "%s" not found. Please, '
@@ -320,7 +343,40 @@ def artifact_patch_request(user, artifact_id, req_op, req_path, req_value=None,
'supported operations: replace' % req_op)
+def artifact_post_req(user, artifact_id):
+ """Deletes the artifact
+
+ Parameters
+ ----------
+ user : qiita_db.user.User
+ The user requesting the action
+ artifact_id : int
+ Id of the artifact being deleted
+ """
+ artifact_id = int(artifact_id)
+ artifact = Artifact(artifact_id)
+ check_artifact_access(user, artifact)
+
+ analysis = artifact.analysis
+
+ if analysis:
+ # Do something when deleting in the analysis part to keep track of it
+ redis_key = "analysis_%s" % analysis.id
+ else:
+ pt_id = artifact.prep_templates[0].id
+ redis_key = PREP_TEMPLATE_KEY_FORMAT % pt_id
+
+ job_id = safe_submit(user.id, delete_artifact, artifact_id)
+ r_client.set(redis_key, dumps({'job_id': job_id, 'is_qiita_job': False}))
+
+
class ArtifactAJAX(BaseHandler):
+ @authenticated
+ def post(self, artifact_id):
+ with safe_execution():
+ artifact_post_req(self.current_user, artifact_id)
+ self.finish()
+
@authenticated
def patch(self, artifact_id):
"""Patches a prep template in the system
diff --git a/qiita_pet/handlers/artifact_handlers/tests/test_base_handlers.py b/qiita_pet/handlers/artifact_handlers/tests/test_base_handlers.py
index 7c5473d35..41d181502 100644
--- a/qiita_pet/handlers/artifact_handlers/tests/test_base_handlers.py
+++ b/qiita_pet/handlers/artifact_handlers/tests/test_base_handlers.py
@@ -252,9 +252,10 @@ def test_artifact_summary_post_request(self):
def test_artifact_patch_request(self):
a = Artifact(1)
+ test_user = User('test@foo.bar')
self.assertEqual(a.name, 'Raw data 1')
- artifact_patch_request(User('test@foo.bar'), 1, 'replace', '/name/',
+ artifact_patch_request(test_user, 1, 'replace', '/name/',
req_value='NEW_NAME')
self.assertEqual(a.name, 'NEW_NAME')
@@ -268,24 +269,44 @@ def test_artifact_patch_request(self):
# Incorrect path parameter
with self.assertRaises(QiitaHTTPError):
- artifact_patch_request(User('test@foo.bar'), 1, 'replace',
+ artifact_patch_request(test_user, 1, 'replace',
'/name/wrong/', req_value='NEW_NAME')
# Missing value
with self.assertRaises(QiitaHTTPError):
- artifact_patch_request(User('test@foo.bar'), 1, 'replace',
- '/name/')
+ artifact_patch_request(test_user, 1, 'replace', '/name/')
# Wrong attribute
with self.assertRaises(QiitaHTTPError):
- artifact_patch_request(User('test@foo.bar'), 1, 'replace',
+ artifact_patch_request(test_user, 1, 'replace',
'/wrong/', req_value='NEW_NAME')
# Wrong operation
with self.assertRaises(QiitaHTTPError):
- artifact_patch_request(User('test@foo.bar'), 1, 'add', '/name/',
+ artifact_patch_request(test_user, 1, 'add', '/name/',
req_value='NEW_NAME')
+ # Changing visibility
+ self.assertEqual(a.visibility, 'private')
+ artifact_patch_request(test_user, 1, 'replace', '/visibility/',
+ req_value='sandbox')
+ self.assertEqual(a.visibility, 'sandbox')
+
+ # Admin can change to private
+ artifact_patch_request(User('admin@foo.bar'), 1, 'replace',
+ '/visibility/', req_value='private')
+ self.assertEqual(a.visibility, 'private')
+
+ # Test user can't change to private
+ with self.assertRaises(QiitaHTTPError):
+ artifact_patch_request(test_user, 1, 'replace', '/visibility/',
+ req_value='private')
+
+ # Unkown req value
+ with self.assertRaises(QiitaHTTPError):
+ artifact_patch_request(test_user, 1, 'replace', '/visibility/',
+ req_value='wrong')
+
class TestBaseHandlers(TestHandlerBase):
def test_get_artifact_summary_ajax_handler(self):
diff --git a/qiita_pet/templates/analysis_description.html b/qiita_pet/templates/analysis_description.html
index ff2e628c0..df1d4949b 100644
--- a/qiita_pet/templates/analysis_description.html
+++ b/qiita_pet/templates/analysis_description.html
@@ -2,6 +2,29 @@
{% block head %}