Merge pull request #18 from WebEngineering2/api_fix

Api fix
This commit is contained in:
Florian Kaiser 2022-03-22 11:23:09 +01:00 committed by GitHub
commit 062f689743
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 66 additions and 46 deletions

View File

@ -1,12 +1,11 @@
import os import os
from apiflask import APIBlueprint, abort from apiflask import APIBlueprint, abort
from flask import jsonify
from db import db from db import db
from helper_functions import get_user_id_from_username, get_username_or_abort_401 from helper_functions import get_user_id_from_username, get_username_or_abort_401, make_response
from auth import auth from auth import auth
from scheme import KeywordResponseSchema, KeywordSchema, DeleteSuccessfulSchema from schema import KeywordResponseSchema, KeywordSchema, DeleteSuccessfulSchema
from models import Keyword from models import Keyword
keyword_blueprint = APIBlueprint('keyword', __name__, url_prefix='/api') keyword_blueprint = APIBlueprint('keyword', __name__, url_prefix='/api')
@ -35,7 +34,7 @@ def add_keyword(data):
db.session.add(new_keyword) db.session.add(new_keyword)
db.session.commit() db.session.commit()
return jsonify({"status": 200, "text": "Successfully added keyword", "data": new_keyword.as_dict()}) return make_response(new_keyword.as_dict(), 200, "Successfully added keyword")
else: else:
abort(500, message="Keyword already exist for this user") abort(500, message="Keyword already exist for this user")
@ -55,7 +54,7 @@ def remove_keyword(data):
db.session.query(Keyword).filter_by(keyword=key, user_id=get_user_id_from_username(username)).delete() db.session.query(Keyword).filter_by(keyword=key, user_id=get_user_id_from_username(username)).delete()
db.session.commit() db.session.commit()
return jsonify({"status": 200, "text": "Successfully removed keyword", "data": {}}) return make_response({}, 200, "Successfully removed keyword")
@keyword_blueprint.route('/keywords', methods=['GET']) @keyword_blueprint.route('/keywords', methods=['GET'])
@ -72,7 +71,7 @@ def get_keywords():
for row in keywords: for row in keywords:
return_keywords.append(row.as_dict()) return_keywords.append(row.as_dict())
return jsonify({"status": 200, "text": "Successfully loaded keywords", "data": return_keywords}) return make_response(return_keywords, 200, "Successfully loaded keywords")
def check_if_keyword_data_exists(data): def check_if_keyword_data_exists(data):

View File

@ -1,10 +1,9 @@
import os import os
from apiflask import APIBlueprint from apiflask import APIBlueprint
from flask import jsonify
from db import db from db import db
from helper_functions import get_user_id_from_username, get_username_or_abort_401 from helper_functions import get_user_id_from_username, get_username_or_abort_401, make_response
from models import Transaction from models import Transaction
from auth import auth from auth import auth
@ -30,4 +29,4 @@ def get_portfolio():
else: else:
return_portfolio[row.symbol] = {"count": row.count, "last_transaction": row.time} return_portfolio[row.symbol] = {"count": row.count, "last_transaction": row.time}
return jsonify({"status": 200, "text": "Successfully loaded symbols", "data": return_portfolio}) return make_response(return_portfolio, 200, "Successfully loaded symbols")

View File

@ -1,13 +1,12 @@
import os import os
from apiflask import APIBlueprint, abort from apiflask import APIBlueprint, abort
from flask import jsonify
from auth import auth from auth import auth
from db import db from db import db
from helper_functions import get_user_id_from_username, get_username_or_abort_401 from helper_functions import get_user_id_from_username, get_username_or_abort_401, make_response
from models import Share from models import Share
from scheme import SymbolSchema, SymbolResponseSchema, DeleteSuccessfulSchema from schema import SymbolSchema, SymbolResponseSchema, DeleteSuccessfulSchema
shares_blueprint = APIBlueprint('share', __name__, url_prefix='/api') shares_blueprint = APIBlueprint('share', __name__, url_prefix='/api')
__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
@ -35,9 +34,9 @@ def add_symbol(data):
db.session.add(new_symbol) db.session.add(new_symbol)
db.session.commit() db.session.commit()
return jsonify({"status": 200, "text": "Successfully added symbol", "data": new_symbol.as_dict()}) return make_response(new_symbol.as_dict(), 200, "Successfully added symbol")
else: else:
return jsonify({"status": 500, "text": "Symbol already exist for this user"}) return make_response({}, 500, "Symbol already exist for this user")
@shares_blueprint.route('/share', methods=['DELETE']) @shares_blueprint.route('/share', methods=['DELETE'])
@ -55,7 +54,7 @@ def remove_symbol(data):
db.session.query(Share).filter_by(symbol=symbol, user_id=get_user_id_from_username(username)).delete() db.session.query(Share).filter_by(symbol=symbol, user_id=get_user_id_from_username(username)).delete()
db.session.commit() db.session.commit()
return jsonify({"status": 200, "text": "Successfully removed symbol", "data": {}}) return make_response({}, 200, "Successfully removed symbol")
@shares_blueprint.route('/shares', methods=['GET']) @shares_blueprint.route('/shares', methods=['GET'])
@ -72,7 +71,7 @@ def get_symbol():
for row in symbols: for row in symbols:
return_symbols.append(row.as_dict()) return_symbols.append(row.as_dict())
return jsonify({"status": 200, "text": "Successfully loaded symbols", "data": return_symbols}) return make_response(return_symbols, 200, "Successfully loaded symbols")
def check_if_symbol_data_exists(data): def check_if_symbol_data_exists(data):

