diff options
| -rw-r--r-- | rust/fatcat-api-spec/README.md | 2 | ||||
| -rw-r--r-- | rust/fatcat-api-spec/api.yaml | 11 | ||||
| -rw-r--r-- | rust/fatcat-api-spec/api/swagger.yaml | 10 | ||||
| -rw-r--r-- | rust/fatcat-api-spec/src/models.rs | 21 | ||||
| -rw-r--r-- | rust/src/endpoints.rs | 298 | 
5 files changed, 238 insertions, 104 deletions
diff --git a/rust/fatcat-api-spec/README.md b/rust/fatcat-api-spec/README.md index 3dcee270..95a39ba3 100644 --- a/rust/fatcat-api-spec/README.md +++ b/rust/fatcat-api-spec/README.md @@ -13,7 +13,7 @@ To see how to make this your own, look here:  [README](https://github.com/swagger-api/swagger-codegen/blob/master/README.md)  - API version: 0.1.0 -- Build date: 2019-01-09T21:14:27.679Z +- Build date: 2019-01-09T23:33:10.040Z  This autogenerated project defines an API crate `fatcat` which contains:  * An `Api` trait defining the API in Rust. diff --git a/rust/fatcat-api-spec/api.yaml b/rust/fatcat-api-spec/api.yaml index 38f06948..da582ade 100644 --- a/rust/fatcat-api-spec/api.yaml +++ b/rust/fatcat-api-spec/api.yaml @@ -101,16 +101,25 @@ definitions:    error_response:      type: object      required: +      - success +      - error        - message      properties: +      success: +        type: boolean +      error: +        type: string        message:          type: string          example: "A really confusing, totally unexpected thing happened"    success:      type: object      required: +      - success        - message      properties: +      success: +        type: boolean        message:          type: string          example: "The computers did the thing successfully!" @@ -721,7 +730,7 @@ paths:        parameters:          - name: editgroup_id            in: query -          required: true  +          required: true            type: string        security:          - Bearer: [] diff --git a/rust/fatcat-api-spec/api/swagger.yaml b/rust/fatcat-api-spec/api/swagger.yaml index 7ee33725..293186c6 100644 --- a/rust/fatcat-api-spec/api/swagger.yaml +++ b/rust/fatcat-api-spec/api/swagger.yaml @@ -6734,8 +6734,14 @@ definitions:    error_response:      type: "object"      required: +    - "error"      - "message" +    - "success"      properties: +      success: +        type: "boolean" +      error: +        type: "string"        message:          type: "string"          example: "A really confusing, totally unexpected thing happened" @@ -6744,11 +6750,15 @@ definitions:      type: "object"      required:      - "message" +    - "success"      properties: +      success: +        type: "boolean"        message:          type: "string"          example: "The computers did the thing successfully!"      example: +      success: true        message: "The computers did the thing successfully!"      upperCaseName: "SUCCESS"    container_entity: diff --git a/rust/fatcat-api-spec/src/models.rs b/rust/fatcat-api-spec/src/models.rs index 536bdd24..a5c588a0 100644 --- a/rust/fatcat-api-spec/src/models.rs +++ b/rust/fatcat-api-spec/src/models.rs @@ -411,13 +411,23 @@ impl EntityHistoryEntry {  #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]  pub struct ErrorResponse { +    #[serde(rename = "success")] +    pub success: bool, + +    #[serde(rename = "error")] +    pub error: String, +      #[serde(rename = "message")]      pub message: String,  }  impl ErrorResponse { -    pub fn new(message: String) -> ErrorResponse { -        ErrorResponse { message: message } +    pub fn new(success: bool, error: String, message: String) -> ErrorResponse { +        ErrorResponse { +            success: success, +            error: error, +            message: message, +        }      }  } @@ -911,13 +921,16 @@ impl ReleaseRef {  #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]  pub struct Success { +    #[serde(rename = "success")] +    pub success: bool, +      #[serde(rename = "message")]      pub message: String,  }  impl Success { -    pub fn new(message: String) -> Success { -        Success { message: message } +    pub fn new(success: bool, message: String) -> Success { +        Success { success: success, message: message }      }  } diff --git a/rust/src/endpoints.rs b/rust/src/endpoints.rs index c49fbfc7..f7f2d948 100644 --- a/rust/src/endpoints.rs +++ b/rust/src/endpoints.rs @@ -66,22 +66,23 @@ macro_rules! wrap_entity_handlers {                  Ok(entity) =>                      $get_resp::FoundEntity(entity),                  Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => -                    $get_resp::NotFound(ErrorResponse { message: format!("No such entity {}: {}", stringify!($model), ident) }), +                    $get_resp::NotFound(ErrorResponse { success: false, error: "not-found".to_string(), message: format!("No such entity {}: {}", stringify!($model), ident) }),                  Err(Error(ErrorKind::Uuid(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "uuid".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidFatcatId(e), _)) =>                      $get_resp::BadRequest(ErrorResponse { +                        success: false, error: "fatcat-id".to_string(),                          message: ErrorKind::InvalidFatcatId(e).to_string() }),                  Err(Error(ErrorKind::MalformedExternalId(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::EditgroupAlreadyAccepted(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "editgroup".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $get_resp::GenericError(ErrorResponse { message: e.to_string() }) +                    $get_resp::GenericError(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -106,31 +107,32 @@ macro_rules! wrap_entity_handlers {                  Ok(edit) =>                      $post_resp::CreatedEntity(edit),                  Err(Error(ErrorKind::Diesel(e), _)) => -                    $post_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    // TODO: needs refinement; what kind of Diesel error? +                    $post_resp::BadRequest(ErrorResponse { success: false, error: "database".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::Uuid(e), _)) => -                    $post_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_resp::BadRequest(ErrorResponse { success: false, error: "uuid".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidFatcatId(e), _)) =>                      $post_resp::BadRequest(ErrorResponse { +                        success: false, error: "fatcat-id".to_string(),                          message: ErrorKind::InvalidFatcatId(e).to_string() }),                  Err(Error(ErrorKind::MalformedExternalId(e), _)) => -                    $post_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::MalformedChecksum(e), _)) => -                    $post_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::NotInControlledVocabulary(e), _)) => -                    $post_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::EditgroupAlreadyAccepted(e), _)) => -                    $post_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_resp::BadRequest(ErrorResponse { success: false, error: "editgroup".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidCredentials(e), _)) => -                    // TODO: why can't I NotAuthorized here? -                    $post_resp::Forbidden(ErrorResponse { message: e.to_string() }), +                    $post_resp::Forbidden(ErrorResponse { success: false, error: "auth".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InsufficientPrivileges(e), _)) => -                    $post_resp::Forbidden(ErrorResponse { message: e.to_string() }), +                    $post_resp::Forbidden(ErrorResponse { success: false, error: "auth".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $post_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $post_resp::GenericError(ErrorResponse { message: e.to_string() }) +                    $post_resp::GenericError(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -157,31 +159,32 @@ macro_rules! wrap_entity_handlers {                  Ok(edit) =>                      $post_batch_resp::CreatedEntities(edit),                  Err(Error(ErrorKind::Diesel(e), _)) => -                    $post_batch_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_batch_resp::BadRequest(ErrorResponse { success: false, error: "database".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::Uuid(e), _)) => -                    $post_batch_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_batch_resp::BadRequest(ErrorResponse { success: false, error: "uuid".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidFatcatId(e), _)) =>                      $post_batch_resp::BadRequest(ErrorResponse { +                        success: false, error: "fatcat-id".to_string(),                          message: ErrorKind::InvalidFatcatId(e).to_string() }),                  Err(Error(ErrorKind::MalformedExternalId(e), _)) => -                    $post_batch_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_batch_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::MalformedChecksum(e), _)) => -                    $post_batch_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_batch_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::NotInControlledVocabulary(e), _)) => -                    $post_batch_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_batch_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::EditgroupAlreadyAccepted(e), _)) => -                    $post_batch_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_batch_resp::BadRequest(ErrorResponse { success: false, error: "editgroup".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidCredentials(e), _)) =>                      // TODO: why can't I NotAuthorized here? -                    $post_batch_resp::Forbidden(ErrorResponse { message: e.to_string() }), +                    $post_batch_resp::Forbidden(ErrorResponse { success: false, error: "auth".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InsufficientPrivileges(e), _)) => -                    $post_batch_resp::Forbidden(ErrorResponse { message: e.to_string() }), +                    $post_batch_resp::Forbidden(ErrorResponse { success: false, error: "auth".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $post_batch_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $post_batch_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $post_batch_resp::GenericError(ErrorResponse { message: e.to_string() }) +                    $post_batch_resp::GenericError(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -208,35 +211,35 @@ macro_rules! wrap_entity_handlers {                  Ok(edit) =>                      $update_resp::UpdatedEntity(edit),                  Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => -                    $update_resp::NotFound(ErrorResponse { message: format!("No such entity {}: {}", stringify!($model), ident) }), +                    $update_resp::NotFound(ErrorResponse { success: false, error: "not-found".to_string(), message: format!("No such entity {}: {}", stringify!($model), ident) }),                  Err(Error(ErrorKind::Diesel(e), _)) => -                    $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $update_resp::BadRequest(ErrorResponse { success: false, error: "database".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::Uuid(e), _)) => -                    $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $update_resp::BadRequest(ErrorResponse { success: false, error: "uuid".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidFatcatId(e), _)) =>                      $update_resp::BadRequest(ErrorResponse { +                        success: false, error: "fatcat-id".to_string(),                          message: ErrorKind::InvalidFatcatId(e).to_string() }),                  Err(Error(ErrorKind::MalformedExternalId(e), _)) => -                    $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $update_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::MalformedChecksum(e), _)) => -                    $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $update_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::NotInControlledVocabulary(e), _)) => -                    $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $update_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::EditgroupAlreadyAccepted(e), _)) => -                    $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $update_resp::BadRequest(ErrorResponse { success: false, error: "editgroup".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidEntityStateTransform(e), _)) => -                    $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $update_resp::BadRequest(ErrorResponse { success: false, error: "entity-state".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $update_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $update_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidCredentials(e), _)) => -                    // TODO: why can't I NotAuthorized here? -                    $update_resp::Forbidden(ErrorResponse { message: e.to_string() }), +                    $update_resp::Forbidden(ErrorResponse { success: false, error: "auth".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InsufficientPrivileges(e), _)) => -                    $update_resp::Forbidden(ErrorResponse { message: e.to_string() }), +                    $update_resp::Forbidden(ErrorResponse { success: false, error: "auth".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $update_resp::GenericError(ErrorResponse { message: e.to_string() }) +                    $update_resp::GenericError(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -262,31 +265,31 @@ macro_rules! wrap_entity_handlers {                  Ok(edit) =>                      $delete_resp::DeletedEntity(edit),                  Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => -                    $delete_resp::NotFound(ErrorResponse { message: format!("No such entity {}: {}", stringify!($model), ident) }), +                    $delete_resp::NotFound(ErrorResponse { success: false, error: "not-found".to_string(), message: format!("No such entity {}: {}", stringify!($model), ident) }),                  Err(Error(ErrorKind::Diesel(e), _)) => -                    $delete_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $delete_resp::BadRequest(ErrorResponse { success: false, error: "database".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::Uuid(e), _)) => -                    $delete_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $delete_resp::BadRequest(ErrorResponse { success: false, error: "uuid".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidFatcatId(e), _)) =>                      $delete_resp::BadRequest(ErrorResponse { +                        success: false, error: "fatcat-id".to_string(),                          message: ErrorKind::InvalidFatcatId(e).to_string() }),                  Err(Error(ErrorKind::MalformedExternalId(e), _)) => -                    $delete_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $delete_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::EditgroupAlreadyAccepted(e), _)) => -                    $delete_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $delete_resp::BadRequest(ErrorResponse { success: false, error: "editgroup".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidEntityStateTransform(e), _)) => -                    $delete_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $delete_resp::BadRequest(ErrorResponse { success: false, error: "entity-state".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $delete_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $delete_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidCredentials(e), _)) => -                    // TODO: why can't I NotAuthorized here? -                    $delete_resp::Forbidden(ErrorResponse { message: e.to_string() }), +                    $delete_resp::Forbidden(ErrorResponse { success: false, error: "auth".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InsufficientPrivileges(e), _)) => -                    $delete_resp::Forbidden(ErrorResponse { message: e.to_string() }), +                    $delete_resp::Forbidden(ErrorResponse { success: false, error: "auth".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $delete_resp::GenericError(ErrorResponse { message: e.to_string() }) +                    $delete_resp::GenericError(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -307,18 +310,19 @@ macro_rules! wrap_entity_handlers {                  Ok(history) =>                      $get_history_resp::FoundEntityHistory(history),                  Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => -                    $get_history_resp::NotFound(ErrorResponse { message: format!("No such entity {}: {}", stringify!($model), ident) }), +                    $get_history_resp::NotFound(ErrorResponse { success: false, error: "not-found".to_string(), message: format!("No such entity {}: {}", stringify!($model), ident) }),                  Err(Error(ErrorKind::Uuid(e), _)) => -                    $get_history_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_history_resp::BadRequest(ErrorResponse { success: false, error: "uuid".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidFatcatId(e), _)) =>                      $get_history_resp::BadRequest(ErrorResponse { +                        success: false, error: "fatcat-id".to_string(),                          message: ErrorKind::InvalidFatcatId(e).to_string() }),                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $get_history_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_history_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $get_history_resp::GenericError(ErrorResponse { message: e.to_string() }) +                    $get_history_resp::GenericError(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -352,17 +356,17 @@ macro_rules! wrap_entity_handlers {                  Ok(entity) =>                      $get_rev_resp::FoundEntityRevision(entity),                  Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => -                    $get_rev_resp::NotFound(ErrorResponse { message: format!("No such entity revision {}: {}", stringify!($model), rev_id) }), +                    $get_rev_resp::NotFound(ErrorResponse { success: false, error: "not-found".to_string(), message: format!("No such entity revision {}: {}", stringify!($model), rev_id) }),                  Err(Error(ErrorKind::Uuid(e), _)) => -                    $get_rev_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_rev_resp::BadRequest(ErrorResponse { success: false, error: "uuid".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::MalformedExternalId(e), _)) => -                    $get_rev_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_rev_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $get_rev_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_rev_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $get_rev_resp::GenericError(ErrorResponse { message: e.to_string() }) +                    $get_rev_resp::GenericError(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -382,13 +386,13 @@ macro_rules! wrap_entity_handlers {                  Ok(edit) =>                      $get_edit_resp::FoundEdit(edit),                  Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => -                    $get_edit_resp::NotFound(ErrorResponse { message: format!("No such {} entity edit: {}", stringify!($model), edit_id) }), +                    $get_edit_resp::NotFound(ErrorResponse { success: false, error: "not-found".to_string(), message: format!("No such {} entity edit: {}", stringify!($model), edit_id) }),                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $get_edit_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_edit_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $get_edit_resp::GenericError(ErrorResponse { message: e.to_string() }) +                    $get_edit_resp::GenericError(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -409,23 +413,26 @@ macro_rules! wrap_entity_handlers {                  $model::db_delete_edit(&conn, edit_id)              }) {                  Ok(()) => -                    $delete_edit_resp::DeletedEdit(Success { message: format!("Successfully deleted work-in-progress {} edit: {}", stringify!($model), edit_id) } ), Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => -                    $delete_edit_resp::NotFound(ErrorResponse { message: format!("No such {} edit: {}", stringify!($model), edit_id) }), +                    $delete_edit_resp::DeletedEdit(Success { +                        success: true, +                        message: format!("Successfully deleted work-in-progress {} edit: {}", stringify!($model), edit_id) +                }), +                Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => +                    $delete_edit_resp::NotFound(ErrorResponse { success: false, error: "not-found".to_string(), message: format!("No such {} edit: {}", stringify!($model), edit_id) }),                  Err(Error(ErrorKind::Diesel(e), _)) => -                    $delete_edit_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $delete_edit_resp::BadRequest(ErrorResponse { success: false, error: "database".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::EditgroupAlreadyAccepted(e), _)) => -                    $delete_edit_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $delete_edit_resp::BadRequest(ErrorResponse { success: false, error: "editgroup".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $delete_edit_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $delete_edit_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidCredentials(e), _)) => -                    // TODO: why can't I NotAuthorized here? -                    $delete_edit_resp::Forbidden(ErrorResponse { message: e.to_string() }), +                    $delete_edit_resp::Forbidden(ErrorResponse { success: false, error: "auth".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InsufficientPrivileges(e), _)) => -                    $delete_edit_resp::Forbidden(ErrorResponse { message: e.to_string() }), +                    $delete_edit_resp::Forbidden(ErrorResponse { success: false, error: "auth".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $delete_edit_resp::GenericError(ErrorResponse { message: e.to_string() }) +                    $delete_edit_resp::GenericError(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -446,18 +453,19 @@ macro_rules! wrap_entity_handlers {                  Ok(redirects) =>                      $get_redirects_resp::FoundEntityRedirects(redirects),                  Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => -                    $get_redirects_resp::NotFound(ErrorResponse { message: format!("No such entity {}: {}", stringify!($model), ident) }), +                    $get_redirects_resp::NotFound(ErrorResponse { success: false, error: "not-found".to_string(), message: format!("No such entity {}: {}", stringify!($model), ident) }),                  Err(Error(ErrorKind::Uuid(e), _)) => -                    $get_redirects_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_redirects_resp::BadRequest(ErrorResponse { success: false, error: "uuid".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::InvalidFatcatId(e), _)) =>                      $get_redirects_resp::BadRequest(ErrorResponse { +                        success: false, error: "fatcat-id".to_string(),                          message: ErrorKind::InvalidFatcatId(e).to_string() }),                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $get_redirects_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_redirects_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $get_redirects_resp::GenericError(ErrorResponse { message: e.to_string() }) +                    $get_redirects_resp::GenericError(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -490,19 +498,19 @@ macro_rules! wrap_lookup_handler {                  Ok(entity) =>                      $get_resp::FoundEntity(entity),                  Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => -                    $get_resp::NotFound(ErrorResponse { message: format!("Not found: {:?} / {:?}", $idname, wikidata_qid) }), +                    $get_resp::NotFound(ErrorResponse { success: false, error: "not-found".to_string(), message: format!("Not found: {:?} / {:?}", $idname, wikidata_qid) }),                  Err(Error(ErrorKind::MalformedExternalId(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::MalformedChecksum(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::MissingOrMultipleExternalId(e), _)) => { -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string(), }) }, +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string(), }) },                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }) +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -526,17 +534,17 @@ macro_rules! wrap_fcid_handler {                  Ok(entity) =>                      $get_resp::Found(entity),                  Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => -                    $get_resp::NotFound(ErrorResponse { message: format!("Not found: {}", id) }), +                    $get_resp::NotFound(ErrorResponse { success: false, error: "not-found".to_string(), message: format!("Not found: {}", id) }),                  Err(Error(ErrorKind::MalformedExternalId(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::NotInControlledVocabulary(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }) +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -565,17 +573,19 @@ macro_rules! wrap_fcid_hide_handler {                  Ok(entity) =>                      $get_resp::Found(entity),                  Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => -                    $get_resp::NotFound(ErrorResponse { message: format!("Not found: {}", id) }), +                    $get_resp::NotFound(ErrorResponse { success: false, +                                        error: "not-found".to_string(), +                                        message: format!("Not found: {}", id) }),                  Err(Error(ErrorKind::MalformedExternalId(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::NotInControlledVocabulary(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "field-syntax".to_string(), message: e.to_string() }),                  Err(Error(ErrorKind::OtherBadRequest(e), _)) => -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }), +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "other".to_string(), message: e.to_string() }),                  Err(e) => {                      error!("{}", e);                      capture_error_chain(&e); -                    $get_resp::BadRequest(ErrorResponse { message: e.to_string() }) +                    $get_resp::BadRequest(ErrorResponse { success: false, error: "internal".to_string(), message: e.to_string() })                  },              };              Box::new(futures::done(Ok(ret))) @@ -823,21 +833,29 @@ impl Api for Server {                  Ok(entity) => LookupFileResponse::FoundEntity(entity),                  Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => {                      LookupFileResponse::NotFound(ErrorResponse { +                        success: false, +                        error: "not-found".to_string(),                          message: format!("Not found: {:?} / {:?} / {:?}", md5, sha1, sha256),                      })                  }                  Err(Error(ErrorKind::MalformedExternalId(e), _)) => {                      LookupFileResponse::BadRequest(ErrorResponse { +                        success: false, +                        error: "field-syntax".to_string(),                          message: e.to_string(),                      })                  }                  Err(Error(ErrorKind::MalformedChecksum(e), _)) => {                      LookupFileResponse::BadRequest(ErrorResponse { +                        success: false, +                        error: "field-syntax".to_string(),                          message: e.to_string(),                      })                  }                  Err(Error(ErrorKind::MissingOrMultipleExternalId(e), _)) => {                      LookupFileResponse::BadRequest(ErrorResponse { +                        success: false, +                        error: "field-syntax".to_string(),                          message: e.to_string(),                      })                  } @@ -845,6 +863,8 @@ impl Api for Server {                      error!("{}", e);                      capture_error_chain(&e);                      LookupFileResponse::BadRequest(ErrorResponse { +                        success: false, +                        error: "internal".to_string(),                          message: e.to_string(),                      })                  } @@ -888,6 +908,8 @@ impl Api for Server {              Ok(entity) => LookupReleaseResponse::FoundEntity(entity),              Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => {                  LookupReleaseResponse::NotFound(ErrorResponse { +                    success: false, +                    error: "not-found".to_string(),                      message: format!(                          "Not found: {:?} / {:?} / {:?} / {:?} / {:?} / {:?}",                          doi, wikidata_qid, isbn13, pmid, pmcid, core_id @@ -896,11 +918,15 @@ impl Api for Server {              }              Err(Error(ErrorKind::MalformedExternalId(e), _)) => {                  LookupReleaseResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "field-syntax".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::MissingOrMultipleExternalId(e), _)) => {                  LookupReleaseResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "field-syntax".to_string(),                      message: e.to_string(),                  })              } @@ -908,6 +934,8 @@ impl Api for Server {                  error!("{}", e);                  capture_error_chain(&e);                  LookupReleaseResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "internal".to_string(),                      message: e.to_string(),                  })              } @@ -948,36 +976,48 @@ impl Api for Server {              Ok(editor) => UpdateEditorResponse::UpdatedEditor(editor),              Err(Error(ErrorKind::Diesel(e), _)) => {                  UpdateEditorResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "database".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::Uuid(e), _)) => UpdateEditorResponse::BadRequest(ErrorResponse { +                success: false, +                error: "uuid".to_string(),                  message: e.to_string(),              }),              Err(Error(ErrorKind::InvalidFatcatId(e), _)) => {                  UpdateEditorResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "fatcat-id".to_string(),                      message: ErrorKind::InvalidFatcatId(e).to_string(),                  })              }              Err(Error(ErrorKind::MalformedExternalId(e), _)) => {                  UpdateEditorResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "field-syntax".to_string(),                      message: e.to_string(),                  })              } -            Err(Error(ErrorKind::InvalidCredentials(e), _)) => -            // TODO: why can't I NotAuthorized here? -            { +            Err(Error(ErrorKind::InvalidCredentials(e), _)) => {                  UpdateEditorResponse::Forbidden(ErrorResponse { +                    success: false, +                    error: "auth".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::InsufficientPrivileges(e), _)) => {                  UpdateEditorResponse::Forbidden(ErrorResponse { +                    success: false, +                    error: "auth".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::OtherBadRequest(e), _)) => {                  UpdateEditorResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "other".to_string(),                      message: e.to_string(),                  })              } @@ -985,6 +1025,8 @@ impl Api for Server {                  error!("{}", e);                  capture_error_chain(&e);                  UpdateEditorResponse::GenericError(ErrorResponse { +                    success: false, +                    error: "internal".to_string(),                      message: e.to_string(),                  })              } @@ -1011,29 +1053,40 @@ impl Api for Server {              self.accept_editgroup_handler(&conn, editgroup_id)          }) {              Ok(()) => AcceptEditgroupResponse::MergedSuccessfully(Success { +                success: true,                  message: "horray!".to_string(),              }),              Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => {                  AcceptEditgroupResponse::NotFound(ErrorResponse { +                    success: false, +                    error: "not-found".to_string(),                      message: format!("No such editgroup: {}", editgroup_id),                  })              }              Err(Error(ErrorKind::EditgroupAlreadyAccepted(e), _)) => {                  AcceptEditgroupResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "editgroup".to_string(),                      message: ErrorKind::EditgroupAlreadyAccepted(e).to_string(),                  })              }              Err(Error(ErrorKind::InvalidCredentials(e), _)) => {                  AcceptEditgroupResponse::Forbidden(ErrorResponse { +                    success: false, +                    error: "auth".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::InsufficientPrivileges(e), _)) => {                  AcceptEditgroupResponse::Forbidden(ErrorResponse { +                    success: false, +                    error: "auth".to_string(),                      message: e.to_string(),                  })              }              Err(e) => AcceptEditgroupResponse::GenericError(ErrorResponse { +                success: false, +                error: "internal".to_string(),                  message: e.to_string(),              }),          }; @@ -1053,6 +1106,8 @@ impl Api for Server {              Ok(entity) => GetEditgroupResponse::Found(entity),              Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => {                  GetEditgroupResponse::NotFound(ErrorResponse { +                    success: false, +                    error: "not-found".to_string(),                      message: format!("No such editgroup: {}", editgroup_id),                  })              } @@ -1060,6 +1115,8 @@ impl Api for Server {              // TODO: dig in to error type here              {                  GetEditgroupResponse::GenericError(ErrorResponse { +                    success: false, +                    error: "internal".to_string(),                      message: e.to_string(),                  })              } @@ -1098,11 +1155,15 @@ impl Api for Server {              Ok(eg) => CreateEditgroupResponse::SuccessfullyCreated(eg),              Err(Error(ErrorKind::InvalidCredentials(e), _)) => {                  CreateEditgroupResponse::Forbidden(ErrorResponse { +                    success: false, +                    error: "auth".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::InsufficientPrivileges(e), _)) => {                  CreateEditgroupResponse::Forbidden(ErrorResponse { +                    success: false, +                    error: "auth".to_string(),                      message: e.to_string(),                  })              } @@ -1110,6 +1171,8 @@ impl Api for Server {              // TODO: dig in to error type here              {                  CreateEditgroupResponse::GenericError(ErrorResponse { +                    success: false, +                    error: "internal".to_string(),                      message: e.to_string(),                  })              } @@ -1130,6 +1193,8 @@ impl Api for Server {                  error!("{}", e);                  capture_error_chain(&e);                  GetChangelogResponse::GenericError(ErrorResponse { +                    success: false, +                    error: "internal".to_string(),                      message: e.to_string(),                  })              } @@ -1148,6 +1213,8 @@ impl Api for Server {              Ok(entry) => GetChangelogEntryResponse::FoundChangelogEntry(entry),              Err(Error(ErrorKind::Diesel(::diesel::result::Error::NotFound), _)) => {                  GetChangelogEntryResponse::NotFound(ErrorResponse { +                    success: false, +                    error: "not-found".to_string(),                      message: format!("No such changelog entry: {}", id),                  })              } @@ -1155,6 +1222,8 @@ impl Api for Server {                  error!("{}", e);                  capture_error_chain(&e);                  GetChangelogEntryResponse::GenericError(ErrorResponse { +                    success: false, +                    error: "internal".to_string(),                      message: e.to_string(),                  })              } @@ -1187,33 +1256,47 @@ impl Api for Server {              Ok((result, true)) => AuthOidcResponse::Created(result),              Ok((result, false)) => AuthOidcResponse::Found(result),              Err(Error(ErrorKind::Diesel(e), _)) => AuthOidcResponse::BadRequest(ErrorResponse { +                success: false, +                error: "database".to_string(),                  message: e.to_string(),              }),              Err(Error(ErrorKind::Uuid(e), _)) => AuthOidcResponse::BadRequest(ErrorResponse { +                success: false, +                error: "uuid".to_string(),                  message: e.to_string(),              }),              Err(Error(ErrorKind::InvalidFatcatId(e), _)) => {                  AuthOidcResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "fatcat-id".to_string(),                      message: ErrorKind::InvalidFatcatId(e).to_string(),                  })              }              Err(Error(ErrorKind::MalformedExternalId(e), _)) => {                  AuthOidcResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "field-syntax".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::MalformedChecksum(e), _)) => {                  AuthOidcResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "field-syntax".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::NotInControlledVocabulary(e), _)) => {                  AuthOidcResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "field-syntax".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::EditgroupAlreadyAccepted(e), _)) => {                  AuthOidcResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "editgroup".to_string(),                      message: e.to_string(),                  })              } @@ -1221,16 +1304,22 @@ impl Api for Server {              // TODO: why can't I NotAuthorized here?              {                  AuthOidcResponse::Forbidden(ErrorResponse { +                    success: false, +                    error: "auth".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::InsufficientPrivileges(e), _)) => {                  AuthOidcResponse::Forbidden(ErrorResponse { +                    success: false, +                    error: "auth".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::OtherBadRequest(e), _)) => {                  AuthOidcResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "other".to_string(),                      message: e.to_string(),                  })              } @@ -1238,6 +1327,8 @@ impl Api for Server {                  error!("{}", e);                  capture_error_chain(&e);                  AuthOidcResponse::GenericError(ErrorResponse { +                    success: false, +                    error: "internal".to_string(),                      message: e.to_string(),                  })              } @@ -1272,28 +1363,37 @@ impl Api for Server {              Ok(())          }) {              Ok(()) => AuthCheckResponse::Success(Success { +                success: true,                  message: "auth check successful!".to_string(),              }),              Err(Error(ErrorKind::Diesel(e), _)) => AuthCheckResponse::BadRequest(ErrorResponse { +                success: false, +                error: "database".to_string(),                  message: e.to_string(),              }),              Err(Error(ErrorKind::Uuid(e), _)) => AuthCheckResponse::BadRequest(ErrorResponse { +                success: false, +                error: "uuid".to_string(),                  message: e.to_string(),              }), -            Err(Error(ErrorKind::InvalidCredentials(e), _)) => -            // TODO: why can't I NotAuthorized here? -            { +            Err(Error(ErrorKind::InvalidCredentials(e), _)) => {                  AuthCheckResponse::Forbidden(ErrorResponse { +                    success: false, +                    error: "auth".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::InsufficientPrivileges(e), _)) => {                  AuthCheckResponse::Forbidden(ErrorResponse { +                    success: false, +                    error: "auth".to_string(),                      message: e.to_string(),                  })              }              Err(Error(ErrorKind::OtherBadRequest(e), _)) => {                  AuthCheckResponse::BadRequest(ErrorResponse { +                    success: false, +                    error: "other".to_string(),                      message: e.to_string(),                  })              } @@ -1301,6 +1401,8 @@ impl Api for Server {                  error!("{}", e);                  capture_error_chain(&e);                  AuthCheckResponse::GenericError(ErrorResponse { +                    success: false, +                    error: "internal".to_string(),                      message: e.to_string(),                  })              }  | 
