This commit is contained in:
h z
2024-12-02 18:33:39 +00:00
parent 72807d41c1
commit 83c5662fcb
14 changed files with 236 additions and 48 deletions

3
.gitignore vendored
View File

@@ -1 +1,2 @@
.env
.env
summerizer.py

1
api/__init__.py Normal file
View File

@@ -0,0 +1 @@
#api/__init__.py

42
api/auth.py Normal file
View File

@@ -0,0 +1,42 @@
#api/auth.py
from flask import Blueprint, session, redirect, url_for, jsonify
from authlib.integrations.flask_client import OAuth
import env_provider
auth_bp = Blueprint('auth', __name__, url_prefix='/api')
oauth = OAuth()
keycloak = oauth.register(
'keycloak',
client_id=env_provider.CLIENT_ID,
client_secret=env_provider.CLIENT_SECRET,
server_metadata_url="https://login.hangman-lab.top/auth/realms/Hangman-Lab/.well-known/openid-configuration",
client_kwargs={"scope": "openid email profile"},
)
@auth_bp.route('/login', methods=['GET'])
def login():
redirect_uri = url_for("auth.authorize", _external=True)
return keycloak.authorize_redirect(redirect_uri)
@auth_bp.route('/authorize', methods=['GET'])
def authorize():
try:
token = keycloak.authorize_access_token()
user_info = keycloak.parse_id_token(token)
session['user'] = user_info
return jsonify({"message": "login successful", "user": user_info})
except Exception as e:
return jsonify({"error": "Authorization failed"}), 401
@auth_bp.route('/logout', methods=['GET'])
def logout():
session.pop('user', None)
logout_url = "https://login.hangman-lab.top/auth/realms/Hangman-Lab/protocol/openid-connect/logout"
return redirect(logout_url)
@auth_bp.route("/user", methods=["GET"])
def user():
u = session.get('user')
if not u:
return jsonify({"username": "guest", "role": "guest"})
return jsonify(u)

51
api/markdown.py Normal file
View File

@@ -0,0 +1,51 @@
#api/markdown.py
from flask import Blueprint, request, jsonify
from db import get_db
from db.models.Markdown import Markdown
markdown_bp = Blueprint('markdown', __name__, url_prefix='/api/markdown')
@markdown_bp.route('/<int:markdown_id>', methods=['GET'])
def get_markdown(markdown_id):
with get_db() as db:
markdown = db.query(Markdown).get(markdown_id)
if markdown is None:
return jsonify({"error": "file not found"}), 404
return jsonify(markdown.to_dict())
@markdown_bp.route('/', methods=['POST'])
def create_markdown():
data = request.json
title = data.get('title')
content = data.get('content')
path = data.get('path')
if not title or not content:
return jsonify({"error": "missing required fields"}), 400
new_markdown = Markdown(title=title, content=content, path=path)
with get_db() as db:
db.add(new_markdown)
db.commit()
return jsonify(new_markdown.to_dict()), 201
@markdown_bp.route('/<int:markdown_id>', methods=['PUT'])
def update_markdown(markdown_id):
with get_db() as db:
markdown = db.query(Markdown).get(markdown_id)
if markdown is None:
return jsonify({"error": "file not found"}), 404
data = request.json
markdown.title = data.get('title')
markdown.content = data.get('content')
markdown.path = data.get('path')
db.commit()
return jsonify(markdown.to_dict()), 200
@markdown_bp.route('/<int:markdown_id>', methods=['DELETE'])
def delete_markdown(markdown_id):
with get_db() as db:
markdown = db.query(Markdown).get(markdown_id)
if markdown is None:
return jsonify({"error": "file not found"}), 404
db.delete(markdown)
db.commit()
return jsonify({"message": "deleted"}), 200

73
app.py
View File

