Compare commits
10 Commits
Author | SHA1 | Date |
---|---|---|
pedro | a49b31dd85 | |
Cayo Puigdefabregas | 493c7636b2 | |
Cayo Puigdefabregas | 88e036eb3c | |
Cayo Puigdefabregas | b759c53e75 | |
Cayo Puigdefabregas | 7ab88ad290 | |
Cayo Puigdefabregas | f6d1cf719c | |
pedro | fb836edfbb | |
Cayo Puigdefabregas | cc350775ed | |
Cayo Puigdefabregas | 0d574cae63 | |
Cayo Puigdefabregas | 9857891b63 |
|
@ -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="#dpps">{% 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 'did:device_web' d.uuid %}">{{ d.signature }}</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,8 @@ INSTALLED_APPS = [
|
||||||
"dashboard",
|
"dashboard",
|
||||||
"admin",
|
"admin",
|
||||||
"api",
|
"api",
|
||||||
|
"dpp",
|
||||||
|
"did",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -239,3 +241,8 @@ LOGGING = {
|
||||||
SNAPSHOT_PATH="/tmp/"
|
SNAPSHOT_PATH="/tmp/"
|
||||||
DATA_UPLOAD_MAX_NUMBER_FILES = 1000
|
DATA_UPLOAD_MAX_NUMBER_FILES = 1000
|
||||||
COMMIT = config('COMMIT', default='')
|
COMMIT = config('COMMIT', default='')
|
||||||
|
|
||||||
|
# DLT SETTINGS
|
||||||
|
TOKEN_DLT = config("TOKEN_DLT", default=None)
|
||||||
|
API_DLT = config("API_DLT", default=None)
|
||||||
|
API_RESULVER = config("API_RESOLVER", default=None)
|
||||||
|
|
|
@ -27,4 +27,6 @@ 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')),
|
||||||
|
path('did/', include('did.urls')),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class DidConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "did"
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
|
@ -0,0 +1,171 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>{{ object.type }}</title>
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet" />
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css" />
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
.custom-container {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 30px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
.section-title {
|
||||||
|
color: #7a9f4f;
|
||||||
|
border-bottom: 2px solid #9cc666;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
.info-row {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.info-label {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #545f71;
|
||||||
|
}
|
||||||
|
.info-value {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.component-card {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border-left: 4px solid #9cc666;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
.component-card:hover {
|
||||||
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
.hash-value {
|
||||||
|
word-break: break-all;
|
||||||
|
background-color: #f3f3f3;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 0.9em;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
.card-title {
|
||||||
|
color: #9cc666;
|
||||||
|
}
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #9cc666;
|
||||||
|
border-color: #9cc666;
|
||||||
|
padding: 0.1em 2em;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.btn-primary:hover {
|
||||||
|
background-color: #8ab555;
|
||||||
|
border-color: #8ab555;
|
||||||
|
}
|
||||||
|
.btn-green-user {
|
||||||
|
background-color: #c7e3a3;
|
||||||
|
}
|
||||||
|
.btn-grey {
|
||||||
|
background-color: #f3f3f3;
|
||||||
|
}
|
||||||
|
footer {
|
||||||
|
background-color: #545f71;
|
||||||
|
color: #ffffff;
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container custom-container">
|
||||||
|
<h1 class="text-center mb-4" style="color: #545f71;">{{ object.manufacturer }} {{ object.type }} {{ object.model }}</h1>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<h2 class="section-title">Details</h2>
|
||||||
|
<div class="info-row row">
|
||||||
|
<div class="col-md-4 info-label">Phid</div>
|
||||||
|
<div class="col-md-8 info-value">
|
||||||
|
<div class="hash-value">{{ object.id }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info-row row">
|
||||||
|
<div class="col-md-4 info-label">Type</div>
|
||||||
|
<div class="col-md-8 info-value">{{ object.type }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if object.is_websnapshot %}
|
||||||
|
{% for snapshot_key, snapshot_value in object.last_user_evidence %}
|
||||||
|
<div class="info-row row">
|
||||||
|
<div class="col-md-4 info-label">{{ snapshot_key }}</div>
|
||||||
|
<div class="col-md-8 info-value">{{ snapshot_value|default:'' }}</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<div class="info-row row">
|
||||||
|
<div class="col-md-4 info-label">Manufacturer</div>
|
||||||
|
<div class="col-md-8 info-value">{{ object.manufacturer|default:'' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="info-row row">
|
||||||
|
<div class="col-md-4 info-label">Model</div>
|
||||||
|
<div class="col-md-8 info-value">{{ object.model|default:'' }}</div>
|
||||||
|
</div>
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<div class="info-row row">
|
||||||
|
<div class="col-md-4 info-label">Serial Number</div>
|
||||||
|
<div class="col-md-8 info-value">{{ object.serial_number|default:'' }}</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<h2 class="section-title">Identifiers</h2>
|
||||||
|
{% for chid in object.hids %}
|
||||||
|
<div class="info-row">
|
||||||
|
<div class="hash-value">{{ chid|default:'' }}</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2 class="section-title mt-5">Components</h2>
|
||||||
|
<div class="row">
|
||||||
|
{% for component in object.components %}
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<div class="card component-card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">{{ component.type }}</h5>
|
||||||
|
<p class="card-text">
|
||||||
|
{% for component_key, component_value in component.items %}
|
||||||
|
{% if component_key not in 'actions,type' %}
|
||||||
|
{% if component_key != 'serialNumber' or user.is_authenticated %}
|
||||||
|
<strong>{{ component_key }}:</strong> {{ component_value }}<br />
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer>
|
||||||
|
<p>
|
||||||
|
©{% now 'Y' %}eReuse. All rights reserved.
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
|
@ -0,0 +1,8 @@
|
||||||
|
from django.urls import path
|
||||||
|
from did import views
|
||||||
|
|
||||||
|
app_name = 'did'
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("<str:pk>", views.PublicDeviceWebView.as_view(), name="device_web"),
|
||||||
|
]
|
|
@ -0,0 +1,60 @@
|
||||||
|
from django.http import JsonResponse, Http404
|
||||||
|
from django.views.generic.base import TemplateView
|
||||||
|
from device.models import Device
|
||||||
|
|
||||||
|
|
||||||
|
class PublicDeviceWebView(TemplateView):
|
||||||
|
template_name = "device_web.html"
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
self.pk = kwargs['pk']
|
||||||
|
self.object = Device(id=self.pk)
|
||||||
|
|
||||||
|
if not self.object.last_evidence:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
if self.request.headers.get('Accept') == 'application/json':
|
||||||
|
return self.get_json_response()
|
||||||
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
self.object.initial()
|
||||||
|
context.update({
|
||||||
|
'object': self.object
|
||||||
|
})
|
||||||
|
return context
|
||||||
|
|
||||||
|
@property
|
||||||
|
def public_fields(self):
|
||||||
|
return {
|
||||||
|
'id': self.object.id,
|
||||||
|
'shortid': self.object.shortid,
|
||||||
|
'uuids': self.object.uuids,
|
||||||
|
'hids': self.object.hids,
|
||||||
|
'components': self.remove_serial_number_from(self.object.components),
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def authenticated_fields(self):
|
||||||
|
return {
|
||||||
|
'serial_number': self.object.serial_number,
|
||||||
|
'components': self.object.components,
|
||||||
|
}
|
||||||
|
|
||||||
|
def remove_serial_number_from(self, components):
|
||||||
|
for component in components:
|
||||||
|
if 'serial_number' in component:
|
||||||
|
del component['SerialNumber']
|
||||||
|
return components
|
||||||
|
|
||||||
|
def get_device_data(self):
|
||||||
|
data = self.public_fields
|
||||||
|
if self.request.user.is_authenticated:
|
||||||
|
data.update(self.authenticated_fields)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_json_response(self):
|
||||||
|
device_data = self.get_device_data()
|
||||||
|
return JsonResponse(device_data)
|
||||||
|
|
|
@ -27,6 +27,8 @@ RUN python -m pip install --upgrade pip || (rm -rf /usr/local/lib/python3.11/sit
|
||||||
|
|
||||||
COPY ./requirements.txt /opt/devicehub-django
|
COPY ./requirements.txt /opt/devicehub-django
|
||||||
RUN pip install -r requirements.txt
|
RUN pip install -r requirements.txt
|
||||||
|
# TODO hardcoded, is ignored in requirements.txt
|
||||||
|
RUN pip install -i https://test.pypi.org/simple/ ereuseapitest==0.0.14
|
||||||
|
|
||||||
# TODO Is there a better way?
|
# TODO Is there a better way?
|
||||||
# Set PYTHONPATH to include the directory with the xapian module
|
# Set PYTHONPATH to include the directory with the xapian module
|
||||||
|
|
|
@ -5,6 +5,156 @@ set -u
|
||||||
# DEBUG
|
# DEBUG
|
||||||
set -x
|
set -x
|
||||||
|
|
||||||
|
# TODO there is a conflict between two shared vars
|
||||||
|
# 1. from the original docker compose devicehub-teal
|
||||||
|
# 2. from the new docker compose that integrates all dpp services
|
||||||
|
wait_for_dpp_shared() {
|
||||||
|
while true; do
|
||||||
|
# specially ensure VERAMO_API_CRED_FILE is not empty,
|
||||||
|
# it takes some time to get data in
|
||||||
|
OPERATOR_TOKEN_FILE='operator-token.txt'
|
||||||
|
if [ -f "/shared/${OPERATOR_TOKEN_FILE}" ] && \
|
||||||
|
[ -f "/shared/create_user_operator_finished" ]; then
|
||||||
|
sleep 5
|
||||||
|
echo "Files ready to process."
|
||||||
|
break
|
||||||
|
else
|
||||||
|
echo "Waiting for file in shared: ${OPERATOR_TOKEN_FILE}"
|
||||||
|
sleep 5
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 3. Generate an environment .env file.
|
||||||
|
# TODO cargar via shared
|
||||||
|
gen_env_vars() {
|
||||||
|
# specific dpp env vars
|
||||||
|
if [ "${DPP_MODULE}" = 'y' ]; then
|
||||||
|
# docker situation
|
||||||
|
if [ -d "${DPP_SHARED:-}" ]; then
|
||||||
|
wait_for_dpp_shared
|
||||||
|
export API_DLT='http://api_connector:3010'
|
||||||
|
export API_DLT_TOKEN="$(cat "/shared/${OPERATOR_TOKEN_FILE}")"
|
||||||
|
export API_RESOLVER='http://id_index_api:3012'
|
||||||
|
# TODO hardcoded
|
||||||
|
export ID_FEDERATED='DH1'
|
||||||
|
# .env situation
|
||||||
|
else
|
||||||
|
dpp_env_vars="$(cat <<END
|
||||||
|
API_DLT='${API_DLT}'
|
||||||
|
API_DLT_TOKEN='${API_DLT_TOKEN}'
|
||||||
|
API_RESOLVER='${API_RESOLVER}'
|
||||||
|
ID_FEDERATED='${ID_FEDERATED}'
|
||||||
|
END
|
||||||
|
)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# generate config using env vars from docker
|
||||||
|
cat > .env <<END
|
||||||
|
${dpp_env_vars:-}
|
||||||
|
DB_USER='${DB_USER}'
|
||||||
|
DB_PASSWORD='${DB_PASSWORD}'
|
||||||
|
DB_HOST='${DB_HOST}'
|
||||||
|
DB_DATABASE='${DB_DATABASE}'
|
||||||
|
URL_MANUALS='${URL_MANUALS:-}'
|
||||||
|
|
||||||
|
HOST='${HOST}'
|
||||||
|
|
||||||
|
SCHEMA='dbtest'
|
||||||
|
DB_SCHEMA='dbtest'
|
||||||
|
|
||||||
|
EMAIL_DEMO='${EMAIL_DEMO}'
|
||||||
|
PASSWORD_DEMO='${PASSWORD_DEMO}'
|
||||||
|
|
||||||
|
JWT_PASS=${JWT_PASS}
|
||||||
|
SECRET_KEY=${SECRET_KEY}
|
||||||
|
END
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_federated_id() {
|
||||||
|
|
||||||
|
# devicehub host and id federated checker
|
||||||
|
|
||||||
|
# //getAll queries are not accepted by this service, so we remove them
|
||||||
|
EXPECTED_ID_FEDERATED="$(curl -s "${API_RESOLVER%/}/getAll" \
|
||||||
|
| jq -r '.url | to_entries | .[] | select(.value == "'"${DEVICEHUB_HOST}"'") | .key' \
|
||||||
|
| head -n 1)"
|
||||||
|
|
||||||
|
# if is a new DEVICEHUB_HOST, then register it
|
||||||
|
if [ -z "${EXPECTED_ID_FEDERATED}" ]; then
|
||||||
|
# TODO better docker compose run command
|
||||||
|
cmd="docker compose run --entrypoint= devicehub flask dlt_insert_members ${DEVICEHUB_HOST}"
|
||||||
|
big_error "No FEDERATED ID maybe you should run \`${cmd}\`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# if not new DEVICEHUB_HOST, then check consistency
|
||||||
|
|
||||||
|
# if there is already an ID in the DLT, it should match with my internal ID
|
||||||
|
if [ ! "${EXPECTED_ID_FEDERATED}" = "${ID_FEDERATED}" ]; then
|
||||||
|
|
||||||
|
big_error "ID_FEDERATED should be ${EXPECTED_ID_FEDERATED} instead of ${ID_FEDERATED}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# not needed, but reserved
|
||||||
|
# EXPECTED_DEVICEHUB_HOST="$(curl -s "${API_RESOLVER%/}/getAll" \
|
||||||
|
# | jq -r '.url | to_entries | .[] | select(.key == "'"${ID_FEDERATED}"'") | .value' \
|
||||||
|
# | head -n 1)"
|
||||||
|
# if [ ! "${EXPECTED_DEVICEHUB_HOST}" = "${DEVICEHUB_HOST}" ]; then
|
||||||
|
# big_error "ERROR: DEVICEHUB_HOST should be ${EXPECTED_DEVICEHUB_HOST} instead of ${DEVICEHUB_HOST}"
|
||||||
|
# fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
config_dpp_part1() {
|
||||||
|
# 12. Add a new server to the 'api resolver'
|
||||||
|
if [ "${ID_SERVICE:-}" ]; then
|
||||||
|
handle_federated_id
|
||||||
|
else
|
||||||
|
# TODO when this runs more than one time per service, this is a problem, but for the docker-reset.sh workflow, that's fine
|
||||||
|
# TODO put this in already_configured
|
||||||
|
./manage.py dlt_insert_members "${DEVICEHUB_HOST}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 13. Do a rsync api resolve
|
||||||
|
./manage.py dlt_rsync_members
|
||||||
|
|
||||||
|
# 14. Register a new user to the DLT
|
||||||
|
DATASET_FILE='/tmp/dataset.json'
|
||||||
|
cat > "${DATASET_FILE}" <<END
|
||||||
|
{
|
||||||
|
"email": "${EMAIL_DEMO}",
|
||||||
|
"password": "${PASSWORD_DEMO}",
|
||||||
|
"api_token": "${API_DLT_TOKEN}"
|
||||||
|
}
|
||||||
|
END
|
||||||
|
./manage.py dlt_register_user "${DATASET_FILE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
config_phase() {
|
||||||
|
init_flagfile='/already_configured'
|
||||||
|
if [ ! -f "${init_flagfile}" ]; then
|
||||||
|
|
||||||
|
if [ "${DPP_MODULE}" = 'y' ]; then
|
||||||
|
# 12, 13, 14
|
||||||
|
config_dpp_part1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO fix wrong syntax
|
||||||
|
# non DL user (only for the inventory)
|
||||||
|
# ./manage.py adduser user2@dhub.com ${PASSWORD_DEMO}
|
||||||
|
|
||||||
|
# # 15. Add inventory snapshots for user "${EMAIL_DEMO}".
|
||||||
|
if [ "${IMPORT_SNAPSHOTS}" = 'y' ]; then
|
||||||
|
cp /mnt/snapshots/*.json example/snapshots/
|
||||||
|
/usr/bin/time ./manage.py up_snapshots "${EMAIL_DEMO}" ${PASSWORD_DEMO}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# remain next command as the last operation for this if conditional
|
||||||
|
touch "${init_flagfile}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
check_app_is_there() {
|
check_app_is_there() {
|
||||||
if [ ! -f "./manage.py" ]; then
|
if [ ! -f "./manage.py" ]; then
|
||||||
usage
|
usage
|
||||||
|
@ -70,6 +220,8 @@ runserver() {
|
||||||
main() {
|
main() {
|
||||||
program_dir='/opt/devicehub-django'
|
program_dir='/opt/devicehub-django'
|
||||||
cd "${program_dir}"
|
cd "${program_dir}"
|
||||||
|
gen_env_vars
|
||||||
|
config_phase
|
||||||
deploy
|
deploy
|
||||||
runserver
|
runserver
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
|
@ -0,0 +1,164 @@
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from ereuseapi.methods import API
|
||||||
|
|
||||||
|
from dpp.models import Proof, UserDpp
|
||||||
|
|
||||||
|
|
||||||
|
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(user):
|
||||||
|
|
||||||
|
dp = UserDpp.objects.filter(user=user).first()
|
||||||
|
if not dp:
|
||||||
|
return
|
||||||
|
|
||||||
|
api_dlt = settings.API_DLT
|
||||||
|
token_dlt = json.loads(dp).get("token_dlt")
|
||||||
|
if not api_dlt or not token_dlt:
|
||||||
|
logger.error("NOT POSSIBLE CONNECT WITH API DLT!!!")
|
||||||
|
return
|
||||||
|
|
||||||
|
return API(api_dlt, token_dlt, "ethereum")
|
||||||
|
|
||||||
|
|
||||||
|
def register_dlt(api, chid, phid, proof_type=None):
|
||||||
|
if proof_type:
|
||||||
|
return api.generate_proof(
|
||||||
|
chid,
|
||||||
|
ALGORITHM,
|
||||||
|
phid,
|
||||||
|
proof_type,
|
||||||
|
settings.ID_FEDERATED
|
||||||
|
)
|
||||||
|
|
||||||
|
return api.register_device(
|
||||||
|
chid,
|
||||||
|
ALGORITHM,
|
||||||
|
phid,
|
||||||
|
settings.ID_FEDERATED
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def issuer_dpp_dlt(api, dpp):
|
||||||
|
phid = dpp.split(":")[0]
|
||||||
|
|
||||||
|
return api.issue_passport(
|
||||||
|
dpp,
|
||||||
|
ALGORITHM,
|
||||||
|
phid,
|
||||||
|
settings.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,
|
||||||
|
"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:
|
||||||
|
api = connect_api(user)
|
||||||
|
if not api:
|
||||||
|
cny_a = 0
|
||||||
|
return
|
||||||
|
|
||||||
|
result = register_dlt(api, 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):
|
||||||
|
token_dlt = settings.TOKEN_DLT
|
||||||
|
api_dlt = settings.API_DLT
|
||||||
|
if not token_dlt or not api_dlt:
|
||||||
|
return
|
||||||
|
|
||||||
|
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:
|
||||||
|
api = connect_api(user)
|
||||||
|
if not api:
|
||||||
|
cny_a = 0
|
||||||
|
return
|
||||||
|
|
||||||
|
result = issuer_dpp_dlt(api, 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)
|
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class DppConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "dpp"
|
|
@ -0,0 +1,35 @@
|
||||||
|
import logging
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.conf import settings
|
||||||
|
from user.models import Institution
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger('django')
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Insert a new Institution in DLT"
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument('domain', type=str, help='institution')
|
||||||
|
|
||||||
|
def handle(self, *args, **kwargs):
|
||||||
|
domain = kwargs.get("domain")
|
||||||
|
api = settings.API_RESOLVER
|
||||||
|
if not api
|
||||||
|
logger.error("you need set the var API_RESOLVER")
|
||||||
|
return
|
||||||
|
|
||||||
|
if "http" not in domain:
|
||||||
|
logger.error("you need put https:// in %s", domain)
|
||||||
|
return
|
||||||
|
|
||||||
|
api = api.strip("/")
|
||||||
|
domain = domain.strip("/")
|
||||||
|
|
||||||
|
data = {"url": domain}
|
||||||
|
url = api + '/registerURL'
|
||||||
|
res = requests.post(url, json=data)
|
||||||
|
print(res.json())
|
|
@ -0,0 +1,72 @@
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from ereuseapi.methods import API
|
||||||
|
from django.conf import settings
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from user.models import User, Institution
|
||||||
|
from dpp.models import UserDpp
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger('django')
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Insert users than are in Dlt with params: path of data set file"
|
||||||
|
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument('dataset_file', type=str, help='institution')
|
||||||
|
|
||||||
|
def handle(self, *args, **kwargs):
|
||||||
|
dataset_file = kwargs.get("dataset_file")
|
||||||
|
self.api_dlt = settings.API_DLT
|
||||||
|
self.institution = Institution.objects.filter().first()
|
||||||
|
if not self.api_dlt:
|
||||||
|
logger.error("you need set the var API_DLT")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.api_dlt = self.api_dlt.strip("/")
|
||||||
|
|
||||||
|
with open(dataset_file) as f:
|
||||||
|
dataset = json.loads(f.read())
|
||||||
|
|
||||||
|
self.add_user(dataset)
|
||||||
|
|
||||||
|
def add_user(self, data):
|
||||||
|
email = data.get("email")
|
||||||
|
password = data.get("password")
|
||||||
|
api_token = data.get("api_token")
|
||||||
|
# ethereum = {"data": {"api_token": api_token}}
|
||||||
|
# data_eth = json.dumps(ethereum)
|
||||||
|
data_eth = json.dumps(api_token)
|
||||||
|
# TODO encrypt in the future
|
||||||
|
# api_keys_dlt = encrypt(password, data_eth)
|
||||||
|
api_keys_dlt = data_eth
|
||||||
|
|
||||||
|
user = User.objects.filter(email=email).first()
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
user = User.objects.create(
|
||||||
|
email=email,
|
||||||
|
password=password,
|
||||||
|
institution = self.institution
|
||||||
|
)
|
||||||
|
|
||||||
|
roles = []
|
||||||
|
token_dlt = api_token
|
||||||
|
api = API(self.api_dlt, token_dlt, "ethereum")
|
||||||
|
result = api.check_user_roles()
|
||||||
|
|
||||||
|
if result.get('Status') == 200:
|
||||||
|
if 'Success' in result.get('Data', {}).get('status'):
|
||||||
|
rols = result.get('Data', {}).get('data', {})
|
||||||
|
roles = [(k, k) for k, v in rols.items() if v]
|
||||||
|
|
||||||
|
roles_dlt = json.dumps(roles)
|
||||||
|
|
||||||
|
UserDpp.objects.create(
|
||||||
|
roles_dlt=roles_dlt,
|
||||||
|
api_keys_dlt=api_keys_dlt,
|
||||||
|
user=user
|
||||||
|
)
|
|
@ -0,0 +1,47 @@
|
||||||
|
import logging
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.conf import settings
|
||||||
|
from dpp.models import MemberFederated
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger('django')
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "Synchronize members of DLT"
|
||||||
|
|
||||||
|
def handle(self, *args, **kwargs):
|
||||||
|
api = settings.API_RESOLVER
|
||||||
|
if not api
|
||||||
|
logger.error("you need set the var API_RESOLVER")
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
api = api.strip("/")
|
||||||
|
|
||||||
|
url = api + '/getAll'
|
||||||
|
res = requests.get(url)
|
||||||
|
if res.status_code != 200:
|
||||||
|
return "Error, {}".format(res.text)
|
||||||
|
response = res.json()
|
||||||
|
members = response['url']
|
||||||
|
counter = members.pop('counter')
|
||||||
|
if counter <= MemberFederated.objects.count():
|
||||||
|
logger.info("Synchronize members of DLT -> All Ok")
|
||||||
|
return "All ok"
|
||||||
|
|
||||||
|
for k, v in members.items():
|
||||||
|
id = self.clean_id(k)
|
||||||
|
member = MemberFederated.objects.filter(dlt_id_provider=id).first()
|
||||||
|
if member:
|
||||||
|
if member.domain != v:
|
||||||
|
member.domain = v
|
||||||
|
member.save()
|
||||||
|
continue
|
||||||
|
MemberFederated.objects.create(dlt_id_provider=id, domain=v)
|
||||||
|
return res.text
|
||||||
|
|
||||||
|
def clean_id(self, id):
|
||||||
|
return int(id.split('DH')[-1])
|
|
@ -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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Generated by Django 5.0.6 on 2024-11-19 19:18
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("dpp", "0001_initial"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="MemberFederated",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"dlt_id_provider",
|
||||||
|
models.IntegerField(primary_key=True, serialize=False),
|
||||||
|
),
|
||||||
|
("domain", models.CharField(max_length=256)),
|
||||||
|
("client_id", models.CharField(max_length=256)),
|
||||||
|
("client_secret", models.CharField(max_length=256)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,60 @@
|
||||||
|
# Generated by Django 5.0.6 on 2024-11-20 10:51
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("dpp", "0002_memberfederated"),
|
||||||
|
("user", "0001_initial"),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="memberfederated",
|
||||||
|
name="institution",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="user.institution",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="memberfederated",
|
||||||
|
name="client_id",
|
||||||
|
field=models.CharField(max_length=256, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="memberfederated",
|
||||||
|
name="client_secret",
|
||||||
|
field=models.CharField(max_length=256, null=True),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="UserDpp",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("roles_dlt", models.TextField()),
|
||||||
|
("api_keys_dlt", models.TextField()),
|
||||||
|
(
|
||||||
|
"user",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,32 @@
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
class MemberFederated(models.Model):
|
||||||
|
dlt_id_provider = models.IntegerField(primary_key=True)
|
||||||
|
domain = models.CharField(max_length=STR_EXTEND_SIZE)
|
||||||
|
# This client_id and client_secret is used for connected to this domain as
|
||||||
|
# a client and this domain then is the server of auth
|
||||||
|
client_id = models.CharField(max_length=STR_EXTEND_SIZE, null=True)
|
||||||
|
client_secret = models.CharField(max_length=STR_EXTEND_SIZE, null=True)
|
||||||
|
institution = models.ForeignKey(
|
||||||
|
Institution, on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
|
|
||||||
|
|
||||||
|
class UserDpp(models.Model):
|
||||||
|
roles_dlt = models.TextField()
|
||||||
|
api_keys_dlt = models.TextField()
|
||||||
|
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
|
@ -0,0 +1,8 @@
|
||||||
|
from django.urls import path
|
||||||
|
from dpp import views
|
||||||
|
|
||||||
|
app_name = 'dpp'
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("<int:proof_id>/", views.ProofView.as_view(), name="proof"),
|
||||||
|
]
|
|
@ -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)
|
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
if institution:
|
||||||
institution_term = "U{}".format(institution.id)
|
institution_term = "U{}".format(institution.id)
|
||||||
final_query = xapian.Query(
|
final_query = xapian.Query(
|
||||||
xapian.Query.OP_AND, query, xapian.Query(institution_term)
|
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)
|
||||||
|
|
|
@ -11,3 +11,6 @@ xlrd==2.0.1
|
||||||
odfpy==1.4.1
|
odfpy==1.4.1
|
||||||
pytz==2024.2
|
pytz==2024.2
|
||||||
json-repair==0.30.0
|
json-repair==0.30.0
|
||||||
|
setuptools==75.5.0
|
||||||
|
requests==2.32.3
|
||||||
|
wheel==0.45.0
|
||||||
|
|
Loading…
Reference in New Issue