Save Markdowns

This commit is contained in:
h z
2024-12-06 15:13:20 +00:00
parent 48dd59f8e4
commit b3ec244e06
9 changed files with 100 additions and 34 deletions

View File

@@ -5,6 +5,11 @@ ENV PYTHONUNBUFFERED 1
WORKDIR /app WORKDIR /app
RUN apt-get update &&\
apt-get install -y \
default-mysql-client &&\
apt-get clean
COPY requirements.txt /app/ COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt RUN pip install --no-cache-dir -r requirements.txt

View File

@@ -40,7 +40,7 @@ def create_path():
if not data or 'name' not in data or 'parent_id' not in data: if not data or 'name' not in data or 'parent_id' not in data:
return jsonify({"error": "bad request"}), 400 return jsonify({"error": "bad request"}), 400
with get_db() as session: with get_db() as session:
if data['parent_id'] != 0 and not session.query(Path).get(data['parent_id']): if data['parent_id'] != 1 and not session.query(Path).get(data['parent_id']):
return jsonify({"error": "path not found"}), 404 return jsonify({"error": "path not found"}), 404
if session.query(Path).filter_by(name=data['name'], parent_id=data['parent_id']).first(): if session.query(Path).filter_by(name=data['name'], parent_id=data['parent_id']).first():
return jsonify({"error": "Path already exists under the parent"}), 409 return jsonify({"error": "Path already exists under the parent"}), 409

29
app.py
View File

