Skip to content

Commit

Permalink
EES-5753 Add and use new email template to highlight breaking changes…
Browse files Browse the repository at this point in the history
… in new publications of api data sets. Uses a small utility class to determine which template id to use. Adds template ID references to infrastructure (template.json). Note this requires a manual faffy deploy ticket to add the required secrets in each environment.
  • Loading branch information
mmoalin committed Feb 14, 2025
1 parent 40fa286 commit 2885e38
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,4 @@ src/GovUk.Education.ExploreEducationStatistics.Admin/appsettings.IdpBootstrapUse

## IDE Files (e.g. local Visual Studio configuration)
*.csproj.user
/src/GovUk.Education.ExploreEducationStatistics.slnLaunch.user
6 changes: 4 additions & 2 deletions infrastructure/templates/template.json
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,8 @@
"ees-notifier-templateid-subscription-confirmation": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-notifier-templateid-subscription-confirmation')]",
"ees-notifier-templateid-subscription-verification": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-notifier-templateid-subscription-verification')]",
"ees-notifier-templateid-api-subscription-confirmation": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-notifier-templateid-api-subscription-confirmation')]",
"ees-notifier-templateid-api-subscription-notification": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-notifier-templateid-api-subscription-notification')]",
"ees-notifier-templateid-api-subscription-major-data-set-version": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-notifier-templateid-api-subscription-major-data-set-version')]",
"ees-notifier-templateid-api-subscription-minor-data-set-version": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-notifier-templateid-api-subscription-minor-data-set-version')]",
"ees-notifier-templateid-api-subscription-verification": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-notifier-templateid-api-subscription-verification')]",
"ees-openidconnect-clientid": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-openidconnect-clientid')]",
"ees-openidconnect-clientsecret": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-openidconnect-clientsecret')]",
Expand Down Expand Up @@ -2985,7 +2986,8 @@
"GovUkNotify:EmailTemplates:SubscriptionConfirmationId": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('ees-notifier-templateid-subscription-confirmation'), '2018-02-14').secretUriWithVersion, ')')]",
"GovUkNotify:EmailTemplates:SubscriptionVerificationId": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('ees-notifier-templateid-subscription-verification'), '2018-02-14').secretUriWithVersion, ')')]",
"GovUkNotify:EmailTemplates:ApiSubscriptionConfirmationId": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('ees-notifier-templateid-api-subscription-confirmation'), '2018-02-14').secretUriWithVersion, ')')]",
"GovUkNotify:EmailTemplates:ApiSubscriptionNotificationId": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('ees-notifier-templateid-api-subscription-notification'), '2018-02-14').secretUriWithVersion, ')')]",
"GovUkNotify:EmailTemplates:ApiSubscriptionMajorDataSetVersionNotificationId": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('ees-notifier-templateid-api-subscription-major-data-set-version'), '2018-02-14').secretUriWithVersion, ')')]",
"GovUkNotify:EmailTemplates:ApiSubscriptionMinorDataSetVersionNotificationId": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('ees-notifier-templateid-api-subscription-minor-data-set-version'), '2018-02-14').secretUriWithVersion, ')')]",
"GovUkNotify:EmailTemplates:ApiSubscriptionVerificationId": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('ees-notifier-templateid-api-subscription-verification'), '2018-02-14').secretUriWithVersion, ')')]"
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using GovUk.Education.ExploreEducationStatistics.Common.Tests.Utils;
using GovUk.Education.ExploreEducationStatistics.Notifier.Functions;
using GovUk.Education.ExploreEducationStatistics.Notifier.Model;
using GovUk.Education.ExploreEducationStatistics.Notifier.Options;
using GovUk.Education.ExploreEducationStatistics.Notifier.Requests;
using GovUk.Education.ExploreEducationStatistics.Notifier.Services.Interfaces;
using GovUk.Education.ExploreEducationStatistics.Notifier.Validators;
Expand All @@ -28,7 +29,7 @@ public abstract class ApiSubscriptionFunctionsTests(NotifierFunctionsIntegration
private const string DataSetTitle = "data set title";
private const string Version = "1.0";
private const string Email = "[email protected]";

public class RequestPendingSubscriptionTests(NotifierFunctionsIntegrationTestFixture fixture)
: ApiSubscriptionFunctionsTests(fixture)
{
Expand Down Expand Up @@ -555,12 +556,12 @@ public async Task Success()
};

await CreateApiSubscription(subscription);

string? unsubscribeUrl = null;
fixture.NotificationClient
.Setup(mock => mock.SendEmail(
Email,
GetGovUkNotifyOptions().EmailTemplates.ApiSubscriptionNotificationId,
GetGovUkNotifyOptions().EmailTemplates.ApiSubscriptionMinorDataSetVersionId,
It.Is<Dictionary<string, dynamic>>(personalisation =>
AssertEmailTemplateValues(
personalisation,
Expand Down Expand Up @@ -746,6 +747,43 @@ await functions.RemoveExpiredSubscriptions(
}
}

public class ApiSubscriptionEmailsHelperTests
{
[Theory]
[InlineData("2.0.0", "major-template-id")]
[InlineData("2.0", "major-template-id")]
[InlineData("3.0.0", "major-template-id")]
[InlineData("3.0", "major-template-id")]
[InlineData("1.1.0", "minor-template-id")]
[InlineData("1.1", "minor-template-id")]
[InlineData("1.0.1", "minor-template-id")]
[InlineData("2.1.0", "minor-template-id")]
[InlineData("2.1", "minor-template-id")]
[InlineData("2.0.1", "minor-template-id")]
[InlineData("1.0.0", "minor-template-id")]
[InlineData("1.0", "minor-template-id")]
[InlineData("0.0.1", "minor-template-id")]
public void SelectApiSubscriptionNotifEmailTemplateID_ReturnsCorrectTemplateId(string version, string expectedTemplateId)
{
var newApiSubscriptionNotifEmailTemplateIdSelector = new ApiSubscriptionEmailsHelper("major-template-id", "minor-template-id");
var templateId = newApiSubscriptionNotifEmailTemplateIdSelector.SelectApiSubscriptionNotifEmailTemplateID(version);
Assert.Equal(expectedTemplateId, templateId);
}


[Theory]
[InlineData("2.*.0")]
[InlineData("Not a version")]
[InlineData("1.1.1.1")]
[InlineData("")]
public void SelectApiSubscriptionNotifEmailTemplateID_ThrowsArgumentException(string version)
{
var newApiSubscriptionNotifEmailTemplateIdSelector = new ApiSubscriptionEmailsHelper("major-template-id", "minor-template-id");
var exception = Assert.Throws<ArgumentException>(() => newApiSubscriptionNotifEmailTemplateIdSelector.SelectApiSubscriptionNotifEmailTemplateID(version));
Assert.Equal(ValidationMessages.InvalidDataSetVersion.Message, exception.Message);
}
}

private string? ExtractEmailFromSubscriptionLinkToken(string? subscriptionLink)
{
if (subscriptionLink == null)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using GovUk.Education.ExploreEducationStatistics.Notifier.Validators;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("GovUk.Education.ExploreEducationStatistics.Notifier.Tests")]

namespace GovUk.Education.ExploreEducationStatistics.Notifier.Options;
internal class ApiSubscriptionEmailsHelper(string apiSubscriptionMajorDataSetVersionId, string apiSubscriptionMinorDataSetVersionId)
{
private readonly string _apiSubscriptionMajorDataSetVersionId = apiSubscriptionMajorDataSetVersionId;
private readonly string _apiSubscriptionMinorDataSetVersionId = apiSubscriptionMinorDataSetVersionId;
/// <summary>
/// Select the correct email template ID based on publication data set version
/// i.e., major/minor version sends a different message via corresponding e-mail template ID
/// </summary>
/// <param name="version"></param>
/// <returns></returns>
/// <exception cref="System.ArgumentException"></exception>
public string SelectApiSubscriptionNotifEmailTemplateID(string version)
{
if (!Common.Utils.DataSetVersionNumber.TryParse(version, out var dataSetVersionNumber))
{
throw new System.ArgumentException(ValidationMessages.InvalidDataSetVersion.Message);
}
var isNewMajorVersion = dataSetVersionNumber!.Major >= 2
&& dataSetVersionNumber.Patch == 0
&& dataSetVersionNumber.Minor == 0;
return isNewMajorVersion ? _apiSubscriptionMajorDataSetVersionId : _apiSubscriptionMinorDataSetVersionId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ public class EmailTemplateOptions

public string ApiSubscriptionConfirmationId { get; init; } = null!;

public string ApiSubscriptionNotificationId { get; init; } = null!;
public string ApiSubscriptionMinorDataSetVersionId { get; init; } = null!;

public string ApiSubscriptionMajorDataSetVersionId { get; init; } = null!;

public string ApiSubscriptionVerificationId { get; init; } = null!;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,13 +363,15 @@ private void SendNotificationEmail(
{ NotifierEmailTemplateFields.DataSetVersion, version },
{ NotifierEmailTemplateFields.UnsubscribeUrl, unsubscribeUrl }
};

var govUkNotifyEmailsConfigs = govUkNotifyOptions.Value.EmailTemplates;
emailService.SendEmail(
email: subscription.RowKey,
templateId: govUkNotifyOptions.Value.EmailTemplates.ApiSubscriptionNotificationId,
templateId: new ApiSubscriptionEmailsHelper(
govUkNotifyEmailsConfigs.ApiSubscriptionMajorDataSetVersionId,
govUkNotifyEmailsConfigs.ApiSubscriptionMinorDataSetVersionId)
.SelectApiSubscriptionNotifEmailTemplateID(version),
values: personalisation);
}

private async Task<AsyncPageable<ApiSubscription>> GetExpiredApiSubscriptions(CancellationToken cancellationToken)
{
Expression<Func<ApiSubscription, bool>> filter = s =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,9 @@ public static class ValidationMessages
Code: nameof(AuthorizationTokenInvalid),
Message: "The authorization token is invalid."
);

public static readonly LocalizableMessage InvalidDataSetVersion = new(
Code: "InvalidDataSetVersion",
Message: "The data set version version number supplied is invalid."
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"SubscriptionConfirmationId": "change-me",
"SubscriptionVerificationId": "change-me",
"ApiSubscriptionConfirmationId": "change-me",
"ApiSubscriptionNotificationId": "change-me",
"ApiSubscriptionMinorDataSetVersionId": "change-me",
"ApiSubscriptionMajorDataSetVersionId": "change-me",
"ApiSubscriptionVerificationId": "change-me"
}
}
Expand Down

0 comments on commit 2885e38

Please sign in to comment.