Skip to content

Commit

Permalink
Refactor update client and update tests. Add E2E test for token valid…
Browse files Browse the repository at this point in the history
…ation
  • Loading branch information
CSR2017 committed Jan 10, 2025
1 parent f373a5b commit e971368
Show file tree
Hide file tree
Showing 13 changed files with 228 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,9 @@ public async Task<ClientClientsResult> GetAllClientsAsync()

private async Task CheckAndCreateClientScopeAsync(string scope)
{
var clientScopes = await _keycloakClient.GetClientScopesAsync(_realm);
ClientScope? clientScope = clientScopes.FirstOrDefault(x => x.Name.Equals(scope));
bool scopeExists = await ClientScopeExistsAsync(scope);

if (clientScope is null)
if (!scopeExists)
{
await _keycloakClient.CreateClientScopeAsync(
_realm,
Expand Down Expand Up @@ -218,6 +217,13 @@ await _keycloakClient.CreateClientScopeAsync(
}
}

private async Task<bool> ClientScopeExistsAsync(string scope)
{
var clientScopes = await _keycloakClient.GetClientScopesAsync(_realm);
ClientScope? clientScope = clientScopes.FirstOrDefault(x => x.Name.Equals(scope));
return clientScope != null;
}

private static IdentityProviderError ExceptionToKeycloakError(FlurlHttpException ex)
{
return ex.StatusCode switch
Expand All @@ -241,16 +247,44 @@ string scope
var client = await _keycloakClient.GetClientAsync(_realm, clientUuid);
if (client != null)
{
client.Name = displayName;
client.DefaultClientScopes = [scope];
await CheckAndCreateClientScopeAsync(scope);
await _keycloakClient.UpdateClientAsync(_realm, clientUuid, client);
return new ClientUpdateResult.Success();
}
else
{
return new ClientUpdateResult.FailureNotFound($"Client {clientUuid} not found.");
var scopeExists = await ClientScopeExistsAsync(scope);
if (scopeExists)
{
// Delete the existing client
await _keycloakClient.DeleteClientAsync(_realm, clientUuid);
Client newClient = new()
{
ClientId = client.ClientId,
Enabled = true,
Secret = client.Secret,
Name = displayName,
ServiceAccountsEnabled = true,
DefaultClientScopes = [scope],
ProtocolMappers = client.ProtocolMappers,
};
// Re-create the client
string? newClientId = await _keycloakClient.CreateClientAndRetrieveClientIdAsync(
_realm,
newClient
);
if (!string.IsNullOrEmpty(newClientId))
{
return new ClientUpdateResult.Success(Guid.Parse(newClientId));
}
}
else
{
var scopeNotFound = $"Scope {scope} not found";
logger.LogError(message: scopeNotFound);
return new ClientUpdateResult.FailureIdentityProvider(
new IdentityProviderError(scopeNotFound)
);
}
}

logger.LogError("Update client failure");
return new ClientUpdateResult.FailureUnknown($"Error while updating the client: {displayName}");
}
catch (FlurlHttpException ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,10 @@ public async Task Should_get_and_failure_reference_not_found_and_invalid_vendor_
EducationOrganizationIds = [],
};

var applicationUpdateResult = await _applicationRepository.UpdateApplication(applicationUpdate);
var applicationUpdateResult = await _applicationRepository.UpdateApplication(
applicationUpdate,
new ApiClientCommand { ClientId = Guid.NewGuid().ToString(), ClientUuid = Guid.NewGuid() }
);
applicationUpdateResult.Should().BeOfType<ApplicationUpdateResult.FailureVendorNotFound>();
}
}
Expand Down Expand Up @@ -235,7 +238,8 @@ public async Task SetUp()
ClaimSetName = command.ClaimSetName,
EducationOrganizationIds = command.EducationOrganizationIds,
VendorId = command.VendorId,
}
},
new ApiClientCommand { ClientId = Guid.NewGuid().ToString(), ClientUuid = Guid.NewGuid() }
);
vendorUpdateResult.Should().BeOfType<ApplicationUpdateResult.Success>();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class InsertTest : ClaimSetTests
[SetUp]
public async Task Setup()
{
ClaimSetInsertCommand claimSet = new() { Name = "Test ClaimSet" };
ClaimSetInsertCommand claimSet = new() { Name = "Test-ClaimSet" };

var result = await _repository.InsertClaimSet(claimSet);
result.Should().BeOfType<ClaimSetInsertResult.Success>();
Expand All @@ -49,7 +49,7 @@ public async Task Should_get_test_claimSet_from_get_all()
claimSetFromDb.Should().BeOfType<ClaimSetResponseReduced>();

var reducedResponse = (ClaimSetResponseReduced)claimSetFromDb;
reducedResponse.Name.Should().Be("Test ClaimSet");
reducedResponse.Name.Should().Be("Test-ClaimSet");
}

[Test]
Expand All @@ -62,13 +62,13 @@ public async Task Should_get_test_claimSet_from_get_by_id()
claimSetFromDb.Should().BeOfType<ClaimSetResponseReduced>();

