Compare commits

..

2 Commits
main ... dpp

Author SHA1 Message Date
Cayo Puigdefabregas 0d574cae63 register device and dpp in dlt and dpp api 2024-11-18 19:37:08 +01:00
Cayo Puigdefabregas 9857891b63 first base for dpp 2024-11-15 18:56:11 +01:00
17 changed files with 327 additions and 5 deletions

View File

@ -29,6 +29,9 @@
<li class="nav-item"> <li class="nav-item">
<a href="#evidences" class="nav-link" data-bs-toggle="tab" data-bs-target="#evidences">{% trans 'Evidences' %}</a> <a href="#evidences" class="nav-link" data-bs-toggle="tab" data-bs-target="#evidences">{% trans 'Evidences' %}</a>
</li> </li>
<li class="nav-item">
<a href="#dpps" class="nav-link" data-bs-toggle="tab" data-bs-target="#evidences">{% trans 'Dpps' %}</a>
</li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{% url 'device:device_web' object.id %}" target="_blank">Web</a> <a class="nav-link" href="{% url 'device:device_web' object.id %}" target="_blank">Web</a>
</li> </li>
@ -229,6 +232,22 @@
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
<div class="tab-pane fade" id="dpps">
<h5 class="card-title">{% trans 'List of dpps' %}</h5>
<div class="list-group col-6">
{% for d in dpps %}
<div class="list-group-item">
<div class="d-flex w-100 justify-content-between">
<small class="text-muted">{{ d.timestamp }}</small>
</div>
<p class="mb-1">
<a href="{% url 'evidence:details' d.uuid %}">{{ d.signature }}</a>
</p>
</div>
{% endfor %}
</div>
</div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -14,6 +14,7 @@ from django.views.generic.base import TemplateView
from dashboard.mixins import DashboardView, Http403 from dashboard.mixins import DashboardView, Http403
from evidence.models import Annotation from evidence.models import Annotation
from lot.models import LotTag from lot.models import LotTag
from dpp.models import Proof
from device.models import Device from device.models import Device
from device.forms import DeviceFormSet from device.forms import DeviceFormSet
@ -103,10 +104,12 @@ class DetailsView(DashboardView, TemplateView):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
self.object.initial() self.object.initial()
lot_tags = LotTag.objects.filter(owner=self.request.user.institution) lot_tags = LotTag.objects.filter(owner=self.request.user.institution)
dpps = Proof.objects.filter(uuid_in=self.object.uuids)
context.update({ context.update({
'object': self.object, 'object': self.object,
'snapshot': self.object.get_last_evidence(), 'snapshot': self.object.get_last_evidence(),
'lot_tags': lot_tags, 'lot_tags': lot_tags,
'dpps': dpps,
}) })
return context return context

View File

@ -89,6 +89,7 @@ INSTALLED_APPS = [
"dashboard", "dashboard",
"admin", "admin",
"api", "api",
"dpp",
] ]

View File

@ -27,4 +27,5 @@ urlpatterns = [
path("user/", include("user.urls")), path("user/", include("user.urls")),
path("lot/", include("lot.urls")), path("lot/", include("lot.urls")),
path('api/', include('api.urls')), path('api/', include('api.urls')),
path('dpp/', include('dpp.urls')),
] ]

0
dpp/__init__.py Normal file
View File

3
dpp/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

151
dpp/api_dlt.py Normal file
View File

