diff --git a/src/Umbraco.Core/Constants-Telemetry.cs b/src/Umbraco.Core/Constants-Telemetry.cs
index f8a382b0bb..0e7c96d250 100644
--- a/src/Umbraco.Core/Constants-Telemetry.cs
+++ b/src/Umbraco.Core/Constants-Telemetry.cs
@@ -29,5 +29,6 @@ public static partial class Constants
public static string DatabaseProvider = "DatabaseProvider";
public static string CurrentServerRole = "CurrentServerRole";
public static string RuntimeMode = "RuntimeMode";
+ public static string BackofficeExternalLoginProviderCount = "BackofficeExternalLoginProviderCount";
}
}
diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml b/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml
index d85e6d7eb4..035d0e42f1 100644
--- a/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml
+++ b/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml
@@ -3010,7 +3010,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
We will send:
- Anonymized site ID, Umbraco version, and packages installed.
- - Number of: Root nodes, Content nodes, Macros, Media, Document Types, Templates, Languages, Domains, User Group, Users, Members, and Property Editors in use.
+ - Number of: Root nodes, Content nodes, Macros, Media, Document Types, Templates, Languages, Domains, User Group, Users, Members, Backoffice external login providers, and Property Editors in use.
- System information: Webserver, server OS, server framework, server OS language, and database provider.
- Configuration settings: Modelsbuilder mode, if custom Umbraco path exists, ASP environment, and if you are in debug mode.
diff --git a/src/Umbraco.Infrastructure/Telemetry/Interfaces/IDetailedTelemetryProvider.cs b/src/Umbraco.Infrastructure/Telemetry/Interfaces/IDetailedTelemetryProvider.cs
index b21b216e68..e6ce3b005f 100644
--- a/src/Umbraco.Infrastructure/Telemetry/Interfaces/IDetailedTelemetryProvider.cs
+++ b/src/Umbraco.Infrastructure/Telemetry/Interfaces/IDetailedTelemetryProvider.cs
@@ -2,7 +2,7 @@ using Umbraco.Cms.Core.Models;
namespace Umbraco.Cms.Infrastructure.Telemetry.Interfaces;
-internal interface IDetailedTelemetryProvider
+public interface IDetailedTelemetryProvider
{
IEnumerable GetInformation();
}
diff --git a/src/Umbraco.Web.BackOffice/Controllers/TinyMceController.cs b/src/Umbraco.Web.BackOffice/Controllers/TinyMceController.cs
index 3d93f9af6c..a9f81344a0 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/TinyMceController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/TinyMceController.cs
@@ -26,6 +26,19 @@ public class TinyMceController : UmbracoAuthorizedApiController
private readonly IIOHelper _ioHelper;
private readonly IShortStringHelper _shortStringHelper;
+ private readonly Dictionary _fileContentTypeMappings =
+ new()
+ {
+ { "image/png", "png" },
+ { "image/jpeg", "jpg" },
+ { "image/gif", "gif" },
+ { "image/bmp", "bmp" },
+ { "image/x-icon", "ico" },
+ { "image/svg+xml", "svg" },
+ { "image/tiff", "tiff" },
+ { "image/webp", "webp" },
+ };
+
public TinyMceController(
IHostingEnvironment hostingEnvironment,
IShortStringHelper shortStringHelper,
@@ -43,16 +56,6 @@ public class TinyMceController : UmbracoAuthorizedApiController
[HttpPost]
public async Task UploadImage(List file)
{
- // Create an unique folder path to help with concurrent users to avoid filename clash
- var imageTempPath =
- _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempImageUploads + "/" + Guid.NewGuid());
-
- // Ensure image temp path exists
- if (Directory.Exists(imageTempPath) == false)
- {
- Directory.CreateDirectory(imageTempPath);
- }
-
// Must have a file
if (file.Count == 0)
{
@@ -65,13 +68,36 @@ public class TinyMceController : UmbracoAuthorizedApiController
return new UmbracoProblemResult("Only one file can be uploaded at a time", HttpStatusCode.BadRequest);
}
+ // Create an unique folder path to help with concurrent users to avoid filename clash
+ var imageTempPath =
+ _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempImageUploads + "/" + Guid.NewGuid());
+
+ // Ensure image temp path exists
+ if (Directory.Exists(imageTempPath) == false)
+ {
+ Directory.CreateDirectory(imageTempPath);
+ }
+
IFormFile formFile = file.First();
// Really we should only have one file per request to this endpoint
// var file = result.FileData[0];
- var fileName = formFile.FileName.Trim(new[] { '\"' }).TrimEnd();
+ var fileName = formFile.FileName.Trim(new[] {'\"'}).TrimEnd();
var safeFileName = fileName.ToSafeFileName(_shortStringHelper);
- var ext = safeFileName.Substring(safeFileName.LastIndexOf('.') + 1).ToLowerInvariant();
+ string ext;
+ var fileExtensionIndex = safeFileName.LastIndexOf('.');
+ if (fileExtensionIndex is not -1)
+ {
+ ext = safeFileName.Substring(fileExtensionIndex + 1).ToLowerInvariant();
+ }
+ else
+ {
+ _fileContentTypeMappings.TryGetValue(formFile.ContentType, out var fileExtension);
+ ext = fileExtension ?? string.Empty;
+
+ // safeFileName will not have a file extension, so we need to add it back
+ safeFileName += $".{ext}";
+ }
if (_contentSettings.IsFileAllowedForUpload(ext) == false ||
_imageUrlGenerator.IsSupportedImageFormat(ext) == false)
diff --git a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.BackOfficeIdentity.cs b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.BackOfficeIdentity.cs
index 6d3ff7edda..1844cf5885 100644
--- a/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.BackOfficeIdentity.cs
+++ b/src/Umbraco.Web.BackOffice/DependencyInjection/UmbracoBuilder.BackOfficeIdentity.cs
@@ -11,7 +11,9 @@ using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Security;
+using Umbraco.Cms.Infrastructure.Telemetry.Interfaces;
using Umbraco.Cms.Web.BackOffice.Security;
+using Umbraco.Cms.Web.BackOffice.Telemetry;
using Umbraco.Cms.Web.Common.AspNetCore;
using Umbraco.Cms.Web.Common.Security;
@@ -65,6 +67,7 @@ public static partial class UmbracoBuilderExtensions
services.TryAddScoped();
services.TryAddSingleton();
services.TryAddSingleton();
+ services.AddTransient();
return new BackOfficeIdentityBuilder(services);
}
diff --git a/src/Umbraco.Web.BackOffice/Telemetry/ExternalLoginTelemetryProvider.cs b/src/Umbraco.Web.BackOffice/Telemetry/ExternalLoginTelemetryProvider.cs
new file mode 100644
index 0000000000..21a59796b3
--- /dev/null
+++ b/src/Umbraco.Web.BackOffice/Telemetry/ExternalLoginTelemetryProvider.cs
@@ -0,0 +1,22 @@
+using Umbraco.Cms.Core;
+using Umbraco.Cms.Core.Models;
+using Umbraco.Cms.Infrastructure.Telemetry.Interfaces;
+using Umbraco.Cms.Web.BackOffice.Security;
+
+namespace Umbraco.Cms.Web.BackOffice.Telemetry;
+
+public class ExternalLoginTelemetryProvider : IDetailedTelemetryProvider
+{
+ private readonly IBackOfficeExternalLoginProviders _externalLoginProviders;
+
+ public ExternalLoginTelemetryProvider(IBackOfficeExternalLoginProviders externalLoginProviders)
+ {
+ _externalLoginProviders = externalLoginProviders;
+ }
+
+ public IEnumerable GetInformation()
+ {
+ IEnumerable providers = _externalLoginProviders.GetBackOfficeProvidersAsync().GetAwaiter().GetResult();
+ yield return new UsageInformation(Constants.Telemetry.BackofficeExternalLoginProviderCount, providers.Count());
+ }
+}
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Telemetry/TelemetryServiceTests.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Telemetry/TelemetryServiceTests.cs
index bc4b68b508..a310caa164 100644
--- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Telemetry/TelemetryServiceTests.cs
+++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Telemetry/TelemetryServiceTests.cs
@@ -50,7 +50,8 @@ public class TelemetryServiceTests : UmbracoIntegrationTest
Constants.Telemetry.IsDebug,
Constants.Telemetry.DatabaseProvider,
Constants.Telemetry.CurrentServerRole,
- Constants.Telemetry.RuntimeMode,
+ Constants.Telemetry.BackofficeExternalLoginProviderCount,
+ Constants.Telemetry.RuntimeMode
};
MetricsConsentService.SetConsentLevel(TelemetryLevel.Detailed);
diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/IndexInitializer.cs b/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/IndexInitializer.cs
index b287f6fbf3..01ca9284f7 100644
--- a/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/IndexInitializer.cs
+++ b/tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/IndexInitializer.cs
@@ -19,6 +19,7 @@ using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Infrastructure.Examine;
using Umbraco.Cms.Infrastructure.Persistence;
+using Umbraco.Cms.Web.Common.DependencyInjection;
using Directory = Lucene.Net.Store.Directory;
using StaticServiceProvider = Umbraco.Cms.Core.DependencyInjection.StaticServiceProvider;