Ensure legacy scope returned when using legacy scope provider (#12465)
* Separate legacy scope provider interface and explicitly implement. * Don't rely on legacy scope provider for existing tests. * Assert correct type returned when using legacy scope provider.
This commit is contained in:
@@ -104,7 +104,7 @@ namespace Umbraco.Cms.Infrastructure.Packaging
|
||||
contentTypeService,
|
||||
contentService,
|
||||
propertyEditors,
|
||||
scopeProvider,
|
||||
(Umbraco.Cms.Infrastructure.Scoping.IScopeProvider) scopeProvider,
|
||||
shortStringHelper,
|
||||
serializer,
|
||||
mediaService,
|
||||
|
||||
@@ -1,9 +1,90 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Umbraco.Cms.Core.Scoping;
|
||||
|
||||
[Obsolete("Please use Umbraco.Cms.Infrastructure.Scoping.IScopeProvider or Umbraco.Cms.Core.Scoping.ICoreScopeProvider instead.")]
|
||||
public interface IScopeProvider : Infrastructure.Scoping.IScopeProvider
|
||||
public interface IScopeProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an ambient scope.
|
||||
/// </summary>
|
||||
/// <param name="isolationLevel">The transaction isolation level.</param>
|
||||
/// <param name="repositoryCacheMode">The repositories cache mode.</param>
|
||||
/// <param name="eventDispatcher">An optional events dispatcher.</param>
|
||||
/// <param name="scopedNotificationPublisher">An optional notification publisher.</param>
|
||||
/// <param name="scopeFileSystems">A value indicating whether to scope the filesystems.</param>
|
||||
/// <param name="callContext">A value indicating whether this scope should always be registered in the call context.</param>
|
||||
/// <param name="autoComplete">A value indicating whether this scope is auto-completed.</param>
|
||||
/// <returns>The created ambient scope.</returns>
|
||||
/// <remarks>
|
||||
/// <para>The created scope becomes the ambient scope.</para>
|
||||
/// <para>If an ambient scope already exists, it becomes the parent of the created scope.</para>
|
||||
/// <para>When the created scope is disposed, the parent scope becomes the ambient scope again.</para>
|
||||
/// <para>Parameters must be specified on the outermost scope, or must be compatible with the parents.</para>
|
||||
/// <para>Auto-completed scopes should be used for read-only operations ONLY. Do not use them if you do not
|
||||
/// understand the associated issues, such as the scope being completed even though an exception is thrown.</para>
|
||||
/// </remarks>
|
||||
IScope CreateScope(
|
||||
IsolationLevel isolationLevel = IsolationLevel.Unspecified,
|
||||
RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified,
|
||||
IEventDispatcher? eventDispatcher = null,
|
||||
IScopedNotificationPublisher? scopedNotificationPublisher = null,
|
||||
bool? scopeFileSystems = null,
|
||||
bool callContext = false,
|
||||
bool autoComplete = false);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a detached scope.
|
||||
/// </summary>
|
||||
/// <returns>A detached scope.</returns>
|
||||
/// <param name="isolationLevel">The transaction isolation level.</param>
|
||||
/// <param name="repositoryCacheMode">The repositories cache mode.</param>
|
||||
/// <param name="eventDispatcher">An optional events dispatcher.</param>
|
||||
/// <param name="scopedNotificationPublisher">An option notification publisher.</param>
|
||||
/// <param name="scopeFileSystems">A value indicating whether to scope the filesystems.</param>
|
||||
/// <remarks>
|
||||
/// <para>A detached scope is not ambient and has no parent.</para>
|
||||
/// <para>It is meant to be attached by <see cref="AttachScope"/>.</para>
|
||||
/// </remarks>
|
||||
/// <remarks>
|
||||
/// This is not used by CMS but is used by Umbraco Deploy.
|
||||
/// </remarks>
|
||||
IScope CreateDetachedScope(
|
||||
IsolationLevel isolationLevel = IsolationLevel.Unspecified,
|
||||
RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified,
|
||||
IEventDispatcher? eventDispatcher = null,
|
||||
IScopedNotificationPublisher? scopedNotificationPublisher = null,
|
||||
bool? scopeFileSystems = null);
|
||||
|
||||
/// <summary>
|
||||
/// Attaches a scope.
|
||||
/// </summary>
|
||||
/// <param name="scope">The scope to attach.</param>
|
||||
/// <param name="callContext">A value indicating whether to force usage of call context.</param>
|
||||
/// <remarks>
|
||||
/// <para>Only a scope created by <see cref="CreateDetachedScope"/> can be attached.</para>
|
||||
/// </remarks>
|
||||
void AttachScope(IScope scope, bool callContext = false);
|
||||
|
||||
/// <summary>
|
||||
/// Detaches a scope.
|
||||
/// </summary>
|
||||
/// <returns>The detached scope.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Only a scope previously attached by <see cref="AttachScope"/> can be detached.</para>
|
||||
/// </remarks>
|
||||
IScope DetachScope();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the scope context.
|
||||
/// </summary>
|
||||
IScopeContext? Context { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sql context.
|
||||
/// </summary>
|
||||
ISqlContext SqlContext { get; }
|
||||
}
|
||||
|
||||
@@ -658,6 +658,42 @@ namespace Umbraco.Cms.Infrastructure.Scoping
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/// <inheritdoc />
|
||||
Cms.Core.Scoping.IScope Cms.Core.Scoping.IScopeProvider.CreateScope(
|
||||
IsolationLevel isolationLevel = IsolationLevel.Unspecified,
|
||||
RepositoryCacheMode repositoryCacheMode = RepositoryCacheMode.Unspecified,
|
||||
IEventDispatcher? eventDispatcher = null,
|
||||
IScopedNotificationPublisher? notificationPublisher = null,
|
||||
bool? scopeFileSystems = null,
|
||||
bool callContext = false,
|
||||
bool autoComplete = false) =>
|
||||
(Cms.Core.Scoping.IScope) CreateScope(
|
||||
isolationLevel,
|
||||
repositoryCacheMode,
|
||||
eventDispatcher,
|
||||
notificationPublisher,
|
||||
scopeFileSystems,
|
||||
callContext,
|
||||
autoComplete);
|
||||
|
||||
/// <inheritdoc />
|
||||
Core.Scoping.IScope Core.Scoping.IScopeProvider.CreateDetachedScope(IsolationLevel isolationLevel,
|
||||
RepositoryCacheMode repositoryCacheMode, IEventDispatcher? eventDispatcher,
|
||||
IScopedNotificationPublisher? scopedNotificationPublisher, bool? scopeFileSystems) =>
|
||||
(Core.Scoping.IScope)CreateDetachedScope(
|
||||
isolationLevel,
|
||||
repositoryCacheMode,
|
||||
eventDispatcher,
|
||||
scopedNotificationPublisher,
|
||||
scopeFileSystems);
|
||||
|
||||
/// <inheritdoc />
|
||||
void Core.Scoping.IScopeProvider.AttachScope(Core.Scoping.IScope scope, bool callContext) =>
|
||||
AttachScope(scope, callContext);
|
||||
|
||||
/// <inheritdoc />
|
||||
Core.Scoping.IScope Core.Scoping.IScopeProvider.DetachScope() =>
|
||||
(Core.Scoping.IScope)DetachScope();
|
||||
}
|
||||
|
||||
#if DEBUG_SCOPES
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Tests.Common.Testing;
|
||||
using Umbraco.Cms.Tests.Integration.Testing;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Scoping;
|
||||
|
||||
[TestFixture]
|
||||
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerFixture)]
|
||||
public class LegacyScopeProviderTests : UmbracoIntegrationTest
|
||||
{
|
||||
[Test]
|
||||
public void CreateScope_Always_ReturnsLegacyIScope()
|
||||
{
|
||||
var scopeProvider = GetRequiredService<global::Umbraco.Cms.Core.Scoping.IScopeProvider>();
|
||||
|
||||
using (var scope = scopeProvider.CreateScope())
|
||||
{
|
||||
Assert.IsInstanceOf<global::Umbraco.Cms.Core.Scoping.IScope>(scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,7 +225,7 @@ namespace Umbraco.Cms.Tests.UnitTests.TestHelpers
|
||||
DomainService = serviceContext.DomainService;
|
||||
|
||||
// create a scope provider
|
||||
IScopeProvider scopeProvider = Mock.Of<IScopeProvider>();
|
||||
Infrastructure.Scoping.IScopeProvider scopeProvider = Mock.Of<Infrastructure.Scoping.IScopeProvider>();
|
||||
Mock.Get(scopeProvider)
|
||||
.Setup(x => x.CreateScope(
|
||||
It.IsAny<IsolationLevel>(),
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.HostedServices
|
||||
var mockMainDom = new Mock<IMainDom>();
|
||||
mockMainDom.SetupGet(x => x.IsMainDom).Returns(isMainDom);
|
||||
|
||||
var mockScopeProvider = new Mock<IScopeProvider>();
|
||||
var mockScopeProvider = new Mock<global::Umbraco.Cms.Infrastructure.Scoping.IScopeProvider>();
|
||||
var mockLogger = new Mock<ILogger<HealthCheckNotifier>>();
|
||||
var mockProfilingLogger = new Mock<IProfilingLogger>();
|
||||
|
||||
|
||||
@@ -20,12 +20,12 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Mapping
|
||||
[TestFixture]
|
||||
public class MappingTests
|
||||
{
|
||||
private IScopeProvider _scopeProvider;
|
||||
private global::Umbraco.Cms.Infrastructure.Scoping.IScopeProvider _scopeProvider;
|
||||
|
||||
[SetUp]
|
||||
public void MockScopeProvider()
|
||||
{
|
||||
var scopeMock = new Mock<IScopeProvider>();
|
||||
var scopeMock = new Mock<global::Umbraco.Cms.Infrastructure.Scoping.IScopeProvider>();
|
||||
scopeMock.Setup(x => x.CreateScope(
|
||||
It.IsAny<IsolationLevel>(),
|
||||
It.IsAny<RepositoryCacheMode>(),
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security
|
||||
|
||||
public MemberManager CreateSut()
|
||||
{
|
||||
IScopeProvider scopeProvider = new Mock<IScopeProvider>().Object;
|
||||
global::Umbraco.Cms.Infrastructure.Scoping.IScopeProvider scopeProvider = new Mock<global::Umbraco.Cms.Infrastructure.Scoping.IScopeProvider>().Object;
|
||||
_mockMemberService = new Mock<IMemberService>();
|
||||
|
||||
var mapDefinitions = new List<IMapDefinition>()
|
||||
@@ -53,8 +53,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security
|
||||
new UmbracoMapper(new MapDefinitionCollection(() => mapDefinitions), scopeProvider),
|
||||
scopeProvider,
|
||||
new IdentityErrorDescriber(),
|
||||
Mock.Of<IPublishedSnapshotAccessor>(),
|
||||
Mock.Of<IExternalLoginWithKeyService>(),
|
||||
Mock.Of<IPublishedSnapshotAccessor>(),
|
||||
Mock.Of<IExternalLoginWithKeyService>(),
|
||||
Mock.Of<ITwoFactorLoginService>());
|
||||
|
||||
_mockIdentityOptions = new Mock<IOptions<IdentityOptions>>();
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security
|
||||
{
|
||||
_mockMemberService = new Mock<IMemberService>();
|
||||
var mockScope = new Mock<IScope>();
|
||||
var mockScopeProvider = new Mock<IScopeProvider>();
|
||||
var mockScopeProvider = new Mock<global::Umbraco.Cms.Infrastructure.Scoping.IScopeProvider>();
|
||||
mockScopeProvider
|
||||
.Setup(x => x.CreateScope(It.IsAny<IsolationLevel>(), It.IsAny<RepositoryCacheMode>(), It.IsAny<IEventDispatcher>(), It.IsAny<IScopedNotificationPublisher>(), It.IsAny<bool?>(), It.IsAny<bool>(), It.IsAny<bool>()))
|
||||
.Returns(mockScope.Object);
|
||||
|
||||
@@ -1171,9 +1171,9 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.PublishedCache.NuCache
|
||||
}
|
||||
}
|
||||
|
||||
private static IScopeProvider GetScopeProvider()
|
||||
private static ICoreScopeProvider GetScopeProvider()
|
||||
{
|
||||
IScopeProvider scopeProvider = Mock.Of<IScopeProvider>();
|
||||
ICoreScopeProvider scopeProvider = Mock.Of<ICoreScopeProvider>();
|
||||
Mock.Get(scopeProvider)
|
||||
.Setup(x => x.Context).Returns(() => null);
|
||||
return scopeProvider;
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.BackOffice.Controllers
|
||||
new ActionCollection(() => null),
|
||||
Mock.Of<ISqlContext>(),
|
||||
Mock.Of<IJsonSerializer>(),
|
||||
Mock.Of<IScopeProvider>(),
|
||||
Mock.Of<ICoreScopeProvider>(),
|
||||
Mock.Of<IAuthorizationService>(),
|
||||
Mock.Of<IContentVersionService>()
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user