folders.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. import logging
  2. import os
  3. import shutil
  4. import uuid
  5. from pathlib import Path
  6. from typing import Optional
  7. from pydantic import BaseModel
  8. import mimetypes
  9. from open_webui.apps.webui.models.folders import (
  10. FolderForm,
  11. FolderItemsUpdateForm,
  12. FolderModel,
  13. Folders,
  14. )
  15. from open_webui.apps.webui.models.chats import Chats
  16. from open_webui.config import UPLOAD_DIR
  17. from open_webui.env import SRC_LOG_LEVELS
  18. from open_webui.constants import ERROR_MESSAGES
  19. from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
  20. from fastapi.responses import FileResponse, StreamingResponse
  21. from open_webui.utils.utils import get_admin_user, get_verified_user
  22. log = logging.getLogger(__name__)
  23. log.setLevel(SRC_LOG_LEVELS["MODELS"])
  24. router = APIRouter()
  25. ############################
  26. # Get Folders
  27. ############################
  28. @router.get("/", response_model=list[FolderModel])
  29. async def get_folders(user=Depends(get_verified_user)):
  30. folders = Folders.get_folders_by_user_id(user.id)
  31. return folders
  32. ############################
  33. # Create Folder
  34. ############################
  35. @router.post("/")
  36. def create_folder(form_data: FolderForm, user=Depends(get_verified_user)):
  37. folder = Folders.get_folder_by_parent_id_and_user_id_and_name(
  38. None, user.id, form_data.name
  39. )
  40. if folder:
  41. raise HTTPException(
  42. status_code=status.HTTP_400_BAD_REQUEST,
  43. detail=ERROR_MESSAGES.DEFAULT("Folder already exists"),
  44. )
  45. try:
  46. folder = Folders.insert_new_folder(user.id, form_data.name)
  47. return folder
  48. except Exception as e:
  49. log.exception(e)
  50. log.error("Error creating folder")
  51. raise HTTPException(
  52. status_code=status.HTTP_400_BAD_REQUEST,
  53. detail=ERROR_MESSAGES.DEFAULT("Error creating folder"),
  54. )
  55. ############################
  56. # Get Folders By Id
  57. ############################
  58. @router.get("/{id}", response_model=Optional[FolderModel])
  59. async def get_folder_by_id(id: str, user=Depends(get_verified_user)):
  60. folder = Folders.get_folder_by_id_and_user_id(id, user.id)
  61. if folder:
  62. return folder
  63. else:
  64. raise HTTPException(
  65. status_code=status.HTTP_404_NOT_FOUND,
  66. detail=ERROR_MESSAGES.NOT_FOUND,
  67. )
  68. ############################
  69. # Update Folder Name By Id
  70. ############################
  71. @router.post("/{id}/update")
  72. async def update_folder_name_by_id(
  73. id: str, form_data: FolderForm, user=Depends(get_verified_user)
  74. ):
  75. folder = Folders.get_folder_by_id_and_user_id(id, user.id)
  76. if folder:
  77. existing_folder = Folders.get_folder_by_parent_id_and_user_id_and_name(
  78. folder.parent_id, user.id, form_data.name
  79. )
  80. if existing_folder:
  81. raise HTTPException(
  82. status_code=status.HTTP_400_BAD_REQUEST,
  83. detail=ERROR_MESSAGES.DEFAULT("Folder already exists"),
  84. )
  85. try:
  86. folder = Folders.update_folder_name_by_id_and_user_id(
  87. id, user.id, form_data.name
  88. )
  89. return folder
  90. except Exception as e:
  91. log.exception(e)
  92. log.error(f"Error updating folder: {id}")
  93. raise HTTPException(
  94. status_code=status.HTTP_400_BAD_REQUEST,
  95. detail=ERROR_MESSAGES.DEFAULT("Error updating folder"),
  96. )
  97. else:
  98. raise HTTPException(
  99. status_code=status.HTTP_404_NOT_FOUND,
  100. detail=ERROR_MESSAGES.NOT_FOUND,
  101. )
  102. ############################
  103. # Update Folder Parent Id By Id
  104. ############################
  105. class FolderParentIdForm(BaseModel):
  106. parent_id: Optional[str] = None
  107. @router.post("/{id}/update/parent")
  108. async def update_folder_parent_id_by_id(
  109. id: str, form_data: FolderParentIdForm, user=Depends(get_verified_user)
  110. ):
  111. folder = Folders.get_folder_by_id_and_user_id(id, user.id)
  112. if folder:
  113. existing_folder = Folders.get_folder_by_parent_id_and_user_id_and_name(
  114. form_data.parent_id, user.id, folder.name
  115. )
  116. if existing_folder:
  117. raise HTTPException(
  118. status_code=status.HTTP_400_BAD_REQUEST,
  119. detail=ERROR_MESSAGES.DEFAULT("Folder already exists"),
  120. )
  121. try:
  122. folder = Folders.update_folder_parent_id_by_id_and_user_id(
  123. id, user.id, form_data.parent_id
  124. )
  125. return folder
  126. except Exception as e:
  127. log.exception(e)
  128. log.error(f"Error updating folder: {id}")
  129. raise HTTPException(
  130. status_code=status.HTTP_400_BAD_REQUEST,
  131. detail=ERROR_MESSAGES.DEFAULT("Error updating folder"),
  132. )
  133. else:
  134. raise HTTPException(
  135. status_code=status.HTTP_404_NOT_FOUND,
  136. detail=ERROR_MESSAGES.NOT_FOUND,
  137. )
  138. ############################
  139. # Update Folder Is Expanded By Id
  140. ############################
  141. class FolderIsExpandedForm(BaseModel):
  142. is_expanded: bool
  143. @router.post("/{id}/update/expanded")
  144. async def update_folder_is_expanded_by_id(
  145. id: str, form_data: FolderIsExpandedForm, user=Depends(get_verified_user)
  146. ):
  147. folder = Folders.get_folder_by_id_and_user_id(id, user.id)
  148. if folder:
  149. try:
  150. folder = Folders.update_folder_is_expanded_by_id_and_user_id(
  151. id, user.id, form_data.is_expanded
  152. )
  153. return folder
  154. except Exception as e:
  155. log.exception(e)
  156. log.error(f"Error updating folder: {id}")
  157. raise HTTPException(
  158. status_code=status.HTTP_400_BAD_REQUEST,
  159. detail=ERROR_MESSAGES.DEFAULT("Error updating folder"),
  160. )
  161. else:
  162. raise HTTPException(
  163. status_code=status.HTTP_404_NOT_FOUND,
  164. detail=ERROR_MESSAGES.NOT_FOUND,
  165. )
  166. ############################
  167. # Update Folder Items By Id
  168. ############################
  169. @router.post("/{id}/update/items")
  170. async def update_folder_items_by_id(
  171. id: str, form_data: FolderItemsUpdateForm, user=Depends(get_verified_user)
  172. ):
  173. folder = Folders.get_folder_by_id_and_user_id(id, user.id)
  174. if folder:
  175. try:
  176. folder = Folders.update_folder_items_by_id_and_user_id(
  177. id, user.id, form_data.items
  178. )
  179. return folder
  180. except Exception as e:
  181. log.exception(e)
  182. log.error(f"Error updating folder: {id}")
  183. raise HTTPException(
  184. status_code=status.HTTP_400_BAD_REQUEST,
  185. detail=ERROR_MESSAGES.DEFAULT("Error updating folder"),
  186. )
  187. else:
  188. raise HTTPException(
  189. status_code=status.HTTP_404_NOT_FOUND,
  190. detail=ERROR_MESSAGES.NOT_FOUND,
  191. )
  192. ############################
  193. # Delete Folder By Id
  194. ############################
  195. @router.delete("/{id}")
  196. async def delete_folder_by_id(id: str, user=Depends(get_verified_user)):
  197. folder = Folders.get_folder_by_id_and_user_id(id, user.id)
  198. if folder:
  199. try:
  200. result = Folders.delete_folder_by_id_and_user_id(id, user.id)
  201. if result:
  202. # Delete all chats in the folder
  203. chats = Chats.get_chats_by_folder_id_and_user_id(id, user.id)
  204. for chat in chats:
  205. Chats.delete_chat_by_id(chat.id, user.id)
  206. return result
  207. else:
  208. raise HTTPException(
  209. status_code=status.HTTP_400_BAD_REQUEST,
  210. detail=ERROR_MESSAGES.DEFAULT("Error deleting folder"),
  211. )
  212. except Exception as e:
  213. log.exception(e)
  214. log.error(f"Error deleting folder: {id}")
  215. raise HTTPException(
  216. status_code=status.HTTP_400_BAD_REQUEST,
  217. detail=ERROR_MESSAGES.DEFAULT("Error deleting folder"),
  218. )
  219. else:
  220. raise HTTPException(
  221. status_code=status.HTTP_404_NOT_FOUND,
  222. detail=ERROR_MESSAGES.NOT_FOUND,
  223. )