Skip to content

Commit

Permalink
fix(offersubscription): skip optional autosetupprovidercallback if it…
Browse files Browse the repository at this point in the history
… is not configured (#865)
  • Loading branch information
ntruchsess authored Jul 24, 2024
1 parent b6fd2e0 commit 900567e
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,11 @@ await _offerProviderService
}

return (
new[] {
[
data.IsSingleInstance ?
ProcessStepTypeId.SINGLE_INSTANCE_SUBSCRIPTION_DETAILS_CREATION :
ProcessStepTypeId.START_AUTOSETUP },
ProcessStepTypeId.START_AUTOSETUP
],
triggerProvider ? ProcessStepStatusId.DONE : ProcessStepStatusId.SKIPPED,
true,
null);
Expand All @@ -100,6 +101,15 @@ await _offerProviderService
throw new NotFoundException($"OfferSubscription {offerSubscriptionId} does not exist");
}

if (string.IsNullOrWhiteSpace(data.CallbackUrl))
{
return (
null,
ProcessStepStatusId.SKIPPED,
true,
null);
}

if (data.Status != OfferSubscriptionStatusId.ACTIVE)
{
throw new ConflictException("offer subscription should be active");
Expand All @@ -110,11 +120,6 @@ await _offerProviderService
throw new ConflictException("Client should be set");
}

if (string.IsNullOrWhiteSpace(data.CallbackUrl))
{
throw new ConflictException("Callback Url should be set here");
}

if (data.ServiceAccounts.Count() > 1)
{
throw new ConflictException("There should be not more than one service account for the offer subscription");
Expand All @@ -123,16 +128,22 @@ await _offerProviderService
CallbackTechnicalUserInfoData? technicalUserInfoData = null;
if (data.ServiceAccounts.Count() == 1)
{
var serviceAccount = data.ServiceAccounts.FirstOrDefault();
var serviceAccount = data.ServiceAccounts.First();
if (serviceAccount.TechnicalClientId == null)
{
throw new ConflictException($"ClientId of serviceAccount {serviceAccount.TechnicalUserId} should be set");
}
var internalClientId = await _provisioningManager.GetIdOfCentralClientAsync(serviceAccount.TechnicalClientId).ConfigureAwait(ConfigureAwaitOptions.None);
var authData = await _provisioningManager.GetCentralClientAuthDataAsync(internalClientId).ConfigureAwait(ConfigureAwaitOptions.None);
async Task<string?> GetServiceAccountSecret(string technicalClientId)
{
var internalClientId = await _provisioningManager.GetIdOfCentralClientAsync(technicalClientId).ConfigureAwait(ConfigureAwaitOptions.None);
var authData = await _provisioningManager.GetCentralClientAuthDataAsync(internalClientId).ConfigureAwait(ConfigureAwaitOptions.None);
return authData.Secret;
}
technicalUserInfoData = new CallbackTechnicalUserInfoData(
serviceAccount.TechnicalUserId,
authData.Secret,
serviceAccount.CompanyServiceAccountKindId == CompanyServiceAccountKindId.INTERNAL
? await GetServiceAccountSecret(serviceAccount.TechnicalClientId).ConfigureAwait(ConfigureAwaitOptions.None)
: null,
serviceAccount.TechnicalClientId);
}

Expand All @@ -141,7 +152,7 @@ await _offerProviderService
new CallbackClientInfoData(data.ClientId)
);
await _offerProviderService
.TriggerOfferProviderCallback(callbackData, data.CallbackUrl!, cancellationToken)
.TriggerOfferProviderCallback(callbackData, data.CallbackUrl, cancellationToken)
.ConfigureAwait(ConfigureAwaitOptions.None);