@ -0,0 +1,151 @@
import time
import logging
from django.conf import settings
from ereuseapi.methods import API
from dpp.models import Proof, Dpp
logger = logging.getLogger('django')
# """The code of the status response of api dlt."""
STATUS_CODE = {
"Success": 201,
"Notwork": 400
}
ALGORITHM = "sha3-256"
PROOF_TYPE = {
'Register': 'Register',
'IssueDPP': 'IssueDPP',
'proof_of_recycling': 'proof_of_recycling',
'Erase': 'Erase',
'EWaste': 'EWaste',
}
def connect_api():
if not settings.get('TOKEN_DLT'):
return
token_dlt = settings.get('TOKEN_DLT')
api_dlt = settings.get('API_DLT')
return API(api_dlt, token_dlt, "ethereum")
def register_dlt(chid, phid, proof_type=None):
api = connect_api()
if not api:
return
if proof_type:
return api.generate_proof(
chid,
ALGORITHM,
phid,
proof_type,
settings.get('ID_FEDERATED')
)
return api.register_device(
chid,
ALGORITHM,
phid,
settings.get('ID_FEDERATED')
)
def issuer_dpp_dlt(dpp):
phid = dpp.split(":")[0]
api = connect_api()
if not api:
return
return api.issue_passport(
dpp,
ALGORITHM,
phid,
settings.get('ID_FEDERATED')
)
def save_proof(signature, ev_uuid, result, proof_type, user):
if result['Status'] == STATUS_CODE.get("Success"):
timestamp = result.get('Data', {}).get('data', {}).get('timestamp')
if not timestamp:
return
d = {
"type": proof_type,
"timestamp": timestamp,
"issuer": user.institution.id,
"user": user,
"uuid": ev_uuid,
"signature": signature,
}
Proof.objects.create(**d)
def register_device_dlt(chid, phid, ev_uuid, user):
cny_a = 1
while cny_a:
result = register_dlt(chid, phid)
try:
assert result['Status'] == STATUS_CODE.get("Success")
assert result['Data']['data']['timestamp']
cny_a = 0
except Exception:
if result.get("Data") != "Device already exists":
logger.error("API return: %s", result)
time.sleep(10)
else:
cny_a = 0
save_proof(phid, ev_uuid, result, PROOF_TYPE['Register'], user)
# TODO is neccesary?
# if settings.get('ID_FEDERATED'):
# cny = 1
# while cny:
# try:
# api.add_service(
# chid,
# 'DeviceHub',
# settings.get('ID_FEDERATED'),
# 'Inventory service',
# 'Inv',
# )
# cny = 0
# except Exception:
# time.sleep(10)
def register_passport_dlt(chid, phid, ev_uuid, user):
dpp = "{chid}:{phid}".format(chid=chid, phid=phid)
if Proof.objects.filter(signature=dpp, type=PROOF_TYPE['IssueDPP']).exists():
return
cny_a = 1
while cny_a:
try:
result = issuer_dpp_dlt(dpp)
cny_a = 0
except Exception as err:
logger.error("ERROR API issue passport return: %s", err)
time.sleep(10)
if result['Status'] is not STATUS_CODE.get("Success"):
logger.error("ERROR API issue passport return: %s", result)
return
save_proof(phid, ev_uuid, result, PROOF_TYPE['IssueDPP'], user)

6
dpp/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class DppConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "dpp"

View File

@ -0,0 +1,52 @@
# Generated by Django 5.0.6 on 2024-11-18 14:29
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
("user", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="Proof",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("timestamp", models.IntegerField()),
("uuid", models.UUIDField()),
("signature", models.CharField(max_length=256)),
("type", models.CharField(max_length=256)),
(
"issuer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="user.institution",
),
),
(
"user",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to=settings.AUTH_USER_MODEL,
),
),
],
),
]

View File

15
dpp/models.py Normal file
View File

@ -0,0 +1,15 @@
from django.db import models
from user.models import User, Institution
from utils.constants import STR_EXTEND_SIZE
# Create your models here.
class Proof(models.Model):
## The signature can be a phid or dpp depending of type of Proof
timestamp = models.IntegerField()
uuid = models.UUIDField()
signature = models.CharField(max_length=STR_EXTEND_SIZE)
type = models.CharField(max_length=STR_EXTEND_SIZE)
issuer = models.ForeignKey(Institution, on_delete=models.CASCADE)
user = models.ForeignKey(
User, on_delete=models.SET_NULL, null=True, blank=True)

3
dpp/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

8
dpp/urls.py Normal file
View File

@ -0,0 +1,8 @@
from django.urls import path
from dpp import views
app_name = 'dpp'
urlpatterns = [
path("<int:proof_id>/", views.LotDashboardView.as_view(), name="proof"),
]

36
dpp/views.py Normal file
View File

