seitime-frappe/frappe/core/api/file.py
Gavin D'souza 59e45a2e2f refactor: File APIs
Restructured and moved most APIs under frappe.core.api.file namespace.
Changed some obvious security gaps (like using get_list instead of
get_all for an endpoint), styled, added type hints and made minor performance
enhancements.

Changes
* download_file API
    * Move API to handler.py
    * Check for permissions via File.is_downloadable instead
* Moved APIs to new namespace: `frappe.core.api.file`
* Backwards compatibility
    * Added APIs to override_whitelisted_methods to maintain existing
      client endpoints
    * Imported APIs to controller's namespace to avoid breaking external
      app usages
2022-03-15 19:39:47 +05:30

123 lines
2.9 KiB
Python

import json
from typing import Dict, List
import frappe
from frappe.utils import cint, cstr
from frappe.core.doctype.file.file import File, setup_folder_path
@frappe.whitelist()
def unzip_file(name: str):
"""Unzip the given file and make file records for each of the extracted files"""
file: File = frappe.get_doc("File", name)
return file.unzip()
@frappe.whitelist()
def get_attached_images(doctype: str, names: List[str]) -> frappe._dict:
"""get list of image urls attached in form
returns {name: ['image.jpg', 'image.png']}"""
if isinstance(names, str):
names = json.loads(names)
img_urls = frappe.db.get_list(
"File",
filters={
"attached_to_doctype": doctype,
"attached_to_name": ("in", names),
"is_folder": 0,
},
fields=["file_url", "attached_to_name as docname"],
)
out = frappe._dict()
for i in img_urls:
out[i.docname] = out.get(i.docname, [])
out[i.docname].append(i.file_url)
return out
@frappe.whitelist()
def get_files_in_folder(folder: str, start: int = 0, page_length: int = 20) -> Dict:
start = cint(start)
page_length = cint(page_length)
attachment_folder = frappe.db.get_value(
"File",
"Home/Attachments",
["name", "file_name", "file_url", "is_folder", "modified"],
as_dict=1,
)
files = frappe.get_list(
"File",
{"folder": folder},
["name", "file_name", "file_url", "is_folder", "modified"],
start=start,
page_length=page_length + 1,
)
if folder == "Home" and attachment_folder not in files:
files.insert(0, attachment_folder)
return {"files": files[:page_length], "has_more": len(files) > page_length}
@frappe.whitelist()
def get_files_by_search_text(text: str) -> List[Dict]:
if not text:
return []
text = "%" + cstr(text).lower() + "%"
return frappe.get_list(
"File",
fields=["name", "file_name", "file_url", "is_folder", "modified"],
filters={"is_folder": False},
or_filters={
"file_name": ("like", text),
"file_url": text,
"name": ("like", text),
},
order_by="modified desc",
limit=20,
)
@frappe.whitelist(allow_guest=True)
def get_max_file_size() -> int:
return cint(frappe.conf.get("max_file_size")) or 10485760
@frappe.whitelist()
def create_new_folder(file_name: str, folder: str) -> File:
"""create new folder under current parent folder"""
file = frappe.new_doc("File")
file.file_name = file_name
file.is_folder = 1
file.folder = folder
file.insert(ignore_if_duplicate=True)
return file
@frappe.whitelist()
def move_file(file_list: List[File], new_parent: str, old_parent: str) -> None:
if isinstance(file_list, str):
file_list = json.loads(file_list)
for file_obj in file_list:
setup_folder_path(file_obj.get("name"), new_parent)
# recalculate sizes
frappe.get_doc("File", old_parent).save()
frappe.get_doc("File", new_parent).save()
@frappe.whitelist()
def zip_files(files: str):
files = frappe.parse_json(files)
frappe.response["filename"] = "files.zip"
frappe.response["filecontent"] = File.zip_files(files)
frappe.response["type"] = "download"