Add device account associations

master
esensar 2018-08-24 14:32:31 +02:00
parent 1ae5d1a2b8
commit cb0e61c906
6 changed files with 170 additions and 4 deletions

View File

@ -1,6 +1,7 @@
from marshmallow import Schema, fields
from webargs.flaskparser import use_args
from flasgger import swag_from
from flask import g
import app.devices as devices
from app.api import ProtectedResource
@ -13,6 +14,9 @@ class DeviceSchema(Schema):
class DeviceWrapperSchema(Schema):
device = fields.Nested(DeviceSchema, required=True, location='json')
class DevicesWrapperSchema(Schema):
devices = fields.Nested(DeviceSchema, required=True,
location='json', many=True)
class RecordingsSchema(Schema):
recorded_at = fields.DateTime()
@ -45,6 +49,12 @@ class DeviceListResource(ProtectedResource):
def post(self, args):
args = args['device']
success = devices.create_device(
args['name'])
args['name'],
g.current_account.id)
if success:
return '', 201
@swag_from('swagger/get_devices_spec.yaml')
def get(self):
return DevicesWrapperSchema().dump(
{'devices': devices.get_devices(g.current_account.id)}), 200

View File

@ -14,7 +14,7 @@ responses:
schema:
type: object
required:
-device
- device
properties:
device:
$ref: '#/definitions/Device'

View File

@ -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'

View File

@ -1,13 +1,13 @@
import sys
from flask import Blueprint
from .models import Device, Recording
from .models import Device, Recording, DeviceAssociation
from app import app
devices_bp = Blueprint('devices', __name__)
# 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
@ -21,6 +21,8 @@ def create_device(name, device_type=1):
"""
device = Device(name, None, device_type)
device.save()
device_association = DeviceAssociation(device.id, account_id)
device_association.save()
def get_device_recordings(device_id):
@ -56,6 +58,16 @@ def get_device(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):
"""
Tries to create recording with given parameters. Raises error on failure

View File

@ -92,6 +92,8 @@ class Device(db.Model):
device_type = db.relationship("DeviceType", foreign_keys=[device_type_id])
configuration = db.Column(JSON, nullable=True)
users = db.relationship("DeviceAssociation")
def __init__(self, name, configuration=None, device_type=1):
self.name = name
self.configuration = configuration
@ -121,6 +123,13 @@ class Device(db.Model):
"""
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
def get(**kwargs):
"""
@ -150,6 +159,58 @@ class Device(db.Model):
return '<Device (name=%s, type=%s)>' % (
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):
__tablename__ = 'device_types'
@ -162,3 +223,16 @@ class DeviceType(db.Model):
def __repr__(self):
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

View File

@ -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 ###