Skip to main content

docbox_http/models/
folder.rs

1use crate::error::HttpError;
2use axum::http::StatusCode;
3use docbox_core::{
4    database::models::folder::{FolderId, FolderWithExtra, ResolvedFolderWithExtra},
5    folders::create_folder::CreateFolderError,
6};
7use garde::Validate;
8use serde::{Deserialize, Serialize};
9use thiserror::Error;
10use utoipa::ToSchema;
11use uuid::Uuid;
12
13/// Request to create a folder
14#[derive(Debug, Validate, Deserialize, ToSchema)]
15pub struct CreateFolderRequest {
16    /// Name for the folder
17    #[garde(length(min = 1, max = 255))]
18    #[schema(min_length = 1, max_length = 255)]
19    pub name: String,
20
21    /// ID of the folder to store folder in
22    #[garde(skip)]
23    #[schema(value_type = Uuid)]
24    pub folder_id: FolderId,
25}
26
27/// Response for requesting a document box
28#[derive(Debug, Serialize, ToSchema)]
29pub struct FolderResponse {
30    /// The folder itself
31    pub folder: FolderWithExtra,
32
33    /// Resolved contents of the folder
34    pub children: ResolvedFolderWithExtra,
35}
36
37/// Request to rename and or move a folder
38#[derive(Debug, Validate, Deserialize, ToSchema)]
39pub struct UpdateFolderRequest {
40    /// Name for the folder
41    #[garde(inner(length(min = 1, max = 255)))]
42    #[schema(min_length = 1, max_length = 255)]
43    pub name: Option<String>,
44
45    /// ID of the new parent folder for the folder
46    #[garde(skip)]
47    #[schema(value_type = Option<Uuid>)]
48    pub folder_id: Option<FolderId>,
49
50    /// Whether to pin the folder
51    #[garde(skip)]
52    #[schema(value_type = Option<bool>)]
53    pub pinned: Option<bool>,
54}
55
56/// Request to create a zip file of folder contents
57#[derive(Debug, Validate, Deserialize, ToSchema)]
58pub struct ZipFolderRequest {
59    /// Optionally only include the specified items (files and folders)
60    ///
61    /// Inclusion is only applied to the direct descendants
62    /// of the folder use exclude to exclude specific content
63    /// from nested folders
64    #[garde(skip)]
65    #[serde(alias = "include_files")]
66    pub include: Option<Vec<Uuid>>,
67
68    /// Optionally exclude the specified items (files and folders)
69    /// including any items that don't match the provided list of IDs
70    ///
71    /// Exclusion is applied deeply to nested files and folders
72    #[garde(skip)]
73    #[serde(alias = "exclude_files")]
74    pub exclude: Option<Vec<Uuid>>,
75}
76
77#[derive(Debug, Error)]
78pub enum HttpFolderError {
79    #[error("unknown folder")]
80    UnknownFolder,
81
82    /// Failed to create the folder
83    #[error(transparent)]
84    CreateError(CreateFolderError),
85
86    #[error("unknown target folder")]
87    UnknownTargetFolder,
88
89    #[error("cannot delete root folder")]
90    CannotDeleteRoot,
91
92    #[error("cannot modify root folder")]
93    CannotModifyRoot,
94
95    #[error("cannot move a folder into itself")]
96    CannotMoveIntoSelf,
97
98    #[error("failed to create zip file")]
99    CreateZipFile,
100}
101
102impl HttpError for HttpFolderError {
103    fn status(&self) -> axum::http::StatusCode {
104        match self {
105            HttpFolderError::UnknownFolder | HttpFolderError::UnknownTargetFolder => {
106                StatusCode::NOT_FOUND
107            }
108            HttpFolderError::CannotModifyRoot
109            | HttpFolderError::CannotDeleteRoot
110            | HttpFolderError::CannotMoveIntoSelf => StatusCode::BAD_REQUEST,
111            HttpFolderError::CreateError(_) | HttpFolderError::CreateZipFile => {
112                StatusCode::INTERNAL_SERVER_ERROR
113            }
114        }
115    }
116}