This commit is contained in:
Cayo Puigdefabregas 2023-01-18 18:56:04 +01:00
parent 8c979d7741
commit faa7c1d605
8 changed files with 473 additions and 0 deletions

View file

@ -18,6 +18,7 @@ from ereuse_devicehub.resources import (
)
from ereuse_devicehub.resources.device import definitions
from ereuse_devicehub.resources.documents import documents
from ereuse_devicehub.resources.did import did
from ereuse_devicehub.resources.enums import PriceSoftware
from ereuse_devicehub.resources.licences import licences
from ereuse_devicehub.resources.metric import definitions as metric_def
@ -36,6 +37,7 @@ class DevicehubConfig(Config):
import_resource(lot),
import_resource(deliverynote),
import_resource(documents),
import_resource(did),
import_resource(tradedocument),
import_resource(inventory),
import_resource(versions),

View file

@ -0,0 +1,115 @@
import csv
import json
import enum
import uuid
import time
import datetime
from collections import OrderedDict
from io import StringIO
from typing import Callable, Iterable, Tuple
import boltons
import flask
import flask_weasyprint
import teal.marshmallow
from boltons import urlutils
from flask import make_response, g, request
from flask import current_app as app
from flask.json import jsonify
from teal.cache import cache
from teal.resource import Resource, View
from ereuse_devicehub import auth
from ereuse_devicehub.db import db
from ereuse_devicehub.resources.device.models import Device
from ereuse_devicehub.resources.did.models import Dpp
class DidView(View):
"""
This view render one public ans static page for see the links for to do the check
of one csv file
"""
def get_url_path(self):
url = urlutils.URL(request.url)
url.normalize()
url.path_parts = url.path_parts[:-2] + ['check', '']
return url.to_text()
def get(self, dpp: str):
self.dpp = dpp
template = 'dpp.html'
if len(dpp.split(":")) == 2:
result = Dpp.query.filter_by(key=dpp).one()
else:
result = Device.query.filter_by(chid=dpp).one()
template = 'chid.html'
if 'json' not in request.headers['Accept']:
result = self.get_result(result, template)
return flask.render_template(template, rq_url=self.get_url_path(),
result={"dpp": dpp, "result": result})
return jsonify(self.get_result(result, template))
def get_result(self, dpp, template):
data = {
'hardware': {},
'dpp': self.dpp,
}
result = {'data': data}
if template == 'dpp.html':
data['hardware'] = json.loads(dpp.snapshot.json_hw)
last_dpp = self.get_last_dpp(dpp)
url_last = ''
if last_dpp:
url_last = 'http://did.ereuse.org/{did}'.format(did=last_dpp)
data['url_last'] = url_last
return result
# if dpp is not a dpp then is a device
device = dpp
dpps = []
for d in device.dpps:
rr = {'dpp': d.key, 'hardware': json.loads(d.snapshot.json_hw)}
dpps.append(rr)
return {'data': dpps}
def get_last_dpp(self, dpp):
dpps = [act.dpp[0] for act in dpp.device.actions if act.t == 'Snapshot' and act.dpp]
last_dpp = ''
for d in dpps:
if d.key == dpp.key:
return last_dpp
last_dpp = d.key
return last_dpp
class DidDef(Resource):
__type__ = 'Did'
SCHEMA = None
VIEW = None # We do not want to create default / documents endpoint
AUTH = False
def __init__(self, app,
import_name=__name__,
static_folder='static',
static_url_path=None,
template_folder='templates',
url_prefix=None,
subdomain=None,
url_defaults=None,
root_path=None,
cli_commands: Iterable[Tuple[Callable, str or None]] = tuple()):
super().__init__(app, import_name, static_folder, static_url_path, template_folder,
url_prefix, subdomain, url_defaults, root_path, cli_commands)
view = DidView.as_view('main', definition=self, auth=app.auth)
# if self.AUTH:
# view = app.auth.requires_auth(view)
did_view = DidView.as_view('DidView', definition=self, auth=app.auth)
self.add_url_rule('/<string:dpp>', defaults={}, view_func=did_view, methods={'GET'})

View file