var reducedResponse = (ClaimSetResponseReduced)claimSetFromDb;
reducedResponse.Name.Should().Be("Test ClaimSet");
reducedResponse.Name.Should().Be("Test-ClaimSet");
}

[Test]
public async Task Should_get_duplicate_failure()
{
ClaimSetInsertCommand claimSetDup = new() { Name = "Test ClaimSet" };
ClaimSetInsertCommand claimSetDup = new() { Name = "Test-ClaimSet" };

var resultDup = await _repository.InsertClaimSet(claimSetDup);
resultDup.Should().BeOfType<ClaimSetInsertResult.FailureDuplicateClaimSetName>();
Expand All @@ -84,15 +84,15 @@ public class UpdateTests : ClaimSetTests
[SetUp]
public async Task Setup()
{
_insertClaimSet = new ClaimSetInsertCommand() { Name = "Test Insert ClaimSet" };
_insertClaimSet = new ClaimSetInsertCommand() { Name = "Test-Insert-ClaimSet" };

_updateClaimSet = new ClaimSetUpdateCommand() { Name = "Test Update ClaimSet" };
_updateClaimSet = new ClaimSetUpdateCommand() { Name = "Test-Update-ClaimSet" };

var insertResult = await _repository.InsertClaimSet(_insertClaimSet);
insertResult.Should().BeOfType<ClaimSetInsertResult.Success>();

_updateClaimSet.Id = (insertResult as ClaimSetInsertResult.Success)!.Id;
_updateClaimSet.Name = "Test Update ClaimSet";
_updateClaimSet.Name = "Test-Update-ClaimSet";

var updateResult = await _repository.UpdateClaimSet(_updateClaimSet);
updateResult.Should().BeOfType<ClaimSetUpdateResult.Success>();
Expand All @@ -112,7 +112,7 @@ public async Task Should_get_update_claimSet_from_get_all()
claimSetFromDb.Should().BeOfType<ClaimSetResponseReduced>();

var reducedResponse = (ClaimSetResponseReduced)claimSetFromDb;
reducedResponse.Name.Should().Be("Test Update ClaimSet");
reducedResponse.Name.Should().Be("Test-Update-ClaimSet");
}

[Test]
Expand All @@ -125,7 +125,7 @@ public async Task Should_get_test_claimSet_from_get_by_id()
claimSetFromDb.Should().BeOfType<ClaimSetResponseReduced>();

var reducedResponse = (ClaimSetResponseReduced)claimSetFromDb;
reducedResponse.Name.Should().Be("Test Update ClaimSet");
reducedResponse.Name.Should().Be("Test-Update-ClaimSet");
}
}

Expand All @@ -139,12 +139,12 @@ public class DeleteTests : ClaimSetTests
public async Task Setup()
{
var insertResult1 = await _repository.InsertClaimSet(
new ClaimSetInsertCommand() { Name = "Test One" }
new ClaimSetInsertCommand() { Name = "Test-One" }
);
_id1 = ((ClaimSetInsertResult.Success)insertResult1).Id;

var insertResult2 = await _repository.InsertClaimSet(
new ClaimSetInsertCommand() { Name = "Test Two" }
new ClaimSetInsertCommand() { Name = "Test-Two" }
);
_id2 = ((ClaimSetInsertResult.Success)insertResult2).Id;

Expand Down Expand Up @@ -180,7 +180,7 @@ public class ExportTest : ClaimSetTests
[SetUp]
public async Task Setup()
{
ClaimSetInsertCommand claimSet = new() { Name = "Test Export ClaimSet" };
ClaimSetInsertCommand claimSet = new() { Name = "Test-Export-ClaimSet" };

var result = await _repository.InsertClaimSet(claimSet);
result.Should().BeOfType<ClaimSetInsertResult.Success>();
Expand All @@ -195,7 +195,7 @@ public async Task Should_export_claimSet()
result.Should().BeOfType<ClaimSetExportResult.Success>();

var valueFromDb = ((ClaimSetExportResult.Success)result).ClaimSetExportResponse;
valueFromDb.Name.Should().Be("Test Export ClaimSet");
valueFromDb.Name.Should().Be("Test-Export-ClaimSet");
}
}

Expand Down Expand Up @@ -233,7 +233,7 @@ public async Task Setup()

ClaimSetImportCommand claimSet = new()
{
Name = "Test Import ClaimSet",
Name = "Test-Import-ClaimSet",
ResourceClaims = resourceClaims,
};

Expand Down Expand Up @@ -262,7 +262,7 @@ public async Task Should_get_test_claimSet_from_get_by_id()
claimSetFromDb.Should().BeOfType<ClaimSetResponse>();

var response = (ClaimSetResponse)claimSetFromDb;
response.Name.Should().Be("Test Import ClaimSet");
response.Name.Should().Be("Test-Import-ClaimSet");
response.ResourceClaims.Should().NotBeNull();
}

Expand Down Expand Up @@ -295,7 +295,7 @@ public async Task Should_get_duplicate_failure()