@@ -1,13 +1,8 @@
# app.py # app.py
from pprint import pprint from pprint import pprint
from sqlalchemy import text
from db.models.Path import Path
from logging_handlers.DatabaseLogHandler import DatabaseLogHandler from logging_handlers.DatabaseLogHandler import DatabaseLogHandler
from urllib.parse import urlparse
from api import limiter from api import limiter
from flask import Flask, request, url_for from flask import Flask, request
from flask_cors import CORS from flask_cors import CORS
import api import api
import env_provider import env_provider
@@ -24,28 +19,12 @@ logger.addHandler(db_handler)
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
try: try:
db.create_all() db.setup_db()
except Exception as e: except Exception as e:
print(f"db not ready {e}") print(f"db not ready")
print(e)
try:
with db.get_db() as session:
root_path = session.query(Path).filter(Path.id == 1).first()
if not root_path:
session.execute(text("SET FOREIGN_KEY_CHECKS=0;"))
#session.execute(text("ALTER TABLE path AUTO_INCREMENT = 0;"))
session.execute(text("ALTER TABLE path MODIFY COLUMN id INT;"))
root_path = Path(id=1, name="")
session.add(root_path)
session.commit()
session.execute(text("ALTER TABLE path MODIFY COLUMN id INT AUTO_INCREMENT;"))
session.execute(text("SET FOREIGN_KEY_CHECKS=1;"))
logger.info("Root path created")
except Exception as e:
logger.error(f"Failed to create root path {e}")
app = Flask(__name__) app = Flask(__name__)
#app.config['SERVER_NAME'] = env_provider.BACKEND_HOST
app.secret_key = env_provider.SESSION_SECRET_KEY app.secret_key = env_provider.SESSION_SECRET_KEY
CORS(app, resources={r"/api/*": {"origins": [ CORS(app, resources={r"/api/*": {"origins": [
env_provider.KC_HOST, env_provider.KC_HOST,

View File

@@ -1,11 +1,16 @@
#db/__init__.py #db/__init__.py
import os
import pkgutil
import subprocess
from contextlib import contextmanager from contextlib import contextmanager
from db.models import Base from db.models import Base
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine from sqlalchemy.dialects.mysql import insert
import env_provider from sqlalchemy import create_engine, text, inspect
from env_provider import DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD from env_provider import DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD, DB_SCHEMA_UPDATED, ENVIRONMENT
engine = create_engine(f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}") engine = create_engine(f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}")
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
@@ -18,7 +23,59 @@ def get_db():
finally: finally:
db.close() db.close()
def dump_db():
try:
os.environ['MYSQL_PWD'] = DB_PASSWORD
dump_cmd = f"mysqldump --no-tablespaces -h {DB_HOST} -P {DB_PORT} -u {DB_USER} {DB_NAME} > /app/dump/db_dump.sql"
subprocess.run(dump_cmd, shell=True, check=True)
except subprocess.CalledProcessError as e:
print(f"Failed to dump database: {e}")
raise e
def clear_db():
with engine.connect() as conn:
conn.execute(text("SET FOREIGN_KEY_CHECKS = 0;"))
inspector = inspect(engine)
for table_name in inspector.get_table_names():
conn.execute(text(f"DROP TABLE IF EXISTS {table_name}"))
conn.execute(text("SET FOREIGN_KEY_CHECKS = 1;"))
def create_all(): def create_all():
with engine.begin() as conn: with engine.begin() as conn:
Base.metadata.create_all(bind=conn) Base.metadata.create_all(bind=conn)
def init_payload():
from db.models import table_models
with get_db() as session:
session.execute(text("SET FOREIGN_KEY_CHECKS = 0;"))
for model in table_models:
print(f"MODEL -- {model}, {hasattr(model, '__pay_load__')}")
if hasattr(model, "__pay_load__"):
payload =model.__pay_load__[ENVIRONMENT]
print(f"- - [ - ] hasattr, {ENVIRONMENT} - {payload}")
stmt = insert(model.__table__).values(payload).prefix_with("IGNORE")
print(f"- - [ - ] {stmt}\n")
session.execute(stmt)
session.execute(text("SET FOREIGN_KEY_CHECKS = 1;"))
session.commit()
def setup_db():
if DB_SCHEMA_UPDATED:
try:
dump_db()
print("[ x ] db dumped")
except Exception as e:
print(f"[ x ] Failed to dump database: {e}")
clear_db()
print("[ x ] db cleared")
create_all()
print("[ x ] db created")
init_payload()
print("[ x ] payload loaded")

View File

@@ -14,4 +14,15 @@ class Path(Base):
"id": self.id, "id": self.id,
"name": self.name, "name": self.name,
"parent_id": self.parent_id, "parent_id": self.parent_id,
} }
__pay_load__ = {
'dev': [
{'id': 1, 'name': '', 'parent_id': None},
{'id': 2, 'name': 'test', 'parent_id': 1},
{'id': 3, 'name': 'test1', 'parent_id': 1},
],
'prod': [
{'id': 1, 'name': '', 'parent_id': None},
]
}

View File

@@ -5,6 +5,11 @@ import importlib
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base() Base = declarative_base()
package_name = "db.models" package_name = "db.models"
for _, module_name, _ in pkgutil.iter_modules(__path__):
importlib.import_module(f"{package_name}.{module_name}")
table_models = []
for _, module_name, _ in pkgutil.iter_modules(__path__):
module = importlib.import_module(f"{package_name}.{module_name}")
if hasattr(module, module_name):
model = getattr(module, module_name)
if hasattr(model, "__tablename__"):
table_models.append(model)

View File

@@ -4,12 +4,17 @@ from dotenv import load_dotenv
load_dotenv() load_dotenv()
def str_to_bool(value):
return value.lower() in ("yes", "true", "t", "1")
ENVIRONMENT = os.getenv("ENVIRONMENT", "dev")
DB_HOST = os.getenv("DB_HOST") DB_HOST = os.getenv("DB_HOST")
DB_PORT = os.getenv("DB_PORT") DB_PORT = os.getenv("DB_PORT")
DB_NAME = os.getenv("DB_NAME") DB_NAME = os.getenv("DB_NAME")
DB_USER = os.getenv("DB_USER") DB_USER = os.getenv("DB_USER")
DB_PASSWORD = os.getenv("DB_PASSWORD") DB_PASSWORD = os.getenv("DB_PASSWORD")
DB_SCHEMA_UPDATED = str_to_bool(os.getenv("DB_SCHEMA_UPDATED", 'false'))
SESSION_SECRET_KEY = os.getenv("SESSION_SECRET_KEY") SESSION_SECRET_KEY = os.getenv("SESSION_SECRET_KEY")
KC_HOST = os.getenv("KC_HOST") KC_HOST = os.getenv("KC_HOST")
@@ -21,15 +26,17 @@ BACKEND_HOST = os.getenv("BACKEND_HOST")
def summerize(): def summerize():
return { return {
"ENVIRONMENT": ENVIRONMENT,
'DB_HOST': DB_HOST, 'DB_HOST': DB_HOST,
'DB_PORT': DB_PORT, 'DB_PORT': DB_PORT,
'DB_NAME': DB_NAME, 'DB_NAME': DB_NAME,
'DB_USER': DB_USER, 'DB_USER': DB_USER,
'DB_PASSWORD': DB_PASSWORD, 'DB_PASSWORD': DB_PASSWORD,
'DB_SCHEMA_UPDATED': DB_SCHEMA_UPDATED,
'SESSION_SECRET_KEY': SESSION_SECRET_KEY, 'SESSION_SECRET_KEY': SESSION_SECRET_KEY,
'KC_HOST': KC_HOST, 'KC_HOST': KC_HOST,
'KC_REALM': KC_REALM, 'KC_REALM': KC_REALM,
'KC_CLIENT_ID': KC_CLIENT_ID, 'KC_CLIENT_ID': KC_CLIENT_ID,
'FRONTEND_HOST': FRONTEND_HOST, 'FRONTEND_HOST': FRONTEND_HOST,
'BACKEND_HOST': BACKEND_HOST, 'BACKEND_HOST': BACKEND_HOST,
} }

0
play.py Normal file
View File

View File

@@ -1,3 +1,4 @@
alembic==1.14.0
Authlib==1.3.2 Authlib==1.3.2
blinker==1.9.0 blinker==1.9.0
certifi==2024.8.30 certifi==2024.8.30
@@ -15,6 +16,7 @@ idna==3.10
itsdangerous==2.2.0 itsdangerous==2.2.0
Jinja2==3.1.4 Jinja2==3.1.4
limits==3.14.1 limits==3.14.1
Mako==1.3.7
markdown-it-py==3.0.0 markdown-it-py==3.0.0
MarkupSafe==3.0.2 MarkupSafe==3.0.2
mdurl==0.1.2 mdurl==0.1.2