diff --git a/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Status.cs b/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Status.cs new file mode 100644 index 0000000..ec764f1 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Status.cs @@ -0,0 +1,19 @@ +using FrostFS.SDK.ModelsV2.Enums; + +namespace FrostFS.SDK.ClientV2.Mappers.GRPC; + +public static class StatusMapper +{ + public static ModelsV2.Status ToModel(this Status.Status status) + { + if (status is null) return new ModelsV2.Status(StatusCode.Success); + var codeName = Enum.GetName(typeof(StatusCode), status.Code); + if (codeName is null) + { + throw new ArgumentException($"Unknown StatusCode. Value: '{status.Code}'."); + } + + return new ModelsV2.Status(Enum.Parse(codeName), status.Message); + + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Services/Container.cs b/src/FrostFS.SDK.ClientV2/Services/Container.cs index 0a685f3..d0b54d9 100644 --- a/src/FrostFS.SDK.ClientV2/Services/Container.cs +++ b/src/FrostFS.SDK.ClientV2/Services/Container.cs @@ -18,6 +18,7 @@ public partial class Client request.AddMetaHeader(); request.Sign(_key); var response = await _containerServiceClient.GetAsync(request); + Verifier.CheckResponse(response); return response.Body.Container.ToModel(); } @@ -33,6 +34,7 @@ public partial class Client request.AddMetaHeader(); request.Sign(_key); var response = await _containerServiceClient.ListAsync(request); + Verifier.CheckResponse(response); foreach (var cid in response.Body.ContainerIds) { yield return ContainerId.FromHash(cid.Value.ToByteArray()); @@ -55,7 +57,7 @@ public partial class Client request.AddMetaHeader(); request.Sign(_key); var response = await _containerServiceClient.PutAsync(request); - RequestVerifier.ProcessResponse(response); + Verifier.CheckResponse(response); return ContainerId.FromHash(response.Body.ContainerId.Value.ToByteArray()); } @@ -71,6 +73,7 @@ public partial class Client }; request.AddMetaHeader(); request.Sign(_key); - await _containerServiceClient.DeleteAsync(request); + var response = await _containerServiceClient.DeleteAsync(request); + Verifier.CheckResponse(response); } } \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Services/Object.cs b/src/FrostFS.SDK.ClientV2/Services/Object.cs index 7192632..62e2ba7 100644 --- a/src/FrostFS.SDK.ClientV2/Services/Object.cs +++ b/src/FrostFS.SDK.ClientV2/Services/Object.cs @@ -27,6 +27,7 @@ public partial class Client request.AddMetaHeader(); request.Sign(_key); var response = await _objectServiceClient.HeadAsync(request); + Verifier.CheckResponse(response); return response.Body.Header.Header.ToModel(); } @@ -55,8 +56,8 @@ public partial class Client ); request.Sign(_key); - var response = await GetObject(request); - return response.ToModel(); + var obj = await GetObject(request); + return obj.ToModel(); } private async Task GetObject(GetRequest request) @@ -146,6 +147,7 @@ public partial class Client } var response = await stream.Close(); + Verifier.CheckResponse(response); return ObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray()); } @@ -176,7 +178,8 @@ public partial class Client }; request.AddMetaHeader(); request.Sign(_key); - await _objectServiceClient.DeleteAsync(request); + var response = await _objectServiceClient.DeleteAsync(request); + Verifier.CheckResponse(response); } public async IAsyncEnumerable SearchObjectsAsync(ContainerId cid, params ObjectFilter[] filters) @@ -245,6 +248,7 @@ internal class ObjectReader : IDisposable } var response = Call.ResponseStream.Current; + Verifier.CheckResponse(response); if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Init) throw new InvalidOperationException("unexpect message type"); return new Object.Object @@ -262,6 +266,7 @@ internal class ObjectReader : IDisposable } var response = Call.ResponseStream.Current; + Verifier.CheckResponse(response); if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Chunk) throw new InvalidOperationException("unexpect message type"); return response.Body.Chunk.ToByteArray(); @@ -311,6 +316,7 @@ internal class SearchReader : IDisposable } var response = Call.ResponseStream.Current; + Verifier.CheckResponse(response); return response.Body?.IdList.ToList(); } diff --git a/src/FrostFS.SDK.ClientV2/RequestVerifier.cs b/src/FrostFS.SDK.ClientV2/Verifier.cs similarity index 90% rename from src/FrostFS.SDK.ClientV2/RequestVerifier.cs rename to src/FrostFS.SDK.ClientV2/Verifier.cs index cc0e27f..f6bbe2a 100644 --- a/src/FrostFS.SDK.ClientV2/RequestVerifier.cs +++ b/src/FrostFS.SDK.ClientV2/Verifier.cs @@ -1,5 +1,6 @@ using System.Security.Cryptography; using FrostFS.Refs; +using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.Cryptography; using FrostFS.Session; using Google.Protobuf; @@ -9,8 +10,9 @@ using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Math; -namespace FrostFS.SDK.ClientV2 { - public static class RequestVerifier +namespace FrostFS.SDK.ClientV2 +{ + public static class Verifier { public const int RFC6979SignatureSize = 64; @@ -72,12 +74,16 @@ namespace FrostFS.SDK.ClientV2 { { return VerifyMatryoskaLevel(message.GetBody(), message.GetMetaHeader(), message.GetVerificationHeader()); } - - public static void ProcessResponse(IResponse resp) + + public static void CheckResponse(IResponse resp) { - Console.WriteLine(resp.MetaHeader.Status); if (!resp.Verify()) throw new FormatException($"invalid response, type={resp.GetType()}"); + var status = resp.MetaHeader.Status.ToModel(); + if (!status.IsSuccess()) + { + throw new ApplicationException(status.ToString()); + } } } } \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Enums/StatusCode.cs b/src/FrostFS.SDK.ModelsV2/Enums/StatusCode.cs new file mode 100644 index 0000000..df0fa57 --- /dev/null +++ b/src/FrostFS.SDK.ModelsV2/Enums/StatusCode.cs @@ -0,0 +1,22 @@ +namespace FrostFS.SDK.ModelsV2.Enums; + +public enum StatusCode +{ + Success = 0, + Internal = 1024, + WrongMagicNumber = 1025, + SignatureVerificationFailure = 1026, + NodeUnderMaintenance = 1027, + ObjectAccessDenied = 2048, + ObjectNotFound = 2049, + ObjectLocked = 2050, + LockNotRegularObject = 2051, + ObjectAlreadyRemoved = 2052, + OutOfRange = 2053, + ContainerNotFound = 3072, + EAclNotFound = 3073, + ContainerAccessDenied = 3074, + TokenNotFound = 4096, + TokenExpired = 4097, + ApeManagerAccessDenied = 5120 +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/Status.cs b/src/FrostFS.SDK.ModelsV2/Status.cs new file mode 100644 index 0000000..4995742 --- /dev/null +++ b/src/FrostFS.SDK.ModelsV2/Status.cs @@ -0,0 +1,25 @@ +using FrostFS.SDK.ModelsV2.Enums; + +namespace FrostFS.SDK.ModelsV2; + +public class Status +{ + public StatusCode Code { get; set; } + public string Message { get; set; } + + public Status(StatusCode code, string? message = null) + { + Code = code; + Message = message ?? string.Empty; + } + + public bool IsSuccess() + { + return Code == StatusCode.Success; + } + + public override string ToString() + { + return $"Response status: {Code}. Message: {Message}."; + } +} \ No newline at end of file