ClaimSetImportCommand claimSetDup = new()
{
Name = "Test Import ClaimSet",
Name = "Test-Import-ClaimSet",
ResourceClaims = resourceClaims,
};

Expand All @@ -313,14 +313,14 @@ public class CopyTest : ClaimSetTests
[SetUp]
public async Task Setup()
{
ClaimSetInsertCommand claimSet = new() { Name = "Original ClaimSet" };
ClaimSetInsertCommand claimSet = new() { Name = "Original-ClaimSet" };

var result = await _repository.InsertClaimSet(claimSet);
result.Should().BeOfType<ClaimSetInsertResult.Success>();
_id = (result as ClaimSetInsertResult.Success)!.Id;
_id.Should().BeGreaterThan(0);

ClaimSetCopyCommand command = new() { OriginalId = _id, Name = "Copy Test ClaimSet" };
ClaimSetCopyCommand command = new() { OriginalId = _id, Name = "Copy-Test-ClaimSet" };

var copy = await _repository.Copy(command);
copy.Should().BeOfType<ClaimSetCopyResult.Success>();
Expand All @@ -347,7 +347,7 @@ public async Task Should_get_claimSet_from_get_by_id()
claimSetFromDb1.Should().BeOfType<ClaimSetResponseReduced>();

var reducedResponse1 = (ClaimSetResponseReduced)claimSetFromDb1;
reducedResponse1.Name.Should().Be("Original ClaimSet");
reducedResponse1.Name.Should().Be("Original-ClaimSet");

var getByIdResult2 = await _repository.GetClaimSet(_idCopy, false);
getByIdResult2.Should().BeOfType<ClaimSetGetResult.Success>();
Expand All @@ -356,7 +356,7 @@ public async Task Should_get_claimSet_from_get_by_id()
claimSetFromDb2.Should().BeOfType<ClaimSetResponseReduced>();

var reducedResponse2 = (ClaimSetResponseReduced)claimSetFromDb2;
reducedResponse2.Name.Should().Be("Copy Test ClaimSet");
reducedResponse2.Name.Should().Be("Copy-Test-ClaimSet");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ ILogger<ApplicationRepository> logger
{
public async Task<ApplicationInsertResult> InsertApplication(
ApplicationInsertCommand command,
ApiClientInsertCommand clientCommand
ApiClientCommand clientCommand
)
{
await using var connection = new NpgsqlConnection(databaseOptions.Value.DatabaseConnection);
Expand Down Expand Up @@ -174,7 +174,10 @@ FROM dmscs.Application a
}
}

public async Task<ApplicationUpdateResult> UpdateApplication(ApplicationUpdateCommand command)
public async Task<ApplicationUpdateResult> UpdateApplication(
ApplicationUpdateCommand command,
ApiClientCommand clientCommand
)
{
await using var connection = new NpgsqlConnection(databaseOptions.Value.DatabaseConnection);
await connection.OpenAsync();
Expand Down Expand Up @@ -209,6 +212,14 @@ INSERT INTO dmscs.ApplicationEducationOrganization (ApplicationId, EducationOrga
});

await connection.ExecuteAsync(sql, educationOrganizations);

string updateApiClientsql = """
UPDATE dmscs.ApiClient
SET ClientUuid=@ClientUuid WHERE ClientId = @ClientId;
""";

await connection.ExecuteAsync(updateApiClientsql, clientCommand);

await transaction.CommitAsync();

return new ApplicationUpdateResult.Success();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0.
// See the LICENSE and NOTICES files in the project root for more information.

using EdFi.DmsConfigurationService.DataModel;
using EdFi.DmsConfigurationService.DataModel.Model;
using EdFi.DmsConfigurationService.DataModel.Model.Application;

Expand All @@ -13,11 +12,14 @@ public interface IApplicationRepository
{
Task<ApplicationInsertResult> InsertApplication(
ApplicationInsertCommand command,
ApiClientInsertCommand clientCommand
ApiClientCommand clientCommand
);
Task<ApplicationQueryResult> QueryApplication(PagingQuery query);
Task<ApplicationGetResult> GetApplication(long id);
Task<ApplicationUpdateResult> UpdateApplication(ApplicationUpdateCommand command);
Task<ApplicationUpdateResult> UpdateApplication(
ApplicationUpdateCommand command,
ApiClientCommand clientCommand
);
Task<ApplicationDeleteResult> DeleteApplication(long id);
Task<ApplicationApiClientsResult> GetApplicationApiClients(long id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public record FailureUnknown(string FailureMessage) : ClientResetResult();

public record ClientUpdateResult
{
public record Success() : ClientUpdateResult;
public record Success(Guid ClientUuid) : ClientUpdateResult;

public record FailureIdentityProvider(IdentityProviderError IdentityProviderError) : ClientUpdateResult();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace EdFi.DmsConfigurationService.DataModel.Model.Application;

public class ApiClientInsertCommand
public class ApiClientCommand
{
public required string ClientId { get; set; }
public required Guid ClientUuid { get; set; }
Expand Down
Loading

0 comments on commit e971368

Please sign in to comment.