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