fixing models and build views for revokeDocument

This commit is contained in:
Cayo Puigdefabregas 2021-06-24 19:09:12 +02:00
parent 77000882f5
commit 8a797f079b
8 changed files with 194 additions and 30 deletions

View File

@ -115,8 +115,20 @@ def upgrade():
op.create_index(op.f('ix_trade_document_created'), 'trade_document', ['created'], unique=False, schema=f'{get_inv()}')
op.create_index(op.f('ix_trade_document_updated'), 'trade_document', ['updated'], unique=False, schema=f'{get_inv()}')
op.create_table('confirm_document',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('action_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.ForeignKeyConstraint(['id'], [f'{get_inv()}.action.id'], ),
sa.ForeignKeyConstraint(['action_id'], [f'{get_inv()}.action.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['common.user.id'], ),
sa.PrimaryKeyConstraint('id'),
schema=f'{get_inv()}'
)
def downgrade():
op.drop_table('action_trade_document', schema=f'{get_inv()}')
op.drop_table('confirm_document', schema=f'{get_inv()}')
op.drop_table('trade_document', schema=f'{get_inv()}')

View File

@ -270,6 +270,19 @@ class TradeDef(ActionDef):
SCHEMA = schemas.Trade
class ConfirmDocumentDef(ActionDef):
VIEW = None
SCHEMA = schemas.ConfirmDocument
class RevokeDocumentDef(ActionDef):
VIEW = None
SCHEMA = schemas.RevokeDocument
class CancelTradeDef(ActionDef):
VIEW = None
SCHEMA = schemas.CancelTrade

View File

@ -296,7 +296,7 @@ class ActionDevice(db.Model):
primary_key=True)
class ActionWithMultipleTradeDocuments(Action):
class ActionWithMultipleTradeDocuments(ActionWithMultipleDevices):
documents = relationship(TradeDocument,
backref=backref('actions_docs', lazy=True, **_sorted_actions),
secondary=lambda: ActionTradeDocument.__table__,
@ -1466,14 +1466,18 @@ class ConfirmDocument(JoinedTableMixin, ActionWithMultipleTradeDocuments):
lazy=True,
order_by=lambda: Action.end_time,
collection_class=list),
primaryjoin='Confirm.action_id == Action.id')
primaryjoin='ConfirmDocument.action_id == Action.id')
def __repr__(self) -> str:
if self.action.t in ['Trade']:
origin = 'To'
if self.user == self.action.user_from:
origin = 'From'
return '<{0.t} {0.id} accepted by {1}>'.format(self, origin)
return '<{0.t}app/views/inventory/ {0.id} accepted by {1}>'.format(self, origin)
class RevokeDocument(ConfirmDocument):
pass
class Confirm(JoinedTableMixin, ActionWithMultipleDevices):
@ -1516,7 +1520,7 @@ class ConfirmRevoke(Confirm):
return '<{0.t} {0.id} accepted by {0.user}>'.format(self)
class Trade(JoinedTableMixin, ActionWithMultipleDevices):
class Trade(JoinedTableMixin, ActionWithMultipleTradeDocuments):
"""Trade actions log the political exchange of devices between users.
Every time a trade action is performed, the old user looses its
political possession, for example ownership, in favor of another

View File

@ -55,15 +55,19 @@ class Action(Thing):
class ActionWithOneDevice(Action):
__doc__ = m.ActionWithOneDevice.__doc__
doc = NestedOn(s_document.TradeDocument, only_query='id')
class ActionWithOneDocument(Action):
__doc__ = m.ActionWithOneDevice.__doc__
device = NestedOn(s_device.Device, only_query='id')
class ActionWithMultipleDocuments(Action):
__doc__ = m.ActionWithMultipleTradeDocuments.__doc__
documents = NestedOn(s_document.TradeDocument,
many=True,
required=True, # todo test ensuring len(devices) >= 1
only_query='id',
collection_class=OrderedSet)
class ActionWithMultipleDevices(Action):
__doc__ = m.ActionWithMultipleDevices.__doc__
devices = NestedOn(s_device.Device,
@ -476,7 +480,7 @@ class Confirm(ActionWithMultipleDevices):
raise ValidationError(txt)
class ConfirmDocument(ActionWithOneDocument):
class ConfirmDocument(ActionWithMultipleDocuments):
__doc__ = m.Confirm.__doc__
action = NestedOn('Action', only_query='id')
@ -580,8 +584,8 @@ class Revoke(ActionWithMultipleDevices):
raise ValidationError(txt)
class RevokeDocument(ActionWithOneDocument):
__doc__ = m.Revoke.__doc__
class RevokeDocument(ActionWithMultipleDocuments):
__doc__ = m.RevokeDocument.__doc__
action = NestedOn('Action', only_query='id')
@validates_schema
@ -598,7 +602,8 @@ class RevokeDocument(ActionWithOneDocument):
This is not checked in the view becouse the list of documents is inmutable
"""
if not data['devices'] == OrderedSet():
import pdb; pdb.set_trace()
if not data['documents'] == OrderedSet():
return
documents = []
@ -684,7 +689,7 @@ class ConfirmRevoke(ActionWithMultipleDevices):
raise ValidationError(txt)
class ConfirmRevokeDocument(ActionWithOneDocument):
class ConfirmRevokeDocument(ActionWithMultipleDocuments):
__doc__ = m.ConfirmRevoke.__doc__
action = NestedOn('Action', only_query='id')

