Skip to content

Resiliency to newly-added capabilities #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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 src/Client/Backblaze.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<Authors>Microcompiler</Authors>
<Company>Bytewizer Inc.</Company>
<Product>Backblaze B2 Cloud Storage</Product>
<LangVersion>7.1</LangVersion>
<LangVersion>8.0</LangVersion>
<RootNamespace>Bytewizer.Backblaze</RootNamespace>
<VersionPrefix>1.1.0</VersionPrefix>
<Version Condition=" '$(Version)' == '' and '$(VersionSuffix)' != '' ">$(VersionPrefix)-$(VersionSuffix)</Version>
Expand Down
6 changes: 5 additions & 1 deletion src/Client/Client/ApiRest.Endpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
using Bytewizer.Backblaze.Models;
using Bytewizer.Backblaze.Extensions;

using Bytewizer.Backblaze.Client.Internal;

namespace Bytewizer.Backblaze.Client
{
public abstract partial class ApiRest : DisposableObject
Expand Down Expand Up @@ -47,7 +49,9 @@ public async Task<IApiResults<AuthorizeAccountResponse>> AuthorizeAccountAync
using (var results = await _policy.InvokeClient.ExecuteAsync(async () =>
{ return await _httpClient.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false); }))
{
return await HandleResponseAsync<AuthorizeAccountResponse>(results).ConfigureAwait(false);
var rawResult = await HandleResponseAsync<AuthorizeAccountResponseRaw>(results).ConfigureAwait(false);

return new ApiResults<AuthorizeAccountResponse>(rawResult.HttpResponse, rawResult.Response.ToAuthorizedAccountResponse());
}

}
Expand Down
77 changes: 77 additions & 0 deletions src/Client/Client/Internal/AllowedRaw.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;

using Newtonsoft.Json;

using Bytewizer.Backblaze.Models;

namespace Bytewizer.Backblaze.Client.Internal
{
/// <summary>
/// Represents information related to an allowed authorization.
/// </summary>
[DebuggerDisplay("{DebuggerDisplay, nq}")]
internal class AllowedRaw
{
/// <summary>
/// Gets or sets a list of <see cref="Capability"/> allowed.
/// </summary>
[JsonProperty(Required = Required.Always)]
public List<string> Capabilities { get; set; }

/// <summary>
/// Gets or sets restricted access only to this bucket id.
/// </summary>
public string BucketId { get; set; }

/// <summary>
/// When bucket id is set and it is a valid bucket that has not been deleted this field is set to the name of the
/// bucket. It's possible that bucket id is set to a bucket that no longer exists in which case this field will be
/// <c>null</c>. It's also null when bucket id is <c>null</c>.
/// </summary>
public string BucketName { get; set; }

/// <summary>
/// Gets or sets restricted access to files whose names start with the prefix.
/// </summary>
public string NamePrefix { get; set; }

/// <summary>
/// Debugger display for this object.
/// </summary>
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string DebuggerDisplay
{
get { return $"{{{nameof(Capabilities)}: {string.Join(", ", Capabilities)}, {nameof(NamePrefix)}: {NamePrefix}}}"; }
}

/// <summary>
/// Translates this <see cref="AllowedRaw"/> instance to an instance of <see cref="Allowed"/>,
/// parsing capabilities into the <see cref="Allowed.Capabilities"/> and
/// <see cref="Allowed.UnknownCapabilities"/> properties.
/// </summary>
/// <returns>An instance of <see cref="Allowed"/>.</returns>
public Allowed ParseCapabilities()
{
Allowed parsed = new Allowed();

parsed.BucketId = this.BucketId;
parsed.BucketName = this.BucketName;
parsed.NamePrefix = this.NamePrefix;

parsed.Capabilities = new Capabilities();
parsed.UnknownCapabilities = new List<string>();

foreach (string capabilityName in this.Capabilities)
{
if (Enum.TryParse<Capability>(capabilityName, out var parsedCapability))
parsed.Capabilities.Add(parsedCapability);
else
parsed.UnknownCapabilities.Add(capabilityName);
}

return parsed;
}
}
}
94 changes: 94 additions & 0 deletions src/Client/Client/Internal/AuthorizeAccountResponseRaw.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using System;
using System.Diagnostics;

using Newtonsoft.Json;

using Bytewizer.Backblaze.Models;

