Merge pull request #96 from eReuse/feature/#95-endpoint-check-hash-reports
Feature/#95 endpoint check hash reports
This commit is contained in:
commit
3f4484cb07
|
@ -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]
|
||||
|
|
|
@ -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()}')
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
|
@ -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}',
|
||||
|
|
|
@ -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."""
|
||||
|
|
Reference in New Issue