View File

@ -2,12 +2,11 @@ import os
import datetime import datetime
from apiflask import abort, APIBlueprint from apiflask import abort, APIBlueprint
from flask import jsonify
from db import db from db import db
from helper_functions import get_user_id_from_username, get_username_or_abort_401 from helper_functions import get_user_id_from_username, get_username_or_abort_401, make_response
from models import Transaction from models import Transaction
from scheme import TransactionSchema from schema import TransactionSchema
from auth import auth from auth import auth
transaction_blueprint = APIBlueprint('transaction', __name__, url_prefix='/api') transaction_blueprint = APIBlueprint('transaction', __name__, url_prefix='/api')
@ -34,7 +33,7 @@ def add_transaction(data):
db.session.add(new_transaction) db.session.add(new_transaction)
db.session.commit() db.session.commit()
return jsonify({"status": 200, "text": "Successfully added transaction", "data": new_transaction.as_dict()}) return make_response(new_transaction.as_dict(), 200, "Successfully added transaction")
@transaction_blueprint.route('/transactions', methods=['GET']) @transaction_blueprint.route('/transactions', methods=['GET'])
@ -51,7 +50,7 @@ def get_transaction():
for row in transactions: for row in transactions:
return_transactions.append(row.as_dict()) return_transactions.append(row.as_dict())
return jsonify({"status": 200, "text": "Successfully loaded transactions", "data": return_transactions}) return make_response(return_transactions, 200, "Successfully loaded transactions")
def check_if_transaction_data_exists(data): def check_if_transaction_data_exists(data):

View File

@ -3,12 +3,11 @@ import os
import jwt import jwt
from apiflask import APIBlueprint, abort from apiflask import APIBlueprint, abort
from flask import jsonify
from db import db from db import db
from helper_functions import check_password, hash_password, get_username_or_abort_401, abort_if_no_admin from helper_functions import check_password, hash_password, get_username_or_abort_401, abort_if_no_admin, make_response
from models import User from models import User
from scheme import UsersSchema, TokenSchema, LoginDataSchema, AdminDataSchema, DeleteUserSchema from schema import UsersSchema, TokenSchema, LoginDataSchema, AdminDataSchema, DeleteUserSchema
from auth import auth from auth import auth
users_blueprint = APIBlueprint('users', __name__, url_prefix='/api') users_blueprint = APIBlueprint('users', __name__, url_prefix='/api')
@ -26,7 +25,7 @@ def users():
for i in User.query.all(): for i in User.query.all():
res.append(i.as_dict()) res.append(i.as_dict())
return jsonify({"status": 200, "data": res}) return make_response(res, 200, "Successfully received all users")
@users_blueprint.route('/user', methods=['GET']) @users_blueprint.route('/user', methods=['GET'])
@ -38,7 +37,7 @@ def user():
res = db.session.query(User).filter_by(username=username).first().as_dict() res = db.session.query(User).filter_by(username=username).first().as_dict()
return jsonify({"status": 200, "data": res}) return make_response(res, 200, "Successfully received current user data")
@users_blueprint.route('/user/login', methods=['POST']) @users_blueprint.route('/user/login', methods=['POST'])
@ -60,7 +59,8 @@ def login(data):
abort(500, message="Unable to login") abort(500, message="Unable to login")
token = jwt.encode({'username': query_user.username, 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=45)}, os.getenv('SECRET_KEY'), "HS256") token = jwt.encode({'username': query_user.username, 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=45)}, os.getenv('SECRET_KEY'), "HS256")
return jsonify({"status": 200, "text": "Successfully logged in", "data": {"token": token}})
return make_response({"token": token}, 200, "Successfully logged in")
@users_blueprint.route('/user/register', methods=['POST']) @users_blueprint.route('/user/register', methods=['POST'])
@ -86,7 +86,7 @@ def register(data):
db.session.add(new_user) db.session.add(new_user)
db.session.commit() db.session.commit()
return jsonify({"status": 200, "text": "Successfully registered user", "data": new_user.as_dict()}) return make_response(new_user.as_dict(), 200, "Successfully registered user")
@users_blueprint.route('/user', methods=['PUT']) @users_blueprint.route('/user', methods=['PUT'])
@ -114,7 +114,7 @@ def update_user(data):
db.session.commit() db.session.commit()
return jsonify({"status": 200, "text": "Successfully updated user", "data": {}}) return make_response({}, 200, "Successfully updated user")
@users_blueprint.route('/user/setAdmin', methods=['PUT']) @users_blueprint.route('/user/setAdmin', methods=['PUT'])
@ -138,7 +138,7 @@ def set_admin(data):
query_user.admin = admin query_user.admin = admin
db.session.commit() db.session.commit()
return jsonify({"status": 200, "text": "Successfully updated users admin rights", "data": {}}) return make_response({}, 200, "Successfully updated users admin rights")
@users_blueprint.route('/user', methods=['DELETE']) @users_blueprint.route('/user', methods=['DELETE'])
@ -160,7 +160,7 @@ def delete_user(data):
db.session.query(User).filter_by(username=username).delete() db.session.query(User).filter_by(username=username).delete()
db.session.commit() db.session.commit()
return jsonify({"status": 200, "text": "Successfully removed user", "data": {}}) return make_response({}, 200, "Successfully removed user")
def check_if_user_data_exists(data): def check_if_user_data_exists(data):

