Hide keyboard shortcuts

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> 

3 

4This file is part of stockstert. 

5 

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. 

10 

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. 

15 

16You should have received a copy of the GNU General Public License 

17along with stockstert. If not, see <http://www.gnu.org/licenses/>. 

18LICENSE""" 

19 

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 

34 

35 

36@app.before_first_request 

37def init(): 

38 if not app.testing: # pragma: no cover 

39 

40 app.secret_key = os.environ["FLASK_SECRET"] 

41 app.config["ENV"] = "develop" 

42 

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" 

51 

52 app.config["SQLALCHEMY_DATABASE_URI"] = uri 

53 app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False 

54 db.init_app(app) 

55 

56 register_blueprints(app) 

57 create_tables(app, db) 

58 

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)) 

68 

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 

78 

79 api_key = request.headers["Authorization"].replace("Basic ", "", 1) 

80 

81 try: 

82 api_key = base64.b64decode( 

83 api_key.encode("utf-8") 

84 ).decode("utf-8") 

85 except (TypeError, Error): 

86 pass 

87 

88 db_api_key = ApiKey.query.get(api_key.split(":", 1)[0]) 

89 

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 

93 

94 elif db_api_key.has_expired(): 

95 db.session.delete(db_api_key) 

96 db.session.commit() 

97 return None 

98 

99 return User.query.get(db_api_key.user_id) 

100 

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) 

109 

110 app.logger.removeHandler(default_handler) 

111 

112 logging.basicConfig( 

113 filename=logging_path, 

114 level=logging.DEBUG, 

115 format="[%(asctime)s] %(levelname)s in %(module)s: %(message)s" 

116 ) 

117 

118 app.logger.error("STARTING FLASK") 

119 app.logger.warning("STARTING FLASK") 

120 app.logger.info("STARTING FLASK") 

121 app.logger.debug("STARTING FLASK")