Atualizar app/app.py
This commit is contained in:
+63
@@ -34,6 +34,60 @@ def notifications(ws):
|
||||
ws.send(json.dumps({"type": "pong", "payload": data}))
|
||||
|
||||
|
||||
# ================
|
||||
# DECORATORS
|
||||
# ================
|
||||
import structlog
|
||||
|
||||
logger = structlog.get_logger()
|
||||
|
||||
@app.before_request
|
||||
def log_request():
|
||||
logger.info(
|
||||
"request",
|
||||
path=request.path,
|
||||
method=request.method,
|
||||
remote=request.remote_addr,
|
||||
)
|
||||
|
||||
@app.after_request
|
||||
def log_response(response):
|
||||
logger.info(
|
||||
"response",
|
||||
path=request.path,
|
||||
status=response.status_code,
|
||||
)
|
||||
return response
|
||||
|
||||
|
||||
from limits import RateLimitItemPerMinute
|
||||
from time import time
|
||||
|
||||
rate_store = {}
|
||||
|
||||
def rate_limited(f):
|
||||
@wraps(f)
|
||||
def wrapper(*args, **kwargs):
|
||||
if app.config["AUTH_MODE"] == "oauth":
|
||||
email = session["user"]["email"]
|
||||
else:
|
||||
email = session["db_user"]["email"]
|
||||
|
||||
key = f"{email}:{f.__name__}"
|
||||
limit = RateLimitItemPerMinute(30) # 30 req/min por endpoint
|
||||
|
||||
now = int(time())
|
||||
window = now // 60
|
||||
|
||||
used = rate_store.get((key, window), 0)
|
||||
if used >= limit.amount:
|
||||
return jsonify({"error": "Rate limit exceeded"}), 429
|
||||
|
||||
rate_store[(key, window)] = used + 1
|
||||
return f(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
|
||||
def admin_required(f):
|
||||
@wraps(f)
|
||||
def wrapper(*args, **kwargs):
|
||||
@@ -290,6 +344,7 @@ def list_conversations():
|
||||
|
||||
@app.route("/api/export/md/<cid>")
|
||||
@login_required
|
||||
@rate_limited
|
||||
def export_md(cid):
|
||||
db = SessionLocal()
|
||||
conv = db.query(Conversation).filter_by(id=cid).first()
|
||||
@@ -314,6 +369,7 @@ from docx import Document
|
||||
|
||||
@app.route("/api/import/<cid>", methods=["POST"])
|
||||
@login_required
|
||||
@rate_limited
|
||||
def import_file(cid):
|
||||
file = request.files.get("file")
|
||||
if not file:
|
||||
@@ -351,6 +407,7 @@ def import_file(cid):
|
||||
|
||||
@app.route("/api/export/pdf/<cid>")
|
||||
@login_required
|
||||
@rate_limited
|
||||
def export_pdf(cid):
|
||||
db = SessionLocal()
|
||||
conv = db.query(Conversation).filter_by(id=cid).first()
|
||||
@@ -372,6 +429,7 @@ def export_pdf(cid):
|
||||
|
||||
@app.route("/api/history/<cid>")
|
||||
@login_required
|
||||
@rate_limited
|
||||
def history(cid):
|
||||
db = SessionLocal()
|
||||
msgs = db.query(Message).filter_by(conversation_id=cid).order_by(Message.created_at).all()
|
||||
@@ -381,6 +439,7 @@ def history(cid):
|
||||
|
||||
@app.route("/api/attachment/<cid>", methods=["POST"])
|
||||
@login_required
|
||||
@rate_limited
|
||||
def upload_attachment(cid):
|
||||
db = SessionLocal()
|
||||
file = request.files.get("file")
|
||||
@@ -401,6 +460,7 @@ def upload_attachment(cid):
|
||||
|
||||
@app.route("/api/attachments/<cid>")
|
||||
@login_required
|
||||
@rate_limited
|
||||
def list_attachments(cid):
|
||||
db = SessionLocal()
|
||||
atts = db.query(Attachment).filter_by(conversation_id=cid).all()
|
||||
@@ -411,6 +471,7 @@ def list_attachments(cid):
|
||||
|
||||
@app.route("/api/download/<att_id>")
|
||||
@login_required
|
||||
@rate_limited
|
||||
def download(att_id):
|
||||
db = SessionLocal()
|
||||
att = db.query(Attachment).filter_by(id=att_id).first()
|
||||
@@ -424,6 +485,7 @@ def download(att_id):
|
||||
|
||||
@app.route("/api/stream")
|
||||
@login_required
|
||||
@rate_limited
|
||||
def stream():
|
||||
cid = request.args.get("conversation_id")
|
||||
model = request.args.get("model", "llama3.2")
|
||||
@@ -485,6 +547,7 @@ def update_tags(cid):
|
||||
|
||||
@app.route("/api/search")
|
||||
@login_required
|
||||
@rate_limited
|
||||
def search():
|
||||
q = request.args.get("q", "").lower()
|
||||
user_email = session["user"]["email"]
|
||||
|
||||
Reference in New Issue
Block a user