Skip to content

Commit

Permalink
com.rest.blockadelabs 1.2.0 (#13)
Browse files Browse the repository at this point in the history
- updated authentication
- updated unit tests
  • Loading branch information
StephenHodgson committed Nov 29, 2023
1 parent 7f5d3ba commit 501cf95
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 121 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/upm-subtree-split.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
upm-subtree-split:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: upm subtree split
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ The recommended installation method is though the unity package manager and [Ope

### Table of Contents

- [Authentication](#authentication)
- [Editor Dashboard](#editor-dashboard) :new:
- [Skybox Dashboard](#skybox-dashboard) :new:
- [History Dashboard](#history-dashboard) :new:
- [Authentication](#authentication) :construction:
- [Editor Dashboard](#editor-dashboard)
- [Skybox Dashboard](#skybox-dashboard)
- [History Dashboard](#history-dashboard)
- [Skyboxes](#skyboxes)
- [Get Skybox Styles](#get-skybox-styles)
- [Get Skybox Export Options](#get-skybox-export-options) :new:
- [Get Skybox Export Options](#get-skybox-export-options)
- [Generate Skybox](#generate-skybox)
- [Get Skybox by Id](#get-skybox)
- [Request Skybox Export](#request-skybox-export) :new:
- [Request Skybox Export](#request-skybox-export)
- [Delete Skybox by Id](#delete-skybox)
- [Get Skybox History](#get-skybox-history)
- [Cancel Skybox Generation](#cancel-skybox-generation)
Expand All @@ -61,8 +61,10 @@ The recommended installation method is though the unity package manager and [Ope

There are 4 ways to provide your API keys, in order of precedence:

1. [Pass keys directly with constructor](#pass-keys-directly-with-constructor)
2. [Unity Scriptable Object](#unity-scriptable-object)
:warning: We recommended using the environment variables to load the API key instead of having it hard coded in your source. It is not recommended use this method in production, but only for accepting user credentials, local testing and quick start scenarios.

1. [Pass keys directly with constructor](#pass-keys-directly-with-constructor) :warning:
2. [Unity Scriptable Object](#unity-scriptable-object) :warning:
3. [Load key from configuration file](#load-key-from-configuration-file)
4. [Use System Environment Variables](#use-system-environment-variables)

Expand Down Expand Up @@ -103,7 +105,7 @@ To create a configuration file, create a new text file named `.blockadelabs` and
You can also load the file directly with known path by calling a static method in Authentication:

```csharp
var api = new BlockadeLabsClient(BlockadeLabsAuthentication.Default.LoadFromDirectory("your/path/to/.blockadelabs"));;
var api = new BlockadeLabsClient(new BlockadeLabsAuthentication().LoadFromDirectory("your/path/to/.blockadelabs"));;
```

#### Use System Environment Variables
Expand All @@ -113,7 +115,7 @@ Use your system's environment variables specify an api key to use.
- Use `BLOCKADE_LABS_API_KEY` for your api key.

```csharp
var api = new BlockadeLabsClient(BlockadeLabsAuthentication.Default.LoadFromEnvironment());
var api = new BlockadeLabsClient(new BlockadeLabsAuthentication().LoadFromEnvironment());
```

### Editor Dashboard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,43 @@

namespace BlockadeLabs
{
public sealed class BlockadeLabsAuthentication : AbstractAuthentication<BlockadeLabsAuthentication, BlockadeLabsAuthInfo>
public sealed class BlockadeLabsAuthentication : AbstractAuthentication<BlockadeLabsAuthentication, BlockadeLabsAuthInfo, BlockadeLabsConfiguration>
{
internal const string CONFIG_FILE = ".blockadelabs";
private const string BLOCKADE_LABS_API_KEY = nameof(BLOCKADE_LABS_API_KEY);

public static implicit operator BlockadeLabsAuthentication(string apiKey) => new BlockadeLabsAuthentication(apiKey);

/// <summary>
/// Instantiates a new Authentication object that will load the default config.
/// Instantiates an empty Authentication object.
/// </summary>
public BlockadeLabsAuthentication()
{
if (cachedDefault != null)
{
return;
}

cachedDefault = (LoadFromAsset<BlockadeLabsConfiguration>() ??
LoadFromDirectory()) ??
LoadFromDirectory(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)) ??
LoadFromEnvironment();
Info = cachedDefault?.Info;
}
public BlockadeLabsAuthentication() { }

/// <summary>
/// Instantiates a new Authentication object with the given <paramref name="apiKey"/>, which may be <see langword="null"/>.
/// </summary>
/// <param name="apiKey">The API key, required to access the API endpoint.</param>
public BlockadeLabsAuthentication(string apiKey) => Info = new BlockadeLabsAuthInfo(apiKey);
public BlockadeLabsAuthentication(string apiKey)
{
Info = new BlockadeLabsAuthInfo(apiKey);
cachedDefault = this;
}

/// <summary>
/// Instantiates a new Authentication object with the given <paramref name="authInfo"/>, which may be <see langword="null"/>.
/// </summary>
/// <param name="authInfo"></param>
public BlockadeLabsAuthentication(BlockadeLabsAuthInfo authInfo) => Info = authInfo;
public BlockadeLabsAuthentication(BlockadeLabsAuthInfo authInfo)
{
Info = authInfo;
cachedDefault = this;
}

/// <summary>
/// Instantiates a new Authentication object with the given <see cref="configuration"/>.
/// </summary>
/// <param name="configuration"><see cref="BlockadeLabsConfiguration"/>.</param>
public BlockadeLabsAuthentication(BlockadeLabsConfiguration configuration) : this(configuration.ApiKey) { }

/// <inheritdoc />
public override BlockadeLabsAuthInfo Info { get; }
Expand All @@ -56,20 +58,20 @@ public BlockadeLabsAuthentication()
/// </summary>
public static BlockadeLabsAuthentication Default
{
get => cachedDefault ??= new BlockadeLabsAuthentication();
internal set => cachedDefault = value;
get => cachedDefault ??= new BlockadeLabsAuthentication().LoadDefault();
set => cachedDefault = value;
}

/// <inheritdoc />
public override BlockadeLabsAuthentication LoadFromAsset<T>()
=> Resources.LoadAll<T>(string.Empty)
.Where(asset => asset != null)
.Where(asset => asset is BlockadeLabsConfiguration config &&
!string.IsNullOrWhiteSpace(config.ApiKey))
.Select(asset => asset is BlockadeLabsConfiguration config
? new BlockadeLabsAuthentication(config.ApiKey)
: null)
.FirstOrDefault();
public override BlockadeLabsAuthentication LoadFromAsset(BlockadeLabsConfiguration configuration = null)
{
if (configuration == null)
{
Debug.LogWarning($"This can be speed this up by passing a {nameof(BlockadeLabsConfiguration)} to the {nameof(BlockadeLabsAuthentication)}.ctr");
configuration = Resources.LoadAll<BlockadeLabsConfiguration>(string.Empty).FirstOrDefault(o => o != null);
}

return configuration != null ? new BlockadeLabsAuthentication(configuration) : null;
}

/// <inheritdoc />
public override BlockadeLabsAuthentication LoadFromEnvironment()
Expand All @@ -87,6 +89,11 @@ public override BlockadeLabsAuthentication LoadFromDirectory(string directory =
directory = Environment.CurrentDirectory;
}

if (string.IsNullOrWhiteSpace(filename))
{
filename = CONFIG_FILE;
}

BlockadeLabsAuthInfo tempAuthInfo = null;

var currentDirectory = new DirectoryInfo(directory);
Expand Down Expand Up @@ -119,12 +126,11 @@ public override BlockadeLabsAuthentication LoadFromDirectory(string directory =
var part = parts[i];
var nextPart = parts[i + 1];

switch (part)
apiKey = part switch
{
case BLOCKADE_LABS_API_KEY:
apiKey = nextPart.Trim();
break;
}
BLOCKADE_LABS_API_KEY => nextPart.Trim(),
_ => apiKey
};
}
}

Expand All @@ -141,13 +147,7 @@ public override BlockadeLabsAuthentication LoadFromDirectory(string directory =
}
}

if (tempAuthInfo == null ||
string.IsNullOrEmpty(tempAuthInfo.ApiKey))
{
return null;
}

return new BlockadeLabsAuthentication(tempAuthInfo);
return string.IsNullOrEmpty(tempAuthInfo?.ApiKey) ? null : new BlockadeLabsAuthentication(tempAuthInfo);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ namespace BlockadeLabs
{
public sealed class BlockadeLabsClient : BaseClient<BlockadeLabsAuthentication, BlockadeLabsSettings>
{
/// <summary>
/// Creates a new client for the BlockadeLabs API, handling auth and allowing for access to various API endpoints.
/// </summary>
/// <param name="authentication">The API authentication information to use for API calls,
/// or <see langword="null"/> to attempt to use the <see cref="BlockadeLabsAuthentication.Default"/>,
/// potentially loading from environment vars or from a config file.</param>
/// <param name="settings">Optional, <see cref="BlockadeLabsSettings"/> for specifying a proxy domain.</param>
/// <exception cref="AuthenticationException">Raised when authentication details are missing or invalid.</exception>
public BlockadeLabsClient(BlockadeLabsAuthentication authentication = null, BlockadeLabsSettings settings = null)
: base(authentication ?? BlockadeLabsAuthentication.Default, settings ?? BlockadeLabsSettings.Default)
{
Expand All @@ -18,6 +26,11 @@ public BlockadeLabsClient(BlockadeLabsAuthentication authentication = null, Bloc

protected override void ValidateAuthentication()
{
if (Authentication?.Info == null)
{
throw new InvalidCredentialException($"Invalid {nameof(BlockadeLabsAuthentication)}");
}

if (!HasValidAuthentication)
{
throw new AuthenticationException("You must provide API authentication. Please refer to https://github.com/RageAgainstThePixel/com.rest.blockadelabs#authentication for details.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,61 @@ namespace BlockadeLabs
{
public sealed class BlockadeLabsSettings : ISettings
{
/// <summary>
/// Creates a new instance of <see cref="BlockadeLabsSettings"/> with default <see cref="BlockadeLabsSettingsInfo"/>.
/// </summary>
public BlockadeLabsSettings()
{
if (cachedDefault != null) { return; }

var config = Resources.LoadAll<BlockadeLabsConfiguration>(string.Empty)
.FirstOrDefault(asset => asset != null);
Info = new BlockadeLabsSettingsInfo();
cachedDefault = this;
}

if (config != null)
/// <summary>
/// Creates a new instance of <see cref="BlockadeLabsSettings"/> with provided <see cref="configuration"/>.
/// </summary>
/// <param name="configuration"><see cref="BlockadeLabsConfiguration"/>.</param>
public BlockadeLabsSettings(BlockadeLabsConfiguration configuration)
{
if (configuration == null)
{
Info = new BlockadeLabsSettingsInfo(config.ProxyDomain);
Default = new BlockadeLabsSettings(Info);
Debug.LogWarning($"This can be speed up by directly passing a {nameof(BlockadeLabsConfiguration)} to the {nameof(BlockadeLabsSettings)}.ctr");
configuration = Resources.LoadAll<BlockadeLabsConfiguration>(string.Empty).FirstOrDefault(asset => asset != null);
}
else

if (configuration == null)
{
Info = new BlockadeLabsSettingsInfo();
Default = new BlockadeLabsSettings(Info);
throw new MissingReferenceException($"Failed to find a valid {nameof(BlockadeLabsConfiguration)}!");
}

Info = new BlockadeLabsSettingsInfo(configuration.ProxyDomain);
cachedDefault = this;
}

/// <summary>
/// Creates a new instance of <see cref="BlockadeLabsSettings"/> with the provided <see cref="settingsInfo"/>.
/// </summary>
/// <param name="settingsInfo"><see cref="BlockadeLabsSettingsInfo"/>.</param>
public BlockadeLabsSettings(BlockadeLabsSettingsInfo settingsInfo)
=> Info = settingsInfo;
{
Info = settingsInfo;
cachedDefault = this;
}

/// <summary>
/// Creates a new instance of <see cref="BlockadeLabsSettings"/>.
/// </summary>
/// <param name="domain">Base api domain.</param>
public BlockadeLabsSettings(string domain)
=> Info = new BlockadeLabsSettingsInfo(domain);
{
Info = new BlockadeLabsSettingsInfo(domain);
cachedDefault = this;
}

private static BlockadeLabsSettings cachedDefault;

public static BlockadeLabsSettings Default
{
get => cachedDefault ??= new BlockadeLabsSettings();
get => cachedDefault ??= new BlockadeLabsSettings(configuration: null);
internal set => cachedDefault = value;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

namespace BlockadeLabs.Tests
{
internal abstract class AbstractTestFixture
{
protected readonly BlockadeLabsClient BlockadeLabsClient;

protected AbstractTestFixture()
{
var auth = new BlockadeLabsAuthentication().LoadDefaultsReversed();
var settings = new BlockadeLabsSettings();
BlockadeLabsClient = new BlockadeLabsClient(auth, settings);
//BlockadeLabsClient.EnableDebug = true;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 501cf95

Please sign in to comment.