from flask import Blueprint, current_app, jsonify, request from sqlalchemy.exc import IntegrityError from sqlalchemy.orm.exc import NoResultFound from app.dao.dao_utils import autocommit from app.dao.service_user_dao import dao_get_service_user from app.dao.services_dao import dao_fetch_service_by_id from app.dao.template_folder_dao import ( dao_create_template_folder, dao_delete_template_folder, dao_get_template_folder_by_id_and_service_id, dao_update_template_folder, ) from app.dao.templates_dao import dao_get_template_by_id_and_service_id from app.errors import InvalidRequest, register_errors from app.models import TemplateFolder from app.schema_validation import validate from app.template_folder.template_folder_schema import ( post_create_template_folder_schema, post_move_template_folder_schema, post_update_template_folder_schema, ) from app.utils import check_suspicious_id template_folder_blueprint = Blueprint( "template_folder", __name__, url_prefix="/service//template-folder" ) register_errors(template_folder_blueprint) @template_folder_blueprint.errorhandler(IntegrityError) def handle_integrity_error(exc): if "template_folder_parent_id_fkey" in str(exc): return jsonify(result="error", message="parent_id not found"), 400 raise @template_folder_blueprint.route("", methods=["GET"]) def get_template_folders_for_service(service_id): check_suspicious_id(service_id) service = dao_fetch_service_by_id(service_id) template_folders = [o.serialize() for o in service.all_template_folders] return jsonify(template_folders=template_folders) @template_folder_blueprint.route("", methods=["POST"]) def create_template_folder(service_id): check_suspicious_id(service_id) data = request.get_json() validate(data, post_create_template_folder_schema) if data.get("parent_id") is not None: try: parent_folder = dao_get_template_folder_by_id_and_service_id( data["parent_id"], service_id ) users_with_permission = parent_folder.users except NoResultFound: raise InvalidRequest("parent_id not found", status_code=400) else: users_with_permission = [] if data.get("created_by_id"): creator = dao_get_service_user(data["created_by_id"], service_id) if creator: users_with_permission = [creator] template_folder = TemplateFolder( service_id=service_id, name=data["name"].strip(), parent_id=data["parent_id"], users=users_with_permission, ) dao_create_template_folder(template_folder) return jsonify(data=template_folder.serialize()), 201 @template_folder_blueprint.route("/", methods=["POST"]) def update_template_folder(service_id, template_folder_id): check_suspicious_id(service_id, template_folder_id) data = request.get_json() validate(data, post_update_template_folder_schema) template_folder = dao_get_template_folder_by_id_and_service_id( template_folder_id, service_id ) template_folder.name = data["name"] if "users_with_permission" in data: template_folder.users = [ dao_get_service_user(user_id, service_id) for user_id in data["users_with_permission"] ] dao_update_template_folder(template_folder) return jsonify(data=template_folder.serialize()), 200 @template_folder_blueprint.route("/", methods=["DELETE"]) def delete_template_folder(service_id, template_folder_id): check_suspicious_id(service_id, template_folder_id) template_folder = dao_get_template_folder_by_id_and_service_id( template_folder_id, service_id ) # don't allow deleting if there's anything in the folder (even if it's just more empty subfolders) if template_folder.subfolders or template_folder.templates: return jsonify(result="error", message="Folder is not empty"), 400 dao_delete_template_folder(template_folder) return "", 204 @template_folder_blueprint.route("/contents", methods=["POST"]) @template_folder_blueprint.route( "//contents", methods=["POST"] ) @autocommit def move_to_template_folder(service_id, target_template_folder_id=None): check_suspicious_id(service_id, target_template_folder_id) data = request.get_json() validate(data, post_move_template_folder_schema) if target_template_folder_id: target_template_folder = dao_get_template_folder_by_id_and_service_id( target_template_folder_id, service_id ) else: target_template_folder = None for template_folder_id in data["folders"]: try: template_folder = dao_get_template_folder_by_id_and_service_id( template_folder_id, service_id ) except NoResultFound: msg = "No folder found with id {} for service {}".format( template_folder_id, service_id ) raise InvalidRequest(msg, status_code=400) _validate_folder_move( target_template_folder, target_template_folder_id, template_folder, template_folder_id, ) template_folder.parent = target_template_folder for template_id in data["templates"]: try: template = dao_get_template_by_id_and_service_id(template_id, service_id) except NoResultFound: msg = "Could not move to folder: No template found with id {} for service {}".format( template_id, service_id ) raise InvalidRequest(msg, status_code=400) if template.archived: current_app.logger.info( "Could not move to folder: Template {} is archived. (Skipping)".format( template_id ) ) else: template.folder = target_template_folder return "", 204 def _validate_folder_move( target_template_folder, target_template_folder_id, template_folder, template_folder_id, ): if str(target_template_folder_id) == str(template_folder_id): msg = "You cannot move a folder to itself" raise InvalidRequest(msg, status_code=400) if target_template_folder and template_folder.is_parent_of(target_template_folder): msg = "You cannot move a folder to one of its subfolders" raise InvalidRequest(msg, status_code=400)