from flask import Blueprint, request, jsonify import api from api import require_auth, etag_response from db import get_db from db.models.Markdown import Markdown from db.models.Path import Path from api import limiter import logging logger = logging.getLogger(__name__) path_bp = Blueprint('path', __name__, url_prefix='/api/path') @path_bp.route('/', methods=['GET']) @limiter.limit(api.get_rate_limit) @etag_response def get_root_paths(): with get_db() as session: paths = session.query(Path).filter(Path.parent_id == 1) return jsonify([pth.to_dict() for pth in paths]), 200 @path_bp.route('/', methods=['GET']) @limiter.limit(api.get_rate_limit) @etag_response def get_path(path_id): with get_db() as session: path = session.query(Path).get(path_id) if path is None: return jsonify({"error": "file not found"}), 404 return jsonify(path.to_dict()), 200 @path_bp.route('/parent/', methods=['GET']) @limiter.limit(api.get_rate_limit) @etag_response def get_path_by_parent(parent_id): with get_db() as session: paths = session.query(Path).filter(Path.parent_id == parent_id).all() return jsonify([pth.to_dict() for pth in paths]), 200 @path_bp.route('/', methods=['POST']) @limiter.limit(api.get_rate_limit) @require_auth(roles=['admin', 'creator']) def create_path(): data = request.json if not data or 'name' not in data or 'parent_id' not in data: return jsonify({"error": "bad request"}), 400 with get_db() as session: if data['parent_id'] != 1 and not session.query(Path).get(data['parent_id']): return jsonify({"error": "path not found"}), 404 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 new_path = Path(name=data['name'], parent_id=data['parent_id']) session.add(new_path) session.commit() return jsonify(new_path.to_dict()), 201 @path_bp.route('/', methods=['PUT']) @limiter.limit(api.get_rate_limit) @require_auth(roles=['admin']) def update_path(path_id): data = request.json if not data or 'name' not in data or 'parent_id' not in data: return jsonify({"error": "bad request"}), 400 with get_db() as session: path = session.query(Path).get(path_id) if path is None: return jsonify({"error": "path not found"}), 404 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 path.name = data['name'] path.parent_id = data['parent_id'] session.commit() return jsonify(path.to_dict()), 200 @path_bp.route('/', methods=['PATCH']) @limiter.limit(api.get_rate_limit) @require_auth(roles=['admin']) def patch_path(path_id): data = request.json if not data or 'name' not in data and 'parent_id' not in data: return jsonify({"error": "bad request"}), 400 with get_db() as session: path = session.query(Path).get(path_id) if path is None: return jsonify({"error": "path not found"}), 404 updated_name =data.get('name', path.name) updated_parent_id = data.get('parent_id', path.parent_id) if session.query(Path).filter_by(name=updated_name, parent_id=updated_parent_id).first(): return jsonify({"error": "Path already exists under the parent"}), 409 path.name = updated_name path.parent_id = updated_parent_id session.commit() return jsonify(path.to_dict()), 200 @path_bp.route('/', methods=['DELETE']) @limiter.limit(api.get_rate_limit) @require_auth(roles=['admin']) def delete_path(path_id): with get_db() as session: path = session.query(Path).get(path_id) if not path: return jsonify({"error": "path not found"}), 404 if session.query(Path).filter_by(parent_id=path_id).first(): return jsonify({"error": "can not delete non empty path"}), 409 if session.query(Markdown).filter_by(path_id=path_id).first(): return jsonify({"error": "can not delete non empty path"}), 409 session.delete(path) session.commit() return jsonify({"message": "path deleted"}), 200 @path_bp.route('/move_forward/', methods=['PATCH']) @require_auth(roles=['admin']) @limiter.limit(api.get_rate_limit) def move_forward(path_id): with get_db() as session: path = session.query(Path).get(path_id) if not path: return jsonify({"error": "file not found"}), 404 siblings = session.query(Path).filter(Path.parent_id == path.parent_id).order_by(Path.order).all() current_index = siblings.index(path) if current_index == 0: return jsonify({"error": "already at the first position"}), 400 previous_path = siblings[current_index - 1] path.order, previous_path.order = previous_path.order, path.order session.commit() return jsonify(path.to_dict()), 200 @path_bp.route('/move_backward/', methods=['PATCH']) @require_auth(roles=['admin']) @limiter.limit(api.get_rate_limit) def move_backward(path_id): with get_db() as session: path = session.query(Path).get(path_id) if not path: return jsonify({"error": "file not found"}), 404 siblings = session.query(Path).filter(Path.parent_id == path.parent_id).order_by(Path.order).all() current_index = siblings.index(path) if current_index == len(siblings) - 1: return jsonify({"error": "already at the last position"}), 400 next_path = siblings[current_index + 1] path.order, next_path.order = next_path.order, path.order session.commit() return jsonify(path.to_dict()), 200