Skip to content

Commit

Permalink
Add support for access keys management in Account Provisioning API
Browse files Browse the repository at this point in the history
  • Loading branch information
const-cloudinary committed Nov 21, 2023
1 parent e1dc7f9 commit 91b770c
Show file tree
Hide file tree
Showing 10 changed files with 538 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,45 @@ public async Task TestUserGroupsInAccount()

Assert.NotNull(foundGroup);
}

[Test, RetryWithDelay]
public async Task TestListAccessKeys()
{
var result = await AccountProvisioning.ListAccessKeysAsync(new ListAccessKeysParams(m_cloudId1));

Assert.LessOrEqual(1, result.Total);
Assert.LessOrEqual(1, result.AccessKeys.Length);
}

[Test, RetryWithDelay]
public async Task TestGenerateAccessKey()
{
var result = await AccountProvisioning.GenerateAccessKeyAsync(new GenerateAccessKeyParams(m_cloudId1)
{
Name = "test_key",
Enabled = false,
});

Assert.AreEqual("test_key", result.Name);
Assert.AreEqual(false, result.Enabled);
}

[Test, RetryWithDelay]
public async Task TestUpdateAccessKey()
{
var accessKeyResult = await AccountProvisioning.ListAccessKeysAsync(new ListAccessKeysParams(m_cloudId1));
var accessKey = accessKeyResult.AccessKeys.FirstOrDefault();

Assert.NotNull(accessKey);

var result = await AccountProvisioning.UpdateAccessKeyAsync(new UpdateAccessKeyParams(m_cloudId1, accessKey.ApiKey)
{
Name = "updated_key",
Enabled = true,
});

Assert.AreEqual("updated_key", result.Name);
Assert.AreEqual(true, result.Enabled);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -215,5 +215,45 @@ public void TestUserGroupsInAccount()

Assert.NotNull(foundGroup);
}

[Test, RetryWithDelay]
public void TestListAccessKeys()
{
var result = AccountProvisioning.ListAccessKeys(new ListAccessKeysParams(m_cloudId1));

Assert.LessOrEqual(1, result.Total);
Assert.LessOrEqual(1, result.AccessKeys.Length);
}

[Test, RetryWithDelay]
public void TestGenerateAccessKey()
{
var result = AccountProvisioning.GenerateAccessKey(new GenerateAccessKeyParams(m_cloudId1)
{
Name = "test_key",
Enabled = false,
});

Assert.AreEqual("test_key", result.Name);
Assert.AreEqual(false, result.Enabled);
}

[Test, RetryWithDelay]
public void TestUpdateAccessKey()
{
var accessKey = AccountProvisioning.ListAccessKeys(new ListAccessKeysParams(m_cloudId1)).AccessKeys.FirstOrDefault();

Assert.NotNull(accessKey);
Assert.IsNotEmpty(accessKey.ApiKey);

var result = AccountProvisioning.UpdateAccessKey(new UpdateAccessKeyParams(m_cloudId1, accessKey.ApiKey)
{
Name = "updated_key",
Enabled = true,
});

Assert.AreEqual("updated_key", result.Name);
Assert.AreEqual(true, result.Enabled);
}
}
}
3 changes: 3 additions & 0 deletions CloudinaryDotNet/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,8 @@ internal static class Constants

/// <summary> User groups resource of account api.</summary>
public const string USER_GROUPS = "user_groups";

/// <summary> Access keys resource of account api.</summary>
public const string ACCESS_KEYS = "access_keys";
}
}
91 changes: 85 additions & 6 deletions CloudinaryDotNet/Provisioning/AccountProvisioning.cs
Original file line number Diff line number Diff line change
Expand Up @@ -446,11 +446,85 @@ public Task<ListUsersResult> UsersGroupUsersAsync(string groupId, CancellationTo
return CallAccountApiAsync<ListUsersResult>(HttpMethod.GET, url, cancellationToken);
}

