diff --git a/ereuse_devicehub/inventory/forms.py b/ereuse_devicehub/inventory/forms.py index 01f71d87..41a3b1ca 100644 --- a/ereuse_devicehub/inventory/forms.py +++ b/ereuse_devicehub/inventory/forms.py @@ -55,9 +55,11 @@ from ereuse_devicehub.resources.device.models import ( DataStorage, Desktop, Device, + HardDrive, Keyboard, Laptop, MemoryCardReader, + Mobile, Monitor, Mouse, Other, @@ -65,6 +67,7 @@ from ereuse_devicehub.resources.device.models import ( Projector, Server, Smartphone, + SolidStateDrive, Tablet, TelevisionSet, ) @@ -100,7 +103,7 @@ DEVICES = { "Drives & Storage": [ "All DataStorage", "HardDrive", - "SolidStageDrive", + "SolidStateDrive", ], "Accessories": [ "All Accessories", @@ -128,6 +131,7 @@ MOBILE = ["Mobile", "Tablet", "Smartphone", "Cellphone"] STORAGE = ["HardDrive", "SolidStateDrive"] ACCESSORIES = ["Mouse", "MemoryCardReader", "SAI", "Keyboard"] OTHERS = ["Other"] +DATASTORAGE = ['HardDrive', 'SolidStateDrive'] class AdvancedSearchForm(FlaskForm): @@ -202,7 +206,7 @@ class FilterForm(FlaskForm): # Generic Filters if "All Devices" == self.device_type: - filter_type = COMPUTERS + MONITORS + MOBILE + OTHERS + filter_type = COMPUTERS + MONITORS + MOBILE + DATASTORAGE + OTHERS elif "All Computers" == self.device_type: filter_type = COMPUTERS @@ -399,6 +403,7 @@ class NewDeviceForm(FlaskForm): sku = StringField('SKU', [validators.Optional()]) image = URLField('Image', [validators.Optional(), validators.URL()]) imei = IntegerField('IMEI', [validators.Optional()]) + data_storage_size = FloatField('Storage Size', [validators.Optional()]) meid = StringField('MEID', [validators.Optional()]) resolution = IntegerField('Resolution width', [validators.Optional()]) screen = FloatField('Screen size', [validators.Optional()]) @@ -418,6 +423,8 @@ class NewDeviceForm(FlaskForm): "Smartphone": Smartphone, "Tablet": Tablet, "Cellphone": Cellphone, + "HardDrive": HardDrive, + "SolidStateDrive": SolidStateDrive, "ComputerMonitor": ComputerMonitor, "Monitor": Monitor, "TelevisionSet": TelevisionSet, @@ -429,7 +436,7 @@ class NewDeviceForm(FlaskForm): "Other": Other, } - def reset_from_obj(self): + def reset_from_obj(self): # noqa: C901 if not self._obj: return disabled = {'disabled': "disabled"} @@ -466,9 +473,13 @@ class NewDeviceForm(FlaskForm): if self._obj.type in ['Smartphone', 'Tablet', 'Cellphone']: self.imei.data = self._obj.imei self.meid.data = self._obj.meid + self.data_storage_size.data = self._obj.data_storage_size if self._obj.type == 'ComputerMonitor': self.resolution.data = self._obj.resolution_width self.screen.data = self._obj.size + if self._obj.type in ['HardDrive', 'SolidStateDrive']: + if self._obj.size: + self.data_storage_size.data = self._obj.size / 1000 if self._obj.placeholder.is_abstract: self.type.render_kw = disabled @@ -493,6 +504,9 @@ class NewDeviceForm(FlaskForm): if self._obj.type in ['Smartphone', 'Tablet', 'Cellphone']: self.imei.render_kw = disabled self.meid.render_kw = disabled + self.data_storage_size.render_kw = disabled + if self._obj.type in ['HardDrive', 'SolidStateDrive']: + self.data_storage_size.render_kw = disabled if self._obj.type == 'ComputerMonitor': self.resolution.render_kw = disabled self.screen.render_kw = disabled @@ -605,6 +619,11 @@ class NewDeviceForm(FlaskForm): if self.type.data in ['Smartphone', 'Tablet', 'Cellphone']: device.imei = self.imei.data device.meid = self.meid.data + device.data_storage_size = self.data_storage_size.data + + if self.type.data in ['HardDrive', 'SolidStateDrive']: + if self.data_storage_size.data: + device.size = self.data_storage_size.data * 1000 device.image = URL(self.image.data) @@ -673,6 +692,11 @@ class NewDeviceForm(FlaskForm): if self._obj.type in ['Smartphone', 'Tablet', 'Cellphone']: self._obj.imei = self.imei.data self._obj.meid = self.meid.data + self._obj.data_storage_size = self.data_storage_size.data + + if self.type.data in ['HardDrive', 'SolidStateDrive']: + if self.data_storage_size.data: + self._obj.size = self.data_storage_size.data * 1000 if ( self.appearance.data @@ -1085,6 +1109,14 @@ class DataWipeForm(ActionFormMixin): del self.document for dev in self._devices: ac = None + if isinstance(dev, Mobile) or isinstance(dev, DataStorage): + ac = Model() + self.populate_obj(ac) + ac.device_id = dev.id + ac.document = document.form._obj + db.session.add(ac) + continue + for hd in dev.components: if not isinstance(hd, DataStorage): continue diff --git a/ereuse_devicehub/inventory/views.py b/ereuse_devicehub/inventory/views.py index c00a8cb1..3f4a52e3 100644 --- a/ereuse_devicehub/inventory/views.py +++ b/ereuse_devicehub/inventory/views.py @@ -47,6 +47,7 @@ from ereuse_devicehub.resources.device.models import ( Computer, DataStorage, Device, + Mobile, Placeholder, ) from ereuse_devicehub.resources.documents.device_row import ActionRow, DeviceRow @@ -1198,6 +1199,10 @@ class ExportsView(View): ac = device.last_erase_action if ac: erasures.append(ac) + elif isinstance(device, Mobile): + ac = device.last_erase_action + if ac: + erasures.append(ac) return erasures def get_costum_details(self, erasures): @@ -1241,15 +1246,19 @@ class ExportsView(View): def get_server_erasure_hosts(self, erasures): erasures_host = [] + erasures_mobile = [] erasures_on_server = [] for erase in erasures: try: + if isinstance(erase.device, Mobile): + erasures_mobile.append(erase.device) + continue if erase.parent.binding.kangaroo: erasures_host.append(erase.parent) erasures_on_server.append(erase) except Exception: pass - return erasures_host, erasures_on_server + return erasures_host, erasures_on_server, erasures_mobile def build_erasure_certificate(self): erasures = self.get_datastorages() @@ -1261,9 +1270,10 @@ class ExportsView(View): my_data, customer_details = self.get_costum_details(erasures) - a, b = self.get_server_erasure_hosts(erasures) - erasures_host, erasures_on_server = a, b + a, b, c = self.get_server_erasure_hosts(erasures) + erasures_host, erasures_on_server, erasures_mobile = a, b, c erasures_host = set(erasures_host) + erasures_mobile = set(erasures_mobile) result_success = 0 result_failed = 0 @@ -1278,7 +1288,8 @@ class ExportsView(View): erasures_on_server = sorted(erasures_on_server, key=lambda x: x.end_time) erasures_normal = list(set(erasures) - set(erasures_on_server)) erasures_normal = sorted(erasures_normal, key=lambda x: x.end_time) - n_computers = len({x.parent for x in erasures} - erasures_host) + n_computers = len({x.parent for x in erasures if x.parent} - erasures_host) + n_mobiles = len(erasures_mobile) params = { 'title': 'Device Sanitization', @@ -1289,10 +1300,12 @@ class ExportsView(View): 'software': software, 'my_data': my_data, 'n_computers': n_computers, + 'n_mobiles': n_mobiles, 'result_success': result_success, 'result_failed': result_failed, 'customer_details': customer_details, 'erasure_hosts': erasures_host, + 'erasure_mobiles': erasures_mobile, 'erasures_normal': erasures_normal, } return flask.render_template('inventory/erasure.html', **params) diff --git a/ereuse_devicehub/resources/device/models.py b/ereuse_devicehub/resources/device/models.py index 34b8ee43..b3aa2343 100644 --- a/ereuse_devicehub/resources/device/models.py +++ b/ereuse_devicehub/resources/device/models.py @@ -1116,6 +1116,9 @@ class Device(Thing): return lot return None + def is_mobile(self): + return isinstance(self, Mobile) + def __lt__(self, other): return self.id < other.id @@ -1425,11 +1428,11 @@ class Computer(Device): @property def external_document_erasure(self): """Returns the external ``DataStorage`` proof of erasure.""" - from ereuse_devicehub.resources.action.models import DataWipe + from ereuse_devicehub.resources.action.models import EraseDataWipe urls = set() try: - ev = self.last_action_of(DataWipe) + ev = self.last_action_of(EraseDataWipe) urls.add(ev.document.url.to_text()) except LookupError: pass @@ -1540,6 +1543,48 @@ class Mobile(Device): raise ValidationError('{} is not a valid meid.'.format(value)) return value + @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 + + @property + def privacy(self): + """Returns the privacy compliance state of the data storage. + + This is, the last erasure performed to the data storage. + """ + from ereuse_devicehub.resources.action.models import EraseBasic + + try: + ev = self.last_action_of(EraseBasic) + except LookupError: + ev = None + return ev + + def get_size(self): + return self.data_storage_size + class Smartphone(Mobile): pass diff --git a/ereuse_devicehub/resources/documents/device_row.py b/ereuse_devicehub/resources/documents/device_row.py index edb1282f..31867a64 100644 --- a/ereuse_devicehub/resources/documents/device_row.py +++ b/ereuse_devicehub/resources/documents/device_row.py @@ -343,6 +343,10 @@ class DeviceRow(BaseDeviceRow): if isinstance(device, d.Mobile): self['IMEI'] = device.imei or '' + self.get_erasure_datawipe_mobile(device) + + if isinstance(device, d.DataStorage): + self.get_erasure_datawipe_mobile(device) def components(self): """Function to get all components information of a device.""" @@ -417,6 +421,32 @@ class DeviceRow(BaseDeviceRow): self['{} {} Size (MB)'.format(ctype, i)] = none2str(component.size) self['{} {} Speed (MHz)'.format(ctype, i)] = none2str(component.speed) + def get_erasure_datawipe_mobile(self, device): + actions = sorted(device.actions) + erasures = [a for a in actions if a.type == 'EraseDataWipe'] + erasure = erasures[-1] if erasures else None + if erasure: + self['Erasure DataStorage 1'] = none2str(device.chid) + if isinstance(device, d.Mobile): + serial_number = none2str(device.imei) + size = device.data_storage_size + size = size * 1000 if size else 0 + storage_size = none2str(size) + + if isinstance(device, d.DataStorage): + serial_number = none2str(device.serial_number) + storage_size = none2str(device.size) + + self['Erasure DataStorage 1 Serial Number'] = serial_number + self['Erasure DataStorage 1 Size (MB)'] = storage_size + self['Erasure DataStorage 1 Software'] = erasure.document.software + self['Erasure DataStorage 1 Result'] = get_result(erasure) + self['Erasure DataStorage 1 Type'] = erasure.type + self['Erasure DataStorage 1 Date'] = format(erasure.document.date or '') + self['Erasure DataStorage 1 Certificate URL'] = ( + erasure.document.url and erasure.document.url.to_text() or '' + ) + def get_datastorage(self, ctype, i, component): """Particular fields for component DataStorage. A DataStorage can be HardDrive or SolidStateDrive. @@ -455,6 +485,10 @@ class DeviceRow(BaseDeviceRow): self['Erasure {} {} Size (MB)'.format(ctype, i)] = none2str(component.size) self['Erasure {} {} Software'.format(ctype, i)] = erasure.document.software self['Erasure {} {} Result'.format(ctype, i)] = get_result(erasure) + self['Erasure {} {} Type'.format(ctype, i)] = erasure.type + self['Erasure {} {} Date'.format(ctype, i)] = format( + erasure.document.date or '' + ) self['Erasure {} {} Certificate URL'.format(ctype, i)] = ( erasure.document.url and erasure.document.url.to_text() or '' ) diff --git a/ereuse_devicehub/static/js/create_device.js b/ereuse_devicehub/static/js/create_device.js index 4acece0f..34965cf6 100644 --- a/ereuse_devicehub/static/js/create_device.js +++ b/ereuse_devicehub/static/js/create_device.js @@ -1,28 +1,44 @@ $(document).ready(() => { - $("#type").on("change", deviceInputs); - $("#amount").on("change", amountInputs); + $("#type").on("change", deviceInputs2); + $("#amount").on("change", deviceInputs2); + deviceInputs2() +}) + +function deviceInputs2() { deviceInputs(); amountInputs(); -}) +} function deviceInputs() { if ($("#type").val() == "ComputerMonitor") { $("#screen").show(); $("#resolution").show(); + $("#components2").hide(); $("#imei").hide(); $("#meid").hide(); + $("#data_storage_size").hide(); } else if (["Smartphone", "Cellphone", "Tablet"].includes($("#type").val())) { $("#screen").hide(); $("#resolution").hide(); + $("#components2").hide(); $("#imei").show(); $("#meid").show(); + $("#data_storage_size").show(); + } else if (["HardDrive", "SolidStateDrive"].includes($("#type").val())) { + $("#screen").hide(); + $("#resolution").hide(); + $("#components2").hide(); + $("#imei").hide(); + $("#meid").hide(); + $("#data_storage_size").show(); } else { $("#screen").hide(); $("#resolution").hide(); $("#imei").hide(); $("#meid").hide(); + $("#data_storage_size").hide(); + $("#components2").show(); }; - amountInputs(); } function amountInputs() { @@ -35,6 +51,7 @@ function amountInputs() { $("#Sku").hide(); $("#imei").hide(); $("#meid").hide(); + $("#data_storage_size").hide(); } else { $("#Phid").show(); $("#Id_device_supplier").show(); @@ -42,6 +59,5 @@ function amountInputs() { $("#Serial_number").show(); $("#Part_number").show(); $("#Sku").show(); - deviceInputs(); }; } diff --git a/ereuse_devicehub/templates/inventory/device_create.html b/ereuse_devicehub/templates/inventory/device_create.html index 8ad8634a..3de677c9 100644 --- a/ereuse_devicehub/templates/inventory/device_create.html +++ b/ereuse_devicehub/templates/inventory/device_create.html @@ -62,6 +62,12 @@ + + + + @@ -152,7 +158,7 @@ {% endif %} -
+
{{ form.components(class_="form-control") }} Description of components @@ -434,6 +440,19 @@ {% endif %}
+
+ + {{ form.data_storage_size(class_="form-control") }} + Size in GB. + {% if form.data_storage_size.errors %} +

+ {% for error in form.data_storage_size.errors %} + {{ error }}
+ {% endfor %} +

+ {% endif %} +
+
{{ form.resolution(class_="form-control") }} diff --git a/ereuse_devicehub/templates/inventory/erasure.html b/ereuse_devicehub/templates/inventory/erasure.html index 5674ae9c..73d201a9 100644 --- a/ereuse_devicehub/templates/inventory/erasure.html +++ b/ereuse_devicehub/templates/inventory/erasure.html @@ -209,6 +209,16 @@ {% endif %} + {% if n_mobiles %} + + + N° of mobiles: + + + {{ n_mobiles }} + + + {% endif %} N° of data storage unit(s): @@ -322,12 +332,20 @@ {% for erasure in erasures %} + {% if erasure.device.is_mobile() %} + + IMEI:{{ (erasure.device.imei or '') }} + + + + {% else %} {{ (erasure.device.serial_number or '').upper() }} {{ (erasure.parent.serial_number or '').upper() }} + {% endif %} {{ erasure.get_public_name() }} @@ -351,12 +369,21 @@

Technical Details

{% endif %} + {% if erasure.device.is_mobile() %} +

{{ (erasure.device.imei or '') }}

+
+
Mobile Drive:
+
Model: {{ erasure.device.model }}
+
IMEI: {{ (erasure.device.imei or '') }}
+
DHID: {{ erasure.device.dhid }}
+
Size: {{ erasure.device.get_size() or '?' }} GB
+ {% else %}

{{ (erasure.device.serial_number or '').upper() }}

Storage Drive:
Model: {{ erasure.device.model }}
SN: {{ (erasure.device.serial_number or '').upper() }}
-
Size: {{ erasure.device.get_size()}}
+
Size: {{ erasure.device.get_size() or '' }}
{% if erasure.parent %}
Computer Host:
@@ -364,6 +391,7 @@
SN: {{ (erasure.parent.serial_number or '').upper() }}
DHID: {{ erasure.parent.dhid }}
{% endif %} + {% endif %}
Erasure:
diff --git a/ereuse_devicehub/templates/inventory/erasure_list.html b/ereuse_devicehub/templates/inventory/erasure_list.html index 0e57e9f9..2449686b 100644 --- a/ereuse_devicehub/templates/inventory/erasure_list.html +++ b/ereuse_devicehub/templates/inventory/erasure_list.html @@ -162,6 +162,7 @@ {% for ac in erasure.items %} + {% if not ac.device.is_mobile() %} + {% endif %} {% endfor %} diff --git a/ereuse_devicehub/templates/inventory/upload_placeholder.html b/ereuse_devicehub/templates/inventory/upload_placeholder.html index 6291589d..7763cd43 100644 --- a/ereuse_devicehub/templates/inventory/upload_placeholder.html +++ b/ereuse_devicehub/templates/inventory/upload_placeholder.html @@ -56,6 +56,12 @@ + + + +