diff --git a/api/api_blueprint_keyword.py b/api/api_blueprint_keyword.py index 232a97b..a22abb3 100644 --- a/api/api_blueprint_keyword.py +++ b/api/api_blueprint_keyword.py @@ -3,7 +3,7 @@ import os from apiflask import APIBlueprint, abort from db import db -from helper_functions import get_user_id_from_username, get_username_or_abort_401, make_response +from helper_functions import make_response, get_email_or_abort_401 from auth import auth from schema import KeywordResponseSchema, KeywordSchema, DeleteSuccessfulSchema from models import Keyword @@ -18,17 +18,17 @@ __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file @keyword_blueprint.auth_required(auth) @keyword_blueprint.doc(summary="Add new keyword", description="Adds new keyword for current user") def add_keyword(data): - username = get_username_or_abort_401() + email = get_email_or_abort_401() check_if_keyword_data_exists(data) key = data['keyword'] - check_keyword = db.session.query(Keyword).filter_by(keyword=key, user_id=get_user_id_from_username(username)).first() + check_keyword = db.session.query(Keyword).filter_by(keyword=key, email=email).first() if check_keyword is None: # Keyword doesn't exist yet for this user new_keyword = Keyword( - user_id=get_user_id_from_username(username), + email=email, keyword=key ) db.session.add(new_keyword) @@ -45,16 +45,21 @@ def add_keyword(data): @keyword_blueprint.auth_required(auth) @keyword_blueprint.doc(summary="Removes existing keyword", description="Removes existing keyword for current user") def remove_keyword(data): - username = get_username_or_abort_401() + email = get_email_or_abort_401() check_if_keyword_data_exists(data) key = data['keyword'] - db.session.query(Keyword).filter_by(keyword=key, user_id=get_user_id_from_username(username)).delete() - db.session.commit() + check_keyword = db.session.query(Keyword).filter_by(keyword=key, email=email).first() - return make_response({}, 200, "Successfully removed keyword") + if check_keyword is None: + return make_response({}, 500, "Keyword doesn't exist for this user") + else: + db.session.query(Keyword).filter_by(keyword=key, email=email).delete() + db.session.commit() + + return make_response({}, 200, "Successfully removed keyword") @keyword_blueprint.route('/keywords', methods=['GET']) @@ -62,10 +67,10 @@ def remove_keyword(data): @keyword_blueprint.auth_required(auth) @keyword_blueprint.doc(summary="Returns all keywords", description="Returns all keywords for current user") def get_keywords(): - username = get_username_or_abort_401() + email = get_email_or_abort_401() return_keywords = [] - keywords = db.session.query(Keyword).filter_by(user_id=get_user_id_from_username(username)).all() + keywords = db.session.query(Keyword).filter_by(email=email).all() if keywords is not None: for row in keywords: diff --git a/api/api_blueprint_portfolio.py b/api/api_blueprint_portfolio.py index 5970ced..b6ecea3 100644 --- a/api/api_blueprint_portfolio.py +++ b/api/api_blueprint_portfolio.py @@ -2,9 +2,9 @@ import os from apiflask import APIBlueprint +from api.schema import PortfolioResponseSchema from db import db -from helper_functions import get_user_id_from_username, get_username_or_abort_401, make_response -from models import Transaction +from helper_functions import make_response, get_email_or_abort_401 from auth import auth portfolio_blueprint = APIBlueprint('portfolio', __name__, url_prefix='/api') @@ -12,21 +12,22 @@ __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file @portfolio_blueprint.route('/portfolio', methods=['GET']) -@portfolio_blueprint.output(200) +@portfolio_blueprint.output(PortfolioResponseSchema(many=True), 200) @portfolio_blueprint.auth_required(auth) @portfolio_blueprint.doc(summary="Returns portfolio", description="Returns all shares of current user") def get_portfolio(): - username = get_username_or_abort_401() + email = get_email_or_abort_401() - return_portfolio = {} - transactions = db.session.query(Transaction).filter_by(user_id=get_user_id_from_username(username)).all() + return_portfolio = [] + transactions = db.session.execute("SELECT symbol, SUM(count), SUM(price), MAX(time) FROM `transactions` WHERE email = '" + email + "' GROUP BY symbol;").all() if transactions is not None: for row in transactions: - if row.symbol in return_portfolio: - return_portfolio[row.symbol]['count'] += row.count - return_portfolio[row.symbol]['last_transaction'] = row.time - else: - return_portfolio[row.symbol] = {"count": row.count, "last_transaction": row.time} + return_portfolio.append({ + "symbol": row[0], + "count": row[1], + # "price": row[2], + "last_transaction": row[3] + }) return make_response(return_portfolio, 200, "Successfully loaded symbols") diff --git a/api/api_blueprint_shares.py b/api/api_blueprint_shares.py index 3e18e8c..1c7c785 100644 --- a/api/api_blueprint_shares.py +++ b/api/api_blueprint_shares.py @@ -4,7 +4,7 @@ from apiflask import APIBlueprint, abort from auth import auth from db import db -from helper_functions import get_user_id_from_username, get_username_or_abort_401, make_response +from helper_functions import make_response, get_email_or_abort_401 from models import Share from schema import SymbolSchema, SymbolResponseSchema, DeleteSuccessfulSchema @@ -18,17 +18,17 @@ __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file @shares_blueprint.auth_required(auth) @shares_blueprint.doc(summary="Add new symbol", description="Adds new symbol for current user") def add_symbol(data): - username = get_username_or_abort_401() + email = get_email_or_abort_401() check_if_symbol_data_exists(data) symbol = data['symbol'] - check_share = db.session.query(Share).filter_by(symbol=symbol, user_id=get_user_id_from_username(username)).first() + check_share = db.session.query(Share).filter_by(symbol=symbol, email=email).first() if check_share is None: # Keyword doesn't exist yet for this user new_symbol = Share( - user_id=get_user_id_from_username(username), + email=email, symbol=symbol ) db.session.add(new_symbol) @@ -45,16 +45,21 @@ def add_symbol(data): @shares_blueprint.auth_required(auth) @shares_blueprint.doc(summary="Removes existing symbol", description="Removes existing symbol for current user") def remove_symbol(data): - username = get_username_or_abort_401() + email = get_email_or_abort_401() check_if_symbol_data_exists(data) symbol = data['symbol'] - db.session.query(Share).filter_by(symbol=symbol, user_id=get_user_id_from_username(username)).delete() - db.session.commit() + check_share = db.session.query(Share).filter_by(symbol=symbol, email=email).first() - return make_response({}, 200, "Successfully removed symbol") + if check_share is None: + return make_response({}, 500, "Symbol doesn't exist for this user") + else: + db.session.query(Share).filter_by(symbol=symbol, email=email).delete() + db.session.commit() + + return make_response({}, 200, "Successfully removed symbol") @shares_blueprint.route('/shares', methods=['GET']) @@ -62,10 +67,10 @@ def remove_symbol(data): @shares_blueprint.auth_required(auth) @shares_blueprint.doc(summary="Returns all symbols", description="Returns all symbols for current user") def get_symbol(): - username = get_username_or_abort_401() + email = get_email_or_abort_401() return_symbols = [] - symbols = db.session.query(Share).filter_by(user_id=get_user_id_from_username(username)).all() + symbols = db.session.query(Share).filter_by(email=email).all() if symbols is not None: for row in symbols: diff --git a/api/api_blueprint_telegram.py b/api/api_blueprint_telegram.py new file mode 100644 index 0000000..1aa6f6e --- /dev/null +++ b/api/api_blueprint_telegram.py @@ -0,0 +1,42 @@ +import os + +from apiflask import APIBlueprint, abort + +from db import db +from helper_functions import make_response, get_email_or_abort_401 +from auth import auth +from schema import TelegramIdSchema, UsersSchema +from models import User + +telegram_blueprint = APIBlueprint('telegram', __name__, url_prefix='/api') +__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) + + +@telegram_blueprint.route('/telegram', methods=['POST']) +@telegram_blueprint.output(UsersSchema(many=False), 200) +@telegram_blueprint.input(schema=TelegramIdSchema) +@telegram_blueprint.auth_required(auth) +@telegram_blueprint.doc(summary="Connects telegram user id", description="Connects telegram user id to user account") +def add_keyword(data): + email = get_email_or_abort_401() + + check_if_telegram_user_id_data_exists(data) + + query_user = db.session.query(User).filter_by(email=email).first() + + if query_user is None: # Username doesn't exist + abort(500, message="Unable to login") + + query_user.telegram_user_id = data['telegram_user_id'] + + db.session.commit() + + return make_response(query_user.as_dict(), 200, "Successfully connected telegram user") + + +def check_if_telegram_user_id_data_exists(data): + if "telegram_user_id" not in data: + abort(400, message="User ID missing") + + if data['telegram_user_id'] == "" or data['telegram_user_id'] is None: + abort(400, message="User ID missing") diff --git a/api/api_blueprint_transactions.py b/api/api_blueprint_transactions.py index b0e58fc..054a032 100644 --- a/api/api_blueprint_transactions.py +++ b/api/api_blueprint_transactions.py @@ -4,9 +4,9 @@ import datetime from apiflask import abort, APIBlueprint from db import db -from helper_functions import get_user_id_from_username, get_username_or_abort_401, make_response +from helper_functions import make_response, get_email_or_abort_401 from models import Transaction -from schema import TransactionSchema +from schema import TransactionSchema, TransactionResponseSchema from auth import auth transaction_blueprint = APIBlueprint('transaction', __name__, url_prefix='/api') @@ -14,17 +14,17 @@ __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file @transaction_blueprint.route('/transaction', methods=['POST']) -@transaction_blueprint.output((), 200) +@transaction_blueprint.output(TransactionResponseSchema(), 200) @transaction_blueprint.input(schema=TransactionSchema) @transaction_blueprint.auth_required(auth) @transaction_blueprint.doc(summary="Adds new transaction", description="Adds new transaction for current user") def add_transaction(data): - username = get_username_or_abort_401() + email = get_email_or_abort_401() check_if_transaction_data_exists(data) new_transaction = Transaction( - user_id=get_user_id_from_username(username), + email=email, symbol=data['symbol'], time=datetime.datetime.strptime(data['time'], '%Y-%m-%dT%H:%M:%S.%fZ'), count=data['count'], @@ -41,10 +41,10 @@ def add_transaction(data): @transaction_blueprint.auth_required(auth) @transaction_blueprint.doc(summary="Returns all transactions", description="Returns all transactions for current user") def get_transaction(): - username = get_username_or_abort_401() + email = get_email_or_abort_401() return_transactions = [] - transactions = db.session.query(Transaction).filter_by(user_id=get_user_id_from_username(username)).all() + transactions = db.session.query(Transaction).filter_by(email=email).all() if transactions is not None: for row in transactions: diff --git a/api/api_blueprint_user.py b/api/api_blueprint_user.py index 747a82f..0afd873 100644 --- a/api/api_blueprint_user.py +++ b/api/api_blueprint_user.py @@ -5,9 +5,9 @@ import jwt from apiflask import APIBlueprint, abort from db import db -from helper_functions import check_password, hash_password, get_username_or_abort_401, abort_if_no_admin, make_response +from helper_functions import check_password, hash_password, abort_if_no_admin, make_response, get_email_or_abort_401 from models import User -from schema import UsersSchema, TokenSchema, LoginDataSchema, AdminDataSchema, DeleteUserSchema +from schema import UsersSchema, TokenSchema, LoginDataSchema, AdminDataSchema, DeleteUserSchema, RegisterDataSchema, UpdateUserDataSchema from auth import auth users_blueprint = APIBlueprint('users', __name__, url_prefix='/api') @@ -33,9 +33,9 @@ def users(): @users_blueprint.auth_required(auth) @users_blueprint.doc(summary="Get current user", description="Returns current user") def user(): - username = get_username_or_abort_401() + email = get_email_or_abort_401() - res = db.session.query(User).filter_by(username=username).first().as_dict() + res = db.session.query(User).filter_by(email=email).first().as_dict() return make_response(res, 200, "Successfully received current user data") @@ -45,40 +45,45 @@ def user(): @users_blueprint.input(schema=LoginDataSchema) @users_blueprint.doc(summary="Login", description="Returns jwt token if username and password match, otherwise returns error") def login(data): - check_if_user_data_exists(data) + check_if_email_data_exists(data) + check_if_password_data_exists(data) - username = data['username'] + email = data['email'] password = data['password'] - query_user = db.session.query(User).filter_by(username=username).first() + query_user = db.session.query(User).filter_by(email=email).first() - if query_user is None: # Username doesn't exist + if query_user is None: # email doesn't exist abort(500, message="Unable to login") if not check_password(query_user.password, password): # Password incorrect 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({'email': query_user.email, 'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=45)}, os.getenv('SECRET_KEY'), "HS256") return make_response({"token": token}, 200, "Successfully logged in") @users_blueprint.route('/user/register', methods=['POST']) @users_blueprint.output(UsersSchema(), 200) -@users_blueprint.input(schema=LoginDataSchema) +@users_blueprint.input(schema=RegisterDataSchema) @users_blueprint.doc(summary="Register", description="Registers user") def register(data): - check_if_user_data_exists(data) + check_if_email_data_exists(data) + check_if_username_data_exists(data) + check_if_password_data_exists(data) + email = data['email'] username = data['username'] password = data['password'] - query_user = db.session.query(User).filter_by(username=username).first() + query_user = db.session.query(User).filter_by(email=email).first() if query_user is not None: # Username already exist - abort(500, message="Username already exist") + abort(500, message="Email already exist") new_user = User( + email=email, username=username, password=hash_password(password), admin=False @@ -91,26 +96,21 @@ def register(data): @users_blueprint.route('/user', methods=['PUT']) @users_blueprint.output({}, 200) -@users_blueprint.input(schema=LoginDataSchema) +@users_blueprint.input(schema=UpdateUserDataSchema) @users_blueprint.auth_required(auth) @users_blueprint.doc(summary="Update user", description="Changes password and/or username of current user") def update_user(data): - username = get_username_or_abort_401() + email = get_email_or_abort_401() - check_if_user_data_exists(data) - - new_username = data['username'] - new_password = data['password'] - - query_user = db.session.query(User).filter_by(username=username).first() + query_user = db.session.query(User).filter_by(email=email).first() if query_user is None: # Username doesn't exist abort(500, message="Unable to login") - if new_password is not None: - query_user.password = hash_password(new_password) - if new_username is not None: - query_user.username = new_username + if "password" in data and data['password'] is not None: + query_user.password = hash_password(data['password']) + if "username" in data and data['username'] is not None: + query_user.username = data['username'] db.session.commit() @@ -125,12 +125,13 @@ def update_user(data): def set_admin(data): abort_if_no_admin() # Only admin users can do this + check_if_email_data_exists(data) check_if_admin_data_exists(data) - username = data['username'] + email = data['email'] admin = data['admin'] - query_user = db.session.query(User).filter_by(username=username).first() + query_user = db.session.query(User).filter_by(email=email).first() if query_user is None: # Username doesn't exist abort(500, message="Unable to login") @@ -147,29 +148,31 @@ def set_admin(data): @users_blueprint.auth_required(auth) @users_blueprint.doc(summary="Delete user", description="Deletes user by username") def delete_user(data): - check_if_delete_data_exists(data) + check_if_email_data_exists(data) - username = data['username'] + email = data['email'] - if username == get_username_or_abort_401(): # Username is same as current user - db.session.query(User).filter_by(username=username).delete() + if email == get_email_or_abort_401(): # Username is same as current user + db.session.query(User).filter_by(email=email).delete() db.session.commit() else: # Delete different user than my user -> only admin users abort_if_no_admin() - db.session.query(User).filter_by(username=username).delete() + db.session.query(User).filter_by(email=email).delete() db.session.commit() return make_response({}, 200, "Successfully removed user") -def check_if_user_data_exists(data): - if "username" not in data: - abort(400, message="Username missing") +def check_if_email_data_exists(data): + if "email" not in data: + abort(400, message="Email missing") - if data['username'] == "" or data['username'] is None: - abort(400, message="Username missing") + if data['email'] == "" or data['email'] is None: + abort(400, message="Email missing") + +def check_if_password_data_exists(data): if "password" not in data: abort(400, message="Password missing") @@ -177,23 +180,17 @@ def check_if_user_data_exists(data): abort(400, message="Password missing") -def check_if_admin_data_exists(data): +def check_if_username_data_exists(data): if "username" not in data: abort(400, message="Username missing") if data['username'] == "" or data['username'] is None: abort(400, message="Username missing") + +def check_if_admin_data_exists(data): if "admin" not in data: abort(400, message="Admin state missing") if data['admin'] == "" or data['admin'] is None: abort(400, message="Admin state missing") - - -def check_if_delete_data_exists(data): - if "username" not in data: - abort(400, message="Username missing") - - if data['username'] == "" or data['username'] is None: - abort(400, message="Username missing") diff --git a/api/app.py b/api/app.py index da31695..1132b2e 100644 --- a/api/app.py +++ b/api/app.py @@ -5,13 +5,14 @@ from apiflask import APIFlask from dotenv import load_dotenv from flask_cors import CORS +from api.api_blueprint_keyword import keyword_blueprint +from api.api_blueprint_portfolio import portfolio_blueprint +from api.api_blueprint_shares import shares_blueprint +from api.api_blueprint_transactions import transaction_blueprint +from api.api_blueprint_telegram import telegram_blueprint from api.helper_functions import hash_password from models import * -from api_blueprint_keyword import keyword_blueprint -from api_blueprint_shares import shares_blueprint from api_blueprint_user import users_blueprint -from api_blueprint_transactions import transaction_blueprint -from api_blueprint_portfolio import portfolio_blueprint def create_app(): @@ -33,25 +34,28 @@ def create_app(): application.register_blueprint(transaction_blueprint) application.register_blueprint(portfolio_blueprint) application.register_blueprint(users_blueprint) + application.register_blueprint(telegram_blueprint) @application.before_first_request def init_database(): db.create_all() - if os.getenv("BOT_USER") is not None and os.getenv("BOT_PASSWORD") is not None: - if db.session.query(User).filter_by(username=os.getenv("BOT_USER")).first() is None: # Check if user already exist + if os.getenv("BOT_EMAIL") is not None and os.getenv("BOT_USERNAME") is not None and os.getenv("BOT_PASSWORD") is not None: + if db.session.query(User).filter_by(email=os.getenv("BOT_EMAIL")).first() is None: # Check if user already exist bot = User( - username=os.getenv("BOT_USER"), + email=os.getenv("BOT_EMAIL"), + username=os.getenv("BOT_USERNAME"), password=hash_password(os.getenv("BOT_PASSWORD")), admin=False ) db.session.add(bot) db.session.commit() - if os.getenv("ADMIN_USER") is not None and os.getenv("ADMIN_PASSWORD") is not None: - if db.session.query(User).filter_by(username=os.getenv("ADMIN_USER")).first() is None: # Check if user already exist + if os.getenv("ADMIN_EMAIL") is not None and os.getenv("ADMIN_USERNAME") is not None and os.getenv("ADMIN_PASSWORD") is not None: + if db.session.query(User).filter_by(email=os.getenv("ADMIN_EMAIL")).first() is None: # Check if user already exist admin = User( - username=os.getenv("ADMIN_USER"), + email=os.getenv("ADMIN_EMAIL"), + username=os.getenv("ADMIN_USERNAME"), password=hash_password(os.getenv("ADMIN_PASSWORD")), admin=True ) diff --git a/api/auth.py b/api/auth.py index 8096012..f13eda3 100644 --- a/api/auth.py +++ b/api/auth.py @@ -17,5 +17,5 @@ def verify_token(token): try: jwt.decode(token, os.getenv('SECRET_KEY'), algorithms=["HS256"]) return True - except jwt.exceptions.DecodeError: + except: return False diff --git a/api/helper_functions.py b/api/helper_functions.py index 59991c6..6eca7a5 100644 --- a/api/helper_functions.py +++ b/api/helper_functions.py @@ -32,53 +32,46 @@ def extract_token_data(token): if token is not None: try: return jwt.decode(token, os.getenv('SECRET_KEY'), algorithms=["HS256"]) - except jwt.exceptions.DecodeError: + except: return None else: return None -def get_username_from_token_data(): +def get_email_from_token_data(): if 'Authorization' in request.headers: token = request.headers['Authorization'].split(" ")[1] if token is not None: if ':' in token: # Maybe bot token, check if token valid and return username after ":" then - username = token.split(":")[1] + email = token.split(":")[1] token = token.split(":")[0] try: - if jwt.decode(token, os.getenv('SECRET_KEY'), algorithms=["HS256"])['username'] == "bot": - return username + if jwt.decode(token, os.getenv('SECRET_KEY'), algorithms=["HS256"])['email'] == os.getenv("BOT_USER"): + return email else: return None - except jwt.exceptions.DecodeError: + except: 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 jwt.decode(token, os.getenv('SECRET_KEY'), algorithms=["HS256"])['email'] + except: return None return None -def get_user_id_from_username(username): - if username is not None: - return db.session.query(User).filter_by(username=username).first().user_id - else: - return None - - -def get_username_or_abort_401(): +def get_email_or_abort_401(): # get username from jwt token - username = get_username_from_token_data() + email = get_email_from_token_data() - if username is None: # If token not provided or invalid -> return 401 code + if email is None: # If token not provided or invalid -> return 401 code abort(401, message="Unable to login") - return username + return email def abort_if_no_admin(): @@ -87,10 +80,10 @@ def abort_if_no_admin(): def is_user_admin(): - username = get_username_or_abort_401() + email = get_email_or_abort_401() - return db.session.query(User).filter_by(username=username).first().admin + return db.session.query(User).filter_by(email=email).first().admin def make_response(data, status=200, text=""): - return jsonify({"status": status, "text": text, "data": {"token": data}}) + return jsonify({"status": status, "text": text, "data": data}) diff --git a/api/models.py b/api/models.py index 59e4287..20c4830 100644 --- a/api/models.py +++ b/api/models.py @@ -3,10 +3,10 @@ from db import db class User(db.Model): __tablename__ = 'users' - username = db.Column('username', db.String(255), nullable=False, unique=True) + email = db.Column('email', db.String(255), primary_key=True, nullable=False, unique=True) password = db.Column('password', db.String(255), nullable=False, server_default='') - user_id = db.Column('user_id', db.Integer(), primary_key=True) - telegram_name = db.Column('telegram_name', db.String(255), nullable=True, server_default='') + username = db.Column('username', db.String(255), nullable=False, server_default='') + telegram_user_id = db.Column('telegram_user_id', db.String(255), nullable=True, server_default='') admin = db.Column('admin', db.Boolean(), server_default='0') def as_dict(self): @@ -16,7 +16,7 @@ class User(db.Model): class Transaction(db.Model): __tablename__ = 'transactions' t_id = db.Column('t_id', db.Integer(), nullable=False, unique=True, primary_key=True) - user_id = db.Column('user_id', db.Integer(), db.ForeignKey('users.user_id', ondelete='CASCADE')) + email = db.Column('email', db.String(255), db.ForeignKey('users.email', ondelete='CASCADE')) symbol = db.Column('symbol', db.String(255)) time = db.Column('time', db.DateTime()) count = db.Column('count', db.Integer()) @@ -29,7 +29,7 @@ class Transaction(db.Model): class Keyword(db.Model): __tablename__ = 'keywords' s_id = db.Column('s_id', db.Integer(), nullable=False, unique=True, primary_key=True) - user_id = db.Column('user_id', db.Integer(), db.ForeignKey('users.user_id', ondelete='CASCADE')) + email = db.Column('email', db.String(255), db.ForeignKey('users.email', ondelete='CASCADE')) keyword = db.Column('keyword', db.String(255)) def as_dict(self): @@ -39,7 +39,7 @@ class Keyword(db.Model): class Share(db.Model): __tablename__ = 'shares' a_id = db.Column('a_id', db.Integer(), nullable=False, unique=True, primary_key=True) - user_id = db.Column('user_id', db.Integer(), db.ForeignKey('users.user_id', ondelete='CASCADE')) + email = db.Column('email', db.String(255), db.ForeignKey('users.email', ondelete='CASCADE')) symbol = db.Column('symbol', db.String(255)) def as_dict(self): diff --git a/api/schema.py b/api/schema.py index bb1371a..67fdf65 100644 --- a/api/schema.py +++ b/api/schema.py @@ -1,5 +1,7 @@ from apiflask import Schema from apiflask.fields import Integer, String, Boolean, Field, Float +from marshmallow import validate +from marshmallow.fields import Email class BaseResponseSchema(Schema): @@ -11,13 +13,13 @@ class BaseResponseSchema(Schema): class UsersSchema(Schema): admin = Boolean() password = String() - telegram_name = String() - user_id = Integer() username = String() + telegram_user_id = String() + email = Email() class AdminDataSchema(Schema): - username = String() + email = Email() admin = Boolean() @@ -26,12 +28,23 @@ class TokenSchema(Schema): class LoginDataSchema(Schema): + email = Email() + password = String() + + +class RegisterDataSchema(Schema): + email = Email() username = String() password = String() +class UpdateUserDataSchema(Schema): + username = String(required=False) + password = String(required=False) + + class DeleteUserSchema(Schema): - username = String() + email = Email() class ChangePasswordSchema(Schema): @@ -50,7 +63,7 @@ class KeywordSchema(Schema): class KeywordResponseSchema(Schema): keyword = String() s_id = Integer() - user_id = Integer() + email = Email() class SymbolSchema(Schema): @@ -60,7 +73,7 @@ class SymbolSchema(Schema): class SymbolResponseSchema(Schema): symbol = String() s_id = Integer() - user_id = Integer() + email = Email() class PortfolioShareResponseSchema(Schema): @@ -69,12 +82,30 @@ class PortfolioShareResponseSchema(Schema): class TransactionSchema(Schema): - user_id = Integer() + symbol = String() + time = String(validate=validate.Regexp(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z")) + count = Integer() + price = Float() + + +class TransactionResponseSchema(Schema): + email = Email() symbol = String() time = String() count = Integer() price = Float() +class TelegramIdSchema(Schema): + telegram_user_id = String() + + +class PortfolioResponseSchema(Schema): + symbol = String() + last_transaction = String() + count = Integer() + # price = Float() + + class DeleteSuccessfulSchema(Schema): pass diff --git a/documentation/api/openapi.json b/documentation/api/openapi.json index 7c9d313..f16137b 100644 --- a/documentation/api/openapi.json +++ b/documentation/api/openapi.json @@ -1 +1 @@ -{"components":{"schemas":{"AdminData":{"properties":{"admin":{"type":"boolean"},"username":{"type":"string"}},"type":"object"},"DeleteSuccessful":{"properties":{},"type":"object"},"DeleteUser":{"properties":{"username":{"type":"string"}},"type":"object"},"HTTPError":{"properties":{"detail":{"type":"object"},"message":{"type":"string"}},"type":"object"},"Keyword":{"properties":{"keyword":{"type":"string"}},"type":"object"},"KeywordResponse":{"properties":{"keyword":{"type":"string"},"s_id":{"type":"integer"},"user_id":{"type":"integer"}},"type":"object"},"LoginData":{"properties":{"password":{"type":"string"},"username":{"type":"string"}},"type":"object"},"Symbol":{"properties":{"symbol":{"type":"string"}},"type":"object"},"SymbolResponse":{"properties":{"s_id":{"type":"integer"},"symbol":{"type":"string"},"user_id":{"type":"integer"}},"type":"object"},"Token":{"properties":{"token":{"type":"string"}},"type":"object"},"Transaction":{"properties":{"count":{"type":"integer"},"price":{"type":"number"},"symbol":{"type":"string"},"time":{"type":"string"},"user_id":{"type":"integer"}},"type":"object"},"Users":{"properties":{"admin":{"type":"boolean"},"password":{"type":"string"},"telegram_name":{"type":"string"},"user_id":{"type":"integer"},"username":{"type":"string"}},"type":"object"},"ValidationError":{"properties":{"detail":{"properties":{"":{"properties":{"":{"items":{"type":"string"},"type":"array"}},"type":"object"}},"type":"object"},"message":{"type":"string"}},"type":"object"}},"securitySchemes":{"BearerAuth":{"scheme":"Bearer","type":"http"}}},"info":{"description":"Webengineering 2 | Telegram Aktienbot","title":"APIFlask","version":"0.0.1"},"openapi":"3.0.3","paths":{"/api/keyword":{"delete":{"description":"Removes existing keyword for current user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DeleteSuccessful"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Removes existing keyword","tags":["Keyword"]},"post":{"description":"Adds new keyword for current user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/KeywordResponse"},"type":"array"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Add new keyword","tags":["Keyword"]}},"/api/keywords":{"get":{"description":"Returns all keywords for current user","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/KeywordResponse"},"type":"array"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Returns all keywords","tags":["Keyword"]}},"/api/portfolio":{"get":{"description":"Returns all shares of current user","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/200"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Returns portfolio","tags":["Portfolio"]}},"/api/share":{"delete":{"description":"Removes existing symbol for current user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Symbol"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DeleteSuccessful"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Removes existing symbol","tags":["Share"]},"post":{"description":"Adds new symbol for current user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Symbol"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/SymbolResponse"},"type":"array"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Add new symbol","tags":["Share"]}},"/api/shares":{"get":{"description":"Returns all symbols for current user","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/SymbolResponse"},"type":"array"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Returns all symbols","tags":["Share"]}},"/api/transaction":{"post":{"description":"Adds new transaction for current user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/()"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Adds new transaction","tags":["Transaction"]}},"/api/transactions":{"get":{"description":"Returns all transactions for current user","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Transaction"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Returns all transactions","tags":["Transaction"]}},"/api/user":{"delete":{"description":"Deletes user by username","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteUser"}}}},"responses":{"204":{"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Delete user","tags":["Users"]},"get":{"description":"Returns current user","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Users"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Get current user","tags":["Users"]},"put":{"description":"Changes password and/or username of current user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginData"}}}},"responses":{"204":{"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Update user","tags":["Users"]}},"/api/user/login":{"post":{"description":"Returns jwt token if username and password match, otherwise returns error","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginData"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Token"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"}},"summary":"Login","tags":["Users"]}},"/api/user/register":{"post":{"description":"Registers user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginData"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Users"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"}},"summary":"Register","tags":["Users"]}},"/api/user/setAdmin":{"put":{"description":"Set admin state of specified user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminData"}}}},"responses":{"204":{"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Set user admin state","tags":["Users"]}},"/api/users":{"get":{"description":"Returns all existing users as array","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Users"},"type":"array"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Get all users","tags":["Users"]}}},"servers":[{"name":"Production","url":"https://aktienbot.flokaiser.com"},{"name":"Local","url":"http://127.0.0.1:5000"}],"tags":[{"name":"Keyword"},{"name":"Share"},{"name":"Transaction"},{"name":"Portfolio"},{"name":"Users"}]} +{"components":{"schemas":{"AdminData":{"properties":{"admin":{"type":"boolean"},"email":{"format":"email","type":"string"}},"type":"object"},"DeleteSuccessful":{"properties":{},"type":"object"},"DeleteUser":{"properties":{"email":{"format":"email","type":"string"}},"type":"object"},"HTTPError":{"properties":{"detail":{"type":"object"},"message":{"type":"string"}},"type":"object"},"Keyword":{"properties":{"keyword":{"type":"string"}},"type":"object"},"KeywordResponse":{"properties":{"email":{"format":"email","type":"string"},"keyword":{"type":"string"},"s_id":{"type":"integer"}},"type":"object"},"LoginData":{"properties":{"email":{"format":"email","type":"string"},"password":{"type":"string"}},"type":"object"},"PortfolioResponse":{"properties":{"count":{"type":"integer"},"last_transaction":{"type":"string"},"symbol":{"type":"string"}},"type":"object"},"RegisterData":{"properties":{"email":{"format":"email","type":"string"},"password":{"type":"string"},"username":{"type":"string"}},"type":"object"},"Symbol":{"properties":{"symbol":{"type":"string"}},"type":"object"},"SymbolResponse":{"properties":{"email":{"format":"email","type":"string"},"s_id":{"type":"integer"},"symbol":{"type":"string"}},"type":"object"},"TelegramId":{"properties":{"telegram_user_id":{"type":"string"}},"type":"object"},"Token":{"properties":{"token":{"type":"string"}},"type":"object"},"Transaction":{"properties":{"count":{"type":"integer"},"price":{"type":"number"},"symbol":{"type":"string"},"time":{"pattern":"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z","type":"string"}},"type":"object"},"TransactionResponse":{"properties":{"count":{"type":"integer"},"email":{"format":"email","type":"string"},"price":{"type":"number"},"symbol":{"type":"string"},"time":{"type":"string"}},"type":"object"},"UpdateUserData":{"properties":{"password":{"type":"string"},"username":{"type":"string"}},"type":"object"},"Users":{"properties":{"admin":{"type":"boolean"},"email":{"format":"email","type":"string"},"password":{"type":"string"},"telegram_user_id":{"type":"string"},"username":{"type":"string"}},"type":"object"},"ValidationError":{"properties":{"detail":{"properties":{"":{"properties":{"":{"items":{"type":"string"},"type":"array"}},"type":"object"}},"type":"object"},"message":{"type":"string"}},"type":"object"}},"securitySchemes":{"BearerAuth":{"scheme":"Bearer","type":"http"}}},"info":{"description":"Webengineering 2 | Telegram Aktienbot","title":"APIFlask","version":"0.0.1"},"openapi":"3.0.3","paths":{"/api/keyword":{"delete":{"description":"Removes existing keyword for current user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DeleteSuccessful"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Removes existing keyword","tags":["Keyword"]},"post":{"description":"Adds new keyword for current user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Keyword"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/KeywordResponse"},"type":"array"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Add new keyword","tags":["Keyword"]}},"/api/keywords":{"get":{"description":"Returns all keywords for current user","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/KeywordResponse"},"type":"array"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Returns all keywords","tags":["Keyword"]}},"/api/portfolio":{"get":{"description":"Returns all shares of current user","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/PortfolioResponse"},"type":"array"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Returns portfolio","tags":["Portfolio"]}},"/api/share":{"delete":{"description":"Removes existing symbol for current user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Symbol"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DeleteSuccessful"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Removes existing symbol","tags":["Share"]},"post":{"description":"Adds new symbol for current user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Symbol"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/SymbolResponse"},"type":"array"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Add new symbol","tags":["Share"]}},"/api/shares":{"get":{"description":"Returns all symbols for current user","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/SymbolResponse"},"type":"array"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Returns all symbols","tags":["Share"]}},"/api/telegram":{"post":{"description":"Connects telegram user id to user account","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelegramId"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Users"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Connects telegram user id","tags":["Telegram"]}},"/api/transaction":{"post":{"description":"Adds new transaction for current user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/TransactionResponse"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Adds new transaction","tags":["Transaction"]}},"/api/transactions":{"get":{"description":"Returns all transactions for current user","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Transaction"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Returns all transactions","tags":["Transaction"]}},"/api/user":{"delete":{"description":"Deletes user by username","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteUser"}}}},"responses":{"204":{"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Delete user","tags":["Users"]},"get":{"description":"Returns current user","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Users"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Get current user","tags":["Users"]},"put":{"description":"Changes password and/or username of current user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserData"}}}},"responses":{"204":{"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Update user","tags":["Users"]}},"/api/user/login":{"post":{"description":"Returns jwt token if username and password match, otherwise returns error","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginData"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Token"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"}},"summary":"Login","tags":["Users"]}},"/api/user/register":{"post":{"description":"Registers user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterData"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Users"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"}},"summary":"Register","tags":["Users"]}},"/api/user/setAdmin":{"put":{"description":"Set admin state of specified user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminData"}}}},"responses":{"204":{"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Set user admin state","tags":["Users"]}},"/api/users":{"get":{"description":"Returns all existing users as array","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Users"},"type":"array"},"status":{"type":"integer"},"text":{"type":"string"}},"type":"object"}}},"description":"Successful response"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPError"}}},"description":"Authentication error"}},"security":[{"BearerAuth":[]}],"summary":"Get all users","tags":["Users"]}}},"servers":[{"name":"Production","url":"https://aktienbot.flokaiser.com"},{"name":"Local","url":"http://127.0.0.1:5000"}],"tags":[{"name":"Keyword"},{"name":"Share"},{"name":"Transaction"},{"name":"Portfolio"},{"name":"Users"},{"name":"Telegram"}]} diff --git a/documentation/api/postman.json b/documentation/api/postman.json index e6fee89..db6e014 100644 --- a/documentation/api/postman.json +++ b/documentation/api/postman.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "b478b800-af91-45a7-8713-b199bcc41866", + "_postman_id": "eed3eb48-b932-4d72-979a-38de9ae2cbf0", "name": "APIFlask", "description": "Webengineering 2 | Telegram Aktienbot", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" @@ -35,7 +35,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"keyword\": \"elit Lorem\"\n}", + "raw": "{\n \"keyword\": \"nisi\"\n}", "options": { "raw": { "language": "json" @@ -68,7 +68,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"keyword\": \"elit Lorem\"\n}", + "raw": "{\n \"keyword\": \"nisi\"\n}", "options": { "raw": { "language": "json" @@ -96,7 +96,7 @@ } ], "cookie": [], - "body": "{\n \"data\": {},\n \"status\": 261201,\n \"text\": \"aliqua amet consectetur elit\"\n}" + "body": "{\n \"data\": {},\n \"status\": -35854777,\n \"text\": \"sint in\"\n}" }, { "name": "Validation error", @@ -111,7 +111,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"keyword\": \"elit Lorem\"\n}", + "raw": "{\n \"keyword\": \"nisi\"\n}", "options": { "raw": { "language": "json" @@ -139,7 +139,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"labore\",\n \"\"\n ]\n }\n },\n \"message\": \"pariatur cillum qui aute\"\n}" + "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"anim quis\",\n \"in velit ali\"\n ]\n }\n },\n \"message\": \"nostrud\"\n}" }, { "name": "Authentication error", @@ -154,7 +154,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"keyword\": \"elit Lorem\"\n}", + "raw": "{\n \"keyword\": \"nisi\"\n}", "options": { "raw": { "language": "json" @@ -182,7 +182,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] }, @@ -212,7 +212,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"keyword\": \"elit Lorem\"\n}", + "raw": "{\n \"keyword\": \"nisi\"\n}", "options": { "raw": { "language": "json" @@ -245,7 +245,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"keyword\": \"elit Lorem\"\n}", + "raw": "{\n \"keyword\": \"nisi\"\n}", "options": { "raw": { "language": "json" @@ -273,7 +273,7 @@ } ], "cookie": [], - "body": "{\n \"data\": [\n {\n \"keyword\": \"tempor dolor commodo ipsum non\",\n \"s_id\": -64068772,\n \"user_id\": 82510382\n },\n {\n \"keyword\": \"in aute ex\",\n \"s_id\": 60028598,\n \"user_id\": -36905324\n }\n ],\n \"status\": 63124172,\n \"text\": \"amet\"\n}" + "body": "{\n \"data\": [\n {\n \"email\": \"8Es0sp5sb@wvQoAOvD.bzz\",\n \"keyword\": \"eiusmo\",\n \"s_id\": -48384117\n },\n {\n \"email\": \"MZ0cnQ1mwRV@oONtzNaRnVSaUXAReoDzwztMr.fiz\",\n \"keyword\": \"ullamco ad\",\n \"s_id\": -36966818\n }\n ],\n \"status\": 55335664,\n \"text\": \"dolor id ex\"\n}" }, { "name": "Validation error", @@ -288,7 +288,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"keyword\": \"elit Lorem\"\n}", + "raw": "{\n \"keyword\": \"nisi\"\n}", "options": { "raw": { "language": "json" @@ -316,7 +316,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"labore\",\n \"\"\n ]\n }\n },\n \"message\": \"pariatur cillum qui aute\"\n}" + "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"anim quis\",\n \"in velit ali\"\n ]\n }\n },\n \"message\": \"nostrud\"\n}" }, { "name": "Authentication error", @@ -331,7 +331,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"keyword\": \"elit Lorem\"\n}", + "raw": "{\n \"keyword\": \"nisi\"\n}", "options": { "raw": { "language": "json" @@ -359,7 +359,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] }, @@ -428,7 +428,7 @@ } ], "cookie": [], - "body": "{\n \"data\": [\n {\n \"keyword\": \"tempor dolor commodo ipsum non\",\n \"s_id\": -64068772,\n \"user_id\": 82510382\n },\n {\n \"keyword\": \"in aute ex\",\n \"s_id\": 60028598,\n \"user_id\": -36905324\n }\n ],\n \"status\": 63124172,\n \"text\": \"amet\"\n}" + "body": "{\n \"data\": [\n {\n \"email\": \"8Es0sp5sb@wvQoAOvD.bzz\",\n \"keyword\": \"eiusmo\",\n \"s_id\": -48384117\n },\n {\n \"email\": \"MZ0cnQ1mwRV@oONtzNaRnVSaUXAReoDzwztMr.fiz\",\n \"keyword\": \"ullamco ad\",\n \"s_id\": -36966818\n }\n ],\n \"status\": 55335664,\n \"text\": \"dolor id ex\"\n}" }, { "name": "Authentication error", @@ -462,7 +462,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] } @@ -497,7 +497,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"symbol\": \"aliquip ullamco Ut\"\n}", + "raw": "{\n \"symbol\": \"magna Excepteur ullamco aute velit\"\n}", "options": { "raw": { "language": "json" @@ -530,7 +530,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"symbol\": \"aliquip ullamco Ut\"\n}", + "raw": "{\n \"symbol\": \"magna Excepteur ullamco aute velit\"\n}", "options": { "raw": { "language": "json" @@ -558,7 +558,7 @@ } ], "cookie": [], - "body": "{\n \"data\": {},\n \"status\": 261201,\n \"text\": \"aliqua amet consectetur elit\"\n}" + "body": "{\n \"data\": {},\n \"status\": -35854777,\n \"text\": \"sint in\"\n}" }, { "name": "Validation error", @@ -573,7 +573,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"symbol\": \"aliquip ullamco Ut\"\n}", + "raw": "{\n \"symbol\": \"magna Excepteur ullamco aute velit\"\n}", "options": { "raw": { "language": "json" @@ -601,7 +601,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"labore\",\n \"\"\n ]\n }\n },\n \"message\": \"pariatur cillum qui aute\"\n}" + "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"anim quis\",\n \"in velit ali\"\n ]\n }\n },\n \"message\": \"nostrud\"\n}" }, { "name": "Authentication error", @@ -616,7 +616,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"symbol\": \"aliquip ullamco Ut\"\n}", + "raw": "{\n \"symbol\": \"magna Excepteur ullamco aute velit\"\n}", "options": { "raw": { "language": "json" @@ -644,7 +644,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] }, @@ -674,7 +674,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"symbol\": \"aliquip ullamco Ut\"\n}", + "raw": "{\n \"symbol\": \"magna Excepteur ullamco aute velit\"\n}", "options": { "raw": { "language": "json" @@ -707,7 +707,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"symbol\": \"aliquip ullamco Ut\"\n}", + "raw": "{\n \"symbol\": \"magna Excepteur ullamco aute velit\"\n}", "options": { "raw": { "language": "json" @@ -735,7 +735,7 @@ } ], "cookie": [], - "body": "{\n \"data\": [\n {\n \"s_id\": -53227093,\n \"symbol\": \"veniam ea amet irure\",\n \"user_id\": 7468241\n },\n {\n \"s_id\": -37877246,\n \"symbol\": \"ut tempor labore non\",\n \"user_id\": -72644124\n }\n ],\n \"status\": 87653200,\n \"text\": \"aliquip reprehenderit dolore\"\n}" + "body": "{\n \"data\": [\n {\n \"email\": \"j32mUuC@iIJKfYQWSepoVsngEZYbfEmOwCzXXxVMP.alp\",\n \"s_id\": 86469214,\n \"symbol\": \"labore ea\"\n },\n {\n \"email\": \"PwKotAxaLBa8nY@nSsGmaxZeZqnRhOGmHhbICYhqTGLESrq.xy\",\n \"s_id\": 63768957,\n \"symbol\": \"laboris pariatur commodo\"\n }\n ],\n \"status\": -1862021,\n \"text\": \"culpa nulla\"\n}" }, { "name": "Validation error", @@ -750,7 +750,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"symbol\": \"aliquip ullamco Ut\"\n}", + "raw": "{\n \"symbol\": \"magna Excepteur ullamco aute velit\"\n}", "options": { "raw": { "language": "json" @@ -778,7 +778,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"labore\",\n \"\"\n ]\n }\n },\n \"message\": \"pariatur cillum qui aute\"\n}" + "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"anim quis\",\n \"in velit ali\"\n ]\n }\n },\n \"message\": \"nostrud\"\n}" }, { "name": "Authentication error", @@ -793,7 +793,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"symbol\": \"aliquip ullamco Ut\"\n}", + "raw": "{\n \"symbol\": \"magna Excepteur ullamco aute velit\"\n}", "options": { "raw": { "language": "json" @@ -821,7 +821,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] }, @@ -890,7 +890,7 @@ } ], "cookie": [], - "body": "{\n \"data\": [\n {\n \"s_id\": -53227093,\n \"symbol\": \"veniam ea amet irure\",\n \"user_id\": 7468241\n },\n {\n \"s_id\": -37877246,\n \"symbol\": \"ut tempor labore non\",\n \"user_id\": -72644124\n }\n ],\n \"status\": 87653200,\n \"text\": \"aliquip reprehenderit dolore\"\n}" + "body": "{\n \"data\": [\n {\n \"email\": \"j32mUuC@iIJKfYQWSepoVsngEZYbfEmOwCzXXxVMP.alp\",\n \"s_id\": 86469214,\n \"symbol\": \"labore ea\"\n },\n {\n \"email\": \"PwKotAxaLBa8nY@nSsGmaxZeZqnRhOGmHhbICYhqTGLESrq.xy\",\n \"s_id\": 63768957,\n \"symbol\": \"laboris pariatur commodo\"\n }\n ],\n \"status\": -1862021,\n \"text\": \"culpa nulla\"\n}" }, { "name": "Authentication error", @@ -924,7 +924,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] } @@ -959,7 +959,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"count\": 96634001,\n \"price\": -71028444.15053315,\n \"symbol\": \"deserunt officia dolore\",\n \"time\": \"magna occaecat est\",\n \"user_id\": -71272721\n}", + "raw": "{\n \"count\": 76782033,\n \"price\": -9709838.042264134,\n \"symbol\": \"mollit esse ex in\",\n \"time\": \"2120-69-63T43:76:75.378Z\"\n}", "options": { "raw": { "language": "json" @@ -992,7 +992,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"count\": 96634001,\n \"price\": -71028444.15053315,\n \"symbol\": \"deserunt officia dolore\",\n \"time\": \"magna occaecat est\",\n \"user_id\": -71272721\n}", + "raw": "{\n \"count\": 76782033,\n \"price\": -9709838.042264134,\n \"symbol\": \"mollit esse ex in\",\n \"time\": \"2120-69-63T43:76:75.378Z\"\n}", "options": { "raw": { "language": "json" @@ -1020,7 +1020,7 @@ } ], "cookie": [], - "body": "{\n \"data\": {\n \"value\": \"reference #/components/schemas/() not found in the OpenAPI spec\"\n },\n \"status\": 14310780,\n \"text\": \"in sint sit\"\n}" + "body": "{\n \"data\": {\n \"count\": 99691073,\n \"email\": \"DAX6XjHTr8eA6M@xsoUe.id\",\n \"price\": -14617384.086570382,\n \"symbol\": \"eu ad deserunt\",\n \"time\": \"ipsum nisi in laboris\"\n },\n \"status\": -51137224,\n \"text\": \"ipsum culpa amet\"\n}" }, { "name": "Validation error", @@ -1035,7 +1035,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"count\": 96634001,\n \"price\": -71028444.15053315,\n \"symbol\": \"deserunt officia dolore\",\n \"time\": \"magna occaecat est\",\n \"user_id\": -71272721\n}", + "raw": "{\n \"count\": 76782033,\n \"price\": -9709838.042264134,\n \"symbol\": \"mollit esse ex in\",\n \"time\": \"2120-69-63T43:76:75.378Z\"\n}", "options": { "raw": { "language": "json" @@ -1063,7 +1063,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"labore\",\n \"\"\n ]\n }\n },\n \"message\": \"pariatur cillum qui aute\"\n}" + "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"anim quis\",\n \"in velit ali\"\n ]\n }\n },\n \"message\": \"nostrud\"\n}" }, { "name": "Authentication error", @@ -1078,7 +1078,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"count\": 96634001,\n \"price\": -71028444.15053315,\n \"symbol\": \"deserunt officia dolore\",\n \"time\": \"magna occaecat est\",\n \"user_id\": -71272721\n}", + "raw": "{\n \"count\": 76782033,\n \"price\": -9709838.042264134,\n \"symbol\": \"mollit esse ex in\",\n \"time\": \"2120-69-63T43:76:75.378Z\"\n}", "options": { "raw": { "language": "json" @@ -1106,7 +1106,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] }, @@ -1175,7 +1175,7 @@ } ], "cookie": [], - "body": "{\n \"data\": {\n \"count\": -19053100,\n \"price\": 39909986.26075193,\n \"symbol\": \"sit nisi\",\n \"time\": \"pariatur eu proident\",\n \"user_id\": 54782742\n },\n \"status\": 87070947,\n \"text\": \"null\"\n}" + "body": "{\n \"data\": {\n \"count\": -37878076,\n \"price\": -40419772.172105886,\n \"symbol\": \"velit ut Ut elit esse\",\n \"time\": \"5462-92-97T03:27:22.076Z\"\n },\n \"status\": -509477,\n \"text\": \"proident\"\n}" }, { "name": "Authentication error", @@ -1209,7 +1209,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] } @@ -1283,7 +1283,7 @@ } ], "cookie": [], - "body": "{\n \"data\": {\n \"value\": \"reference #/components/schemas/200 not found in the OpenAPI spec\"\n },\n \"status\": 14426134,\n \"text\": \"velit in ad dolore\"\n}" + "body": "{\n \"data\": [\n {\n \"count\": 75537465,\n \"last_transaction\": \"dolor enim\",\n \"symbol\": \"enim nostrud non deserunt\"\n },\n {\n \"count\": -69490418,\n \"last_transaction\": \"et\",\n \"symbol\": \"Excepteur irure est enim\"\n }\n ],\n \"status\": 7099250,\n \"text\": \"dolore in ad\"\n}" }, { "name": "Authentication error", @@ -1317,7 +1317,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] } @@ -1352,7 +1352,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"username\": \"aliqua dolor do\"\n}", + "raw": "{\n \"email\": \"HqkZQ@KMWQFPMhWGvBHrdzOdOampAHweUvPCej.kvbl\"\n}", "options": { "raw": { "language": "json" @@ -1385,7 +1385,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"username\": \"aliqua dolor do\"\n}", + "raw": "{\n \"email\": \"HqkZQ@KMWQFPMhWGvBHrdzOdOampAHweUvPCej.kvbl\"\n}", "options": { "raw": { "language": "json" @@ -1428,7 +1428,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"username\": \"aliqua dolor do\"\n}", + "raw": "{\n \"email\": \"HqkZQ@KMWQFPMhWGvBHrdzOdOampAHweUvPCej.kvbl\"\n}", "options": { "raw": { "language": "json" @@ -1456,7 +1456,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"cupidatat mollit laborum aute\",\n \"aute in laboris dolor\"\n ]\n }\n },\n \"message\": \"in dolore exercitation eu elit\"\n}" + "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"anim quis\",\n \"in velit ali\"\n ]\n }\n },\n \"message\": \"nostrud\"\n}" }, { "name": "Authentication error", @@ -1471,7 +1471,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"username\": \"aliqua dolor do\"\n}", + "raw": "{\n \"email\": \"HqkZQ@KMWQFPMhWGvBHrdzOdOampAHweUvPCej.kvbl\"\n}", "options": { "raw": { "language": "json" @@ -1499,7 +1499,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] }, @@ -1568,7 +1568,7 @@ } ], "cookie": [], - "body": "{\n \"data\": {\n \"admin\": false,\n \"password\": \"voluptate magna esse\",\n \"telegram_name\": \"id\",\n \"user_id\": -55336867,\n \"username\": \"do exercitation\"\n },\n \"status\": -11469710,\n \"text\": \"aute\"\n}" + "body": "{\n \"data\": {\n \"admin\": false,\n \"email\": \"VNB@NeqjbTmHnkWDwPacdUoXgpYVTNlD.iip\",\n \"password\": \"fugiat ipsum\",\n \"telegram_user_id\": \"et\",\n \"username\": \"nostrud laborum\"\n },\n \"status\": -78288268,\n \"text\": \"laborum minim\"\n}" }, { "name": "Authentication error", @@ -1602,7 +1602,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] }, @@ -1632,7 +1632,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"password\": \"ut minim\",\n \"username\": \"esse sit enim consectetur\"\n}", + "raw": "{\n \"password\": \"elit do in esse\",\n \"username\": \"mollit velit sed reprehenderit\"\n}", "options": { "raw": { "language": "json" @@ -1665,7 +1665,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"password\": \"ut minim\",\n \"username\": \"esse sit enim consectetur\"\n}", + "raw": "{\n \"password\": \"elit do in esse\",\n \"username\": \"mollit velit sed reprehenderit\"\n}", "options": { "raw": { "language": "json" @@ -1708,7 +1708,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"password\": \"ut minim\",\n \"username\": \"esse sit enim consectetur\"\n}", + "raw": "{\n \"password\": \"elit do in esse\",\n \"username\": \"mollit velit sed reprehenderit\"\n}", "options": { "raw": { "language": "json" @@ -1736,7 +1736,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"labore\",\n \"\"\n ]\n }\n },\n \"message\": \"pariatur cillum qui aute\"\n}" + "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"anim quis\",\n \"in velit ali\"\n ]\n }\n },\n \"message\": \"nostrud\"\n}" }, { "name": "Authentication error", @@ -1751,7 +1751,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"password\": \"ut minim\",\n \"username\": \"esse sit enim consectetur\"\n}", + "raw": "{\n \"password\": \"elit do in esse\",\n \"username\": \"mollit velit sed reprehenderit\"\n}", "options": { "raw": { "language": "json" @@ -1779,7 +1779,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] }, @@ -1799,7 +1799,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"password\": \"ut minim\",\n \"username\": \"esse sit enim consectetur\"\n}", + "raw": "{\n \"email\": \"YKQkCdcOoJ3vH@wbOpjGTXH.avm\",\n \"password\": \"veniam\"\n}", "options": { "raw": { "language": "json" @@ -1827,7 +1827,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"password\": \"ut minim\",\n \"username\": \"esse sit enim consectetur\"\n}", + "raw": "{\n \"email\": \"YKQkCdcOoJ3vH@wbOpjGTXH.avm\",\n \"password\": \"veniam\"\n}", "options": { "raw": { "language": "json" @@ -1856,7 +1856,7 @@ } ], "cookie": [], - "body": "{\n \"data\": {\n \"token\": \"minim\"\n },\n \"status\": 86563099,\n \"text\": \"non tempor quis ullamco est\"\n}" + "body": "{\n \"data\": {\n \"token\": \"do ipsu\"\n },\n \"status\": 31961350,\n \"text\": \"Lorem dolor commodo laborum cillum\"\n}" }, { "name": "Validation error", @@ -1865,7 +1865,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"password\": \"ut minim\",\n \"username\": \"esse sit enim consectetur\"\n}", + "raw": "{\n \"email\": \"YKQkCdcOoJ3vH@wbOpjGTXH.avm\",\n \"password\": \"veniam\"\n}", "options": { "raw": { "language": "json" @@ -1894,7 +1894,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"labore\",\n \"\"\n ]\n }\n },\n \"message\": \"pariatur cillum qui aute\"\n}" + "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"anim quis\",\n \"in velit ali\"\n ]\n }\n },\n \"message\": \"nostrud\"\n}" } ] }, @@ -1914,7 +1914,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"password\": \"ut minim\",\n \"username\": \"esse sit enim consectetur\"\n}", + "raw": "{\n \"email\": \"DJR029Ov-keM@pyhCxnpZmcVMxADSiCjmsGRZksCf.zz\",\n \"password\": \"sed voluptate\",\n \"username\": \"voluptate aute proident\"\n}", "options": { "raw": { "language": "json" @@ -1942,7 +1942,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"password\": \"ut minim\",\n \"username\": \"esse sit enim consectetur\"\n}", + "raw": "{\n \"email\": \"DJR029Ov-keM@pyhCxnpZmcVMxADSiCjmsGRZksCf.zz\",\n \"password\": \"sed voluptate\",\n \"username\": \"voluptate aute proident\"\n}", "options": { "raw": { "language": "json" @@ -1971,7 +1971,7 @@ } ], "cookie": [], - "body": "{\n \"data\": {\n \"admin\": false,\n \"password\": \"voluptate magna esse\",\n \"telegram_name\": \"id\",\n \"user_id\": -55336867,\n \"username\": \"do exercitation\"\n },\n \"status\": -11469710,\n \"text\": \"aute\"\n}" + "body": "{\n \"data\": {\n \"admin\": false,\n \"email\": \"VNB@NeqjbTmHnkWDwPacdUoXgpYVTNlD.iip\",\n \"password\": \"fugiat ipsum\",\n \"telegram_user_id\": \"et\",\n \"username\": \"nostrud laborum\"\n },\n \"status\": -78288268,\n \"text\": \"laborum minim\"\n}" }, { "name": "Validation error", @@ -1980,7 +1980,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"password\": \"ut minim\",\n \"username\": \"esse sit enim consectetur\"\n}", + "raw": "{\n \"email\": \"DJR029Ov-keM@pyhCxnpZmcVMxADSiCjmsGRZksCf.zz\",\n \"password\": \"sed voluptate\",\n \"username\": \"voluptate aute proident\"\n}", "options": { "raw": { "language": "json" @@ -2009,7 +2009,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"labore\",\n \"\"\n ]\n }\n },\n \"message\": \"pariatur cillum qui aute\"\n}" + "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"anim quis\",\n \"in velit ali\"\n ]\n }\n },\n \"message\": \"nostrud\"\n}" } ] }, @@ -2039,7 +2039,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"admin\": true,\n \"username\": \"sunt\"\n}", + "raw": "{\n \"admin\": false,\n \"email\": \"qUgn5u1bWI4cwc@LjiesdFcoYwvweQto.dj\"\n}", "options": { "raw": { "language": "json" @@ -2073,7 +2073,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"admin\": true,\n \"username\": \"sunt\"\n}", + "raw": "{\n \"admin\": false,\n \"email\": \"qUgn5u1bWI4cwc@LjiesdFcoYwvweQto.dj\"\n}", "options": { "raw": { "language": "json" @@ -2117,7 +2117,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"admin\": true,\n \"username\": \"sunt\"\n}", + "raw": "{\n \"admin\": false,\n \"email\": \"qUgn5u1bWI4cwc@LjiesdFcoYwvweQto.dj\"\n}", "options": { "raw": { "language": "json" @@ -2146,7 +2146,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"labore\",\n \"\"\n ]\n }\n },\n \"message\": \"pariatur cillum qui aute\"\n}" + "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"anim quis\",\n \"in velit ali\"\n ]\n }\n },\n \"message\": \"nostrud\"\n}" }, { "name": "Authentication error", @@ -2161,7 +2161,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"admin\": true,\n \"username\": \"sunt\"\n}", + "raw": "{\n \"admin\": false,\n \"email\": \"qUgn5u1bWI4cwc@LjiesdFcoYwvweQto.dj\"\n}", "options": { "raw": { "language": "json" @@ -2190,7 +2190,7 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] }, @@ -2259,7 +2259,7 @@ } ], "cookie": [], - "body": "{\n \"data\": [\n {\n \"admin\": true,\n \"password\": \"incididunt id dolore\",\n \"telegram_name\": \"id sed\",\n \"user_id\": 15906508,\n \"username\": \"dolor consequat ullamco\"\n },\n {\n \"admin\": true,\n \"password\": \"voluptate non\",\n \"telegram_name\": \"dolor sunt fugiat exercitation\",\n \"user_id\": 95246024,\n \"username\": \"Duis qui culpa Ut labore\"\n }\n ],\n \"status\": 81180129,\n \"text\": \"in ullamco\"\n}" + "body": "{\n \"data\": [\n {\n \"admin\": false,\n \"email\": \"paghoo4COL6gQNz@SJXcMSOC.kus\",\n \"password\": \"exercitation laboris Ut cillum nisi\",\n \"telegram_user_id\": \"id in incididunt sint\",\n \"username\": \"sed laborum cill\"\n },\n {\n \"admin\": false,\n \"email\": \"WFYb2q0XXey6WZa@JNSezyFkIVzneuifIXi.la\",\n \"password\": \"velit irure veniam\",\n \"telegram_user_id\": \"pariatur sed commodo\",\n \"username\": \"incididunt consequat\"\n }\n ],\n \"status\": -92106336,\n \"text\": \"commodo ull\"\n}" }, { "name": "Authentication error", @@ -2293,7 +2293,189 @@ } ], "cookie": [], - "body": "{\n \"detail\": {},\n \"message\": \"eiusmod enim ipsum\"\n}" + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" + } + ] + } + ] + }, + { + "name": "Telegram", + "item": [ + { + "name": "Connects telegram user id", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"telegram_user_id\": \"do quis\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/api/telegram", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "telegram" + ] + }, + "description": "Connects telegram user id to user account" + }, + "response": [ + { + "name": "Successful response", + "originalRequest": { + "method": "POST", + "header": [ + { + "description": "Added as a part of security scheme: bearer", + "key": "Authorization", + "value": "Bearer " + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"telegram_user_id\": \"do quis\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/api/telegram", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "telegram" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"data\": {\n \"admin\": false,\n \"email\": \"VNB@NeqjbTmHnkWDwPacdUoXgpYVTNlD.iip\",\n \"password\": \"fugiat ipsum\",\n \"telegram_user_id\": \"et\",\n \"username\": \"nostrud laborum\"\n },\n \"status\": -78288268,\n \"text\": \"laborum minim\"\n}" + }, + { + "name": "Validation error", + "originalRequest": { + "method": "POST", + "header": [ + { + "description": "Added as a part of security scheme: bearer", + "key": "Authorization", + "value": "Bearer " + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"telegram_user_id\": \"do quis\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/api/telegram", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "telegram" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"detail\": {\n \"\": {\n \"\": [\n \"velit\",\n \"ut laboris\"\n ]\n }\n },\n \"message\": \"dolore nostrud officia ex\"\n}" + }, + { + "name": "Authentication error", + "originalRequest": { + "method": "POST", + "header": [ + { + "description": "Added as a part of security scheme: bearer", + "key": "Authorization", + "value": "Bearer " + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"telegram_user_id\": \"do quis\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/api/telegram", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "telegram" + ] + } + }, + "status": "Unauthorized", + "code": 401, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"detail\": {},\n \"message\": \"irure ad do quis\"\n}" } ] } diff --git a/documentation/database/structure_database.pdf b/documentation/database/structure_database.pdf deleted file mode 100644 index fdd0a10..0000000 Binary files a/documentation/database/structure_database.pdf and /dev/null differ diff --git a/documentation/database/structure_database.png b/documentation/database/structure_database.png new file mode 100644 index 0000000..d7d459d Binary files /dev/null and b/documentation/database/structure_database.png differ diff --git a/documentation/database/structure_database.uxf b/documentation/database/structure_database.uxf index 6702c2a..3f3aaf2 100644 --- a/documentation/database/structure_database.uxf +++ b/documentation/database/structure_database.uxf @@ -1,105 +1,26 @@ - - - 10 - - UMLClass - - 580 - 320 - 210 - 80 - - Stichwort +10Database V0.1UMLClass70536021080keywords -- -PK: s_id -FK: username -Stichwort - - - - UMLClass - - 580 - 100 - 210 - 130 - - User +PK: s_id int(11) +FK: email varchar(255) +keyword varchar(255)UMLClass425240210130users -- -PK: username -password -user_id -telegramname -Rolle - - - - - UMLClass - - 930 - 80 - 210 - 90 - - Aktie +PK: email varchar(255) +password varchar(255) +username varchar(255) +telegram_user_id varchar(255) +admin tinyint(1) +UMLClass70515021070shares -- -PK: a_id -FK: username -Aktiensymbol - - - - - UMLClass - - 200 - 320 - 210 - 130 - - Transaktion +PK: a_id int(11) +FK: email varchar(255) +symbol varchar(255) +UMLClass135150210130transaction -- -PK: t_id -FK: username -FK: Aktiensymbol -Zeitpunkt -Anzahl(+/-) -Preis(+/-) - - - - - Relation - - 780 - 120 - 170 - 30 - - lt=<- - 150.0;10.0;10.0;10.0 - - - Relation - - 400 - 120 - 200 - 260 - - lt=<- - 10.0;240.0;180.0;10.0 - - - Relation - - 510 - 200 - 90 - 190 - - lt=<- - 70.0;170.0;10.0;10.0 - - +PK: t_id int(11) +FK: email varchar(255) +symbol varchar(255) +time datetime +count int(11) +price float +Relation335190110100lt=<<- +group=110;10;60;10;60;80;90;80Relation625190100100lt=<<-80;10;50;10;50;80;10;80Relation625260100160lt=<<-80;140;50;140;50;10;10;10UMLClass14041010030Database V0.1 \ No newline at end of file