@@ -1,51 +1,30 @@
from authlib.integrations import flask_client
from flask import Flask, jsonify, request, url_for, redirect, session
# app.py
from urllib.parse import urlparse
from flask import Flask
from flask_cors import CORS
from authlib.integrations.flask_client import OAuth
import os
import env_provider
import db
from api.auth import auth_bp
from api.markdown import markdown_bp
def is_allowed_origin(origin):
parsed_origin = urlparse(origin)
if parsed_origin.hostname in ['localhost', '127.0.0.1']:
return True
allowed_origins = [
"https://login.hangman-lab.top",
"https://git.hangman-lab.top",
]
return origin in allowed_origins
db.create_all()
app = Flask(__name__)
CORS(app)
oauth = OAuth(app)
keycloak = oauth.register(
'keycloak',
client_id="main",
client_secret="<KEY>",
server_metadata_url="https://login.hangman-lab.top/auth/realms/Hangman-Lab/.well-known/openid-configuration",
client_kwargs={"scope": "openid email profile"},
)
@app.route('/api/login')
def login():
redirect_uri = url_for("authorize", _external=True)
return keycloak.authorize_redirect(redirect_uri)
@app.route('/api/authorize')
def authorize():
token = keycloak.authorize_access_token()
user_info = keycloak.parse_id_token(token)
session['user'] = user_info
@app.route('/api/logout')
def logout():
session.pop('user', None)
logout_url = "https://login.hangman-lab.top/auth/realms/Hangman-Lab/protocol/openid-connect/logout"
return redirect(logout_url)
@app.route("/api/user")
def user():
u = session.get('user')
if not u:
return jsonify({"username": "guest", "role": "guest"})
return jsonify(user)
@app.route('/api/get_note_list', methods=['GET'])
def get_note_list():
raise NotImplementedError
@app.route('/api/get_note', methods=['GET'])
def get_note(idx):
raise NotImplementedError
app.secret_key = env_provider.SESSION_SECRET_KEY
CORS(app, resources={r"/api/*": {"origins": is_allowed_origin}})
app.register_blueprint(markdown_bp)
app.register_blueprint(auth_bp)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)

23
db/__init__.py Normal file
View File

@@ -0,0 +1,23 @@
#db/__init__.py
from contextlib import contextmanager
from models import Base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
import env_provider
engine = create_engine(env_provider.DB_CONNECT_STRING)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
@contextmanager
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
def create_all():
with engine.begin() as conn:
Base.metadata.create_all(bind=conn)

21
db/models/BackendLog.py Normal file
View File

@@ -0,0 +1,21 @@
#db/models/BackendLog.py
from sqlalchemy import Column, Integer, String, DateTime, Text
from db.models import Base
import datetime
class BackendLog(Base):
__tablename__ = 'backend_log'
id = Column(Integer, primary_key=True, autoincrement=True)
level = Column(String(50), nullable=False)
message = Column(Text, nullable=False)
timestamp = Column(DateTime, nullable=False)
extra = Column(Text, nullable=True)
def to_dict(self):
return {
"id": self.id,
"level": self.level,
"message": self.message,
"timestamp": self.timestamp,
"extra": self.extra,
}

21
db/models/Markdown.py Normal file
View File

@@ -0,0 +1,21 @@
#db/models/Markdown.py
from sqlalchemy import Column, Text, Integer, String, DateTime
from db.models import Base
import datetime
class Markdown(Base):
__tablename__ = 'markdown'
id = Column(Integer, primary_key=True)
title = Column(String(255), nullable=False)
content = Column(Text, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.utcnow)
path = Column(String(255), nullable=False)
def to_dict(self):
return {
'id': self.id,
'title': self.title,
'content': self.content,
'created_at': self.created_at,
'path': self.path,
}

10
db/models/__init__.py Normal file
View File

@@ -0,0 +1,10 @@
#db/models/__init__.py
import pkgutil
import importlib
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
package_name = "db.models"
for _, module_name, _ in pkgutil.iter_modules(__path__):
importlib.import_module(f"{package_name}.{module_name}")

9
db/utils.py Normal file
View File

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

10
env_provider.py Normal file
View File

@@ -0,0 +1,10 @@
#env_provider.py
import os
from dotenv import load_dotenv
load_dotenv()
CLIENT_ID = os.getenv("CLIENT_ID")
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
DB_CONNECT_STRING = os.getenv("DB_CONNECT_STRING")
SESSION_SECRET_KEY = os.getenv("SESSION_SECRET_KEY")

View File

@@ -0,0 +1,19 @@
#logging_handlers/DatabaseLogHandler.py
import logging
import traceback
from db import get_db
from db.models.BackendLog import BackendLog
class DatabaseLogHandler(logging.Handler):
def emit(self, record):
message = self.format(record)
level = record.levelname
extra = getattr(record, 'extra', None)
log_entry = BackendLog(message=message, level=level, extra=extra)
try:
with get_db() as db:
db.add(log_entry)
db.commit()
except Exception:
print(f"Failed to log to database: {traceback.format_exc()}")

View File

@@ -0,0 +1 @@
#logging_handlers/__init__.py

0
requirements.txt Normal file
View File