@ -0,0 +1,100 @@
from sortedcontainers import SortedSet
from sqlalchemy.util import OrderedSet
from sqlalchemy import Unicode, BigInteger, Column, Sequence, ForeignKey
from sqlalchemy.orm import backref, relationship
from sqlalchemy.dialects.postgresql import UUID
from flask import g
from teal.db import CASCADE_OWN
from ereuse_devicehub.resources.user.models import User
from ereuse_devicehub.resources.device.models import Device
from ereuse_devicehub.resources.action.models import Snapshot, ActionStatus
from ereuse_devicehub.resources.models import Thing, STR_SM_SIZE
PROOF_ENUM = {
'Register': 'Register',
'IssueDPP': 'IssueDPP',
'proof_of_recycling': 'proof_of_recycling',
}
_sorted_proofs = {
'order_by': lambda: Proof.created,
'collection_class': SortedSet
}
class Proof(Thing):
id = Column(BigInteger, Sequence('device_seq'), primary_key=True)
id.comment = """The identifier of the device for this database. Used only
internally for software; users should not use this."""
documentId = Column(Unicode(STR_SM_SIZE), nullable=True)
documentId.comment = "is the hash of snapshot.json_wb"
documentSignature = Column(Unicode(STR_SM_SIZE), nullable=True)
documentSignature.comment = "is the snapshot.json_wb with the signature of the user"
timestamp = Column(BigInteger, nullable=False)
type = Column(Unicode(STR_SM_SIZE), nullable=False)
issuer_id = Column(UUID(as_uuid=True),
ForeignKey(User.id),
nullable=False,
default=lambda: g.user.id)
issuer = relationship(User,
backref=backref('issuered_proofs', lazy=True, collection_class=set),
primaryjoin=User.id == issuer_id)
issuer_id.comment = """The user that recorded this proof in the system."""
device_id = Column(BigInteger, ForeignKey(Device.id), nullable=False)
device = relationship(Device,
backref=backref('proofs',
lazy=True,
cascade=CASCADE_OWN),
primaryjoin=Device.id == device_id)
snapshot_id = Column(UUID(as_uuid=True), ForeignKey(Snapshot.id), nullable=True)
snapshot = relationship(Snapshot,
backref=backref('proofs', lazy=True),
collection_class=OrderedSet,
primaryjoin=Snapshot.id == snapshot_id)
action_status_id = Column(UUID(as_uuid=True), ForeignKey(ActionStatus.id), nullable=True)
action_status = relationship(ActionStatus,
backref=backref('proofs', lazy=True),
primaryjoin=ActionStatus.id == action_status_id)
class Dpp(Thing):
"""
Digital PassPort:
It is a type of proof with some field more.
Is the official Digital Passport
"""
id = Column(BigInteger, Sequence('device_seq'), primary_key=True)
key = Column(Unicode(STR_SM_SIZE), nullable=False)
key.comment = "chid:phid, (chid it's in device and phid it's in the snapshot)"
documentId = Column(Unicode(STR_SM_SIZE), nullable=True)
documentId.comment = "is the hash of snapshot.json_wb"
documentSignature = Column(Unicode(STR_SM_SIZE), nullable=True)
documentSignature.comment = "is the snapshot.json_wb with the signature of the user"
timestamp = Column(BigInteger, nullable=False)
issuer_id = Column(UUID(as_uuid=True),
ForeignKey(User.id),
nullable=False,
default=lambda: g.user.id)
issuer = relationship(User,
backref=backref('issuered_dpp', lazy=True, collection_class=set),
primaryjoin=User.id == issuer_id)
issuer_id.comment = """The user that recorded this proof in the system."""
device_id = Column(BigInteger, ForeignKey(Device.id), nullable=False)
device = relationship(Device,
backref=backref('dpps',
lazy=True,
cascade=CASCADE_OWN),
primaryjoin=Device.id == device_id)
snapshot_id = Column(UUID(as_uuid=True), ForeignKey(Snapshot.id), nullable=False)
snapshot = relationship(Snapshot,
backref=backref('dpp', lazy=True),
collection_class=OrderedSet,
primaryjoin=Snapshot.id == snapshot_id)