View File

@ -5,7 +5,8 @@ from sqlalchemy.util import OrderedSet
from teal.marshmallow import ValidationError
from ereuse_devicehub.db import db
from ereuse_devicehub.resources.action.models import Trade, Confirm, ConfirmRevoke, Revoke
from ereuse_devicehub.resources.action.models import (Trade, Confirm, ConfirmRevoke,
Revoke, RevokeDocument, ConfirmDocument)
from ereuse_devicehub.resources.user.models import User
from ereuse_devicehub.resources.lot.views import delete_from_trade
@ -152,7 +153,7 @@ class ConfirmMixin():
self.schema = schema
a = resource_def.schema.load(data)
self.validate(a)
if not a['devices'] and not a['documents']:
if not a['devices']:
raise ValidationError('Devices not exist.')
self.model = self.Model(**a)
@ -267,3 +268,134 @@ class ConfirmRevokeView(ConfirmMixin):
dev.reset_owner()
trade.lot.devices.difference_update(devices)
class ConfirmDocumentMixin():
"""
Very Important:
==============
All of this Views than inherit of this class is executed for users
than is not owner of the Trade action.
The owner of Trade action executed this actions of confirm and revoke from the
lot
"""
Model = None
def __init__(self, data, resource_def, schema):
# import pdb; pdb.set_trace()
self.schema = schema
a = resource_def.schema.load(data)
self.validate(a)
if not a['documents']:
raise ValidationError('Documents not exist.')
self.model = self.Model(**a)
def post(self):
db.session().final_flush()
ret = self.schema.jsonify(self.model)
ret.status_code = 201
db.session.commit()
return ret
class ConfirmDocumentView(ConfirmDocumentMixin):
"""Handler for manager the Confirmation register from post
request_confirm = {
'type': 'Confirm',
'action': trade.id,
'devices': [device_id]
}
"""
Model = Confirm
def validate(self, data):
"""If there are one device than have one confirmation,
then remove the list this device of the list of devices of this action
"""
real_devices = []
for dev in data['devices']:
ac = dev.last_action_trading
if ac.type == Confirm.t and not ac.user == g.user:
real_devices.append(dev)
data['devices'] = OrderedSet(real_devices)
# Change the owner for every devices
for dev in data['devices']:
user_to = data['action'].user_to
dev.change_owner(user_to)
class RevokeDocumentView(ConfirmDocumentMixin):
"""Handler for manager the Revoke register from post
request_revoke = {
'type': 'Revoke',
'action': trade.id,
'devices': [device_id],
}
"""
Model = RevokeDocument
def __init__(self, data, resource_def, schema):
self.schema = schema
a = resource_def.schema.load(data)
self.validate(a)
def validate(self, data):
"""All devices need to have the status of DoubleConfirmation."""
### check ###
if not data['documents']:
raise ValidationError('Documents not exist.')
for doc in data['documents']:
if not doc.trading == 'Confirmed':
txt = 'Some of documents do not have enough to confirm for to do a revoke'
ValidationError(txt)
### End check ###
class ConfirmRevokeDocumentView(ConfirmDocumentMixin):
"""Handler for manager the Confirmation register from post
request_confirm_revoke = {
'type': 'ConfirmRevoke',
'action': action_revoke.id,
'devices': [device_id]
}
"""
Model = ConfirmRevoke
def validate(self, data):
"""All devices need to have the status of revoke."""
if not data['action'].type == 'Revoke':
txt = 'Error: this action is not a revoke action'
ValidationError(txt)
for dev in data['devices']:
if not dev.trading == 'Revoke':
txt = 'Some of devices do not have revoke to confirm'
ValidationError(txt)
devices = OrderedSet(data['devices'])
data['devices'] = devices
# Change the owner for every devices
# data['action'] == 'Revoke'
trade = data['action'].action
for dev in devices:
dev.reset_owner()
trade.lot.devices.difference_update(devices)

