This commit is contained in:
h z
2024-12-02 19:50:34 +00:00
parent 83c5662fcb
commit 5557b3434b
7 changed files with 94 additions and 15 deletions

View File

@@ -2,6 +2,8 @@
from flask import Blueprint, session, redirect, url_for, jsonify from flask import Blueprint, session, redirect, url_for, jsonify
from authlib.integrations.flask_client import OAuth from authlib.integrations.flask_client import OAuth
import env_provider import env_provider
import logging
logger = logging.getLogger(__name__)
auth_bp = Blueprint('auth', __name__, url_prefix='/api') auth_bp = Blueprint('auth', __name__, url_prefix='/api')
oauth = OAuth() oauth = OAuth()
@@ -26,10 +28,13 @@ def authorize():
session['user'] = user_info session['user'] = user_info
return jsonify({"message": "login successful", "user": user_info}) return jsonify({"message": "login successful", "user": user_info})
except Exception as e: except Exception as e:
logger.error(f"Authorization failed: {str(e)}")
return jsonify({"error": "Authorization failed"}), 401 return jsonify({"error": "Authorization failed"}), 401
@auth_bp.route('/logout', methods=['GET']) @auth_bp.route('/logout', methods=['GET'])
def logout(): def logout():
session.pop('user', None) u = session.pop('user', None)
if u:
logger.info(f"Logged out user: {u}")
logout_url = "https://login.hangman-lab.top/auth/realms/Hangman-Lab/protocol/openid-connect/logout" logout_url = "https://login.hangman-lab.top/auth/realms/Hangman-Lab/protocol/openid-connect/logout"
return redirect(logout_url) return redirect(logout_url)

43
api/log.py Normal file
View File

@@ -0,0 +1,43 @@
#api/log.py
from flask import Blueprint, jsonify, request
from db import get_db
from db.models.Log import Log
from db.utils import insert_log
logs_bp = Blueprint('log', __name__, url_prefix='/api/log')
@logs_bp.route('/', methods=['GET'])
def get_logs():
level = request.args.get('level')
application = request.args.get('application')
page = int(request.args.get('page', 1))
per_page = int(request.args.get('per_page', 10))
with get_db() as db:
query = db.query(Log)
if level:
query = query.filter(Log.level == level)
if application:
query = query.filter(Log.application == application)
total_logs = query.count()
logs = query.order_by(Log.timestamp.desc()).offset((page - 1)*per_page).limit(per_page).all()
return jsonify({
"total": total_logs,
"page": page,
"per_page": per_page,
"logs": [log.to_dict() for log in logs]
})
@logs_bp.route('/', methods=['POST'])
def create_log():
data = request.json
required_fields = ['level', 'message']
for field in required_fields:
if field not in data:
return jsonify({"error": f"missing {field} in request"}), 400
level = data.get('level')
message = data.get('message')
application = "frontend"
extra = data.get('extra', None)
log_entry = Log(level=level, message=message, application=application, extra=extra)
insert_log(log_entry)

View File

@@ -2,6 +2,8 @@
from flask import Blueprint, request, jsonify from flask import Blueprint, request, jsonify
from db import get_db from db import get_db
from db.models.Markdown import Markdown from db.models.Markdown import Markdown
import logging
logger = logging.getLogger(__name__)
markdown_bp = Blueprint('markdown', __name__, url_prefix='/api/markdown') markdown_bp = Blueprint('markdown', __name__, url_prefix='/api/markdown')
@@ -23,9 +25,14 @@ def create_markdown():
return jsonify({"error": "missing required fields"}), 400 return jsonify({"error": "missing required fields"}), 400
new_markdown = Markdown(title=title, content=content, path=path) new_markdown = Markdown(title=title, content=content, path=path)
with get_db() as db: with get_db() as db:
db.add(new_markdown) try:
db.commit() db.add(new_markdown)
return jsonify(new_markdown.to_dict()), 201 db.commit()
return jsonify(new_markdown.to_dict()), 201
except Exception as e:
logger.error(f"failed to create markdown: {e}")
db.rollback()
return jsonify({"error": "create failed"}), 500
@markdown_bp.route('/<int:markdown_id>', methods=['PUT']) @markdown_bp.route('/<int:markdown_id>', methods=['PUT'])
def update_markdown(markdown_id): def update_markdown(markdown_id):

