folders.py 7.4 KB

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