Add device account associations
parent
1ae5d1a2b8
commit
cb0e61c906
|
@ -1,6 +1,7 @@
|
||||||
from marshmallow import Schema, fields
|
from marshmallow import Schema, fields
|
||||||
from webargs.flaskparser import use_args
|
from webargs.flaskparser import use_args
|
||||||
from flasgger import swag_from
|
from flasgger import swag_from
|
||||||
|
from flask import g
|
||||||
import app.devices as devices
|
import app.devices as devices
|
||||||
from app.api import ProtectedResource
|
from app.api import ProtectedResource
|
||||||
|
|
||||||
|
@ -13,6 +14,9 @@ class DeviceSchema(Schema):
|
||||||
class DeviceWrapperSchema(Schema):
|
class DeviceWrapperSchema(Schema):
|
||||||
device = fields.Nested(DeviceSchema, required=True, location='json')
|
device = fields.Nested(DeviceSchema, required=True, location='json')
|
||||||
|
|
||||||
|
class DevicesWrapperSchema(Schema):
|
||||||
|
devices = fields.Nested(DeviceSchema, required=True,
|
||||||
|
location='json', many=True)
|
||||||
|
|
||||||
class RecordingsSchema(Schema):
|
class RecordingsSchema(Schema):
|
||||||
recorded_at = fields.DateTime()
|
recorded_at = fields.DateTime()
|
||||||
|
@ -45,6 +49,12 @@ class DeviceListResource(ProtectedResource):
|
||||||
def post(self, args):
|
def post(self, args):
|
||||||
args = args['device']
|
args = args['device']
|
||||||
success = devices.create_device(
|
success = devices.create_device(
|
||||||
args['name'])
|
args['name'],
|
||||||
|
g.current_account.id)
|
||||||
if success:
|
if success:
|
||||||
return '', 201
|
return '', 201
|
||||||
|
|
||||||
|
@swag_from('swagger/get_devices_spec.yaml')
|
||||||
|
def get(self):
|
||||||
|
return DevicesWrapperSchema().dump(
|
||||||
|
{'devices': devices.get_devices(g.current_account.id)}), 200
|
||||||
|
|
|
@ -14,7 +14,7 @@ responses:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
-device
|
- device
|
||||||
properties:
|
properties:
|
||||||
device:
|
device:
|
||||||
$ref: '#/definitions/Device'
|
$ref: '#/definitions/Device'
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
Gets all associated devices
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Device
|
||||||
|
parameters:
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Success
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- devices
|
||||||
|
properties:
|
||||||
|
devices:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/Device'
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import sys
|
import sys
|
||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
from .models import Device, Recording
|
from .models import Device, Recording, DeviceAssociation
|
||||||
from app import app
|
from app import app
|
||||||
|
|
||||||
devices_bp = Blueprint('devices', __name__)
|
devices_bp = Blueprint('devices', __name__)
|
||||||
|
|
||||||
|
|
||||||
# Public interface
|
# Public interface
|
||||||
def create_device(name, device_type=1):
|
def create_device(name, account_id, device_type=1):
|
||||||
"""
|
"""
|
||||||
Tries to create device with given parameters
|
Tries to create device with given parameters
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ def create_device(name, device_type=1):
|
||||||
"""
|
"""
|
||||||
device = Device(name, None, device_type)
|
device = Device(name, None, device_type)
|
||||||
device.save()
|
device.save()
|
||||||
|
device_association = DeviceAssociation(device.id, account_id)
|
||||||
|
device_association.save()
|
||||||
|
|
||||||
|
|
||||||
def get_device_recordings(device_id):
|
def get_device_recordings(device_id):
|
||||||
|
@ -56,6 +58,16 @@ def get_device(device_id):
|
||||||
return Device.get(id=device_id)
|
return Device.get(id=device_id)
|
||||||
|
|
||||||
|
|
||||||
|
def get_devices(account_id):
|
||||||
|
"""
|
||||||
|
Tries to get all devices associated to account. Raises error on
|
||||||
|
failure
|
||||||
|
|
||||||
|
:returns: List of Devices associated to this account
|
||||||
|
:rtype: List of Devices
|
||||||
|
"""
|
||||||
|
return Device.get_many_for_user(account_id)
|
||||||
|
|
||||||
def create_recording(device_id, raw_json):
|
def create_recording(device_id, raw_json):
|
||||||
"""
|
"""
|
||||||
Tries to create recording with given parameters. Raises error on failure
|
Tries to create recording with given parameters. Raises error on failure
|
||||||
|
|
|
@ -92,6 +92,8 @@ class Device(db.Model):
|
||||||
device_type = db.relationship("DeviceType", foreign_keys=[device_type_id])
|
device_type = db.relationship("DeviceType", foreign_keys=[device_type_id])
|
||||||
configuration = db.Column(JSON, nullable=True)
|
configuration = db.Column(JSON, nullable=True)
|
||||||
|
|
||||||
|
users = db.relationship("DeviceAssociation")
|
||||||
|
|
||||||
def __init__(self, name, configuration=None, device_type=1):
|
def __init__(self, name, configuration=None, device_type=1):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
|
@ -121,6 +123,13 @@ class Device(db.Model):
|
||||||
"""
|
"""
|
||||||
return Device.query.filter_by(**kwargs).all()
|
return Device.query.filter_by(**kwargs).all()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_many_for_user(account_id):
|
||||||
|
"""
|
||||||
|
Get many devices which are associated to account
|
||||||
|
"""
|
||||||
|
return Device.query.filter(Device.users.any(account_id=account_id)).all()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get(**kwargs):
|
def get(**kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -150,6 +159,58 @@ class Device(db.Model):
|
||||||
return '<Device (name=%s, type=%s)>' % (
|
return '<Device (name=%s, type=%s)>' % (
|
||||||
self.name, self.device_type_id)
|
self.name, self.device_type_id)
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceAssociation(db.Model):
|
||||||
|
__tablename__ = 'device_associations'
|
||||||
|
|
||||||
|
device_id = db.Column(db.Integer, db.ForeignKey('devices.id'), primary_key=True)
|
||||||
|
account_id = db.Column(db.Integer, db.ForeignKey('accounts.id'), primary_key=True)
|
||||||
|
access_level = db.Column(db.Integer, db.ForeignKey('access_levels.id'),
|
||||||
|
nullable=False)
|
||||||
|
|
||||||
|
def __init__(self, device_id, account_id, access_level=1):
|
||||||
|
self.device_id = device_id
|
||||||
|
self.account_id = account_id
|
||||||
|
self.access_level = access_level
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
"""
|
||||||
|
Stores this device association to database
|
||||||
|
This may raise errors
|
||||||
|
"""
|
||||||
|
db.session.add(self)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_many(**kwargs):
|
||||||
|
"""
|
||||||
|
Get many device associations with given filters as a list
|
||||||
|
|
||||||
|
Available filters:
|
||||||
|
* device_id
|
||||||
|
* account_id
|
||||||
|
"""
|
||||||
|
return DeviceAssociation.query.filter_by(**kwargs).all()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_for_user(account_id):
|
||||||
|
"""
|
||||||
|
Get many device associations for user with account id passed in
|
||||||
|
parameter
|
||||||
|
"""
|
||||||
|
return get_many(account_id=account_id)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_for_device(device_id):
|
||||||
|
"""
|
||||||
|
Get many device associations for device with account id passed in
|
||||||
|
parameter
|
||||||
|
"""
|
||||||
|
return get_many(device_id=device_id)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<DeviceAssociation (device_id=%s, accoount_id=%s)>' % (self.device_id, self.account_id)
|
||||||
|
|
||||||
|
|
||||||
class DeviceType(db.Model):
|
class DeviceType(db.Model):
|
||||||
__tablename__ = 'device_types'
|
__tablename__ = 'device_types'
|
||||||
|
@ -162,3 +223,16 @@ class DeviceType(db.Model):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<DeviceType (name %s)>' % self.name
|
return '<DeviceType (name %s)>' % self.name
|
||||||
|
|
||||||
|
|
||||||
|
class AccessLevel(db.Model):
|
||||||
|
__tablename__ = 'access_levels'
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
name = db.Column(db.String, nullable=False)
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<AccessLevel (name %s)>' % self.name
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: efbd47fca2fd
|
||||||
|
Revises: 6b444e5e2eef
|
||||||
|
Create Date: 2018-08-24 14:23:01.904259
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'efbd47fca2fd'
|
||||||
|
down_revision = '6b444e5e2eef'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('access_levels',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('name', sa.String(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.create_table('device_associations',
|
||||||
|
sa.Column('device_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('account_id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('access_level', sa.Integer(), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['access_level'], ['access_levels.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['account_id'], ['accounts.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['device_id'], ['devices.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('device_id', 'account_id')
|
||||||
|
)
|
||||||
|
|
||||||
|
access_levels_table = sa.Table('access_levels', sa.MetaData(),
|
||||||
|
sa.Column('id', sa.Integer),
|
||||||
|
sa.Column('name', sa.String))
|
||||||
|
|
||||||
|
op.bulk_insert(access_levels_table,
|
||||||
|
[
|
||||||
|
{'id':1, 'name':'FULL'}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('device_associations')
|
||||||
|
op.drop_table('access_levels')
|
||||||
|
# ### end Alembic commands ###
|
Loading…
Reference in New Issue