Merged in feature/device-documentation (pull request #59)

Feature/device documentation
develop
Ensar Sarajcic 2018-11-04 14:08:24 +00:00
commit 8745c5e783
8 changed files with 197 additions and 1 deletions

View File

@ -24,6 +24,7 @@ def add_resources():
DeviceTypeResource, DeviceTypeResource,
DeviceTypeListResource, DeviceTypeListResource,
DeviceConfigurationResource, DeviceConfigurationResource,
DeviceDocumentationResource,
DeviceSecretResource, DeviceSecretResource,
DeviceSecretResetResource, DeviceSecretResetResource,
DeviceShareResource, DeviceShareResource,
@ -56,6 +57,8 @@ def add_resources():
api.add_resource(DeviceTypeListResource, '/v1/devices/types') api.add_resource(DeviceTypeListResource, '/v1/devices/types')
api.add_resource(DeviceConfigurationResource, api.add_resource(DeviceConfigurationResource,
'/v1/devices/<int:device_id>/configuration') '/v1/devices/<int:device_id>/configuration')
api.add_resource(DeviceDocumentationResource,
'/v1/devices/<int:device_id>/documentation')
api.add_resource(DeviceSecretResource, api.add_resource(DeviceSecretResource,
'/v1/devices/<int:device_id>/secret') '/v1/devices/<int:device_id>/secret')
api.add_resource(DeviceSecretResetResource, api.add_resource(DeviceSecretResetResource,

View File

@ -45,6 +45,11 @@ class RecordingsQuerySchema(Schema):
orders = fields.Raw() orders = fields.Raw()
class DeviceDocumentationSchema(BaseTimestampedResourceSchema):
device_id = fields.Integer(dump_only=True)
text = fields.String(required=True)
class DeviceSecretSchema(BaseResourceSchema): class DeviceSecretSchema(BaseResourceSchema):
device_secret = fields.String(dump_only=True) device_secret = fields.String(dump_only=True)
secret_algorithm = fields.String(required=True) secret_algorithm = fields.String(required=True)
@ -167,6 +172,23 @@ class DeviceConfigurationResource(ProtectedResource):
return devices.get_device_configuration(device_id), 200 return devices.get_device_configuration(device_id), 200
class DeviceDocumentationResource(ProtectedResource):
@use_args(DeviceDocumentationSchema(), locations=('json',))
@swag_from('swagger/update_device_documentation_spec.yaml')
def put(self, args, device_id):
validate_device_ownership(device_id)
update_device_documentation = devices.update_device_documentation(
device_id, args['text'])
return DeviceDocumentationSchema().dump(
update_device_documentation), 200
@swag_from('swagger/get_device_documentation_spec.yaml')
def get(self, device_id):
validate_device_ownership(device_id)
return DeviceDocumentationSchema().dump(
devices.get_device_documentation(device_id)), 200
class DeviceSecretResource(ProtectedResource): class DeviceSecretResource(ProtectedResource):
@swag_from('swagger/get_device_secret_spec.yaml') @swag_from('swagger/get_device_secret_spec.yaml')
def get(self, device_id): def get(self, device_id):

View File

@ -0,0 +1,17 @@
Gets a device documentation
---
tags:
- Device
- Docs
parameters:
- in: path
name: device_id
required: true
type: integer
description: Id of the device
responses:
200:
description: Success
schema:
$ref: '#/definitions/DeviceDocumentation'

View File

@ -0,0 +1,26 @@
Updates a device documentation
---
tags:
- Device
- Docs
parameters:
- in: path
name: device_id
required: true
type: integer
description: Id of the device
- in: body
name: body
required: true
schema:
$ref: '#/definitions/DeviceDocumentation'
responses:
200:
description: Success
schema:
type: object
required:
- content
properties:
content:
$ref: '#/definitions/DeviceDocumentation'

View File

@ -8,7 +8,8 @@ from .models import (Device,
Recording, Recording,
DeviceAssociation, DeviceAssociation,
DeviceType, DeviceType,
AccessLevel) AccessLevel,
DeviceDocumentation)
from itsdangerous import URLSafeSerializer from itsdangerous import URLSafeSerializer
from app.core import app from app.core import app
from app.errors import NotPresentError from app.errors import NotPresentError
@ -238,6 +239,29 @@ def get_devices(account_id):
return Device.get_many_for_user(account_id) return Device.get_many_for_user(account_id)
def get_device_documentation(device_id):
"""
Tries to get device documentation associated to given device.
:returns: DeviceDocumentation
"""
if not Device.exists(id=device_id):
raise NotPresentError("Device with id %s does not exist" % device_id)
return DeviceDocumentation.get_for_device(device_id)
def update_device_documentation(device_id, new_text):
"""
Tries to update device documentation
"""
if not Device.exists(id=device_id):
raise NotPresentError("Device with id %s does not exist" % device_id)
device_documentation = DeviceDocumentation.get_for_device(device_id)
device_documentation.text = new_text
device_documentation.save()
return device_documentation
def get_device_types(): def get_device_types():
""" """
Tries to get all device types. Raises error on failure Tries to get all device types. Raises error on failure

View File

@ -137,6 +137,8 @@ class Device(db.Model):
cascade="save-update, merge, delete") cascade="save-update, merge, delete")
widgets = db.relationship("DashboardWidget", widgets = db.relationship("DashboardWidget",
cascade="save-update, merge, delete") cascade="save-update, merge, delete")
documentations = db.relationship("DeviceDocumentation",
cascade="save-update, merge, delete")
def __init__(self, name, configuration=None, device_type=1): def __init__(self, name, configuration=None, device_type=1):
self.name = name self.name = name
@ -341,6 +343,54 @@ class DeviceType(db.Model):
return '<DeviceType (name %s)>' % self.name return '<DeviceType (name %s)>' % self.name
class DeviceDocumentation(db.Model):
__tablename__ = 'device_documentations'
device_id = db.Column(db.Integer, db.ForeignKey('devices.id'),
primary_key=True)
text = db.Column(db.Text, nullable=False)
created_at = db.Column(db.DateTime,
nullable=False,
default=db.func.current_timestamp())
modified_at = db.Column(db.DateTime,
nullable=False,
default=db.func.current_timestamp(),
onupdate=db.func.current_timestamp())
def __init__(self, device_id, text):
self.device_id = device_id
self.text = text
def save(self):
"""
Stores this device documentation to database
This may raise errors
"""
db.session.add(self)
db.session.commit()
@staticmethod
def get(**kwargs):
"""
Get device documentation with given filters
Available filters:
* device_id
"""
return DeviceDocumentation.query.filter_by(**kwargs).first()
@staticmethod
def get_for_device(device_id):
"""
Get documentation for device with device id passed in
parameter
"""
return (DeviceDocumentation.get(device_id=device_id) or
DeviceDocumentation(device_id, ""))
def __repr__(self):
return '<DeviceDocumentation (device_id %s)>' % self.device_id
class AccessLevel(db.Model): class AccessLevel(db.Model):
__tablename__ = 'access_levels' __tablename__ = 'access_levels'

View File

@ -233,6 +233,25 @@ definitions:
modified_at: modified_at:
$ref: '#/definitions/datetime' $ref: '#/definitions/datetime'
DeviceDocumentation:
type: object
required:
- device_id
- text
- created_at
- modified_at
properties:
device_id:
$ref: '#/definitions/id'
text:
type: string
description: Text of documentation
example: This device is used for ...
created_at:
$ref: '#/definitions/datetime'
modified_at:
$ref: '#/definitions/datetime'
DeviceShareTokenCreation: DeviceShareTokenCreation:
type: object type: object
required: required:

View File

@ -0,0 +1,35 @@
"""empty message
Revision ID: 9f71f5a68c53
Revises: 3cf41808886b
Create Date: 2018-11-04 15:00:35.383875
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '9f71f5a68c53'
down_revision = '3cf41808886b'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('device_documentations',
sa.Column('device_id', sa.Integer(), nullable=False),
sa.Column('text', sa.Text(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('modified_at', sa.DateTime(), nullable=False),
sa.ForeignKeyConstraint(['device_id'], ['devices.id'], ),
sa.PrimaryKeyConstraint('device_id')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('device_documentations')
# ### end Alembic commands ###