View File

@ -625,11 +625,11 @@ class Computer(Device):
It is a subset of the Linux definition of DMI / DMI decode.
"""
amount = Column(Integer, check_range('amount', min=0, max=100), default=0)
owner_id = db.Column(UUID(as_uuid=True),
db.ForeignKey(User.id),
nullable=False,
default=lambda: g.user.id)
author = db.relationship(User, primaryjoin=owner_id == User.id)
# owner_id = db.Column(UUID(as_uuid=True),
# db.ForeignKey(User.id),
# nullable=False,
# default=lambda: g.user.id)
# author = db.relationship(User, primaryjoin=owner_id == User.id)
transfer_state = db.Column(IntEnum(TransferState), default=TransferState.Initial, nullable=False)
transfer_state.comment = TransferState.__doc__
receiver_id = db.Column(UUID(as_uuid=True),

View File

@ -94,7 +94,8 @@ class TradeDocument(Thing):
"""The trading state, or None if no Trade action has
ever been performed to this device. This extract the posibilities for to do"""
confirm = 'Confirm'
# import pdb; pdb.set_trace()
confirm = 'ConfirmDocument'
to_confirm = 'To Confirm'
revoke = 'Revoke'
@ -105,16 +106,13 @@ class TradeDocument(Thing):
actions = list(reversed(actions))
ac = actions[0]
if ac.type == confirm:
return confirm
if ac.type == revoke:
return revoke
if ac.type == confirm:
if ac.user == self.owner:
return confirm
return to_confirm
return 'Confirmed'
def last_action_of(self, *types):
"""Gets the last action of the given types.

View File

@ -6,7 +6,7 @@ from teal.resource import View
from ereuse_devicehub.db import db
from ereuse_devicehub.resources.tradedocument.models import TradeDocument
from ereuse_devicehub.resources.action.models import Confirm, Revoke
from ereuse_devicehub.resources.action.models import ConfirmDocument
from ereuse_devicehub.resources.hash_reports import ReportHash
@ -28,7 +28,7 @@ class TradeDocumentView(View):
trade = doc.lot.trade
if trade:
trade.documents.add(doc)
confirm = Confirm(action=trade,
confirm = ConfirmDocument(action=trade,
user=g.user,
devices=set(),
documents={doc})