Files
lrc-backend/backend/__init__.py

153 lines
4.3 KiB
Python

# -*- coding: utf-8 -*-
"""
Backend base module
"""
import logging
from logging.config import dictConfig
import coloredlogs as coloredlogs
import jwt
import requests
from flask import Flask, jsonify
from flask_httpauth import HTTPTokenAuth, HTTPBasicAuth, MultiAuth
from flask_jwt_extended import JWTManager, decode_token
from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
from backend.config import Config
__author__ = "Tobias Kurze"
__copyright__ = "Copyright 2019, Tobias Kurze, KIT"
__credits__ = ["Tobias Kurze"]
__license__ = ""
__version__ = "0.9.0"
__maintainer__ = "Tobias Kurze"
__email__ = "it@t-kurze.de"
# __status__ = "Production"
__status__ = "Development"
dictConfig({
'version': 1,
'formatters': {
'default': {
'format': '[%(asctime)s] {%(threadName)s} %(levelname)s in %(module)s, line %(lineno)d: %(message)s',
}
},
'handlers': {
'wsgi': {
'class': 'logging.StreamHandler',
'stream': 'ext://flask.logging.wsgi_errors_stream',
'formatter': 'default'
},
'root_file': {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': Config.ROOT_LOG_FILE,
'when': 'd',
'interval': 1,
'backupCount': 3,
'formatter': 'default',
},
'file': {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': Config.LOG_FILE,
'when': 'd',
'interval': 1,
'backupCount': 5,
'formatter': 'default',
},
'errors_file': {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': Config.ERROR_LOG_FILE,
'when': 'd',
'interval': 1,
'backupCount': 5,
'level': 'ERROR',
'formatter': 'default',
},
},
'loggers': {
'mal': {
'level': Config.LOG_LEVEL,
'handlers': ['wsgi', 'file', 'errors_file']
}
},
'root': {
'level': 'ERROR',
'handlers': ['root_file', 'errors_file']
}
})
main_logger = logging.getLogger("lrc")
coloredlogs.install(level='DEBUG', logger=main_logger)
class LrcException(Exception):
def __init__(self, message: str, html_code: int = None):
super().__init__(message)
self.html_code = html_code
def __repr__(self):
if self.html_code is not None:
return "LRC Exception: \"{}\" (HTML Code: {})".format(', '.join(super().args), self.html_code)
return ', '.join(super().args)
def __str__(self):
return self.__repr__()
app = Flask(__name__)
app.config.from_object('backend.config.Config')
db = SQLAlchemy(app)
login_manager = LoginManager()
login_manager.init_app(app)
# flask_jwt_extended: to be used usually by API
jwt_extended = JWTManager(app)
#
jwt_auth = HTTPTokenAuth('Bearer')
@jwt_auth.verify_token
def verify_token(token):
"""This function (and HTTPTokenAuth('Bearer')) has been defined to be used together with MultiAuth. For API calls
solely using JWT authentication, jwt_required of flask_jwt_extended should be used directly."""
app.logger.info(token)
try:
decoded = decode_token(token)
except jwt.exceptions.DecodeError as e:
app.logger.warn("Could not verify token: {}".format(str(e)))
return False
except jwt.exceptions.ExpiredSignatureError as e:
app.logger.warn("Could not verify token: {}".format(str(e)))
return False
app.logger.info(decoded)
return True
basic_auth = HTTPBasicAuth()
multi_auth = MultiAuth(basic_auth, jwt_auth)
from backend.auth import oidc_auth, auth_bp
try:
oidc_auth.init_app(app)
except requests.exceptions.ConnectionError as err:
app.logger.error("Could not connect to OIDC!!", err)
# oidc_multi_auth = MultiAuth(oidc_auth, jwt_auth) <- can't work as OIDCAuthentication not implementing HTTPAuth
from .serve_frontend import fe_bp
from .api import auth_api_bp, api_v1, api_bp
app.register_blueprint(auth_bp)
app.register_blueprint(auth_api_bp)
app.register_blueprint(api_bp)
app.register_blueprint(fe_bp)
CORS(app)
CORS(api_bp)
# Fix flask-restplus by duck typing error handlers
jwt_extended._set_error_handler_callbacks(api_v1)