private static string UrlWithOptionalParameter(Url baseUrl, string urlParameter)
/// <summary>
/// Lists access keys.
/// </summary>
/// <param name="parameters">Parameters to list access keys.</param>
/// <returns>Parsed information about access keys.</returns>
public ListAccessKeysResult ListAccessKeys(ListAccessKeysParams parameters)
{
var url = GetAccessKeysUrl(parameters.SubAccountId);
var urlBuilder = new UrlBuilder(url, parameters.ToParamsDictionary());
return CallAccountApi<ListAccessKeysResult>(HttpMethod.GET, urlBuilder.ToString());
}

/// <summary>
/// Lists access keys asynchronously.
/// </summary>
/// <param name="parameters">Parameters to list access keys.</param>
/// <param name="cancellationToken">(Optional) Cancellation token.</param>
/// <returns>Parsed information about access keys.</returns>
public Task<ListAccessKeysResult> ListAccessKeysAsync(ListAccessKeysParams parameters, CancellationToken? cancellationToken = null)
{
var url = GetAccessKeysUrl(parameters.SubAccountId);
var urlBuilder = new UrlBuilder(url, parameters.ToParamsDictionary());
return CallAccountApiAsync<ListAccessKeysResult>(HttpMethod.GET, urlBuilder.ToString(), cancellationToken);
}

/// <summary>
/// Generates access key.
/// </summary>
/// <param name="parameters">Parameters to generate access key.</param>
/// <returns>Parsed information about generated access key.</returns>
public AccessKeyResult GenerateAccessKey(GenerateAccessKeyParams parameters)
{
var url = GetAccessKeysUrl(parameters.SubAccountId);
return CallAccountApi<AccessKeyResult>(HttpMethod.POST, url, parameters);
}

/// <summary>
/// Generates access key asynchronously.
/// </summary>
/// <param name="parameters">Parameters to generate access key.</param>
/// <param name="cancellationToken">(Optional) Cancellation token.</param>
/// <returns>Parsed information about generated access key.</returns>
public Task<AccessKeyResult> GenerateAccessKeyAsync(GenerateAccessKeyParams parameters, CancellationToken? cancellationToken = null)
{
var url = GetAccessKeysUrl(parameters.SubAccountId);
return CallAccountApiAsync<AccessKeyResult>(HttpMethod.POST, url, cancellationToken, parameters);
}

/// <summary>
/// Updates access key.
/// </summary>
/// <param name="parameters">Parameters to update access key.</param>
/// <returns>Parsed information about updated access key.</returns>
public AccessKeyResult UpdateAccessKey(UpdateAccessKeyParams parameters)
{
if (!string.IsNullOrEmpty(urlParameter))
var url = GetAccessKeysUrl(parameters.SubAccountId, parameters.ApiKey);
return CallAccountApi<AccessKeyResult>(HttpMethod.PUT, url, parameters);
}

/// <summary>
/// Updates access key asynchronously.
/// </summary>
/// <param name="parameters">Parameters to update access key.</param>
/// <param name="cancellationToken">(Optional) Cancellation token.</param>
/// <returns>Parsed information about updated access key.</returns>
public Task<AccessKeyResult> UpdateAccessKeyAsync(UpdateAccessKeyParams parameters, CancellationToken? cancellationToken = null)
{
var url = GetAccessKeysUrl(parameters.SubAccountId, parameters.ApiKey);
return CallAccountApiAsync<AccessKeyResult>(HttpMethod.PUT, url, cancellationToken, parameters);
}

private static string UrlWithOptionalParameters(Url baseUrl, params string[] urlParameters)
{
foreach (var urlParameter in urlParameters)
{
baseUrl.Add(urlParameter);
if (!string.IsNullOrEmpty(urlParameter))
{
baseUrl.Add(urlParameter);
}
}

return baseUrl.BuildUrl();
Expand Down Expand Up @@ -515,16 +589,21 @@ private string GetUserGroupsUrl(string groupId = null)
return BuildAccountApiUrl(Constants.USER_GROUPS, groupId);
}