@ -0,0 +1,36 @@
from django.views.generic.edit import View
from django.http import JsonResponse
from evidence.xapian import search
from dpp.models import Proof
from dpp.api_dlt import ALGORITHM
class ProofView(View):
def get(self, request, *args, **kwargs):
timestamp = kwargs.get("proof_id")
proof = Proof.objects.filter(timestamp=timestamp).first()
if not proof:
return JsonResponse({}, status=404)
ev_uuid = 'uuid:"{}"'.format(proof.uuid)
matches = search(None, ev_uuid, limit=1)
if not matches or matches.size() < 1:
return JsonResponse({}, status=404)
for x in matches:
snap = x.document.get_data()
data = {
"algorithm": ALGORITHM,
"document": snap
}
d = {
'@context': ['https://ereuse.org/proof0.json'],
'data': data,
}
return JsonResponse(d, status=200)
return JsonResponse({}, status=404)

View File

@ -1,4 +1,5 @@
import json import json
import hashlib
from dmidecode import DMIParse from dmidecode import DMIParse
from django.db import models from django.db import models
@ -58,6 +59,12 @@ class Evidence:
if a: if a:
self.owner = a.owner self.owner = a.owner
def get_phid(self):
if not self.doc:
self.get_doc()
return hashlib.sha3_256(json.dumps(self.doc)).hexdigest()
def get_doc(self): def get_doc(self):
self.doc = {} self.doc = {}
if not self.owner: if not self.owner:

View File

@ -8,11 +8,13 @@ from evidence.parse_details import get_lshw_child
from evidence.models import Annotation from evidence.models import Annotation
from evidence.xapian import index from evidence.xapian import index
from dpp.api_dlt import register_device_dlt, register_passport_dlt
from utils.constants import CHASSIS_DH from utils.constants import CHASSIS_DH
logger = logging.getLogger('django') logger = logging.getLogger('django')
def get_mac(lshw): def get_mac(lshw):
try: try:
if type(lshw) is dict: if type(lshw) is dict:
@ -40,6 +42,8 @@ class Build:
self.uuid = self.json['uuid'] self.uuid = self.json['uuid']
self.user = user self.user = user
self.hid = None self.hid = None
self.chid = None
self.phid = self.get_signature(self.json)
self.generate_chids() self.generate_chids()
if check: if check:
@ -47,6 +51,7 @@ class Build:
self.index() self.index()
self.create_annotations() self.create_annotations()
self.register_device_dlt()
def index(self): def index(self):
snap = json.dumps(self.json) snap = json.dumps(self.json)
@ -70,7 +75,8 @@ class Build:
hid = f"{manufacturer}{model}{chassis}{serial_number}{sku}" hid = f"{manufacturer}{model}{chassis}{serial_number}{sku}"
return hashlib.sha3_256(hid.encode()).hexdigest() self.chid = hashlib.sha3_256(hid.encode()).hexdigest()
return self.chid
def create_annotations(self): def create_annotations(self):
annotation = Annotation.objects.filter( annotation = Annotation.objects.filter(
@ -129,3 +135,10 @@ class Build:
logger.warning(txt, snapshot['uuid']) logger.warning(txt, snapshot['uuid'])
return f"{manufacturer}{model}{chassis}{serial_number}{sku}{mac}" return f"{manufacturer}{model}{chassis}{serial_number}{sku}{mac}"
def get_signature(self, doc):
return hashlib.sha3_256(json.dumps(doc).encode()).hexdigest()
def register_device_dlt(self):
register_device_dlt(self.chid, self.phid, self.uuid, self.user)
register_passport_dlt(self.chid, self.phid, self.uuid, self.user)

View File

@ -22,10 +22,14 @@ def search(institution, qs, offset=0, limit=10):
qp.set_stemming_strategy(xapian.QueryParser.STEM_SOME) qp.set_stemming_strategy(xapian.QueryParser.STEM_SOME)
qp.add_prefix("uuid", "uuid") qp.add_prefix("uuid", "uuid")
query = qp.parse_query(qs) query = qp.parse_query(qs)
institution_term = "U{}".format(institution.id) if institution:
final_query = xapian.Query( institution_term = "U{}".format(institution.id)
xapian.Query.OP_AND, query, xapian.Query(institution_term) final_query = xapian.Query(
) xapian.Query.OP_AND, query, xapian.Query(institution_term)
)
else:
final_query = xapian.Query(query)
enquire = xapian.Enquire(database) enquire = xapian.Enquire(database)
enquire.set_query(final_query) enquire.set_query(final_query)
matches = enquire.get_mset(offset, limit) matches = enquire.get_mset(offset, limit)