23
app.py
View File

@@ -1,13 +1,25 @@
# app.py # app.py
from urllib.parse import urlparse from urllib.parse import urlparse
from flask import Flask from flask import Flask, request
from flask_cors import CORS from flask_cors import CORS
import env_provider import env_provider
import db import db
from api.auth import auth_bp from api.auth import auth_bp
from api.log import logs_bp
from api.markdown import markdown_bp from api.markdown import markdown_bp
import logging
from logging_handlers.DatabaseLogHandler import DatabaseLogHandler
logger = logging.getLogger(__name__)
db_handler = DatabaseLogHandler(application="backend")
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
db_handler.setFormatter(formatter)
logger.addHandler(db_handler)
logger.setLevel(logging.INFO)
def is_allowed_origin(origin): def is_allowed_origin(origin):
parsed_origin = urlparse(origin) parsed_origin = urlparse(origin)
@@ -26,5 +38,14 @@ CORS(app, resources={r"/api/*": {"origins": is_allowed_origin}})
app.register_blueprint(markdown_bp) app.register_blueprint(markdown_bp)
app.register_blueprint(auth_bp) app.register_blueprint(auth_bp)
app.register_blueprint(logs_bp)
@app.before_request
def log_request():
if request.path.startswith("/api/log"):
return
logger.info(f"Request received: {request.method} {request.path} from {request.remote_addr}")
if __name__ == '__main__': if __name__ == '__main__':
logger.info("Starting app")
app.run(host='0.0.0.0', port=5000) app.run(host='0.0.0.0', port=5000)

View File

@@ -1,16 +1,17 @@
#db/models/BackendLog.py #db/models/Log.py
from sqlalchemy import Column, Integer, String, DateTime, Text from sqlalchemy import Column, Integer, String, DateTime, Text
from db.models import Base from db.models import Base
import datetime import datetime
class BackendLog(Base): class Log(Base):
__tablename__ = 'backend_log' __tablename__ = 'log'
id = Column(Integer, primary_key=True, autoincrement=True) id = Column(Integer, primary_key=True, autoincrement=True)
level = Column(String(50), nullable=False) level = Column(String(50), nullable=False)
message = Column(Text, nullable=False) message = Column(Text, nullable=False)
timestamp = Column(DateTime, nullable=False) timestamp = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
extra = Column(Text, nullable=True) extra = Column(Text, nullable=True)
application = Column(String(50), nullable=False)
def to_dict(self): def to_dict(self):
return { return {
"id": self.id, "id": self.id,
@@ -18,4 +19,5 @@ class BackendLog(Base):
"message": self.message, "message": self.message,
"timestamp": self.timestamp, "timestamp": self.timestamp,
"extra": self.extra, "extra": self.extra,
"application": self.application,
} }

View File

@@ -1,9 +1,7 @@
#db/utils.py #db/utils.py
from db import get_db from db import get_db
from db.models.BackendLog import BackendLog
def insert_backend_log(level, message, extra=None): def insert_log(log_entry):
log_entry = BackendLog(level=level, message=message, extra=extra)
with get_db() as db: with get_db() as db:
db.add(log_entry) db.add(log_entry)
db.commit() db.commit()

View File

@@ -3,14 +3,17 @@
import logging import logging
import traceback import traceback
from db import get_db from db import get_db
from db.models.BackendLog import BackendLog from db.models.Log import Log
class DatabaseLogHandler(logging.Handler): class DatabaseLogHandler(logging.Handler):
def __init__(self, application="backend"):
super().__init__()
self.application = application
def emit(self, record): def emit(self, record):
message = self.format(record) message = self.format(record)
level = record.levelname level = record.levelname
extra = getattr(record, 'extra', None) extra = str(getattr(record, 'extra', None)) if hasattr(record, 'extra') else None
log_entry = BackendLog(message=message, level=level, extra=extra) log_entry = Log(message=message, level=level, application=self.application, extra=extra)
try: try:
with get_db() as db: with get_db() as db:
db.add(log_entry) db.add(log_entry)