moved everything to a new module called backend
This commit is contained in:
78
backend/api/__init__.py
Normal file
78
backend/api/__init__.py
Normal file
@@ -0,0 +1,78 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from flask import Blueprint, abort
|
||||
from flask_restplus import Api, Namespace
|
||||
|
||||
api_authorizations = {
|
||||
'apikey': {
|
||||
'type': 'apiKey',
|
||||
'in': 'header',
|
||||
'name': 'X-API-KEY'
|
||||
},
|
||||
'basicAuth': {
|
||||
'type': 'basic',
|
||||
'scheme': 'basic'
|
||||
},
|
||||
'bearerAuth': {
|
||||
'type': 'apiKey',
|
||||
'scheme': 'bearer',
|
||||
'name': 'Authorization',
|
||||
'in': 'header'
|
||||
}
|
||||
}
|
||||
|
||||
api_bp = Blueprint('api', __name__, url_prefix='/api')
|
||||
api_v1 = Api(api_bp, prefix="/v1", version='0.1', title='Vue Test API',
|
||||
description='The Vue Test API', doc='/v1/doc/', authorizations=api_authorizations, security='bearerAuth')
|
||||
|
||||
api_user = Namespace('user', description="User management namespace", authorizations=api_authorizations)
|
||||
api_group = Namespace('group', description="Group management namespace", authorizations=api_authorizations)
|
||||
api_room = Namespace('room', description="Room management namespace", authorizations=api_authorizations)
|
||||
api_recorder = Namespace('recorder', description="Recorder management namespace", authorizations=api_authorizations)
|
||||
api_virtual_command = Namespace('virtual_command', description="Virtual command namespace",
|
||||
authorizations=api_authorizations)
|
||||
api_cron_job = Namespace('cron_job', description="Cron job namespace",
|
||||
authorizations=api_authorizations)
|
||||
api_control = Namespace('control', description="Control namespace",
|
||||
authorizations=api_authorizations)
|
||||
|
||||
api_v1.add_namespace(api_user)
|
||||
api_v1.add_namespace(api_group)
|
||||
api_v1.add_namespace(api_room)
|
||||
api_v1.add_namespace(api_recorder)
|
||||
api_v1.add_namespace(api_virtual_command)
|
||||
api_v1.add_namespace(api_cron_job)
|
||||
api_v1.add_namespace(api_control)
|
||||
|
||||
auth_api_bp = Blueprint('auth_api', __name__, url_prefix='/api/auth')
|
||||
auth_api_v1 = Api(auth_api_bp, prefix="/v1", version='0.1', title='Auth API',
|
||||
description='Auth API', doc='/v1/doc/', authorizations=api_authorizations, security='bearerAuth')
|
||||
|
||||
auth_api_providers_ns = Namespace('providers')
|
||||
auth_api_register_ns = Namespace('register')
|
||||
auth_api_v1.add_namespace(auth_api_providers_ns)
|
||||
auth_api_v1.add_namespace(auth_api_register_ns)
|
||||
# user_api_bp = Blueprint('user_api', __name__, url_prefix='/api/user')
|
||||
# group_api_bp = Blueprint('group_api', __name__, url_prefix='/api/group')
|
||||
|
||||
from .example_api import *
|
||||
from .auth_api import *
|
||||
from .user_api import *
|
||||
from .group_api import *
|
||||
from .room_api import *
|
||||
from .recorder_api import *
|
||||
from .control_api import *
|
||||
from .virtual_command_api import *
|
||||
|
||||
|
||||
# from .group_api import *
|
||||
|
||||
|
||||
@api_bp.route('/<path:path>')
|
||||
def catch_all_api(path):
|
||||
"""
|
||||
Default 404 response for undefined paths in API.
|
||||
:param path:
|
||||
:return:
|
||||
"""
|
||||
abort(404)
|
||||
196
backend/api/auth_api.py
Normal file
196
backend/api/auth_api.py
Normal file
@@ -0,0 +1,196 @@
|
||||
# Copyright (c) 2019. Tobias Kurze
|
||||
"""
|
||||
This module provides functions related to authentication through the API.
|
||||
For example: listing of available auth providers or registration of users.
|
||||
|
||||
Login through API does not start a new session, but instead returns JWT.
|
||||
"""
|
||||
import base64
|
||||
import json
|
||||
from pprint import pprint
|
||||
|
||||
import flask
|
||||
from datetime import datetime, timedelta
|
||||
import jwt
|
||||
from flask import request, jsonify, current_app, url_for, Response, session, redirect, make_response
|
||||
from flask_jwt_extended import create_access_token, create_refresh_token, jwt_refresh_token_required, get_jwt_identity, \
|
||||
get_raw_jwt, jwt_required
|
||||
from functools import wraps
|
||||
from random import randint
|
||||
|
||||
from flask_login import logout_user, login_user
|
||||
from typing import Iterable
|
||||
|
||||
from flask_restplus import Resource, fields
|
||||
from werkzeug.routing import BuildError
|
||||
|
||||
from backend import db, app, jwt_extended
|
||||
from backend.api import auth_api_bp, auth_api_providers_ns, auth_api_register_ns
|
||||
from backend.auth import AUTH_PROVIDERS, oidc_auth
|
||||
from backend.models.user_model import User, Group, BlacklistToken
|
||||
|
||||
|
||||
@auth_api_bp.route('/providers', methods=('GET',))
|
||||
def get_auth_providers():
|
||||
providers = dict()
|
||||
for p in AUTH_PROVIDERS:
|
||||
provider = dict(AUTH_PROVIDERS[p])
|
||||
try:
|
||||
provider["url"] = url_for(AUTH_PROVIDERS[p]["url"])
|
||||
except BuildError:
|
||||
provider["url"] = AUTH_PROVIDERS[p]["url"]
|
||||
providers[p] = provider
|
||||
return jsonify(providers)
|
||||
|
||||
|
||||
@auth_api_providers_ns.route('/')
|
||||
class AuthProviders(Resource):
|
||||
def get(self):
|
||||
return get_auth_providers()
|
||||
|
||||
|
||||
@auth_api_bp.route('/register', methods=('POST',))
|
||||
def register():
|
||||
data = request.get_json()
|
||||
user = User(**data)
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
return jsonify(user.to_dict()), 201
|
||||
|
||||
|
||||
@auth_api_register_ns.route('/')
|
||||
@auth_api_register_ns.expect(auth_api_register_ns.model('RegisterModel', {
|
||||
'nickname': fields.String(required=False, description='The user\'s nickname'),
|
||||
'first_name': fields.String(required=False, description='The user\'s first name'),
|
||||
'last_name': fields.String(required=False, description='The user\'s last name'),
|
||||
'lang': fields.String(required=False, description='The user\'s preferred language'),
|
||||
'timezone': fields.String(required=False, description='The user\'s preferred timezone'),
|
||||
'email': fields.String(required=True, description='The user\'s e-mail address'),
|
||||
'password': fields.String(required=False, description='The group\'s name')
|
||||
}))
|
||||
class AuthProviders(Resource):
|
||||
def get(self):
|
||||
return register()
|
||||
|
||||
|
||||
@auth_api_bp.route('/login', methods=('GET', 'POST',))
|
||||
def login():
|
||||
print("login")
|
||||
print(request)
|
||||
data = request.get_json()
|
||||
if not data:
|
||||
return jsonify({'message': 'Invalid request data', 'authenticated': False}), 401
|
||||
print(data)
|
||||
user = User.authenticate(**data)
|
||||
|
||||
if not user:
|
||||
return jsonify({'message': 'Invalid credentials', 'authenticated': False}), 401
|
||||
|
||||
token = {
|
||||
'access_token': create_access_token(identity=user, fresh=True),
|
||||
'refresh_token': create_refresh_token(identity=user)
|
||||
}
|
||||
return jsonify(token), 200
|
||||
|
||||
# Endpoint for revoking the current users access token
|
||||
@auth_api_bp.route('/logout', methods=['GET', 'DELETE'])
|
||||
@jwt_required
|
||||
def logout():
|
||||
jti = get_raw_jwt()['jti']
|
||||
db.session.add(BlacklistToken(token=jti))
|
||||
db.session.commit()
|
||||
return jsonify({"msg": "Successfully logged out"}), 200
|
||||
|
||||
|
||||
# Endpoint for revoking the current users refresh token
|
||||
@auth_api_bp.route('/logout2', methods=['GET', 'DELETE'])
|
||||
@jwt_refresh_token_required
|
||||
def logout2():
|
||||
jti = get_raw_jwt()['jti']
|
||||
db.session.add(BlacklistToken(token=jti))
|
||||
db.session.commit()
|
||||
return jsonify({"msg": "Successfully logged out"}), 200
|
||||
|
||||
|
||||
def check_and_create_groups(groups: Iterable[str]):
|
||||
user_groups = []
|
||||
for g in groups:
|
||||
group = Group.get_by_name(g)
|
||||
if group is None:
|
||||
group = Group(name=g)
|
||||
db.session.add(group)
|
||||
user_groups.append(group)
|
||||
|
||||
db.session.commit()
|
||||
return user_groups
|
||||
|
||||
|
||||
def create_or_retrieve_user_from_userinfo(userinfo):
|
||||
try:
|
||||
email = userinfo["email"]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
user_groups = check_and_create_groups(groups=userinfo.get("memberOf", []))
|
||||
user = User.get_by_identifier(email)
|
||||
|
||||
if user is not None:
|
||||
app.logger.info("user found -> update user")
|
||||
pprint(user.to_dict())
|
||||
user.first_name = userinfo.get("given_name", "")
|
||||
user.last_name = userinfo.get("family_name", "")
|
||||
for g in user_groups:
|
||||
user.groups.append(g)
|
||||
db.session.commit()
|
||||
return user
|
||||
|
||||
user = User(email=email, first_name=userinfo.get("given_name", ""),
|
||||
last_name=userinfo.get("family_name", ""), external_user=True,
|
||||
groups=user_groups)
|
||||
|
||||
app.logger.info("creating new user")
|
||||
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
return user
|
||||
|
||||
|
||||
@auth_api_bp.route('/oidc', methods=['GET'])
|
||||
@auth_api_bp.route('/oidc/<redirect_url>', methods=['GET'])
|
||||
@oidc_auth.oidc_auth()
|
||||
def oidc(redirect_url=None):
|
||||
user = create_or_retrieve_user_from_userinfo(flask.session['userinfo'])
|
||||
if user is None:
|
||||
return "Could not authenticate: could not find or create user.", 401
|
||||
if current_app.config.get("AUTH_RETURN_EXTERNAL_JWT", False):
|
||||
token = jwt.encode(flask.session['id_token'], current_app.config['SECRET_KEY'])
|
||||
else:
|
||||
token = json.dumps({
|
||||
'access_token': create_access_token(identity=user, fresh=True),
|
||||
'refresh_token': create_refresh_token(identity=user)
|
||||
})
|
||||
if redirect_url is None:
|
||||
redirect_url = request.headers.get("Referer")
|
||||
if redirect_url is None:
|
||||
redirect_url = request.args.get('redirect_url')
|
||||
if redirect_url is None:
|
||||
redirect_url = "/"
|
||||
app.logger.info("Token: {}".format(token))
|
||||
response = make_response(redirect(redirect_url))
|
||||
response.set_cookie('tokens', base64.b64encode(token.encode('utf-8')))
|
||||
return response
|
||||
|
||||
|
||||
@auth_api_bp.route('/refresh', methods=['GET'])
|
||||
@jwt_refresh_token_required
|
||||
def refresh():
|
||||
"""Refresh token endpoint. This will generate a new access token from
|
||||
the refresh token, but will mark that access token as non-fresh,
|
||||
as we do not actually verify a password in this endpoint."""
|
||||
jwt_identity = get_jwt_identity()
|
||||
user = User.get_by_identifier(jwt_identity)
|
||||
app.logger.info("Refreshing token for " + str(user))
|
||||
new_token = create_access_token(identity=user, fresh=False)
|
||||
ret = {'access_token': new_token}
|
||||
return jsonify(ret), 200
|
||||
|
||||
42
backend/api/control_api.py
Normal file
42
backend/api/control_api.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# Copyright (c) 2019. Tobias Kurze
|
||||
"""
|
||||
This module provides functions related to authentication through the API.
|
||||
For example: listing of available auth providers or registration of users.
|
||||
|
||||
Login through API does not start a new session, but instead returns JWT.
|
||||
"""
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
from flask_jwt_extended import jwt_required, get_current_user, get_jwt_claims
|
||||
from flask_restplus import fields, Resource
|
||||
|
||||
from backend import db
|
||||
from backend.api import api_control, get_jwt_identity
|
||||
|
||||
control_command_response_model = api_control.model('Control Command Response', {
|
||||
'time': fields.DateTime(required=False, description='Creation date of the recorder'),
|
||||
'state': fields.String(min_length=3, required=True, description='The recorder\'s name'),
|
||||
'output': fields.String(required=False, description='The recorder\'s description'),
|
||||
'error': fields.String(required=False, description='The recorder\'s description'),
|
||||
})
|
||||
|
||||
|
||||
@api_control.route('')
|
||||
class ControlCommand(Resource):
|
||||
control_command_parser = api_control.parser()
|
||||
control_command_parser.add_argument('recorder_id', type=int, default=1, required=True)
|
||||
control_command_parser.add_argument('command_id', type=int, default=1, required=True)
|
||||
control_command_parser.add_argument('parameters', default=json.dumps({'p1': 'v1'}), type=dict, required=False,
|
||||
location='json')
|
||||
|
||||
@jwt_required
|
||||
@api_control.doc('run_command')
|
||||
@api_control.expect(control_command_parser)
|
||||
@api_control.marshal_with(control_command_response_model, skip_none=False, code=201)
|
||||
def post(self):
|
||||
print(get_current_user())
|
||||
print(get_jwt_identity())
|
||||
current_user = {'user': get_current_user(), 'claims': get_jwt_claims()}
|
||||
args = self.control_command_parser.parse_args()
|
||||
return {'time': datetime.utcnow(), 'output': args, 'state': current_user}
|
||||
134
backend/api/example_api.py
Normal file
134
backend/api/example_api.py
Normal file
@@ -0,0 +1,134 @@
|
||||
|
||||
import datetime
|
||||
import ipaddress
|
||||
import json
|
||||
import logging
|
||||
from random import *
|
||||
from flask import jsonify, Blueprint, request
|
||||
from flask_restplus import Resource, reqparse
|
||||
|
||||
from backend import basic_auth, multi_auth, db, jwt_auth
|
||||
from backend.api import api_v1, api_bp
|
||||
|
||||
|
||||
@api_bp.route('/random')
|
||||
def random_number():
|
||||
"""
|
||||
:return: a random number
|
||||
"""
|
||||
response = {
|
||||
'randomNumber': randint(1, 100)
|
||||
}
|
||||
return jsonify(response)
|
||||
|
||||
|
||||
@api_bp.route('/test_jwt')
|
||||
@jwt_auth.login_required
|
||||
def random_number_jwt():
|
||||
"""
|
||||
:return: a random number
|
||||
"""
|
||||
response = {
|
||||
'randomNumber': randint(1, 100)
|
||||
}
|
||||
return jsonify(response)
|
||||
|
||||
|
||||
class HelloWorld(Resource):
|
||||
"""
|
||||
This is a test class.
|
||||
"""
|
||||
def get(self):
|
||||
"""
|
||||
just a test!
|
||||
:return: Hello: World
|
||||
"""
|
||||
print(str(self))
|
||||
return {'hello': 'world'}
|
||||
|
||||
|
||||
api_v1.add_resource(HelloWorld, '/')
|
||||
|
||||
|
||||
class SensorData_Handler(Resource):
|
||||
parser = reqparse.RequestParser()
|
||||
parser.add_argument('values', type=str, required=True, help="sensor data values are required (as JSON list)")
|
||||
|
||||
@basic_auth.login_required
|
||||
def get(self, mac):
|
||||
sensor = Sensor.get_by_mac_user(mac, g.user)
|
||||
if not sensor:
|
||||
return "sensor not found", 404
|
||||
return jsonify(sensor.get_sensor_data())
|
||||
# return {'task': 'id: ' + mac}
|
||||
|
||||
@multi_auth.login_required
|
||||
def post(self, mac):
|
||||
sensor = Sensor.get_by_mac(mac)
|
||||
if not sensor:
|
||||
return "sensor not found", 404
|
||||
|
||||
print("JSON")
|
||||
print(request.json)
|
||||
print(request.json['values'])
|
||||
args = SensorData_Handler.parser.parse_args()
|
||||
print("values...")
|
||||
print(args['values'])
|
||||
values = json.loads(args['values'])
|
||||
app.logger.info("vals: " + str(values) + " (len: " + str(len(values)) + ")")
|
||||
|
||||
rough_geo_location = None
|
||||
try:
|
||||
rough_geo_location_info = None
|
||||
ip = ipaddress.ip_address(request.remote_addr)
|
||||
if request.remote_addr == "127.0.0.1":
|
||||
ip = ipaddress.ip_address("89.245.37.108")
|
||||
if isinstance(ip, ipaddress.IPv4Address):
|
||||
rough_geo_location_info = geoip4.record_by_addr(str(ip))
|
||||
elif isinstance(ip, ipaddress.IPv6Address):
|
||||
rough_geo_location_info = geoip6.record_by_addr(str(ip))
|
||||
|
||||
if rough_geo_location_info is not None:
|
||||
rough_geo_location = json.dumps({key: rough_geo_location_info[key] for key in ['country_code',
|
||||
'country_name',
|
||||
'postal_code',
|
||||
'city',
|
||||
'time_zone',
|
||||
'latitude',
|
||||
'longitude']
|
||||
})
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
for values_at_time in values:
|
||||
wasss_app.logger.info("values_at_time: " + str(values_at_time) + " (len: " + str(len(values_at_time)) + ")")
|
||||
sensor_data = SensorData(sensor=sensor, rough_geo_location=rough_geo_location)
|
||||
val_cycle = cycle(values_at_time)
|
||||
for sensor_data_header in sensor.get_sensor_data_headers():
|
||||
value = next(val_cycle)
|
||||
if sensor_data_header == SensorData.HEADER_TIMESTAMP:
|
||||
sensor_data.timestamp = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S%z")
|
||||
wasss_app.logger.info(sensor_data.timestamp)
|
||||
elif sensor_data_header == SensorData.HEADER_VOLTAGE:
|
||||
sensor_data.voltage = value
|
||||
elif sensor_data_header == SensorData.HEADER_TEMPERATURE:
|
||||
sensor_data.temp = value
|
||||
elif sensor_data_header == SensorData.HEADER_HUMIDITY:
|
||||
sensor_data.humidity = value
|
||||
elif sensor_data_header == SensorData.HEADER_PRESSURE:
|
||||
sensor_data.pressure = value
|
||||
elif sensor_data_header == SensorData.HEADER_BRIGHTNESS:
|
||||
sensor_data.brightness = value
|
||||
elif sensor_data_header == SensorData.HEADER_SPEED:
|
||||
sensor_data.speed = value
|
||||
elif sensor_data_header == SensorData.HEADER_MOTION:
|
||||
sensor_data.motion = value
|
||||
else:
|
||||
gen_sen_data = GenericSensorData(sensor=sensor, name=sensor_data_header, value=value)
|
||||
db.session.add(sensor_data)
|
||||
|
||||
db.session.commit()
|
||||
return jsonify("ok")
|
||||
|
||||
|
||||
api_v1.add_resource(SensorData_Handler, '/sensor/<string:mac>/data')
|
||||
87
backend/api/group_api.py
Normal file
87
backend/api/group_api.py
Normal file
@@ -0,0 +1,87 @@
|
||||
# Copyright (c) 2019. Tobias Kurze
|
||||
"""
|
||||
This module provides functions related to authentication through the API.
|
||||
For example: listing of available auth providers or registration of users.
|
||||
|
||||
Login through API does not start a new session, but instead returns JWT.
|
||||
"""
|
||||
from flask_jwt_extended import jwt_required
|
||||
from flask_restplus import fields, Resource
|
||||
|
||||
from backend import db
|
||||
from backend.api import api_group
|
||||
from backend.models.user_model import Group
|
||||
|
||||
group_model = api_group.model('Group', {
|
||||
'id': fields.String(required=False, description='The group\'s identifier'),
|
||||
'name': fields.String(required=True, description='The group\'s name'),
|
||||
'description': fields.String(required=False, description='The group\'s description'),
|
||||
'users': fields.List(fields.Nested(api_group.model('group_member',
|
||||
{'id': fields.Integer(), 'nickname': fields.String(),
|
||||
'first_name': fields.String(), 'last_name': fields.String(),
|
||||
'email': fields.String(), 'registered_on': fields.DateTime(),
|
||||
'last_seen': fields.DateTime()})),
|
||||
required=False, description='Group members.')
|
||||
})
|
||||
|
||||
|
||||
@api_group.route('/<int:id>')
|
||||
@api_group.response(404, 'Group not found')
|
||||
@api_group.param('id', 'The group identifier')
|
||||
class GroupResource(Resource):
|
||||
@jwt_required
|
||||
@api_group.doc('get_group')
|
||||
@api_group.marshal_with(group_model)
|
||||
def get(self, id):
|
||||
"""Fetch a user given its identifier"""
|
||||
group = Group.get_by_id(id)
|
||||
if group is not None:
|
||||
return group
|
||||
api_group.abort(404)
|
||||
|
||||
@jwt_required
|
||||
@api_group.doc('delete_todo')
|
||||
@api_group.response(204, 'Todo deleted')
|
||||
def delete(self, id):
|
||||
'''Delete a task given its identifier'''
|
||||
group = Group.get_by_id(id)
|
||||
if group is not None:
|
||||
group.delete()
|
||||
return '', 204
|
||||
api_group.abort(404)
|
||||
|
||||
@jwt_required
|
||||
@api_group.doc('update_group')
|
||||
@api_group.expect(group_model)
|
||||
@api_group.marshal_with(group_model)
|
||||
def put(self, id):
|
||||
'''Update a task given its identifier'''
|
||||
group = Group.get_by_id(id)
|
||||
if group is not None:
|
||||
group.name = api_group["name"]
|
||||
db.session.commit()
|
||||
return group
|
||||
api_group.abort(404)
|
||||
|
||||
|
||||
@api_group.route('')
|
||||
class GroupList(Resource):
|
||||
@jwt_required
|
||||
@api_group.doc('groups')
|
||||
@api_group.marshal_list_with(group_model)
|
||||
def get(self):
|
||||
"""
|
||||
List all groups
|
||||
:return: groups
|
||||
"""
|
||||
return Group.get_all()
|
||||
|
||||
@jwt_required
|
||||
@api_group.doc('create_group')
|
||||
@api_group.expect(group_model)
|
||||
@api_group.marshal_with(group_model, code=201)
|
||||
def post(self):
|
||||
group = Group(**api_group.payload)
|
||||
db.session.add(group)
|
||||
db.session.commit()
|
||||
return group
|
||||
275
backend/api/recorder_api.py
Normal file
275
backend/api/recorder_api.py
Normal file
@@ -0,0 +1,275 @@
|
||||
# Copyright (c) 2019. Tobias Kurze
|
||||
"""
|
||||
This module provides functions related to authentication through the API.
|
||||
For example: listing of available auth providers or registration of users.
|
||||
|
||||
Login through API does not start a new session, but instead returns JWT.
|
||||
"""
|
||||
from datetime import datetime
|
||||
from pprint import pprint
|
||||
|
||||
from flask_jwt_extended import jwt_required
|
||||
from flask_restplus import fields, Resource, inputs
|
||||
|
||||
from backend import db, app
|
||||
from backend.api import api_recorder
|
||||
from backend.models.recorder_model import Recorder, RecorderModel, RecorderCommand
|
||||
from backend.models.room_model import Room
|
||||
import backend.recorder_adapters as r_a
|
||||
|
||||
recorder_model = api_recorder.model('Recorder', {
|
||||
'id': fields.String(required=False, description='The recorder\'s identifier'),
|
||||
'created_at': fields.DateTime(required=False, description='Creation date of the recorder'),
|
||||
'last_time_modified': fields.DateTime(required=False, description='Creation date of the recorder'),
|
||||
'name': fields.String(min_length=3, required=True, description='The recorder\'s name'),
|
||||
'description': fields.String(required=False, description='The recorder\'s description'),
|
||||
'locked': fields.Boolean(required=False, description='Indicates whether the recorder settings can be altered'),
|
||||
'lock_message': fields.String(required=False, description='Optional: message explaining lock state'),
|
||||
'offline': fields.Boolean(required=False,
|
||||
description='Should be set when recorder is disconnected for maintenance, etc.'),
|
||||
'ip': fields.String(required=False, description='The recorder\'s IP address'),
|
||||
'network_name': fields.String(required=False, description='The recorder\'s network name'),
|
||||
'ssh_port': fields.Integer(required=True, default=22, description='The recorder\'s SSH port number'),
|
||||
'telnet_port': fields.Integer(required=True, default=23, description='The recorder\'s telnet port number'),
|
||||
# 'use_telnet_instead_ssh': fields.Boolean(required=False, default=False,
|
||||
# description='If this is set, telnet will be used instead of ssh. '
|
||||
# 'This might require specific commands.'),
|
||||
'recorder_model': fields.Nested(api_recorder.model('recorder_model',
|
||||
{'id': fields.Integer(),
|
||||
'name': fields.String(attribute="model_name", )}),
|
||||
required=False,
|
||||
allow_null=True,
|
||||
skip_none=False,
|
||||
description='Model of the recorder.'),
|
||||
'room': fields.Nested(api_recorder.model('recorder_room',
|
||||
{'id': fields.Integer(), 'name': fields.String(),
|
||||
'number': fields.String(), 'alternate_name': fields.String()}),
|
||||
r0equired=False,
|
||||
allow_null=True,
|
||||
skip_none=False,
|
||||
description='Room in which the recorder is located.'),
|
||||
'virtual_commands': fields.List(fields.Nested(api_recorder.model('recorder_virtual_commands',
|
||||
{'id': fields.Integer(),
|
||||
'name': fields.String()})))
|
||||
})
|
||||
|
||||
recorder_command_model = api_recorder.model('Recorder Command', {
|
||||
'id': fields.String(required=False, description='The recorder command\'s identifier'),
|
||||
'name': fields.String(required=True, description='The recorder command\'s name'),
|
||||
'alternative_name': fields.String(required=False, description='The recorder command\'s alternative name'),
|
||||
'disabled': fields.Boolean(required=False, description='Indicates if the recorder command is disabled'),
|
||||
'created_at': fields.DateTime(required=False, description='Creation date of the recorder'),
|
||||
'last_time_modified': fields.DateTime(required=False),
|
||||
'description': fields.String(required=False, description='The recorder command\'s description'),
|
||||
'parameters': fields.Raw(required=True, description='The recorder parameters'),
|
||||
'recorder_model': fields.Nested(api_recorder.model('recorder_command_models',
|
||||
{'id': fields.Integer(),
|
||||
'name': fields.String(attribute="model_name", )})),
|
||||
})
|
||||
|
||||
recorder_model_model = api_recorder.model('Recorder Model', {
|
||||
'id': fields.String(required=False, description='The recorder model\'s identifier'),
|
||||
'name': fields.String(attribute="model_name", required=True, description='The recorder model\'s name'),
|
||||
'created_at': fields.DateTime(required=False, description='Creation date of the recorder'),
|
||||
'last_time_modified': fields.DateTime(required=False),
|
||||
'notes': fields.String(required=False, description='The recorder model\'s notes'),
|
||||
'requires_username': fields.Boolean(),
|
||||
'requires_password': fields.Boolean(),
|
||||
|
||||
'recorders': fields.List(fields.Nested(api_recorder.model('recorder_model',
|
||||
{'id': fields.Integer(),
|
||||
'name': fields.String(attribute="model_name", ),
|
||||
'network_name': fields.String(),
|
||||
'ip': fields.String()})), required=False,
|
||||
description='Model of the recorder.'),
|
||||
'commands': fields.List(fields.Nested(recorder_command_model), attribute="recorder_commands")
|
||||
})
|
||||
|
||||
|
||||
# ==
|
||||
|
||||
@api_recorder.route('/<int:id>')
|
||||
@api_recorder.response(404, 'Recorder not found')
|
||||
@api_recorder.param('id', 'The recorder identifier')
|
||||
class RecorderResource(Resource):
|
||||
@jwt_required
|
||||
@api_recorder.doc('get_recorder')
|
||||
@api_recorder.marshal_with(recorder_model, skip_none=False)
|
||||
def get(self, id):
|
||||
"""Fetch a recorder given its identifier"""
|
||||
recorder = Recorder.query.get(id)
|
||||
if recorder is not None:
|
||||
return recorder
|
||||
api_recorder.abort(404)
|
||||
|
||||
@jwt_required
|
||||
@api_recorder.doc('delete_todo')
|
||||
@api_recorder.response(204, 'Todo deleted')
|
||||
def delete(self, id):
|
||||
"""Delete a recorder given its identifier"""
|
||||
recorder = Recorder.query.get(id)
|
||||
if recorder is not None:
|
||||
db.session.delete(recorder)
|
||||
db.session.commit()
|
||||
return '', 204
|
||||
api_recorder.abort(404)
|
||||
|
||||
recorder_update_parser = api_recorder.parser()
|
||||
recorder_update_parser.add_argument('name', type=str, required=False, nullable=False, store_missing=False)
|
||||
recorder_update_parser.add_argument('network_name', type=inputs.regex(inputs.netloc_regex), required=False, store_missing=False)
|
||||
recorder_update_parser.add_argument('ip', type=inputs.ipv4, required=False, store_missing=False)
|
||||
recorder_update_parser.add_argument('ip6', type=inputs.ipv6, required=False, store_missing=False)
|
||||
recorder_update_parser.add_argument('ssh_port', type=inputs.int_range(0,65535), required=False, default=22, store_missing=False)
|
||||
recorder_update_parser.add_argument('telnet_port', type=inputs.int_range(0,65535), required=False, default=23, store_missing=False)
|
||||
recorder_update_parser.add_argument('room_id', type=int, required=False, store_missing=False)
|
||||
recorder_update_parser.add_argument('offline', type=inputs.boolean, required=False, default=False, store_missing=False)
|
||||
recorder_update_parser.add_argument('locked', type=inputs.boolean, required=False, default=False, store_missing=False)
|
||||
recorder_update_parser.add_argument('lock_message', type=str, required=False, nullable=True, default=None,
|
||||
store_missing=False)
|
||||
recorder_update_parser.add_argument('model_id', type=int, required=False, store_missing=False)
|
||||
recorder_update_parser.add_argument('description', type=str, required=False, nullable=True, default=None,
|
||||
store_missing=False)
|
||||
recorder_update_parser.add_argument('virtual_command_ids', action='split', nullable=True, default=[],
|
||||
required=False, store_missing=False)
|
||||
|
||||
@jwt_required
|
||||
@api_recorder.doc('update_recorder')
|
||||
@api_recorder.expect(recorder_model)
|
||||
def put(self, id):
|
||||
"""Update a recorder given its identifier"""
|
||||
args = self.recorder_update_parser.parse_args(strict=True)
|
||||
args['last_time_modified'] = datetime.utcnow()
|
||||
pprint(args)
|
||||
|
||||
num_rows_matched = Recorder.query.filter_by(id=id).update(args)
|
||||
print(num_rows_matched)
|
||||
|
||||
if num_rows_matched < 1:
|
||||
api_recorder.abort(404)
|
||||
db.session.commit()
|
||||
return "ok"
|
||||
|
||||
|
||||
@api_recorder.route('')
|
||||
class RecorderList(Resource):
|
||||
@jwt_required
|
||||
@api_recorder.doc('recorders')
|
||||
@api_recorder.marshal_list_with(recorder_model, skip_none=False)
|
||||
def get(self):
|
||||
"""
|
||||
List all recorders
|
||||
:return: recorders
|
||||
"""
|
||||
return Recorder.get_all()
|
||||
|
||||
@jwt_required
|
||||
@api_recorder.doc('create_recorder')
|
||||
@api_recorder.expect(recorder_model)
|
||||
@api_recorder.marshal_with(recorder_model, skip_none=False, code=201)
|
||||
def post(self):
|
||||
if "room_id" in api_recorder.payload:
|
||||
if api_recorder.payload["room_id"] is None:
|
||||
api_recorder.payload["room"] = None
|
||||
else:
|
||||
room = Room.query.get(api_recorder.payload["room_id"])
|
||||
if room is not None:
|
||||
api_recorder.payload["room"] = room
|
||||
else:
|
||||
return "specified room (id: {}) does not exist!".format(api_recorder.payload["room_id"]), 404
|
||||
if "recorder_model_id" in api_recorder.payload:
|
||||
if api_recorder.payload["recorder_model_id"] is None:
|
||||
api_recorder.payload["recorder_model"] = None
|
||||
else:
|
||||
rec_model = RecorderModel.query.get(api_recorder.payload["recorder_model_id"])
|
||||
if rec_model is not None:
|
||||
api_recorder.payload["recorder_model"] = rec_model
|
||||
else:
|
||||
return "specified recorder model (id: {}) does not exist!".format(
|
||||
api_recorder.payload["recorder_model_id"]), 404
|
||||
recorder = Recorder(**api_recorder.payload)
|
||||
db.session.add(recorder)
|
||||
db.session.commit()
|
||||
return recorder
|
||||
|
||||
|
||||
@api_recorder.route('/model/<int:id>')
|
||||
@api_recorder.response(404, 'Recorder Model not found')
|
||||
@api_recorder.param('id', 'The recorder model identifier')
|
||||
class RecorderModelResource(Resource):
|
||||
@jwt_required
|
||||
@api_recorder.doc('get_recorder_model')
|
||||
@api_recorder.marshal_with(recorder_model_model)
|
||||
def get(self, id):
|
||||
"""Fetch a recorder model given its identifier"""
|
||||
recorder_model = RecorderModel.query.get(id)
|
||||
if recorder_model is not None:
|
||||
return recorder_model
|
||||
api_recorder.abort(404)
|
||||
|
||||
recorder_model_parser = api_recorder.parser()
|
||||
recorder_model_parser.add_argument('notes', type=str, required=True)
|
||||
|
||||
@jwt_required
|
||||
@api_recorder.doc('update_recorder_model')
|
||||
@api_recorder.expect(recorder_model_parser)
|
||||
@api_recorder.marshal_with(recorder_model_model)
|
||||
def put(self, id):
|
||||
"""Update a recorder_model given its identifier"""
|
||||
num_rows_matched = RecorderModel.query.filter_by(id=id).update(api_recorder.payload)
|
||||
if num_rows_matched < 1:
|
||||
api_recorder.abort(404)
|
||||
db.session.commit()
|
||||
return "ok"
|
||||
|
||||
|
||||
@api_recorder.route('/model')
|
||||
class RecorderModelList(Resource):
|
||||
@jwt_required
|
||||
@api_recorder.doc('recorders')
|
||||
@api_recorder.marshal_list_with(recorder_model_model)
|
||||
def get(self):
|
||||
return RecorderModel.get_all()
|
||||
|
||||
|
||||
@api_recorder.route('/command/<int:id>')
|
||||
@api_recorder.response(404, 'Recorder Command not found')
|
||||
@api_recorder.param('id', 'The recorder command identifier')
|
||||
class RecorderCommandResource(Resource):
|
||||
@jwt_required
|
||||
@api_recorder.doc('get_recorder_command')
|
||||
@api_recorder.marshal_with(recorder_command_model)
|
||||
def get(self, id):
|
||||
"""Fetch a recorder command given its identifier"""
|
||||
recorder_command = RecorderCommand.query.get(id)
|
||||
if recorder_command is not None:
|
||||
return recorder_command
|
||||
api_recorder.abort(404)
|
||||
|
||||
recorder_command_model_parser = api_recorder.parser()
|
||||
recorder_command_model_parser.add_argument('description', type=str, required=False)
|
||||
recorder_command_model_parser.add_argument('alternative_name', type=str, required=False)
|
||||
|
||||
@jwt_required
|
||||
@api_recorder.doc('update_recorder_command')
|
||||
@api_recorder.expect(recorder_command_model_parser)
|
||||
@api_recorder.marshal_with(recorder_command_model)
|
||||
def put(self, id):
|
||||
"""Update a recorder command given its identifier"""
|
||||
num_rows_matched = RecorderCommand.query.filter_by(id=id).update(api_recorder.payload)
|
||||
if num_rows_matched < 1:
|
||||
api_recorder.abort(404)
|
||||
db.session.commit()
|
||||
return "ok"
|
||||
|
||||
|
||||
@api_recorder.route('/command')
|
||||
class RecorderCommandList(Resource):
|
||||
@jwt_required
|
||||
@api_recorder.doc('recorder_commands')
|
||||
@api_recorder.marshal_list_with(recorder_command_model)
|
||||
def get(self):
|
||||
"""
|
||||
List all recorders commands
|
||||
:return: recorder commands
|
||||
"""
|
||||
return RecorderCommand.get_all()
|
||||
122
backend/api/room_api.py
Normal file
122
backend/api/room_api.py
Normal file
@@ -0,0 +1,122 @@
|
||||
# Copyright (c) 2019. Tobias Kurze
|
||||
"""
|
||||
This module provides functions related to authentication through the API.
|
||||
For example: listing of available auth providers or registration of users.
|
||||
|
||||
Login through API does not start a new session, but instead returns JWT.
|
||||
"""
|
||||
from flask_jwt_extended import jwt_required
|
||||
from flask_restplus import fields, Resource
|
||||
from sqlalchemy import exc
|
||||
|
||||
from backend import db, app
|
||||
from backend.api import api_room
|
||||
from backend.models.room_model import Room
|
||||
from backend.models.recorder_model import Recorder
|
||||
|
||||
room_model = api_room.model('Room', {
|
||||
'id': fields.String(required=False, description='The room\'s identifier'),
|
||||
'created_at': fields.DateTime(required=False, description='Creation date of the room info'),
|
||||
'name': fields.String(required=True, description='The room\'s name'),
|
||||
'alternate_name': fields.String(required=False, description='The room\'s alternate name'),
|
||||
'comment': fields.String(required=False, description='The room\'s comment'),
|
||||
'number': fields.String(required=True, description='The room\'s number'),
|
||||
'building_name': fields.String(required=False, description='The building\'s name'),
|
||||
'building_number': fields.String(required=False, description='The building\'s number'),
|
||||
'recorder': fields.Nested(api_room.model('room_recorder',
|
||||
{'id': fields.Integer(), 'name': fields.String(),
|
||||
'ip': fields.String(), 'network_name': fields.String()}),
|
||||
allow_null=True,
|
||||
skip_none=False,
|
||||
required=False,
|
||||
description='Room recorder.'),
|
||||
|
||||
})
|
||||
|
||||
|
||||
@api_room.route('/<int:id>')
|
||||
@api_room.response(404, 'Room not found')
|
||||
@api_room.param('id', 'The room identifier')
|
||||
class RoomResource(Resource):
|
||||
@jwt_required
|
||||
@api_room.doc('get_room')
|
||||
@api_room.marshal_with(room_model, skip_none=False)
|
||||
def get(self, id):
|
||||
"""Fetch a user given its identifier"""
|
||||
room = Room.query.get(id)
|
||||
if room is not None:
|
||||
return room
|
||||
api_room.abort(404)
|
||||
|
||||
@jwt_required
|
||||
@api_room.doc('delete_todo')
|
||||
@api_room.response(204, 'Todo deleted')
|
||||
def delete(self, id):
|
||||
'''Delete a task given its identifier'''
|
||||
room = Room.query.get(id)
|
||||
if room is not None:
|
||||
db.session.delete(room)
|
||||
db.session.commit()
|
||||
return '', 204
|
||||
api_room.abort(404)
|
||||
|
||||
@jwt_required
|
||||
@api_room.doc('update_room')
|
||||
@api_room.expect(room_model)
|
||||
def put(self, id):
|
||||
app.logger.debug(api_room.payload)
|
||||
'''Update a task given its identifier'''
|
||||
if "recorder_id" in api_room.payload:
|
||||
if api_room.payload["recorder_id"] is None:
|
||||
api_room.payload["recorder"] = None
|
||||
else:
|
||||
recorder = Recorder.query.get(api_room.payload["recorder_id"])
|
||||
if recorder is not None:
|
||||
api_room.payload["recorder"] = recorder
|
||||
else:
|
||||
return "specified recorder (id: {}) does not exist!".format(api_room.payload["recorder_id"]), 404
|
||||
room = Room.query.get(id)
|
||||
if room is not None:
|
||||
room.recorder = api_room.payload["recorder"]
|
||||
else:
|
||||
num_rows_matched = Room.query.filter_by(id=id).update(api_room.payload)
|
||||
db.session.commit()
|
||||
return "ok"
|
||||
api_room.abort(404)
|
||||
|
||||
|
||||
@api_room.route('')
|
||||
class RoomList(Resource):
|
||||
@jwt_required
|
||||
@api_room.doc('rooms')
|
||||
@api_room.marshal_list_with(room_model, skip_none=False)
|
||||
def get(self):
|
||||
"""
|
||||
List all rooms
|
||||
:return: rooms
|
||||
"""
|
||||
return Room.get_all()
|
||||
|
||||
@jwt_required
|
||||
@api_room.doc('create_room')
|
||||
@api_room.expect(room_model)
|
||||
@api_room.marshal_with(room_model, skip_none=False, code=201)
|
||||
def post(self):
|
||||
if "recorder_id" in api_room.payload:
|
||||
if api_room.payload["recorder_id"] is None:
|
||||
api_room.payload["recorder"] = None
|
||||
else:
|
||||
recorder = Recorder.query.get(api_room.payload["recorder_id"])
|
||||
if recorder is not None:
|
||||
api_room.payload["recorder"] = recorder
|
||||
else:
|
||||
return "specified recorder (id: {}) does not exist!".format(api_room.payload["recorder_id"]), 404
|
||||
del api_room.payload["recorder_id"]
|
||||
room = Room(**api_room.payload)
|
||||
db.session.add(room)
|
||||
try:
|
||||
db.session.commit()
|
||||
return room
|
||||
except exc.IntegrityError as e:
|
||||
db.session.rollback()
|
||||
return str(e.detail), 400
|
||||
107
backend/api/user_api.py
Normal file
107
backend/api/user_api.py
Normal file
@@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2019. Tobias Kurze
|
||||
"""
|
||||
This module provides functions related to authentication through the API.
|
||||
For example: listing of available auth providers or registration of users.
|
||||
|
||||
Login through API does not start a new session, but instead returns JWT.
|
||||
"""
|
||||
from datetime import datetime
|
||||
from pprint import pprint
|
||||
|
||||
|
||||
from flask_jwt_extended import get_jwt_identity, jwt_required, current_user
|
||||
from flask_restplus import Resource, fields, inputs
|
||||
|
||||
from backend import db, app, jwt_auth
|
||||
from backend.api import api_user
|
||||
from backend.models.user_model import User, Group
|
||||
|
||||
user_model = api_user.model('User', {
|
||||
'id': fields.String(required=True, description='The user\'s identifier'),
|
||||
'first_name': fields.String(required=True, description='The user\'s first name'),
|
||||
'last_name': fields.String(required=True, description='The user\'s last name'),
|
||||
'email': fields.String(required=True, description='The user\'s email address'),
|
||||
'nickname': fields.String(required=False, description='The user\'s nick name'),
|
||||
'groups': fields.List(
|
||||
fields.Nested(api_user.model('user_group', {'id': fields.Integer(), 'name': fields.String()})),
|
||||
required=False, description='Group memberships.'),
|
||||
})
|
||||
|
||||
user_update_parser = api_user.parser()
|
||||
user_update_parser.add_argument('email', type=inputs.email, required=False, nullable=False, store_missing=False)
|
||||
user_update_parser.add_argument('nickname', type=str, required=False, store_missing=False)
|
||||
user_update_parser.add_argument('first_name', type=str, required=False, store_missing=False)
|
||||
user_update_parser.add_argument('last_name', type=str, required=False, store_missing=False)
|
||||
|
||||
|
||||
@api_user.route('/profile')
|
||||
class Profile(Resource):
|
||||
@jwt_required
|
||||
@api_user.marshal_with(user_model)
|
||||
def get(self):
|
||||
"""Get infos about logged in user."""
|
||||
current_user_id = get_jwt_identity()
|
||||
app.logger.info(current_user_id)
|
||||
return User.get_by_identifier(current_user_id)
|
||||
|
||||
@jwt_required
|
||||
@api_user.expect(user_update_parser)
|
||||
def put(self):
|
||||
args = user_update_parser.parse_args()
|
||||
args['last_time_modified'] = datetime.utcnow()
|
||||
pprint(args)
|
||||
print(current_user)
|
||||
num_rows_matched = User.query.filter_by(id=current_user.id).update(args)
|
||||
print(num_rows_matched)
|
||||
|
||||
if num_rows_matched < 1:
|
||||
api_user.abort("Nothing has been updated!")
|
||||
db.session.commit()
|
||||
return "ok"
|
||||
|
||||
|
||||
@api_user.route('')
|
||||
class UserList(Resource):
|
||||
"""
|
||||
This is a test class.
|
||||
"""
|
||||
|
||||
# @jwt_auth.login_required
|
||||
@jwt_required
|
||||
@api_user.doc('users')
|
||||
@api_user.marshal_list_with(user_model)
|
||||
def get(self):
|
||||
"""
|
||||
just a test!
|
||||
:return: Hello: World
|
||||
"""
|
||||
current_user = get_jwt_identity()
|
||||
app.logger.info(current_user)
|
||||
return User.get_all()
|
||||
|
||||
@jwt_required
|
||||
@api_user.doc('create_group')
|
||||
@api_user.expect(user_model)
|
||||
@api_user.marshal_with(user_model, code=201)
|
||||
def post(self):
|
||||
user = User(**api_user.payload)
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
return user
|
||||
|
||||
|
||||
@api_user.route('/<id>')
|
||||
@api_user.param('id', 'The user identifier')
|
||||
@api_user.response(404, 'User not found')
|
||||
class UserResource(Resource):
|
||||
@jwt_auth.login_required
|
||||
@api_user.doc('get_user')
|
||||
@api_user.marshal_with(user_model)
|
||||
def get(self, id):
|
||||
"""Fetch a user given its identifier"""
|
||||
user = User.get_by_id(id)
|
||||
if user is not None:
|
||||
return user
|
||||
api_user.abort(404)
|
||||
|
||||
# api_user.add_resource(UserResource, '/')
|
||||
134
backend/api/virtual_command_api.py
Normal file
134
backend/api/virtual_command_api.py
Normal file
@@ -0,0 +1,134 @@
|
||||
# Copyright (c) 2019. Tobias Kurze
|
||||
"""
|
||||
This module provides functions related to authentication through the API.
|
||||
For example: listing of available auth providers or registration of users.
|
||||
|
||||
Login through API does not start a new session, but instead returns JWT.
|
||||
"""
|
||||
import inspect
|
||||
import pkgutil
|
||||
from pprint import pprint
|
||||
|
||||
from flask_jwt_extended import jwt_required
|
||||
from flask_restplus import fields, Resource
|
||||
|
||||
from backend import db, app
|
||||
from backend.api import api_virtual_command
|
||||
from backend.models.recorder_model import Recorder, RecorderModel, RecorderCommand
|
||||
from backend.models.room_model import Room
|
||||
import backend.recorder_adapters as r_a
|
||||
|
||||
virtual_command_model = api_virtual_command.model('VirtualCommand', {
|
||||
'id': fields.String(required=False, description='The recorder\'s identifier'),
|
||||
'created_at': fields.DateTime(required=False, description='Creation date of the recorder'),
|
||||
'name': fields.String(min_length=3, required=True, description='The recorder\'s name'),
|
||||
'description': fields.String(required=False, description='The recorder\'s description'),
|
||||
|
||||
'parent_virtual_command': fields.Nested(api_virtual_command.model('VirtualCommandParent',
|
||||
{
|
||||
'id': fields.String(required=False,
|
||||
description='The recorder\'s identifier'),
|
||||
'name': fields.String(min_length=3,
|
||||
required=True,
|
||||
description='The recorder\'s name'),
|
||||
},
|
||||
required=False,
|
||||
allow_null=True,
|
||||
skip_none=False,
|
||||
description='Parent virtual command.')),
|
||||
'room': fields.Nested(api_virtual_command.model('recorder_room',
|
||||
{'id': fields.Integer(), 'name': fields.String(),
|
||||
'number': fields.String(), 'alternate_name': fields.String()}),
|
||||
r0equired=False,
|
||||
allow_null=True,
|
||||
skip_none=False,
|
||||
description='Room in which the recorder is located.')
|
||||
})
|
||||
|
||||
|
||||
# ==
|
||||
|
||||
@api_virtual_command.route('/<int:id>')
|
||||
@api_virtual_command.response(404, 'Recorder not found')
|
||||
@api_virtual_command.param('id', 'The recorder identifier')
|
||||
class VirtualCommandResource(Resource):
|
||||
@jwt_required
|
||||
@api_virtual_command.doc('get_recorder')
|
||||
@api_virtual_command.marshal_with(virtual_command_model, skip_none=False)
|
||||
def get(self, id):
|
||||
"""Fetch a recorder given its identifier"""
|
||||
recorder = Recorder.query.get(id)
|
||||
if recorder is not None:
|
||||
return recorder
|
||||
api_virtual_command.abort(404)
|
||||
|
||||
@jwt_required
|
||||
@api_virtual_command.doc('delete_todo')
|
||||
@api_virtual_command.response(204, 'Todo deleted')
|
||||
def delete(self, id):
|
||||
"""Delete a recorder given its identifier"""
|
||||
recorder = Recorder.query.get(id)
|
||||
if recorder is not None:
|
||||
db.session.delete(recorder)
|
||||
db.session.commit()
|
||||
return '', 204
|
||||
api_virtual_command.abort(404)
|
||||
|
||||
virtual_command_model_parser = api_virtual_command.parser()
|
||||
virtual_command_model_parser.add_argument('notes', type=str, required=True)
|
||||
|
||||
@jwt_required
|
||||
@api_virtual_command.doc('update_recorder')
|
||||
@api_virtual_command.expect(virtual_command_model_parser)
|
||||
def put(self, id):
|
||||
"""Update a recorder given its identifier"""
|
||||
num_rows_matched = Recorder.query.filter_by(id=id).update(api_virtual_command.payload)
|
||||
if num_rows_matched < 1:
|
||||
api_virtual_command.abort(404)
|
||||
db.session.commit()
|
||||
return "ok"
|
||||
|
||||
|
||||
@api_virtual_command.route('')
|
||||
class RecorderList(Resource):
|
||||
@jwt_required
|
||||
@api_virtual_command.doc('recorders')
|
||||
@api_virtual_command.marshal_list_with(virtual_command_model, skip_none=False)
|
||||
def get(self):
|
||||
"""
|
||||
List all recorders
|
||||
:return: recorders
|
||||
"""
|
||||
return Recorder.get_all()
|
||||
|
||||
virtual_command_model_parser = api_virtual_command.parser()
|
||||
virtual_command_model_parser.add_argument('notes', type=str, required=True)
|
||||
|
||||
@jwt_required
|
||||
@api_virtual_command.doc('create_recorder')
|
||||
@api_virtual_command.expect(virtual_command_model_parser)
|
||||
@api_virtual_command.marshal_with(virtual_command_model, skip_none=False, code=201)
|
||||
def post(self):
|
||||
if "room_id" in api_virtual_command.payload:
|
||||
if api_virtual_command.payload["room_id"] is None:
|
||||
api_virtual_command.payload["room"] = None
|
||||
else:
|
||||
room = Room.query.get(api_virtual_command.payload["room_id"])
|
||||
if room is not None:
|
||||
api_virtual_command.payload["room"] = room
|
||||
else:
|
||||
return "specified room (id: {}) does not exist!".format(api_virtual_command.payload["room_id"]), 404
|
||||
if "recorder_model_id" in api_virtual_command.payload:
|
||||
if api_virtual_command.payload["recorder_model_id"] is None:
|
||||
api_virtual_command.payload["recorder_model"] = None
|
||||
else:
|
||||
rec_model = RecorderModel.query.get(api_virtual_command.payload["recorder_model_id"])
|
||||
if rec_model is not None:
|
||||
api_virtual_command.payload["recorder_model"] = rec_model
|
||||
else:
|
||||
return "specified recorder model (id: {}) does not exist!".format(
|
||||
api_virtual_command.payload["recorder_model_id"]), 404
|
||||
recorder = Recorder(**api_virtual_command.payload)
|
||||
db.session.add(recorder)
|
||||
db.session.commit()
|
||||
return recorder
|
||||
Reference in New Issue
Block a user