return (
Expand Down
4 changes: 2 additions & 2 deletions src/marketplace/Offers.Library/Service/OfferSetupService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ public async Task TriggerActivateSubscription(Guid offerSubscriptionId)
if (string.IsNullOrWhiteSpace(offerDetails.RequesterEmail))
{
return new ValueTuple<IEnumerable<ProcessStepTypeId>?, ProcessStepStatusId, bool, string?>(
offerDetails.InstanceData.IsSingleInstance ? null : new[] { ProcessStepTypeId.TRIGGER_PROVIDER_CALLBACK },
offerDetails.InstanceData.IsSingleInstance || !offerDetails.HasCallbackUrl ? null : [ProcessStepTypeId.TRIGGER_PROVIDER_CALLBACK],
ProcessStepStatusId.DONE,
true,
null);
Expand All @@ -687,7 +687,7 @@ public async Task TriggerActivateSubscription(Guid offerSubscriptionId)
SendMail(basePortalAddress, $"{offerDetails.RequesterFirstname} {offerDetails.RequesterLastname}", offerDetails.RequesterEmail, offerDetails.OfferName, offerDetails.OfferTypeId);

return new ValueTuple<IEnumerable<ProcessStepTypeId>?, ProcessStepStatusId, bool, string?>(
offerDetails.InstanceData.IsSingleInstance ? null : new[] { ProcessStepTypeId.TRIGGER_PROVIDER_CALLBACK },
offerDetails.InstanceData.IsSingleInstance || !offerDetails.HasCallbackUrl ? null : [ProcessStepTypeId.TRIGGER_PROVIDER_CALLBACK],
ProcessStepStatusId.DONE,
true,
null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ public record SubscriptionActivationData(
Guid? SalesManagerId,
Guid? ProviderCompanyId,
string? ClientClientId,
IEnumerable<string> InternalServiceAccountClientIds
IEnumerable<string> InternalServiceAccountClientIds,
bool HasCallbackUrl
);
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public interface IOfferSubscriptionsRepository
Task<VerifyProcessData?> GetProcessStepData(Guid offerSubscriptionId, IEnumerable<ProcessStepTypeId> processStepTypeIds);
Task<OfferSubscriptionClientCreationData?> GetClientCreationData(Guid offerSubscriptionId);
Task<OfferSubscriptionTechnicalUserCreationData?> GetTechnicalUserCreationData(Guid offerSubscriptionId);
Task<(IEnumerable<(Guid TechnicalUserId, string? TechnicalClientId)> ServiceAccounts, string? ClientId, string? CallbackUrl, OfferSubscriptionStatusId Status)> GetTriggerProviderCallbackInformation(Guid offerSubscriptionId);
Task<(IEnumerable<(Guid TechnicalUserId, string? TechnicalClientId, CompanyServiceAccountKindId CompanyServiceAccountKindId)> ServiceAccounts, string? ClientId, string? CallbackUrl, OfferSubscriptionStatusId Status)> GetTriggerProviderCallbackInformation(Guid offerSubscriptionId);
OfferSubscriptionProcessData CreateOfferSubscriptionProcessData(Guid offerSubscriptionId, string offerUrl);
void RemoveOfferSubscriptionProcessData(Guid offerSubscriptionProcessDataId);
IAsyncEnumerable<ProcessStepData> GetProcessStepsForSubscription(Guid offerSubscriptionId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,8 @@ public Task<Guid> GetOfferSubscriptionDataForProcessIdAsync(Guid processId) =>
x.Offer.OfferTypeId == OfferTypeId.APP && (x.Offer.AppInstanceSetup == null || !x.Offer.AppInstanceSetup!.IsSingleInstance) ?
x.AppSubscriptionDetail!.AppInstance!.IamClient!.ClientClientId :
null,
x.CompanyServiceAccounts.Where(sa => sa.CompanyServiceAccountKindId == CompanyServiceAccountKindId.INTERNAL && sa.ClientClientId != null).Select(sa => sa.ClientClientId!)
x.CompanyServiceAccounts.Where(sa => sa.CompanyServiceAccountKindId == CompanyServiceAccountKindId.INTERNAL && sa.ClientClientId != null).Select(sa => sa.ClientClientId!),
x.Offer.ProviderCompany!.ProviderCompanyDetail!.AutoSetupCallbackUrl != null
))
.SingleOrDefaultAsync();

Expand Down Expand Up @@ -451,11 +452,11 @@ public Task<Guid> GetOfferSubscriptionDataForProcessIdAsync(Guid processId) =>
.SingleOrDefaultAsync();

/// <inheritdoc />
public Task<(IEnumerable<(Guid TechnicalUserId, string? TechnicalClientId)> ServiceAccounts, string? ClientId, string? CallbackUrl, OfferSubscriptionStatusId Status)> GetTriggerProviderCallbackInformation(Guid offerSubscriptionId) =>
public Task<(IEnumerable<(Guid TechnicalUserId, string? TechnicalClientId, CompanyServiceAccountKindId CompanyServiceAccountKindId)> ServiceAccounts, string? ClientId, string? CallbackUrl, OfferSubscriptionStatusId Status)> GetTriggerProviderCallbackInformation(Guid offerSubscriptionId) =>
_context.OfferSubscriptions
.Where(x => x.Id == offerSubscriptionId)
.Select(x => new ValueTuple<IEnumerable<(Guid, string?)>, string?, string?, OfferSubscriptionStatusId>(
x.CompanyServiceAccounts.Select(sa => new ValueTuple<Guid, string?>(sa.Id, sa.ClientClientId)),
.Select(x => new ValueTuple<IEnumerable<(Guid, string?, CompanyServiceAccountKindId)>, string?, string?, OfferSubscriptionStatusId>(
x.CompanyServiceAccounts.Select(sa => new ValueTuple<Guid, string?, CompanyServiceAccountKindId>(sa.Id, sa.ClientClientId, sa.CompanyServiceAccountKindId)),
x.AppSubscriptionDetail!.AppInstance!.IamClient!.ClientClientId,
x.Offer!.ProviderCompany!.ProviderCompanyDetail!.AutoSetupCallbackUrl,
x.OfferSubscriptionStatusId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public async Task TriggerProviderCallback_InvalidSubscriptionId_Throws()
// Arrange
var fakeId = Guid.NewGuid();
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(fakeId))
.Returns<(IEnumerable<(Guid, string?)>, string?, string?, OfferSubscriptionStatusId)>(default);
.Returns<(IEnumerable<(Guid, string?, CompanyServiceAccountKindId)>, string?, string?, OfferSubscriptionStatusId)>(default);
async Task Act() => await _sut.TriggerProviderCallback(fakeId, CancellationToken.None);

// Act
Expand All @@ -159,7 +159,7 @@ public async Task TriggerProviderCallback_WithPendingSubscription_Throws()
// Arrange
var fakeId = Guid.NewGuid();
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(fakeId))
.Returns((Enumerable.Empty<(Guid, string?)>(), string.Empty, null, OfferSubscriptionStatusId.PENDING));
.Returns((Enumerable.Empty<(Guid, string?, CompanyServiceAccountKindId)>(), string.Empty, "callback", OfferSubscriptionStatusId.PENDING));
async Task Act() => await _sut.TriggerProviderCallback(fakeId, CancellationToken.None);

// Act
Expand All @@ -175,7 +175,7 @@ public async Task TriggerProviderCallback_WithClientIdNotSet_Throws()
// Arrange
var fakeId = Guid.NewGuid();
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(fakeId))
.Returns((Enumerable.Empty<(Guid, string?)>(), null, null, OfferSubscriptionStatusId.ACTIVE));
.Returns((Enumerable.Empty<(Guid, string?, CompanyServiceAccountKindId)>(), null, "callback", OfferSubscriptionStatusId.ACTIVE));
async Task Act() => await _sut.TriggerProviderCallback(fakeId, CancellationToken.None);

// Act
Expand All @@ -186,19 +186,19 @@ public async Task TriggerProviderCallback_WithClientIdNotSet_Throws()
}

[Fact]
public async Task TriggerProviderCallback_WithCallbackUrlNotSet_Throws()
public async Task TriggerProviderCallback_WithCallbackUrlNotSet_Skips()
{
// Arrange
var fakeId = Guid.NewGuid();
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(fakeId))
.Returns((Enumerable.Empty<(Guid, string?)>(), "cl1", null, OfferSubscriptionStatusId.ACTIVE));
async Task Act() => await _sut.TriggerProviderCallback(fakeId, CancellationToken.None);
.Returns((Enumerable.Empty<(Guid, string?, CompanyServiceAccountKindId)>(), "cl1", null, OfferSubscriptionStatusId.ACTIVE));

// Act
var ex = await Assert.ThrowsAsync<ConflictException>(Act);
var result = await _sut.TriggerProviderCallback(fakeId, CancellationToken.None);

// Assert
ex.Message.Should().Be("Callback Url should be set here");
result.nextStepTypeIds.Should().BeNull();
result.stepStatusId.Should().Be(ProcessStepStatusId.SKIPPED);
}

[Fact]
Expand All @@ -207,7 +207,7 @@ public async Task TriggerProviderCallback_WithNoServiceAccountSet_CallsExpected(
// Arrange
var fakeId = Guid.NewGuid();
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(fakeId))
.Returns((Enumerable.Empty<(Guid, string?)>(), "cl1", "https://callback.com", OfferSubscriptionStatusId.ACTIVE));
.Returns((Enumerable.Empty<(Guid, string?, CompanyServiceAccountKindId)>(), "cl1", "https://callback.com", OfferSubscriptionStatusId.ACTIVE));

// Act
var result = await _sut.TriggerProviderCallback(fakeId, CancellationToken.None);
Expand All @@ -226,10 +226,10 @@ public async Task TriggerProviderCallback_WithMultipleServiceAccountSet_Throws()
{
// Arrange
var fakeId = Guid.NewGuid();
var serviceAccounts = new (Guid, string?)[]
var serviceAccounts = new (Guid, string?, CompanyServiceAccountKindId)[]
{
new(Guid.NewGuid(), "sa1"),
new(Guid.NewGuid(), "sa2")
new(Guid.NewGuid(), "sa1", CompanyServiceAccountKindId.INTERNAL),
new(Guid.NewGuid(), "sa2", CompanyServiceAccountKindId.INTERNAL)
};
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(fakeId))
.Returns((serviceAccounts, "cl1", "https://callback.com", OfferSubscriptionStatusId.ACTIVE));
Expand All @@ -243,15 +243,15 @@ public async Task TriggerProviderCallback_WithMultipleServiceAccountSet_Throws()
}

