Merge pull request 'Logging erweitern um IP-Adressen #70-4 (#85)' (#87) from #85 into #70

Reviewed-on: sh-edraft.de/kd_discord_bot#87
Closes #85
This commit is contained in:
Sven Heidemann 2022-10-25 21:24:27 +02:00
commit 801d4bf16b
8 changed files with 64 additions and 21 deletions

View File

@ -13,7 +13,7 @@
}, },
"BotLoggingSettings": { "BotLoggingSettings": {
"Api": { "Api": {
"Path": "logs/", "Path": "logs/$date_now/",
"Filename": "api.log", "Filename": "api.log",
"ConsoleLogLevel": "TRACE", "ConsoleLogLevel": "TRACE",
"FileLogLevel": "TRACE" "FileLogLevel": "TRACE"

View File

@ -8,7 +8,7 @@
"LoggingSettings": { "LoggingSettings": {
"Path": "logs/", "Path": "logs/",
"Filename": "bot.log", "Filename": "bot.log",
"ConsoleLogLevel": "TRACE", "ConsoleLogLevel": "DEBUG",
"FileLogLevel": "TRACE" "FileLogLevel": "TRACE"
}, },
"BotLoggingSettings": { "BotLoggingSettings": {
@ -27,7 +27,7 @@
"Database": { "Database": {
"Path": "logs/", "Path": "logs/",
"Filename": "database.log", "Filename": "database.log",
"ConsoleLogLevel": "TRACE", "ConsoleLogLevel": "DEBUG",
"FileLogLevel": "TRACE" "FileLogLevel": "TRACE"
}, },
"Message": { "Message": {

View File

@ -13,7 +13,7 @@
}, },
"BotLoggingSettings": { "BotLoggingSettings": {
"Api": { "Api": {
"Path": "logs/", "Path": "logs/$date_now/",
"Filename": "api.log", "Filename": "api.log",
"ConsoleLogLevel": "ERROR", "ConsoleLogLevel": "ERROR",
"FileLogLevel": "INFO" "FileLogLevel": "INFO"

View File

@ -13,7 +13,7 @@
}, },
"BotLoggingSettings": { "BotLoggingSettings": {
"Api": { "Api": {
"Path": "logs/", "Path": "logs/$date_now/",
"Filename": "api.log", "Filename": "api.log",
"ConsoleLogLevel": "INFO", "ConsoleLogLevel": "INFO",
"FileLogLevel": "DEBUG" "FileLogLevel": "DEBUG"

View File

@ -1,13 +1,15 @@
import json import re
import sys import sys
import textwrap
import uuid import uuid
from functools import partial from functools import partial
from typing import Union
import eventlet import eventlet
from cpl_core.dependency_injection import ServiceProviderABC from cpl_core.dependency_injection import ServiceProviderABC
from cpl_core.utils import CredentialManager from cpl_core.utils import CredentialManager
from eventlet import wsgi from eventlet import wsgi
from flask import Flask, request, jsonify, Response, make_response from flask import Flask, request, jsonify, Response
from flask_cors import CORS from flask_cors import CORS
from flask_socketio import SocketIO from flask_socketio import SocketIO
from werkzeug.exceptions import NotFound from werkzeug.exceptions import NotFound
@ -40,21 +42,36 @@ class Api(Flask):
self._logger = logger self._logger = logger
self._services = services self._services = services
self._apt_settings = api_settings self._api_settings = api_settings
self._auth_settings = auth_settings self._auth_settings = auth_settings
self._cors = CORS(self, support_credentials=True) self._cors = CORS(self, support_credentials=True)
# register before request # register hooks
self.before_request_funcs.setdefault(None, []).append(self.before_request) self.before_request(self.before_request_hook)
self.after_request(self.after_request_hook)
# register error handler
exc_class, code = self._get_exc_class_and_code(Exception) exc_class, code = self._get_exc_class_and_code(Exception)
self.error_handler_spec[None][code][exc_class] = self.handle_exception self.register_error_handler(exc_class, self.handle_exception)
# websockets # websockets
self._socketio = SocketIO(self, cors_allowed_origins='*', path='/api/socket.io') self._socketio = SocketIO(self, cors_allowed_origins='*', path='/api/socket.io')
self._socketio.on_event('connect', self.on_connect) self._socketio.on_event('connect', self.on_connect)
self._socketio.on_event('disconnect', self.on_disconnect) self._socketio.on_event('disconnect', self.on_disconnect)
self._requests = {}
@staticmethod
def _get_methods_from_registered_route() -> Union[list[str], str]:
methods = ['Unknown']
if request.path in Route.registered_routes and len(Route.registered_routes[request.path]) >= 1 and 'methods' in Route.registered_routes[request.path][1]:
methods = Route.registered_routes[request.path][1]['methods']
if len(methods) == 1:
return methods[0]
return methods
def _register_routes(self): def _register_routes(self):
for path, f in Route.registered_routes.items(): for path, f in Route.registered_routes.items():
route = f[0] route = f[0]
@ -88,20 +105,46 @@ class Api(Flask):
error = ErrorDTO(None, user_message) error = ErrorDTO(None, user_message)
return jsonify(error.to_dict()), 400 return jsonify(error.to_dict()), 400
def before_request(self, *args, **kwargs): def before_request_hook(self):
self._logger.debug(__name__, f'Received GET @{request.url}') request_id = uuid.uuid4()
headers = str(request.headers).replace("\n", "\n\t") self._requests[request] = request_id
self._logger.trace(__name__, f'Headers: \n\t{headers}') method = request.access_control_request_method
self._logger.info(__name__, f'Received {request_id} @ {self._get_methods_from_registered_route() if method is None else method} {request.url} from {request.remote_addr}')
headers = str(request.headers).replace('\n', '\n\t\t')
data = request.get_data()
data = '' if len(data) == 0 else str(data.decode(encoding="utf-8"))
text = textwrap.dedent(f'Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tUser-Agent: {request.user_agent.string}\n\tBody: {data}')
self._logger.trace(__name__, text)
def after_request_hook(self, response: Response):
method = request.access_control_request_method
request_id = f'{self._get_methods_from_registered_route() if method is None else method} {request.url} from {request.remote_addr}'
if request in self._requests:
request_id = self._requests[request]
self._logger.info(__name__, f'Answered {request_id}')
headers = str(request.headers).replace('\n', '\n\t\t')
data = request.get_data()
data = '' if len(data) == 0 else str(data.decode(encoding="utf-8"))
text = textwrap.dedent(f'Request: {request_id}:\n\tHeader:\n\t\t{headers}\n\tResponse: {data}')
self._logger.trace(__name__, text)
return response
def start(self): def start(self):
self._logger.info(__name__, f'Starting API {self._apt_settings.host}:{self._apt_settings.port}') self._logger.info(__name__, f'Starting API {self._api_settings.host}:{self._api_settings.port}')
self._register_routes() self._register_routes()
self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key) self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key)
# from waitress import serve # from waitress import serve
# https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html # https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html
# serve(self, host=self._apt_settings.host, port=self._apt_settings.port, threads=10, connection_limit=1000, channel_timeout=10) # serve(self, host=self._apt_settings.host, port=self._apt_settings.port, threads=10, connection_limit=1000, channel_timeout=10)
wsgi.server( wsgi.server(
eventlet.listen((self._apt_settings.host, self._apt_settings.port)), eventlet.listen((self._api_settings.host, self._api_settings.port)),
self, self,
log_output=False log_output=False
) )

View File

@ -1,19 +1,18 @@
{ {
"Api": { "Api": {
"Port": 5000, "Port": 8044,
"Host": "0.0.0.0", "Host": "0.0.0.0",
"RedirectToHTTPS": false "RedirectToHTTPS": false
}, },
"Authentication": { "Authentication": {
"SecretKey": "RjNiNUxEeisjSnZ6Zz1XIUBnc2EleHNG", "SecretKey": "RjNiNUxEeisjSnZ6Zz1XIUBnc2EleHNG",
"Issuer": "http://localhost:5000", "Issuer": "http://localhost:8084",
"Audience": "http://localhost:4200", "Audience": "http://localhost:4200",
"TokenExpireTime": 1, "TokenExpireTime": 1,
"RefreshTokenExpireTime": 7 "RefreshTokenExpireTime": 7
}, },
"DiscordAuthentication": { "DiscordAuthentication": {
"ClientSecret": "V3FTb3JYVFBiVktEeHZxdWJDWW4xcnBCbXRwdmpwcy0=", "ClientSecret": "V3FTb3JYVFBiVktEeHZxdWJDWW4xcnBCbXRwdmpwcy0=",
"_RedirectURL": "http://localhost:5000/api/auth/discord/register",
"RedirectURL": "http://localhost:4200/auth/register", "RedirectURL": "http://localhost:4200/auth/register",
"Scope": [ "Scope": [
"identify", "identify",

View File

@ -37,7 +37,7 @@ import { SettingsService } from './services/settings/settings.service';
JwtModule.forRoot({ JwtModule.forRoot({
config: { config: {
tokenGetter, tokenGetter,
allowedDomains: ['localhost:5000', 'localhost:5001'], allowedDomains: ['localhost:8044', 'localhost:8041', 'localhost:5000'],
disallowedRoutes: [] disallowedRoutes: []
} }
}), }),

View File

@ -56,6 +56,7 @@ export class SocketService {
this.socket.on("disconnect", () => { this.socket.on("disconnect", () => {
if (this.disconnected) { if (this.disconnected) {
this.spinnerService.showSpinner();
return; return;
} }