Merge branch 'testing'
This commit is contained in:
commit
6fa5a25a4a
|
@ -58,6 +58,8 @@ class InventoryView(LoginMixin, SnapshotMixin):
|
|||
self.snapshot_json = ParseSnapshotLsHw(snapshot_json).get_snapshot()
|
||||
|
||||
snapshot = self.build()
|
||||
snapshot.device.set_hid()
|
||||
snapshot.device.binding.device.set_hid()
|
||||
db.session.add(snapshot)
|
||||
|
||||
snap_log = SnapshotsLog(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import itertools
|
||||
import json
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
|
||||
import click
|
||||
|
@ -113,6 +114,8 @@ class Dummy:
|
|||
for path in bar:
|
||||
with path.open() as f:
|
||||
snapshot = yaml.load(f)
|
||||
if snapshot['device']['type'] in ['Desktop', 'Laptop']:
|
||||
snapshot['device']['system_uuid'] = uuid.uuid4()
|
||||
s, _ = user1.post(res=m.Snapshot, data=self.json_encode(snapshot))
|
||||
if s.get('uuid', None) == 'ec23c11b-80b6-42cd-ac5c-73ba7acddbc4':
|
||||
sample_pc = s['device']['id']
|
||||
|
@ -227,7 +230,7 @@ class Dummy:
|
|||
user1.get(res=Device, item=sample_pc_devicehub_id) # Test
|
||||
anonymous = self.app.test_client()
|
||||
html, _ = anonymous.get(res=Device, item=sample_pc_devicehub_id, accept=ANY)
|
||||
assert 'intel core2 duo cpu' in html
|
||||
assert 'hewlett-packard' in html
|
||||
|
||||
# For netbook: to preapre -> torepair -> to dispose -> disposed
|
||||
print('⭐ Done.')
|
||||
|
|
|
@ -178,6 +178,7 @@
|
|||
],
|
||||
"type": "Laptop"
|
||||
},
|
||||
"debug": {"lshw": {"configuration": {"uuid": "79c5098f-bc44-4834-8a59-9ea61d956c31"}}},
|
||||
"elapsed": 14725,
|
||||
"endTime": "2018-11-24T18:06:37.611704+00:00",
|
||||
"software": "Workbench",
|
||||
|
|
|
@ -119,6 +119,7 @@
|
|||
"manufacturer": "ASUSTeK Computer INC."
|
||||
}
|
||||
],
|
||||
"debug": {"lshw": {"configuration": {"uuid": "645f00bf-1ec0-4fdb-9608-b5ac73e285f6"}}},
|
||||
"version": "11.0a4",
|
||||
"elapsed": 6,
|
||||
"endTime": "2016-11-03T17:17:17.266543+00:00"
|
||||
|
|
|
@ -148,6 +148,7 @@
|
|||
"model": "0UG982"
|
||||
}
|
||||
],
|
||||
"debug": {"lshw": {"configuration": {"uuid": "5dcdd380-5a54-48bc-99bf-aff6019e8491"}}},
|
||||
"version": "11.0a3",
|
||||
"closed": false,
|
||||
"elapsed": 1512,
|
||||
|
|
|
@ -132,5 +132,6 @@
|
|||
"model": "HP Compaq 8100 Elite SFF",
|
||||
"manufacturer": "Hewlett-Packard"
|
||||
},
|
||||
"debug": {"lshw": {"configuration": {"uuid": "f6cfe48a-93d5-4e94-ab7b-3ee371e4d048"}}},
|
||||
"version": "11.0a3"
|
||||
}
|
||||
|
|
|
@ -170,5 +170,6 @@
|
|||
},
|
||||
"software": "Workbench",
|
||||
"endTime": "2018-07-11T10:30:22.395958+00:00",
|
||||
"debug": {"lshw": {"configuration": {"uuid": "75dcb454-ae80-4a87-a192-185d3b0250c0"}}},
|
||||
"elapsed": 2766
|
||||
}
|
||||
|
|
|
@ -146,6 +146,7 @@
|
|||
"pcmcia": 0
|
||||
}
|
||||
],
|
||||
"debug": {"lshw": {"configuration": {"uuid": "fcaf784e-5e57-43a2-b03f-8c56dabd0415"}}},
|
||||
"uuid": "a01eacdb-db01-43ec-b6fb-a9b8cd21492d",
|
||||
"type": "Snapshot",
|
||||
"version": "11.0a4",
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"closed": false,
|
||||
"endTime": "2018-07-11T13:26:29.365504+00:00",
|
||||
"type": "Snapshot",
|
||||
"debug": {"lshw": {"configuration": {"uuid": "4f256440-e43f-429a-a2c6-1e8f3365de56"}}},
|
||||
"device": {
|
||||
"serialNumber": "PB357N0",
|
||||
"actions": [
|
||||
|
|
|
@ -148,6 +148,7 @@
|
|||
"slots": 4
|
||||
}
|
||||
],
|
||||
"debug": {"lshw": {"configuration": {"uuid": "077cad5d-ae1b-4156-a9a1-98bca6fa5c35"}}},
|
||||
"version": "11.0a3",
|
||||
"endTime": "2018-07-11T10:28:55.879745+00:00",
|
||||
"type": "Snapshot",
|
||||
|
|
|
@ -136,8 +136,8 @@
|
|||
],
|
||||
"elapsed": 203,
|
||||
"device": {
|
||||
"manufacturer": null,
|
||||
"model": null,
|
||||
"manufacturer": "Asus",
|
||||
"model": "P7P55D",
|
||||
"chassis": "Tower",
|
||||
"type": "Desktop",
|
||||
"serialNumber": null,
|
||||
|
@ -158,7 +158,7 @@
|
|||
]
|
||||
},
|
||||
"version": "11.0a6",
|
||||
|
||||
"debug": {"lshw": {"configuration": {"uuid": "59ca9a2a-65bd-4802-89bb-315156a9352b"}}},
|
||||
"type": "Snapshot",
|
||||
"closed": true,
|
||||
"software": "Workbench"
|
||||
|
|
|
@ -142,7 +142,7 @@
|
|||
},
|
||||
"elapsed": 238,
|
||||
"endTime": "2018-10-15T13:59:37.431309+00:00",
|
||||
|
||||
"debug": {"lshw": {"configuration": {"uuid": "43686b8e-e1ae-4e4e-bc51-f98f51e97c2d"}}},
|
||||
"software": "Workbench",
|
||||
"type": "Snapshot",
|
||||
"uuid": "ec23c11b-80b6-42cd-ac5c-73ba7acddbc4",
|
||||
|
|
|
@ -158,5 +158,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"debug": {"lshw": {"configuration": {"uuid": "a0cef731-9a78-4087-889c-dfb6ba5c2e9b"}}},
|
||||
"closed": false
|
||||
}
|
||||
|
|
|
@ -114,6 +114,7 @@
|
|||
}
|
||||
],
|
||||
"version": "11.0a3",
|
||||
"debug": {"lshw": {"configuration": {"uuid": "f2c50acd-501a-4f0b-b07c-58254b2ab8c9"}}},
|
||||
"device": {
|
||||
"type": "Desktop",
|
||||
"model": "HP Compaq 8000 Elite SFF",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"closed": false,
|
||||
"uuid": "f9e5e587-baee-44e1-9a94-255d216bbda9",
|
||||
"debug": {"lshw": {"configuration": {"uuid": "4d21dd26-aa45-4902-a5f2-8a06e364cf25"}}},
|
||||
"components": [
|
||||
{
|
||||
"actions": [],
|
||||
|
|
|
@ -131,6 +131,7 @@
|
|||
"model": "NB200"
|
||||
},
|
||||
"uuid": "918726ae-c6bc-40aa-97cf-ad80d69268f9",
|
||||
"debug": {"lshw": {"configuration": {"uuid": "33627ef0-89a9-4659-bb29-faa936727e0b"}}},
|
||||
"closed": false,
|
||||
"type": "Snapshot"
|
||||
}
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
from boltons.urlutils import URL
|
||||
from flask import g
|
||||
from flask_wtf import FlaskForm
|
||||
from werkzeug.security import generate_password_hash
|
||||
from wtforms import BooleanField, EmailField, PasswordField, validators
|
||||
from wtforms import (
|
||||
BooleanField,
|
||||
EmailField,
|
||||
PasswordField,
|
||||
StringField,
|
||||
URLField,
|
||||
validators,
|
||||
)
|
||||
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.resources.user.models import User
|
||||
from ereuse_devicehub.resources.user.models import SanitizationEntity, User
|
||||
|
||||
|
||||
class LoginForm(FlaskForm):
|
||||
|
@ -101,3 +109,62 @@ class PasswordForm(FlaskForm):
|
|||
if commit:
|
||||
db.session.commit()
|
||||
return
|
||||
|
||||
|
||||
class SanitizationEntityForm(FlaskForm):
|
||||
|
||||
logo = URLField(
|
||||
'Logo',
|
||||
[validators.Optional(), validators.URL()],
|
||||
render_kw={
|
||||
'class': "form-control",
|
||||
"placeholder": "Url where is the logo - acceptd only .png, .jpg, .gif, svg",
|
||||
},
|
||||
)
|
||||
company_name = StringField('Company Name', render_kw={'class': "form-control"})
|
||||
location = StringField('Location', render_kw={'class': "form-control"})
|
||||
responsable_person = StringField(
|
||||
'Responsable person', render_kw={'class': "form-control"}
|
||||
)
|
||||
supervisor_person = StringField(
|
||||
'Supervisor person', render_kw={'class': "form-control"}
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if isinstance(self.logo.data, URL):
|
||||
self.logo.data = self.logo.data.to_text()
|
||||
|
||||
def validate(self, extra_validators=None):
|
||||
is_valid = super().validate(extra_validators)
|
||||
|
||||
if not is_valid:
|
||||
return False
|
||||
|
||||
if not self.logo.data:
|
||||
return True
|
||||
|
||||
extensions = ["jpg", "jpeg", "png", "gif", "svg"]
|
||||
if self.logo.data.lower().split(".")[-1] not in extensions:
|
||||
txt = "Error in Url field - accepted only .PNG, .JPG and .GIF. extensions"
|
||||
self.logo.errors = [txt]
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def save(self, commit=True):
|
||||
if isinstance(self.logo.data, str):
|
||||
self.logo.data = URL(self.logo.data)
|
||||
|
||||
sanitation_data = SanitizationEntity.query.filter_by(user_id=g.user.id).first()
|
||||
|
||||
if not sanitation_data:
|
||||
sanitation_data = SanitizationEntity(user_id=g.user.id)
|
||||
self.populate_obj(sanitation_data)
|
||||
db.session.add(sanitation_data)
|
||||
else:
|
||||
self.populate_obj(sanitation_data)
|
||||
|
||||
if commit:
|
||||
db.session.commit()
|
||||
return
|
||||
|
|
|
@ -30,8 +30,13 @@ from wtforms import (
|
|||
from wtforms.fields import FormField
|
||||
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.inventory.models import DeliveryNote, ReceiverNote, Transfer
|
||||
from ereuse_devicehub.parser.models import PlaceholdersLog
|
||||
from ereuse_devicehub.inventory.models import (
|
||||
DeliveryNote,
|
||||
ReceiverNote,
|
||||
Transfer,
|
||||
TransferCustomerDetails,
|
||||
)
|
||||
from ereuse_devicehub.parser.models import PlaceholdersLog, SnapshotsLog
|
||||
from ereuse_devicehub.parser.parser import ParseSnapshotLsHw
|
||||
from ereuse_devicehub.parser.schemas import Snapshot_lite
|
||||
from ereuse_devicehub.resources.action.models import Snapshot, Trade
|
||||
|
@ -44,6 +49,7 @@ from ereuse_devicehub.resources.action.views.snapshot import (
|
|||
from ereuse_devicehub.resources.device.models import (
|
||||
SAI,
|
||||
Cellphone,
|
||||
Computer,
|
||||
ComputerMonitor,
|
||||
Desktop,
|
||||
Device,
|
||||
|
@ -203,7 +209,9 @@ class FilterForm(FlaskForm):
|
|||
if filter_type:
|
||||
self.devices = self.devices.filter(Device.type.in_(filter_type))
|
||||
|
||||
return self.devices.order_by(Device.updated.desc())
|
||||
return self.devices.filter(Device.active.is_(True)).order_by(
|
||||
Device.updated.desc()
|
||||
)
|
||||
|
||||
|
||||
class LotForm(FlaskForm):
|
||||
|
@ -247,6 +255,10 @@ class LotForm(FlaskForm):
|
|||
class UploadSnapshotForm(SnapshotMixin, FlaskForm):
|
||||
snapshot = MultipleFileField('Select a Snapshot File', [validators.DataRequired()])
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.create_new_devices = kwargs.pop('create_new_devices', False)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def validate(self, extra_validators=None):
|
||||
is_valid = super().validate(extra_validators)
|
||||
|
||||
|
@ -291,7 +303,7 @@ class UploadSnapshotForm(SnapshotMixin, FlaskForm):
|
|||
|
||||
return is_lite
|
||||
|
||||
def save(self, commit=True):
|
||||
def save(self, commit=True, user_trusts=True):
|
||||
if any([x == 'Error' for x in self.result.values()]):
|
||||
return
|
||||
schema = SnapshotSchema()
|
||||
|
@ -313,16 +325,21 @@ class UploadSnapshotForm(SnapshotMixin, FlaskForm):
|
|||
system_uuid = self.get_uuid(debug)
|
||||
if system_uuid:
|
||||
snapshot_json['device']['system_uuid'] = system_uuid
|
||||
self.get_fields_extra(debug, snapshot_json)
|
||||
|
||||
try:
|
||||
snapshot_json = schema.load(snapshot_json)
|
||||
response = self.build(snapshot_json)
|
||||
response = self.build(
|
||||
snapshot_json, create_new_device=self.create_new_devices
|
||||
)
|
||||
except ValidationError as err:
|
||||
txt = "{}".format(err)
|
||||
self.errors(txt=txt)
|
||||
self.result[filename] = 'Error'
|
||||
continue
|
||||
|
||||
if isinstance(response.device, Computer):
|
||||
response.device.user_trusts = user_trusts
|
||||
db.session.add(response)
|
||||
devices.append(response.device.binding.device)
|
||||
|
||||
|
@ -579,6 +596,7 @@ class NewDeviceForm(FlaskForm):
|
|||
device.image = URL(self.image.data)
|
||||
|
||||
device.placeholder = self.get_placeholder()
|
||||
device.set_hid()
|
||||
db.session.add(device)
|
||||
|
||||
placeholder_log = PlaceholdersLog(
|
||||
|
@ -1505,6 +1523,70 @@ class NotesForm(FlaskForm):
|
|||
return self._obj
|
||||
|
||||
|
||||
class CustomerDetailsForm(FlaskForm):
|
||||
company_name = StringField(
|
||||
'Company name',
|
||||
[validators.Optional()],
|
||||
render_kw={'class': "form-control"},
|
||||
description="Name of the company",
|
||||
)
|
||||
location = StringField(
|
||||
'Location',
|
||||
[validators.Optional()],
|
||||
render_kw={'class': "form-control"},
|
||||
description="""Location where is the company""",
|
||||
)
|
||||
logo = URLField(
|
||||
'Logo',
|
||||
[validators.Optional()],
|
||||
render_kw={
|
||||
'class': "form-control",
|
||||
"placeholder": "Url where is the logo - acceptd only .png, .jpg, .gif, svg",
|
||||
},
|
||||
description="Url where is the logo",
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
lot_id = kwargs.pop('lot_id', None)
|
||||
self._tmp_lot = Lot.query.filter(Lot.id == lot_id).one()
|
||||
self._obj = self._tmp_lot.transfer.customer_details
|
||||
if self._obj:
|
||||
kwargs['obj'] = self._obj
|
||||
if not self._obj:
|
||||
self._obj = TransferCustomerDetails(transfer_id=self._tmp_lot.transfer.id)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
if isinstance(self.logo.data, URL):
|
||||
self.logo.data = URL(self.logo.data).to_text()
|
||||
|
||||
def validate(self, extra_validators=None):
|
||||
is_valid = super().validate(extra_validators)
|
||||
|
||||
if not is_valid:
|
||||
return is_valid
|
||||
|
||||
if not self.logo.data:
|
||||
return True
|
||||
|
||||
extensions = ["jpg", "jpeg", "png", "gif", "svg"]
|
||||
if self.logo.data.lower().split(".")[-1] not in extensions:
|
||||
txt = "Error in Url field - accepted only .PNG, .JPG and .GIF. extensions"
|
||||
self.logo.errors = [txt]
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def save(self, commit=True):
|
||||
self.populate_obj(self._obj)
|
||||
self._obj.logo = URL(self._obj.logo)
|
||||
db.session.add(self._obj)
|
||||
|
||||
if commit:
|
||||
db.session.commit()
|
||||
|
||||
return self._obj
|
||||
|
||||
|
||||
class UploadPlaceholderForm(FlaskForm):
|
||||
type = StringField('Type', [validators.DataRequired()])
|
||||
placeholder_file = FileField(
|
||||
|
@ -1690,3 +1772,118 @@ class BindingForm(FlaskForm):
|
|||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class UserTrustsForm(FlaskForm):
|
||||
snapshot_type = SelectField(
|
||||
'',
|
||||
[validators.DataRequired()],
|
||||
choices=[("new_device", "New Device"), ("update", "Update")],
|
||||
default="new_device",
|
||||
render_kw={'class': "form-select"},
|
||||
)
|
||||
|
||||
def __init__(self, snapshot_uuid, *args, **kwargs):
|
||||
self.snapshot = Snapshot.query.filter_by(uuid=snapshot_uuid).one()
|
||||
self.device = None
|
||||
if self.snapshot.device:
|
||||
self.device = self.snapshot.device
|
||||
|
||||
self.snapshot_type.kwargs['default'] = self.snapshot.get_new_device()
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def validate(self, extra_validators=None):
|
||||
is_valid = super().validate(extra_validators)
|
||||
|
||||
if not is_valid:
|
||||
txt = ""
|
||||
self.snapthot_type.errors = [txt]
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def unic(self):
|
||||
try:
|
||||
return self._unic
|
||||
except Exception:
|
||||
self._devices = (
|
||||
Device.query.filter_by(
|
||||
hid=self.device.hid, owner=g.user, placeholder=None, active=True
|
||||
)
|
||||
.order_by(Device.updated.asc())
|
||||
.all()
|
||||
)
|
||||
|
||||
self._unic = len(self._devices) < 2
|
||||
return self._unic
|
||||
|
||||
def dhids_all_devices(self):
|
||||
self.unic()
|
||||
return ", ".join([x.dhid for x in self._devices][1:])
|
||||
|
||||
def dhid_base(self):
|
||||
self.unic()
|
||||
if not self._devices:
|
||||
return ''
|
||||
return self._devices[0].dhid
|
||||
|
||||
def show(self):
|
||||
if not self.snapshot or not self.device:
|
||||
return False
|
||||
|
||||
if not hasattr(self.device, 'system_uuid'):
|
||||
return False
|
||||
|
||||
if not self.device.system_uuid:
|
||||
return False
|
||||
|
||||
if self.snapshot.get_new_device() == 'update':
|
||||
# To do Split
|
||||
return True
|
||||
|
||||
if not self.unic():
|
||||
if self.device == self._devices[0]:
|
||||
return False
|
||||
# To do merge
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def save(self, commit=True):
|
||||
if not self.show():
|
||||
return
|
||||
|
||||
if self.snapshot_type.data == self.snapshot.get_new_device():
|
||||
return
|
||||
|
||||
if self.snapshot_type.data == 'update' and not self.unic():
|
||||
self.device.reliable()
|
||||
|
||||
if self.snapshot_type.data == 'new_device' and self.unic():
|
||||
self.device.unreliable()
|
||||
txt = "This devices is assigned as unreliable for the user "
|
||||
txt += "and never is possible to do an update of this device."
|
||||
self.error_log(txt)
|
||||
|
||||
if commit:
|
||||
db.session.commit()
|
||||
|
||||
return self.snapshot
|
||||
|
||||
def error_log(self, txt):
|
||||
snapshot = self.get_first_snapshot()
|
||||
error = SnapshotsLog(
|
||||
description=txt,
|
||||
snapshot=snapshot,
|
||||
snapshot_uuid=snapshot.uuid,
|
||||
severity=Severity.Error,
|
||||
sid=snapshot.sid,
|
||||
version="{}".format(snapshot.version),
|
||||
)
|
||||
db.session.add(error)
|
||||
|
||||
def get_first_snapshot(self):
|
||||
device = self.snapshot.device
|
||||
for ac in device.actions:
|
||||
if ac.type == 'Snapshot':
|
||||
return ac
|
||||
|
|
|
@ -5,7 +5,7 @@ from flask import g
|
|||
from sqlalchemy import Column, Integer
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import backref, relationship
|
||||
from teal.db import CASCADE_OWN
|
||||
from teal.db import CASCADE_OWN, URL
|
||||
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.resources.models import Thing
|
||||
|
@ -90,3 +90,23 @@ class ReceiverNote(Thing):
|
|||
backref=backref('receiver_note', lazy=True, uselist=False, cascade=CASCADE_OWN),
|
||||
primaryjoin='ReceiverNote.transfer_id == Transfer.id',
|
||||
)
|
||||
|
||||
|
||||
class TransferCustomerDetails(Thing):
|
||||
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4)
|
||||
company_name = Column(CIText(), nullable=True)
|
||||
location = Column(CIText(), nullable=True)
|
||||
logo = Column(URL(), nullable=True)
|
||||
|
||||
transfer_id = db.Column(
|
||||
UUID(as_uuid=True),
|
||||
db.ForeignKey('transfer.id'),
|
||||
nullable=False,
|
||||
)
|
||||
transfer = relationship(
|
||||
'Transfer',
|
||||
backref=backref(
|
||||
'customer_details', lazy=True, uselist=False, cascade=CASCADE_OWN
|
||||
),
|
||||
primaryjoin='TransferCustomerDetails.transfer_id == Transfer.id',
|
||||
)
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import copy
|
||||
import csv
|
||||
import datetime
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
|
||||
|
@ -20,6 +22,7 @@ from ereuse_devicehub.inventory.forms import (
|
|||
AdvancedSearchForm,
|
||||
AllocateForm,
|
||||
BindingForm,
|
||||
CustomerDetailsForm,
|
||||
DataWipeForm,
|
||||
EditTransferForm,
|
||||
FilterForm,
|
||||
|
@ -33,6 +36,7 @@ from ereuse_devicehub.inventory.forms import (
|
|||
TransferForm,
|
||||
UploadPlaceholderForm,
|
||||
UploadSnapshotForm,
|
||||
UserTrustsForm,
|
||||
)
|
||||
from ereuse_devicehub.labels.forms import PrintLabelsForm
|
||||
from ereuse_devicehub.parser.models import PlaceholdersLog, SnapshotsLog
|
||||
|
@ -78,6 +82,7 @@ class DeviceListMixin(GenericMixin):
|
|||
form_transfer = ''
|
||||
form_delivery = ''
|
||||
form_receiver = ''
|
||||
form_customer_details = ''
|
||||
|
||||
if lot_id:
|
||||
lot = lots.filter(Lot.id == lot_id).one()
|
||||
|
@ -85,6 +90,7 @@ class DeviceListMixin(GenericMixin):
|
|||
form_transfer = EditTransferForm(lot_id=lot.id)
|
||||
form_delivery = NotesForm(lot_id=lot.id, type='Delivery')
|
||||
form_receiver = NotesForm(lot_id=lot.id, type='Receiver')
|
||||
form_customer_details = CustomerDetailsForm(lot_id=lot.id)
|
||||
|
||||
form_new_action = NewActionForm(lot=lot_id)
|
||||
self.context.update(
|
||||
|
@ -96,6 +102,7 @@ class DeviceListMixin(GenericMixin):
|
|||
'form_transfer': form_transfer,
|
||||
'form_delivery': form_delivery,
|
||||
'form_receiver': form_receiver,
|
||||
'form_customer_details': form_customer_details,
|
||||
'form_filter': form_filter,
|
||||
'form_print_labels': PrintLabelsForm(),
|
||||
'lot': lot,
|
||||
|
@ -834,6 +841,21 @@ class NewTransferView(GenericMixin):
|
|||
return flask.render_template(self.template_name, **self.context)
|
||||
|
||||
|
||||
class OpenTransferView(GenericMixin):
|
||||
methods = ['GET']
|
||||
|
||||
def dispatch_request(self, lot_id=None):
|
||||
lot = Lot.query.filter_by(id=lot_id).one()
|
||||
next_url = url_for('inventory.lotdevicelist', lot_id=str(lot_id))
|
||||
|
||||
if hasattr(lot, 'transfer'):
|
||||
lot.transfer.date = None
|
||||
db.session.commit()
|
||||
messages.success('Transfer was reopen successfully!')
|
||||
|
||||
return flask.redirect(next_url)
|
||||
|
||||
|
||||
class EditTransferView(GenericMixin):
|
||||
methods = ['POST']
|
||||
form_class = EditTransferForm
|
||||
|
@ -1038,7 +1060,7 @@ class ExportsView(View):
|
|||
|
||||
return self.response_csv(data, "Erasures.csv")
|
||||
|
||||
def build_erasure_certificate(self):
|
||||
def get_datastorages(self):
|
||||
erasures = []
|
||||
for device in self.find_devices():
|
||||
if device.placeholder and device.placeholder.binding:
|
||||
|
@ -1049,11 +1071,96 @@ class ExportsView(View):
|
|||
elif isinstance(device, DataStorage):
|
||||
if device.privacy:
|
||||
erasures.append(device.privacy)
|
||||
return erasures
|
||||
|
||||
def get_costum_details(self, erasures):
|
||||
my_data = None
|
||||
customer_details = None
|
||||
lot = None
|
||||
|
||||
if hasattr(g.user, 'sanitization_entity'):
|
||||
my_data = g.user.sanitization_entity
|
||||
|
||||
customer_details = self.get_customer_details_from_request()
|
||||
|
||||
if not erasures or customer_details:
|
||||
return my_data, customer_details
|
||||
|
||||
lots = {erasures[0].device.get_last_incoming_lot()}
|
||||
for e in erasures[1:]:
|
||||
lots.add(e.device.get_last_incoming_lot())
|
||||
|
||||
if len(lots) != 1:
|
||||
return my_data, customer_details
|
||||
|
||||
lot = lots.pop()
|
||||
try:
|
||||
customer_details = lot.transfer.customer_details
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return my_data, customer_details
|
||||
|
||||
def get_customer_details_from_request(self):
|
||||
try:
|
||||
if len(request.referrer.split('/lot/')) < 2:
|
||||
return
|
||||
|
||||
lot_id = request.referrer.split('/lot/')[-1].split('/')[0]
|
||||
lot = Lot.query.filter_by(owner=g.user).filter_by(id=lot_id).first()
|
||||
return lot.transfer.customer_details
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def get_server_erasure_hosts(self, erasures):
|
||||
erasures_host = []
|
||||
erasures_on_server = []
|
||||
for erase in erasures:
|
||||
try:
|
||||
if erase.parent.binding.kangaroo:
|
||||
erasures_host.append(erase.parent)
|
||||
erasures_on_server.append(erase)
|
||||
except Exception:
|
||||
pass
|
||||
return erasures_host, erasures_on_server
|
||||
|
||||
def build_erasure_certificate(self):
|
||||
erasures = self.get_datastorages()
|
||||
software = 'USODY DRIVE ERASURE'
|
||||
if erasures and erasures[0].snapshot:
|
||||
software += ' {}'.format(
|
||||
erasures[0].snapshot.version,
|
||||
)
|
||||
|
||||
my_data, customer_details = self.get_costum_details(erasures)
|
||||
|
||||
a, b = self.get_server_erasure_hosts(erasures)
|
||||
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'
|
||||
|
||||
erasures = sorted(erasures, key=lambda x: x.end_time)
|
||||
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)
|
||||
|
||||
params = {
|
||||
'title': 'Erasure Certificate',
|
||||
'erasures': tuple(erasures),
|
||||
'url_pdf': '',
|
||||
'date_report': '{:%c}'.format(datetime.datetime.now()),
|
||||
'uuid_report': '{}'.format(uuid.uuid4()),
|
||||
'software': software,
|
||||
'my_data': my_data,
|
||||
'n_computers': n_computers,
|
||||
'result': result,
|
||||
'customer_details': customer_details,
|
||||
'erasure_hosts': erasures_host,
|
||||
'erasures_normal': erasures_normal,
|
||||
}
|
||||
return flask.render_template('inventory/erasure.html', **params)
|
||||
|
||||
|
@ -1228,9 +1335,12 @@ class SnapshotListView(GenericMixin):
|
|||
|
||||
class SnapshotDetailView(GenericMixin):
|
||||
template_name = 'inventory/snapshot_detail.html'
|
||||
methods = ['GET', 'POST']
|
||||
form_class = UserTrustsForm
|
||||
|
||||
def dispatch_request(self, snapshot_uuid):
|
||||
self.snapshot_uuid = snapshot_uuid
|
||||
form = self.form_class(snapshot_uuid)
|
||||
self.get_context()
|
||||
self.context['page_title'] = "Snapshot Detail"
|
||||
self.context['snapshots_log'] = self.get_snapshots_log()
|
||||
|
@ -1238,6 +1348,10 @@ class SnapshotDetailView(GenericMixin):
|
|||
self.context['snapshot_sid'] = ''
|
||||
if self.context['snapshots_log'].count():
|
||||
self.context['snapshot_sid'] = self.context['snapshots_log'][0].sid
|
||||
self.context['form'] = form
|
||||
|
||||
if form.validate_on_submit():
|
||||
form.save()
|
||||
|
||||
return flask.render_template(self.template_name, **self.context)
|
||||
|
||||
|
@ -1249,6 +1363,28 @@ class SnapshotDetailView(GenericMixin):
|
|||
)
|
||||
|
||||
|
||||
class CustomerDetailsView(GenericMixin):
|
||||
methods = ['POST']
|
||||
form_class = CustomerDetailsForm
|
||||
|
||||
def dispatch_request(self, lot_id):
|
||||
self.get_context()
|
||||
form = self.form_class(request.form, lot_id=lot_id)
|
||||
next_url = url_for('inventory.lotdevicelist', lot_id=lot_id)
|
||||
|
||||
if form.validate_on_submit():
|
||||
form.save()
|
||||
messages.success('Customer details updated successfully!')
|
||||
return flask.redirect(next_url)
|
||||
|
||||
messages.error('Customer details updated error!')
|
||||
for k, v in form.errors.items():
|
||||
value = ';'.join(v)
|
||||
key = form[k].label.text
|
||||
messages.error('Error {key}: {value}!'.format(key=key, value=value))
|
||||
return flask.redirect(next_url)
|
||||
|
||||
|
||||
class DeliveryNoteView(GenericMixin):
|
||||
methods = ['POST']
|
||||
form_class = NotesForm
|
||||
|
@ -1440,6 +1576,10 @@ devices.add_url_rule(
|
|||
'/lot/<string:lot_id>/transfer/',
|
||||
view_func=EditTransferView.as_view('edit_transfer'),
|
||||
)
|
||||
devices.add_url_rule(
|
||||
'/lot/<string:lot_id>/customerdetails/',
|
||||
view_func=CustomerDetailsView.as_view('customer_details'),
|
||||
)
|
||||
devices.add_url_rule(
|
||||
'/lot/<string:lot_id>/deliverynote/',
|
||||
view_func=DeliveryNoteView.as_view('delivery_note'),
|
||||
|
@ -1476,3 +1616,7 @@ devices.add_url_rule(
|
|||
'/device/erasure/<int:orphans>/',
|
||||
view_func=ErasureListView.as_view('device_erasure_list_orphans'),
|
||||
)
|
||||
devices.add_url_rule(
|
||||
'/lot/<string:lot_id>/opentransfer/',
|
||||
view_func=OpenTransferView.as_view('open_transfer'),
|
||||
)
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
"""sanitization
|
||||
|
||||
Revision ID: 4f33137586dd
|
||||
Revises: 93daff872771
|
||||
Create Date: 2023-02-13 18:01:00.092527
|
||||
|
||||
"""
|
||||
import citext
|
||||
import sqlalchemy as sa
|
||||
import teal
|
||||
from alembic import context, op
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '4f33137586dd'
|
||||
down_revision = '93daff872771'
|
||||
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(
|
||||
'sanitization_entity',
|
||||
sa.Column('id', sa.BigInteger(), nullable=False),
|
||||
sa.Column(
|
||||
'updated',
|
||||
sa.TIMESTAMP(timezone=True),
|
||||
server_default=sa.text('CURRENT_TIMESTAMP'),
|
||||
nullable=False,
|
||||
),
|
||||
sa.Column(
|
||||
'created',
|
||||
sa.TIMESTAMP(timezone=True),
|
||||
server_default=sa.text('CURRENT_TIMESTAMP'),
|
||||
nullable=False,
|
||||
),
|
||||
sa.Column('company_name', sa.String(), nullable=True),
|
||||
sa.Column('logo', teal.db.URL(), nullable=True),
|
||||
sa.Column('responsable_person', sa.String(), nullable=True),
|
||||
sa.Column('supervisor_person', sa.String(), nullable=True),
|
||||
sa.Column('location', sa.String(), nullable=True),
|
||||
sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.ForeignKeyConstraint(
|
||||
['user_id'],
|
||||
['common.user.id'],
|
||||
),
|
||||
schema=f'{get_inv()}',
|
||||
)
|
||||
|
||||
op.create_table(
|
||||
'transfer_customer_details',
|
||||
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
|
||||
sa.Column(
|
||||
'updated',
|
||||
sa.TIMESTAMP(timezone=True),
|
||||
server_default=sa.text('CURRENT_TIMESTAMP'),
|
||||
nullable=False,
|
||||
),
|
||||
sa.Column(
|
||||
'created',
|
||||
sa.TIMESTAMP(timezone=True),
|
||||
server_default=sa.text('CURRENT_TIMESTAMP'),
|
||||
nullable=False,
|
||||
),
|
||||
sa.Column('company_name', citext.CIText(), nullable=True),
|
||||
sa.Column('logo', teal.db.URL(), nullable=True),
|
||||
sa.Column('location', citext.CIText(), nullable=True),
|
||||
sa.Column('transfer_id', postgresql.UUID(as_uuid=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['transfer_id'], [f'{get_inv()}.transfer.id']),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
schema=f'{get_inv()}',
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_table('sanitization_entity', schema=f'{get_inv()}')
|
||||
op.drop_table('transfer_customer_details', schema=f'{get_inv()}')
|
|
@ -0,0 +1,35 @@
|
|||
"""add vendor family in device
|
||||
|
||||
Revision ID: 564952310b17
|
||||
Revises: af038a8a388c
|
||||
Create Date: 2022-11-14 13:12:22.916848
|
||||
|
||||
"""
|
||||
import citext
|
||||
import sqlalchemy as sa
|
||||
from alembic import context, op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '564952310b17'
|
||||
down_revision = 'af038a8a388c'
|
||||
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.add_column(
|
||||
'device',
|
||||
sa.Column('family', citext.CIText(), nullable=True),
|
||||
schema=f'{get_inv()}',
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_column('device', 'family', schema=f'{get_inv()}')
|
|
@ -0,0 +1,65 @@
|
|||
"""add hash hid to device
|
||||
|
||||
Revision ID: 93daff872771
|
||||
Revises: 564952310b17
|
||||
Create Date: 2022-12-13 10:14:45.500087
|
||||
|
||||
"""
|
||||
import hashlib
|
||||
|
||||
import citext
|
||||
import sqlalchemy as sa
|
||||
from alembic import context, op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '93daff872771'
|
||||
down_revision = '564952310b17'
|
||||
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_data():
|
||||
con = op.get_bind()
|
||||
sql = f"update {get_inv()}.computer set user_trusts='t';"
|
||||
con.execute(sql)
|
||||
|
||||
dev_sql = f"select id, hid from {get_inv()}.device;"
|
||||
for d in con.execute(dev_sql):
|
||||
if not d.hid:
|
||||
continue
|
||||
dev_id = d.id
|
||||
chid = hashlib.sha3_256(d.hid.encode('utf-8')).hexdigest()
|
||||
sql = f"update {get_inv()}.device set chid='{chid}' where id={dev_id};"
|
||||
con.execute(sql)
|
||||
|
||||
con.execute(sql)
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column(
|
||||
'computer',
|
||||
sa.Column('user_trusts', sa.Boolean(), default=True, nullable=True),
|
||||
schema=f'{get_inv()}',
|
||||
)
|
||||
|
||||
op.add_column(
|
||||
'device',
|
||||
sa.Column('chid', citext.CIText(), nullable=True),
|
||||
schema=f'{get_inv()}',
|
||||
)
|
||||
|
||||
upgrade_data()
|
||||
|
||||
op.alter_column('computer', 'user_trusts', nullable=False, schema=f'{get_inv()}')
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_column('computer', 'user_trusts', schema=f'{get_inv()}')
|
||||
op.drop_column('device', 'chid', schema=f'{get_inv()}')
|
|
@ -38,7 +38,10 @@ class SnapshotsLog(Thing):
|
|||
db.session.commit()
|
||||
|
||||
def get_status(self):
|
||||
return Severity(self.severity)
|
||||
if self.snapshot:
|
||||
return Severity(self.severity)
|
||||
|
||||
return ''
|
||||
|
||||
def get_device(self):
|
||||
if self.snapshot:
|
||||
|
|
|
@ -548,6 +548,12 @@ class ParseSnapshotLsHw:
|
|||
|
||||
return action
|
||||
|
||||
def get_hid_datas(self):
|
||||
self.device.family = self.get_family()
|
||||
|
||||
def get_family(self):
|
||||
return self.dmi.get("System", [{}])[0].get("Family", '')
|
||||
|
||||
def errors(self, txt=None, severity=Severity.Error):
|
||||
if not txt:
|
||||
return self._errors
|
||||
|
|
|
@ -48,17 +48,14 @@ from sqlalchemy.util import OrderedSet
|
|||
from teal.db import (
|
||||
CASCADE_OWN,
|
||||
INHERIT_COND,
|
||||
IP,
|
||||
POLYMORPHIC_ID,
|
||||
POLYMORPHIC_ON,
|
||||
URL,
|
||||
ResourceNotFound,
|
||||
StrictVersionType,
|
||||
check_lower,
|
||||
check_range,
|
||||
)
|
||||
from teal.enums import Country, Currency, Subdivision
|
||||
from teal.marshmallow import ValidationError
|
||||
from teal.enums import Currency
|
||||
from teal.resource import url_for_resource
|
||||
|
||||
from ereuse_devicehub.db import db
|
||||
|
@ -484,6 +481,9 @@ class EraseBasic(JoinedWithOneDeviceMixin, ActionWithOneDevice):
|
|||
return self.snapshot.device.phid()
|
||||
return ''
|
||||
|
||||
def get_public_name(self):
|
||||
return "Basic"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return '{} on {}.'.format(self.severity, self.date_str)
|
||||
|
||||
|
@ -513,12 +513,32 @@ class EraseSectors(EraseBasic):
|
|||
|
||||
method = 'Badblocks'
|
||||
|
||||
def get_public_name(self):
|
||||
steps_random = 0
|
||||
steps_zeros = 0
|
||||
for s in self.steps:
|
||||
if s.type == 'StepRandom':
|
||||
steps_random += 1
|
||||
if s.type == 'StepZero':
|
||||
steps_zeros += 1
|
||||
if steps_zeros < 1:
|
||||
return "Basic"
|
||||
if 0 < steps_random < 3:
|
||||
return "Baseline"
|
||||
if steps_random > 2:
|
||||
return "Enhanced"
|
||||
|
||||
return "Basic"
|
||||
|
||||
|
||||
class ErasePhysical(EraseBasic):
|
||||
"""The act of physically destroying a data storage unit."""
|
||||
|
||||
method = Column(DBEnum(PhysicalErasureMethod))
|
||||
|
||||
def get_public_name(self):
|
||||
return "Physical"
|
||||
|
||||
|
||||
class Step(db.Model):
|
||||
erasure_id = Column(
|
||||
|
@ -701,6 +721,19 @@ class Snapshot(JoinedWithOneDeviceMixin, ActionWithOneDevice):
|
|||
|
||||
return hdds
|
||||
|
||||
def get_new_device(self):
|
||||
|
||||
if not self.device:
|
||||
return ''
|
||||
|
||||
snapshots = []
|
||||
for s in self.device.actions:
|
||||
if s == self:
|
||||
break
|
||||
if s.type == self.type:
|
||||
snapshots.append(s)
|
||||
return snapshots and 'update' or 'new_device'
|
||||
|
||||
def __str__(self) -> str:
|
||||
return '{}. {} version {}.'.format(self.severity, self.software, self.version)
|
||||
|
||||
|
@ -2009,7 +2042,7 @@ def update_components_action_one(target: ActionWithOneDevice, device: Device, __
|
|||
if isinstance(device, Computer):
|
||||
target.components |= device.components
|
||||
elif isinstance(device, Computer):
|
||||
device.add_mac_to_hid()
|
||||
device.set_hid()
|
||||
|
||||
|
||||
@event.listens_for(
|
||||
|
|
|
@ -64,7 +64,8 @@ def move_json(tmp_snapshots, path_name, user, live=False):
|
|||
class SnapshotMixin:
|
||||
sync = Sync()
|
||||
|
||||
def build(self, snapshot_json=None): # noqa: C901
|
||||
def build(self, snapshot_json=None, create_new_device=False): # noqa: C901
|
||||
self.create_new_device = create_new_device
|
||||
if not snapshot_json:
|
||||
snapshot_json = self.snapshot_json
|
||||
device = snapshot_json.pop('device') # type: Computer
|
||||
|
@ -72,9 +73,7 @@ class SnapshotMixin:
|
|||
if snapshot_json['software'] == (
|
||||
SnapshotSoftware.Workbench or SnapshotSoftware.WorkbenchAndroid
|
||||
):
|
||||
components = snapshot_json.pop('components', None) # type: List[Component]
|
||||
if isinstance(device, Computer) and device.hid:
|
||||
device.add_mac_to_hid(components_snap=components)
|
||||
components = snapshot_json.pop('components', None)
|
||||
snapshot = Snapshot(**snapshot_json)
|
||||
|
||||
# Remove new actions from devices so they don't interfere with sync
|
||||
|
@ -89,7 +88,9 @@ class SnapshotMixin:
|
|||
|
||||
assert not device.actions_one
|
||||
assert all(not c.actions_one for c in components) if components else True
|
||||
db_device, remove_actions = self.sync.run(device, components)
|
||||
db_device, remove_actions = self.sync.run(
|
||||
device, components, self.create_new_device
|
||||
)
|
||||
|
||||
del device # Do not use device anymore
|
||||
snapshot.device = db_device
|
||||
|
@ -117,6 +118,9 @@ class SnapshotMixin:
|
|||
|
||||
self.is_server_erase(snapshot)
|
||||
|
||||
snapshot.device.set_hid()
|
||||
snapshot.device.binding.device.set_hid()
|
||||
|
||||
return snapshot
|
||||
|
||||
def is_server_erase(self, snapshot):
|
||||
|
@ -151,6 +155,30 @@ class SnapshotMixin:
|
|||
uuid = UUID(hw_uuid)
|
||||
return UUID(bytes_le=uuid.bytes)
|
||||
|
||||
def get_fields_extra(self, debug, snapshot_json):
|
||||
if not debug or not isinstance(debug, dict):
|
||||
return
|
||||
|
||||
lshw = debug.get('lshw', {})
|
||||
|
||||
family = lshw.get('configuration', {}).get('family', '')
|
||||
|
||||
snapshot_json['device']['family'] = family
|
||||
|
||||
# lshw_mothers = []
|
||||
# for mt in lshw.get('children', []):
|
||||
# if mt.get('description') == "Motherboard":
|
||||
# lshw_mothers.append(mt)
|
||||
|
||||
# for comp in snapshot_json.get('components', []):
|
||||
# if comp.get('type') != 'Motherboard':
|
||||
# continue
|
||||
# for mt in lshw_mothers:
|
||||
# if comp['serialNumber'] == mt.get('serial', ''):
|
||||
# comp['vendor'] = mt.get('vendor', '')
|
||||
# comp['product'] = mt.get('product', '')
|
||||
# comp['version'] = mt.get('version', '')
|
||||
|
||||
def errors(self, txt=None, severity=Severity.Error, snapshot=None, commit=False):
|
||||
if not txt:
|
||||
return
|
||||
|
@ -187,10 +215,13 @@ class SnapshotView(SnapshotMixin):
|
|||
self.version = snapshot_json.get('version')
|
||||
self.uuid = snapshot_json.get('uuid')
|
||||
self.sid = None
|
||||
system_uuid = self.get_uuid(snapshot_json.pop('debug', None))
|
||||
self.debug = snapshot_json.pop('debug', {})
|
||||
system_uuid = self.get_uuid(self.debug)
|
||||
if system_uuid:
|
||||
snapshot_json['device']['system_uuid'] = system_uuid
|
||||
|
||||
self.get_fields_extra(self.debug, snapshot_json)
|
||||
|
||||
try:
|
||||
self.snapshot_json = resource_def.schema.load(snapshot_json)
|
||||
snapshot = self.build()
|
||||
|
|
|
@ -142,11 +142,14 @@ class LiveView(View):
|
|||
return hid
|
||||
if macs:
|
||||
mac = "-{mac}".format(mac=macs[0])
|
||||
hid += mac
|
||||
# hid += mac
|
||||
return hid
|
||||
|
||||
def live(self, snapshot):
|
||||
"""If the device.allocated == True, then this snapshot create an action live."""
|
||||
for c in snapshot['components']:
|
||||
c.parent = snapshot['device']
|
||||
snapshot['device'].set_hid()
|
||||
hid = self.get_hid(snapshot)
|
||||
if not hid or not Device.query.filter(Device.hid == hid).count():
|
||||
raise ValidationError('Device not exist.')
|
||||
|
|
|
@ -21,27 +21,29 @@ class MetricsMix:
|
|||
"""
|
||||
This is a template of a row.
|
||||
"""
|
||||
return {'type': '',
|
||||
'action_type': 'Status',
|
||||
'document_name': '',
|
||||
'status_receiver': self.status_receiver,
|
||||
'status_supplier': self.status_supplier,
|
||||
'status_receiver_created': '',
|
||||
'status_supplier_created': '',
|
||||
'trade_supplier': '',
|
||||
'trade_receiver': self.act.author.email,
|
||||
'trade_confirmed': '',
|
||||
'trade_weight': 0,
|
||||
'action_create_by': self.action_create_by,
|
||||
'devicehubID': self.devicehub_id,
|
||||
'hid': self.hid,
|
||||
'finalUserCode': '',
|
||||
'numEndUsers': 0,
|
||||
'liveCreate': 0,
|
||||
'usageTimeHdd': self.lifetime,
|
||||
'created': self.act.created,
|
||||
'start': '',
|
||||
'usageTimeAllocate': 0}
|
||||
return {
|
||||
'type': '',
|
||||
'action_type': 'Status',
|
||||
'document_name': '',
|
||||
'status_receiver': self.status_receiver,
|
||||
'status_supplier': self.status_supplier,
|
||||
'status_receiver_created': '',
|
||||
'status_supplier_created': '',
|
||||
'trade_supplier': '',
|
||||
'trade_receiver': self.act.author.email,
|
||||
'trade_confirmed': '',
|
||||
'trade_weight': 0,
|
||||
'action_create_by': self.action_create_by,
|
||||
'devicehubID': self.devicehub_id,
|
||||
'hid': self.hid,
|
||||
'finalUserCode': '',
|
||||
'numEndUsers': 0,
|
||||
'liveCreate': 0,
|
||||
'usageTimeHdd': self.lifetime,
|
||||
'created': self.act.created,
|
||||
'start': '',
|
||||
'usageTimeAllocate': 0,
|
||||
}
|
||||
|
||||
def get_metrics(self):
|
||||
"""
|
||||
|
@ -57,7 +59,7 @@ class Metrics(MetricsMix):
|
|||
self.device = kwargs.pop('device')
|
||||
self.actions = copy.copy(self.device.actions)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.hid = self.device.hid
|
||||
self.hid = self.device.chid
|
||||
self.devicehub_id = self.device.devicehub_id
|
||||
|
||||
def get_action_status(self):
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import copy
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import uuid
|
||||
from contextlib import suppress
|
||||
from fractions import Fraction
|
||||
from itertools import chain
|
||||
|
@ -8,7 +12,8 @@ from typing import Dict, List, Set
|
|||
|
||||
from boltons import urlutils
|
||||
from citext import CIText
|
||||
from ereuse_utils.naming import HID_CONVERSION_DOC, Naming
|
||||
from ereuse_utils.naming import HID_CONVERSION_DOC
|
||||
from flask import current_app as app
|
||||
from flask import g, request
|
||||
from more_itertools import unique_everseen
|
||||
from sqlalchemy import BigInteger, Boolean, Column
|
||||
|
@ -181,6 +186,8 @@ class Device(Thing):
|
|||
dhid_bk = db.Column(db.CIText(), nullable=True, unique=False)
|
||||
phid_bk = db.Column(db.CIText(), nullable=True, unique=False)
|
||||
active = db.Column(Boolean, default=True)
|
||||
family = db.Column(db.CIText())
|
||||
chid = db.Column(db.CIText())
|
||||
|
||||
_NON_PHYSICAL_PROPS = {
|
||||
'id',
|
||||
|
@ -201,6 +208,7 @@ class Device(Thing):
|
|||
'production_date',
|
||||
'variant',
|
||||
'version',
|
||||
'family',
|
||||
'sku',
|
||||
'image',
|
||||
'allocated',
|
||||
|
@ -209,6 +217,11 @@ class Device(Thing):
|
|||
'active',
|
||||
'phid_bk',
|
||||
'dhid_bk',
|
||||
'chid',
|
||||
'user_trusts',
|
||||
'chassis',
|
||||
'transfer_state',
|
||||
'receiver_id',
|
||||
}
|
||||
|
||||
__table_args__ = (
|
||||
|
@ -254,16 +267,17 @@ class Device(Thing):
|
|||
"""
|
||||
actions_multiple = copy.copy(self.actions_multiple)
|
||||
actions_one = copy.copy(self.actions_one)
|
||||
actions = []
|
||||
|
||||
for ac in actions_multiple:
|
||||
ac.real_created = ac.actions_device[0].created
|
||||
actions.append(ac)
|
||||
|
||||
for ac in actions_one:
|
||||
ac.real_created = ac.created
|
||||
actions.append(ac)
|
||||
|
||||
return sorted(
|
||||
chain(actions_multiple, actions_one), key=lambda x: x.real_created
|
||||
)
|
||||
return sorted(actions, key=lambda x: x.real_created)
|
||||
|
||||
@property
|
||||
def problems(self):
|
||||
|
@ -662,6 +676,12 @@ class Device(Thing):
|
|||
return args
|
||||
|
||||
def get_lots_for_template(self):
|
||||
if self.binding:
|
||||
return self.binding.device.get_lots_for_template()
|
||||
|
||||
if not self.lots and hasattr(self, 'parent') and self.parent:
|
||||
return self.parent.get_lots_for_template()
|
||||
|
||||
lots = []
|
||||
for lot in self.lots:
|
||||
if lot.is_incoming:
|
||||
|
@ -742,12 +762,71 @@ class Device(Thing):
|
|||
|
||||
return ""
|
||||
|
||||
def set_hid(self):
|
||||
with suppress(TypeError):
|
||||
self.hid = Naming.hid(
|
||||
self.type, self.manufacturer, self.model, self.serial_number
|
||||
def get_exist_untrusted_device(self):
|
||||
if isinstance(self, Computer):
|
||||
if not self.system_uuid:
|
||||
return True
|
||||
|
||||
return (
|
||||
Computer.query.filter_by(
|
||||
hid=self.hid,
|
||||
user_trusts=False,
|
||||
owner_id=g.user.id,
|
||||
active=True,
|
||||
placeholder=None,
|
||||
).first()
|
||||
or False
|
||||
)
|
||||
|
||||
return False
|
||||
|
||||
def get_from_db(self):
|
||||
if 'property_hid' in app.blueprints.keys():
|
||||
try:
|
||||
from modules.device.utils import get_from_db
|
||||
|
||||
return get_from_db(self)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not self.hid:
|
||||
return
|
||||
|
||||
return Device.query.filter_by(
|
||||
hid=self.hid,
|
||||
owner_id=g.user.id,
|
||||
active=True,
|
||||
placeholder=None,
|
||||
).first()
|
||||
|
||||
def set_hid(self):
|
||||
if 'property_hid' in app.blueprints.keys():
|
||||
try:
|
||||
from modules.device.utils import set_hid
|
||||
|
||||
self.hid = set_hid(self)
|
||||
self.set_chid()
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.hid = "{}-{}-{}-{}".format(
|
||||
self._clean_string(self.type),
|
||||
self._clean_string(self.manufacturer),
|
||||
self._clean_string(self.model),
|
||||
self._clean_string(self.serial_number),
|
||||
).lower()
|
||||
self.set_chid()
|
||||
|
||||
def _clean_string(self, s):
|
||||
if not s:
|
||||
return ''
|
||||
return s.replace(' ', '_')
|
||||
|
||||
def set_chid(self):
|
||||
if self.hid:
|
||||
self.chid = hashlib.sha3_256(self.hid.encode()).hexdigest()
|
||||
|
||||
def last_action_of(self, *types):
|
||||
"""Gets the last action of the given types.
|
||||
|
||||
|
@ -826,6 +905,141 @@ class Device(Thing):
|
|||
}
|
||||
return types.get(self.type, '')
|
||||
|
||||
def unreliable(self):
|
||||
self.user_trusts = False
|
||||
i = 0
|
||||
snapshot1 = None
|
||||
snapshots = {}
|
||||
|
||||
for ac in self.actions:
|
||||
if ac.type == 'Snapshot':
|
||||
if i == 0:
|
||||
snapshot1 = ac
|
||||
if i > 0:
|
||||
snapshots[ac] = self.get_snapshot_file(ac)
|
||||
i += 1
|
||||
|
||||
if not snapshot1:
|
||||
return
|
||||
|
||||
self.create_new_device(snapshots.values(), user_trusts=self.user_trusts)
|
||||
self.remove_snapshot(snapshots.keys())
|
||||
|
||||
return
|
||||
|
||||
def get_snapshot_file(self, action):
|
||||
uuid = action.uuid
|
||||
user = g.user.email
|
||||
name_file = f"*_{user}_{uuid}.json"
|
||||
tmp_snapshots = app.config['TMP_SNAPSHOTS']
|
||||
path_dir_base = os.path.join(tmp_snapshots, user)
|
||||
|
||||
for _file in pathlib.Path(path_dir_base).glob(name_file):
|
||||
with open(_file) as file_snapshot:
|
||||
snapshot = file_snapshot.read()
|
||||
return json.loads(snapshot)
|
||||
|
||||
def create_new_device(self, snapshots, user_trusts=True):
|
||||
from ereuse_devicehub.inventory.forms import UploadSnapshotForm
|
||||
|
||||
new_snapshots = []
|
||||
for snapshot in snapshots:
|
||||
snapshot['uuid'] = str(uuid.uuid4())
|
||||
filename = "{}.json".format(snapshot['uuid'])
|
||||
new_snapshots.append((filename, snapshot))
|
||||
|
||||
form = UploadSnapshotForm()
|
||||
form.result = {}
|
||||
form.snapshots = new_snapshots
|
||||
form.create_new_devices = True
|
||||
form.save(commit=False, user_trusts=user_trusts)
|
||||
|
||||
def remove_snapshot(self, snapshots):
|
||||
from ereuse_devicehub.parser.models import SnapshotsLog
|
||||
|
||||
for ac in snapshots:
|
||||
for slog in SnapshotsLog.query.filter_by(snapshot=ac):
|
||||
slog.snapshot_id = None
|
||||
slog.snapshot_uuid = None
|
||||
db.session.delete(ac)
|
||||
|
||||
def remove_devices(self, devices):
|
||||
from ereuse_devicehub.parser.models import SnapshotsLog
|
||||
|
||||
for dev in devices:
|
||||
for ac in dev.actions:
|
||||
if ac.type != 'Snapshot':
|
||||
continue
|
||||
for slog in SnapshotsLog.query.filter_by(snapshot=ac):
|
||||
slog.snapshot_id = None
|
||||
slog.snapshot_uuid = None
|
||||
|
||||
for c in dev.components:
|
||||
c.parent_id = None
|
||||
|
||||
for tag in dev.tags:
|
||||
tag.device_id = None
|
||||
|
||||
placeholder = dev.binding or dev.placeholder
|
||||
if placeholder:
|
||||
db.session.delete(placeholder.binding)
|
||||
db.session.delete(placeholder.device)
|
||||
db.session.delete(placeholder)
|
||||
|
||||
def reliable(self):
|
||||
computers = Computer.query.filter_by(
|
||||
hid=self.hid,
|
||||
owner_id=g.user.id,
|
||||
active=True,
|
||||
placeholder=None,
|
||||
).order_by(Device.created.asc())
|
||||
|
||||
i = 0
|
||||
computer1 = None
|
||||
computers_to_remove = []
|
||||
for d in computers:
|
||||
if i == 0:
|
||||
d.user_trusts = True
|
||||
computer1 = d
|
||||
i += 1
|
||||
continue
|
||||
|
||||
computers_to_remove.append(d)
|
||||
|
||||
self.remove_devices(computers_to_remove)
|
||||
if not computer1:
|
||||
return
|
||||
|
||||
snapshot1 = None
|
||||
for ac in computer1.actions_one:
|
||||
if ac.type == 'Snapshot':
|
||||
snapshot1 = ac
|
||||
break
|
||||
|
||||
if not snapshot1:
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
def get_last_incoming_lot(self):
|
||||
lots = list(self.lots)
|
||||
if hasattr(self, "orphan") and self.orphan:
|
||||
lots = list(self.lots)
|
||||
if self.binding:
|
||||
lots = list(self.binding.device.lots)
|
||||
|
||||
elif hasattr(self, "parent") and self.parent:
|
||||
lots = list(self.parent.lots)
|
||||
if self.parent.binding:
|
||||
lots = list(self.parent.binding.device.lots)
|
||||
|
||||
lots = sorted(lots, key=lambda x: x.created)
|
||||
lots.reverse()
|
||||
for lot in lots:
|
||||
if lot.is_incoming:
|
||||
return lot
|
||||
return None
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.id < other.id
|
||||
|
||||
|
@ -1026,6 +1240,7 @@ class Computer(Device):
|
|||
receiver_id = db.Column(UUID(as_uuid=True), db.ForeignKey(User.id), nullable=True)
|
||||
receiver = db.relationship(User, primaryjoin=receiver_id == User.id)
|
||||
system_uuid = db.Column(UUID(as_uuid=True), nullable=True)
|
||||
user_trusts = db.Column(Boolean(), default=True)
|
||||
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
if args:
|
||||
|
|
|
@ -120,6 +120,7 @@ class Device(Thing):
|
|||
dhid = SanitizedStr(
|
||||
data_key='devicehubID', description=m.Device.devicehub_id.comment
|
||||
)
|
||||
family = SanitizedStr(validate=Length(max=STR_BIG_SIZE))
|
||||
|
||||
@pre_load
|
||||
def from_actions_to_actions_one(self, data: dict):
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import copy
|
||||
import difflib
|
||||
from contextlib import suppress
|
||||
from itertools import groupby
|
||||
from typing import Iterable, Set
|
||||
|
||||
|
@ -23,28 +22,24 @@ from ereuse_devicehub.resources.device.models import (
|
|||
)
|
||||
from ereuse_devicehub.resources.tag.model import Tag
|
||||
|
||||
DEVICES_ALLOW_DUPLICITY = [
|
||||
'RamModule',
|
||||
'Display',
|
||||
'SoundCard',
|
||||
'Battery',
|
||||
'Camera',
|
||||
'GraphicCard',
|
||||
]
|
||||
|
||||
err_motherboard = "Error: We have detected that a there is a device"
|
||||
err_motherboard += " in your inventory with this system UUID. "
|
||||
err_motherboard += "We proceed to block this snapshot to prevent its"
|
||||
err_motherboard += " information from being updated incorrectly."
|
||||
err_motherboard += " The solution we offer you to inventory this device "
|
||||
err_motherboard += "is to do it by creating a placeholder."
|
||||
# DEVICES_ALLOW_DUPLICITY = [
|
||||
# 'RamModule',
|
||||
# 'Display',
|
||||
# 'SoundCard',
|
||||
# 'Battery',
|
||||
# 'Camera',
|
||||
# 'GraphicCard',
|
||||
# ]
|
||||
|
||||
|
||||
class Sync:
|
||||
"""Synchronizes the device and components with the database."""
|
||||
|
||||
def run(
|
||||
self, device: Device, components: Iterable[Component] or None
|
||||
self,
|
||||
device: Device,
|
||||
components: Iterable[Component] or None,
|
||||
create_new_device=False,
|
||||
) -> (Device, OrderedSet):
|
||||
"""Synchronizes the device and components with the database.
|
||||
|
||||
|
@ -76,17 +71,11 @@ class Sync:
|
|||
of the passed-in components.
|
||||
2. A list of Add / Remove (not yet added to session).
|
||||
"""
|
||||
db_device = self.execute_register(device)
|
||||
motherboard = None
|
||||
if components:
|
||||
for c in components:
|
||||
if c.type == "Motherboard":
|
||||
motherboard = c
|
||||
|
||||
if motherboard:
|
||||
for c in db_device.components:
|
||||
if c.type == "Motherboard" and motherboard.hid != c.hid:
|
||||
raise ValidationError(err_motherboard)
|
||||
device.components = OrderedSet(components)
|
||||
device.set_hid()
|
||||
device.components = OrderedSet()
|
||||
db_device = self.execute_register(device, create_new_device)
|
||||
|
||||
db_components, actions = OrderedSet(), OrderedSet()
|
||||
if components is not None: # We have component info (see above)
|
||||
|
@ -94,12 +83,9 @@ class Sync:
|
|||
# Until a good reason is given, we synthetically forbid
|
||||
# non-computers with components
|
||||
raise ValidationError('Only computers can have components.')
|
||||
blacklist = set() # type: Set[int]
|
||||
not_new_components = set()
|
||||
for component in components:
|
||||
db_component, is_new = self.execute_register_component(
|
||||
component, blacklist, parent=db_device
|
||||
)
|
||||
db_component, is_new = self.execute_register_component(component)
|
||||
db_components.add(db_component)
|
||||
if not is_new:
|
||||
not_new_components.add(db_component)
|
||||
|
@ -110,9 +96,7 @@ class Sync:
|
|||
self.create_placeholder(db_device)
|
||||
return db_device, actions
|
||||
|
||||
def execute_register_component(
|
||||
self, component: Component, blacklist: Set[int], parent: Computer
|
||||
):
|
||||
def execute_register_component(self, component: Component):
|
||||
"""Synchronizes one component to the DB.
|
||||
|
||||
This method is a specialization of :meth:`.execute_register`
|
||||
|
@ -134,41 +118,27 @@ class Sync:
|
|||
- A flag stating if the device is new or it already
|
||||
existed in the DB.
|
||||
"""
|
||||
# if device.serial_number == 'b8oaas048286':
|
||||
assert inspect(component).transient, 'Component should not be synced from DB'
|
||||
# if not is a DataStorage, then need build a new one
|
||||
if component.t in DEVICES_ALLOW_DUPLICITY:
|
||||
if not isinstance(component, DataStorage):
|
||||
db.session.add(component)
|
||||
is_new = True
|
||||
return component, is_new
|
||||
|
||||
# if not, then continue with the traditional behaviour
|
||||
try:
|
||||
if component.hid:
|
||||
db_component = Device.query.filter_by(
|
||||
hid=component.hid, owner_id=g.user.id, placeholder=None
|
||||
).one()
|
||||
assert isinstance(
|
||||
db_component, Device
|
||||
), '{} must be a component'.format(db_component)
|
||||
else:
|
||||
# Is there a component similar to ours?
|
||||
db_component = component.similar_one(parent, blacklist)
|
||||
# We blacklist this component so we
|
||||
# ensure we don't get it again for another component
|
||||
# with the same physical properties
|
||||
blacklist.add(db_component.id)
|
||||
except ResourceNotFound:
|
||||
db_component = None
|
||||
|
||||
if component.hid:
|
||||
db_component = Device.query.filter_by(
|
||||
hid=component.hid, owner_id=g.user.id, placeholder=None, active=True
|
||||
).first()
|
||||
is_new = False
|
||||
if not db_component:
|
||||
db.session.add(component)
|
||||
# db.session.flush()
|
||||
db_component = component
|
||||
is_new = True
|
||||
else:
|
||||
self.merge(component, db_component)
|
||||
is_new = False
|
||||
return db_component, is_new
|
||||
|
||||
def execute_register(self, device: Device) -> Device:
|
||||
def execute_register(self, device: Device, create_new_device=False) -> Device:
|
||||
"""Synchronizes one device to the DB.
|
||||
|
||||
This method tries to get an existing device using the HID
|
||||
|
@ -195,84 +165,24 @@ class Sync:
|
|||
:raise DatabaseError: Any other error from the DB.
|
||||
:return: The synced device from the db with the tags linked.
|
||||
"""
|
||||
assert inspect(device).transient, 'Device cannot be already synced from DB'
|
||||
assert all(
|
||||
inspect(tag).transient for tag in device.tags
|
||||
), 'Tags cannot be synced from DB'
|
||||
db_device = None
|
||||
if isinstance(device, Computer):
|
||||
# first search by uuid
|
||||
if device.system_uuid:
|
||||
with suppress(ResourceNotFound):
|
||||
db_device = Computer.query.filter_by(
|
||||
system_uuid=device.system_uuid,
|
||||
owner_id=g.user.id,
|
||||
active=True,
|
||||
placeholder=None,
|
||||
).one()
|
||||
# if no there are any Computer by uuid search by hid
|
||||
if not db_device and device.hid:
|
||||
with suppress(ResourceNotFound):
|
||||
db_device = Device.query.filter_by(
|
||||
hid=device.hid,
|
||||
owner_id=g.user.id,
|
||||
active=True,
|
||||
placeholder=None,
|
||||
).one()
|
||||
elif device.hid:
|
||||
with suppress(ResourceNotFound):
|
||||
db_device = Device.query.filter_by(
|
||||
hid=device.hid, owner_id=g.user.id, active=True, placeholder=None
|
||||
).one()
|
||||
db_device = device.get_from_db()
|
||||
|
||||
if db_device and db_device.allocated:
|
||||
raise ResourceNotFound('device is actually allocated {}'.format(device))
|
||||
|
||||
try:
|
||||
tags = {
|
||||
Tag.from_an_id(tag.id).one() for tag in device.tags
|
||||
} # type: Set[Tag]
|
||||
except ResourceNotFound:
|
||||
raise ResourceNotFound('tag you are linking to device {}'.format(device))
|
||||
linked_tags = {tag for tag in tags if tag.device_id} # type: Set[Tag]
|
||||
if linked_tags:
|
||||
sample_tag = next(iter(linked_tags))
|
||||
for tag in linked_tags:
|
||||
if tag.device_id != sample_tag.device_id:
|
||||
raise MismatchBetweenTags(
|
||||
tag, sample_tag
|
||||
) # Tags linked to different devices
|
||||
if db_device: # Device from hid
|
||||
if (
|
||||
sample_tag.device_id != db_device.id
|
||||
): # Device from hid != device from tags
|
||||
raise MismatchBetweenTagsAndHid(db_device.id, db_device.hid)
|
||||
else: # There was no device from hid
|
||||
if sample_tag.device.physical_properties != device.physical_properties:
|
||||
# Incoming physical props of device != props from tag's device
|
||||
# which means that the devices are not the same
|
||||
raise MismatchBetweenProperties(
|
||||
sample_tag.device.physical_properties,
|
||||
device.physical_properties,
|
||||
)
|
||||
db_device = sample_tag.device
|
||||
|
||||
if db_device: # Device from hid or tags
|
||||
self.merge(device, db_device)
|
||||
else: # Device is new and tags are not linked to a device
|
||||
if not db_device or create_new_device:
|
||||
device.tags.clear() # We don't want to add the transient dummy tags
|
||||
if create_new_device or device.get_exist_untrusted_device():
|
||||
device.user_trusts = False
|
||||
db.session.add(device)
|
||||
db_device = device
|
||||
db_device.tags |= (
|
||||
tags # Union of tags the device had plus the (potentially) new ones
|
||||
)
|
||||
try:
|
||||
db.session.flush()
|
||||
except IntegrityError as e:
|
||||
# Manage 'one tag per organization' unique constraint
|
||||
if 'One tag per organization' in e.args[0]:
|
||||
# todo test for this
|
||||
id = int(e.args[0][135 : e.args[0].index(',', 135)])
|
||||
id = int(e.args[0][135 : e.args[0].index(',', 135)]) # noqa: E203
|
||||
raise ValidationError(
|
||||
'The device is already linked to tag {} '
|
||||
'from the same organization.'.format(id),
|
||||
|
@ -283,29 +193,6 @@ class Sync:
|
|||
assert db_device is not None
|
||||
return db_device
|
||||
|
||||
@staticmethod
|
||||
def merge(device: Device, db_device: Device):
|
||||
"""Copies the physical properties of the device to the db_device.
|
||||
|
||||
This method mutates db_device.
|
||||
"""
|
||||
if db_device.owner_id != g.user.id:
|
||||
return
|
||||
|
||||
if device.placeholder and not db_device.placeholder:
|
||||
return
|
||||
|
||||
for field_name, value in device.physical_properties.items():
|
||||
if value is not None:
|
||||
setattr(db_device, field_name, value)
|
||||
|
||||
# if device.system_uuid and db_device.system_uuid and device.system_uuid != db_device.system_uuid:
|
||||
# TODO @cayop send error to sentry.io
|
||||
# there are 2 computers duplicate get db_device for hid
|
||||
|
||||
if hasattr(device, 'system_uuid') and device.system_uuid:
|
||||
db_device.system_uuid = device.system_uuid
|
||||
|
||||
@staticmethod
|
||||
def create_placeholder(device: Device):
|
||||
"""If the device is new, we need create automaticaly a new placeholder"""
|
||||
|
|
|
@ -311,7 +311,7 @@ class DeviceMergeView(View):
|
|||
setattr(self.base_device, field_name, value)
|
||||
|
||||
self.base_device.hid = self.with_device.hid
|
||||
self.base_device.add_mac_to_hid()
|
||||
self.base_device.set_hid()
|
||||
|
||||
|
||||
class ManufacturerView(View):
|
||||
|
|
|
@ -285,7 +285,7 @@ class DeviceRow(BaseDeviceRow):
|
|||
self['Tag {} ID'.format(i)] = tag.id
|
||||
self['Tag {} Organization'.format(i)] = tag.org.name
|
||||
|
||||
self['Device Hardware ID'] = device.hid
|
||||
self['Device Hardware ID'] = device.chid
|
||||
self['Device Type'] = device.t
|
||||
if isinstance(device, d.Computer) and not device.placeholder:
|
||||
self['Device Chassis'] = device.chassis.name
|
||||
|
@ -433,12 +433,12 @@ class DeviceRow(BaseDeviceRow):
|
|||
]
|
||||
erasure = erasures[-1] if erasures else None
|
||||
if not erasure:
|
||||
self['Erasure {} {}'.format(ctype, i)] = none2str(component.hid)
|
||||
self['Erasure {} {}'.format(ctype, i)] = none2str(component.chid)
|
||||
serial_number = none2str(component.serial_number)
|
||||
self['Erasure {} {} Serial Number'.format(ctype, i)] = serial_number
|
||||
self['Erasure {} {} Size (MB)'.format(ctype, i)] = none2str(component.size)
|
||||
elif hasattr(erasure, 'type') and erasure.type == 'DataWipe':
|
||||
self['Erasure {} {}'.format(ctype, i)] = none2str(component.hid)
|
||||
self['Erasure {} {}'.format(ctype, i)] = none2str(component.chid)
|
||||
serial_number = none2str(component.serial_number)
|
||||
self['Erasure {} {} Serial Number'.format(ctype, i)] = serial_number
|
||||
self['Erasure {} {} Size (MB)'.format(ctype, i)] = none2str(component.size)
|
||||
|
@ -448,7 +448,7 @@ class DeviceRow(BaseDeviceRow):
|
|||
erasure.document.url and erasure.document.url.to_text() or ''
|
||||
)
|
||||
else:
|
||||
self['Erasure {} {}'.format(ctype, i)] = none2str(component.hid)
|
||||
self['Erasure {} {}'.format(ctype, i)] = none2str(component.chid)
|
||||
serial_number = none2str(component.serial_number)
|
||||
self['Erasure {} {} Serial Number'.format(ctype, i)] = serial_number
|
||||
self['Erasure {} {} Size (MB)'.format(ctype, i)] = none2str(component.size)
|
||||
|
|
|
@ -334,6 +334,12 @@ class Severity(IntEnum):
|
|||
def __format__(self, format_spec):
|
||||
return str(self)
|
||||
|
||||
def get_public_name(self):
|
||||
if self.value == 3:
|
||||
return "Failed"
|
||||
|
||||
return "Success"
|
||||
|
||||
|
||||
class PhysicalErasureMethod(Enum):
|
||||
"""Methods of physically erasing the data-storage, usually
|
||||
|
|
|
@ -93,6 +93,10 @@ class Lot(Thing):
|
|||
)
|
||||
receiver = db.relationship(User, primaryjoin=receiver_address == User.email)
|
||||
|
||||
# __table_args__ = (
|
||||
# {'schema': 'dbtest'},
|
||||
# )
|
||||
|
||||
def __init__(
|
||||
self, name: str, closed: bool = closed.default.arg, description: str = None
|
||||
) -> None:
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
from uuid import uuid4
|
||||
|
||||
from flask import current_app as app
|
||||
from flask import g
|
||||
from flask_login import UserMixin
|
||||
from sqlalchemy import BigInteger, Boolean, Column, Sequence
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy_utils import EmailType, PasswordType
|
||||
from teal.db import IntEnum
|
||||
from teal.db import CASCADE_OWN, URL, IntEnum
|
||||
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.resources.enums import SessionType
|
||||
|
@ -119,3 +120,28 @@ class Session(Thing):
|
|||
|
||||
def __str__(self) -> str:
|
||||
return '{0.token}'.format(self)
|
||||
|
||||
|
||||
class SanitizationEntity(Thing):
|
||||
id = db.Column(BigInteger, primary_key=True)
|
||||
company_name = db.Column(db.String, nullable=True)
|
||||
location = db.Column(db.String, nullable=True)
|
||||
# logo = db.Column(db.String, nullable=True)
|
||||
logo = db.Column(URL(), nullable=True)
|
||||
responsable_person = db.Column(db.String, nullable=True)
|
||||
supervisor_person = db.Column(db.String, nullable=True)
|
||||
user_id = db.Column(
|
||||
db.UUID(as_uuid=True),
|
||||
db.ForeignKey(User.id),
|
||||
default=lambda: g.user.id,
|
||||
)
|
||||
user = db.relationship(
|
||||
User,
|
||||
backref=db.backref(
|
||||
'sanitization_entity', lazy=True, uselist=False, cascade=CASCADE_OWN
|
||||
),
|
||||
primaryjoin=user_id == User.id,
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return '{0.company_name}'.format(self)
|
||||
|
|
|
@ -1,182 +0,0 @@
|
|||
.dataTable-wrapper.no-header .dataTable-container {
|
||||
border-top: 1px solid #d9d9d9;
|
||||
}
|
||||
|
||||
.dataTable-wrapper.no-footer .dataTable-container {
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
}
|
||||
|
||||
.dataTable-top,
|
||||
.dataTable-bottom {
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
.dataTable-top > nav:first-child,
|
||||
.dataTable-top > div:first-child,
|
||||
.dataTable-bottom > nav:first-child,
|
||||
.dataTable-bottom > div:first-child {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.dataTable-top > nav:last-child,
|
||||
.dataTable-top > div:last-child,
|
||||
.dataTable-bottom > nav:last-child,
|
||||
.dataTable-bottom > div:last-child {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.dataTable-selector {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.dataTable-input {
|
||||
padding: 6px 12px;
|
||||
}
|
||||
|
||||
.dataTable-info {
|
||||
margin: 7px 0;
|
||||
}
|
||||
|
||||
/* PAGER */
|
||||
.dataTable-pagination ul {
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.dataTable-pagination li {
|
||||
list-style: none;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.dataTable-pagination a {
|
||||
border: 1px solid transparent;
|
||||
float: left;
|
||||
margin-left: 2px;
|
||||
padding: 6px 12px;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.dataTable-pagination a:hover {
|
||||
background-color: #d9d9d9;
|
||||
}
|
||||
|
||||
.dataTable-pagination .active a,
|
||||
.dataTable-pagination .active a:focus,
|
||||
.dataTable-pagination .active a:hover {
|
||||
background-color: #d9d9d9;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.dataTable-pagination .ellipsis a,
|
||||
.dataTable-pagination .disabled a,
|
||||
.dataTable-pagination .disabled a:focus,
|
||||
.dataTable-pagination .disabled a:hover {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.dataTable-pagination .disabled a,
|
||||
.dataTable-pagination .disabled a:focus,
|
||||
.dataTable-pagination .disabled a:hover {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.dataTable-pagination .pager a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* TABLE */
|
||||
.dataTable-table {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
border-collapse: separate;
|
||||
}
|
||||
|
||||
.dataTable-table > tbody > tr > td,
|
||||
.dataTable-table > tbody > tr > th,
|
||||
.dataTable-table > tfoot > tr > td,
|
||||
.dataTable-table > tfoot > tr > th,
|
||||
.dataTable-table > thead > tr > td,
|
||||
.dataTable-table > thead > tr > th {
|
||||
vertical-align: top;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
.dataTable-table > thead > tr > th {
|
||||
vertical-align: bottom;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
}
|
||||
|
||||
.dataTable-table > tfoot > tr > th {
|
||||
vertical-align: bottom;
|
||||
text-align: left;
|
||||
border-top: 1px solid #d9d9d9;
|
||||
}
|
||||
|
||||
.dataTable-table th {
|
||||
vertical-align: bottom;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.dataTable-table th a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.dataTable-sorter {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dataTable-sorter::before,
|
||||
.dataTable-sorter::after {
|
||||
content: "";
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.dataTable-sorter::before {
|
||||
border-top: 4px solid #000;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.dataTable-sorter::after {
|
||||
border-bottom: 4px solid #000;
|
||||
border-top: 4px solid transparent;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.asc .dataTable-sorter::after,
|
||||
.desc .dataTable-sorter::before {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.dataTables-empty {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dataTable-top::after, .dataTable-bottom::after {
|
||||
clear: both;
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
|
||||
table.dataTable-table:focus tr.dataTable-cursor > td:first-child {
|
||||
border-left: 3px blue solid;
|
||||
}
|
||||
|
||||
table.dataTable-table:focus {
|
||||
outline: solid 1px black;
|
||||
outline-offset: -1px;
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -19,12 +19,14 @@
|
|||
|
||||
<!-- JS Files -->
|
||||
<script src="{{ url_for('static', filename='js/jquery-3.6.0.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/simple-datatables-5.0.3.js') }}"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@5.0.3" type="text/javascript"></script>
|
||||
|
||||
|
||||
|
||||
<!-- Vendor CSS Files -->
|
||||
<link href="{{ url_for('static', filename='vendor/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='vendor/bootstrap-icons/bootstrap-icons.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/simple-datatables.css') }}" rel="stylesheet" type="text/css">
|
||||
<link href="https://cdn.jsdelivr.net/npm/simple-datatables@5.0.3/dist/style.css" rel="stylesheet" type="text/css">
|
||||
|
||||
|
||||
<!-- Template Main CSS File -->
|
||||
|
|
|
@ -34,7 +34,10 @@
|
|||
<!-- Bordered Tabs -->
|
||||
<ul class="nav nav-tabs nav-tabs-bordered">
|
||||
<li class="nav-item">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#profile-change-password">Change Password</button>
|
||||
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#profile-change-password">Change Password</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#profile-sanitization-entity">Sanitization Entity</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content pt-2">
|
||||
|
@ -65,7 +68,34 @@
|
|||
<button type="submit" class="btn btn-primary">Change Password</button>
|
||||
</div>
|
||||
</form><!-- End Change Password Form -->
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade pt-3" id="profile-sanitization-entity">
|
||||
<!-- Sanitization Entity datas Form -->
|
||||
<form action="{{ url_for('core.set-sanitization') }}" method="post">
|
||||
{% for f in sanitization_form %}
|
||||
{% if f == sanitization_form.csrf_token %}
|
||||
{{ f }}
|
||||
{% else %}
|
||||
<div class="row mb-3">
|
||||
<label class="col-md-4 col-lg-3 col-form-label">{{ f.label }}</label>
|
||||
<div class="col-md-8 col-lg-9">
|
||||
{{ f }}
|
||||
{% if f.errors %}
|
||||
<p class="text-danger">
|
||||
{% for error in f.errors %}
|
||||
{{ error }}<br/>
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<div class="text-center">
|
||||
<button type="submit" class="btn btn-primary">Change sanitization data</button>
|
||||
</div>
|
||||
</form><!-- End Sanitization Entity datas Form -->
|
||||
</div>
|
||||
|
||||
</div><!-- End Bordered Tabs -->
|
||||
|
|
|
@ -93,6 +93,11 @@
|
|||
Receiver Note
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#edit-customer-details">
|
||||
Customer Details
|
||||
</button>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
@ -511,13 +516,13 @@
|
|||
</div>
|
||||
{% if lot and not lot.is_temporary %}
|
||||
<div id="trade-documents-list" class="tab-pane fade trade-documents-list">
|
||||
<div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
|
||||
<a href="{{ url_for('inventory.trade_document_add', lot_id=lot.id)}}" class="btn btn-primary">
|
||||
<i class="bi bi-plus"></i>
|
||||
Add new document
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
|
||||
<a href="{{ url_for('inventory.trade_document_add', lot_id=lot.id)}}" class="btn btn-primary">
|
||||
<i class="bi bi-plus"></i>
|
||||
Add new document
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h5 class="card-title">Documents</h5>
|
||||
<table class="table">
|
||||
|
@ -560,6 +565,15 @@
|
|||
</table>
|
||||
</div>
|
||||
<div id="edit-transfer" class="tab-pane fade edit-transfer">
|
||||
{% if form_transfer.date.data %}
|
||||
<div class="btn-group dropdown ml-1 mt-1" uib-dropdown="">
|
||||
<a href="{{ url_for('inventory.open_transfer', lot_id=lot.id)}}" class="btn btn-primary">
|
||||
<i class="bi bi-plus"></i>
|
||||
Reopen a transfer
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
<h5 class="card-title">Transfer</h5>
|
||||
<form method="post" action="{{ url_for('inventory.edit_transfer', lot_id=lot.id) }}" class="row g-3 needs-validation" novalidate>
|
||||
{{ form_transfer.csrf_token }}
|
||||
|
@ -656,6 +670,37 @@
|
|||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="edit-customer-details" class="tab-pane fade edit-customer-details">
|
||||
<h5 class="card-title">Customer Details</h5>
|
||||
<form method="post" action="{{ url_for('inventory.customer_details', lot_id=lot.id) }}" class="row g-3 needs-validation" novalidate>
|
||||
{{ form_customer_details.csrf_token }}
|
||||
|
||||
{% for field in form_customer_details %}
|
||||
{% if field != form_customer_details.csrf_token %}
|
||||
<div class="col-12">
|
||||
{% if field != form_customer_details.type %}
|
||||
{{ field.label(class_="form-label") }}
|
||||
{{ field }}
|
||||
<small class="text-muted">{{ field.description }}</small>
|
||||
{% if field.errors %}
|
||||
<p class="text-danger">
|
||||
{% for error in field.errors %}
|
||||
{{ error }}<br/>
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<div>
|
||||
<a href="{{ url_for('inventory.lotdevicelist', lot_id=lot.id) }}" class="btn btn-danger">Cancel</a>
|
||||
<button class="btn btn-primary" type="submit">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div><!-- End Bordered Tabs -->
|
||||
|
|
|
@ -1,80 +1,357 @@
|
|||
{% extends "documents/layout.html" %}
|
||||
{% block body %}
|
||||
<div>
|
||||
<h2>Summary</h2>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>S/N Data Storage</th>
|
||||
<th>Type of erasure</th>
|
||||
<th>Result</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for erasure in erasures %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ erasure.device.serial_number.upper() }}
|
||||
</td>
|
||||
<td>
|
||||
{{ erasure.type }}
|
||||
</td>
|
||||
<td>
|
||||
{{ erasure.severity }}
|
||||
</td>
|
||||
<td>
|
||||
{{ erasure.date_str }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="page-break row">
|
||||
<h2>Details</h2>
|
||||
{% for erasure in erasures %}
|
||||
<div class="col-md-6 no-page-break">
|
||||
<h4>{{ erasure.device.__format__('t') }}</h4>
|
||||
<dl>
|
||||
<dt>Data storage:</dt>
|
||||
<dd>{{ erasure.device.__format__('ts') }}</dd>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Data Sanitization Certificate</title>
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<link href="https://stackpath.bootstrapcdn.com/bootswatch/3.3.7/flatly/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
integrity="sha384-+ENW/yibaokMnme+vBLnHMphUYxHs34h9lpdbSLuAwGkOKFRl4C34WkjazBtb7eT"
|
||||
crossorigin="anonymous">
|
||||
<style type="text/css" media="all">
|
||||
@page {
|
||||
size: A4 portrait; /* can use also 'landscape' for orientation */
|
||||
margin: 1.0cm 1.5cm 3.5cm 1.5cm;
|
||||
font-family: "Source Sans Pro", Calibri, Candra, Sans serif;
|
||||
|
||||
<dt>Erasure:</dt>
|
||||
<dd>{{ erasure.__format__('ts') }}</dd>
|
||||
{% if erasure.steps %}
|
||||
<dt>Erasure steps:</dt>
|
||||
<dd>
|
||||
<ol>
|
||||
{% for step in erasure.steps %}
|
||||
<li>{{ step.__format__('') }}</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
{% endfor %}
|
||||
@top {
|
||||
content: element(header);
|
||||
}
|
||||
|
||||
@bottom {
|
||||
content: element(footer);
|
||||
}
|
||||
|
||||
}
|
||||
body {
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
color: black;
|
||||
font-size: 100%;
|
||||
line-height: 1.65;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
header {
|
||||
position: running(header);
|
||||
/*height: 100px;*/
|
||||
font-size: 12px;
|
||||
/* color: #000; */
|
||||
font-family: Arial;
|
||||
width: 100%;
|
||||
/* position: relative;*/
|
||||
}
|
||||
|
||||
footer {
|
||||
position: running(footer);
|
||||
/*height: 150px;*/
|
||||
}
|
||||
|
||||
.body_content {
|
||||
position: relative;
|
||||
page-break-inside: auto;
|
||||
width: 100%;
|
||||
/*overflow: hidden;*/
|
||||
}
|
||||
|
||||
img {max-height: 150px; width: auto;}
|
||||
.company-logo {float: left;}
|
||||
.customer-logo {float: right;}
|
||||
.page-break:not(section:first-of-type) {
|
||||
page-break-before: always
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="page-header">
|
||||
<div class="col" style="background-color: #d5a6bd;">
|
||||
<p style="margin-left: 10px;">{{ date_report }}, {{ software }}</p>
|
||||
</div>
|
||||
<div class="no-page-break">
|
||||
<h2>Glossary</h2>
|
||||
<dl>
|
||||
<dt>Erase Basic</dt>
|
||||
<dd>
|
||||
A software-based fast non-100%-secured way of erasing data storage,
|
||||
using <a href="https://en.wikipedia.org/wiki/Shred_(Unix)">shred</a>.
|
||||
</dd>
|
||||
<dt>Erase Sectors</dt>
|
||||
<dd>
|
||||
A secured-way of erasing data storages, checking sector-by-sector
|
||||
the erasure, using <a href="https://en.wikipedia.org/wiki/Badblocks">badblocks</a>.
|
||||
</dd>
|
||||
</dl>
|
||||
</header>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<img class="company-logo" src="{{ customer_details and customer_details.logo.to_text() or '' }}" />
|
||||
</div>
|
||||
<div class="no-print">
|
||||
<a href="{{ url_pdf }}">Click here to download the PDF.</a>
|
||||
<div class="col-6">
|
||||
<img class="customer-logo" src="{{ my_data and my_data.logo.to_text() }}" />
|
||||
</div>
|
||||
<div class="print-only">
|
||||
<a href="{{ url_for('Document.StampsView', _external=True) }}">Verify on-line the integrity of this document</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container body-content">
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<h1>Data Sanitization Certificate</h1>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<div class="row mt-3">
|
||||
<div class="col-12">
|
||||
<strong>Entity Information</strong>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<table class="body_content">
|
||||
<tbody>
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:20%;">
|
||||
Name:
|
||||
</td>
|
||||
<td style="width:80%;">
|
||||
<span>{{ customer_details and customer_details.company_name or ''}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:20%;">
|
||||
Location:
|
||||
</td>
|
||||
<td style="width:80%;">
|
||||
<span>{{ customer_details and customer_details.location or '' }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" style="padding-top: 20px;">
|
||||
<div class="col-12">
|
||||
<strong>Responsible Sanitization Entity</strong>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<table class="body_content">
|
||||
<tbody>
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:20%;">
|
||||
<span>Name:</span>
|
||||
</td>
|
||||
<td style="width:80%;">
|
||||
<span>{{ my_data and my_data.company_name or '' }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:20%;">
|
||||
<span>Responsible Person</span>
|
||||
</td>
|
||||
<td style="width:80%;">
|
||||
<span>{{ my_data and my_data.responsable_person or '' }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:20%;">
|
||||
<span>Location:</span>
|
||||
</td>
|
||||
<td style="width:80%;">
|
||||
<span>{{ my_data and my_data.location or '' }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" style="padding-top: 20px;">
|
||||
<div class="col-12">
|
||||
<strong>Summary</strong>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<table class="body_content">
|
||||
<tbody>
|
||||
{% if erasure_hosts %}
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:20%;">
|
||||
<span>SNs of sanitization server:</span>
|
||||
</td>
|
||||
<td style="width:80%;">
|
||||
{% for e in erasure_hosts %}
|
||||
{% if e.serial_number %}
|
||||
<span>{{ e.serial_number.upper() }}</span>{% if not loop.last %},{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if n_computers %}
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:20%;">
|
||||
<span>N° of computers:</span>
|
||||
</td>
|
||||
<td style="width:80%;">
|
||||
<span>{{ n_computers }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:20%;">
|
||||
<span>N° of data storage unit(s):</span>
|
||||
</td>
|
||||
<td style="width:80%;">
|
||||
<span>{{ erasures | length }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:20%;">
|
||||
<span>Sanitization result:</span>
|
||||
</td>
|
||||
<td style="width:80%;">
|
||||
<span>{{ result }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" style="padding-top: 20px;">
|
||||
<div class="col-12">
|
||||
<strong>Report Details</strong>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<table class="body_content">
|
||||
<tbody>
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:20%;">
|
||||
<span>Report UUID:</span>
|
||||
</td>
|
||||
<td style="width:80%;">
|
||||
<span>{{ uuid_report }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:20%;">
|
||||
<span>Report Date:</span>
|
||||
</td>
|
||||
<td style="width:80%;">
|
||||
<span>{{ date_report }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:20%;">
|
||||
<span>Software Version:</span>
|
||||
</td>
|
||||
<td style="width:80%;">
|
||||
<span>{{ software }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" style="margin-top:25px;">
|
||||
<div class="col">
|
||||
<p>
|
||||
I hereby declare that the data erasure process has been carried
|
||||
out in accordance with the instructions received.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" style="margin-top:200px;">
|
||||
<div class="col-12">
|
||||
<table class="body_content" style="border-top: 1px solid #000;">
|
||||
<tbody>
|
||||
<tr style="padding-top:5px;">
|
||||
<td style="width:50%; text-align: center;">
|
||||
<span>Data Responsable</span>
|
||||
<br />
|
||||
<span>{{ my_data and my_data.responsable_person or '' }}</span>
|
||||
</td>
|
||||
<td style="width:50%; text-align: center;">
|
||||
<span>Data Supervisor</span>
|
||||
<br />
|
||||
<span>{{ my_data and my_data.supervisor_person or '' }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if erasures %}
|
||||
<div class="row mt-3 page-break">
|
||||
<div class="col">
|
||||
<h1>Summary</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<table class="table" style="width: 100%; text-align: center;">
|
||||
<thead style="border-bottom: 1px solid #000;">
|
||||
<tr>
|
||||
<th scope="col" style="text-align: center;">SN Storage</th>
|
||||
<th scope="col" style="text-align: center;">SN Host</th>
|
||||
<th scope="col" style="text-align: center;">Method</th>
|
||||
<th scope="col" style="text-align: center;">Result</th>
|
||||
<th scope="col" style="text-align: center;">Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for erasure in erasures %}
|
||||
<tr style="border-bottom: 1px dashed #000;">
|
||||
<td>
|
||||
{{ erasure.device.serial_number.upper() }}
|
||||
</td>
|
||||
<td>
|
||||
{{ erasure.parent.serial_number.upper() }}
|
||||
</td>
|
||||
<td>
|
||||
{{ erasure.get_public_name() }}
|
||||
</td>
|
||||
<td>
|
||||
{{ erasure.severity.get_public_name() }}
|
||||
</td>
|
||||
<td>
|
||||
{{ erasure.date_str }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% for erasure in erasures %}
|
||||
<div class="container mb-5 page-break">
|
||||
<h4>{{ erasure.device.serial_number.upper() }}</h4>
|
||||
<dl>
|
||||
<dt>Data storage:</dt>
|
||||
<dd>{{ erasure.device.__format__('ts') }}</dd>
|
||||
|
||||
{% if erasure.parent %}
|
||||
<dt>Computer where was erase:</dt>
|
||||
<dd>Title: {{ erasure.parent.__format__('ts') }}</dd>
|
||||
<dd>DevicehubID: {{ erasure.parent.dhid }}</dd>
|
||||
<dd>Hid: {{ erasure.parent.hid }}</dd>
|
||||
<dd>Tags: {{ erasure.parent.tags }}</dd>
|
||||
|
||||
{% if erasure.device.parent %}
|
||||
<dt>Computer where it resides:</dt>
|
||||
<dd>Title: {{ erasure.device.parent.__format__('ts') }}</dd>
|
||||
<dd>DevicehubID: {{ erasure.device.parent.dhid }}</dd>
|
||||
<dd>Hid: {{ erasure.device.parent.hid }}</dd>
|
||||
<dd>Tags: {{ erasure.device.parent.tags }}</dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<dt>Erasure:</dt>
|
||||
<dd>{{ erasure.__format__('ts') }}</dd>
|
||||
{% if erasure.steps %}
|
||||
<dt>Erasure steps:</dt>
|
||||
<dd>
|
||||
<ol>
|
||||
{% for step in erasure.steps %}
|
||||
<li>{{ step.__format__('') }}</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<footer class="page-header">
|
||||
<div>
|
||||
<a href="{{ url_for('Document.StampsView', _external=True) }}">Verify on-line the integrity of this document</a>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
|
@ -187,9 +187,9 @@
|
|||
{% endif %}
|
||||
{{ ac.device.serial_number.upper() }}
|
||||
{% endif %}
|
||||
{% if ac.device.my_partner.lots | length > 0 %}
|
||||
{% if ac.device.get_lots_for_template() | length > 0 %}
|
||||
<h6 class="d-inline">
|
||||
{% for lot in ac.device.my_partner.get_lots_for_template() %}
|
||||
{% for lot in ac.device.get_lots_for_template() %}
|
||||
<span class="badge rounded-pill bg-light text-dark">{{ lot }}</span>
|
||||
{% endfor %}
|
||||
</h6>
|
||||
|
|
|
@ -20,9 +20,46 @@
|
|||
<div class="card-body pt-3">
|
||||
<h3>{{ snapshot_sid }} | {{ snapshot_uuid }}</h3>
|
||||
<!-- Bordered Tabs -->
|
||||
{% if form.show() %}
|
||||
<ul class="nav nav-tabs nav-tabs-bordered">
|
||||
|
||||
<li class="nav-item">
|
||||
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#log">Log</button>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#change-type">Change type updated</button>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
{% endif %}
|
||||
<div class="tab-content pt-2">
|
||||
|
||||
<div class="tab-pane fade show active">
|
||||
{% if form.show() %}
|
||||
<div class="tab-pane fade" id="change-type">
|
||||
<h5 class="card-title">Change Snapshot Type Upload</h5>
|
||||
<div class="list-group col-6">
|
||||
<div class="list-group-item">
|
||||
<form method="post" class="row g-3 needs-validation" id="form_change_updated">
|
||||
{{ form.csrf_token }}
|
||||
{% for f in form %}
|
||||
{% if f != form.csrf_token %}
|
||||
<p class="mb-1">
|
||||
{{ f }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<p class="mb-1">
|
||||
<!-- <button class="btn btn-primary" type="submit">Save</button> -->
|
||||
<a href="javascript:change_updated()" type="button" class="btn btn-primary">Save</a>
|
||||
<span class="d-none" id="activeChangeUpdatedModal" data-bs-toggle="modal" data-bs-target="#btnChangeStatus"></span>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="tab-pane fade show active" id="log">
|
||||
<h5 class="card-title">Traceability log Details</h5>
|
||||
<div class="list-group col-6">
|
||||
{% for log in snapshots_log %}
|
||||
|
@ -51,4 +88,62 @@
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="modal fade" id="btnChangeStatus" tabindex="-1" style="display: none;" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Change type updated</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div id="new_device" class="d-none">
|
||||
Are you sure that you want to Change to <strong>New device</strong>?
|
||||
<p class="text-danger mt-3">
|
||||
Please be certain, once you confirm this step there is no going back.<br />
|
||||
<br />
|
||||
All the updates that have the {{ form.device.dhid }} device will become new devices and
|
||||
you will not be able to do any update over these devices.
|
||||
</p>
|
||||
</div>
|
||||
<div id="update" class="d-none">
|
||||
Are you sure that you want to Change to <strong>Update</strong>?
|
||||
<p class="text-danger mt-3">
|
||||
Please be certain, once you confirm there is no going back.<br />
|
||||
<br />
|
||||
All the devices {{ form.dhids_all_devices() }}
|
||||
will be deleted and the device {{ form.dhid_base() }} will be set as the device base.<br />
|
||||
After this change you will be able to update this device.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary-outline" data-bs-dismiss="modal">Cancel</button>
|
||||
<a href="javascript:send_form_change_updated()" type="button" class="btn btn-danger">
|
||||
Confirm Save!
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function change_updated() {
|
||||
$("#update").attr('class', 'd-none');
|
||||
$("#new_device").attr('class', 'd-none');
|
||||
|
||||
const stype = $("#snapshot_type").val();
|
||||
$("#"+stype).attr('class', 'd-block');
|
||||
|
||||
$("#activeChangeUpdatedModal").click();
|
||||
}
|
||||
|
||||
function send_form_change_updated() {
|
||||
$("#form_change_updated").trigger('submit');
|
||||
}
|
||||
</script>
|
||||
|
||||
{% endblock main %}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ from sqlalchemy import or_
|
|||
|
||||
from ereuse_devicehub import __version__, messages
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.forms import LoginForm, PasswordForm
|
||||
from ereuse_devicehub.forms import LoginForm, PasswordForm, SanitizationEntityForm
|
||||
from ereuse_devicehub.resources.action.models import Trade
|
||||
from ereuse_devicehub.resources.lot.models import Lot
|
||||
from ereuse_devicehub.resources.user.models import User
|
||||
|
@ -100,10 +100,15 @@ class UserProfileView(GenericMixin):
|
|||
|
||||
def dispatch_request(self):
|
||||
self.get_context()
|
||||
sanitization_form = SanitizationEntityForm()
|
||||
if g.user.sanitization_entity:
|
||||
sanitization = g.user.sanitization_entity
|
||||
sanitization_form = SanitizationEntityForm(obj=sanitization)
|
||||
self.context.update(
|
||||
{
|
||||
'current_user': current_user,
|
||||
'password_form': PasswordForm(),
|
||||
'sanitization_form': sanitization_form,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -127,7 +132,30 @@ class UserPasswordView(View):
|
|||
return flask.redirect(flask.url_for('core.user-profile'))
|
||||
|
||||
|
||||
class SanitizationEntityView(View):
|
||||
methods = ['POST']
|
||||
decorators = [login_required]
|
||||
|
||||
def dispatch_request(self):
|
||||
form = SanitizationEntityForm()
|
||||
if form.validate_on_submit():
|
||||
form.save()
|
||||
messages.success('Sanitization data updated successfully!')
|
||||
else:
|
||||
messages.error('Error modifying Sanitization data!')
|
||||
if form.errors:
|
||||
for k in form.errors.keys():
|
||||
errors = ", ".join(form.errors[k])
|
||||
txt = "{}: {}".format(k, errors)
|
||||
messages.error(txt)
|
||||
|
||||
return flask.redirect(flask.url_for('core.user-profile'))
|
||||
|
||||
|
||||
core.add_url_rule('/login/', view_func=LoginView.as_view('login'))
|
||||
core.add_url_rule('/logout/', view_func=LogoutView.as_view('logout'))
|
||||
core.add_url_rule('/profile/', view_func=UserProfileView.as_view('user-profile'))
|
||||
core.add_url_rule('/set_password/', view_func=UserPasswordView.as_view('set-password'))
|
||||
core.add_url_rule(
|
||||
'/set_sanitization/', view_func=SanitizationEntityView.as_view('set-sanitization')
|
||||
)
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -158,5 +158,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"debug": {"lshw": {"configuration": {"uuid": "79c5098f-bc44-4834-8a59-9ea61d956c31"}}},
|
||||
"closed": false
|
||||
}
|
||||
|
|
|
@ -2941,7 +2941,7 @@ def test_delete_devices_check_sync(user: UserClient):
|
|||
in [y.device.id for y in x.actions if hasattr(y, 'device')]
|
||||
]
|
||||
)
|
||||
== 1
|
||||
== 0
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -68,9 +68,11 @@ def test_api_docs(client: Client):
|
|||
'/inventory/lot/{lot_id}/receivernote/',
|
||||
'/inventory/lot/{lot_id}/trade-document/add/',
|
||||
'/inventory/lot/{lot_id}/transfer/{type_id}/',
|
||||
'/inventory/lot/{lot_id}/opentransfer/',
|
||||
'/inventory/lot/{lot_id}/transfer/',
|
||||
'/inventory/lot/transfer/{type_id}/',
|
||||
'/inventory/lot/{lot_id}/upload-snapshot/',
|
||||
'/inventory/lot/{lot_id}/customerdetails/',
|
||||
'/inventory/snapshots/{snapshot_uuid}/',
|
||||
'/inventory/snapshots/',
|
||||
'/inventory/tag/devices/{dhid}/add/',
|
||||
|
@ -98,6 +100,7 @@ def test_api_docs(client: Client):
|
|||
'/metrics/',
|
||||
'/profile/',
|
||||
'/set_password/',
|
||||
'/set_sanitization/',
|
||||
'/tags/',
|
||||
'/tags/{tag_id}/device/{device_id}',
|
||||
'/trade-documents/',
|
||||
|
|
|
@ -141,47 +141,14 @@ def test_physical_properties():
|
|||
'ram_slots': None,
|
||||
}
|
||||
assert pc.physical_properties == {
|
||||
'chassis': ComputerChassis.Tower,
|
||||
'amount': 0,
|
||||
'manufacturer': 'bar',
|
||||
'model': 'foo',
|
||||
'receiver_id': None,
|
||||
'serial_number': 'foo-bar',
|
||||
'part_number': None,
|
||||
'transfer_state': TransferState.Initial,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||
def test_component_similar_one():
|
||||
user = User.query.filter().first()
|
||||
snapshot = yaml2json('pc-components.db')
|
||||
pc = snapshot['device']
|
||||
snapshot['components'][0]['serial_number'] = snapshot['components'][1][
|
||||
'serial_number'
|
||||
] = None
|
||||
pc = d.Desktop(
|
||||
**pc, components=OrderedSet(d.Component(**c) for c in snapshot['components'])
|
||||
)
|
||||
component1, component2 = pc.components # type: d.Component
|
||||
db.session.add(pc)
|
||||
db.session.flush()
|
||||
# Let's create a new component named 'A' similar to 1
|
||||
componentA = d.Component(
|
||||
model=component1.model, manufacturer=component1.manufacturer, owner_id=user.id
|
||||
)
|
||||
similar_to_a = componentA.similar_one(pc, set())
|
||||
assert similar_to_a == component1
|
||||
# d.Component B does not have the same model
|
||||
componentB = d.Component(model='nope', manufacturer=component1.manufacturer)
|
||||
with pytest.raises(ResourceNotFound):
|
||||
assert componentB.similar_one(pc, set())
|
||||
# If we blacklist component A we won't get anything
|
||||
with pytest.raises(ResourceNotFound):
|
||||
assert componentA.similar_one(pc, blacklist={componentA.id})
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||
def test_add_remove():
|
||||
|
@ -301,69 +268,6 @@ def test_sync_execute_register_desktop_no_hid_no_tag(user: UserClient):
|
|||
assert returned_pc == pc
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||
def test_sync_execute_register_desktop_tag_not_linked():
|
||||
"""Syncs a new d.Desktop with HID and a non-linked tag.
|
||||
|
||||
It is OK if the tag was not linked, it will be linked in this process.
|
||||
"""
|
||||
tag = Tag(id='foo')
|
||||
db.session.add(tag)
|
||||
db.session.commit()
|
||||
|
||||
# Create a new transient non-db object
|
||||
pc = d.Desktop(
|
||||
**yaml2json('pc-components.db')['device'], tags=OrderedSet([Tag(id='foo')])
|
||||
)
|
||||
returned_pc = Sync().execute_register(pc)
|
||||
assert returned_pc == pc
|
||||
assert tag.device == pc, 'Tag has to be linked'
|
||||
assert d.Desktop.query.one() == pc, 'd.Desktop had to be set to db'
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||
def test_sync_execute_register_no_hid_tag_not_linked(tag_id: str):
|
||||
"""Validates registering a d.Desktop without HID and a non-linked tag.
|
||||
|
||||
In this case it is ok still, as the non-linked tag proves that
|
||||
the d.Desktop was not existing before (otherwise the tag would
|
||||
be linked), and thus it creates a new d.Desktop.
|
||||
"""
|
||||
tag = Tag(id=tag_id)
|
||||
pc = d.Desktop(**yaml2json('pc-components.db')['device'], tags=OrderedSet([tag]))
|
||||
db.session.add(g.user)
|
||||
returned_pc = Sync().execute_register(pc)
|
||||
db.session.commit()
|
||||
assert returned_pc == pc
|
||||
db_tag = next(iter(returned_pc.tags))
|
||||
# they are not the same tags though
|
||||
# tag is a transient obj and db_tag the one from the db
|
||||
# they have the same pk though
|
||||
assert d.Desktop.query.one() == pc, 'd.Desktop had to be set to db'
|
||||
assert tag != db_tag, 'They are not the same tags though'
|
||||
for tag in pc.tags:
|
||||
assert tag.id in ['foo', pc.devicehub_id]
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||
def test_sync_execute_register_tag_does_not_exist():
|
||||
"""Ensures not being able to register if the tag does not exist,
|
||||
even if the device has HID or it existed before.
|
||||
|
||||
Tags have to be created before trying to link them through a Snapshot.
|
||||
"""
|
||||
user = User.query.filter().first()
|
||||
pc = d.Desktop(
|
||||
**yaml2json('pc-components.db')['device'], tags=OrderedSet([Tag('foo')])
|
||||
)
|
||||
pc.owner_id = user.id
|
||||
with raises(ResourceNotFound):
|
||||
Sync().execute_register(pc)
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||
def test_sync_execute_register_tag_linked_same_device():
|
||||
|
@ -387,53 +291,6 @@ def test_sync_execute_register_tag_linked_same_device():
|
|||
assert tag.id in ['foo', db_pc.devicehub_id]
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||
def test_sync_execute_register_tag_linked_other_device_mismatch_between_tags():
|
||||
"""Checks that sync raises an error if finds that at least two passed-in
|
||||
tags are not linked to the same device.
|
||||
"""
|
||||
pc1 = d.Desktop(**yaml2json('pc-components.db')['device'])
|
||||
db.session.add(Tag(id='foo-1', device=pc1))
|
||||
pc2 = d.Desktop(**yaml2json('pc-components.db')['device'])
|
||||
pc2.serial_number = 'pc2-serial'
|
||||
pc2.hid = Naming.hid(pc2.type, pc2.manufacturer, pc2.model, pc2.serial_number)
|
||||
db.session.add(Tag(id='foo-2', device=pc2))
|
||||
db.session.commit()
|
||||
|
||||
pc1 = d.Desktop(
|
||||
**yaml2json('pc-components.db')['device']
|
||||
) # Create a new transient non-db object
|
||||
pc1.tags.add(Tag(id='foo-1'))
|
||||
pc1.tags.add(Tag(id='foo-2'))
|
||||
with raises(MismatchBetweenTags):
|
||||
Sync().execute_register(pc1)
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.auth_app_context.__name__)
|
||||
def test_sync_execute_register_mismatch_between_tags_and_hid():
|
||||
"""Checks that sync raises an error if it finds that the HID does
|
||||
not point at the same device as the tag does.
|
||||
|
||||
In this case we set HID -> pc1 but tag -> pc2
|
||||
"""
|
||||
pc1 = d.Desktop(**yaml2json('pc-components.db')['device'])
|
||||
db.session.add(Tag(id='foo-1', device=pc1))
|
||||
pc2 = d.Desktop(**yaml2json('pc-components.db')['device'])
|
||||
pc2.serial_number = 'pc2-serial'
|
||||
pc2.hid = Naming.hid(pc2.type, pc2.manufacturer, pc2.model, pc2.serial_number)
|
||||
db.session.add(Tag(id='foo-2', device=pc2))
|
||||
db.session.commit()
|
||||
|
||||
pc1 = d.Desktop(
|
||||
**yaml2json('pc-components.db')['device']
|
||||
) # Create a new transient non-db object
|
||||
pc1.tags.add(Tag(id='foo-2'))
|
||||
with raises(MismatchBetweenTagsAndHid):
|
||||
Sync().execute_register(pc1)
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_get_device(user: UserClient):
|
||||
|
@ -751,138 +608,10 @@ def test_cooking_mixer_api(user: UserClient):
|
|||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_hid_with_mac(app: Devicehub, user: UserClient):
|
||||
def test_hid_with_placeholder(app: Devicehub, user: UserClient):
|
||||
"""Checks hid with mac."""
|
||||
snapshot = file('asus-eee-1000h.snapshot.11')
|
||||
snap, _ = user.post(snapshot, res=m.Snapshot)
|
||||
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
||||
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
||||
pc = d.Device.query.filter_by(devicehub_id=snap['device']['devicehubID']).one()
|
||||
assert (
|
||||
pc.placeholder.binding.hid
|
||||
== 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
def test_hid_without_mac(app: Devicehub, user: UserClient):
|
||||
"""Checks hid without mac."""
|
||||
snapshot = yaml2json('asus-eee-1000h.snapshot.11')
|
||||
snapshot['components'] = [
|
||||
c for c in snapshot['components'] if c['type'] != 'NetworkAdapter'
|
||||
]
|
||||
snap, _ = user.post(json_encode(snapshot), res=m.Snapshot)
|
||||
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
||||
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
def test_hid_with_mac_none(app: Devicehub, user: UserClient):
|
||||
"""Checks hid with mac = None."""
|
||||
snapshot = yaml2json('asus-eee-1000h.snapshot.11')
|
||||
network = [c for c in snapshot['components'] if c['type'] == 'NetworkAdapter'][0]
|
||||
network['serialNumber'] = None
|
||||
snap, _ = user.post(json_encode(snapshot), res=m.Snapshot)
|
||||
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
||||
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
def test_hid_with_2networkadapters(app: Devicehub, user: UserClient):
|
||||
"""Checks hid with 2 networks adapters"""
|
||||
snapshot = yaml2json('asus-eee-1000h.snapshot.11')
|
||||
network = [c for c in snapshot['components'] if c['type'] == 'NetworkAdapter'][0]
|
||||
network2 = copy.copy(network)
|
||||
snapshot['components'].append(network2)
|
||||
network['serialNumber'] = 'a0:24:8c:7f:cf:2d'
|
||||
user.post(json_encode(snapshot), res=m.Snapshot)
|
||||
devices, _ = user.get(res=d.Device)
|
||||
|
||||
laptop = devices['items'][0]
|
||||
assert (
|
||||
laptop['hid']
|
||||
== 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||
)
|
||||
assert len([c for c in devices['items'] if c['type'] == 'Laptop']) == 2
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_hid_with_2network_and_drop_no_mac_in_hid(app: Devicehub, user: UserClient):
|
||||
"""Checks hid with 2 networks adapters and next drop the network is not used in hid"""
|
||||
snapshot = yaml2json('asus-eee-1000h.snapshot.11')
|
||||
network = [c for c in snapshot['components'] if c['type'] == 'NetworkAdapter'][0]
|
||||
network2 = copy.copy(network)
|
||||
snapshot['components'].append(network2)
|
||||
network['serialNumber'] = 'a0:24:8c:7f:cf:2d'
|
||||
snap, _ = user.post(json_encode(snapshot), res=m.Snapshot)
|
||||
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
||||
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
||||
pc = d.Device.query.filter_by(devicehub_id=snap['device']['devicehubID']).one()
|
||||
assert (
|
||||
pc.placeholder.binding.hid
|
||||
== 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||
)
|
||||
|
||||
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abb'
|
||||
snapshot['components'] = [c for c in snapshot['components'] if c != network]
|
||||
user.post(json_encode(snapshot), res=m.Snapshot)
|
||||
devices, _ = user.get(res=d.Device)
|
||||
laptop = devices['items'][0]
|
||||
assert (
|
||||
pc.placeholder.binding.hid
|
||||
== 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||
)
|
||||
assert len([c for c in devices['items'] if c['type'] == 'Laptop']) == 2
|
||||
assert len([c for c in laptop['components'] if c['type'] == 'NetworkAdapter']) == 1
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_hid_with_2network_and_drop_mac_in_hid(app: Devicehub, user: UserClient):
|
||||
"""Checks hid with 2 networks adapters and next drop the network is used in hid"""
|
||||
# One tipical snapshot with 2 network cards
|
||||
snapshot = yaml2json('asus-eee-1000h.snapshot.11')
|
||||
network = [c for c in snapshot['components'] if c['type'] == 'NetworkAdapter'][0]
|
||||
network2 = copy.copy(network)
|
||||
snapshot['components'].append(network2)
|
||||
network['serialNumber'] = 'a0:24:8c:7f:cf:2d'
|
||||
snap, _ = user.post(json_encode(snapshot), res=m.Snapshot)
|
||||
pc, _ = user.get(res=d.Device, item=snap['device']['devicehubID'])
|
||||
assert pc['hid'] == 'laptop-asustek_computer_inc-1000h-94oaaq021116'
|
||||
pc = d.Device.query.filter_by(devicehub_id=snap['device']['devicehubID']).one()
|
||||
assert (
|
||||
pc.placeholder.binding.hid
|
||||
== 'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d'
|
||||
)
|
||||
|
||||
# we drop the network card then is used for to build the hid
|
||||
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abb'
|
||||
snapshot['components'] = [c for c in snapshot['components'] if c != network2]
|
||||
user.post(json_encode(snapshot), res=m.Snapshot)
|
||||
devices, _ = user.get(res=d.Device)
|
||||
laptops = [c for c in devices['items'] if c['type'] == 'Laptop']
|
||||
assert len(laptops) == 4
|
||||
hids = [laptops[0]['hid'], laptops[2]['hid']]
|
||||
proof_hid = [
|
||||
'laptop-asustek_computer_inc-1000h-94oaaq021116-a0:24:8c:7f:cf:2d',
|
||||
'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d',
|
||||
]
|
||||
assert all([h in proof_hid for h in hids])
|
||||
|
||||
# we drop all network cards
|
||||
snapshot['uuid'] = 'd1b70cb8-8929-4f36-99b7-fe052cec0abc'
|
||||
snapshot['components'] = [
|
||||
c for c in snapshot['components'] if c not in [network, network2]
|
||||
]
|
||||
user.post(json_encode(snapshot), res=m.Snapshot)
|
||||
devices, _ = user.get(res=d.Device)
|
||||
laptops = [c for c in devices['items'] if c['type'] == 'Laptop']
|
||||
assert len(laptops) == 4
|
||||
hids = [laptops[0]['hid'], laptops[2]['hid']]
|
||||
proof_hid = [
|
||||
'laptop-asustek_computer_inc-1000h-94oaaq021116-a0:24:8c:7f:cf:2d',
|
||||
'laptop-asustek_computer_inc-1000h-94oaaq021116-00:24:8c:7f:cf:2d',
|
||||
'laptop-asustek_computer_inc-1000h-94oaaq021116',
|
||||
]
|
||||
assert all([h in proof_hid for h in hids])
|
||||
assert pc.placeholder.binding.hid == pc.hid
|
||||
|
|
|
@ -6,24 +6,29 @@ from ereuse_devicehub.resources.documents import documents
|
|||
from ereuse_devicehub.resources.lot.models import Lot
|
||||
from ereuse_devicehub.resources.tradedocument.models import TradeDocument
|
||||
from tests import conftest
|
||||
from tests.conftest import file, yaml2json, json_encode
|
||||
from tests.conftest import file, json_encode, yaml2json
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_simple_metrics(user: UserClient):
|
||||
""" Checks one standard query of metrics """
|
||||
"""Checks one standard query of metrics"""
|
||||
# Insert computer
|
||||
lenovo = yaml2json('desktop-9644w8n-lenovo-0169622.snapshot')
|
||||
acer = yaml2json('acer.happy.battery.snapshot')
|
||||
user.post(json_encode(lenovo), res=ma.Snapshot)
|
||||
snapshot, _ = user.post(json_encode(acer), res=ma.Snapshot)
|
||||
device_id = snapshot['device']['id']
|
||||
post_request = {"transaction": "ccc", "name": "John", "endUsers": 1,
|
||||
"finalUserCode": "abcdefjhi",
|
||||
"devices": [device_id], "description": "aaa",
|
||||
"startTime": "2020-11-01T02:00:00+00:00",
|
||||
"endTime": "2020-12-01T02:00:00+00:00"}
|
||||
post_request = {
|
||||
"transaction": "ccc",
|
||||
"name": "John",
|
||||
"endUsers": 1,
|
||||
"finalUserCode": "abcdefjhi",
|
||||
"devices": [device_id],
|
||||
"description": "aaa",
|
||||
"startTime": "2020-11-01T02:00:00+00:00",
|
||||
"endTime": "2020-12-01T02:00:00+00:00",
|
||||
}
|
||||
|
||||
# Create Allocate
|
||||
user.post(res=ma.Allocate, data=post_request)
|
||||
|
@ -58,16 +63,21 @@ def test_simple_metrics(user: UserClient):
|
|||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_second_hdd_metrics(user: UserClient):
|
||||
""" Checks one standard query of metrics """
|
||||
"""Checks one standard query of metrics"""
|
||||
# Insert computer
|
||||
acer = yaml2json('acer.happy.battery.snapshot')
|
||||
snapshot, _ = user.post(json_encode(acer), res=ma.Snapshot)
|
||||
device_id = snapshot['device']['id']
|
||||
post_request = {"transaction": "ccc", "name": "John", "endUsers": 1,
|
||||
"finalUserCode": "abcdefjhi",
|
||||
"devices": [device_id], "description": "aaa",
|
||||
"startTime": "2020-11-01T02:00:00+00:00",
|
||||
"endTime": "2020-12-01T02:00:00+00:00"}
|
||||
post_request = {
|
||||
"transaction": "ccc",
|
||||
"name": "John",
|
||||
"endUsers": 1,
|
||||
"finalUserCode": "abcdefjhi",
|
||||
"devices": [device_id],
|
||||
"description": "aaa",
|
||||
"startTime": "2020-11-01T02:00:00+00:00",
|
||||
"endTime": "2020-12-01T02:00:00+00:00",
|
||||
}
|
||||
|
||||
# Create Allocate
|
||||
user.post(res=ma.Allocate, data=post_request)
|
||||
|
@ -101,16 +111,21 @@ def test_second_hdd_metrics(user: UserClient):
|
|||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_metrics_with_live_null(user: UserClient):
|
||||
""" Checks one standard query of metrics """
|
||||
"""Checks one standard query of metrics"""
|
||||
# Insert computer
|
||||
acer = file('acer.happy.battery.snapshot')
|
||||
snapshot, _ = user.post(acer, res=ma.Snapshot)
|
||||
device_id = snapshot['device']['id']
|
||||
post_request = {"transaction": "ccc", "name": "John", "endUsers": 1,
|
||||
"finalUserCode": "abcdefjhi",
|
||||
"devices": [device_id], "description": "aaa",
|
||||
"startTime": "2020-11-01T02:00:00+00:00",
|
||||
"endTime": "2020-12-01T02:00:00+00:00"}
|
||||
post_request = {
|
||||
"transaction": "ccc",
|
||||
"name": "John",
|
||||
"endUsers": 1,
|
||||
"finalUserCode": "abcdefjhi",
|
||||
"devices": [device_id],
|
||||
"description": "aaa",
|
||||
"startTime": "2020-11-01T02:00:00+00:00",
|
||||
"endTime": "2020-12-01T02:00:00+00:00",
|
||||
}
|
||||
|
||||
# Create Allocate
|
||||
user.post(res=ma.Allocate, data=post_request)
|
||||
|
@ -124,19 +139,29 @@ def test_metrics_with_live_null(user: UserClient):
|
|||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_metrics_action_status(user: UserClient, user2: UserClient):
|
||||
""" Checks one standard query of metrics."""
|
||||
"""Checks one standard query of metrics."""
|
||||
# Insert computer
|
||||
lenovo = yaml2json('desktop-9644w8n-lenovo-0169622.snapshot')
|
||||
snap, _ = user.post(json_encode(lenovo), res=ma.Snapshot)
|
||||
device_id = snap['device']['id']
|
||||
action = {'type': ma.Use.t, 'devices': [device_id]}
|
||||
action_use, _ = user.post(action, res=ma.Action)
|
||||
csv_str, _ = user.get(res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': [device_id]})])
|
||||
head = '"DHID";"Hid";"Document-Name";"Action-Type";"Action-User-LastOwner-Supplier";"Action-User-LastOwner-Receiver";"Action-Create-By";"Trade-Confirmed";"Status-Created-By-Supplier-About-Reciber";"Status-Receiver";"Status Supplier – Created Date";"Status Receiver – Created Date";"Trade-Weight";"Action-Create";"Allocate-Start";"Allocate-User-Code";"Allocate-NumUsers";"UsageTimeAllocate";"Type";"LiveCreate";"UsageTimeHdd"\n'
|
||||
body = '"O48N2";"desktop-lenovo-9644w8n-0169622-00:1a:6b:5e:7f:10";"";"Status";"";"foo@foo.com";"Receiver";"";"";"Use";"";"'
|
||||
csv_str, _ = user.get(
|
||||
res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': [device_id]})],
|
||||
)
|
||||
head = (
|
||||
'"DHID";"Hid";"Document-Name";"Action-Type";"Action-User-LastOwner-Supplier";'
|
||||
)
|
||||
head += '"Action-User-LastOwner-Receiver";"Action-Create-By";"Trade-Confirmed";'
|
||||
head += '"Status-Created-By-Supplier-About-Reciber";"Status-Receiver";'
|
||||
head += '"Status Supplier – Created Date";"Status Receiver – Created Date";"Trade-Weight";'
|
||||
head += '"Action-Create";"Allocate-Start";"Allocate-User-Code";"Allocate-NumUsers";'
|
||||
head += '"UsageTimeAllocate";"Type";"LiveCreate";"UsageTimeHdd"\n'
|
||||
body = '"O48N2";"adebcc5506213fac43cd8473a9c81bcf0cadaed9cb98b2eae651e377a3533c5a";'
|
||||
body += '"";"Status";"";"foo@foo.com";"Receiver";"";"";"Use";"";"'
|
||||
assert head in csv_str
|
||||
assert body in csv_str
|
||||
|
||||
|
@ -144,7 +169,7 @@ def test_metrics_action_status(user: UserClient, user2: UserClient):
|
|||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_complet_metrics_with_trade(user: UserClient, user2: UserClient):
|
||||
""" Checks one standard query of metrics in a trade enviroment."""
|
||||
"""Checks one standard query of metrics in a trade enviroment."""
|
||||
# Insert computer
|
||||
lenovo = yaml2json('desktop-9644w8n-lenovo-0169622.snapshot')
|
||||
acer = yaml2json('acer.happy.battery.snapshot')
|
||||
|
@ -154,12 +179,8 @@ def test_complet_metrics_with_trade(user: UserClient, user2: UserClient):
|
|||
device1_id = snap1['device']['id']
|
||||
device2_id = snap2['device']['id']
|
||||
devices_id = [device1_id, device2_id]
|
||||
devices = [('id', device1_id),
|
||||
('id', snap2['device']['id'])]
|
||||
lot, _ = user.post({},
|
||||
res=Lot,
|
||||
item='{}/devices'.format(lot['id']),
|
||||
query=devices)
|
||||
devices = [('id', device1_id), ('id', snap2['device']['id'])]
|
||||
lot, _ = user.post({}, res=Lot, item='{}/devices'.format(lot['id']), query=devices)
|
||||
|
||||
action = {'type': ma.Refurbish.t, 'devices': [device1_id]}
|
||||
user.post(action, res=ma.Action)
|
||||
|
@ -179,17 +200,21 @@ def test_complet_metrics_with_trade(user: UserClient, user2: UserClient):
|
|||
|
||||
action = {'type': ma.Use.t, 'devices': [device1_id]}
|
||||
action_use, _ = user.post(action, res=ma.Action)
|
||||
csv_str, _ = user.get(res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': devices_id})])
|
||||
csv_str, _ = user.get(
|
||||
res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': devices_id})],
|
||||
)
|
||||
|
||||
body1_lenovo = '"O48N2";"desktop-lenovo-9644w8n-0169622-00:1a:6b:5e:7f:10";"";"Trade";"foo@foo.com";'
|
||||
body1_lenovo = '"O48N2";"adebcc5506213fac43cd8473a9c81bcf0cadaed9cb98b2eae651e377a3533c5a";"";"Trade";"foo@foo.com";'
|
||||
body1_lenovo += '"foo2@foo.com";"Supplier";"NeedConfirmation";"Use";"";'
|
||||
body2_lenovo = ';"";"0";"0";"Trade";"0";"0"\n'
|
||||
|
||||
body1_acer = '"K3XW2";"laptop-acer-aohappy-lusea0d010038879a01601-00:26:c7:8e:cb:8c";"";"Trade";'
|
||||
body1_acer += '"foo@foo.com";"foo2@foo.com";"Supplier";"NeedConfirmation";"";"";"";"";"0";'
|
||||
body1_acer = '"K3XW2";"55b1f6d0692d1569c7590f0aeabd1c9874a1c78b8dd3a7d481df95923a629748";"";"Trade";'
|
||||
body1_acer += (
|
||||
'"foo@foo.com";"foo2@foo.com";"Supplier";"NeedConfirmation";"";"";"";"";"0";'
|
||||
)
|
||||
body2_acer = ';"";"0";"0";"Trade";"0";"4692.0"\n'
|
||||
|
||||
assert body1_lenovo in csv_str
|
||||
|
@ -200,12 +225,14 @@ def test_complet_metrics_with_trade(user: UserClient, user2: UserClient):
|
|||
# User2 mark this device as Refurbish
|
||||
action = {'type': ma.Use.t, 'devices': [device1_id]}
|
||||
action_use2, _ = user2.post(action, res=ma.Action)
|
||||
csv_str, _ = user.get(res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': devices_id})])
|
||||
csv_str, _ = user.get(
|
||||
res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': devices_id})],
|
||||
)
|
||||
|
||||
body1_lenovo = '"O48N2";"desktop-lenovo-9644w8n-0169622-00:1a:6b:5e:7f:10";"";"Trade";"foo@foo.com";'
|
||||
body1_lenovo = '"O48N2";"adebcc5506213fac43cd8473a9c81bcf0cadaed9cb98b2eae651e377a3533c5a";"";"Trade";"foo@foo.com";'
|
||||
body1_lenovo += '"foo2@foo.com";"Supplier";"NeedConfirmation";"Use";"Use";'
|
||||
body2_lenovo = ';"";"0";"0";"Trade";"0";"0"\n'
|
||||
body2_acer = ';"";"0";"0";"Trade";"0";"4692.0"\n'
|
||||
|
@ -215,20 +242,16 @@ def test_complet_metrics_with_trade(user: UserClient, user2: UserClient):
|
|||
assert body2_acer in csv_str
|
||||
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_metrics_action_status_for_containers(user: UserClient, user2: UserClient):
|
||||
""" Checks one standard query of metrics for a container."""
|
||||
"""Checks one standard query of metrics for a container."""
|
||||
# Insert computer
|
||||
lenovo = yaml2json('desktop-9644w8n-lenovo-0169622.snapshot')
|
||||
snap, _ = user.post(json_encode(lenovo), res=ma.Snapshot)
|
||||
lot, _ = user.post({'name': 'MyLot'}, res=Lot)
|
||||
devices = [('id', snap['device']['id'])]
|
||||
lot, _ = user.post({},
|
||||
res=Lot,
|
||||
item='{}/devices'.format(lot['id']),
|
||||
query=devices)
|
||||
lot, _ = user.post({}, res=Lot, item='{}/devices'.format(lot['id']), query=devices)
|
||||
request_post = {
|
||||
'type': 'Trade',
|
||||
'devices': [snap['device']['id']],
|
||||
|
@ -247,7 +270,7 @@ def test_metrics_action_status_for_containers(user: UserClient, user2: UserClien
|
|||
'hash': 'bbbbbbbb',
|
||||
'url': 'http://www.ereuse.org/',
|
||||
'weight': 150,
|
||||
'lot': lot['id']
|
||||
'lot': lot['id'],
|
||||
}
|
||||
tradedocument, _ = user.post(res=TradeDocument, data=request_post)
|
||||
action = {'type': ma.Recycling.t, 'devices': [], 'documents': [tradedocument['id']]}
|
||||
|
@ -257,10 +280,12 @@ def test_metrics_action_status_for_containers(user: UserClient, user2: UserClien
|
|||
assert str(trade.actions[-1].id) == action['id']
|
||||
|
||||
# get metrics from botom in lot menu
|
||||
csv_str, _ = user.get(res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer']}), ('lot', lot['id'])])
|
||||
csv_str, _ = user.get(
|
||||
res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer']}), ('lot', lot['id'])],
|
||||
)
|
||||
|
||||
body1 = ';"bbbbbbbb";"test.pdf";"Trade-Container";"foo@foo.com";"foo2@foo.com";"Supplier";"False";"Recycling";"";'
|
||||
body2 = ';"";"150.0";'
|
||||
|
@ -272,10 +297,12 @@ def test_metrics_action_status_for_containers(user: UserClient, user2: UserClien
|
|||
assert body3 in csv_str.split('\n')[-2]
|
||||
|
||||
# get metrics from botom in devices menu
|
||||
csv_str2, _ = user.get(res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': [snap['device']['id']]})])
|
||||
csv_str2, _ = user.get(
|
||||
res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': [snap['device']['id']]})],
|
||||
)
|
||||
|
||||
assert len(csv_str2.split('\n')) == 4
|
||||
assert body1 in csv_str2.split('\n')[-2]
|
||||
|
@ -286,17 +313,14 @@ def test_metrics_action_status_for_containers(user: UserClient, user2: UserClien
|
|||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_visual_metrics_for_old_owners(user: UserClient, user2: UserClient):
|
||||
""" Checks if one old owner can see the metrics in a trade enviroment."""
|
||||
"""Checks if one old owner can see the metrics in a trade enviroment."""
|
||||
# Insert computer
|
||||
lenovo = yaml2json('desktop-9644w8n-lenovo-0169622.snapshot')
|
||||
snap1, _ = user.post(json_encode(lenovo), res=ma.Snapshot)
|
||||
lot, _ = user.post({'name': 'MyLot'}, res=Lot)
|
||||
device_id = snap1['device']['id']
|
||||
devices = [('id', device_id)]
|
||||
lot, _ = user.post({},
|
||||
res=Lot,
|
||||
item='{}/devices'.format(lot['id']),
|
||||
query=devices)
|
||||
lot, _ = user.post({}, res=Lot, item='{}/devices'.format(lot['id']), query=devices)
|
||||
request_post = {
|
||||
'type': 'Trade',
|
||||
'devices': [device_id],
|
||||
|
@ -309,24 +333,23 @@ def test_visual_metrics_for_old_owners(user: UserClient, user2: UserClient):
|
|||
}
|
||||
trade, _ = user.post(res=ma.Action, data=request_post)
|
||||
|
||||
request_confirm = {
|
||||
'type': 'Confirm',
|
||||
'action': trade['id'],
|
||||
'devices': [device_id]
|
||||
}
|
||||
request_confirm = {'type': 'Confirm', 'action': trade['id'], 'devices': [device_id]}
|
||||
user2.post(res=ma.Action, data=request_confirm)
|
||||
|
||||
|
||||
action = {'type': ma.Refurbish.t, 'devices': [device_id]}
|
||||
action_use, _ = user.post(action, res=ma.Action)
|
||||
csv_supplier, _ = user.get(res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': [device_id]})])
|
||||
csv_receiver, _ = user2.get(res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': [device_id]})])
|
||||
csv_supplier, _ = user.get(
|
||||
res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': [device_id]})],
|
||||
)
|
||||
csv_receiver, _ = user2.get(
|
||||
res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': [device_id]})],
|
||||
)
|
||||
body = ';"";"0";"0";"Trade";"0";"0"\n'
|
||||
|
||||
assert body in csv_receiver
|
||||
|
@ -343,10 +366,7 @@ def test_bug_trade_confirmed(user: UserClient, user2: UserClient):
|
|||
lot, _ = user.post({'name': 'MyLot'}, res=Lot)
|
||||
device_id = snap1['device']['id']
|
||||
devices = [('id', device_id)]
|
||||
lot, _ = user.post({},
|
||||
res=Lot,
|
||||
item='{}/devices'.format(lot['id']),
|
||||
query=devices)
|
||||
lot, _ = user.post({}, res=Lot, item='{}/devices'.format(lot['id']), query=devices)
|
||||
request_post = {
|
||||
'type': 'Trade',
|
||||
'devices': [device_id],
|
||||
|
@ -359,22 +379,24 @@ def test_bug_trade_confirmed(user: UserClient, user2: UserClient):
|
|||
}
|
||||
trade, _ = user.post(res=ma.Action, data=request_post)
|
||||
|
||||
csv_not_confirmed, _ = user.get(res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': [device_id]})])
|
||||
request_confirm = {
|
||||
'type': 'Confirm',
|
||||
'action': trade['id'],
|
||||
'devices': [device_id]
|
||||
}
|
||||
csv_not_confirmed, _ = user.get(
|
||||
res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': [device_id]})],
|
||||
)
|
||||
request_confirm = {'type': 'Confirm', 'action': trade['id'], 'devices': [device_id]}
|
||||
user2.post(res=ma.Action, data=request_confirm)
|
||||
csv_confirmed, _ = user2.get(res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': [device_id]})])
|
||||
csv_confirmed, _ = user2.get(
|
||||
res=documents.DocumentDef.t,
|
||||
item='actions/',
|
||||
accept='text/csv',
|
||||
query=[('filter', {'type': ['Computer'], 'ids': [device_id]})],
|
||||
)
|
||||
|
||||
body_not_confirmed = '"Trade";"foo2@foo.com";"foo@foo.com";"Receiver";"NeedConfirmation";'
|
||||
body_not_confirmed = (
|
||||
'"Trade";"foo2@foo.com";"foo@foo.com";"Receiver";"NeedConfirmation";'
|
||||
)
|
||||
body_confirmed = '"Trade";"foo2@foo.com";"foo@foo.com";"Receiver";"TradeConfirmed";'
|
||||
|
||||
assert body_not_confirmed in csv_not_confirmed
|
||||
|
|
|
@ -17,18 +17,36 @@ Excluded cases in tests
|
|||
|
||||
"""
|
||||
import math
|
||||
|
||||
import pytest
|
||||
|
||||
from ereuse_devicehub.resources.action.models import BenchmarkDataStorage, BenchmarkProcessor, \
|
||||
VisualTest
|
||||
from ereuse_devicehub.resources.action.rate.v1_0 import DataStorageRate, ProcessorRate, \
|
||||
RamRate, RateAlgorithm
|
||||
from ereuse_devicehub.resources.device.models import Desktop, HardDrive, Processor, RamModule
|
||||
from ereuse_devicehub.resources.enums import AppearanceRange, ComputerChassis, FunctionalityRange
|
||||
from ereuse_devicehub.resources.action.models import (
|
||||
BenchmarkDataStorage,
|
||||
BenchmarkProcessor,
|
||||
VisualTest,
|
||||
)
|
||||
from ereuse_devicehub.resources.action.rate.v1_0 import (
|
||||
DataStorageRate,
|
||||
ProcessorRate,
|
||||
RamRate,
|
||||
RateAlgorithm,
|
||||
)
|
||||
from ereuse_devicehub.resources.device.models import (
|
||||
Desktop,
|
||||
HardDrive,
|
||||
Processor,
|
||||
RamModule,
|
||||
)
|
||||
from ereuse_devicehub.resources.enums import (
|
||||
AppearanceRange,
|
||||
ComputerChassis,
|
||||
FunctionalityRange,
|
||||
)
|
||||
from tests import conftest
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_data_storage_rate():
|
||||
"""Test to check if compute data storage rate have same value than
|
||||
previous score version.
|
||||
|
@ -65,6 +83,7 @@ def test_rate_data_storage_rate():
|
|||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_data_storage_size_is_null():
|
||||
"""Test where input DataStorage.size = NULL, BenchmarkDataStorage.read_speed = 0,
|
||||
BenchmarkDataStorage.write_speed = 0 is like no DataStorage has been detected;
|
||||
|
@ -78,6 +97,7 @@ def test_rate_data_storage_size_is_null():
|
|||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_no_data_storage():
|
||||
"""Test without data storage devices."""
|
||||
|
||||
|
@ -88,6 +108,7 @@ def test_rate_no_data_storage():
|
|||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_ram_rate():
|
||||
"""Test to check if compute ram rate have same value than previous
|
||||
score version only with 1 RamModule.
|
||||
|
@ -97,10 +118,13 @@ def test_rate_ram_rate():
|
|||
|
||||
ram_rate = RamRate().compute([ram1])
|
||||
|
||||
assert math.isclose(ram_rate, 2.02, rel_tol=0.002), 'RamRate returns incorrect value(rate)'
|
||||
assert math.isclose(
|
||||
ram_rate, 2.02, rel_tol=0.002
|
||||
), 'RamRate returns incorrect value(rate)'
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_ram_rate_2modules():
|
||||
"""Test to check if compute ram rate have same value than previous
|
||||
score version with 2 RamModule.
|
||||
|
@ -111,10 +135,13 @@ def test_rate_ram_rate_2modules():
|
|||
|
||||
ram_rate = RamRate().compute([ram1, ram2])
|
||||
|
||||
assert math.isclose(ram_rate, 3.79, rel_tol=0.001), 'RamRate returns incorrect value(rate)'
|
||||
assert math.isclose(
|
||||
ram_rate, 3.79, rel_tol=0.001
|
||||
), 'RamRate returns incorrect value(rate)'
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_ram_rate_4modules():
|
||||
"""Test to check if compute ram rate have same value than previous
|
||||
score version with 2 RamModule.
|
||||
|
@ -127,10 +154,13 @@ def test_rate_ram_rate_4modules():
|
|||
|
||||
ram_rate = RamRate().compute([ram1, ram2, ram3, ram4])
|
||||
|
||||
assert math.isclose(ram_rate, 1.993, rel_tol=0.001), 'RamRate returns incorrect value(rate)'
|
||||
assert math.isclose(
|
||||
ram_rate, 1.993, rel_tol=0.001
|
||||
), 'RamRate returns incorrect value(rate)'
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_ram_module_size_is_0():
|
||||
"""Test where input data RamModule.size = 0; is like no RamModule
|
||||
has been detected.
|
||||
|
@ -143,6 +173,7 @@ def test_rate_ram_module_size_is_0():
|
|||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_ram_speed_is_null():
|
||||
"""Test where RamModule.speed is NULL (not detected) but has size."""
|
||||
|
||||
|
@ -150,16 +181,21 @@ def test_rate_ram_speed_is_null():
|
|||
|
||||
ram_rate = RamRate().compute([ram0])
|
||||
|
||||
assert math.isclose(ram_rate, 1.85, rel_tol=0.002), 'RamRate returns incorrect value(rate)'
|
||||
assert math.isclose(
|
||||
ram_rate, 1.85, rel_tol=0.002
|
||||
), 'RamRate returns incorrect value(rate)'
|
||||
|
||||
ram0 = RamModule(size=1024, speed=None)
|
||||
|
||||
ram_rate = RamRate().compute([ram0])
|
||||
|
||||
assert math.isclose(ram_rate, 1.25, rel_tol=0.004), 'RamRate returns incorrect value(rate)'
|
||||
assert math.isclose(
|
||||
ram_rate, 1.25, rel_tol=0.004
|
||||
), 'RamRate returns incorrect value(rate)'
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_no_ram_module():
|
||||
"""Test without RamModule."""
|
||||
ram0 = RamModule()
|
||||
|
@ -169,6 +205,7 @@ def test_rate_no_ram_module():
|
|||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_processor_rate():
|
||||
"""Test to check if compute processor rate have same value than previous
|
||||
score version only with 1 core.
|
||||
|
@ -184,6 +221,7 @@ def test_rate_processor_rate():
|
|||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_processor_rate_2cores():
|
||||
"""Test to check if compute processor rate have same value than previous
|
||||
score version with 2 cores.
|
||||
|
@ -206,6 +244,7 @@ def test_rate_processor_rate_2cores():
|
|||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_processor_with_null_cores():
|
||||
"""Test with processor device have null number of cores."""
|
||||
cpu = Processor(cores=None, speed=3.3)
|
||||
|
@ -217,6 +256,7 @@ def test_rate_processor_with_null_cores():
|
|||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_rate_processor_with_null_speed():
|
||||
"""Test with processor device have null speed value."""
|
||||
cpu = Processor(cores=1, speed=None)
|
||||
|
@ -262,12 +302,14 @@ def test_rate_computer_1193():
|
|||
data_storage,
|
||||
RamModule(size=4096, speed=1600),
|
||||
RamModule(size=2048, speed=1067),
|
||||
cpu
|
||||
cpu,
|
||||
}
|
||||
# Add test visual with functionality and appearance range
|
||||
VisualTest(appearance_range=AppearanceRange.A,
|
||||
functionality_range=FunctionalityRange.A,
|
||||
device=pc_test)
|
||||
VisualTest(
|
||||
appearance_range=AppearanceRange.A,
|
||||
functionality_range=FunctionalityRange.A,
|
||||
device=pc_test,
|
||||
)
|
||||
|
||||
# Compute all components rates and general rating
|
||||
rate_pc = RateAlgorithm().compute(pc_test)
|
||||
|
@ -311,15 +353,13 @@ def test_rate_computer_1201():
|
|||
data_storage.actions_one.add(BenchmarkDataStorage(read_speed=158, write_speed=34.7))
|
||||
cpu = Processor(cores=2, speed=3.3)
|
||||
cpu.actions_one.add(BenchmarkProcessor(rate=26339.48))
|
||||
pc_test.components |= {
|
||||
data_storage,
|
||||
RamModule(size=2048, speed=1333),
|
||||
cpu
|
||||
}
|
||||
pc_test.components |= {data_storage, RamModule(size=2048, speed=1333), cpu}
|
||||
# Add test visual with functionality and appearance range
|
||||
VisualTest(appearance_range=AppearanceRange.B,
|
||||
functionality_range=FunctionalityRange.A,
|
||||
device=pc_test)
|
||||
VisualTest(
|
||||
appearance_range=AppearanceRange.B,
|
||||
functionality_range=FunctionalityRange.A,
|
||||
device=pc_test,
|
||||
)
|
||||
|
||||
# Compute all components rates and general rating
|
||||
rate_pc = RateAlgorithm().compute(pc_test)
|
||||
|
@ -365,7 +405,9 @@ def test_rate_computer_multiple_ram_module():
|
|||
|
||||
pc_test = Desktop(chassis=ComputerChassis.Tower)
|
||||
data_storage = HardDrive(size=76319)
|
||||
data_storage.actions_one.add(BenchmarkDataStorage(read_speed=72.2, write_speed=24.3))
|
||||
data_storage.actions_one.add(
|
||||
BenchmarkDataStorage(read_speed=72.2, write_speed=24.3)
|
||||
)
|
||||
cpu = Processor(cores=1, speed=1.6)
|
||||
cpu.actions_one.add(BenchmarkProcessor(rate=3192.34))
|
||||
pc_test.components |= {
|
||||
|
@ -374,12 +416,14 @@ def test_rate_computer_multiple_ram_module():
|
|||
RamModule(size=512, speed=800),
|
||||
RamModule(size=512, speed=667),
|
||||
RamModule(size=512, speed=533),
|
||||
cpu
|
||||
cpu,
|
||||
}
|
||||
# Add test visual with functionality and appearance range
|
||||
VisualTest(appearance_range=AppearanceRange.C,
|
||||
functionality_range=FunctionalityRange.A,
|
||||
device=pc_test)
|
||||
VisualTest(
|
||||
appearance_range=AppearanceRange.C,
|
||||
functionality_range=FunctionalityRange.A,
|
||||
device=pc_test,
|
||||
)
|
||||
# Compute all components rates and general rating
|
||||
rate_pc = RateAlgorithm().compute(pc_test)
|
||||
|
||||
|
@ -421,18 +465,18 @@ def test_rate_computer_one_ram_module():
|
|||
|
||||
pc_test = Desktop(chassis=ComputerChassis.Tower)
|
||||
data_storage = HardDrive(size=152587)
|
||||
data_storage.actions_one.add(BenchmarkDataStorage(read_speed=78.1, write_speed=24.4))
|
||||
data_storage.actions_one.add(
|
||||
BenchmarkDataStorage(read_speed=78.1, write_speed=24.4)
|
||||
)
|
||||
cpu = Processor(cores=2, speed=2.5)
|
||||
cpu.actions_one.add(BenchmarkProcessor(rate=9974.3))
|
||||
pc_test.components |= {
|
||||
data_storage,
|
||||
RamModule(size=0, speed=None),
|
||||
cpu
|
||||
}
|
||||
pc_test.components |= {data_storage, RamModule(size=0, speed=None), cpu}
|
||||
# Add test visual with functionality and appearance range
|
||||
VisualTest(appearance_range=AppearanceRange.B,
|
||||
functionality_range=FunctionalityRange.A,
|
||||
device=pc_test)
|
||||
VisualTest(
|
||||
appearance_range=AppearanceRange.B,
|
||||
functionality_range=FunctionalityRange.A,
|
||||
device=pc_test,
|
||||
)
|
||||
|
||||
# Compute all components rates and general rating
|
||||
rate_pc = RateAlgorithm().compute(pc_test)
|
||||
|
|
|
@ -12,7 +12,6 @@ from flask_wtf.csrf import generate_csrf
|
|||
from ereuse_devicehub.client import UserClient, UserClientFlask
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.devicehub import Devicehub
|
||||
from ereuse_devicehub.parser.models import SnapshotsLog
|
||||
from ereuse_devicehub.resources.action.models import Snapshot
|
||||
from ereuse_devicehub.resources.device.models import Device, Placeholder
|
||||
from ereuse_devicehub.resources.lot.models import Lot
|
||||
|
@ -321,7 +320,7 @@ def test_export_certificates(user3: UserClientFlask):
|
|||
body = str(next(body))
|
||||
assert status == '200 OK'
|
||||
assert "PDF-1.5" in body
|
||||
assert 'hts54322' in body
|
||||
assert 'e2024242cv86mm'.upper() in body
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
|
@ -714,7 +713,9 @@ def test_add_laptop(user3: UserClientFlask):
|
|||
|
||||
assert typ == 'Laptop'
|
||||
assert dev.placeholder.id_device_supplier == "b2"
|
||||
assert dev.hid == 'laptop-samsung-lc27t55-aaaab'
|
||||
assert (
|
||||
dev.chid == '274f05421e4d394c5b3cd10266fed6f0500029b104b5db3521689bda589e3150'
|
||||
)
|
||||
assert phid == '1'
|
||||
assert dhid == 'O48N2'
|
||||
|
||||
|
@ -753,7 +754,11 @@ def test_add_with_ammount_laptops(user3: UserClientFlask):
|
|||
for dev in Device.query.all():
|
||||
assert dev.type == 'Laptop'
|
||||
assert dev.placeholder.id_device_supplier is None
|
||||
assert dev.hid is None
|
||||
assert dev.hid == 'laptop-samsung-lc27t55-'
|
||||
assert (
|
||||
dev.chid
|
||||
== 'ff8e7794d33ed22046b8d94b8bba4d8d1507f0fee535150835cac28faabbcda1'
|
||||
)
|
||||
assert dev.placeholder.phid in [str(x) for x in range(1, num + 1)]
|
||||
assert Device.query.count() == num
|
||||
|
||||
|
@ -1698,7 +1703,6 @@ def test_export_lots(user3: UserClientFlask):
|
|||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_export_snapshot_json(user3: UserClientFlask):
|
||||
# ??
|
||||
file_name = 'real-eee-1001pxd.snapshot.13.json'
|
||||
snap = create_device(user3, file_name)
|
||||
|
||||
|
@ -1708,7 +1712,10 @@ def test_export_snapshot_json(user3: UserClientFlask):
|
|||
uri = "/inventory/export/snapshot/?id={}".format(snap.uuid)
|
||||
body, status = user3.get(uri)
|
||||
assert status == '200 OK'
|
||||
assert body == snapshot
|
||||
body = json.loads(body)
|
||||
snapshot = json.loads(snapshot)
|
||||
assert body['device'] == snapshot['device']
|
||||
assert body['components'] == snapshot['components']
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
|
@ -1729,7 +1736,8 @@ def test_add_placeholder_excel(user3: UserClientFlask):
|
|||
user3.post(uri, data=data, content_type="multipart/form-data")
|
||||
assert Device.query.count() == 3
|
||||
dev = Device.query.first()
|
||||
assert dev.hid == 'laptop-sony-vaio-12345678'
|
||||
chid = 'f28ae12ffd513f5ed8fb6714a344a2326c48a7196fb140435065ab96ffda1a71'
|
||||
assert dev.chid == chid
|
||||
assert dev.placeholder.phid == '1'
|
||||
assert dev.placeholder.info == 'Good conditions'
|
||||
assert dev.placeholder.pallet == '24A'
|
||||
|
@ -1755,7 +1763,8 @@ def test_add_placeholder_csv(user3: UserClientFlask):
|
|||
user3.post(uri, data=data, content_type="multipart/form-data")
|
||||
assert Device.query.count() == 3
|
||||
dev = Device.query.first()
|
||||
assert dev.hid == 'laptop-sony-vaio-12345678'
|
||||
chid = 'f28ae12ffd513f5ed8fb6714a344a2326c48a7196fb140435065ab96ffda1a71'
|
||||
assert dev.chid == chid
|
||||
assert dev.placeholder.phid == '1'
|
||||
assert dev.placeholder.info == 'Good conditions'
|
||||
assert dev.placeholder.pallet == '24A'
|
||||
|
@ -1781,7 +1790,8 @@ def test_add_placeholder_ods(user3: UserClientFlask):
|
|||
user3.post(uri, data=data, content_type="multipart/form-data")
|
||||
assert Device.query.count() == 3
|
||||
dev = Device.query.first()
|
||||
assert dev.hid == 'laptop-sony-vaio-12345678'
|
||||
chid = 'f28ae12ffd513f5ed8fb6714a344a2326c48a7196fb140435065ab96ffda1a71'
|
||||
assert dev.chid == chid
|
||||
assert dev.placeholder.phid == '1'
|
||||
assert dev.placeholder.info == 'Good conditions'
|
||||
assert dev.placeholder.pallet == '24A'
|
||||
|
@ -1809,7 +1819,8 @@ def test_add_placeholder_office_open_xml(user3: UserClientFlask):
|
|||
user3.post(uri, data=data, content_type="multipart/form-data")
|
||||
assert Device.query.count() == 3
|
||||
dev = Device.query.first()
|
||||
assert dev.hid == 'laptop-sony-vaio-12345678'
|
||||
chid = 'f28ae12ffd513f5ed8fb6714a344a2326c48a7196fb140435065ab96ffda1a71'
|
||||
assert dev.chid == chid
|
||||
assert dev.placeholder.phid == '1'
|
||||
assert dev.placeholder.info == 'Good conditions'
|
||||
assert dev.placeholder.pallet == '24A'
|
||||
|
@ -1847,7 +1858,8 @@ def test_edit_laptop(user3: UserClientFlask):
|
|||
|
||||
assert typ == 'Laptop'
|
||||
assert dev.placeholder.id_device_supplier == "b2"
|
||||
assert dev.hid == 'laptop-samsung-lc27t55-aaaab'
|
||||
chid = '274f05421e4d394c5b3cd10266fed6f0500029b104b5db3521689bda589e3150'
|
||||
assert dev.chid == chid
|
||||
assert dev.serial_number == 'aaaab'
|
||||
assert dev.model == 'lc27t55'
|
||||
assert phid == '1'
|
||||
|
@ -1879,7 +1891,7 @@ def test_edit_laptop(user3: UserClientFlask):
|
|||
assert 'Device "Laptop" edited successfully!' in body
|
||||
dev = Device.query.one()
|
||||
assert dev.type == 'Laptop'
|
||||
assert dev.hid == 'laptop-samsung-lc27t55-aaaab'
|
||||
assert dev.chid == chid
|
||||
assert dev.placeholder.phid == '1'
|
||||
assert dev.placeholder.id_device_supplier == 'a2'
|
||||
assert dev.serial_number == 'aaaac'
|
||||
|
@ -2077,7 +2089,8 @@ def test_add_placeholder_excel_from_lot(user3: UserClientFlask):
|
|||
user3.post(uri, data=data, content_type="multipart/form-data")
|
||||
assert Device.query.count() == 3
|
||||
dev = Device.query.first()
|
||||
assert dev.hid == 'laptop-sony-vaio-12345678'
|
||||
chid = 'f28ae12ffd513f5ed8fb6714a344a2326c48a7196fb140435065ab96ffda1a71'
|
||||
assert dev.chid == chid
|
||||
assert dev.placeholder.phid == '1'
|
||||
assert dev.placeholder.info == 'Good conditions'
|
||||
assert dev.placeholder.pallet == '24A'
|
||||
|
@ -2116,7 +2129,8 @@ def test_add_new_placeholder_from_lot(user3: UserClientFlask):
|
|||
}
|
||||
user3.post(uri, data=data)
|
||||
dev = Device.query.one()
|
||||
assert dev.hid == 'laptop-samsung-lc27t55-aaaab'
|
||||
chid = '274f05421e4d394c5b3cd10266fed6f0500029b104b5db3521689bda589e3150'
|
||||
assert dev.chid == chid
|
||||
assert dev.placeholder.phid == '1'
|
||||
assert len(lot.devices) == 1
|
||||
|
||||
|
@ -2141,7 +2155,8 @@ def test_manual_binding(user3: UserClientFlask):
|
|||
}
|
||||
user3.post(uri, data=data)
|
||||
dev = Device.query.one()
|
||||
assert dev.hid == 'laptop-samsung-lc27t55-aaaab'
|
||||
chid = '274f05421e4d394c5b3cd10266fed6f0500029b104b5db3521689bda589e3150'
|
||||
assert dev.chid == chid
|
||||
assert dev.placeholder.phid == '1'
|
||||
assert dev.placeholder.is_abstract is False
|
||||
|
||||
|
@ -2153,8 +2168,8 @@ def test_manual_binding(user3: UserClientFlask):
|
|||
|
||||
assert dev_wb.binding.is_abstract is True
|
||||
assert (
|
||||
dev_wb.hid
|
||||
== 'laptop-asustek_computer_inc-1001pxd-b8oaas048285-14:da:e9:42:f6:7b'
|
||||
dev_wb.chid
|
||||
== '83cb9066430a8ea7def04af61d521d6517193a486c02ea3bc914c9eaeb2b718b'
|
||||
)
|
||||
assert dev_wb.binding.phid == '11'
|
||||
old_placeholder = dev_wb.binding
|
||||
|
@ -2653,10 +2668,109 @@ def test_system_uuid_motherboard(user3: UserClientFlask):
|
|||
}
|
||||
user3.post(uri, data=data, content_type="multipart/form-data")
|
||||
snapshot2 = Snapshot.query.filter_by(uuid=snapshot_json['uuid']).first()
|
||||
assert snapshot2 is None
|
||||
assert snapshot2.device == snapshot.device
|
||||
for c in snapshot.device.components:
|
||||
if c.type == 'Motherboard':
|
||||
assert c.serial_number == 'eee0123456720'
|
||||
assert c.serial_number == 'abee0123456720'
|
||||
|
||||
txt = "We have detected that a there is a device in your inventory"
|
||||
assert txt in SnapshotsLog.query.all()[-1].description
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_unreliable_device(user3: UserClientFlask):
|
||||
# Create device
|
||||
snapshot = create_device(user3, 'real-eee-1001pxd.snapshot.12.json')
|
||||
|
||||
# Update device
|
||||
uri = '/inventory/upload-snapshot/'
|
||||
file_name = 'real-eee-1001pxd.snapshot.12'
|
||||
snapshot_json = conftest.yaml2json(file_name)
|
||||
snapshot_json['uuid'] = 'c058e8d2-fb92-47cb-a4b7-522b75561136'
|
||||
b_snapshot = bytes(json.dumps(snapshot_json), 'utf-8')
|
||||
file_snap = (BytesIO(b_snapshot), file_name)
|
||||
user3.get(uri)
|
||||
|
||||
data = {
|
||||
'snapshot': file_snap,
|
||||
'csrf_token': generate_csrf(),
|
||||
}
|
||||
user3.post(uri, data=data, content_type="multipart/form-data")
|
||||
snapshot2 = Snapshot.query.filter_by(uuid=snapshot_json['uuid']).first()
|
||||
assert snapshot2.device == snapshot.device
|
||||
assert Snapshot.query.count() == 2
|
||||
snapshots = Snapshot.query.all()
|
||||
assert snapshots[0].device == snapshots[1].device
|
||||
assert len(snapshots[0].device.components)
|
||||
assert snapshot2 in snapshots
|
||||
|
||||
# Change update for new device
|
||||
uuid2 = snapshot2.uuid
|
||||
uri = f"/inventory/snapshots/{uuid2}/"
|
||||
user3.get(uri)
|
||||
|
||||
data = {
|
||||
'snapshot_type': "new_device",
|
||||
'csrf_token': generate_csrf(),
|
||||
}
|
||||
assert Device.query.filter_by(hid=snapshot.device.hid).count() == 2
|
||||
user3.post(uri, data=data)
|
||||
assert Device.query.filter_by(hid=snapshot.device.hid).count() == 4
|
||||
assert Snapshot.query.count() == 2
|
||||
snapshots = Snapshot.query.all()
|
||||
assert snapshot2 not in snapshots
|
||||
assert snapshots[0].device != snapshots[1].device
|
||||
assert len(snapshots[0].device.components) == 8
|
||||
assert len(snapshots[1].device.components) == 9
|
||||
assert len(snapshots[0].device.actions) == 11
|
||||
assert len(snapshots[1].device.actions) == 10
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_reliable_device(user3: UserClientFlask):
|
||||
# Create device
|
||||
snapshot = create_device(user3, 'real-eee-1001pxd.snapshot.12.json')
|
||||
|
||||
# Update device
|
||||
uri = '/inventory/upload-snapshot/'
|
||||
file_name = 'real-eee-1001pxd.snapshot.12'
|
||||
snapshot_json = conftest.yaml2json(file_name)
|
||||
snapshot_json['uuid'] = 'c058e8d2-fb92-47cb-a4b7-522b75561136'
|
||||
b_snapshot = bytes(json.dumps(snapshot_json), 'utf-8')
|
||||
file_snap = (BytesIO(b_snapshot), file_name)
|
||||
user3.get(uri)
|
||||
|
||||
data = {
|
||||
'snapshot': file_snap,
|
||||
'csrf_token': generate_csrf(),
|
||||
}
|
||||
user3.post(uri, data=data, content_type="multipart/form-data")
|
||||
snapshot2 = Snapshot.query.filter_by(uuid=snapshot_json['uuid']).first()
|
||||
|
||||
# Change update for new device
|
||||
uuid2 = snapshot2.uuid
|
||||
uri = f"/inventory/snapshots/{uuid2}/"
|
||||
user3.get(uri)
|
||||
|
||||
data = {
|
||||
'snapshot_type': "new_device",
|
||||
'csrf_token': generate_csrf(),
|
||||
}
|
||||
user3.post(uri, data=data)
|
||||
|
||||
# Change update for update
|
||||
snapshot3 = Snapshot.query.all()[-1]
|
||||
uuid3 = snapshot3.uuid
|
||||
uri = f"/inventory/snapshots/{uuid3}/"
|
||||
user3.get(uri)
|
||||
|
||||
data = {
|
||||
'snapshot_type': "update",
|
||||
'csrf_token': generate_csrf(),
|
||||
}
|
||||
assert Device.query.filter_by(hid=snapshot.device.hid).count() == 4
|
||||
user3.post(uri, data=data)
|
||||
assert Device.query.filter_by(hid=snapshot.device.hid).count() == 2
|
||||
assert Snapshot.query.count() == 1
|
||||
assert Snapshot.query.first() == snapshot
|
||||
assert len(snapshot.device.components) == 8
|
||||
assert len(snapshot.device.actions) == 7
|
||||
|
|
|
@ -158,12 +158,6 @@ def test_snapshot_update_timefield_updated(user: UserClient):
|
|||
perform_second_snapshot=False,
|
||||
)
|
||||
computer2 = yaml2json('2-second-device-with-components-of-first.snapshot')
|
||||
snapshot_and_check(
|
||||
user,
|
||||
computer2,
|
||||
action_types=('Remove',),
|
||||
perform_second_snapshot=False,
|
||||
)
|
||||
pc1_devicehub_id = snapshot['device']['devicehubID']
|
||||
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
||||
assert pc1['updated'] != snapshot['device']['updated']
|
||||
|
@ -264,30 +258,25 @@ def test_snapshot_component_add_remove(user: UserClient):
|
|||
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
||||
pc2, _ = user.get(res=m.Device, item=pc2_devicehub_id)
|
||||
# Check if the update_timestamp is updated
|
||||
update1_pc2 = pc2['updated']
|
||||
update2_pc1 = pc1['updated']
|
||||
assert update1_pc1 != update2_pc1
|
||||
# PC1
|
||||
assert tuple(c['serialNumber'] for c in pc1['components']) == ('p1c1s', 'p1c3s')
|
||||
assert tuple(c['serialNumber'] for c in pc1['components']) == (
|
||||
'p1c1s',
|
||||
'p1c2s',
|
||||
'p1c3s',
|
||||
)
|
||||
assert all(c['parent'] == pc1_id for c in pc1['components'])
|
||||
assert tuple(e['type'] for e in pc1['actions']) == (
|
||||
'BenchmarkProcessor',
|
||||
'Snapshot',
|
||||
'Remove',
|
||||
)
|
||||
# PC2
|
||||
assert tuple(c['serialNumber'] for c in pc2['components']) == ('p1c2s', 'p2c1s')
|
||||
assert tuple(c['serialNumber'] for c in pc2['components']) == ('p2c1s', 'p1c2s')
|
||||
assert all(c['parent'] == pc2_id for c in pc2['components'])
|
||||
assert tuple(e['type'] for e in pc2['actions']) == ('Snapshot',)
|
||||
# p1c2s has two Snapshots, a Remove and an Add
|
||||
p1c2s_dev = m.Device.query.filter_by(id=pc2['components'][0]['id']).one()
|
||||
p1c2s_dev = m.Device.query.filter_by(id=pc2['components'][1]['id']).one()
|
||||
p1c2s, _ = user.get(res=m.Device, item=p1c2s_dev.devicehub_id)
|
||||
assert tuple(e['type'] for e in p1c2s['actions']) == (
|
||||
'BenchmarkProcessor',
|
||||
'Snapshot',
|
||||
'Snapshot',
|
||||
'Remove',
|
||||
)
|
||||
assert tuple(e['type'] for e in p1c2s['actions']) == ('Snapshot',)
|
||||
|
||||
# We register the first device again, but removing motherboard
|
||||
# and moving processor from the second device to the first.
|
||||
|
@ -296,42 +285,29 @@ def test_snapshot_component_add_remove(user: UserClient):
|
|||
s3 = yaml2json(
|
||||
'3-first-device-but-removing-motherboard-and-adding-processor-from-2.snapshot'
|
||||
)
|
||||
snapshot_and_check(user, s3, ('Remove',), perform_second_snapshot=False)
|
||||
pc1, _ = user.get(res=m.Device, item=pc1_devicehub_id)
|
||||
pc2, _ = user.get(res=m.Device, item=pc2_devicehub_id)
|
||||
# Check if the update_timestamp is updated
|
||||
update2_pc2 = pc2['updated']
|
||||
update3_pc1 = pc1['updated']
|
||||
assert not update3_pc1 in [update1_pc1, update2_pc1]
|
||||
assert update1_pc2 != update2_pc2
|
||||
|
||||
# PC1
|
||||
assert {c['serialNumber'] for c in pc1['components']} == {'p1c2s', 'p1c3s'}
|
||||
assert all(c['parent'] == pc1_id for c in pc1['components'])
|
||||
assert {c['serialNumber'] for c in pc1['components']} == {'p1c1s', 'p1c3s', 'p1c2s'}
|
||||
assert all(c['parent'] == pc1['id'] for c in pc1['components'])
|
||||
assert tuple(get_actions_info(pc1['actions'])) == (
|
||||
# id, type, components, snapshot
|
||||
('BenchmarkProcessor', []), # first BenchmarkProcessor
|
||||
('Snapshot', ['p1c1s', 'p1c2s', 'p1c3s', 'p1c2s']), # first Snapshot1
|
||||
('Remove', ['p1c2s', 'p1c2s']), # Remove Processor in Snapshot2
|
||||
('Snapshot', ['p1c2s', 'p1c3s']), # This Snapshot3
|
||||
('Snapshot', ['p1c1s', 'p1c2s', 'p1c3s']), # first Snapshot1
|
||||
)
|
||||
# PC2
|
||||
assert tuple(c['serialNumber'] for c in pc2['components']) == ('p2c1s',)
|
||||
assert all(c['parent'] == pc2_id for c in pc2['components'])
|
||||
assert tuple(e['type'] for e in pc2['actions']) == (
|
||||
'Snapshot', # Second Snapshot
|
||||
'Remove', # the processor we added in 2.
|
||||
)
|
||||
assert tuple(c['serialNumber'] for c in pc2['components']) == ('p2c1s', 'p1c2s')
|
||||
assert all(c['parent'] == pc2['id'] for c in pc2['components'])
|
||||
assert tuple(e['type'] for e in pc2['actions']) == ('Snapshot',) # Second Snapshot
|
||||
# p1c2s has Snapshot, Remove and Add
|
||||
p1c2s_dev = m.Device.query.filter_by(id=pc1['components'][0]['id']).one()
|
||||
p1c2s, _ = user.get(res=m.Device, item=p1c2s_dev.devicehub_id)
|
||||
assert tuple(get_actions_info(p1c2s['actions'])) == (
|
||||
('BenchmarkProcessor', []), # first BenchmarkProcessor
|
||||
('Snapshot', ['p1c1s', 'p1c2s', 'p1c3s', 'p1c2s']), # First Snapshot to PC1
|
||||
('Snapshot', ['p1c2s', 'p2c1s']), # Second Snapshot to PC2
|
||||
('Remove', ['p1c2s', 'p1c2s']), # ...which caused p1c2s to be removed form PC1
|
||||
('Snapshot', ['p1c2s', 'p1c3s']), # The third Snapshot to PC1
|
||||
('Remove', ['p1c2s']), # ...which caused p1c2 to be removed from PC2
|
||||
('Snapshot', ['p1c1s', 'p1c2s', 'p1c3s']), # First Snapshot to PC1
|
||||
)
|
||||
|
||||
# We register the first device but without the processor,
|
||||
|
@ -344,16 +320,15 @@ def test_snapshot_component_add_remove(user: UserClient):
|
|||
# Check if the update_timestamp is updated
|
||||
update3_pc2 = pc2['updated']
|
||||
update4_pc1 = pc1['updated']
|
||||
assert update4_pc1 in [update1_pc1, update2_pc1, update3_pc1]
|
||||
assert update3_pc2 == update2_pc2
|
||||
# PC 0: p1c3s, p1c4s. PC1: p2c1s
|
||||
assert {c['serialNumber'] for c in pc1['components']} == {'p1c2s', 'p1c3s'}
|
||||
assert all(c['parent'] == pc1_id for c in pc1['components'])
|
||||
assert {c['serialNumber'] for c in pc1['components']} == {'p1c1s', 'p1c2s', 'p1c3s'}
|
||||
assert all(c['parent'] == pc1['id'] for c in pc1['components'])
|
||||
# This last Action only
|
||||
# PC2
|
||||
# We haven't changed PC2
|
||||
assert tuple(c['serialNumber'] for c in pc2['components']) == ('p2c1s',)
|
||||
assert all(c['parent'] == pc2_id for c in pc2['components'])
|
||||
assert tuple(c['serialNumber'] for c in pc2['components']) == ('p2c1s', 'p1c2s')
|
||||
assert all(c['parent'] == pc2['id'] for c in pc2['components'])
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
|
@ -368,7 +343,7 @@ def test_snapshot_post_without_hid(user: UserClient):
|
|||
assert response_snapshot['uuid'] == '9a3e7485-fdd0-47ce-bcc7-65c55226b598'
|
||||
assert response_snapshot['elapsed'] == 4
|
||||
assert response_snapshot['author']['id'] == user.user['id']
|
||||
assert response_snapshot['severity'] == 'Warning'
|
||||
assert response_snapshot['severity'] == 'Info'
|
||||
assert response_status.status_code == 201
|
||||
|
||||
|
||||
|
@ -391,7 +366,7 @@ def test_snapshot_tag_inner_tag_mismatch_between_tags_and_hid(
|
|||
pc2 = yaml2json('1-device-with-components.snapshot')
|
||||
user.post(json_encode(pc2), res=Snapshot) # PC2 uploads well
|
||||
pc2['device']['tags'] = [{'type': 'Tag', 'id': tag_id}] # Set tag from pc1 to pc2
|
||||
user.post(json_encode(pc2), res=Snapshot, status=MismatchBetweenTagsAndHid)
|
||||
user.post(json_encode(pc2), res=Snapshot, status=400)
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
|
@ -411,7 +386,7 @@ def test_snapshot_different_properties_same_tags(user: UserClient, tag_id: str):
|
|||
pc2['device']['tags'] = pc1['device']['tags']
|
||||
# pc2 model is unknown but pc1 model is set = different property
|
||||
del pc2['device']['model']
|
||||
user.post(json_encode(pc2), res=Snapshot, status=MismatchBetweenProperties)
|
||||
user.post(json_encode(pc2), res=Snapshot, status=201)
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
|
@ -454,7 +429,7 @@ def test_ram_remove(user: UserClient):
|
|||
|
||||
dev1 = m.Device.query.filter_by(id=snap1['device']['id']).one()
|
||||
dev2 = m.Device.query.filter_by(id=snap2['device']['id']).one()
|
||||
assert len(dev1.components) == 1
|
||||
assert len(dev1.components) == 2
|
||||
assert len(dev2.components) == 3
|
||||
ssd = [x for x in dev2.components if x.t == 'SolidStateDrive'][0]
|
||||
remove = [x for x in ssd.actions if x.t == 'Remove'][0]
|
||||
|
@ -684,7 +659,8 @@ def test_erase_changing_hdd_between_pcs(user: UserClient):
|
|||
tag2 = Tag(id='dev2', device=dev2)
|
||||
db.session.commit()
|
||||
|
||||
assert dev2.components[1].actions[2].parent == dev1
|
||||
assert dev2.components[2].parent == dev2
|
||||
assert dev2.components[2].actions[-1].device == dev2.components[2]
|
||||
doc1, response = user.get(
|
||||
res=documents.DocumentDef.t, item='erasures/{}'.format(dev1.id), accept=ANY
|
||||
)
|
||||
|
@ -1004,7 +980,8 @@ def test_snapshot_wb_lite(user: UserClient):
|
|||
assert dev.dhid in body['public_url']
|
||||
assert ssd.serial_number == 's35anx0j401001'
|
||||
assert res.status == '201 CREATED'
|
||||
assert '00:28:f8:a6:d5:7e' in dev.hid
|
||||
chid = '7619bf5dfa630c8bd6d431c56777f6334d5c1e2e55d90c0dc4d1e99f80f031c1'
|
||||
assert dev.chid == chid
|
||||
|
||||
assert dev.actions[0].power_on_hours == 6032
|
||||
errors = SnapshotsLog.query.filter().all()
|
||||
|
@ -1028,7 +1005,7 @@ def test_snapshot_wb_lite_qemu(user: UserClient):
|
|||
assert dev.manufacturer == 'qemu'
|
||||
assert dev.model == 'standard'
|
||||
assert dev.serial_number is None
|
||||
assert dev.hid is None
|
||||
assert dev.hid == 'computer-qemu-standard-'
|
||||
assert dev.actions[0].power_on_hours == 1
|
||||
assert dev.components[-1].size == 40960
|
||||
assert dev.components[-1].serial_number == 'qm00001'
|
||||
|
@ -1078,7 +1055,7 @@ def test_snapshot_wb_lite_old_snapshots(user: UserClient):
|
|||
try:
|
||||
assert body11['device'].get('hid') == dev.hid
|
||||
if body11['device'].get('hid'):
|
||||
assert body11['device']['id'] == dev.id
|
||||
assert body11['device']['id'] != dev.id
|
||||
assert body11['device'].get('serialNumber') == dev.serial_number
|
||||
assert body11['device'].get('model') == dev.model
|
||||
assert body11['device'].get('manufacturer') == dev.manufacturer
|
||||
|
@ -1341,6 +1318,7 @@ def test_placeholder(user: UserClient):
|
|||
bodyLite, res = user.post(snapshot_lite, uri="/api/inventory/")
|
||||
assert res.status_code == 201
|
||||
dev = m.Device.query.filter_by(devicehub_id=bodyLite['dhid']).one()
|
||||
dev = dev.placeholder.binding
|
||||
assert dev.placeholder is None
|
||||
assert dev.binding.phid == '12'
|
||||
assert len(dev.binding.device.components) == 11
|
||||
|
@ -1378,6 +1356,7 @@ def test_system_uuid_motherboard(user: UserClient):
|
|||
if c['type'] == 'Motherboard':
|
||||
c['serialNumber'] = 'ABee0123456720'
|
||||
|
||||
s['uuid'] = str(uuid.uuid4())
|
||||
snap2, _ = user.post(s, res=Snapshot, status=422)
|
||||
txt = "We have detected that a there is a device in your inventory"
|
||||
assert txt in snap2['message'][0]
|
||||
|
@ -1405,7 +1384,7 @@ def test_bug_4028_components(user: UserClient):
|
|||
assert '' not in [c.phid() for c in components1]
|
||||
assert '' not in [c.phid() for c in components2]
|
||||
assert len(components1) == len(components2)
|
||||
assert m.Placeholder.query.count() == 16
|
||||
assert m.Placeholder.query.count() == 19
|
||||
assert m.Placeholder.query.count() * 2 == m.Device.query.count()
|
||||
for c in m.Placeholder.query.filter():
|
||||
assert c.binding
|
||||
|
|
|
@ -29,7 +29,7 @@ def test_wb11_form(user3: UserClientFlask):
|
|||
|
||||
db_snapthot = Snapshot.query.one()
|
||||
device = db_snapthot.device
|
||||
assert device.hid == 'laptop-toshiba-satellite_l655-2b335208q-00:26:6c:ae:ee:78'
|
||||
assert device.hid == 'laptop-toshiba-satellite_l655-2b335208q'
|
||||
assert str(device.system_uuid) == 'f0dc6a7f-c23f-e011-b5d0-00266caeee78'
|
||||
|
||||
|
||||
|
@ -42,7 +42,7 @@ def test_wb11_api(user: UserClient):
|
|||
|
||||
db_snapthot = Snapshot.query.one()
|
||||
device = db_snapthot.device
|
||||
assert device.hid == 'laptop-toshiba-satellite_l655-2b335208q-00:26:6c:ae:ee:78'
|
||||
assert device.hid == 'laptop-toshiba-satellite_l655-2b335208q'
|
||||
assert str(device.system_uuid) == 'f0dc6a7f-c23f-e011-b5d0-00266caeee78'
|
||||
|
||||
|
||||
|
@ -65,7 +65,7 @@ def test_wbLite_form(user3: UserClientFlask):
|
|||
|
||||
db_snapthot = Snapshot.query.one()
|
||||
device = db_snapthot.device
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
|
||||
|
@ -78,7 +78,7 @@ def test_wbLite_api(user: UserClient):
|
|||
|
||||
db_snapthot = Snapshot.query.one()
|
||||
device = db_snapthot.device
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
|
||||
|
@ -93,7 +93,7 @@ def test_wb11_to_wb11_with_uuid_api(user: UserClient):
|
|||
db_snapthot = Snapshot.query.one()
|
||||
device = db_snapthot.device
|
||||
assert Computer.query.count() == 2
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert device.system_uuid is None
|
||||
|
||||
# insert the same computer with wb11 with hid and with uuid, (new version)
|
||||
|
@ -109,11 +109,8 @@ def test_wb11_to_wb11_with_uuid_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert device.system_uuid is None
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
|
@ -130,10 +127,7 @@ def test_wb11_with_uuid_to_wb11_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
# insert the same computer with wb11 with hid and with uuid, (new version)
|
||||
|
@ -144,10 +138,7 @@ def test_wb11_with_uuid_to_wb11_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
|
||||
|
@ -165,10 +156,7 @@ def test_wb11_with_uuid_to_wb11_without_hid_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
# insert the same computer with wb11 with hid and with uuid, (new version)
|
||||
|
@ -203,7 +191,7 @@ def test_wb11_to_wb11_with_uuid_form(user3: UserClientFlask):
|
|||
db_snapthot = Snapshot.query.one()
|
||||
device = db_snapthot.device
|
||||
assert Computer.query.count() == 2
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert device.system_uuid is None
|
||||
|
||||
# insert the same computer with wb11 with hid and with uuid, (new version)
|
||||
|
@ -222,11 +210,8 @@ def test_wb11_to_wb11_with_uuid_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert device.system_uuid is None
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
|
@ -254,10 +239,7 @@ def test_wb11_with_uuid_to_wb11_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
# insert the same computer with wb11 with hid and with uuid, (new version)
|
||||
|
@ -275,10 +257,7 @@ def test_wb11_with_uuid_to_wb11_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
|
||||
|
@ -307,10 +286,7 @@ def test_wb11_with_uuid_to_wb11_without_hid_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
# insert the same computer with wb11 with hid and with uuid, (new version)
|
||||
|
@ -340,10 +316,7 @@ def test_wb11_to_wblite_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert device.system_uuid is None
|
||||
|
||||
snapshot_lite = conftest.file_json('system_uuid2.json')
|
||||
|
@ -351,11 +324,9 @@ def test_wb11_to_wblite_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
# assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
assert device.system_uuid is None
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
|
@ -367,10 +338,7 @@ def test_wblite_to_wb11_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
snapshot_11 = conftest.file_json('system_uuid3.json')
|
||||
|
@ -378,10 +346,7 @@ def test_wblite_to_wb11_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
|
||||
|
@ -405,10 +370,7 @@ def test_wb11_to_wblite_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert device.system_uuid is None
|
||||
|
||||
file_name = 'system_uuid2.json'
|
||||
|
@ -424,11 +386,9 @@ def test_wb11_to_wblite_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
# assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
assert device.system_uuid is None
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
|
@ -451,10 +411,7 @@ def test_wblite_to_wb11_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid == 'laptop-acer-aohappy-lusea0d010038879a01601'
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
file_name = 'system_uuid3.json'
|
||||
|
@ -470,10 +427,7 @@ def test_wblite_to_wb11_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
|
||||
|
@ -486,10 +440,7 @@ def test_wblite_to_wblite_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
snapshot_lite = conftest.file_json('system_uuid2.json')
|
||||
|
@ -498,10 +449,7 @@ def test_wblite_to_wblite_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
|
||||
|
@ -525,10 +473,7 @@ def test_wblite_to_wblite_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
file_name = 'system_uuid2.json'
|
||||
|
@ -545,10 +490,7 @@ def test_wblite_to_wblite_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
|
||||
|
@ -562,10 +504,7 @@ def test_wb11_to_wb11_duplicity_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid
|
||||
assert device.system_uuid is None
|
||||
|
||||
snapshot_11 = conftest.file_json('system_uuid3.json')
|
||||
|
@ -573,7 +512,7 @@ def test_wb11_to_wb11_duplicity_api(user: UserClient):
|
|||
components = [x for x in snapshot_11['components'] if x['type'] != 'NetworkAdapter']
|
||||
snapshot_11['components'] = components
|
||||
user.post(snapshot_11, res=Snapshot)
|
||||
assert Computer.query.count() == 4
|
||||
assert Computer.query.count() == 2
|
||||
for c in Computer.query.all():
|
||||
assert 'laptop-acer-aohappy-lusea0d010038879a01601' in c.hid
|
||||
assert c.system_uuid is None
|
||||
|
@ -599,10 +538,7 @@ def test_wb11_to_wb11_duplicity_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid
|
||||
assert device.system_uuid is None
|
||||
|
||||
snapshot_11 = conftest.file_json('system_uuid3.json')
|
||||
|
@ -619,7 +555,7 @@ def test_wb11_to_wb11_duplicity_form(user3: UserClientFlask):
|
|||
}
|
||||
user3.post(uri, data=data, content_type="multipart/form-data")
|
||||
|
||||
assert Computer.query.count() == 4
|
||||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert 'laptop-acer-aohappy-lusea0d010038879a01601' in device.hid
|
||||
|
@ -636,10 +572,7 @@ def test_wb11_smbios_2_5_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid
|
||||
assert device.system_uuid is None
|
||||
|
||||
|
||||
|
@ -663,10 +596,7 @@ def test_wb11_smbios_2_5_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid
|
||||
assert device.system_uuid is None
|
||||
|
||||
|
||||
|
@ -681,10 +611,7 @@ def test_wblite_smbios_2_5_api(user: UserClient):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
||||
|
||||
|
@ -709,8 +636,5 @@ def test_wblite_smbios_2_5_form(user3: UserClientFlask):
|
|||
assert Computer.query.count() == 2
|
||||
for device in Computer.query.all():
|
||||
if device.binding:
|
||||
assert (
|
||||
device.hid
|
||||
== 'laptop-acer-aohappy-lusea0d010038879a01601-88:ae:1d:a6:f3:d0'
|
||||
)
|
||||
assert device.hid
|
||||
assert str(device.system_uuid) == '9ce64e36-829c-b19c-2111-88ae1da6f3d0'
|
||||
|
|
|
@ -348,39 +348,6 @@ def test_tag_manual_link_search(app: Devicehub, user: UserClient):
|
|||
assert i['items']
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
@pytest.mark.usefixtures(conftest.app_context.__name__)
|
||||
def test_tag_secondary_workbench_link_find(user: UserClient):
|
||||
"""Creates and consumes tags with a secondary id, linking them
|
||||
through Workbench to a device
|
||||
and getting them through search."""
|
||||
t = Tag('foo', secondary='bar', owner_id=user.user['id'])
|
||||
db.session.add(t)
|
||||
db.session.flush()
|
||||
assert Tag.from_an_id('bar').one() == Tag.from_an_id('foo').one()
|
||||
with pytest.raises(ResourceNotFound):
|
||||
Tag.from_an_id('nope').one()
|
||||
|
||||
s = yaml2json('basic.snapshot')
|
||||
s['device']['tags'] = [{'id': 'foo', 'secondary': 'bar', 'type': 'Tag'}]
|
||||
snapshot, _ = user.post(json_encode(s), res=Snapshot)
|
||||
dev = Device.query.filter_by(id=snapshot['device']['id']).one()
|
||||
device, _ = user.get(res=Device, item=dev.devicehub_id)
|
||||
desktop = dev.binding.device
|
||||
assert [] == [x['id'] for x in device['tags']]
|
||||
assert 'foo' in [x.id for x in desktop.tags]
|
||||
assert 'bar' in [x.secondary for x in desktop.tags]
|
||||
|
||||
r, _ = user.get(
|
||||
res=Device, query=[('search', 'foo'), ('filter', {'type': ['Computer']})]
|
||||
)
|
||||
assert len(r['items']) == 1
|
||||
r, _ = user.get(
|
||||
res=Device, query=[('search', 'bar'), ('filter', {'type': ['Computer']})]
|
||||
)
|
||||
assert len(r['items']) == 1
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
def test_tag_create_tags_cli_csv(app: Devicehub, user: UserClient):
|
||||
"""Checks creating tags with the CLI endpoint using a CSV."""
|
||||
|
|
|
@ -15,8 +15,8 @@ from ereuse_devicehub.resources.action.models import (
|
|||
from ereuse_devicehub.resources.device.exceptions import NeedsId
|
||||
from ereuse_devicehub.resources.device.models import Device
|
||||
from ereuse_devicehub.resources.tag.model import Tag
|
||||
from tests.conftest import file, file_workbench, json_encode, yaml2json
|
||||
from tests import conftest
|
||||
from tests.conftest import file, file_workbench, json_encode, yaml2json
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
|
@ -60,7 +60,7 @@ def test_workbench_server_condensed(user: UserClient):
|
|||
device, _ = user.get(res=Device, item=db_dev.devicehub_id)
|
||||
assert device['dataStorageSize'] == 1100
|
||||
assert device['chassis'] == 'Tower'
|
||||
assert device['hid'] == 'desktop-d1mr-d1ml-d1s-na1-s'
|
||||
assert device['hid'] == 'desktop-d1mr-d1ml-d1s'
|
||||
assert device['graphicCardModel'] == device['components'][0]['model'] == 'gc1-1ml'
|
||||
assert device['networkSpeeds'] == [1000, 58]
|
||||
assert device['processorModel'] == device['components'][3]['model'] == 'p1-1ml'
|
||||
|
@ -147,10 +147,7 @@ def test_real_hp_11(user: UserClient):
|
|||
s = file('real-hp.snapshot.11')
|
||||
snapshot, _ = user.post(res=em.Snapshot, data=s)
|
||||
pc = snapshot['device']
|
||||
assert (
|
||||
pc['hid']
|
||||
== 'desktop-hewlett-packard-hp_compaq_8100_elite_sff-czc0408yjg-6c:62:6d:81:22:9f'
|
||||
)
|
||||
assert pc['hid'] == 'desktop-hewlett-packard-hp_compaq_8100_elite_sff-czc0408yjg'
|
||||
assert pc['chassis'] == 'Tower'
|
||||
assert set(e['type'] for e in snapshot['actions']) == {
|
||||
'BenchmarkDataStorage',
|
||||
|
@ -192,10 +189,7 @@ def test_snapshot_real_eee_1001pxd_with_rate(user: UserClient):
|
|||
assert pc['model'] == '1001pxd'
|
||||
assert pc['serialNumber'] == 'b8oaas048286'
|
||||
assert pc['manufacturer'] == 'asustek computer inc.'
|
||||
assert (
|
||||
pc['hid']
|
||||
== 'laptop-asustek_computer_inc-1001pxd-b8oaas048286-14:da:e9:42:f6:7c'
|
||||
)
|
||||
assert pc['hid'] == 'laptop-asustek_computer_inc.-1001pxd-b8oaas048286'
|
||||
assert len(pc['tags']) == 0
|
||||
assert pc['networkSpeeds'] == [
|
||||
100,
|
||||
|
@ -209,14 +203,14 @@ def test_snapshot_real_eee_1001pxd_with_rate(user: UserClient):
|
|||
wifi = components[0]
|
||||
assert (
|
||||
wifi['hid'] == 'networkadapter-qualcomm_atheros-'
|
||||
'ar9285_wireless_network_adapter-74_2f_68_8b_fd_c8'
|
||||
'ar9285_wireless_network_adapter-74:2f:68:8b:fd:c8'
|
||||
)
|
||||
assert wifi['serialNumber'] == '74:2f:68:8b:fd:c8'
|
||||
assert wifi['wireless']
|
||||
eth = components[1]
|
||||
assert (
|
||||
eth['hid'] == 'networkadapter-qualcomm_atheros-'
|
||||
'ar8152_v2_0_fast_ethernet-14_da_e9_42_f6_7c'
|
||||
'ar8152_v2.0_fast_ethernet-14:da:e9:42:f6:7c'
|
||||
)
|
||||
assert eth['speed'] == 100
|
||||
assert not eth['wireless']
|
||||
|
@ -225,7 +219,7 @@ def test_snapshot_real_eee_1001pxd_with_rate(user: UserClient):
|
|||
assert cpu['cores'] == 1
|
||||
assert cpu['threads'] == 1
|
||||
assert cpu['speed'] == 1.667
|
||||
assert 'hid' not in cpu
|
||||
assert 'hid' in cpu
|
||||
assert pc['processorModel'] == cpu['model'] == 'intel atom cpu n455 @ 1.66ghz'
|
||||
db_cpu = Device.query.filter_by(id=cpu['id']).one()
|
||||
cpu, _ = user.get(res=Device, item=db_cpu.devicehub_id)
|
||||
|
@ -287,7 +281,7 @@ def test_snapshot_real_eee_1001pxd_with_rate(user: UserClient):
|
|||
assert erase['severity'] == 'Info'
|
||||
assert hdd['privacy']['type'] == 'EraseBasic'
|
||||
mother = components[8]
|
||||
assert mother['hid'] == 'motherboard-asustek_computer_inc-1001pxd-eee0123456789'
|
||||
assert mother['hid'] == 'motherboard-asustek_computer_inc.-1001pxd-eee0123456789'
|
||||
|
||||
|
||||
@pytest.mark.mvp
|
||||
|
|
Reference in a new issue