[Fact]
public async Task TriggerProviderCallback_WithValidData_ReturnsExpected()
public async Task TriggerProviderCallback_WithValidData_InternalSA_ReturnsExpected()
{
// Arrange
var technicalUserId = Guid.NewGuid();
var technicalUserClientId = "sa1";
var technicalUserInternalClientId = Guid.NewGuid().ToString();
var serviceAccounts = new (Guid, string?)[]
var serviceAccounts = new (Guid, string?, CompanyServiceAccountKindId)[]
{
new(technicalUserId, technicalUserClientId)
new(technicalUserId, technicalUserClientId, CompanyServiceAccountKindId.INTERNAL)
};
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(_subscriptionId))
.Returns((serviceAccounts, "cl1", "https://callback.com", OfferSubscriptionStatusId.ACTIVE));
Expand All @@ -271,6 +271,34 @@ public async Task TriggerProviderCallback_WithValidData_ReturnsExpected()
.MustHaveHappenedOnceExactly();
}

[Fact]
public async Task TriggerProviderCallback_WithValidData_ExternalSA_ReturnsExpected()
{
// Arrange
var technicalUserId = Guid.NewGuid();
var technicalUserClientId = "sa1";
var serviceAccounts = new (Guid, string?, CompanyServiceAccountKindId)[]
{
new(technicalUserId, technicalUserClientId, CompanyServiceAccountKindId.EXTERNAL)
};
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(_subscriptionId))
.Returns((serviceAccounts, "cl1", "https://callback.com", OfferSubscriptionStatusId.ACTIVE));

// Act
var result = await _sut.TriggerProviderCallback(_subscriptionId, CancellationToken.None);

// Assert
result.nextStepTypeIds.Should().BeNull();
result.stepStatusId.Should().Be(ProcessStepStatusId.DONE);
result.modified.Should().BeTrue();
A.CallTo(() => _provisioningManager.GetIdOfCentralClientAsync(A<string>._))
.MustNotHaveHappened();
A.CallTo(() => _provisioningManager.GetCentralClientAuthDataAsync(A<string>._))
.MustNotHaveHappened();
A.CallTo(() => _offerProviderService.TriggerOfferProviderCallback(A<OfferProviderCallbackData>.That.Matches(x => x.TechnicalUserInfo!.TechnicalUserSecret == null), A<string>._, A<CancellationToken>._))
.MustHaveHappenedOnceExactly();
}

#endregion

#region Setup
Expand Down
Loading

0 comments on commit 900567e

Please sign in to comment.