.
This commit is contained in:
parent
8c979d7741
commit
faa7c1d605
|
@ -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),
|
||||
|
|
0
ereuse_devicehub/resources/did/__init__.py
Normal file
0
ereuse_devicehub/resources/did/__init__.py
Normal file
115
ereuse_devicehub/resources/did/did.py
Normal file
115
ereuse_devicehub/resources/did/did.py
Normal 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'})
|
100
ereuse_devicehub/resources/did/models.py
Normal file
100
ereuse_devicehub/resources/did/models.py
Normal 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)
|
73
ereuse_devicehub/resources/did/templates/chid.html
Normal file
73
ereuse_devicehub/resources/did/templates/chid.html
Normal 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>
|
83
ereuse_devicehub/resources/did/templates/dpp.html
Normal file
83
ereuse_devicehub/resources/did/templates/dpp.html
Normal 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>
|
26
ereuse_devicehub/resources/did/templates/layout.html
Normal file
26
ereuse_devicehub/resources/did/templates/layout.html
Normal 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>
|
74
ereuse_devicehub/resources/did/templates/stamp.html
Normal file
74
ereuse_devicehub/resources/did/templates/stamp.html
Normal 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>
|
Reference in a new issue