Skip to content

Commit 0c7ef06

Browse files
nikolajlauridsennikolajlauridsenbergmania
authored
V9: Fix missing site identifier (#12040)
* Add SiteIdentifierService * Use SiteIdentifierService in TelemetryService * Use SiteIdentifierService when installing * Remove timeout * Use TryGetOrCreateSiteIdentifier in TelemetryService * Add site identifier to dashboard url * Fix and add tests * Don't accept empty guid as valid site identifier * Fix dashboard controller * Fix site id query parameter * Use Optionsmonitor onchange Co-authored-by: nikolajlauridsen <[email protected]> Co-authored-by: Bjarke Berg <[email protected]>
1 parent 4a6c409 commit 0c7ef06

File tree

10 files changed

+287
-80
lines changed

10 files changed

+287
-80
lines changed

src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ private void AddCoreServices()
262262
Services.AddSingleton<IValueEditorCache, ValueEditorCache>();
263263

264264
// Register telemetry service used to gather data about installed packages
265+
Services.AddUnique<ISiteIdentifierService, SiteIdentifierService>();
265266
Services.AddUnique<ITelemetryService, TelemetryService>();
266267

267268
// Register a noop IHtmlSanitizer to be replaced

src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
using System;
22
using System.Threading.Tasks;
3+
using Microsoft.Extensions.DependencyInjection;
34
using Microsoft.Extensions.Logging;
45
using Microsoft.Extensions.Options;
56
using Umbraco.Cms.Core.Configuration;
67
using Umbraco.Cms.Core.Configuration.Models;
78
using Umbraco.Cms.Core.Install.Models;
9+
using Umbraco.Cms.Core.Telemetry;
10+
using Umbraco.Cms.Web.Common.DependencyInjection;
811

912
namespace Umbraco.Cms.Core.Install.InstallSteps
1013
{
@@ -13,31 +16,29 @@ namespace Umbraco.Cms.Core.Install.InstallSteps
1316
PerformsAppRestart = false)]
1417
public class TelemetryIdentifierStep : InstallSetupStep<object>
1518
{
16-
private readonly ILogger<TelemetryIdentifierStep> _logger;
1719
private readonly IOptions<GlobalSettings> _globalSettings;
18-
private readonly IConfigManipulator _configManipulator;
20+
private readonly ISiteIdentifierService _siteIdentifierService;
1921

20-
public TelemetryIdentifierStep(ILogger<TelemetryIdentifierStep> logger, IOptions<GlobalSettings> globalSettings, IConfigManipulator configManipulator)
22+
public TelemetryIdentifierStep(
23+
IOptions<GlobalSettings> globalSettings,
24+
ISiteIdentifierService siteIdentifierService)
2125
{
22-
_logger = logger;
2326
_globalSettings = globalSettings;
24-
_configManipulator = configManipulator;
27+
_siteIdentifierService = siteIdentifierService;
2528
}
2629

27-
public override Task<InstallSetupResult> ExecuteAsync(object model)
30+
[Obsolete("Use constructor that takes GlobalSettings and ISiteIdentifierService")]
31+
public TelemetryIdentifierStep(
32+
ILogger<TelemetryIdentifierStep> logger,
33+
IOptions<GlobalSettings> globalSettings,
34+
IConfigManipulator configManipulator)
35+
: this(globalSettings, StaticServiceProvider.Instance.GetRequiredService<ISiteIdentifierService>())
2836
{
29-
// Generate GUID
30-
var telemetrySiteIdentifier = Guid.NewGuid();
31-
32-
try
33-
{
34-
_configManipulator.SetGlobalId(telemetrySiteIdentifier.ToString());
35-
}
36-
catch (Exception ex)
37-
{
38-
_logger.LogError(ex, "Couldn't update config files with a telemetry site identifier");
39-
}
37+
}
4038

39+
public override Task<InstallSetupResult> ExecuteAsync(object model)
40+
{
41+
_siteIdentifierService.TryCreateSiteIdentifier(out _);
4142
return Task.FromResult<InstallSetupResult>(null);
4243
}
4344

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
3+
namespace Umbraco.Cms.Core.Telemetry
4+
{
5+
/// <summary>
6+
/// Used to get and create the site identifier
7+
/// </summary>
8+
public interface ISiteIdentifierService
9+
{
10+
11+
/// <summary>
12+
/// Tries to get the site identifier
13+
/// </summary>
14+
/// <returns>True if success.</returns>
15+
bool TryGetSiteIdentifier(out Guid siteIdentifier);
16+
17+
/// <summary>
18+
/// Creates the site identifier and writes it to config.
19+
/// </summary>
20+
/// <param name="createdGuid">asd.</param>
21+
/// <returns>True if success.</returns>
22+
bool TryCreateSiteIdentifier(out Guid createdGuid);
23+
24+
/// <summary>
25+
/// Tries to get the site identifier or otherwise create it if it doesn't exist.
26+
/// </summary>
27+
/// <param name="siteIdentifier">The out parameter for the existing or create site identifier.</param>
28+
/// <returns>True if success.</returns>
29+
bool TryGetOrCreateSiteIdentifier(out Guid siteIdentifier);
30+
}
31+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System;
2+
using Microsoft.Extensions.Logging;
3+
using Microsoft.Extensions.Options;
4+
using Umbraco.Cms.Core.Configuration;
5+
using Umbraco.Cms.Core.Configuration.Models;
6+
7+
namespace Umbraco.Cms.Core.Telemetry
8+
{
9+
/// <inheritdoc />
10+
internal class SiteIdentifierService : ISiteIdentifierService
11+
{
12+
private GlobalSettings _globalSettings;
13+
private readonly IConfigManipulator _configManipulator;
14+
private readonly ILogger<SiteIdentifierService> _logger;
15+
16+
public SiteIdentifierService(
17+
IOptionsMonitor<GlobalSettings> optionsMonitor,
18+
IConfigManipulator configManipulator,
19+
ILogger<SiteIdentifierService> logger)
20+
{
21+
_globalSettings = optionsMonitor.CurrentValue;
22+
optionsMonitor.OnChange(globalSettings => _globalSettings = globalSettings);
23+
_configManipulator = configManipulator;
24+
_logger = logger;
25+
}
26+
27+
/// <inheritdoc/>
28+
public bool TryGetSiteIdentifier(out Guid siteIdentifier)
29+
{
30+
// Parse telemetry string as a GUID & verify its a GUID and not some random string
31+
// since users may have messed with or decided to empty the app setting or put in something random
32+
if (Guid.TryParse(_globalSettings.Id, out var parsedTelemetryId) is false
33+
|| parsedTelemetryId == Guid.Empty)
34+
{
35+
siteIdentifier = Guid.Empty;
36+
return false;
37+
}
38+
39+
siteIdentifier = parsedTelemetryId;
40+
return true;
41+
}
42+
43+
/// <inheritdoc/>
44+
public bool TryGetOrCreateSiteIdentifier(out Guid siteIdentifier)
45+
{
46+
if (TryGetSiteIdentifier(out Guid existingId))
47+
{
48+
siteIdentifier = existingId;
49+
return true;
50+
}
51+
52+
if (TryCreateSiteIdentifier(out Guid createdId))
53+
{
54+
siteIdentifier = createdId;
55+
return true;
56+
}
57+
58+
siteIdentifier = Guid.Empty;
59+
return false;
60+
}
61+
62+
/// <inheritdoc/>
63+
public bool TryCreateSiteIdentifier(out Guid createdGuid)
64+
{
65+
createdGuid = Guid.NewGuid();
66+
67+
try
68+
{
69+
_configManipulator.SetGlobalId(createdGuid.ToString());
70+
}
71+
catch (Exception ex)
72+
{
73+
_logger.LogError(ex, "Couldn't update config files with a telemetry site identifier");
74+
createdGuid = Guid.Empty;
75+
return false;
76+
}
77+
78+
return true;
79+
}
80+
}
81+
}

src/Umbraco.Core/Telemetry/TelemetryService.cs

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3-
using Microsoft.Extensions.Options;
43
using Umbraco.Cms.Core.Configuration;
5-
using Umbraco.Cms.Core.Configuration.Models;
64
using Umbraco.Cms.Core.Manifest;
75
using Umbraco.Cms.Core.Telemetry.Models;
86
using Umbraco.Extensions;
@@ -12,27 +10,27 @@ namespace Umbraco.Cms.Core.Telemetry
1210
/// <inheritdoc/>
1311
internal class TelemetryService : ITelemetryService
1412
{
15-
private readonly IOptionsMonitor<GlobalSettings> _globalSettings;
1613
private readonly IManifestParser _manifestParser;
1714
private readonly IUmbracoVersion _umbracoVersion;
15+
private readonly ISiteIdentifierService _siteIdentifierService;
1816

1917
/// <summary>
2018
/// Initializes a new instance of the <see cref="TelemetryService"/> class.
2119
/// </summary>
2220
public TelemetryService(
23-
IOptionsMonitor<GlobalSettings> globalSettings,
2421
IManifestParser manifestParser,
25-
IUmbracoVersion umbracoVersion)
22+
IUmbracoVersion umbracoVersion,
23+
ISiteIdentifierService siteIdentifierService)
2624
{
2725
_manifestParser = manifestParser;
2826
_umbracoVersion = umbracoVersion;
29-
_globalSettings = globalSettings;
27+
_siteIdentifierService = siteIdentifierService;
3028
}
3129

3230
/// <inheritdoc/>
3331
public bool TryGetTelemetryReportData(out TelemetryReportData telemetryReportData)
3432
{
35-
if (TryGetTelemetryId(out Guid telemetryId) is false)
33+
if (_siteIdentifierService.TryGetOrCreateSiteIdentifier(out Guid telemetryId) is false)
3634
{
3735
telemetryReportData = null;
3836
return false;
@@ -42,28 +40,14 @@ public bool TryGetTelemetryReportData(out TelemetryReportData telemetryReportDat
4240
{
4341
Id = telemetryId,
4442
Version = _umbracoVersion.SemanticVersion.ToSemanticStringWithoutBuild(),
45-
Packages = GetPackageTelemetry()
43+
Packages = GetPackageTelemetry(),
4644
};
4745
return true;
4846
}
4947

50-
private bool TryGetTelemetryId(out Guid telemetryId)
51-
{
52-
// Parse telemetry string as a GUID & verify its a GUID and not some random string
53-
// since users may have messed with or decided to empty the app setting or put in something random
54-
if (Guid.TryParse(_globalSettings.CurrentValue.Id, out var parsedTelemetryId) is false)
55-
{
56-
telemetryId = Guid.Empty;
57-
return false;
58-
}
59-
60-
telemetryId = parsedTelemetryId;
61-
return true;
62-
}
63-
6448
private IEnumerable<PackageTelemetry> GetPackageTelemetry()
6549
{
66-
List<PackageTelemetry> packages = new ();
50+
List<PackageTelemetry> packages = new();
6751
IEnumerable<PackageManifest> manifests = _manifestParser.GetManifests();
6852

6953
foreach (PackageManifest manifest in manifests)
@@ -76,7 +60,7 @@ private IEnumerable<PackageTelemetry> GetPackageTelemetry()
7660
packages.Add(new PackageTelemetry
7761
{
7862
Name = manifest.PackageName,
79-
Version = manifest.Version ?? string.Empty
63+
Version = manifest.Version ?? string.Empty,
8064
});
8165
}
8266

src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Installer.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
using Microsoft.Extensions.DependencyInjection;
2+
using Microsoft.Extensions.Options;
3+
using Umbraco.Cms.Core.Configuration.Models;
24
using Umbraco.Cms.Core.DependencyInjection;
35
using Umbraco.Cms.Core.Install.InstallSteps;
46
using Umbraco.Cms.Core.Install.Models;
7+
using Umbraco.Cms.Core.Telemetry;
58
using Umbraco.Cms.Infrastructure.Install;
69
using Umbraco.Cms.Infrastructure.Install.InstallSteps;
710
using Umbraco.Extensions;
@@ -19,7 +22,12 @@ internal static IUmbracoBuilder AddInstaller(this IUmbracoBuilder builder)
1922
builder.Services.AddScoped<InstallSetupStep, NewInstallStep>();
2023
builder.Services.AddScoped<InstallSetupStep, UpgradeStep>();
2124
builder.Services.AddScoped<InstallSetupStep, FilePermissionsStep>();
22-
builder.Services.AddScoped<InstallSetupStep, TelemetryIdentifierStep>();
25+
builder.Services.AddScoped<InstallSetupStep, TelemetryIdentifierStep>(provider =>
26+
{
27+
return new TelemetryIdentifierStep(
28+
provider.GetRequiredService<IOptions<GlobalSettings>>(),
29+
provider.GetRequiredService<ISiteIdentifierService>());
30+
});
2331
builder.Services.AddScoped<InstallSetupStep, DatabaseConfigureStep>();
2432
builder.Services.AddScoped<InstallSetupStep, DatabaseInstallStep>();
2533
builder.Services.AddScoped<InstallSetupStep, DatabaseUpgradeStep>();

src/Umbraco.Infrastructure/HostedServices/ReportSiteTask.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,6 @@ public override async Task PerformExecuteAsync(object state)
5959
// Send data to LIVE telemetry
6060
s_httpClient.BaseAddress = new Uri("https://telemetry.umbraco.com/");
6161

62-
// Set a low timeout - no need to use a larger default timeout for this POST request
63-
s_httpClient.Timeout = new TimeSpan(0, 0, 1);
64-
6562
#if DEBUG
6663
// Send data to DEBUG telemetry service
6764
s_httpClient.BaseAddress = new Uri("https://telemetry.rainbowsrock.net/");

0 commit comments

Comments
 (0)