Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""LICENSE
2Copyright 2020 Hermann Krumrey <hermann@krumreyh.com>
4This file is part of stockstert.
6stockstert is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
11stockstert is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
16You should have received a copy of the GNU General Public License
17along with stockstert. If not, see <http://www.gnu.org/licenses/>.
18LICENSE"""
20import os
21import base64
22import logging
23from binascii import Error
24from typing import Optional
25from flask import render_template
26from flask.logging import default_handler
27from werkzeug.exceptions import HTTPException
28from stockstert.db.auth.User import User
29from stockstert.db.auth.ApiKey import ApiKey
30from stockstert.db.models import create_tables
31from stockstert.flask import app, db, login_manager
32from stockstert.config import logging_path # , db_user, db_key, db_name
33from stockstert.routes.blueprints import register_blueprints
36@app.before_first_request
37def init():
38 if not app.testing: # pragma: no cover
40 app.secret_key = os.environ["FLASK_SECRET"]
41 app.config["ENV"] = "develop"
43 if app.config["ENV"] == "production":
44 print("Currently disabled")
45 # uri = "mysql://{}:{}@localhost:3306/{}".format(
46 # db_user, db_key, db_name
47 # )
48 exit()
49 else:
50 uri = "sqlite:////tmp/stockstert.db"
52 app.config["SQLALCHEMY_DATABASE_URI"] = uri
53 app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
54 db.init_app(app)
56 register_blueprints(app)
57 create_tables(app, db)
59 # Set up login manager
60 @login_manager.user_loader
61 def load_user(user_id: str) -> Optional[User]:
62 """
63 Loads a user from an ID
64 :param user_id: The ID
65 :return: The User
66 """
67 return User.query.get(int(user_id))
69 @login_manager.request_loader
70 def load_user_from_request(request) -> Optional[User]:
71 """
72 Loads a user pased on a provided API key
73 :param request: The request containing the API key in the headers
74 :return: The user or None if no valid API key was provided
75 """
76 if "Authorization" not in request.headers:
77 return None
79 api_key = request.headers["Authorization"].replace("Basic ", "", 1)
81 try:
82 api_key = base64.b64decode(
83 api_key.encode("utf-8")
84 ).decode("utf-8")
85 except (TypeError, Error):
86 pass
88 db_api_key = ApiKey.query.get(api_key.split(":", 1)[0])
90 # Check for validity of API key
91 if db_api_key is None or not db_api_key.verify_key(api_key):
92 return None
94 elif db_api_key.has_expired():
95 db.session.delete(db_api_key)
96 db.session.commit()
97 return None
99 return User.query.get(db_api_key.user_id)
101 @app.errorhandler(HTTPException)
102 def error_handling(error: HTTPException):
103 """
104 Custom redirect for 401 errors
105 :param error: The error that caused the error handler to be called
106 :return: A redirect to the login page
107 """
108 return render_template("error.html", error=error)
110 app.logger.removeHandler(default_handler)
112 logging.basicConfig(
113 filename=logging_path,
114 level=logging.DEBUG,
115 format="[%(asctime)s] %(levelname)s in %(module)s: %(message)s"
116 )
118 app.logger.error("STARTING FLASK")
119 app.logger.warning("STARTING FLASK")
120 app.logger.info("STARTING FLASK")
121 app.logger.debug("STARTING FLASK")