Skip to content
Snippets Groups Projects
Commit 9cb7caad authored by Jorrit Schaap's avatar Jorrit Schaap
Browse files

TMSS-1144: made dataproducts and referenced model(parts) immutable when a subtask is finished

parent b102eeca
No related branches found
No related tags found
1 merge request!635Resolve TMSS-1144
# Generated by Django 3.0.9 on 2021-10-07 09:17
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('tmssapp', '0010_subtaskinputoutput'),
]
operations = [
migrations.RunSQL('''CREATE OR REPLACE FUNCTION tmssapp_block_dataproduct_immutable_fields_update()
RETURNS trigger AS
$BODY$
DECLARE
dp_producing_subtask_state tmssapp_subtaskstate.value%type;
BEGIN
SELECT tmssapp_subtask.state_id FROM tmssapp_dataproduct INTO dp_producing_subtask_state
INNER JOIN tmssapp_subtaskoutput on tmssapp_subtaskoutput.id=tmssapp_dataproduct.producer_id
INNER JOIN tmssapp_subtask on tmssapp_subtask.id=tmssapp_subtaskoutput.subtask_id
WHERE tmssapp_dataproduct.id=OLD.id
LIMIT 1;
IF dp_producing_subtask_state = 'finished' THEN
IF OLD.filename <> NEW.filename OR
OLD.directory <> NEW.directory OR
OLD.size <> NEW.size OR
OLD.dataformat_id <> NEW.dataformat_id OR
OLD.datatype_id <> NEW.datatype_id OR
OLD.specifications_doc <> NEW.specifications_doc OR
OLD.specifications_template_id <> NEW.specifications_template_id OR
OLD.feedback_doc <> NEW.feedback_doc OR
OLD.feedback_template_id <> NEW.feedback_template_id OR
OLD.sap_id <> NEW.sap_id OR
OLD.global_identifier_id <> NEW.global_identifier_id OR
OLD.producer_id <> NEW.producer_id THEN
RAISE EXCEPTION 'ILLEGAL UPDATE OF IMMUTABLE DATAPRODUCT FIELD';
END IF;
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
DROP TRIGGER IF EXISTS tmssapp_block_dataproduct_immutable_fields_update ON tmssapp_dataproduct ;
CREATE TRIGGER tmssapp_block_dataproduct_immutable_fields_update
BEFORE UPDATE ON tmssapp_dataproduct
FOR EACH ROW EXECUTE PROCEDURE tmssapp_block_dataproduct_immutable_fields_update();
'''),
migrations.RunSQL('''CREATE OR REPLACE FUNCTION tmssapp_block_dataproducthash_immutable_fields_update()
RETURNS trigger AS
$BODY$
DECLARE
dp_producing_subtask_state tmssapp_subtaskstate.value%type;
BEGIN
SELECT tmssapp_subtask.state_id FROM tmssapp_dataproducthash INTO dp_producing_subtask_state
INNER JOIN tmssapp_dataproduct on tmssapp_dataproduct.id=tmssapp_dataproducthash.dataproduct_id
INNER JOIN tmssapp_subtaskoutput on tmssapp_subtaskoutput.id=tmssapp_dataproduct.producer_id
INNER JOIN tmssapp_subtask on tmssapp_subtask.id=tmssapp_subtaskoutput.subtask_id
WHERE tmssapp_dataproducthash.id=OLD.id
LIMIT 1;
IF dp_producing_subtask_state = 'finished' THEN
IF OLD.hash <> NEW.hash OR
OLD.hash_algorithm_id <> NEW.hash_algorithm_id OR
OLD.dataproduct_id <> NEW.dataproduct_id THEN
RAISE EXCEPTION 'ILLEGAL UPDATE OF IMMUTABLE DATAPRODUCTHASH FIELD';
END IF;
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
DROP TRIGGER IF EXISTS tmssapp_block_dataproducthash_immutable_fields_update ON tmssapp_dataproducthash ;
CREATE TRIGGER tmssapp_block_dataproducthash_immutable_fields_update
BEFORE UPDATE ON tmssapp_dataproducthash
FOR EACH ROW EXECUTE PROCEDURE tmssapp_block_dataproducthash_immutable_fields_update();
'''),
migrations.RunSQL('''CREATE OR REPLACE FUNCTION tmssapp_block_dataproductarchiveinfo_immutable_fields_update()
RETURNS trigger AS
$BODY$
DECLARE
dp_producing_subtask_state tmssapp_subtaskstate.value%type;
BEGIN
SELECT tmssapp_subtask.state_id FROM tmssapp_dataproductarchiveinfo INTO dp_producing_subtask_state
INNER JOIN tmssapp_dataproduct on tmssapp_dataproduct.id=tmssapp_dataproductarchiveinfo.dataproduct_id
INNER JOIN tmssapp_subtaskoutput on tmssapp_subtaskoutput.id=tmssapp_dataproduct.producer_id
INNER JOIN tmssapp_subtask on tmssapp_subtask.id=tmssapp_subtaskoutput.subtask_id
WHERE tmssapp_dataproductarchiveinfo.id=OLD.id
LIMIT 1;
IF dp_producing_subtask_state = 'finished' THEN
IF OLD.storage_ticket <> NEW.storage_ticket OR
OLD.dataproduct_id <> NEW.dataproduct_id THEN
RAISE EXCEPTION 'ILLEGAL UPDATE OF IMMUTABLE DATAPRODUCTARCHIVEINFO FIELD';
END IF;
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
DROP TRIGGER IF EXISTS tmssapp_block_dataproductarchiveinfo_immutable_fields_update ON tmssapp_dataproductarchiveinfo ;
CREATE TRIGGER tmssapp_block_dataproductarchiveinfo_immutable_fields_update
BEFORE UPDATE ON tmssapp_dataproductarchiveinfo
FOR EACH ROW EXECUTE PROCEDURE tmssapp_block_dataproductarchiveinfo_immutable_fields_update();
'''),
migrations.RunSQL('''CREATE OR REPLACE FUNCTION tmssapp_block_sap_immutable_fields_update()
RETURNS trigger AS
$BODY$
DECLARE
dp_producing_subtask_state tmssapp_subtaskstate.value%type;
BEGIN
SELECT tmssapp_subtask.state_id FROM tmssapp_sap INTO dp_producing_subtask_state
INNER JOIN tmssapp_dataproduct on tmssapp_dataproduct.sap_id=tmssapp_sap.id
INNER JOIN tmssapp_subtaskoutput on tmssapp_subtaskoutput.id=tmssapp_dataproduct.producer_id
INNER JOIN tmssapp_subtask on tmssapp_subtask.id=tmssapp_subtaskoutput.subtask_id
WHERE tmssapp_sap.id=OLD.id
LIMIT 1;
IF dp_producing_subtask_state = 'finished' THEN
IF OLD.specifications_doc <> NEW.specifications_doc OR
OLD.specifications_template_id <> NEW.specifications_template_id OR
OLD.global_identifier_id <> NEW.global_identifier_id THEN
RAISE EXCEPTION 'ILLEGAL UPDATE OF IMMUTABLE SAP FIELD';
END IF;
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
DROP TRIGGER IF EXISTS tmssapp_block_sap_immutable_fields_update ON tmssapp_sap ;
CREATE TRIGGER tmssapp_block_sap_immutable_fields_update
BEFORE UPDATE ON tmssapp_sap
FOR EACH ROW EXECUTE PROCEDURE tmssapp_block_sap_immutable_fields_update();
''')
]
...@@ -443,6 +443,7 @@ class SAP(BasicCommon, TemplateSchemaMixin): ...@@ -443,6 +443,7 @@ class SAP(BasicCommon, TemplateSchemaMixin):
specifications_doc = JSONField(help_text='SAP properties.') specifications_doc = JSONField(help_text='SAP properties.')
specifications_template = ForeignKey('SAPTemplate', null=False, on_delete=CASCADE, help_text='Schema used for specifications_doc.') specifications_template = ForeignKey('SAPTemplate', null=False, on_delete=CASCADE, help_text='Schema used for specifications_doc.')
global_identifier = OneToOneField('SIPidentifier', null=False, editable=False, on_delete=PROTECT, help_text='The global unique identifier for LTA SIP.') global_identifier = OneToOneField('SIPidentifier', null=False, editable=False, on_delete=PROTECT, help_text='The global unique identifier for LTA SIP.')
# please note that the all fields become immutable when its dataproduct's producing subtask is finished (See SQL triggers)
def save(self, force_insert=False, force_update=False, using=None, update_fields=None): def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
self.annotate_validate_add_defaults_to_doc_using_template('specifications_doc', 'specifications_template') self.annotate_validate_add_defaults_to_doc_using_template('specifications_doc', 'specifications_template')
...@@ -472,6 +473,7 @@ class Dataproduct(TemplateSchemaMixin, RefreshFromDbInvalidatesCachedPropertiesM ...@@ -472,6 +473,7 @@ class Dataproduct(TemplateSchemaMixin, RefreshFromDbInvalidatesCachedPropertiesM
feedback_template = ForeignKey('DataproductFeedbackTemplate', on_delete=PROTECT, help_text='Schema used for feedback_doc.') feedback_template = ForeignKey('DataproductFeedbackTemplate', on_delete=PROTECT, help_text='Schema used for feedback_doc.')
sap = ForeignKey('SAP', on_delete=PROTECT, null=True, related_name="dataproducts", help_text='SAP this dataproduct was generated out of (NULLable).') sap = ForeignKey('SAP', on_delete=PROTECT, null=True, related_name="dataproducts", help_text='SAP this dataproduct was generated out of (NULLable).')
global_identifier = OneToOneField('SIPidentifier', editable=False, null=False, on_delete=PROTECT, help_text='The global unique identifier for LTA SIP.') global_identifier = OneToOneField('SIPidentifier', editable=False, null=False, on_delete=PROTECT, help_text='The global unique identifier for LTA SIP.')
# please note that the all fields except deleted_since and expected_size become immutable when its dataproduct's producing subtask is finished (See SQL triggers)
class Meta(BasicCommon.Meta): class Meta(BasicCommon.Meta):
constraints = [UniqueConstraint(fields=['directory', 'filename'], name='%(class)s_unique_path')] constraints = [UniqueConstraint(fields=['directory', 'filename'], name='%(class)s_unique_path')]
...@@ -525,10 +527,12 @@ class DataproductArchiveInfo(BasicCommon): ...@@ -525,10 +527,12 @@ class DataproductArchiveInfo(BasicCommon):
storage_ticket = CharField(max_length=128, help_text='Archive-system identifier.') storage_ticket = CharField(max_length=128, help_text='Archive-system identifier.')
public_since = DateTimeField(null=True, help_text='Dataproduct is available for public download since this moment, or NULL if dataproduct is not (NULLable).') public_since = DateTimeField(null=True, help_text='Dataproduct is available for public download since this moment, or NULL if dataproduct is not (NULLable).')
corrupted_since = DateTimeField(null=True, help_text='Earliest timestamp from which this dataproduct is known to be partially or fully corrupt, or NULL if dataproduct is not known to be corrupt (NULLable).') corrupted_since = DateTimeField(null=True, help_text='Earliest timestamp from which this dataproduct is known to be partially or fully corrupt, or NULL if dataproduct is not known to be corrupt (NULLable).')
# please note that the dataproduct, storage_ticket fields become immutable when its dataproduct's producing subtask is finished (See SQL triggers)
class DataproductHash(BasicCommon): class DataproductHash(BasicCommon):
dataproduct = ForeignKey('Dataproduct', related_name='hashes', on_delete=PROTECT, help_text='The dataproduct to which this hash refers.') dataproduct = ForeignKey('Dataproduct', related_name='hashes', on_delete=PROTECT, help_text='The dataproduct to which this hash refers.')
hash_algorithm = ForeignKey('HashAlgorithm', null=False, on_delete=PROTECT, help_text='Algorithm used for hashing (MD5, AES256).') hash_algorithm = ForeignKey('HashAlgorithm', null=False, on_delete=PROTECT, help_text='Algorithm used for hashing (MD5, AES256).')
hash = CharField(max_length=128, help_text='Hash value.') hash = CharField(max_length=128, help_text='Hash value.')
# please note that the dataproduct, hash_algorithm, hash fields become immutable when its dataproduct's producing subtask is finished (See SQL triggers)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment