diff --git a/ereuse_devicehub/inventory/forms.py b/ereuse_devicehub/inventory/forms.py
index 78c9ebfe..e05e4a04 100644
--- a/ereuse_devicehub/inventory/forms.py
+++ b/ereuse_devicehub/inventory/forms.py
@@ -52,6 +52,7 @@ from ereuse_devicehub.resources.device.models import (
Cellphone,
Computer,
ComputerMonitor,
+ DataStorage,
Desktop,
Device,
Keyboard,
@@ -851,7 +852,13 @@ class NewActionForm(ActionFormMixin):
if not is_valid:
return False
- if self.type.data in ['Allocate', 'Deallocate', 'Trade', 'DataWipe']:
+ if self.type.data in [
+ 'Allocate',
+ 'Deallocate',
+ 'Trade',
+ 'DataWipe',
+ 'EraseDataWipe',
+ ]:
return False
return True
@@ -1067,15 +1074,26 @@ class DataWipeForm(ActionFormMixin):
Model = db.Model._decl_class_registry.data[self.type.data]()
self.instance = Model()
devices = self.devices.data
+ if not self.document.success.data:
+ self.severity.data = Severity.Error.name
severity = self.severity.data
self.devices.data = self._devices
self.severity.data = Severity[self.severity.data]
document = copy.copy(self.document)
del self.document
- self.populate_obj(self.instance)
- self.instance.document = document.form._obj
- db.session.add(self.instance)
+ for dev in self._devices:
+ ac = None
+ for hd in dev.components:
+ if not isinstance(hd, DataStorage):
+ continue
+ ac = Model()
+ self.populate_obj(ac)
+ ac.parent = dev
+ ac.device = hd
+ ac.device_id = hd.id
+ ac.document = document.form._obj
+ db.session.add(ac)
db.session.commit()
self.devices.data = devices
diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py
index 7e5a7999..c00a8cb1 100644
--- a/ereuse_devicehub/inventory/views.py
+++ b/ereuse_devicehub/inventory/views.py
@@ -1176,9 +1176,9 @@ class ExportsView(View):
row = [
ac.device.serial_number.upper(),
ac.device.dhid,
- ac.snapshot.uuid,
+ ac.snapshot.uuid if ac.snapshot else '',
ac.type,
- ac.get_phid(),
+ ac.parent.phid() if ac.parent else '',
ac.severity,
ac.created.strftime('%Y-%m-%d %H:%M:%S'),
]
@@ -1192,11 +1192,12 @@ class ExportsView(View):
if device.placeholder and device.placeholder.binding:
device = device.placeholder.binding
if isinstance(device, Computer):
- for privacy in device.privacy:
- erasures.append(privacy)
+ for ac in device.last_erase_action:
+ erasures.append(ac)
elif isinstance(device, DataStorage):
- if device.privacy:
- erasures.append(device.privacy)
+ ac = device.last_erase_action
+ if ac:
+ erasures.append(ac)
return erasures
def get_costum_details(self, erasures):
@@ -1264,9 +1265,14 @@ class ExportsView(View):
erasures_host, erasures_on_server = a, b
erasures_host = set(erasures_host)
- result = 'Success'
- if "Failed" in [e.severity.get_public_name() for e in erasures]:
- result = 'Failed'
+ result_success = 0
+ result_failed = 0
+ for e in erasures:
+ result = e.severity.get_public_name()
+ if "Failed" == result:
+ result_failed += 1
+ if "Success" == result:
+ result_success += 1
erasures = sorted(erasures, key=lambda x: x.end_time)
erasures_on_server = sorted(erasures_on_server, key=lambda x: x.end_time)
@@ -1283,7 +1289,8 @@ class ExportsView(View):
'software': software,
'my_data': my_data,
'n_computers': n_computers,
- 'result': result,
+ 'result_success': result_success,
+ 'result_failed': result_failed,
'customer_details': customer_details,
'erasure_hosts': erasures_host,
'erasures_normal': erasures_normal,
diff --git a/ereuse_devicehub/migrations/versions/5169765e2653_add_new_erase_data_wipe.py b/ereuse_devicehub/migrations/versions/5169765e2653_add_new_erase_data_wipe.py
new file mode 100644
index 00000000..1621a547
--- /dev/null
+++ b/ereuse_devicehub/migrations/versions/5169765e2653_add_new_erase_data_wipe.py
@@ -0,0 +1,45 @@
+"""add new erase_data_wipe
+
+Revision ID: 5169765e2653
+Revises: 2f2ef041483a
+Create Date: 2023-05-23 10:34:46.312074
+
+"""
+import sqlalchemy as sa
+from alembic import context, op
+from sqlalchemy.dialects import postgresql
+
+# revision identifiers, used by Alembic.
+revision = '5169765e2653'
+down_revision = '2f2ef041483a'
+branch_labels = None
+depends_on = None
+
+
+def get_inv():
+ INV = context.get_x_argument(as_dictionary=True).get('inventory')
+ if not INV:
+ raise ValueError("Inventory value is not specified")
+ return INV
+
+
+def upgrade():
+ op.create_table(
+ 'erase_data_wipe',
+ sa.Column('document_id', sa.BigInteger(), nullable=False),
+ sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
+ sa.ForeignKeyConstraint(
+ ['document_id'],
+ [f'{get_inv()}.document.id'],
+ ),
+ sa.ForeignKeyConstraint(
+ ['id'],
+ [f'{get_inv()}.erase_basic.id'],
+ ),
+ sa.PrimaryKeyConstraint('id'),
+ schema=f'{get_inv()}',
+ )
+
+
+def downgrade():
+ op.drop_table('erase_data_wipe', schema=f'{get_inv()}')
diff --git a/ereuse_devicehub/resources/action/__init__.py b/ereuse_devicehub/resources/action/__init__.py
index 96c966f4..9f83ad1d 100644
--- a/ereuse_devicehub/resources/action/__init__.py
+++ b/ereuse_devicehub/resources/action/__init__.py
@@ -246,6 +246,11 @@ class DataWipeDef(ActionDef):
SCHEMA = schemas.DataWipe
+class EraseDataWipe(ActionDef):
+ VIEW = None
+ SCHEMA = schemas.EraseDataWipe
+
+
class AllocateDef(ActionDef):
VIEW = AllocateView
SCHEMA = schemas.Allocate
diff --git a/ereuse_devicehub/resources/action/models.py b/ereuse_devicehub/resources/action/models.py
index 41a65265..20128497 100644
--- a/ereuse_devicehub/resources/action/models.py
+++ b/ereuse_devicehub/resources/action/models.py
@@ -483,6 +483,8 @@ class EraseBasic(JoinedWithOneDeviceMixin, ActionWithOneDevice):
"""
if self.snapshot:
return self.snapshot.device.phid()
+ if self.parent:
+ return self.parent.phid()
return ''
def get_public_name(self):
@@ -544,6 +546,24 @@ class ErasePhysical(EraseBasic):
return "Physical"
+class EraseDataWipe(EraseBasic):
+ """The device has been selected for insert one proof of erease disk."""
+
+ id = Column(UUID(as_uuid=True), ForeignKey(EraseBasic.id), primary_key=True)
+ document_comment = """The user that gets the device due this deal."""
+ document_id = db.Column(
+ BigInteger, db.ForeignKey('data_wipe_document.id'), nullable=False
+ )
+ document = db.relationship(
+ 'DataWipeDocument',
+ backref=backref('erase_actions', lazy=True, cascade=CASCADE_OWN),
+ primaryjoin='EraseDataWipe.document_id == DataWipeDocument.id',
+ )
+
+ def get_public_name(self):
+ return "EraseDataWipe"
+
+
class Step(db.Model):
erasure_id = Column(
UUID(as_uuid=True),
@@ -1539,6 +1559,7 @@ class ToPrepare(ActionWithMultipleDevices):
class DataWipe(JoinedTableMixin, ActionWithMultipleDevices):
+ # class DataWipe(JoinedWithOneDeviceMixin, ActionWithOneDevice):
"""The device has been selected for insert one proof of erease disk."""
document_comment = """The user that gets the device due this deal."""
diff --git a/ereuse_devicehub/resources/action/schemas.py b/ereuse_devicehub/resources/action/schemas.py
index 6b10ca69..4760edf6 100644
--- a/ereuse_devicehub/resources/action/schemas.py
+++ b/ereuse_devicehub/resources/action/schemas.py
@@ -45,8 +45,8 @@ from ereuse_devicehub.resources.tradedocument import schemas as s_document
from ereuse_devicehub.resources.tradedocument.models import TradeDocument
from ereuse_devicehub.resources.user import schemas as s_user
from ereuse_devicehub.resources.user.models import User
-from ereuse_devicehub.teal.enums import Country, Currency, Subdivision
-from ereuse_devicehub.teal.marshmallow import IP, URL, EnumField, SanitizedStr, Version
+from ereuse_devicehub.teal.enums import Currency
+from ereuse_devicehub.teal.marshmallow import URL, EnumField, SanitizedStr, Version
from ereuse_devicehub.teal.resource import Schema
@@ -588,6 +588,11 @@ class DataWipe(ActionWithMultipleDevicesCheckingOwner):
document = NestedOn(s_generic_document.DataWipeDocument, only_query='id')
+class EraseDataWipe(ActionWithMultipleDevicesCheckingOwner):
+ __doc__ = m.DataWipe.__doc__
+ document = NestedOn(s_generic_document.DataWipeDocument, only_query='id')
+
+
class Live(ActionWithOneDevice):
__doc__ = m.Live.__doc__
"""
@@ -808,12 +813,12 @@ class Trade(ActionWithMultipleDevices):
@pre_load
def adding_devices(self, data: dict):
- if not 'devices' in data.keys():
+ if 'devices' not in data.keys():
data['devices'] = []
@validates_schema
def validate_lot(self, data: dict):
- if not g.user.email in [data['user_from_email'], data['user_to_email']]:
+ if g.user.email not in [data['user_from_email'], data['user_to_email']]:
txt = "you need to be one of the users of involved in the Trade"
raise ValidationError(txt)
@@ -879,7 +884,7 @@ class Trade(ActionWithMultipleDevices):
txt = "you need one user for to do a trade"
raise ValidationError(txt)
- if not g.user.email in [user_from, user_to]:
+ if g.user.email not in [user_from, user_to]:
txt = "you need to be one of participate of the action"
raise ValidationError(txt)
diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py
index 4858706b..23c2166f 100644
--- a/ereuse_devicehub/resources/device/models.py
+++ b/ereuse_devicehub/resources/device/models.py
@@ -1355,6 +1355,22 @@ class Computer(Device):
if privacy
)
+ @property
+ def last_erase_action(self):
+ components = self.components
+ if self.placeholder and self.placeholder.binding:
+ components = self.placeholder.binding.components
+
+ return set(
+ ac
+ for ac in (
+ hdd.last_erase_action
+ for hdd in components
+ if isinstance(hdd, DataStorage)
+ )
+ if ac
+ )
+
@property
def external_document_erasure(self):
"""Returns the external ``DataStorage`` proof of erasure."""
@@ -1568,12 +1584,40 @@ class DataStorage(JoinedComponentTableMixin, Component):
ev = None
return ev
+ @property
+ def last_erase_action(self):
+ erase_auto = None
+ erase_manual = None
+
+ if self.binding:
+ erase_auto = self.privacy
+ erase_manual = self.binding.device.privacy
+ if self.placeholder:
+ erase_manual = self.privacy
+ if self.placeholder.binding:
+ erase_auto = self.placeholder.binding.privacy
+
+ if erase_auto and erase_manual:
+ return (
+ erase_auto
+ if erase_auto.created > erase_manual.created
+ else erase_manual
+ )
+ if erase_manual:
+ return erase_manual
+ if erase_auto:
+ return erase_auto
+ return None
+
def __format__(self, format_spec):
v = super().__format__(format_spec)
if 's' in format_spec:
v += ' – {} GB'.format(self.size // 1000 if self.size else '?')
return v
+ def get_size(self):
+ return '{} GB'.format(self.size // 1000 if self.size else '?')
+
@property
def external_document_erasure(self):
"""Returns the external ``DataStorage`` proof of erasure."""
diff --git a/ereuse_devicehub/templates/inventory/device_list.html b/ereuse_devicehub/templates/inventory/device_list.html
index 82976a38..344e9f66 100644
--- a/ereuse_devicehub/templates/inventory/device_list.html
+++ b/ereuse_devicehub/templates/inventory/device_list.html
@@ -209,7 +209,7 @@
-
+
DataWipe
diff --git a/ereuse_devicehub/templates/inventory/erasure.html b/ereuse_devicehub/templates/inventory/erasure.html
index 681f31a6..854d9a19 100644
--- a/ereuse_devicehub/templates/inventory/erasure.html
+++ b/ereuse_devicehub/templates/inventory/erasure.html
@@ -66,91 +66,108 @@
-
-
+
-
-
-
Data Sanitization Certificate
-
-
-
-
-
Entity Information
+
+
{{ date_report }}, {{ software }}
+
+
+
+
+
-
-
- Name:
- |
+
- {{ customer_details and customer_details.company_name or ''}}
- |
-
-
-
- Location:
- |
-
- {{ customer_details and customer_details.location or '' }}
+
+
+
+
+ Responsible Sanitization Entity
+ |
+
+
+
+ Name:
+ |
+
+ {{ my_data and my_data.company_name or '' }}
+ |
+
+
+
+ Responsible Person
+ |
+
+ {{ my_data and my_data.responsable_person or '' }}
+ |
+
+
+
+ Location:
+ |
+
+ {{ my_data and my_data.location or '' }}
+ |
+
+
+ |
+
+
|
+
-
- Responsible Sanitization Entity
-
-
-
- Name:
- |
+
- {{ my_data and my_data.company_name or '' }}
- |
-
-
-
- Responsible Person
- |
-
- {{ my_data and my_data.responsable_person or '' }}
- |
-
-
-
- Location:
- |
-
- {{ my_data and my_data.location or '' }}
+
+
+
+
+ Entity Information
+ |
+
+
+
+ Name:
+ |
+
+ {{ customer_details and customer_details.company_name or ''}}
+ |
+
+
+
+ Location:
+ |
+
+ {{ customer_details and customer_details.location or '' }}
+ |
+
+
+
+ |
+
+
|
+
+
Summary
@@ -158,6 +175,16 @@
+ {% if customer_details and customer_details.transfer %}
+
+
+ Code Transfer:
+ |
+
+ {{ customer_details.transfer.code or '' }}
+ |
+
+ {% endif %}
{% if erasure_hosts %}
@@ -166,7 +193,7 @@
|
{% for e in erasure_hosts %}
{% if e.serial_number %}
- {{ e.serial_number.upper() }}{% if not loop.last %},{% endif %}
+ {{ (e.serial_number or '').upper() }}{% if not loop.last %},{% endif %}
{% endif %}
{% endfor %}
|
@@ -192,10 +219,18 @@
- Sanitization result:
+ N° result Success:
|
- {{ result }}
+ {{ result_success }}
+ |
+
+
+
+ N° result Failed:
+ |
+
+ {{ result_failed }}
|
@@ -288,10 +323,10 @@
{% for erasure in erasures %}
- {{ erasure.device.serial_number and erasure.device.serial_number.upper() or '' }}
+ {{ (erasure.device.serial_number or '').upper() }}
|
- {{ erasure.parent.serial_number and erasure.parent.serial_number.upper() or '' }}
+ {{ (erasure.parent.serial_number or '').upper() }}
|
{{ erasure.get_public_name() }}
@@ -311,39 +346,43 @@
{% for erasure in erasures %}
- {{ erasure.device.serial_number.upper() }}
-
- - Data storage:
- - {{ erasure.device.__format__('ts') }}
-
- {% if erasure.parent %}
- - Computer where was erase:
- - Title: {{ erasure.parent.__format__('ts') }}
- - DevicehubID: {{ erasure.parent.dhid }}
- - Hid: {{ erasure.parent.chid }}
- - Tags: {{ erasure.parent.tags }}
-
- {% if erasure.device.parent %}
- - Computer where it resides:
- - Title: {{ erasure.device.parent.__format__('ts') }}
- - DevicehubID: {{ erasure.device.parent.dhid }}
- - Hid: {{ erasure.device.parent.chid }}
- - Tags: {{ erasure.device.parent.tags }}
- {% endif %}
+ {% if loop.index == 1 %}
+
+ Tenchnical Details
+
{% endif %}
+ {{ (erasure.device.serial_number or '').upper() }}
+
+ - Storage Drive:
+ - Model: {{ erasure.device.model }}
+ - SN: {{ (erasure.device.serial_number or '').upper() }}
+ - Size: {{ erasure.device.get_size()}}
+ {% if erasure.parent %}
+
+ - Computer Host:
+ - Model: {{ erasure.parent.model }}
+ - SN: {{ (erasure.parent.serial_number or '').upper() }}
+ - DHID: {{ erasure.parent.dhid }}
+ {% endif %}
+
- Erasure:
- {{ erasure.__format__('ts') }}
{% if erasure.steps %}
- Erasure steps:
- -
-
- {% for step in erasure.steps %}
- - {{ step.__format__('') }}
- {% endfor %}
-
-
- {% endif %}
+ -
+
+ {% for step in erasure.steps %}
+ - {{ step.__format__('') }}
+ {% endfor %}
+
+
+ {% endif %}
+ {% if erasure.type == 'EraseDataWipe' %}
+
+ - Software:
+ - {{ erasure.document and erasure.document.software or ''}}
+ {% endif %}
{% if erasure.device.proofs %}
- DLT Proofs:
-
diff --git a/tests/test_basic.py b/tests/test_basic.py
index bf78792d..3922e959 100644
--- a/tests/test_basic.py
+++ b/tests/test_basic.py
@@ -125,4 +125,4 @@ def test_api_docs(client: Client):
'scheme': 'basic',
'name': 'Authorization',
}
- assert len(docs['definitions']) == 134
+ assert len(docs['definitions']) == 135
diff --git a/tests/test_render_2_0.py b/tests/test_render_2_0.py
index b5bd45ab..342619c7 100644
--- a/tests/test_render_2_0.py
+++ b/tests/test_render_2_0.py
@@ -1375,6 +1375,34 @@ def test_action_datawipe(user3: UserClientFlask):
assert dev.binding.device.devicehub_id in body
+@pytest.mark.mvp
+@pytest.mark.usefixtures(conftest.app_context.__name__)
+def test_action_erasedatawipe(user3: UserClientFlask):
+ snap = create_device(user3, 'real-eee-1001pxd.snapshot.12.json')
+ dev = snap.device
+ uri = '/inventory/device/'
+ user3.get(uri)
+
+ b_file = b'1234567890'
+ file_name = "my_file.doc"
+ file_upload = (BytesIO(b_file), file_name)
+
+ data = {
+ 'csrf_token': generate_csrf(),
+ 'type': "EraseDataWipe",
+ 'severity': "Info",
+ 'devices': "{}".format(dev.binding.device.id),
+ 'document-file_name': file_upload,
+ }
+
+ uri = '/inventory/action/datawipe/add/'
+ body, status = user3.post(uri, data=data, content_type="multipart/form-data")
+ assert status == '200 OK'
+ assert dev.binding.device.actions[-1].type == 'EraseDataWipe'
+ assert 'Action "EraseDataWipe" created successfully!' in body
+ assert dev.binding.device.devicehub_id in body
+
+
@pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__)
def test_wb_settings(user3: UserClientFlask):
|