Merge pull request #96 from eReuse/feature/#95-endpoint-check-hash-reports

Feature/#95 endpoint check hash reports
This commit is contained in:
cayop 2020-12-22 12:54:50 +01:00 committed by GitHub
commit 3f4484cb07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 127 additions and 7 deletions

View File

@ -6,13 +6,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
ml).
## master
[1.0.1-beta]
[1.0.2-beta]
## testing
[1.0.3-beta]
## [1.0.3-beta]
- [addend] #85 add mac of network adapter to device hid
- [addend] #95 adding endpoint for check the hash of one report
- [changed] #94 change form of snapshot manual
## [1.0.2-beta]

View File

@ -0,0 +1,43 @@
"""empty message
Revision ID: 3eb50297c365
Revises: 378b6b147b46
Create Date: 2020-12-18 16:26:15.453694
"""
import citext
import sqlalchemy as sa
from alembic import op
from alembic import context
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = '3eb50297c365'
down_revision = '378b6b147b46'
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():
# Report Hash table
op.create_table('report_hash',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('created', sa.TIMESTAMP(timezone=True), server_default=sa.text('CURRENT_TIMESTAMP'),
nullable=False, comment='When Devicehub created this.'),
sa.Column('hash3', citext.CIText(), nullable=False),
sa.PrimaryKeyConstraint('id'),
schema=f'{get_inv()}'
)
def downgrade():
op.drop_table('report_hash', schema=f'{get_inv()}')

View File

@ -11,19 +11,19 @@ import flask
import flask_weasyprint
import teal.marshmallow
from boltons import urlutils
from flask import make_response, g
from flask import make_response, g, request
from flask.json import jsonify
from teal.cache import cache
from teal.resource import Resource
from teal.resource import Resource, View
from ereuse_devicehub.db import db
from ereuse_devicehub.resources.action import models as evs
from ereuse_devicehub.resources.device import models as devs
from ereuse_devicehub.resources.device.views import DeviceView
from ereuse_devicehub.resources.documents.device_row import DeviceRow, StockRow
from ereuse_devicehub.resources.documents.device_row import DeviceRow
from ereuse_devicehub.resources.lot import LotView
from ereuse_devicehub.resources.lot.models import Lot
from ereuse_devicehub.resources.hash_reports import insert_hash, ReportHash
class Format(enum.Enum):
@ -117,7 +117,7 @@ class DevicesDocumentView(DeviceView):
def generate_post_csv(self, query):
"""Get device query and put information in csv format."""
data = StringIO()
cw = csv.writer(data, delimiter=';', quotechar='"')
cw = csv.writer(data, delimiter=';', lineterminator="\n", quotechar='"')
first = True
for device in query:
d = DeviceRow(device)
@ -125,7 +125,9 @@ class DevicesDocumentView(DeviceView):
cw.writerow(d.keys())
first = False
cw.writerow(d.values())
output = make_response(data.getvalue().encode('utf-8'))
bfile = data.getvalue().encode('utf-8')
output = make_response(bfile)
insert_hash(bfile)
output.headers['Content-Disposition'] = 'attachment; filename=export.csv'
output.headers['Content-type'] = 'text/csv'
return output
@ -190,6 +192,19 @@ class StockDocumentView(DeviceView):
return output
class CheckView(View):
model = ReportHash
def get(self):
qry = dict(request.values)
hash3 = qry.get('hash')
result = False
if hash3 and ReportHash.query.filter_by(hash3=hash3).count():
result = True
return jsonify(result)
class DocumentDef(Resource):
__type__ = 'Document'
SCHEMA = None
@ -238,3 +253,6 @@ class DocumentDef(Resource):
stock_view = StockDocumentView.as_view('stockDocumentView', definition=self, auth=app.auth)
stock_view = app.auth.requires_auth(stock_view)
self.add_url_rule('/stock/', defaults=d, view_func=stock_view, methods=get)
check_view = CheckView.as_view('CheckView', definition=self, auth=app.auth)
self.add_url_rule('/check/', defaults={}, view_func=check_view, methods=get)

View File

@ -0,0 +1,29 @@
"""Hash implementation and save in database
"""
import hashlib
from citext import CIText
from sqlalchemy import Column
from sqlalchemy.dialects.postgresql import UUID
from uuid import uuid4
from ereuse_devicehub.db import db
class ReportHash(db.Model):
"""Save the hash than is create when one report is download.
"""
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4)
id.comment = """The identifier of the device for this database. Used only
internally for software; users should not use this.
"""
hash3 = db.Column(CIText(), nullable=False)
hash3.comment = """The normalized name of the hash."""
def insert_hash(bfile):
hash3 = hashlib.sha3_256(bfile).hexdigest()
db_hash = ReportHash(hash3=hash3)
db.session.add(db_hash)
db.session.commit()
db.session.flush()

View File

@ -53,6 +53,7 @@ def test_api_docs(client: Client):
'/documents/lots/',
'/documents/static/{filename}',
'/documents/stock/',
'/documents/check/',
'/drills/{dev1_id}/merge/{dev2_id}',
'/graphic-cards/{dev1_id}/merge/{dev2_id}',
'/hard-drives/{dev1_id}/merge/{dev2_id}',

View File

@ -1,4 +1,5 @@
import csv
import hashlib
from datetime import datetime
from io import StringIO
from pathlib import Path
@ -15,7 +16,9 @@ from ereuse_devicehub.resources.documents import documents
from ereuse_devicehub.resources.device import models as d
from ereuse_devicehub.resources.lot.models import Lot
from ereuse_devicehub.resources.tag.model import Tag
from ereuse_devicehub.resources.hash_reports import ReportHash
from ereuse_devicehub.db import db
from tests import conftest
from tests.conftest import file
@ -103,6 +106,7 @@ def test_export_csv_permitions(user: UserClient, user2: UserClient, client: Clie
assert len(csv_user) > 0
assert len(csv_user2) == 0
@pytest.mark.mvp
def test_export_basic_snapshot(user: UserClient):
"""Test export device information in a csv file."""
@ -128,6 +132,30 @@ def test_export_basic_snapshot(user: UserClient):
assert fixture_csv[1][18] == export_csv[1][18], 'Computer information are not equal'
assert fixture_csv[1][20:] == export_csv[1][20:], 'Computer information are not equal'
@pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__)
def test_check_insert_hash(app: Devicehub, user: UserClient, client: Client):
"""Test export device information in a csv file."""
snapshot, _ = user.post(file('basic.snapshot'), res=Snapshot)
csv_str, _ = user.get(res=documents.DocumentDef.t,
item='devices/',
accept='text/csv',
query=[('filter', {'type': ['Computer']})])
hash3 = hashlib.sha3_256(csv_str.encode('utf-8')).hexdigest()
assert ReportHash.query.filter_by(hash3=hash3).count() == 1
result, status = client.get(res=documents.DocumentDef.t, item='check/', query=[('hash', hash3)])
assert status.status_code == 200
assert result == True
ff = open('/tmp/test.csv', 'w')
ff.write(csv_str)
ff.close()
a= open('/tmp/test.csv').read()
assert hash3 == hashlib.sha3_256(a.encode('utf-8')).hexdigest()
@pytest.mark.mvp
def test_export_extended(app: Devicehub, user: UserClient):
"""Test a export device with all information and a lot of components."""