private string GetAccessKeysUrl(string subAccountId = null, string apiKey = null)
{
return BuildAccountApiUrl(Constants.SUB_ACCOUNTS, subAccountId, Constants.ACCESS_KEYS, apiKey);
}

private string GetUserGroupsUrlForUsers(string groupId, string userId = null)
{
var baseUrl = ProvisioningApi.AccountApiUrlV.Add(Constants.USER_GROUPS).Add(groupId).Add(Constants.USERS);
return UrlWithOptionalParameter(baseUrl, userId);
return UrlWithOptionalParameters(baseUrl, userId);
}

private string BuildAccountApiUrl(string resourceName, string urlParameter)
private string BuildAccountApiUrl(string resourceName, params string[] urlParameters)
{
var baseUrl = ProvisioningApi.AccountApiUrlV.Add(resourceName);
return UrlWithOptionalParameter(baseUrl, urlParameter);
return UrlWithOptionalParameters(baseUrl, urlParameters);
}
}
}
48 changes: 48 additions & 0 deletions CloudinaryDotNet/Provisioning/Actions/AccessKeyResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
namespace CloudinaryDotNet.Actions
{
using System;
using System.Runtime.Serialization;

/// <summary>
/// A single access key.
/// </summary>
[DataContract]
public class AccessKeyResult : BaseResult
{
/// <summary>
/// Gets or sets name of the access key.
/// </summary>
[DataMember(Name = "name")]
public string Name { get; set; }

/// <summary>
/// Gets or sets API key.
/// </summary>
[DataMember(Name = "api_key")]
public string ApiKey { get; set; }

/// <summary>
/// Gets or sets the API secret.
/// </summary>
[DataMember(Name = "api_secret")]
public string ApiSecret { get; set; }

/// <summary>
/// Gets or sets date when the key was created.
/// </summary>
[DataMember(Name = "created_at")]
public DateTime CreatedAt { get; set; }

/// <summary>
/// Gets or sets date when the key was updated.
/// </summary>
[DataMember(Name = "updated_at")]
public DateTime UpdatedAt { get; set; }

/// <summary>
/// Gets or sets a value indicating whether access key is enabled or not.
/// </summary>
[DataMember(Name = "enabled")]
public bool Enabled { get; set; }
}
}
60 changes: 60 additions & 0 deletions CloudinaryDotNet/Provisioning/Actions/GenerateAccessKeyParams.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
namespace CloudinaryDotNet.Actions
{
using System.Collections.Generic;
using System.Runtime.Serialization;

/// <summary>
/// Parameters of generate access key request.
/// </summary>
public class GenerateAccessKeyParams : BaseParams
{
/// <summary>
/// Initializes a new instance of the <see cref="GenerateAccessKeyParams"/> class.
/// </summary>
/// <param name="subAccountId">The ID of the sub-account.</param>
public GenerateAccessKeyParams(string subAccountId)
{
SubAccountId = subAccountId;
}

/// <summary>
/// Gets or sets the ID of the sub-account.
/// </summary>
public string SubAccountId { get; set; }

/// <summary>
/// Gets or sets the name of the access key.
/// </summary>
public string Name { get; set; }

/// <summary>
/// Gets or sets whether the access key is enabled.
/// </summary>
public bool? Enabled { get; set; }

/// <summary>
/// Validate object model.
/// </summary>
public override void Check()
{
Utils.ShouldNotBeEmpty(() => SubAccountId);
}

/// <summary>
/// Add parameters to the object model dictionary.
/// </summary>
/// <param name="dict">Dictionary to be updated with parameters.</param>
protected override void AddParamsToDictionary(SortedDictionary<string, object> dict)
{
if (!string.IsNullOrEmpty(Name))
{
AddParam(dict, "name", Name);
}

if (Enabled.HasValue)
{
AddParam(dict, "enabled", Enabled);
}
}
}
}
Loading

0 comments on commit 91b770c

Please sign in to comment.