From 430cfad2772bd28b8cf1425414329069ba76c67c Mon Sep 17 00:00:00 2001 From: fakz9 Date: Sat, 25 Nov 2023 08:38:04 +0300 Subject: [PATCH] feat: admin panel --- .gitignore | 3 +- app.py | 3 +- database/models.py | 3 ++ routes/__init__.py | 1 + routes/admin.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++ routes/orders.py | 7 +++- 6 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 routes/admin.py diff --git a/.gitignore b/.gitignore index c32e659..be4fa47 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ __pycache__/ .env test.* test/ -apks/ \ No newline at end of file +apks/ +*.log \ No newline at end of file diff --git a/app.py b/app.py index 5b49938..6d1bd5e 100644 --- a/app.py +++ b/app.py @@ -20,7 +20,7 @@ migrate = Migrate(app, database.db) server_session = Session(app) # CORS config -CORS(app, supports_credentials=True) +CORS(app, expose_headers=["Content-Range", 'Authorization'], supports_credentials=True) jwt = JWTManager(app) blueprints = [ (routes.auth_blueprint, '/auth'), @@ -31,6 +31,7 @@ blueprints = [ (routes.general_blueprint, '/general'), (routes.application_blueprint, '/application'), (routes.sipro_blueprint, '/sipro'), + (routes.admin_blueprint, '/admin'), ] for blueprint, url_prefix in blueprints: diff --git a/database/models.py b/database/models.py index d6495fc..22399f1 100644 --- a/database/models.py +++ b/database/models.py @@ -11,6 +11,9 @@ class User(db.Model): password_hash = db.Column(db.String, nullable=False, comment='Пароль') sipro_id = db.Column(db.Integer, nullable=True, comment='ID пользователя в SIPRO') + is_admin = db.Column(db.Boolean, nullable=False, default=False, server_default='0', comment='Админ ли юзверь') + + city_id = db.Column(db.Integer, nullable=False, default='1', server_default='1', comment='ID страны') class Assembly(db.Model): diff --git a/routes/__init__.py b/routes/__init__.py index cdcdd1a..7be1b8b 100644 --- a/routes/__init__.py +++ b/routes/__init__.py @@ -6,3 +6,4 @@ from routes.assembly import assembly_blueprint from routes.general import general_blueprint from routes.application import application_blueprint from routes.sipro import sipro_blueprint +from routes.admin import admin_blueprint diff --git a/routes/admin.py b/routes/admin.py new file mode 100644 index 0000000..8bdac68 --- /dev/null +++ b/routes/admin.py @@ -0,0 +1,89 @@ +import json + +from flask import Blueprint, request, make_response, jsonify +from flask_jwt_extended import get_jwt_identity, verify_jwt_in_request +from werkzeug.security import generate_password_hash + +import database +import sipro.api.general + +admin_blueprint = Blueprint('admin', __name__) + + +@admin_blueprint.before_request +def admin_check(): + if request.method == 'OPTIONS': + return + if not verify_jwt_in_request(optional=True): + return {'error': 'Unauthorized'}, 401 + + user_id = get_jwt_identity() + is_admin = database.db.session.get(database.User, user_id).is_admin + if not is_admin: + return {'error': 'Unauthorized'}, 401 + + +def format_user(user: database.User): + return { + 'id': user.id, + 'login': user.login, + 'city_id': user.city_id, + 'is_admin': user.is_admin + } + + +@admin_blueprint.get('/ping') +def ping(): + return {"response": "pong"} + + +@admin_blueprint.get('/user') +def get_users(): + response = make_response(jsonify( + [format_user(user) for user in database.User.query.all()] + )) + + response.headers['Content-Range'] = 'user 0-1/1' + return response + + +@admin_blueprint.get('/user/') +def get_user(user_id): + user = database.db.session.get(database.User, user_id) + return format_user(user) + + +@admin_blueprint.put('/user/') +def put_user(user_id): + params: dict = request.json + password = params.get('password').strip() + if password: + params['password_hash'] = generate_password_hash(password) + del params['password'] + database.db.session.bulk_update_mappings(database.User, [params]) + database.db.session.commit() + user = database.db.session.get(database.User, user_id) + return format_user(user) + + +@admin_blueprint.get('/city') +def get_cities(): + filters = request.args.get('filter') + if filters: + filters = json.loads(filters) + else: + filters = {} + cities = sipro.api.general.get_cities() + for key, value in filters.items(): + match key: + case 'id': + cities = list(filter(lambda city: city['id'] in value, cities)) + total_cities = len(cities) + range_start, range_end = 0, total_cities - 1 + range_raw = request.args.get('range') + if range_raw: + range_start, range_end = json.loads(range_raw) + cities = cities[range_start:range_end + 1] + response = make_response(jsonify(cities)) + response.headers['Content-Range'] = f'city {range_start}-{range_end}/{total_cities}' + return response diff --git a/routes/orders.py b/routes/orders.py index 541e5fc..5aa8798 100644 --- a/routes/orders.py +++ b/routes/orders.py @@ -1,4 +1,7 @@ +import database from flask import Blueprint, jsonify, request +from flask_jwt_extended import get_jwt_identity + from routes.utils import jwt_protect_blueprint import sipro.api.orders @@ -30,8 +33,10 @@ def get_orders(): @orders_blueprint.get('/getByProductId') def get_orders_by_supplier_product_id(): + #user_id = get_jwt_identity() + #city_id = database.db.session.get(database.User, user_id).city_id params = dict(request.args) - # product_id = args.get('productId') + #params['city'] = city_id return sipro.api.orders.get_orders_from_barcode(params=params)