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
46 changes: 42 additions & 4 deletions src/Auth0.ManagementApi/Clients/ConnectionsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Auth0.ManagementApi.Models.Connections;

namespace Auth0.ManagementApi.Clients
{
Expand All @@ -16,6 +17,7 @@
{
private readonly JsonConverter[] _converters = { new PagedListConverter<Connection>("connections") };
readonly JsonConverter[] checkpointPaginationConverter = new JsonConverter[] { new CheckpointPagedListConverter<Connection>("connections") };
readonly JsonConverter[] enabledClientsCheckpointPaginationConverter = new JsonConverter[] { new CheckpointPagedListConverter<EnabledClients>("clients") };
private readonly JsonConverter[] _defaultMappingsConverter = { new ListConverter<ScimMapping>("mapping") };

/// <summary>
Expand Down Expand Up @@ -94,8 +96,7 @@
/// <returns>An <see cref="IPagedList{Connection}"/> containing the list of connections.</returns>
public Task<IPagedList<Connection>> GetAllAsync(GetConnectionsRequest request, PaginationInfo pagination = null, CancellationToken cancellationToken = default)
{
if (request == null)
throw new ArgumentNullException(nameof(request));
request.ThrowIfNull();

Check warning on line 99 in src/Auth0.ManagementApi/Clients/ConnectionsClient.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Clients/ConnectionsClient.cs#L99

Added line #L99 was not covered by tests

var queryStrings = new Dictionary<string, string>
{
Expand Down Expand Up @@ -135,8 +136,7 @@
public Task<ICheckpointPagedList<Connection>> GetAllAsync(GetConnectionsRequest request, CheckpointPaginationInfo pagination = null,
CancellationToken cancellationToken = default)
{
if (request == null)
throw new ArgumentNullException(nameof(request));
request.ThrowIfNull();

Check warning on line 139 in src/Auth0.ManagementApi/Clients/ConnectionsClient.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Clients/ConnectionsClient.cs#L139

Added line #L139 was not covered by tests

var queryStrings = new Dictionary<string, string>
{
Expand Down Expand Up @@ -275,5 +275,43 @@
{
return Connection.SendAsync<object>(HttpMethod.Delete, BuildUri($"connections/{EncodePath(id)}/scim-configuration/tokens/{EncodePath(tokenId)}"), null, DefaultHeaders, cancellationToken: cancellationToken);
}

/// <inheritdoc />
public Task<ICheckpointPagedList<EnabledClients>> GetEnabledClientsAsync(
EnabledClientsGetRequest request,
CheckpointPaginationInfo? pagination = null,
CancellationToken cancellationToken = default)
{
request.ThrowIfNull();
request.ConnectionId.ThrowIfNull();

Check warning on line 286 in src/Auth0.ManagementApi/Clients/ConnectionsClient.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Clients/ConnectionsClient.cs#L284-L286

Added lines #L284 - L286 were not covered by tests

var queryStrings = new Dictionary<string, string>();

Check warning on line 288 in src/Auth0.ManagementApi/Clients/ConnectionsClient.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Clients/ConnectionsClient.cs#L288

Added line #L288 was not covered by tests

if (pagination != null)
{
queryStrings["from"] = pagination.From;
queryStrings["take"] = pagination.Take.ToString();
}

Check warning on line 294 in src/Auth0.ManagementApi/Clients/ConnectionsClient.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Clients/ConnectionsClient.cs#L291-L294

Added lines #L291 - L294 were not covered by tests

return Connection.GetAsync<ICheckpointPagedList<EnabledClients>>(
BuildUri(
$"connections/{EncodePath(request.ConnectionId)}/clients",
queryStrings),
DefaultHeaders,
enabledClientsCheckpointPaginationConverter,
cancellationToken);
}

Check warning on line 303 in src/Auth0.ManagementApi/Clients/ConnectionsClient.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Clients/ConnectionsClient.cs#L296-L303

Added lines #L296 - L303 were not covered by tests

/// <inheritdoc />
public Task UpdateEnabledClientsAsync(string id, EnabledClientsUpdateRequest request, CancellationToken cancellationToken = default)
{
request.ThrowIfNull();
return Connection.SendAsync<object>(
new HttpMethod("PATCH"),
BuildUri($"connections/{EncodePath(id)}/clients"),
request.EnabledClients,
DefaultHeaders,
cancellationToken: cancellationToken);
}

Check warning on line 315 in src/Auth0.ManagementApi/Clients/ConnectionsClient.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Clients/ConnectionsClient.cs#L307-L315

Added lines #L307 - L315 were not covered by tests
}
}
19 changes: 19 additions & 0 deletions src/Auth0.ManagementApi/Clients/IConnectionsClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@


using Auth0.ManagementApi.Models.Connections;

namespace Auth0.ManagementApi.Clients
{
using System.Threading;
Expand Down Expand Up @@ -148,5 +150,22 @@ public interface IConnectionsClient
/// <param name="tokenId">The ID of the <see cref="ScimToken"/> to delete</param>
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
Task DeleteScimTokenAsync(string id, string tokenId, CancellationToken cancellationToken = default);

/// <summary>
/// Retrieves a <see cref="ICheckpointPagedList"/> list of enabled clients for a connection.
/// </summary>
/// <param name="request">The request containing criteria for retrieving enabled clients.</param>
/// <param name="pagination">The checkpoint pagination information to use for paged results.</param>
/// <param name="cancellationToken">The cancellation token to cancel the operation.</param>
/// <returns>An <see cref="ICheckpointPagedList{EnabledClients}"/> containing the list of enabled clients.</returns>
public Task<ICheckpointPagedList<EnabledClients>> GetEnabledClientsAsync(EnabledClientsGetRequest request, CheckpointPaginationInfo? pagination = null, CancellationToken cancellationToken = default);

/// <summary>
/// Updates the list of enabled clients for a connection.
/// </summary>
/// <param name="id">The ID of the connection to update enabled clients for.</param>
/// <param name="request">The request containing the updated list of enabled clients.</param>
/// <param name="cancellationToken">The cancellation token to cancel the operation.</param>
public Task UpdateEnabledClientsAsync(string id, EnabledClientsUpdateRequest request, CancellationToken cancellationToken = default);
}
}
14 changes: 14 additions & 0 deletions src/Auth0.ManagementApi/ExtensionMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,19 @@
var enumMemberAttribute = ((EnumMemberAttribute[])enumType.GetTypeInfo().GetDeclaredField(name).GetCustomAttributes(typeof(EnumMemberAttribute), true))[0];
return enumMemberAttribute.Value;
}

/// <summary>
/// Throws an <see cref="ArgumentNullException"/> if the provided object is <see langword="null"/>.
/// </summary>
/// <param name="input">The object to check for <see langword="null"/>.</param>
/// <param name="paramName">The name of the parameter being checked, automatically captured using <see cref="System.Runtime.CompilerServices.CallerArgumentExpressionAttribute"/>.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="input"/> is <see langword="null"/>.</exception>
public static void ThrowIfNull(this object input, [System.Runtime.CompilerServices.CallerArgumentExpression("input")] string? paramName = null)
{

Check warning on line 47 in src/Auth0.ManagementApi/ExtensionMethods.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/ExtensionMethods.cs#L47

Added line #L47 was not covered by tests
if (input == null)
{
throw new ArgumentNullException(paramName);

Check warning on line 50 in src/Auth0.ManagementApi/ExtensionMethods.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/ExtensionMethods.cs#L49-L50

Added lines #L49 - L50 were not covered by tests
}
}

Check warning on line 52 in src/Auth0.ManagementApi/ExtensionMethods.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/ExtensionMethods.cs#L52

Added line #L52 was not covered by tests
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using Auth0.ManagementApi.Models.Connections;
using Newtonsoft.Json;

Expand Down Expand Up @@ -35,9 +36,7 @@ public abstract class ConnectionBase
[JsonProperty("realms")]
public string[] Realms { get; set; }

/// <summary>
/// The identifiers of the clients for which the connection is to be enabled. If the array is empty or the property is not specified, no clients are enabled.
/// </summary>
[Obsolete("This field is deprecated and will be removed in a future version. Use ConnectionsClient.GetEnabledClientsAsync and ConnectionsClient.UpdateEnabledClientsAsync instead. ")]
[JsonProperty("enabled_clients")]
public string[] EnabledClients { get; set; }

Expand Down
12 changes: 12 additions & 0 deletions src/Auth0.ManagementApi/Models/Connections/EnabledClients.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Newtonsoft.Json;

namespace Auth0.ManagementApi.Models.Connections;

public class EnabledClients
{
/// <summary>
/// The client ID
/// </summary>
[JsonProperty("client_id")]
public string? ClientId { get; set; }

Check warning on line 11 in src/Auth0.ManagementApi/Models/Connections/EnabledClients.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Models/Connections/EnabledClients.cs#L11

Added line #L11 was not covered by tests
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Auth0.ManagementApi.Models.Connections;

/// <summary>
/// Contains information required to fetch <see cref="EnabledClients"/>.
/// </summary>
public class EnabledClientsGetRequest
{
/// <summary>
/// The id of the connection for which enabled clients are to be retrieved
/// </summary>
public string ConnectionId { get; set; }

Check warning on line 11 in src/Auth0.ManagementApi/Models/Connections/EnabledClientsGetRequest.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Models/Connections/EnabledClientsGetRequest.cs#L11

Added line #L11 was not covered by tests
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Collections.Generic;
using Newtonsoft.Json;

namespace Auth0.ManagementApi.Models.Connections;

/// <summary>
/// Contains information required to update <see cref="EnabledClients"/>.
/// </summary>
public class EnabledClientsToUpdate
{
/// <summary>
/// The client_id of the client to be the subject to change status
/// </summary>
[JsonProperty("client_id")]
public string ClientId { get; set; }

Check warning on line 15 in src/Auth0.ManagementApi/Models/Connections/EnabledClientsUpdateRequest.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Models/Connections/EnabledClientsUpdateRequest.cs#L15

Added line #L15 was not covered by tests

/// <summary>
/// Whether the connection is enabled or not for this client_id
/// </summary>
[JsonProperty("status")]
public bool? Status { get; set; }

Check warning on line 21 in src/Auth0.ManagementApi/Models/Connections/EnabledClientsUpdateRequest.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Models/Connections/EnabledClientsUpdateRequest.cs#L21

Added line #L21 was not covered by tests
};

public class EnabledClientsUpdateRequest
{
/// <summary>
/// The list of enabled clients to update
/// </summary>
[JsonProperty("enabled_clients")]
public IEnumerable<EnabledClientsToUpdate> EnabledClients { get; set; }

Check warning on line 30 in src/Auth0.ManagementApi/Models/Connections/EnabledClientsUpdateRequest.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Models/Connections/EnabledClientsUpdateRequest.cs#L30

Added line #L30 was not covered by tests
}
100 changes: 100 additions & 0 deletions tests/Auth0.ManagementApi.IntegrationTests/ConnectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,106 @@ async Task<ScimTokenCreateResponse> CreateScimTokenAndValidate(ScimTokenCreateRe
}
}

[Fact]
public async Task Test_enabled_clients_get_and_update()
{

await fixture.ApiClient.Connections.GetAllAsync(new GetConnectionsRequest
{
Strategy = new[] {"auth0"}
}, new PaginationInfo());

var optionsCreateRequestObject = GetConnectionOptionsRequest();

// Create a new connection
var newConnectionRequest = new ConnectionCreateRequest
{
Name = $"{TestingConstants.ConnectionPrefix}-{TestBaseUtils.MakeRandomName()}",
Strategy = "auth0",
DisplayName = "enabledClientsConnectionTest",
Options = optionsCreateRequestObject
};
var newConnectionResponse = await fixture.ApiClient.Connections.CreateAsync(newConnectionRequest);

fixture.TrackIdentifier(CleanUpType.Connections, newConnectionResponse.Id);

newConnectionResponse.Should().NotBeNull();
newConnectionResponse.Name.Should().Be(newConnectionRequest.Name);
newConnectionResponse.Strategy.Should().Be(newConnectionRequest.Strategy);
newConnectionResponse.DisplayName.Should().Be(newConnectionRequest.DisplayName);

var listOfClientsToEnabled = new List<EnabledClientsToUpdate>();
listOfClientsToEnabled.Add(
new EnabledClientsToUpdate()
{
ClientId = TestBaseUtils.GetVariable("AUTH0_CLIENT_ID"),
Status = true
}
);
var enabledClientsUpdateRequest = new EnabledClientsUpdateRequest()
{
EnabledClients = listOfClientsToEnabled
};

await fixture.ApiClient.Connections.UpdateEnabledClientsAsync(newConnectionResponse.Id, enabledClientsUpdateRequest);

var enabledClients =
await fixture.ApiClient.Connections.GetEnabledClientsAsync(
new EnabledClientsGetRequest()
{
ConnectionId = newConnectionResponse.Id
}, new CheckpointPaginationInfo()
);

enabledClients.Should().NotBeNull();
enabledClients.Count.Should().Be(1);
enabledClients.First().ClientId.Should().Be(TestBaseUtils.GetVariable("AUTH0_CLIENT_ID"));

// Delete the connection and ensure we get exception when trying to get connection again
await fixture.ApiClient.Connections.DeleteAsync(newConnectionResponse.Id);
Func<Task> getFunc = async () => await fixture.ApiClient.Connections.GetAsync(newConnectionResponse.Id);
getFunc.Should().Throw<ErrorApiException>().And.ApiError.ErrorCode.Should().Be("inexistent_connection");

fixture.UnTrackIdentifier(CleanUpType.Connections, newConnectionResponse.Id);
}

[Fact]
public async Task Test_GetEnabledClients_Throws_When_Input_Is_Null()
{
var exception = await Assert.ThrowsAsync<ArgumentNullException>(
() => fixture.ApiClient.Connections.GetEnabledClientsAsync(null));
exception.Message.Should().Contain("request");
}

[Fact]
public async Task Test_GetEnabledClients_Throws_When_ConnectionId_Is_Null()
{
var request = new EnabledClientsGetRequest();
var exception = await Assert.ThrowsAsync<ArgumentNullException>(
() => fixture.ApiClient.Connections.GetEnabledClientsAsync(request));
exception.Message.Should().Contain("request");
}


[Fact]
public async Task Test_UpdateEnabledClients_Throws_When_ConnectionId_Is_Null()
{
var exception = await Assert.ThrowsAsync<ArgumentNullException>(
() => fixture.ApiClient.Connections.UpdateEnabledClientsAsync("id", null));
exception.Message.Should().Contain("request");
}

[Fact]
public async Task Test_GetConnections_Throws_When_Input_Is_Null()
{
var exception = await Assert.ThrowsAsync<ArgumentNullException>(
() => fixture.ApiClient.Connections.GetAllAsync(null, new PaginationInfo()));
exception.Message.Should().Contain("request");

exception = await Assert.ThrowsAsync<ArgumentNullException>(
() => fixture.ApiClient.Connections.GetAllAsync(null, new CheckpointPaginationInfo()));
exception.Message.Should().Contain("request");
}
private async Task<string> GenerateBruckeManagementApiToken()
{
using var authenticationApiClient =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;
using FluentAssertions;
using Xunit;

namespace Auth0.ManagementApi.IntegrationTests;

public class ExtensionMethodsTests
{
[Fact]
public void ThrowsArgumentNullException_WhenInputIsNull()
{
// Act & Assert
void ValidateInput(object input)
{
var exception = Assert.Throws<ArgumentNullException>(() => input.ThrowIfNull());
exception.Message.Should().Contain($"{nameof(input)}");
}
ValidateInput(null);
}

[Fact]
public void DoesNotThrowException_WhenInputIsNotNull()
{
// Act & Assert
var input = new object();
input.ThrowIfNull(); // Should not throw
}
}
Loading