diff --git a/api/Constants.py b/api/Constants.py new file mode 100644 index 0000000000000000000000000000000000000000..4e1b2640d755eae624afe6e1a25d7c92e9279f6d --- /dev/null +++ b/api/Constants.py @@ -0,0 +1 @@ +APP_NAME = 'RoadmapApi' diff --git a/api/Pipfile b/api/Pipfile index d3963dbcbe76a2b37f864d959b7e3cc5b5c40c67..5120d9626aa1a0c81bb2ae12d025b2d61a87c5d2 100644 --- a/api/Pipfile +++ b/api/Pipfile @@ -3,6 +3,11 @@ url = "https://pypi.python.org/simple" verify_ssl = true name = "pypi" +[[source]] +url = "https://pypi.thecodedev.de" +verify_ssl = true +name = "TheCodeLabs" + [requires] python_version = "3.7" @@ -11,6 +16,8 @@ flask = "==1.1.2" flask_jwt_extended = "==3.24.1" gevent = "==1.5.0" psycopg2 = "==2.8.5" +TheCodeLabs-BaseUtils = "==1.0.0" +TheCodeLabs-FlaskUtils = "==1.0.2" [dev-packages] pyyaml = "==5.3.1" diff --git a/api/Pipfile.lock b/api/Pipfile.lock index 64b0959391b68772aba0e93139965543c4096240..3d9c8b6e300c27b277743e95132386160b271f65 100644 --- a/api/Pipfile.lock +++ b/api/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "1aaa3c81cbaa411a612d61507c5ee3b1093c021977a99472b39661b380700170" + "sha256": "8217206c84c7464d990a1d9955f2a7d271997ed4a052584a0f63c3d387d0359f" }, "pipfile-spec": 6, "requires": { @@ -12,6 +12,11 @@ "name": "pypi", "url": "https://pypi.python.org/simple", "verify_ssl": true + }, + { + "name": "TheCodeLabs", + "url": "https://pypi.thecodedev.de", + "verify_ssl": true } ] }, @@ -52,10 +57,10 @@ }, "click": { "hashes": [ - "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc", - "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a" + "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", + "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" ], - "version": "==7.1.1" + "version": "==7.1.2" }, "flask": { "hashes": [ @@ -221,6 +226,20 @@ ], "version": "==1.14.0" }, + "thecodelabs-baseutils": { + "hashes": [ + "sha256:daab1cf2480b3c1352ef94f78774d4c4c8759d91a6c50b113bcb1c73081263cb" + ], + "index": "pypi", + "version": "==1.0.0" + }, + "thecodelabs-flaskutils": { + "hashes": [ + "sha256:98833b87fd1b0b42a7ad6ac9de3b79676623cc21b0fabc940863412e8ee40961" + ], + "index": "pypi", + "version": "==1.0.2" + }, "werkzeug": { "hashes": [ "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43", diff --git a/api/RoadmapAPIServer.py b/api/RoadmapAPIServer.py index f736e5e013cd4753f443a36e654a30f9fc248484..e81fd063ead1f5e310d78697fb7691acf32afd04 100644 --- a/api/RoadmapAPIServer.py +++ b/api/RoadmapAPIServer.py @@ -1,77 +1,62 @@ import datetime -import json +import logging +import os -from flask import Flask, send_from_directory, request +from TheCodeLabs_BaseUtils import DefaultLogger +from TheCodeLabs_FlaskUtils import FlaskBaseApp from flask import jsonify +from flask import send_from_directory, request from flask_jwt_extended import ( JWTManager, create_access_token ) -from gevent.pywsgi import WSGIServer +import Constants from Database import Database from RequestValidator import RequestValidator, ValidationError from UserService import UserService from blueprints import SubTaskAPI, MilestoneAPI, TaskAPI, RoadmapAPI -with open('version.json', 'r') as f: - VERSION = json.load(f) -VERSION = VERSION['version'] +LOGGER = DefaultLogger().create_logger_if_not_exists(Constants.APP_NAME) -with open("settings.json", "r") as f: - SETTINGS = json.load(f) -SERVER_SETTINGS = SETTINGS["server"] -app = Flask(__name__) +class RoadmapApi(FlaskBaseApp): + def __init__(self, appName: str, rootDir: str, logger: logging.Logger, settingsPath: str): + super().__init__(appName, rootDir, logger, settingsPath=settingsPath) + self._database = Database(self._settings["database"]) + self._userService = UserService(self._settings["users"]) -app.config["JWT_SECRET_KEY"] = SERVER_SETTINGS["secret"] -jwt = JWTManager(app) + def _register_blueprints(self, app): + app.config["JWT_SECRET_KEY"] = self._serverSettings["secret"] + jwt = JWTManager(app) -database = Database(SETTINGS["database"]) -userService = UserService(SETTINGS["users"]) + @app.route('/') + def index(): + return send_from_directory("docs", "api.html") + @app.route('/login', methods=['POST']) + def login(): + try: + parameters = RequestValidator.validate(request, ["username", "password"]) + except ValidationError as e: + return e.response, 400 -@app.route('/') -def index(): - return send_from_directory("docs", "api.html") + password = self._userService.get_password_by_username(parameters["username"]) + if password is None: + return jsonify({"success": False, "msg": "Unknown username"}), 401 + if password != parameters["password"]: + return jsonify({"success": False, "msg": "Bad credentials"}), 401 -@app.route('/version', methods=['GET']) -def version(): - return jsonify(VERSION) + expires = datetime.timedelta(hours=1) + access_token = create_access_token(identity=parameters["username"], expires_delta=expires) + return jsonify(access_token=access_token), 200 - -@app.route('/login', methods=['POST']) -def login(): - try: - parameters = RequestValidator.validate(request, ["username", "password"]) - except ValidationError as e: - return e.response, 400 - - password = userService.get_password_by_username(parameters["username"]) - if password is None: - return jsonify({"success": False, "msg": "Unknown username"}), 401 - - if password != parameters["password"]: - return jsonify({"success": False, "msg": "Bad credentials"}), 401 - - expires = datetime.timedelta(hours=1) - access_token = create_access_token(identity=parameters["username"], expires_delta=expires) - return jsonify(access_token=access_token), 200 - - -app.register_blueprint(RoadmapAPI.construct_blueprint(database)) -app.register_blueprint(MilestoneAPI.construct_blueprint(database)) -app.register_blueprint(TaskAPI.construct_blueprint(database)) -app.register_blueprint(SubTaskAPI.construct_blueprint(database)) + app.register_blueprint(RoadmapAPI.construct_blueprint(self._database)) + app.register_blueprint(MilestoneAPI.construct_blueprint(self._database)) + app.register_blueprint(TaskAPI.construct_blueprint(self._database)) + app.register_blueprint(SubTaskAPI.construct_blueprint(self._database)) if __name__ == "__main__": - if SERVER_SETTINGS["useSSL"]: - http_server = WSGIServer((SERVER_SETTINGS["listen"], SERVER_SETTINGS["port"]), app, - keyfile=SERVER_SETTINGS["keyfile"], certfile=SERVER_SETTINGS["certfile"]) - else: - http_server = WSGIServer((SERVER_SETTINGS["listen"], SERVER_SETTINGS["port"]), app) - - print('RoadmapClient {}({}) - Listening on {}:{}...'.format(VERSION['name'], VERSION['code'], - SERVER_SETTINGS['listen'], SERVER_SETTINGS['port'])) - http_server.serve_forever() + roadmapApi = RoadmapApi(Constants.APP_NAME, os.path.dirname(__file__), LOGGER, 'settings.json') + roadmapApi.start_server()