namespace Bytewizer.Backblaze.Client.Internal
{
/// <summary>
/// Contains the results of authorize account request operation.
/// </summary>
[DebuggerDisplay("{DebuggerDisplay, nq}")]
internal class AuthorizeAccountResponseRaw : IResponse
{
/// <summary>
/// The identifier for the account.
/// </summary>
[JsonProperty(Required = Required.Always)]
public string AccountId { get; internal set; }

/// <summary>
/// An authorization token to use with all calls other than authorize account that need an authorization header.
/// This authorization token is valid for at most 24 hours.
/// </summary>
[JsonProperty(Required = Required.Always)]
public string AuthorizationToken { get; internal set; }

/// <summary>
/// The capabilities of this auth token and any restrictions on using it.
/// </summary>
[JsonProperty(Required = Required.Always)]
public AllowedRaw Allowed { get; internal set; }

/// <summary>
/// The base url to use for all API calls except for uploading and downloading files.
/// </summary>
[JsonProperty(Required = Required.Always)]
public Uri ApiUrl { get; internal set; }

/// <summary>
/// The base url to use for downloading files.
/// </summary>
[JsonProperty(Required = Required.Always)]
public Uri DownloadUrl { get; internal set; }

/// <summary>
/// The recommended size for each part of a large file. We recommend using this part size for optimal upload performance.
/// </summary>
[JsonProperty(Required = Required.Always)]
public long RecommendedPartSize { get; internal set; }

/// <summary>
/// The smallest possible size of a part of a large file (except the last one). This is smaller than the <see cref="RecommendedPartSize"/>.
/// If you use it you may find that it takes longer overall to upload a large file.
/// </summary>
[JsonProperty(Required = Required.Always)]
public long AbsoluteMinimumPartSize { get; internal set; }

/// <summary>
/// OBSOLETE: This field will always have the same value as <see cref="RecommendedPartSize"/>.
/// </summary>
[Obsolete("This field will always have the same value as 'RecommendedPartSize'.")]
public long MinimumPartSize { get; internal set; }

/// <summary>
/// Debugger display for this object.
/// </summary>
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string DebuggerDisplay
{
get { return $"{{{nameof(AccountId)}: {AccountId}, {nameof(AuthorizationToken)}: {AuthorizationToken}}}"; }
}

internal AuthorizeAccountResponse ToAuthorizedAccountResponse()
{
var response = new AuthorizeAccountResponse();

response.AccountId = this.AccountId;
response.AuthorizationToken = this.AuthorizationToken;
response.Allowed = this.Allowed.ParseCapabilities();
response.ApiUrl = this.ApiUrl;
response.DownloadUrl = this.DownloadUrl;
response.RecommendedPartSize = this.RecommendedPartSize;
response.AbsoluteMinimumPartSize = this.AbsoluteMinimumPartSize;

#pragma warning disable 618
response.MinimumPartSize = this.MinimumPartSize;
#pragma warning restore 618

return response;
}
}
}
20 changes: 18 additions & 2 deletions src/Client/Models/Allowed.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics;
using System.Collections.Generic;
using System.Diagnostics;

using Newtonsoft.Json;

Expand All @@ -16,6 +17,11 @@ public class Allowed
[JsonProperty(Required = Required.Always)]
public Capabilities Capabilities { get; set; }

/// <summary>
/// Gets or sets a list of capabilities that couldn't be parsed into <see cref="Capability"/> values.
/// </summary>
public List<string> UnknownCapabilities { get; set; }

/// <summary>
/// Gets or sets restricted access only to this bucket id.
/// </summary>
Expand All @@ -39,7 +45,17 @@ public class Allowed
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string DebuggerDisplay
{
get { return $"{{{nameof(Capabilities)}: {string.Join(", ", Capabilities)}, {nameof(NamePrefix)}: {NamePrefix}}}"; }
get
{
string unknownCapabilitiesString = "";

if ((this.UnknownCapabilities != null) && (this.UnknownCapabilities.Count > 0))
{
unknownCapabilitiesString = " (+ " + string.Join(", ", UnknownCapabilities) + ")";
}

return $"{{{nameof(Capabilities)}: {string.Join(", ", Capabilities)}{unknownCapabilitiesString}, {nameof(NamePrefix)}: {NamePrefix}}}";
}
}
}
}
3 changes: 3 additions & 0 deletions src/Client/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Backblaze.Tests.Unit")]
Loading