Compare commits
1 Commits
00f6895850
...
26b64f8c15
| Author | SHA1 | Date | |
|---|---|---|---|
| 26b64f8c15 |
@@ -2,10 +2,10 @@ FROM python:3.12-slim
|
|||||||
ENV PYTHONDONTWRITEBYTECODE 1
|
ENV PYTHONDONTWRITEBYTECODE 1
|
||||||
ENV PYTHONUNBUFFERED 1
|
ENV PYTHONUNBUFFERED 1
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN apt-get update &&\
|
#RUN apt-get update &&\
|
||||||
apt-get install -y default-mysql-client &&\
|
# apt-get install -y default-mysql-client &&\
|
||||||
apt-get clean &&\
|
# apt-get clean &&\
|
||||||
rm -rf /var/lib/apt/lists/*
|
# rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY requirements.txt ./requirements.txt
|
COPY requirements.txt ./requirements.txt
|
||||||
RUN pip install --no-cache-dir -r ./requirements.txt
|
RUN pip install --no-cache-dir -r ./requirements.txt
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import shutil
|
import shutil
|
||||||
import zipfile
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from flask import Blueprint, send_file, jsonify
|
from flask import Blueprint, send_file, jsonify
|
||||||
@@ -60,6 +59,7 @@ def traverse(path_id, paths):
|
|||||||
with open(f"{md.title}.mdmeta", "w") as meta_file:
|
with open(f"{md.title}.mdmeta", "w") as meta_file:
|
||||||
meta_file.write(f"created_at: {md.created_at}\n")
|
meta_file.write(f"created_at: {md.created_at}\n")
|
||||||
meta_file.write(f"order: {md.order}\n")
|
meta_file.write(f"order: {md.order}\n")
|
||||||
|
meta_file.write(f"shortcut: {md.shortcut}\n")
|
||||||
children = [c for c in paths.values() if c.parent_id == path_id]
|
children = [c for c in paths.values() if c.parent_id == path_id]
|
||||||
for child in children:
|
for child in children:
|
||||||
traverse(child.id, paths)
|
traverse(child.id, paths)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from flask import Blueprint, request, jsonify
|
from flask import Blueprint, request, jsonify
|
||||||
from sqlalchemy import or_
|
from sqlalchemy import or_
|
||||||
|
|
||||||
import api
|
import api
|
||||||
from api import require_auth, etag_response
|
from api import require_auth, etag_response
|
||||||
from contexts.RequestContext import RequestContext
|
from contexts.RequestContext import RequestContext
|
||||||
@@ -29,6 +28,7 @@ def get_home():
|
|||||||
if markdown is None:
|
if markdown is None:
|
||||||
return jsonify({}), 204
|
return jsonify({}), 204
|
||||||
return jsonify(markdown.to_dict()), 200
|
return jsonify(markdown.to_dict()), 200
|
||||||
|
|
||||||
@markdown_bp.route('/by_path/<int:path_id>', methods=['GET'])
|
@markdown_bp.route('/by_path/<int:path_id>', methods=['GET'])
|
||||||
@limiter.limit(api.get_rate_limit)
|
@limiter.limit(api.get_rate_limit)
|
||||||
@etag_response
|
@etag_response
|
||||||
@@ -36,6 +36,7 @@ def get_markdowns_by_path(path_id):
|
|||||||
with get_db() as session:
|
with get_db() as session:
|
||||||
markdowns = session.query(Markdown).filter(Markdown.path_id == path_id).all()
|
markdowns = session.query(Markdown).filter(Markdown.path_id == path_id).all()
|
||||||
return jsonify([md.to_dict() for md in markdowns]), 200
|
return jsonify([md.to_dict() for md in markdowns]), 200
|
||||||
|
|
||||||
@markdown_bp.route('/get_index/<int:path_id>', methods=['GET'])
|
@markdown_bp.route('/get_index/<int:path_id>', methods=['GET'])
|
||||||
@limiter.limit(api.get_rate_limit)
|
@limiter.limit(api.get_rate_limit)
|
||||||
@etag_response
|
@etag_response
|
||||||
@@ -66,11 +67,16 @@ def create_markdown():
|
|||||||
title = data.get('title')
|
title = data.get('title')
|
||||||
content = data.get('content')
|
content = data.get('content')
|
||||||
path_id = data.get('path_id')
|
path_id = data.get('path_id')
|
||||||
|
shortcut = data.get('shortcut', "")
|
||||||
if not title or not content:
|
if not title or not content:
|
||||||
return jsonify({"error": "missing required fields"}), 400
|
return jsonify({"error": "missing required fields"}), 400
|
||||||
new_markdown = Markdown(title=title, content=content, path_id=path_id)
|
new_markdown = Markdown(title=title, content=content, path_id=path_id, shortcut=shortcut)
|
||||||
with get_db() as session:
|
with get_db() as session:
|
||||||
try:
|
try:
|
||||||
|
if shortcut != "":
|
||||||
|
r = session.query(Markdown).filter(Markdown.shortcut == shortcut).all()
|
||||||
|
if len(r) > 0:
|
||||||
|
return jsonify({"error": "duplicate shortcut"}), 400
|
||||||
session.add(new_markdown)
|
session.add(new_markdown)
|
||||||
session.commit()
|
session.commit()
|
||||||
return jsonify(new_markdown.to_dict()), 201
|
return jsonify(new_markdown.to_dict()), 201
|
||||||
@@ -89,10 +95,19 @@ def update_markdown(markdown_id):
|
|||||||
if markdown is None:
|
if markdown is None:
|
||||||
return jsonify({"error": "file not found"}), 404
|
return jsonify({"error": "file not found"}), 404
|
||||||
data = request.json
|
data = request.json
|
||||||
|
if data.get('shortcut', "") != "":
|
||||||
|
r = session.query(Markdown).filter(
|
||||||
|
Markdown.shortcut == data.get('shortcut')
|
||||||
|
).filter(
|
||||||
|
Markdown.id != markdown_id
|
||||||
|
).all()
|
||||||
|
if len(r) > 0:
|
||||||
|
return jsonify({"error": "duplicate shortcut"}), 400
|
||||||
if request.method == "PUT":
|
if request.method == "PUT":
|
||||||
markdown.title = data.get('title')
|
markdown.title = data.get('title')
|
||||||
markdown.content = data.get('content')
|
markdown.content = data.get('content')
|
||||||
markdown.path_id = data.get('path_id')
|
markdown.path_id = data.get('path_id')
|
||||||
|
markdown.shortcut = data.get('shortcut', '')
|
||||||
elif request.method == "PATCH":
|
elif request.method == "PATCH":
|
||||||
if 'title' in data:
|
if 'title' in data:
|
||||||
markdown.title = data.get('title')
|
markdown.title = data.get('title')
|
||||||
@@ -100,6 +115,8 @@ def update_markdown(markdown_id):
|
|||||||
markdown.content = data.get('content')
|
markdown.content = data.get('content')
|
||||||
if 'path_id' in data:
|
if 'path_id' in data:
|
||||||
markdown.path_id = data.get('path_id')
|
markdown.path_id = data.get('path_id')
|
||||||
|
if 'shortcut' in data:
|
||||||
|
markdown.shortcut = data.get('shortcut')
|
||||||
session.commit()
|
session.commit()
|
||||||
return jsonify(markdown.to_dict()), 200
|
return jsonify(markdown.to_dict()), 200
|
||||||
|
|
||||||
@@ -157,8 +174,16 @@ def move_backward(markdown_id):
|
|||||||
@markdown_bp.route('/search/<string:keyword>', methods=['GET'])
|
@markdown_bp.route('/search/<string:keyword>', methods=['GET'])
|
||||||
@limiter.limit(api.get_rate_limit)
|
@limiter.limit(api.get_rate_limit)
|
||||||
def search_markdowns(keyword):
|
def search_markdowns(keyword):
|
||||||
with (get_db() as session):
|
with get_db() as session:
|
||||||
res = session.query(Markdown).filter(
|
res = session.query(Markdown).filter(
|
||||||
or_(Markdown.title.like(keyword), Markdown.content.like(keyword))
|
or_(Markdown.title.like(keyword), Markdown.content.like(keyword))
|
||||||
).all()
|
).all()
|
||||||
return jsonify([md.to_dict() for md in res]), 200
|
return jsonify([md.to_dict() for md in res]), 200
|
||||||
|
|
||||||
|
@markdown_bp.route('/links', methods=['GET'])
|
||||||
|
@limiter.limit(api.get_rate_limit)
|
||||||
|
def get_links():
|
||||||
|
with get_db() as session:
|
||||||
|
mds = [md.to_dict() for md in session.query(Markdown).filter(Markdown.shortcut != "").all()]
|
||||||
|
links = [f"[{md['shortcut']}]: {md['id']}" for md in mds]
|
||||||
|
return jsonify(links), 200
|
||||||
|
|||||||
@@ -21,14 +21,14 @@ def get_db():
|
|||||||
finally:
|
finally:
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
def dump_db():
|
# def dump_db():
|
||||||
try:
|
# try:
|
||||||
os.environ['MYSQL_PWD'] = DB_PASSWORD
|
# 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"
|
# 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)
|
# subprocess.run(dump_cmd, shell=True, check=True)
|
||||||
except subprocess.CalledProcessError as e:
|
# except subprocess.CalledProcessError as e:
|
||||||
print(f"Failed to dump database: {e}")
|
# print(f"Failed to dump database: {e}")
|
||||||
raise e
|
# raise e
|
||||||
|
|
||||||
def clear_db():
|
def clear_db():
|
||||||
with engine.connect() as conn:
|
with engine.connect() as conn:
|
||||||
@@ -73,11 +73,11 @@ def init_payload():
|
|||||||
|
|
||||||
def setup_db():
|
def setup_db():
|
||||||
if DB_SCHEMA_UPDATED:
|
if DB_SCHEMA_UPDATED:
|
||||||
try:
|
# try:
|
||||||
dump_db()
|
# dump_db()
|
||||||
print("[ x ] db dumped")
|
# print("[ x ] db dumped")
|
||||||
except Exception as e:
|
# except Exception as e:
|
||||||
print(f"[ x ] Failed to dump database: {e}")
|
# print(f"[ x ] Failed to dump database: {e}")
|
||||||
clear_db()
|
clear_db()
|
||||||
print("[ x ] db cleared")
|
print("[ x ] db cleared")
|
||||||
create_all()
|
create_all()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from sqlalchemy import Column, Text, Integer, String, DateTime, ForeignKey, Float, text
|
from sqlalchemy import Column, Text, Integer, String, DateTime, ForeignKey, Float, text, UniqueConstraint
|
||||||
from db.models import Base
|
from db.models import Base
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ class Markdown(Base):
|
|||||||
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
||||||
path_id = Column(Integer, ForeignKey('path.id'), nullable=False)
|
path_id = Column(Integer, ForeignKey('path.id'), nullable=False)
|
||||||
order = Column(String(36), default=lambda: str(uuid.uuid4()))
|
order = Column(String(36), default=lambda: str(uuid.uuid4()))
|
||||||
|
shortcut = Column(String(36), default="")
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {
|
return {
|
||||||
'id': self.id,
|
'id': self.id,
|
||||||
@@ -21,6 +21,7 @@ class Markdown(Base):
|
|||||||
'created_at': self.created_at,
|
'created_at': self.created_at,
|
||||||
'path_id': self.path_id,
|
'path_id': self.path_id,
|
||||||
'order': self.order,
|
'order': self.order,
|
||||||
|
'shortcut': self.shortcut,
|
||||||
}
|
}
|
||||||
__pay_load__ = {
|
__pay_load__ = {
|
||||||
'dev': [
|
'dev': [
|
||||||
|
|||||||
Reference in New Issue
Block a user