Add role management routes
parent
3b09857dbc
commit
562e2653c9
|
@ -1,6 +1,6 @@
|
||||||
from app.core import bcrypt
|
from app.core import bcrypt
|
||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
from .models import Account
|
from .models import Account, Role
|
||||||
|
|
||||||
accounts_bp = Blueprint('accounts', __name__)
|
accounts_bp = Blueprint('accounts', __name__)
|
||||||
|
|
||||||
|
@ -44,6 +44,44 @@ def update_account_role(account_id, role_id):
|
||||||
acc.save()
|
acc.save()
|
||||||
|
|
||||||
|
|
||||||
|
def create_role(display_name, permissions):
|
||||||
|
"""
|
||||||
|
Tries to create role
|
||||||
|
|
||||||
|
:param display_name: Name of role - display only
|
||||||
|
:param permissions: List of strings - permissions that this role has
|
||||||
|
:type display_name: String
|
||||||
|
:type permissions: List of String
|
||||||
|
:returns: True if role is successfully created
|
||||||
|
:rtype: Boolean
|
||||||
|
:raises: ValueError if role already exists
|
||||||
|
"""
|
||||||
|
role = Role(display_name, permissions)
|
||||||
|
role.save()
|
||||||
|
|
||||||
|
|
||||||
|
def get_role(role_id):
|
||||||
|
"""
|
||||||
|
Tries to get role
|
||||||
|
|
||||||
|
:param role_id: Id of role
|
||||||
|
:type role_id: int
|
||||||
|
:returns: Role if found
|
||||||
|
:rtype: Role
|
||||||
|
"""
|
||||||
|
return Role.get(role_id)
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_roles():
|
||||||
|
"""
|
||||||
|
Gets all roles
|
||||||
|
|
||||||
|
:returns: Role list if found
|
||||||
|
:rtype: List of Roles
|
||||||
|
"""
|
||||||
|
return Role.get_all()
|
||||||
|
|
||||||
|
|
||||||
def create_token(username, password):
|
def create_token(username, password):
|
||||||
"""
|
"""
|
||||||
Tries to create token for account with given parameters.
|
Tries to create token for account with given parameters.
|
||||||
|
|
|
@ -122,10 +122,12 @@ class Role(db.Model):
|
||||||
__tablename__ = 'roles'
|
__tablename__ = 'roles'
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
display_name = db.Column(db.String)
|
display_name = db.Column(db.String, unique=True)
|
||||||
|
permissions = db.Column(db.ARRAY(db.String))
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name, permissions):
|
||||||
self.display_name = str(name)
|
self.display_name = str(name)
|
||||||
|
self.permissions = permissions
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
"""
|
"""
|
||||||
|
@ -147,7 +149,7 @@ class Role(db.Model):
|
||||||
"""
|
"""
|
||||||
Get role with id = roleId
|
Get role with id = roleId
|
||||||
"""
|
"""
|
||||||
return Role.query.filter_by(id=roleId)
|
return Role.query.filter_by(id=roleId).first_or_404()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<Role %s>' % self.display_name
|
return '<Role %s (%s)>' % self.display_name, self.permissions
|
||||||
|
|
|
@ -40,7 +40,9 @@ class ProtectedResource(Resource):
|
||||||
def add_resources():
|
def add_resources():
|
||||||
from .resources.account import (AccountResource,
|
from .resources.account import (AccountResource,
|
||||||
AccountListResource,
|
AccountListResource,
|
||||||
AccountRoleResource)
|
AccountRoleResource,
|
||||||
|
RoleResource,
|
||||||
|
RolesResource)
|
||||||
from .resources.token import TokenResource, ValidateTokenResource
|
from .resources.token import TokenResource, ValidateTokenResource
|
||||||
from .resources.device import (DeviceResource,
|
from .resources.device import (DeviceResource,
|
||||||
DeviceRecordingResource,
|
DeviceRecordingResource,
|
||||||
|
@ -53,6 +55,8 @@ def add_resources():
|
||||||
api.add_resource(AccountResource, '/v1/accounts/<int:account_id>')
|
api.add_resource(AccountResource, '/v1/accounts/<int:account_id>')
|
||||||
api.add_resource(AccountListResource, '/v1/accounts')
|
api.add_resource(AccountListResource, '/v1/accounts')
|
||||||
api.add_resource(AccountRoleResource, '/v1/accounts/<int:account_id>/role')
|
api.add_resource(AccountRoleResource, '/v1/accounts/<int:account_id>/role')
|
||||||
|
api.add_resource(RoleResource, '/v1/roles/<int:role_id>')
|
||||||
|
api.add_resource(RolesResource, '/v1/roles')
|
||||||
api.add_resource(TokenResource, '/v1/token')
|
api.add_resource(TokenResource, '/v1/token')
|
||||||
api.add_resource(ValidateTokenResource, '/v1/token/validate')
|
api.add_resource(ValidateTokenResource, '/v1/token/validate')
|
||||||
api.add_resource(DeviceResource, '/v1/devices/<int:device_id>')
|
api.add_resource(DeviceResource, '/v1/devices/<int:device_id>')
|
||||||
|
|
|
@ -17,6 +17,32 @@ class RoleUpdateSchema(Schema):
|
||||||
role_id = fields.Integer(required=True, load_only=True, location='json')
|
role_id = fields.Integer(required=True, load_only=True, location='json')
|
||||||
|
|
||||||
|
|
||||||
|
class RoleSchema(Schema):
|
||||||
|
role_id = fields.Integer(required=True, location='json')
|
||||||
|
display_name = fields.String(required=True, location='json')
|
||||||
|
permissions = fields.List(fields.String, required=True,
|
||||||
|
location='json', many=True)
|
||||||
|
|
||||||
|
|
||||||
|
class RoleWrapperSchema(Schema):
|
||||||
|
role = fields.Nested(RoleSchema, required=True, location='json')
|
||||||
|
|
||||||
|
|
||||||
|
class RolesWrapperSchema(Schema):
|
||||||
|
roles = fields.Nested(RoleSchema, required=True,
|
||||||
|
location='json', many=True)
|
||||||
|
|
||||||
|
|
||||||
|
class RoleCreationSchema(Schema):
|
||||||
|
display_name = fields.String(required=True, location='json')
|
||||||
|
permissions = fields.List(fields.String, required=True,
|
||||||
|
location='json', many=True)
|
||||||
|
|
||||||
|
|
||||||
|
class RoleCreationWrapperSchema(Schema):
|
||||||
|
role = fields.Nested(RoleCreationSchema, required=True, location='json')
|
||||||
|
|
||||||
|
|
||||||
class UserWrapperSchema(Schema):
|
class UserWrapperSchema(Schema):
|
||||||
user = fields.Nested(UserSchema, required=True, location='json')
|
user = fields.Nested(UserSchema, required=True, location='json')
|
||||||
|
|
||||||
|
@ -29,6 +55,29 @@ class AccountResource(ProtectedResource):
|
||||||
abort(403, message='You can only get your own account', status='error')
|
abort(403, message='You can only get your own account', status='error')
|
||||||
|
|
||||||
|
|
||||||
|
class RoleResource(ProtectedResource):
|
||||||
|
@swag_from('swagger/get_role_spec.yaml')
|
||||||
|
def get(self, role_id):
|
||||||
|
return RoleWrapperSchema().dump(
|
||||||
|
{'role': accounts.get_role(role_id)}), 200
|
||||||
|
|
||||||
|
|
||||||
|
class RolesResource(ProtectedResource):
|
||||||
|
@use_args(RoleCreationWrapperSchema())
|
||||||
|
@swag_from('swagger/create_role_spec.yaml')
|
||||||
|
def post(self, args):
|
||||||
|
args = args['role']
|
||||||
|
success = accounts.create_role(args['display_name'],
|
||||||
|
args['permissions'])
|
||||||
|
if success:
|
||||||
|
return '', 201
|
||||||
|
|
||||||
|
@swag_from('swagger/get_roles_spec.yaml')
|
||||||
|
def get(self):
|
||||||
|
return RolesWrapperSchema().dump(
|
||||||
|
{'roles': accounts.get_all_roles()}), 200
|
||||||
|
|
||||||
|
|
||||||
class AccountRoleResource(ProtectedResource):
|
class AccountRoleResource(ProtectedResource):
|
||||||
@use_args(RoleUpdateSchema())
|
@use_args(RoleUpdateSchema())
|
||||||
@swag_from('swagger/update_account_role_spec.yaml')
|
@swag_from('swagger/update_account_role_spec.yaml')
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 55611f1868bd
|
||||||
|
Revises: 5aa58dcd7a2c
|
||||||
|
Create Date: 2018-09-23 00:56:34.193022
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '55611f1868bd'
|
||||||
|
down_revision = '5aa58dcd7a2c'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('roles', sa.Column('permissions', sa.ARRAY(sa.String()), nullable=True))
|
||||||
|
op.create_unique_constraint(None, 'roles', ['display_name'])
|
||||||
|
role = sa.table('roles', sa.column('id', sa.Integer),
|
||||||
|
sa.column('permissions', sa.ARRAY(sa.String)))
|
||||||
|
op.execute(role.update().where(role.c.id == op.inline_literal(1)).
|
||||||
|
values({'permissions':
|
||||||
|
['CREATE_DEVICE_TYPE', 'ASSIGN_ROLE',
|
||||||
|
'CREATE_DEVICE', 'CREATE_DASHBOARD',
|
||||||
|
'READ_DEVICE_TYPES', 'READ_ROLES']})
|
||||||
|
)
|
||||||
|
|
||||||
|
op.execute(role.update().where(role.c.id == op.inline_literal(2)).
|
||||||
|
values({'permissions':
|
||||||
|
['CREATE_DEVICE', 'CREATE_DASHBOARD',
|
||||||
|
'READ_DEVICE_TYPES', 'READ_ROLES']})
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_constraint(None, 'roles', type_='unique')
|
||||||
|
op.drop_column('roles', 'permissions')
|
||||||
|
# ### end Alembic commands ###
|
Loading…
Reference in New Issue