Unattended install: Added the ability to set the telemetry level (#20249)

* Added the ability to set the telemetry level for an unattended install

Added 'UnattendedTelemetryLevel' to 'UnattendedSettings'

Renamed 'CreateUnattendedUserNotificationHandler' to 'PostUnattendedInstallNotificationHandler'

Set the telemetry level in the unattended install notification handler

* Add DefaultValue attribute to 'UnattendedTelemetryLevel'

* Added UnattendedTelemetryLevel to template.

* Updated cli and ide hosts.

---------

Co-authored-by: Andy Butland <abutland73@gmail.com>
This commit is contained in:
Mitchel
2025-09-29 15:07:30 +00:00
committed by GitHub
parent 81f29be53b
commit ac6b205e7f
7 changed files with 59 additions and 9 deletions

View File

@@ -25,7 +25,7 @@ public static class InstallerBuilderExtensions
builder.AddInstallSteps();
services.AddTransient<IInstallService, InstallService>();
builder.AddNotificationAsyncHandler<UnattendedInstallNotification, CreateUnattendedUserNotificationHandler>();
builder.AddNotificationAsyncHandler<UnattendedInstallNotification, PostUnattendedInstallNotificationHandler>();
builder.WithCollectionBuilder<MapDefinitionCollectionBuilder>().Add<InstallerViewModelsMapDefinition>();
return builder;

View File

@@ -12,27 +12,31 @@ using Umbraco.Extensions;
namespace Umbraco.Cms.Api.Management.Install;
public class CreateUnattendedUserNotificationHandler : INotificationAsyncHandler<UnattendedInstallNotification>
public class PostUnattendedInstallNotificationHandler : INotificationAsyncHandler<UnattendedInstallNotification>
{
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly IOptions<UnattendedSettings> _unattendedSettings;
private readonly IUserService _userService;
private readonly IMetricsConsentService _metricsConsentService;
public CreateUnattendedUserNotificationHandler(IOptions<UnattendedSettings> unattendedSettings, IUserService userService, IServiceScopeFactory serviceScopeFactory)
public PostUnattendedInstallNotificationHandler(IOptions<UnattendedSettings> unattendedSettings, IUserService userService, IServiceScopeFactory serviceScopeFactory, IMetricsConsentService metricsConsentService)
{
_unattendedSettings = unattendedSettings;
_userService = userService;
_serviceScopeFactory = serviceScopeFactory;
_metricsConsentService = metricsConsentService;
}
/// <summary>
/// Listening for when the UnattendedInstallNotification fired after a sucessfulk
/// Listening for when the UnattendedInstallNotification fired after a successful unattended install
/// This creates the user and sets the telemetry level based on the 'Unattended' settings.
/// </summary>
/// <param name="notification"></param>
/// <param name="cancellationToken"></param>
public async Task HandleAsync(UnattendedInstallNotification notification, CancellationToken cancellationToken)
{
UnattendedSettings? unattendedSettings = _unattendedSettings.Value;
// Ensure we have the setting enabled (Sanity check)
// In theory this should always be true as the event only fired when a sucessfull
if (_unattendedSettings.Value.InstallUnattended == false)
@@ -83,7 +87,7 @@ public class CreateUnattendedUserNotificationHandler : INotificationAsyncHandler
$"No user found in membership provider with id of {Constants.Security.SuperUserIdAsString}.");
}
//To change the password here we actually need to reset it since we don't have an old one to use to change
// To change the password here we actually need to reset it since we don't have an old one to use to change
var resetToken = await backOfficeUserManager.GeneratePasswordResetTokenAsync(membershipUser);
if (string.IsNullOrWhiteSpace(resetToken))
{
@@ -98,5 +102,7 @@ public class CreateUnattendedUserNotificationHandler : INotificationAsyncHandler
throw new InvalidOperationException("Could not reset password: " +
string.Join(", ", resetResult.Errors.ToErrorMessage()));
}
await _metricsConsentService.SetConsentLevelAsync(unattendedSettings.UnattendedTelemetryLevel);
}
}

View File

@@ -3,6 +3,7 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Umbraco.Cms.Core.Models;
namespace Umbraco.Cms.Core.Configuration.Models;
@@ -14,6 +15,7 @@ public class UnattendedSettings
{
private const bool StaticInstallUnattended = false;
private const bool StaticUpgradeUnattended = false;
private const TelemetryLevel StaticTelemetryLevel = TelemetryLevel.Detailed;
/// <summary>
/// Gets or sets a value indicating whether unattended installs are enabled.
@@ -58,4 +60,10 @@ public class UnattendedSettings
/// Gets or sets a value to use for creating a user with a password for Unattended Installs
/// </summary>
public string? UnattendedUserPassword { get; set; } = null;
/// <summary>
/// Gets or sets a telemetry level to use for Unattended Installs
/// </summary>
[DefaultValue(StaticTelemetryLevel)]
public TelemetryLevel UnattendedTelemetryLevel { get; set; } = StaticTelemetryLevel;
}

View File

@@ -63,6 +63,10 @@
"longName": "password",
"shortName": ""
},
"UnattendedTelemetryLevel": {
"longName": "telemetry-level",
"shortName": ""
},
"NoNodesViewPath": {
"longName": "no-nodes-view-path",
"shortName": ""

View File

@@ -62,6 +62,11 @@
"id": "UnattendedUserPassword",
"isVisible": true
},
{
"id": "UnattendedTelemetryLevel",
"isVisible": true,
"defaultValue": "Detailed"
},
{
"id": "NoNodesViewPath",
"isVisible": true

View File

@@ -82,7 +82,7 @@
"replaces": "CUSTOM_VERSION",
"isRequired": false
},
"FinalVersion" : {
"FinalVersion": {
"type": "generated",
"generator": "switch",
"datatype": "text",
@@ -103,8 +103,7 @@
]
}
},
"DotnetVersion":
{
"DotnetVersion": {
"type": "generated",
"generator": "switch",
"datatype": "text",
@@ -300,6 +299,33 @@
},
"replaces": "UNATTENDED_USER_PASSWORD_FROM_TEMPLATE"
},
"UnattendedTelemetryLevel": {
"displayName": "Unattended telemetry level",
"description": "Specifies the level of telemetry information the installation will report.",
"type": "parameter",
"datatype": "choice",
"defaultValue": "Detailed",
"choices": [
{
"choice": "Minimal",
"description": "Minimal information"
},
{
"choice": "Basic",
"description": "Basic information"
},
{
"choice": "Detailed",
"description": "Detailed information"
}
],
"forms": {
"global": [
"jsonEncode"
]
},
"replaces": "UNATTENDED_TELEMETRY_LEVEL_FROM_TEMPLATE"
},
"UsingUnattenedInstall": {
"type": "computed",
"value": "(UnattendedUserName != '' && UnattendedUserEmail != '' && UnattendedUserPassword != '' && (HasConnectionString || HasDevelopmentConnectionString))"

View File

@@ -35,7 +35,8 @@
"InstallUnattended": true,
"UnattendedUserName": "UNATTENDED_USER_NAME_FROM_TEMPLATE",
"UnattendedUserEmail": "UNATTENDED_USER_EMAIL_FROM_TEMPLATE",
"UnattendedUserPassword": "UNATTENDED_USER_PASSWORD_FROM_TEMPLATE"
"UnattendedUserPassword": "UNATTENDED_USER_PASSWORD_FROM_TEMPLATE",
"UnattendedTelemetryLevel": "UNATTENDED_TELEMETRY_LEVEL_FROM_TEMPLATE"
},
//#endif
"Content": {