Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn main() {
#[cfg(genproto)]
fn generate_protos() {
download_file(
"https://raw.githubusercontent.com/lightningdevkit/vss-server/cb1159c3b1835c66a857b25b114f15d18d2a4297/app/src/main/proto/vss.proto",
"https://raw.githubusercontent.com/lightningdevkit/vss-server/7f492fcac0c561b212f49ca40f7d16075822440f/app/src/main/proto/vss.proto",
"src/proto/vss.proto",
).unwrap();

Expand Down
7 changes: 7 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ pub enum VssError {
/// Please refer to [`ErrorCode::ConflictException`].
ConflictError(String),

/// Please refer to [`ErrorCode::AuthException`].
AuthError(String),

/// Please refer to [`ErrorCode::InternalServerException`].
InternalServerError(String),

Expand Down Expand Up @@ -53,6 +56,9 @@ impl Display for VssError {
VssError::ConflictError(message) => {
write!(f, "Potential version conflict in write operation: {}", message)
}
VssError::AuthError(message) => {
write!(f, "Authentication or Authorization failure: {}", message)
}
VssError::InternalServerError(message) => {
write!(f, "InternalServerError: {}", message)
}
Expand All @@ -71,6 +77,7 @@ impl From<ErrorResponse> for VssError {
ErrorCode::NoSuchKeyException => VssError::NoSuchKeyError(error_response.message),
ErrorCode::InvalidRequestException => VssError::InvalidRequestError(error_response.message),
ErrorCode::ConflictException => VssError::ConflictError(error_response.message),
ErrorCode::AuthException => VssError::AuthError(error_response.message),
ErrorCode::InternalServerException => VssError::InternalServerError(error_response.message),
_ => VssError::InternalError(format!(
"VSS responded with an unknown error code: {}, message: {}",
Expand Down
4 changes: 4 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ pub enum ErrorCode {
InternalServerException = 3,
/// Used when the specified `key` in a `GetObjectRequest` does not exist.
NoSuchKeyException = 4,
/// Used when authentication fails or in case of an unauthorized request.
AuthException = 5,
}
impl ErrorCode {
/// String value of the enum field names used in the ProtoBuf definition.
Expand All @@ -361,6 +363,7 @@ impl ErrorCode {
ErrorCode::InvalidRequestException => "INVALID_REQUEST_EXCEPTION",
ErrorCode::InternalServerException => "INTERNAL_SERVER_EXCEPTION",
ErrorCode::NoSuchKeyException => "NO_SUCH_KEY_EXCEPTION",
ErrorCode::AuthException => "AUTH_EXCEPTION",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
Expand All @@ -371,6 +374,7 @@ impl ErrorCode {
"INVALID_REQUEST_EXCEPTION" => Some(Self::InvalidRequestException),
"INTERNAL_SERVER_EXCEPTION" => Some(Self::InternalServerException),
"NO_SUCH_KEY_EXCEPTION" => Some(Self::NoSuchKeyException),
"AUTH_EXCEPTION" => Some(Self::AuthException),
_ => None,
}
}
Expand Down
55 changes: 54 additions & 1 deletion tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,56 @@ mod tests {
mock_server.expect(4).assert();
}

#[tokio::test]
async fn test_auth_err_handling() {
let base_url = mockito::server_url();
let vss_client = VssClient::new(&base_url, retry_policy());

// Invalid Request Error
let error_response =
ErrorResponse { error_code: ErrorCode::AuthException.into(), message: "AuthException".to_string() };
let mock_server = mockito::mock("POST", Matcher::Any)
.with_status(401)
.with_body(&error_response.encode_to_vec())
.create();

let get_result = vss_client
.get_object(&GetObjectRequest { store_id: "store".to_string(), key: "k1".to_string() })
.await;
assert!(matches!(get_result.unwrap_err(), VssError::AuthError { .. }));

let put_result = vss_client
.put_object(&PutObjectRequest {
store_id: "store".to_string(),
global_version: Some(4),
transaction_items: vec![KeyValue { key: "k1".to_string(), version: 2, value: b"k1v3".to_vec() }],
delete_items: vec![],
})
.await;
assert!(matches!(put_result.unwrap_err(), VssError::AuthError { .. }));

let delete_result = vss_client
.delete_object(&DeleteObjectRequest {
store_id: "store".to_string(),
key_value: Some(KeyValue { key: "k1".to_string(), version: 2, value: b"k1v3".to_vec() }),
})
.await;
assert!(matches!(delete_result.unwrap_err(), VssError::AuthError { .. }));

let list_result = vss_client
.list_key_versions(&ListKeyVersionsRequest {
store_id: "store".to_string(),
page_size: Some(5),
page_token: None,
key_prefix: Some("k".into()),
})
.await;
assert!(matches!(list_result.unwrap_err(), VssError::AuthError { .. }));

// Verify 4 requests hit the server
mock_server.expect(4).assert();
}

#[tokio::test]
async fn test_conflict_err_handling() {
let base_url = mockito::server_url();
Expand Down Expand Up @@ -401,7 +451,10 @@ mod tests {
.skip_retry_on_error(|e| {
matches!(
e,
VssError::NoSuchKeyError(..) | VssError::InvalidRequestError(..) | VssError::ConflictError(..)
VssError::NoSuchKeyError(..)
| VssError::InvalidRequestError(..)
| VssError::ConflictError(..)
| VssError::AuthError(..)
)
})
}
Expand Down