View File

@ -24,9 +24,6 @@ def create_app():
db.init_app(application) db.init_app(application)
# Create all tables
db.create_all()
# api blueprints # api blueprints
application.register_blueprint(keyword_blueprint) application.register_blueprint(keyword_blueprint)
application.register_blueprint(shares_blueprint) application.register_blueprint(shares_blueprint)
@ -34,6 +31,10 @@ def create_app():
application.register_blueprint(portfolio_blueprint) application.register_blueprint(portfolio_blueprint)
application.register_blueprint(users_blueprint) application.register_blueprint(users_blueprint)
@application.before_first_request
def init_database():
db.create_all()
return application return application

View File

@ -11,6 +11,9 @@ def verify_token(token):
if token is None: if token is None:
return False return False
if ':' in token: # Bot token
token = token.split(":")[0]
try: try:
jwt.decode(token, os.getenv('SECRET_KEY'), algorithms=["HS256"]) jwt.decode(token, os.getenv('SECRET_KEY'), algorithms=["HS256"])
return True return True

View File

@ -2,7 +2,7 @@ import os
from dotenv import load_dotenv from dotenv import load_dotenv
from scheme import BaseResponseSchema from schema import BaseResponseSchema
load_dotenv() load_dotenv()

View File

@ -4,7 +4,7 @@ import uuid
import jwt import jwt
from apiflask import abort from apiflask import abort
from flask import request from flask import request, jsonify
from db import db from db import db
from models import User from models import User
@ -38,11 +38,30 @@ def extract_token_data(token):
return None return None
def get_username_from_token_data(token_data): def get_username_from_token_data():
if token_data is not None: if 'Authorization' in request.headers:
return token_data['username'] token = request.headers['Authorization'].split(" ")[1]
else:
return None if token is not None:
if ':' in token: # Maybe bot token, check if token valid and return username after ":" then
username = token.split(":")[1]
token = token.split(":")[0]
try:
if jwt.decode(token, os.getenv('SECRET_KEY'), algorithms=["HS256"])['username'] == "bot":
return username
else:
return None
except jwt.exceptions.DecodeError:
return None
else: # "Normal" token, extract username from token
try:
return jwt.decode(token, os.getenv('SECRET_KEY'), algorithms=["HS256"])['username']
except jwt.exceptions.DecodeError:
return None
return None
def get_user_id_from_username(username): def get_user_id_from_username(username):
@ -54,7 +73,7 @@ def get_user_id_from_username(username):
def get_username_or_abort_401(): def get_username_or_abort_401():
# get username from jwt token # get username from jwt token
username = get_username_from_token_data(extract_token_data(get_token())) username = get_username_from_token_data()
if username is None: # If token not provided or invalid -> return 401 code if username is None: # If token not provided or invalid -> return 401 code
abort(401, message="Unable to login") abort(401, message="Unable to login")
@ -71,3 +90,7 @@ def is_user_admin():
username = get_username_or_abort_401() username = get_username_or_abort_401()
return db.session.query(User).filter_by(username=username).first().admin return db.session.query(User).filter_by(username=username).first().admin
def make_response(data, status=200, text=""):
return jsonify({"status": status, "text": text, "data": {"token": data}})

View File

@ -1,12 +1,9 @@
Flask~=2.0.3 Flask~=2.0.3
python-dotenv==0.19.2 python-dotenv==0.19.2
requests==2.27.1
uwsgi==2.0.20 uwsgi==2.0.20
Flask_SQLAlchemy==2.5.1 Flask_SQLAlchemy==2.5.1
python-dotenv==0.19.2 python-dotenv==0.19.2
pymysql==1.0.2 pymysql==1.0.2
pyjwt==2.3.0 pyjwt==2.3.0
apiflask==0.12.0 apiflask==0.12.0
flask-swagger-ui==3.36.0 flask-cors==3.0.10
flask-cors==3.0.10