View file

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<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">
<script src="https://use.fontawesome.com/7553aecc27.js"></script>
<title>Devicehub | Stamp create and Stamp verify</title>
<style>
/*Sticky footer*/
html {
position: relative;
min-height: 100%;
}
body {
margin-bottom: 60px; /* Margin bottom by footer height */
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
height: 6em;
}
</style>
</head>
<body>
<nav class="navbar navbar-default" style="background-color: gainsboro; margin: 0 !important">
<div class="container-fluid">
<a href="https://www.usody.com/" target="_blank">
<h1 align="center">Usody</h1>
</a>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="page-header col-md-6 col-md-offset-3">
This is the info for chid: {{result.dpp}}
</div>
<div class="col-md-6 col-md-offset-3">
{% for dpp in result.result.data %}
<h5>Digital Passport</h5>
{{ dpp.dpp }}
<h5>Hardware</h5>
<ul>
<li>Device</li>
<ul>
<li>Chassis: {{ dpp.hardware.device.chassis }}</li>
<li>Manufacturer: {{ dpp.hardware.device.manufacturer }}</li>
<li>Model: {{ dpp.hardware.device.model }}</li>
<li>SerialNumber: {{ dpp.hardware.device.serialNumber }}</li>
<li>Sku: {{ dpp.hardware.device.sku }}</li>
<li>Type: {{ dpp.hardware.device.type }}</li>
<li>Version: {{ dpp.hardware.device.version }}</li>
</ul>
<li>Components</li>
<ul>
{% for component in dpp.hardware.components %}
<li>{{ component }}</li>
{% endfor %}
</ul>
</ul>
<hr />
{% endfor %}
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<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">
<script src="https://use.fontawesome.com/7553aecc27.js"></script>
<title>Devicehub | Stamp create and Stamp verify</title>
<style>
/*Sticky footer*/
html {
position: relative;
min-height: 100%;
}
body {
margin-bottom: 60px; /* Margin bottom by footer height */
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
height: 6em;
}
</style>
</head>
<body>
<nav class="navbar navbar-default" style="background-color: gainsboro; margin: 0 !important">
<div class="container-fluid">
<a href="https://www.usody.com/" target="_blank">
<h1 align="center">Usody</h1>
</a>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="page-header col-md-6 col-md-offset-3">
This is the info for Digital Passport: {{result.dpp}}
</div>
<div class="col-md-6 col-md-offset-3">
<h5>Hardware</h5>
<ul>
<li>Device</li>
<ul>
<li>Chassis: {{ result.result.data.hardware.device.chassis }}</li>
<li>Manufacturer: {{ result.result.data.hardware.device.manufacturer }}</li>
<li>Model: {{ result.result.data.hardware.device.model }}</li>
<li>SerialNumber: {{ result.result.data.hardware.device.serialNumber }}</li>
<li>Sku: {{ result.result.data.hardware.device.sku }}</li>
<li>Type: {{ result.result.data.hardware.device.type }}</li>
<li>Version: {{ result.result.data.hardware.device.version }}</li>
</ul>
<li>Components</li>
<ul>
{% for component in result.result.data.hardware.components %}
<li>{{ component }}</li>
{% endfor %}
</ul>
</ul>
{% if result.result.data.url_last %}
<h5>Last Digital passport</h5>
<a href="{{ result.result.data.url_last }}">{{ result.result.data.url_last }}</a>
{% endif %}
{% if result.result.data.digitalPassports %}
<h5>Digital Passports</h5>
<ul>
{% for dpp in result.result.data.digitalPassports %}
<li>{{ dpp }}</li>
{% endfor %}
</ul>
{% endif %}
<br />
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,26 @@
{% import 'devices/macros.html' as macros %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<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">
<link rel="stylesheet"
type="text/css"
href="{{ url_for('Document.static', filename='print.css') }}">
<title>USOdy | {{ title }}</title>
</head>
<body>
<div class="container">
<div class="row">
<header class="page-header">
<h1> {{ title }}</h1>
</header>
</div>
{% block body %}{% endblock %}
</div>
</body>
</html>

View file

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<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">
<script src="https://use.fontawesome.com/7553aecc27.js"></script>
<title>Devicehub | Stamp create and Stamp verify</title>
<style>
/*Sticky footer*/
html {
position: relative;
min-height: 100%;
}
body {
margin-bottom: 60px; /* Margin bottom by footer height */
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
height: 6em;
}
</style>
</head>
<body>
<nav class="navbar navbar-default" style="background-color: gainsboro; margin: 0 !important">
<div class="container-fluid">
<a href="https://www.usody.com/" target="_blank">
<h1 align="center">Usody</h1>
</a>
</div>
</nav>
<div class="container-fluid">
<div class="page-header col-md-6 col-md-offset-3">
<div class="row">
{% if result.0 == 'Ok' %}
<div class="alert alert-info" style="background-color: #3fb618;" role="alert">
{{ result.1 }}
</div>
{% elif result.0 == 'Bad' %}
<div class="alert alert-danger" style="background-color: #ff0039" role="alert">
{{ result.1 }}
</div>
{% endif %}
</div>
<div class="row">
<a href="http://dlt.ereuse.org/stamps/create?url={{ rq_url }}" target="_blank">Add one new check in your csv</a>
</div>
<div class="row">
<a href="http://dlt.ereuse.org/stamps/check?url={{ rq_url }}" target="_blank">Verify a CSV file in here.</a>
</div>
</div>
<div class="row">
<div class="page-header col-md-6 col-md-offset-3">
If you want us to verify a document issued by us, upload it using the following form
</div>
<div class="col-md-6 col-md-offset-3">
<form enctype="multipart/form-data" action="" method="post">
<label for="name">Document: </label>
<input type="file" name="docUpload" accept="*" /><br />
<input type="submit" id="send-signup" name="signup" value="Verify" />
</form>
</div>
</div>
</div>
</body>
</html>