From 12d59d69ff80641855bfaa2bd52c8b45d053370d Mon Sep 17 00:00:00 2001 From: H4CK3R-01 Date: Sun, 27 Mar 2022 17:23:33 +0200 Subject: [PATCH 1/4] Changed database model --- api/api_blueprint_keyword.py | 25 +++++---- api/api_blueprint_portfolio.py | 23 ++++---- api/api_blueprint_shares.py | 25 +++++---- api/api_blueprint_transactions.py | 14 ++--- api/api_blueprint_user.py | 89 +++++++++++++++---------------- api/app.py | 18 +++---- api/auth.py | 2 +- api/helper_functions.py | 37 ++++++------- api/models.py | 12 ++--- api/schema.py | 45 +++++++++++++--- 10 files changed, 160 insertions(+), 130 deletions(-) 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_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..4e1dfa3 100644 --- a/api/app.py +++ b/api/app.py @@ -7,11 +7,7 @@ from flask_cors import CORS 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(): @@ -38,20 +34,22 @@ def create_app(): 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 From 62d66c1d6f4093ea5db25b72ab33b83c369e19b5 Mon Sep 17 00:00:00 2001 From: H4CK3R-01 Date: Sun, 27 Mar 2022 17:24:26 +0200 Subject: [PATCH 2/4] Added endpoint to set telegram user id --- api/api_blueprint_telegram.py | 42 +++++++++++++++++++++++++++++++++++ api/app.py | 6 +++++ 2 files changed, 48 insertions(+) create mode 100644 api/api_blueprint_telegram.py 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/app.py b/api/app.py index 4e1dfa3..1132b2e 100644 --- a/api/app.py +++ b/api/app.py @@ -5,6 +5,11 @@ 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_user import users_blueprint @@ -29,6 +34,7 @@ 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(): From 634bc4835dd47530be284c575d17829dab4f9c5a Mon Sep 17 00:00:00 2001 From: H4CK3R-01 Date: Sun, 27 Mar 2022 17:50:28 +0200 Subject: [PATCH 3/4] Updated database model --- documentation/database/structure_database.pdf | Bin 1874 -> 0 bytes documentation/database/structure_database.png | Bin 0 -> 38191 bytes documentation/database/structure_database.uxf | 123 ++++-------------- 3 files changed, 22 insertions(+), 101 deletions(-) delete mode 100644 documentation/database/structure_database.pdf create mode 100644 documentation/database/structure_database.png diff --git a/documentation/database/structure_database.pdf b/documentation/database/structure_database.pdf deleted file mode 100644 index fdd0a10cc3d434febb82b15e71dfc2b240f8f22b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1874 zcmaJ?Yfuwc6fOgm8Wj))v5G7j5X#^_@*trYAcR18NJtP-UT%^NL`Z_k62So!L8S#1 z1Z<%&=%|#3yb%;ftqeG*1srs$fTH*;iin8Cs>SXiPO9zn{<-&l_nfoe`OciPc0wNC z8D2xD*xkF|dyPT|AV4kILUD5g`HFZP(}4VV6vud&R4v2608ABw#{w)D28W}?H5jU- zB$ae-2o4&A%+jXn##hC*-;DWo|J21}>CKA1!=?7h0I_kpvRneyoV9LMRd zojW}0mhEYEZ+PxbJ>T&#e9>h1xuZ%C4R&b(&b3{cb@;Ts|0YcmB7E1@Q99Ceihrg) zV(Ec9U54k{Z6(4ygB>mvEeHD7&kvet%2$TXS-eOX@ZADwdxpE)#nmX5Eb<)_W zK7cwtTwv{MdpxAr6udc<02db?9egO`4B89<3x;^7@5(92CgJXaG^1M$TEkx|3e5YM z%RC;ufA_*Udb%W{`V+T6wO~X7~$6=@olL+-ld$ZI>b-i;wXweQJzx0 z<$HQnWYA5YP=W4xpUJ}*VZ=aQbh$ZYVY)5vw>frC=S_GS_jw$m=L@2T&0woS-wK1) zglA3m=arRjF86L`E8YgARl+G3nv`W(o~3c(N{}yOR`>cI>}h*bylyDmHIIMNq9Wi) z=eDDbDJ5Xk5;%CLx-#f=h-5LZ?3*m3Gt`B*K4!-_gAz|ME)@a&A@i0+2riVcsfTu0@(3R6Go`^LJ_mNHourYxwes;6~ZKUsGzXZhRO^h_>~ZGhB% z(cCsx98jOTII7+zporOEJwVMg81S@mlYZHrJYZzaNQgHaT3GkPuJYibc_|gmoA*{4 z3I}V%H(J)MHF3E*XFzw%^=MD2bY59-IDGY=3ZhwQU z<+{=&`==eH)%n>D=cq&t+eF(Mu8M0L&>CzEUo*be;(bx9@z+b7#LBDP!8giQOShQ) zPQg^N*{&l_WS27a-Rh-Q;g|~70%Qk^z>wqw3>2a<7%0ND>O_qc(-JK$)TpIm3@J7|y_0YsF-|l;;piiV0eB{`j~D?E^2FhQeBztrpnw6| z2ZX?csD_{cFlLMcF_{A8s*}PY;>u=003C)RIUF((l0NA*J8Z;>5}c$=@`gXKC!>R0 zREy0Ve6e^PhAX5f=&d4VkwO&%ZcwN^Ra(WzyFM<-Z#J$J1z`OHnS%ZS(m#-NXCM5D zjtM7)6-DY*)Pi2>L?W$!#B$NQ%!uuU;%K}&W=3@Fhy3;NS$g9@wTwrI>cDeFAOwME zFb#oV7-2a<@M;KJ?Ff1ia}`&pRsU~Alv0)`#WW5IvWm3;V-0-`3{)Zz1UVA{5daRM zg@pjzP_8Es;o#{b3~<(A8Z8kw!qHJrEJ=gODMW23gx~A}m<$Gu0my+_3`UrQZsY<~ zdW=R$^ce=zi8MdOAP6R;{S+f|{g*GqW)OOQW=Es_2gV|b`_T^9po(}*L;kD;D!CdU zRThB)9uV#(k+NwR%777!iP6|7o5qmQnRF(~lC#(>CIjKPF=Y~%fx?&+W6>cx6M``Y zB4@A=x}3>|P__#v5)`S`I6&4}1d0{gF@R0zW;dg^^NidSEskpN83|!RGK!s@cMzZQ EH-T`x>;M1& diff --git a/documentation/database/structure_database.png b/documentation/database/structure_database.png new file mode 100644 index 0000000000000000000000000000000000000000..d7d459d1b9e71e0d75fd6f7a1b955ba34ea40f17 GIT binary patch literal 38191 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 z (NRWtHMuz5nn_T=+Tzl%?#1x4Fl z%W@V`q#4CQ%ZPeNFk57=86?qgXD^z%`ffZ50*V}woCBe zwTayV5A)_|l}9B1Tfq>LKMt#6MYOr z|19?E4hw&cEj2*{d!vr91xYtuf^GgjF%BNlQb@$hAiHQVI{5J)pg1eN-(v8=zb8JR z@7mPjI!vmYz_y;1I~slp6^~Rm;$4#eMD?0C0Juf+aBvm$xG%jKkz#scVI1uVV8OUP zQT-SkSvqx|6$5Aw%sVN3Q-9@|Acjj3poD%wl)V+BD)+mO+eL1zh3$mwmox(r^!G1U z++P)2@5lXpt!PPTKTFl$eJ>aqh~nmFK=e468LrB)dGrNG3w z{{I%vPq|a2$CAEARL4x+nC5w?Z{T5>4mVe07I9G0pe-%eFhH^#9f89spkudKI zbUzg7+mxQ%lbd!d6zcSGWDnD&s@ijCD~mY#rCi=Bg-MmT%KwO^-!cPy(mjvD3}D95 zF;1suoD2JHG(-0?_|PUnhz zNIKsGEXA->2ncu~g}XfYXzCd`-^d+JP|9r94fFvy_;7I_u?AK-oyl7Dn44=15!5X( zsK*|$-YLhx-|-9Vlie-a;~dxsUKSR?`pw3MJDDwizFzrb9`<9ailfZGXPr5PQ*E6w z#<}cyk@dI)n+N;+^4x78u}?s^qwvlW`usaffu_iIdw`;Go9x!$`t6>yNWYV4wP=QD zb!;MPF2h$l?1R7;m~*;?bAAjWVr#uaA?4yWDJ!x9o4DUtSFf& z_#2`5pwLaV; z8p43XyERw1WU755Tn0FA`8SMYGTFov zsQl#Hq3r!~q8Tbrf89%g;YRx}1qRmG=Nj!y&8Yy1jfA%J>*L??#KgV8g*Sop$V6`~ z<4tQb8cs0=Vz73uy1;cEqGh+MraFp^u+&ak-Kok$ucZQBZD=>9pC_&f)Q2(a@sUR& z^s(6Ra2Co_*On}ONG0;|SE5)3>T2ohJtEVHsVM6!IqUTAAdT6X_-7Y7X1JOQ4?_~b z(Dpjcuj&o`v4xQfAF>TupJyUIFvOT7P)Z3jnZCKy&wIM4a(Y~l|J7j_Zv@)qZqRd2 zWTA;x24>C@kmLa4jeKz?Sn4yvjmH04APbdnV=Rt!z4=-d(B8X`DB|$ZYg{&hj!NC= zTuTT?!LVo%qZY?DcwTj#kCp0g)#yl@?2b%~p4_QsD`R#Zac_h#iN!;!@kq#%?$*Hj z<8^Xq9#QcMX5r8BETh^~H7$ry>xMn?m2P!!B6q(TWAj8$dHd3U$Wzr?*a>Z`rHO+4 z45{$Oh*d+{HJ)w6Z^cqXJc z>;5LLt+Uz_xZlcP!M%|^M+I`;k2MRtuRlfpJF`gb8uK)mXr9|zZG(J$rRR}Mg*qc9 zD}B`7CN+qb`?&v%F!@EjhQDVk$(NX7sl45WXc@~}Q!o(ZlAGTrL9tA5ygwi`W;#uD zHGOf2$2|SU`Rf}u_?^(h)(r~@3gVOgoiHsPXCXyXwX|CpKAEm6PQNj&N422;fix1O zyd&Ku$1jvuztlCAa1C!8--&AgotztCbO>kDpxgfky75fhpVQidH2OSXi3dx`cmhZN z@$uYfx$x<0$O~E`Bts)I80-7DR-dHF3$_c~I|p+)J@f_%OpxQX@^|r>2>R?KLNfjI z-swNpR(pnoi_fo*IA5efZ<>DD-(M|Yc1UcEytjUqzFtURa0Itd`UjLGLns7k7mVYD zCu^C;j65lt7Hh<@2)mgBZCP#J{7Evj_)X=VIb)y_Uw@q%yhBv3f-tUUirpC3H}qRj zhE@{ecy~IT$d6{GEoPibG={e=uwH zAIEO9xnp@Hb6+ao;ScF;AH4PtHzAX=r)*xa@yTm1BNKT;x9?wH)oa*tk*7dOvz!xCq}yzwCE z$y9dQZi8UYe|1tkZCh{7jKBCxq4@ElXWC>KMDy~z@<_<0!OJ4s-^3hXzl{`gR_hP4 z-!`&a#Up;`gYo^wy%hsT6G%{rQxwP7S-RMl!UEd0(b4b1S-}vFn4%)DS@@+9-_phh zEQf)$KBN!o1=brC?B+cDY0f;_&Q({-7ZVy`Ds~B-3>KM*CpR z6!{zq(;qorDe*Xu1G;m0f9iQG!)OmkbnDD}wT2~5K%CG<-FIxyz5@;2WvC+B1xYej zE_XFh)J+NA5b|k7s1JUhEhVpY%b2crUJt^F+2s8mzhkDOGL$ zj;*^Z;#LQqg)(lofHn_=BP!%*u2=&sW6C#Cdv}^WOxgjT_?T&u_~8Ub=Gs@CcyXzQ zYTrx?hz1%rzlt0;oucA>^$Ua!PQmdj&;ggB*)5^k4b49koDgT>2iV*pVSrzJ8FkPM!S1x3~&LR zx}M(O-yi2~l>eozeYrtsaOiO8(F-{+XBXbv_YA zzo#%~^}FVcWa$I35jjr7Z0$De{l7CUt#rYcAKRIl7*J8OA=ZxmTYE{5NY3=Js@`bA z(yx{S#guuI!m!v!9>#V*Pl7AwCHRw2801r$u`ue9jGzkmucJeA*^O0#XPtFJP3Y0E%_S;G6O zjvLOSE?b<}ySh2RM50H5F9xVmQA3W2TR9%BIzf?DRW5cUog7ya5D={p4UFZkIr1aG zCgKp^?jk-iN-J0{6aUQJJ#BYLGglV>tVUKF=1;eY_v~#19jwmL$UUbh$k;HYYS?g1a61f41=H?KA6To z(4yz^+Q5k-&RJ~P8=<-`_xN-YMYV)Cyt-n4Vc)C4Uc7{{+Q$nh?+dUwsqIUMgoMb1 z!wSO1GV9pP`!JMDj&v^JICatS3Pt-z9>r}KdgcIuY25xb0h2>4Ss%HNN5sK9oO^HX z$(eWALnT)*F8qBa7#)&OXbvvQ@Zg4i$j^`0ZT;mVYH+F~$VOCktlnOVH+JO1-Nt{7 zHY*Nr+d30~?p_@ra3sVBn&j?@-aPay+wEDVIae;(DfqLD0H(n06*2^$M`aZe$jVME4?2;Z>({zYGS^y!Z3~N<18F;pfG&W(p^O=Vf<=slSK6 zH@$-jpQsA$u)k^zC_KMVK1p zk^xg6C1$eSLwL;LLfF`Bkzc3ts?makFODmDH(tC;%+p4eQ`wTgvC}Zjf!pZ_j-&W;Nl(N+sbbcb8Uofa zZ-&y0{eFmy2?q$xTpd@gQc=#*=wM42*`GVZ8C|2IvQwEOGk7Ksr~Eij;6?kyr}@=m zYyZ_(`nc3jVNB=5J7Mz}UbdQWqQveecGK={mzbAEr$U5R7q78plY6&T{t~57czc@7pyCjFy6LJsxF{)X`hj!!b+8UEs~~=sfpM6$W}S1 zHbzLGG{uW^ahX)MZywrDSuZb|s;JK2W@v8hSFKBrP}y83$hB3N&bQH!vipi-k!=O_ zJNzd?TyXr{Axw?_xFut>+9@Zr=5EnZD(%;Z>O$#IST_uoNcolJ?(bf4f3!$}aLqM| zteUZ@qoP{b)+C5VRAkuqKXm5GNE08iImeRY^`O=@gh-D%W3fHNuiDKlos`9e!x4sz zN0{TyOM!;+fg{8+V=Tp(=pNfeK9|TAJWR%FXX%eE7t{lrn#$BIv6Yde1D9@XSpg1b z!>e+B@R(@zoyYs{e#veX96c`0Y(Cq{R~P6PaV*m9@G{TYshJ$#Bi(DL;?G*P?cZ;n zqjmJ=Fpk~N;4bJ5r0q1$UQb*mYG)5^{J|4U(!WPCSvizWAr1$~AOAiSK-8&qiFj@Q zE9Q;eE-9>?#a}S?4Mx%G@hSEvS|`4cR-WyKgV>)uuSQ1+8ts3I zU7y==o4~(=cA$fH)Lv^opz!ygE$l^FJ+l(uV1&xae@p)r0(4tf%=WZgP=;;`2=g*i zD)$6@+0|vavi}acfm*T~(OWLR+Wz;T3p~!p%RcFjKFhbC|5pte2tWg6kX)Fh8ft^W?P;)8>%xYKklUHf~GqD0kzUt>UP!j8w2{}$C#ve{Fur$~N1w{zv2(s0`;WK1fDlH - - 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 From 836c9f54cf9b60574bb0f800ae39324fc98b7156 Mon Sep 17 00:00:00 2001 From: H4CK3R-01 Date: Sun, 27 Mar 2022 17:57:22 +0200 Subject: [PATCH 4/4] Updated postman and openapi documentation --- documentation/api/openapi.json | 2 +- documentation/api/postman.json | 334 +++++++++++++++++++++++++-------- 2 files changed, 259 insertions(+), 77 deletions(-) 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}" } ] }