32 lines
910 B
Python
32 lines
910 B
Python
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from flask import Blueprint, abort, current_app, send_from_directory
|
|
|
|
from app.services.vault import Vault
|
|
|
|
bp = Blueprint("attachments", __name__, url_prefix="/attachments")
|
|
|
|
|
|
@bp.get("/<path:subpath>")
|
|
def serve_attachment(subpath: str):
|
|
# Resolve within the vault attachments directory
|
|
vault_path = current_app.config.get("KB_VAULT_PATH")
|
|
if not vault_path:
|
|
abort(404)
|
|
|
|
v = Vault(vault_path)
|
|
attachments_dir = Path(v.paths.attachments).resolve()
|
|
requested = (attachments_dir / subpath).resolve()
|
|
|
|
# Prevent path traversal
|
|
try:
|
|
requested.relative_to(attachments_dir)
|
|
except Exception:
|
|
abort(403)
|
|
|
|
if not requested.exists() or not requested.is_file():
|
|
abort(404)
|
|
|
|
return send_from_directory(attachments_dir, os.path.relpath(str(requested), str(attachments_dir))) |