folder create idempotency
This commit is contained in:
@@ -502,7 +502,10 @@ mod doc {
|
|||||||
post,
|
post,
|
||||||
path = "/api/folders",
|
path = "/api/folders",
|
||||||
request_body = CreateFolderRequest,
|
request_body = CreateFolderRequest,
|
||||||
responses((status = 200, description = "Folder created", body = FolderResponse)),
|
responses(
|
||||||
|
(status = 201, description = "Folder created", body = FolderResponse),
|
||||||
|
(status = 200, description = "Folder already existed", body = FolderResponse)
|
||||||
|
),
|
||||||
tag = "Folders"
|
tag = "Folders"
|
||||||
)]
|
)]
|
||||||
pub(super) fn create_folder() {}
|
pub(super) fn create_folder() {}
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ pub async fn create_folder(
|
|||||||
..
|
..
|
||||||
}: TenantScopedConn,
|
}: TenantScopedConn,
|
||||||
Json(payload): Json<CreateFolderRequest>,
|
Json(payload): Json<CreateFolderRequest>,
|
||||||
) -> AppResult<Json<FolderResponse>> {
|
) -> AppResult<(StatusCode, Json<FolderResponse>)> {
|
||||||
if payload.name.trim().is_empty() {
|
if payload.name.trim().is_empty() {
|
||||||
return Err(AppError::bad_request("name must not be empty"));
|
return Err(AppError::bad_request("name must not be empty"));
|
||||||
}
|
}
|
||||||
@@ -202,8 +202,8 @@ pub async fn create_folder(
|
|||||||
.optional()?
|
.optional()?
|
||||||
};
|
};
|
||||||
|
|
||||||
let folder: Folder = if let Some(folder) = existing {
|
let (folder, created): (Folder, bool) = if let Some(folder) = existing {
|
||||||
folder
|
(folder, false)
|
||||||
} else {
|
} else {
|
||||||
let new_folder = NewFolder {
|
let new_folder = NewFolder {
|
||||||
id: Uuid::new_v4(),
|
id: Uuid::new_v4(),
|
||||||
@@ -220,28 +220,43 @@ pub async fn create_folder(
|
|||||||
.optional()?;
|
.optional()?;
|
||||||
|
|
||||||
if let Some(id) = inserted_id {
|
if let Some(id) = inserted_id {
|
||||||
|
(
|
||||||
folders::table
|
folders::table
|
||||||
.find(id)
|
.find(id)
|
||||||
.filter(folders::tenant_id.eq(tenant_id))
|
.filter(folders::tenant_id.eq(tenant_id))
|
||||||
.first(&mut conn)?
|
.first(&mut conn)?,
|
||||||
|
true,
|
||||||
|
)
|
||||||
} else if let Some(parent_id) = payload.parent_id {
|
} else if let Some(parent_id) = payload.parent_id {
|
||||||
|
(
|
||||||
folders::table
|
folders::table
|
||||||
.filter(folders::tenant_id.eq(tenant_id))
|
.filter(folders::tenant_id.eq(tenant_id))
|
||||||
.filter(folders::parent_id.eq(Some(parent_id)))
|
.filter(folders::parent_id.eq(Some(parent_id)))
|
||||||
.filter(folders::name.eq(name))
|
.filter(folders::name.eq(name))
|
||||||
.first(&mut conn)?
|
.first(&mut conn)?,
|
||||||
|
false,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
|
(
|
||||||
folders::table
|
folders::table
|
||||||
.filter(folders::tenant_id.eq(tenant_id))
|
.filter(folders::tenant_id.eq(tenant_id))
|
||||||
.filter(folders::parent_id.is_null())
|
.filter(folders::parent_id.is_null())
|
||||||
.filter(folders::name.eq(name))
|
.filter(folders::name.eq(name))
|
||||||
.first(&mut conn)?
|
.first(&mut conn)?,
|
||||||
|
false,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Json(FolderResponse {
|
let response = Json(FolderResponse {
|
||||||
folder: folder_to_info(folder),
|
folder: folder_to_info(folder),
|
||||||
}))
|
});
|
||||||
|
|
||||||
|
if created {
|
||||||
|
Ok((StatusCode::CREATED, response))
|
||||||
|
} else {
|
||||||
|
Ok((StatusCode::OK, response))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_folder_contents(
|
pub async fn list_folder_contents(
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ async fn folder_move_and_delete_flow() -> Result<()> {
|
|||||||
Some(&token),
|
Some(&token),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
assert_eq!(folder_resp.status(), StatusCode::OK);
|
assert_eq!(folder_resp.status(), StatusCode::CREATED);
|
||||||
let folder_body = body_to_vec(folder_resp.into_body()).await?;
|
let folder_body = body_to_vec(folder_resp.into_body()).await?;
|
||||||
let folder: FolderResponse = serde_json::from_slice(&folder_body)?;
|
let folder: FolderResponse = serde_json::from_slice(&folder_body)?;
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ async fn update_folder_parent_to_root() -> Result<()> {
|
|||||||
Some(&token),
|
Some(&token),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
assert_eq!(parent_resp.status(), StatusCode::OK);
|
assert_eq!(parent_resp.status(), StatusCode::CREATED);
|
||||||
let parent_body = body_to_vec(parent_resp.into_body()).await?;
|
let parent_body = body_to_vec(parent_resp.into_body()).await?;
|
||||||
let parent: FolderResponse = serde_json::from_slice(&parent_body)?;
|
let parent: FolderResponse = serde_json::from_slice(&parent_body)?;
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ async fn update_folder_parent_to_root() -> Result<()> {
|
|||||||
Some(&token),
|
Some(&token),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
assert_eq!(child_resp.status(), StatusCode::OK);
|
assert_eq!(child_resp.status(), StatusCode::CREATED);
|
||||||
let child_body = body_to_vec(child_resp.into_body()).await?;
|
let child_body = body_to_vec(child_resp.into_body()).await?;
|
||||||
let child: FolderResponse = serde_json::from_slice(&child_body)?;
|
let child: FolderResponse = serde_json::from_slice(&child_body)?;
|
||||||
|
|
||||||
@@ -310,14 +310,14 @@ async fn create_folder_is_idempotent() -> Result<()> {
|
|||||||
let first_resp = app
|
let first_resp = app
|
||||||
.post_json("/api/folders", &payload, Some(&token))
|
.post_json("/api/folders", &payload, Some(&token))
|
||||||
.await?;
|
.await?;
|
||||||
assert!(first_resp.status().is_success());
|
assert_eq!(first_resp.status(), StatusCode::CREATED);
|
||||||
let first_body = body_to_vec(first_resp.into_body()).await?;
|
let first_body = body_to_vec(first_resp.into_body()).await?;
|
||||||
let first_folder: FolderResponse = serde_json::from_slice(&first_body)?;
|
let first_folder: FolderResponse = serde_json::from_slice(&first_body)?;
|
||||||
|
|
||||||
let second_resp = app
|
let second_resp = app
|
||||||
.post_json("/api/folders", &payload, Some(&token))
|
.post_json("/api/folders", &payload, Some(&token))
|
||||||
.await?;
|
.await?;
|
||||||
assert!(second_resp.status().is_success());
|
assert_eq!(second_resp.status(), StatusCode::OK);
|
||||||
let second_body = body_to_vec(second_resp.into_body()).await?;
|
let second_body = body_to_vec(second_resp.into_body()).await?;
|
||||||
let second_folder: FolderResponse = serde_json::from_slice(&second_body)?;
|
let second_folder: FolderResponse = serde_json::from_slice(&second_body)?;
|
||||||
|
|
||||||
@@ -424,7 +424,7 @@ async fn folder_rename_updates_name_and_child_paths() -> Result<()> {
|
|||||||
Some(&token),
|
Some(&token),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
assert_eq!(parent_resp.status(), StatusCode::OK);
|
assert_eq!(parent_resp.status(), StatusCode::CREATED);
|
||||||
let parent_body = body_to_vec(parent_resp.into_body()).await?;
|
let parent_body = body_to_vec(parent_resp.into_body()).await?;
|
||||||
let parent: FolderResponse = serde_json::from_slice(&parent_body)?;
|
let parent: FolderResponse = serde_json::from_slice(&parent_body)?;
|
||||||
|
|
||||||
@@ -438,7 +438,7 @@ async fn folder_rename_updates_name_and_child_paths() -> Result<()> {
|
|||||||
Some(&token),
|
Some(&token),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
assert_eq!(child_resp.status(), StatusCode::OK);
|
assert_eq!(child_resp.status(), StatusCode::CREATED);
|
||||||
let child_body = body_to_vec(child_resp.into_body()).await?;
|
let child_body = body_to_vec(child_resp.into_body()).await?;
|
||||||
let child: FolderResponse = serde_json::from_slice(&child_body)?;
|
let child: FolderResponse = serde_json::from_slice(&child_body)?;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user