From bef3c6dc9b311f9716255ab39c5a63070b2f0ec6 Mon Sep 17 00:00:00 2001 From: Tobias Kurze Date: Tue, 19 Mar 2019 16:34:05 +0100 Subject: [PATCH] added authentication API --- __init__.py | 11 ++++++----- api/__init__.py | 3 +++ api/auth_api.py | 35 +++++++++++++++++++++++++++++++++++ api/example_api.py | 9 ++++++--- serve_frontend.py | 23 ++++++++++++++++++++++- 5 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 api/auth_api.py diff --git a/__init__.py b/__init__.py index 7afbcc2..7f990b6 100644 --- a/__init__.py +++ b/__init__.py @@ -11,17 +11,18 @@ jwt_auth = HTTPTokenAuth() basic_auth = HTTPBasicAuth() multi_auth = MultiAuth(basic_auth, jwt_auth) -from .serve_frontend import fe_bp -from .api import api_bp - app = Flask(__name__) - app.config.from_object('backend.config.Config') +db = SQLAlchemy(app) + +from .serve_frontend import fe_bp +from .api import auth_api_bp, api_bp from backend.auth import oidc_auth oidc_auth.init_app(app) +app.register_blueprint(auth_api_bp) app.register_blueprint(api_bp) app.register_blueprint(fe_bp) -db = SQLAlchemy(app) + diff --git a/api/__init__.py b/api/__init__.py index 66653b1..7dae563 100644 --- a/api/__init__.py +++ b/api/__init__.py @@ -25,4 +25,7 @@ api_bp = Blueprint('api', __name__, url_prefix='/api') api_v1 = Api(api_bp, prefix="/v1", version='0.1', title='Vue Test API', description='The Vue Test API', doc='/v1/doc/', authorizations=api_authorizations, security='bearerAuth') +auth_api_bp = Blueprint('auth_api', __name__, url_prefix='/api/auth') + from .example_api import * +from .auth_api import * diff --git a/api/auth_api.py b/api/auth_api.py new file mode 100644 index 0000000..9739d2d --- /dev/null +++ b/api/auth_api.py @@ -0,0 +1,35 @@ +# Copyright (c) 2019. Tobias Kurze +import datetime +import jwt +from flask import request, jsonify, current_app +from functools import wraps +from random import randint + +from backend import db +from backend.api import auth_api_bp +from backend.models.user_model import User + + +@auth_api_bp.route('/register', methods=('POST',)) +def register(): + data = request.get_json() + user = User(**data) + db.session.add(user) + db.session.commit() + return jsonify(user.to_dict()), 201 + + +@auth_api_bp.route('/login', methods=('GET', 'POST',)) +def login(): + data = request.get_json() + user = User.authenticate(**data) + + if not user: + return jsonify({ 'message': 'Invalid credentials', 'authenticated': False }), 401 + + token = jwt.encode({ + 'sub': user.email, + 'iat':datetime.utcnow(), + 'exp': datetime.utcnow() + datetime.timedelta(minutes=30)}, + current_app.config['SECRET_KEY']) + return jsonify({'token': token.decode('UTF-8')}) diff --git a/api/example_api.py b/api/example_api.py index 5956f9c..d686586 100644 --- a/api/example_api.py +++ b/api/example_api.py @@ -1,9 +1,12 @@ +import datetime +import ipaddress +import json import logging from random import * -from flask import jsonify, Blueprint +from flask import jsonify, Blueprint, request from flask_restplus import Resource, reqparse -from backend import basic_auth, multi_auth +from backend import basic_auth, multi_auth, db from backend.api import api_v1, api_bp @@ -59,7 +62,7 @@ class SensorData_Handler(Resource): print("values...") print(args['values']) values = json.loads(args['values']) - wasss_app.logger.info("vals: " + str(values) + " (len: " + str(len(values)) + ")") + app.logger.info("vals: " + str(values) + " (len: " + str(len(values)) + ")") rough_geo_location = None try: diff --git a/serve_frontend.py b/serve_frontend.py index de42dc1..5cb8d05 100644 --- a/serve_frontend.py +++ b/serve_frontend.py @@ -2,11 +2,13 @@ # -*- coding: utf-8 -*- import flask +from flask.json import dump from jose import jwt, jwk import os -from flask import render_template, send_from_directory, Blueprint, jsonify +from flask import render_template, send_from_directory, Blueprint, jsonify, url_for from flask_pyoidc.user_session import UserSession +from backend import app from backend.auth import oidc_auth fe_path = os.path.join(os.getcwd(), "frontend", "dist") @@ -41,6 +43,25 @@ def test_oidc(): token_header=token_header) +def has_no_empty_params(rule): + defaults = rule.defaults if rule.defaults is not None else () + arguments = rule.arguments if rule.arguments is not None else () + return len(defaults) >= len(arguments) + + +@fe_bp.route("/site-map") +def site_map(): + links = [] + for rule in app.url_map.iter_rules(): + # Filter out rules we can't navigate to in a browser + # and rules that require parameters + if has_no_empty_params(rule): + #if "GET" in rule.methods and has_no_empty_params(rule): + url = url_for(rule.endpoint, **(rule.defaults or {})) + links.append((url, rule.endpoint)) + # links is now a list of url, endpoint tuples + #dump(links) + return jsonify(links) @fe_bp.route('/', defaults={'path': ''}) @fe_bp.route('/')