# 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_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'), 'name': fields.String(min_length=3, required=True, description='The recorder\'s name'), 'description': fields.String(required=False, description='The recorder\'s description'), '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()}), 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()}), required=False, allow_null=True, skip_none=False, description='Room in which the recorder is located.') }) 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'), 'last_time_modified': fields.DateTime(required=False), 'description': fields.String(required=False, description='The recorder command\'s description'), 'parameters': fields.String(required=True, description='The recorder parameters'), 'recorder_model': fields.Nested(api_recorder.model('recorder_command_models', {'id': fields.Integer(), 'name': fields.String()})), }) 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'), 'last_time_modified': fields.DateTime(required=False), 'notes': fields.String(required=False, description='The recorder model\'s notes'), 'recorders': fields.List(fields.Nested(api_recorder.model('recorder_model', {'id': fields.Integer(), 'name': fields.String(), '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('/') @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) @jwt_required @api_recorder.doc('update_recorder') @api_recorder.expect(recorder_model) def put(self, id): """Update a recorder given its identifier""" num_rows_matched = Recorder.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('') 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/') @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/') @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) @jwt_required @api_recorder.doc('delete_recorder_command') @api_recorder.response(204, 'Recorder_command deleted') def delete(self, id): """Delete a recorder command given its identifier""" recorder_command = RecorderCommand.query.get(id) if recorder_command is not None: db.session.delete(recorder_command) db.session.commit() return '', 204 api_recorder.abort(404) @jwt_required @api_recorder.doc('update_recorder_command') @api_recorder.expect(recorder_command_model) @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() @jwt_required @api_recorder.doc('create_recorder_commands') @api_recorder.expect(recorder_command_model) @api_recorder.marshal_with(recorder_command_model, code=201) def post(self): recorder_command = RecorderCommand(**api_recorder.payload) db.session.add(recorder_command) db.session.commit() return recorder_command