409 on duplicate
This commit is contained in:
@@ -12,6 +12,7 @@ pub type AppResult<T> = Result<T, AppError>;
|
||||
pub struct AppError {
|
||||
status: StatusCode,
|
||||
message: String,
|
||||
code: Option<String>,
|
||||
}
|
||||
|
||||
impl AppError {
|
||||
@@ -19,6 +20,7 @@ impl AppError {
|
||||
Self {
|
||||
status,
|
||||
message: message.into(),
|
||||
code: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +28,10 @@ impl AppError {
|
||||
Self::new(StatusCode::BAD_REQUEST, message)
|
||||
}
|
||||
|
||||
pub fn conflict(message: impl Into<String>) -> Self {
|
||||
Self::new(StatusCode::CONFLICT, message)
|
||||
}
|
||||
|
||||
pub fn unauthorized() -> Self {
|
||||
Self::new(StatusCode::UNAUTHORIZED, "unauthorized")
|
||||
}
|
||||
@@ -37,6 +43,11 @@ impl AppError {
|
||||
pub fn internal<E: Display>(error: E) -> Self {
|
||||
Self::new(StatusCode::INTERNAL_SERVER_ERROR, error.to_string())
|
||||
}
|
||||
|
||||
pub fn with_code(mut self, code: impl Into<String>) -> Self {
|
||||
self.code = Some(code.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for AppError {
|
||||
@@ -44,6 +55,7 @@ impl IntoResponse for AppError {
|
||||
let status = self.status;
|
||||
let body = Json(ErrorResponse {
|
||||
error: self.message,
|
||||
code: self.code,
|
||||
});
|
||||
(status, body).into_response()
|
||||
}
|
||||
@@ -52,6 +64,8 @@ impl IntoResponse for AppError {
|
||||
#[derive(Serialize)]
|
||||
struct ErrorResponse {
|
||||
error: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
code: Option<String>,
|
||||
}
|
||||
|
||||
impl From<diesel::result::Error> for AppError {
|
||||
|
||||
@@ -1151,9 +1151,10 @@ pub async fn update_document(
|
||||
match update_result.execute(&mut conn) {
|
||||
Ok(_) => {}
|
||||
Err(diesel::result::Error::DatabaseError(DatabaseErrorKind::UniqueViolation, _)) => {
|
||||
return Err(AppError::bad_request(
|
||||
return Err(AppError::conflict(
|
||||
"another document in this folder already uses that filename",
|
||||
));
|
||||
)
|
||||
.with_code("duplicate_filename"));
|
||||
}
|
||||
Err(err) => return Err(AppError::from(err)),
|
||||
}
|
||||
@@ -1822,7 +1823,7 @@ async fn process_upload(
|
||||
|
||||
let (document, version) = {
|
||||
let mut conn = state.db_for_tenant(tenant_id)?;
|
||||
conn.transaction(|conn| {
|
||||
let transaction_result = conn.transaction(|conn| {
|
||||
let new_document = NewDocument {
|
||||
id: doc_id,
|
||||
filename: stored_filename.clone(),
|
||||
@@ -1859,7 +1860,18 @@ async fn process_upload(
|
||||
let version: DocumentVersion = document_versions::table.find(version_id).first(conn)?;
|
||||
|
||||
Ok::<_, diesel::result::Error>((document, version))
|
||||
})?
|
||||
});
|
||||
|
||||
match transaction_result {
|
||||
Ok(result) => result,
|
||||
Err(diesel::result::Error::DatabaseError(DatabaseErrorKind::UniqueViolation, _)) => {
|
||||
return Err(AppError::conflict(
|
||||
"another document in this folder already uses that filename",
|
||||
)
|
||||
.with_code("duplicate_filename"))
|
||||
}
|
||||
Err(err) => return Err(AppError::from(err)),
|
||||
}
|
||||
};
|
||||
|
||||
let detail = {
|
||||
|
||||
Reference in New Issue
Block a user