|
|
@@ -103,32 +103,32 @@ manager = Manager(
|
|
|
reconnect_timeout=app.config['AMI_TIMEOUT'],
|
|
|
)
|
|
|
|
|
|
-class AuthMiddleware:
|
|
|
- '''ASGI process middleware that rejects requests missing
|
|
|
- the correct authentication header'''
|
|
|
-
|
|
|
- def __init__(self, app):
|
|
|
- self.app = app
|
|
|
- async def __call__(self, scope, receive, send):
|
|
|
- if 'headers' not in scope:
|
|
|
- return await self.app(scope, receive, send)
|
|
|
- for header, value in scope['headers']:
|
|
|
- if ((header == bytes(app.config['AUTH_HEADER'].lower(), 'utf-8')) and
|
|
|
- (value == bytes(app.config['AUTH_SECRET'], 'utf-8'))):
|
|
|
- return await self.app(scope, receive, send)
|
|
|
- # Paths "/openapi.json" and "/ui" do not require auth
|
|
|
- if (('path' in scope) and
|
|
|
- ((scope['path'] in NO_AUTH_ROUTES) or
|
|
|
- (scope['path'].startswith('/static/records')))):
|
|
|
- return await self.app(scope, receive, send)
|
|
|
- return await self.error_response(receive, send)
|
|
|
- async def error_response(self, receive, send):
|
|
|
- await send({'type': 'http.response.start',
|
|
|
- 'status': 401,
|
|
|
- 'headers': [(b'content-length', b'21')]})
|
|
|
- await send({'type': 'http.response.body',
|
|
|
- 'body': b'Authorization requred',
|
|
|
- 'more_body': False})
|
|
|
+# class AuthMiddleware:
|
|
|
+ # '''ASGI process middleware that rejects requests missing
|
|
|
+ # the correct authentication header'''
|
|
|
+
|
|
|
+ # def __init__(self, app):
|
|
|
+ # self.app = app
|
|
|
+ # async def __call__(self, scope, receive, send):
|
|
|
+ # if 'headers' not in scope:
|
|
|
+ # return await self.app(scope, receive, send)
|
|
|
+ # for header, value in scope['headers']:
|
|
|
+ # if ((header == bytes(app.config['AUTH_HEADER'].lower(), 'utf-8')) and
|
|
|
+ # (value == bytes(app.config['AUTH_SECRET'], 'utf-8'))):
|
|
|
+ # return await self.app(scope, receive, send)
|
|
|
+ # # Paths "/openapi.json" and "/ui" do not require auth
|
|
|
+ # if (('path' in scope) and
|
|
|
+ # ((scope['path'] in NO_AUTH_ROUTES) or
|
|
|
+ # (scope['path'].startswith('/static/records')))):
|
|
|
+ # return await self.app(scope, receive, send)
|
|
|
+ # return await self.error_response(receive, send)
|
|
|
+ # async def error_response(self, receive, send):
|
|
|
+ # await send({'type': 'http.response.start',
|
|
|
+ # 'status': 401,
|
|
|
+ # 'headers': [(b'content-length', b'21')]})
|
|
|
+ # await send({'type': 'http.response.body',
|
|
|
+ # 'body': b'Authorization requred',
|
|
|
+ # 'more_body': False})
|
|
|
|
|
|
def authRequired(func):
|
|
|
@wraps(func)
|
|
|
@@ -147,7 +147,7 @@ def authRequired(func):
|
|
|
abort(401)
|
|
|
return authWrapper
|
|
|
|
|
|
-app.asgi_app = AuthMiddleware(app.asgi_app)
|
|
|
+# app.asgi_app = AuthMiddleware(app.asgi_app)
|
|
|
db = PintDB(app)
|
|
|
|
|
|
@manager.register_event('FullyBooted')
|
|
|
@@ -287,12 +287,14 @@ async def ui():
|
|
|
js_url=app.config['SWAGGER_JS_URL'],
|
|
|
css_url=app.config['SWAGGER_CSS_URL'])
|
|
|
|
|
|
+@authRequired
|
|
|
@app.route('/ami/action', methods=['POST'])
|
|
|
async def action():
|
|
|
_payload = await request.get_data()
|
|
|
reply = await manager.send_action(json.loads(_payload))
|
|
|
return str(reply)
|
|
|
|
|
|
+@authRequired
|
|
|
@app.route('/ami/getvar/<string:variable>')
|
|
|
async def amiGetVar(variable):
|
|
|
'''AMI GetVar
|
|
|
@@ -309,11 +311,13 @@ async def amiGetVar(variable):
|
|
|
app.logger.warning('GetVar({})->{}'.format(variable, reply.value))
|
|
|
return reply.value
|
|
|
|
|
|
+@authRequired
|
|
|
@app.route('/ami/auths')
|
|
|
async def amiPJSIPShowAuths():
|
|
|
app.logger.warning(pformat(request.headers))
|
|
|
return successReply(app.cache['devices'])
|
|
|
|
|
|
+@authRequired
|
|
|
@app.route('/ami/aors')
|
|
|
async def amiPJSIPShowAors():
|
|
|
aors = {}
|
|
|
@@ -679,6 +683,7 @@ def getUsersStatesCombined():
|
|
|
|
|
|
@app.route('/atxfer/<userA>/<userB>')
|
|
|
class AtXfer(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('userA', 'User initiating the attended transfer', 'path')
|
|
|
@app.param('userB', 'Transfer destination user', 'path')
|
|
|
@app.response(HTTPStatus.OK, 'Json reply')
|
|
|
@@ -701,6 +706,7 @@ class AtXfer(Resource):
|
|
|
|
|
|
@app.route('/bxfer/<userA>/<userB>')
|
|
|
class BXfer(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('userA', 'User initiating the blind transfer', 'path')
|
|
|
@app.param('userB', 'Transfer destination user', 'path')
|
|
|
@app.response(HTTPStatus.OK, 'Json reply')
|
|
|
@@ -723,6 +729,7 @@ class BXfer(Resource):
|
|
|
|
|
|
@app.route('/originate/<user>/<number>')
|
|
|
class Originate(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('user', 'User initiating the call', 'path')
|
|
|
@app.param('number', 'Destination number', 'path')
|
|
|
@app.response(HTTPStatus.OK, 'Json reply')
|
|
|
@@ -748,6 +755,7 @@ class Originate(Resource):
|
|
|
|
|
|
@app.route('/hangup/<user>')
|
|
|
class Hangup(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('user', 'User to hangup', 'path')
|
|
|
@app.response(HTTPStatus.OK, 'Json reply')
|
|
|
@app.response(HTTPStatus.UNAUTHORIZED, 'Authorization required')
|
|
|
@@ -781,6 +789,7 @@ class UsersStates(Resource):
|
|
|
|
|
|
@app.route('/user/<user>/state')
|
|
|
class UserState(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('user', 'User to query for combined state', 'path')
|
|
|
@app.response(HTTPStatus.OK, 'JSON data {"user":user,"state":state}')
|
|
|
@app.response(HTTPStatus.UNAUTHORIZED, 'Authorization required')
|
|
|
@@ -794,6 +803,7 @@ class UserState(Resource):
|
|
|
|
|
|
@app.route('/user/<user>/presence')
|
|
|
class PresenceState(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('user', 'User to query for presence state', 'path')
|
|
|
@app.response(HTTPStatus.OK, 'JSON data {"user":user,"state":state}')
|
|
|
@app.response(HTTPStatus.UNAUTHORIZED, 'Authorization required')
|
|
|
@@ -807,6 +817,7 @@ class PresenceState(Resource):
|
|
|
|
|
|
@app.route('/user/<user>/presence/<state>')
|
|
|
class SetPresenceState(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('user', 'Target user to set the presence state', 'path')
|
|
|
@app.param('state',
|
|
|
'The presence state for user, one of: not_set, unavailable, available, away, xa, chat or dnd',
|
|
|
@@ -832,6 +843,7 @@ class SetPresenceState(Resource):
|
|
|
|
|
|
@app.route('/users/devices')
|
|
|
class UsersDevices(Resource):
|
|
|
+ @authRequired
|
|
|
@app.response(HTTPStatus.OK, 'JSON reply with user:device map or error message')
|
|
|
@app.response(HTTPStatus.UNAUTHORIZED, 'Authorization required')
|
|
|
async def get(self):
|
|
|
@@ -851,6 +863,7 @@ class UsersDevices(Resource):
|
|
|
@app.route('/device/<device>/<user>/on')
|
|
|
@app.route('/user/<user>/<device>/on')
|
|
|
class UserDeviceBind(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('device', 'Device number to bind to', 'path')
|
|
|
@app.param('user', 'User to bind to device', 'path')
|
|
|
@app.response(HTTPStatus.OK, 'JSON reply with fields "success" and "result"')
|
|
|
@@ -888,6 +901,7 @@ class UserDeviceBind(Resource):
|
|
|
|
|
|
@app.route('/device/<device>/off')
|
|
|
class DeviceUnBind(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('device', 'Device number to unbind', 'path')
|
|
|
@app.response(HTTPStatus.OK, 'JSON reply with fields "success" and "result"')
|
|
|
@app.response(HTTPStatus.UNAUTHORIZED, 'Authorization required')
|
|
|
@@ -912,6 +926,7 @@ class DeviceUnBind(Resource):
|
|
|
|
|
|
@app.route('/cdr')
|
|
|
class CDR(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('end', 'End of datetime range. Defaults to now. Allowed formats are: timestamp, ISO 8601 or YYYYMMDDhhmmss', 'query')
|
|
|
@app.param('start', 'Start of datetime range. Defaults to end-24h. Allowed formats are: timestamp, ISO 8601 or YYYYMMDDhhmmss', 'query')
|
|
|
@app.response(HTTPStatus.OK, 'JSON reply')
|
|
|
@@ -927,6 +942,7 @@ class CDR(Resource):
|
|
|
|
|
|
@app.route('/cel')
|
|
|
class CEL(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('end', 'End of datetime range. Defaults to now. Allowed formats are: timestamp, ISO 8601 or YYYYMMDDhhmmss', 'query')
|
|
|
@app.param('start', 'Start of datetime range. Defaults to end-24h. Allowed formats are: timestamp, ISO 8601 or YYYYMMDDhhmmss', 'query')
|
|
|
@app.response(HTTPStatus.OK, 'JSON reply')
|
|
|
@@ -942,6 +958,7 @@ class CEL(Resource):
|
|
|
|
|
|
@app.route('/calls')
|
|
|
class Calls(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('end', 'End of datetime range. Defaults to now. Allowed formats are: timestamp, ISO 8601 and YYYYMMDDhhmmss', 'query')
|
|
|
@app.param('start', 'Start of datetime range. Defaults to end-24h. Allowed formats are: timestamp, ISO 8601 and YYYYMMDDhhmmss', 'query')
|
|
|
@app.response(HTTPStatus.OK, 'JSON reply')
|
|
|
@@ -970,6 +987,7 @@ class Calls(Resource):
|
|
|
|
|
|
@app.route('/user/<user>/calls')
|
|
|
class UserCalls(Resource):
|
|
|
+ @authRequired
|
|
|
@app.param('user', 'User to query for call stats', 'path')
|
|
|
@app.param('end', 'End of datetime range. Defaults to now. Allowed formats are: timestamp, ISO 8601 and YYYYMMDDhhmmss', 'query')
|
|
|
@app.param('start', 'Start of datetime range. Defaults to end-24h. Allowed formats are: timestamp, ISO 8601 and YYYYMMDDhhmmss', 'query')
|