Skip to content

Commit 11a1c28

Browse files
committed
add suffix check in flow, update tests (#2064)
1 parent 630e4dd commit 11a1c28

File tree

4 files changed

+121
-18
lines changed

4 files changed

+121
-18
lines changed

landingzones/tests/test_views_taskflow.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from django.urls import reverse
1313

1414
# Projectroles dependency
15+
from projectroles.app_settings import AppSettingAPI
1516
from projectroles.models import SODAR_CONSTANTS
1617
from projectroles.plugins import get_backend_api
1718

@@ -43,6 +44,7 @@
4344
from landingzones.views import ZONE_MOVE_INVALID_STATUS
4445

4546

47+
app_settings = AppSettingAPI()
4648
User = auth.get_user_model()
4749

4850

@@ -55,6 +57,7 @@
5557
PROJECT_TYPE_PROJECT = SODAR_CONSTANTS['PROJECT_TYPE_PROJECT']
5658

5759
# Local constants
60+
APP_NAME = 'landingzones'
5861
SHEET_PATH = SHEET_DIR + 'i_small.zip'
5962
ZONE_TITLE = '20190703_172456'
6063
ZONE_SUFFIX = 'Test Zone'
@@ -675,6 +678,41 @@ def test_validate_md5_file_only(self):
675678
self.assertEqual(len(self.zone_coll.data_objects), 1)
676679
self.assertEqual(len(self.assay_coll.data_objects), 0)
677680

681+
def test_validate_prohibit(self):
682+
"""Test validating zone with prohibited file name suffix"""
683+
app_settings.set(
684+
APP_NAME, 'file_name_prohibit', 'txt', project=self.project
685+
)
686+
irods_obj = self.make_irods_object(self.zone_coll, TEST_OBJ_NAME)
687+
self.make_irods_md5_object(irods_obj)
688+
zone = LandingZone.objects.first()
689+
self.assertEqual(zone.status, ZONE_STATUS_ACTIVE)
690+
self.assertEqual(len(self.zone_coll.data_objects), 2)
691+
self.assertEqual(len(self.assay_coll.data_objects), 0)
692+
self.assertEqual(len(mail.outbox), 1)
693+
self.assertEqual(
694+
AppAlert.objects.filter(alert_name='zone_validate').count(), 0
695+
)
696+
697+
with self.login(self.user):
698+
response = self.client.post(self.url_validate)
699+
self.assertRedirects(response, self.url_redirect)
700+
701+
self.assert_zone_status(zone, ZONE_STATUS_FAILED)
702+
self.assertEqual(len(self.zone_coll.data_objects), 2)
703+
self.assertEqual(len(self.assay_coll.data_objects), 0)
704+
self.assertEqual(len(mail.outbox), 1)
705+
tl_event = TimelineEvent.objects.filter(
706+
event_name='zone_validate'
707+
).first()
708+
self.assertIsInstance(tl_event, TimelineEvent)
709+
self.assertEqual(
710+
tl_event.get_status().status_type, self.timeline.TL_STATUS_FAILED
711+
)
712+
self.assertEqual(
713+
AppAlert.objects.filter(alert_name='zone_move').count(), 0
714+
)
715+
678716
def test_move_invalid_status(self):
679717
"""Test validating and moving with invalid zone status (should fail)"""
680718
irods_obj = self.make_irods_object(self.zone_coll, TEST_OBJ_NAME)

landingzones/views.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from django.views.generic import TemplateView, CreateView, UpdateView
1313

1414
# Projectroles dependency
15+
from projectroles.app_settings import AppSettingAPI
1516
from projectroles.plugins import get_backend_api
1617
from projectroles.views import (
1718
LoggedInPermissionMixin,
@@ -38,6 +39,7 @@
3839
from landingzones.models import LandingZone
3940

4041

42+
app_settings = AppSettingAPI()
4143
logger = logging.getLogger(__name__)
4244
User = auth.get_user_model()
4345

@@ -386,9 +388,14 @@ def _submit_validate_move(self, zone, validate_only, request=None):
386388
tl_event.set_status(timeline.TL_STATUS_SUBMIT)
387389

388390
flow_data = self.get_flow_data(
389-
zone,
390-
'landing_zone_move',
391-
{'zone_uuid': str(zone.sodar_uuid)},
391+
zone=zone,
392+
flow_name='landing_zone_move',
393+
data={
394+
'zone_uuid': str(zone.sodar_uuid),
395+
'file_name_prohibit': app_settings.get(
396+
APP_NAME, 'file_name_prohibit', project=project
397+
),
398+
},
392399
)
393400
if validate_only:
394401
flow_data['validate_only'] = True

taskflowbackend/flows/landing_zone_move.py

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616

1717

1818
SAMPLE_COLL = settings.IRODS_SAMPLE_COLL
19-
ZONE_INFO_CALC = 'Calculating missing checksums in iRODS'
19+
ZONE_INFO_CHECK = 'Checking availability and file types of {count} file{plural}'
20+
ZONE_INFO_CALC = 'Computing missing checksums in iRODS'
2021
ZONE_INFO_VALIDATE = 'Validating {count} file{plural}'
2122
ZONE_INFO_READ_ONLY = ', write access disabled'
2223

@@ -39,6 +40,9 @@ def build(self, force_fail=False):
3940
sample_path = self.irods_backend.get_path(zone.assay)
4041
zone_path = self.irods_backend.get_path(zone)
4142
admin_name = self.irods.username
43+
file_name_prohibit = None
44+
if self.flow_data.get('file_name_prohibit'):
45+
file_name_prohibit = self.flow_data['file_name_prohibit'].split(',')
4246

4347
# HACK: Set zone status in the Django site
4448
zone.set_status(
@@ -151,6 +155,46 @@ def build(self, force_fail=False):
151155
)
152156
)
153157

158+
self.add_task(
159+
lz_tasks.SetLandingZoneStatusTask(
160+
name='Set landing zone status to VALIDATING (check)',
161+
project=self.project,
162+
inject={
163+
'landing_zone': zone,
164+
'status': ZONE_STATUS_VALIDATING,
165+
'status_info': ZONE_INFO_CHECK.format(
166+
count=file_count, plural=file_count_msg_plural
167+
)
168+
+ (ZONE_INFO_READ_ONLY if not validate_only else ''),
169+
'flow_name': self.flow_name,
170+
},
171+
)
172+
)
173+
if file_name_prohibit:
174+
self.add_task(
175+
irods_tasks.BatchCheckFileSuffixTask(
176+
name='Batch check file types for zone data objects',
177+
irods=self.irods,
178+
inject={
179+
'file_paths': zone_objects_nomd5,
180+
'suffixes': file_name_prohibit,
181+
'zone_path': zone_path,
182+
},
183+
)
184+
)
185+
self.add_task(
186+
irods_tasks.BatchCheckFileExistTask(
187+
name='Batch check file and MD5 checksum file existence for '
188+
'zone data objects',
189+
irods=self.irods,
190+
inject={
191+
'file_paths': zone_objects_nomd5,
192+
'md5_paths': zone_objects_md5,
193+
'zone_path': zone_path,
194+
},
195+
)
196+
)
197+
154198
self.add_task(
155199
lz_tasks.SetLandingZoneStatusTask(
156200
name='Set landing zone status to VALIDATING (calculate)',
@@ -190,19 +234,6 @@ def build(self, force_fail=False):
190234
},
191235
)
192236
)
193-
194-
self.add_task(
195-
irods_tasks.BatchCheckFileExistTask(
196-
name='Batch check file and MD5 checksum file existence for '
197-
'zone data objects',
198-
irods=self.irods,
199-
inject={
200-
'file_paths': zone_objects_nomd5,
201-
'md5_paths': zone_objects_md5,
202-
'zone_path': zone_path,
203-
},
204-
)
205-
)
206237
self.add_task(
207238
irods_tasks.BatchValidateChecksumsTask(
208239
name='Batch validate MD5 checksums of {} data objects'.format(

taskflowbackend/tests/test_flows.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
COLL_NAME = 'test_coll'
8181
SUB_COLL_NAME = 'sub'
8282
OBJ_COLL_NAME = 'obj'
83-
OBJ_NAME = 'test_file'
83+
OBJ_NAME = 'test_file.txt'
8484
SHEET_PATH = SHEET_DIR + 'i_small.zip'
8585
UPDATED_TITLE = 'NewTitle'
8686
UPDATED_DESC = 'updated description'
@@ -1085,6 +1085,33 @@ def test_validate_no_checksum(self):
10851085
self.assertIsNotNone(obj.replicas[0].checksum)
10861086
self.assertEqual(obj.replicas[0].checksum, self.get_md5_checksum(obj))
10871087

1088+
def test_validate_prohibit(self):
1089+
"""Test landing_zone_move validation with prohibited file name"""
1090+
coll_path = os.path.join(self.zone_path, COLL_NAME)
1091+
zone_coll = self.irods.collections.create(coll_path)
1092+
obj = self.make_irods_object(zone_coll, OBJ_NAME)
1093+
obj_path = obj.path
1094+
self.make_irods_md5_object(obj)
1095+
self.assertEqual(self.irods.data_objects.exists(obj_path), True)
1096+
self.assertEqual(
1097+
self.irods.data_objects.exists(obj_path + '.md5'), True
1098+
)
1099+
flow_data = {
1100+
'zone_uuid': str(self.zone.sodar_uuid),
1101+
'validate_only': True,
1102+
'file_name_prohibit': 'txt',
1103+
}
1104+
flow = self.taskflow.get_flow(
1105+
irods_backend=self.irods_backend,
1106+
project=self.project,
1107+
flow_name='landing_zone_move',
1108+
flow_data=flow_data,
1109+
)
1110+
with self.assertRaisesRegex(Exception, OBJ_NAME):
1111+
self.build_and_run(flow)
1112+
self.zone.refresh_from_db()
1113+
self.assertEqual(self.zone.status, ZONE_STATUS_FAILED)
1114+
10881115
def test_revert(self):
10891116
"""Test reverting landing_zone_move"""
10901117
coll_path = os.path.join(self.zone_path, COLL_NAME)

0 commit comments

Comments
 (0)