Merge branch 'release/10.8' into v10/dev

This commit is contained in:
Bjarke Berg
2023-11-27 18:08:30 +01:00
25 changed files with 2086 additions and 1942 deletions

View File

@@ -43,7 +43,7 @@ parameters:
default: ' '
variables:
nodeVersion: 14.18.1
nodeVersion: 20
dotnetVersion: 6.x
dotnetIncludePreviewVersions: false
solution: umbraco.sln
@@ -69,6 +69,7 @@ stages:
steps:
- task: NodeTool@0
displayName: Use Node.js $(nodeVersion)
retryCountOnTaskFailure: 3
inputs:
versionSpec: $(nodeVersion)
- task: Cache@2
@@ -81,9 +82,9 @@ stages:
path: $(npm_config_cache)
- script: npm ci --no-fund --no-audit --prefer-offline
workingDirectory: src/Umbraco.Web.UI.Client
displayName: Run npm ci
displayName: Run npm ci (Backoffice)
- task: gulp@0
displayName: Run gulp build
displayName: Run gulp build (Backoffice)
inputs:
gulpFile: src/Umbraco.Web.UI.Client/gulpfile.js
targets: coreBuild
@@ -208,7 +209,8 @@ stages:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
displayName: Use Node.js 10.15.0
displayName: Use Node.js 10.15.x
retryCountOnTaskFailure: 3
inputs:
versionSpec: 10.15.0 # Won't work with higher versions
- script: |
@@ -442,6 +444,7 @@ stages:
path: $(Build.SourcesDirectory)/tests/Umbraco.Tests.AcceptanceTest/misc/nupkg
- task: NodeTool@0
displayName: Use Node.js $(nodeVersion)
retryCountOnTaskFailure: 3
inputs:
versionSpec: $(nodeVersion)
- task: Cache@2

View File

@@ -372,7 +372,7 @@ public class ContentService : RepositoryService, IContentService
public IContent CreateAndSave(string name, int parentId, string contentTypeAlias, int userId = Constants.Security.SuperUserId)
{
// TODO: what about culture?
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
{
// locking the content tree secures content types too
scope.WriteLock(Constants.Locks.ContentTree);
@@ -395,6 +395,8 @@ public class ContentService : RepositoryService, IContentService
Save(content, userId);
scope.Complete();
return content;
}
}
@@ -416,7 +418,7 @@ public class ContentService : RepositoryService, IContentService
throw new ArgumentNullException(nameof(parent));
}
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
{
// locking the content tree secures content types too
scope.WriteLock(Constants.Locks.ContentTree);
@@ -431,6 +433,7 @@ public class ContentService : RepositoryService, IContentService
Save(content, userId);
scope.Complete();
return content;
}
}
@@ -508,10 +511,11 @@ public class ContentService : RepositoryService, IContentService
/// <inheritdoc />
public void PersistContentSchedule(IContent content, ContentScheduleCollection contentSchedule)
{
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
{
scope.WriteLock(Constants.Locks.ContentTree);
_documentRepository.PersistContentSchedule(content, contentSchedule);
scope.Complete();
}
}
@@ -2960,7 +2964,7 @@ public class ContentService : RepositoryService, IContentService
public ContentDataIntegrityReport CheckDataIntegrity(ContentDataIntegrityReportOptions options)
{
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
{
scope.WriteLock(Constants.Locks.ContentTree);
@@ -2973,6 +2977,8 @@ public class ContentService : RepositoryService, IContentService
scope.Notifications.Publish(new ContentTreeChangeNotification(root, TreeChangeTypes.RefreshAll, EventMessagesFactory.Get()));
}
scope.Complete();
return report;
}
}

View File

@@ -322,7 +322,6 @@ public abstract class ContentTypeServiceBase<TRepository, TItem> : ContentTypeSe
}
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
{
scope.ReadLock(ReadLockIds);
return Repository.GetMany(ids.ToArray());

View File

@@ -68,7 +68,7 @@ internal class ContentVersionService : IContentVersionService
/// <inheritdoc />
public void SetPreventCleanup(int versionId, bool preventCleanup, int userId = -1)
{
using (ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true))
using (ICoreScope scope = _scopeProvider.CreateCoreScope())
{
scope.WriteLock(Constants.Locks.ContentTree);
_documentVersionRepository.SetPreventCleanup(versionId, preventCleanup);
@@ -77,6 +77,7 @@ internal class ContentVersionService : IContentVersionService
if (version is null)
{
scope.Complete();
return;
}
@@ -87,6 +88,7 @@ internal class ContentVersionService : IContentVersionService
var message = $"set preventCleanup = '{preventCleanup}' for version '{versionId}'";
Audit(auditType, userId, version.ContentId, message, $"{version.VersionDate}");
scope.Complete();
}
}
@@ -120,13 +122,14 @@ internal class ContentVersionService : IContentVersionService
*
* tl;dr lots of scopes to enable other connections to use the DB whilst we work.
*/
using (ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true))
using (ICoreScope scope = _scopeProvider.CreateCoreScope())
{
IReadOnlyCollection<ContentVersionMeta>? allHistoricVersions =
_documentVersionRepository.GetDocumentVersionsEligibleForCleanup();
if (allHistoricVersions is null)
{
scope.Complete();
return Array.Empty<ContentVersionMeta>();
}
@@ -149,6 +152,8 @@ internal class ContentVersionService : IContentVersionService
versionsToDelete.Add(version);
}
scope.Complete();
}
if (!versionsToDelete.Any())
@@ -161,7 +166,7 @@ internal class ContentVersionService : IContentVersionService
foreach (IEnumerable<ContentVersionMeta> group in versionsToDelete.InGroupsOf(Constants.Sql.MaxParameterCount))
{
using (ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true))
using (ICoreScope scope = _scopeProvider.CreateCoreScope())
{
scope.WriteLock(Constants.Locks.ContentTree);
var groupEnumerated = group.ToList();
@@ -174,12 +179,16 @@ internal class ContentVersionService : IContentVersionService
scope.Notifications.Publish(
new ContentDeletedVersionsNotification(version.ContentId, messages, version.VersionId));
}
scope.Complete();
}
}
using (_scopeProvider.CreateCoreScope(autoComplete: true))
using (ICoreScope scope = _scopeProvider.CreateCoreScope())
{
Audit(AuditType.Delete, Constants.Security.SuperUserId, -1, $"Removed {versionsToDelete.Count} ContentVersion(s) according to cleanup policy");
scope.Complete();
}
return versionsToDelete;

View File

@@ -608,7 +608,7 @@ namespace Umbraco.Cms.Core.Services.Implement
public IReadOnlyDictionary<Udi, IEnumerable<string>> GetReferences(int id)
{
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete:true);
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
return _dataTypeRepository.FindUsages(id);
}

View File

@@ -33,7 +33,7 @@ public class DefaultContentVersionCleanupPolicy : IContentVersionCleanupPolicy
var theRest = new List<ContentVersionMeta>();
using (_scopeProvider.CreateCoreScope(autoComplete: true))
using (ICoreScope scope = _scopeProvider.CreateCoreScope())
{
var policyOverrides = _documentVersionRepository.GetCleanupPolicies()?
.ToDictionary(x => x.ContentTypeId);
@@ -77,6 +77,8 @@ public class DefaultContentVersionCleanupPolicy : IContentVersionCleanupPolicy
yield return version;
}
}
scope.Complete();
}
}

View File

@@ -1197,7 +1197,7 @@ namespace Umbraco.Cms.Core.Services
public ContentDataIntegrityReport CheckDataIntegrity(ContentDataIntegrityReportOptions options)
{
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
{
scope.WriteLock(Constants.Locks.MediaTree);
@@ -1210,6 +1210,7 @@ namespace Umbraco.Cms.Core.Services
scope.Notifications.Publish(new MediaTreeChangeNotification(root, TreeChangeTypes.RefreshAll, EventMessagesFactory.Get()));
}
scope.Complete();
return report;
}
}

View File

@@ -59,8 +59,10 @@ public class TwoFactorLoginService : ITwoFactorLoginService2
/// <inheritdoc />
public async Task DeleteUserLoginsAsync(Guid userOrMemberKey)
{
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
using ICoreScope scope = _scopeProvider.CreateCoreScope();
await _twoFactorLoginRepository.DeleteUserLoginsAsync(userOrMemberKey);
scope.Complete();
}
/// <inheritdoc />
@@ -155,8 +157,12 @@ public class TwoFactorLoginService : ITwoFactorLoginService2
/// <inheritdoc />
public async Task<bool> DisableAsync(Guid userOrMemberKey, string providerName)
{
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
return await _twoFactorLoginRepository.DeleteUserLoginsAsync(userOrMemberKey, providerName);
using ICoreScope scope = _scopeProvider.CreateCoreScope();
var result = await _twoFactorLoginRepository.DeleteUserLoginsAsync(userOrMemberKey, providerName);
scope.Complete();
return result;
}
/// <inheritdoc />
@@ -173,9 +179,10 @@ public class TwoFactorLoginService : ITwoFactorLoginService2
/// <inheritdoc />
public Task SaveAsync(TwoFactorLogin twoFactorLogin)
{
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
using ICoreScope scope = _scopeProvider.CreateCoreScope();
_twoFactorLoginRepository.Save(twoFactorLogin);
scope.Complete();
return Task.CompletedTask;
}

View File

@@ -8,6 +8,11 @@ namespace Umbraco.Extensions;
public static class UserServiceExtensions
{
public static EntityPermission? GetPermissions(this IUserService userService, IUser? user, string path)
{
return userService.GetAllPermissions(user, path).FirstOrDefault();
}
public static EntityPermissionCollection GetAllPermissions(this IUserService userService, IUser? user, string path)
{
var ids = path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries)
.Select(x =>
@@ -23,7 +28,7 @@ public static class UserServiceExtensions
" could not be parsed into an array of integers or the path was empty");
}
return userService.GetPermissions(user, ids[^1]).FirstOrDefault();
return userService.GetPermissions(user, ids[^1]);
}
/// <summary>

View File

@@ -94,7 +94,7 @@ public class ScheduledPublishing : RecurringHostedServiceBase
// but then what should be its "scope"? could we attach it to scopes?
// - and we should definitively *not* have to flush it here (should be auto)
using UmbracoContextReference contextReference = _umbracoContextFactory.EnsureUmbracoContext();
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
using ICoreScope scope = _scopeProvider.CreateCoreScope();
/* We used to assume that there will never be two instances running concurrently where (IsMainDom && ServerRole == SchedulingPublisher)
* However this is possible during an azure deployment slot swap for the SchedulingPublisher instance when trying to achieve zero downtime deployments.
@@ -113,6 +113,8 @@ public class ScheduledPublishing : RecurringHostedServiceBase
grouped.Count(),
grouped.Key);
}
scope.Complete();
}
finally
{

View File

@@ -1,6 +1,9 @@
using Umbraco.Cms.Core.Models;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Persistence.Repositories;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Infrastructure.Scoping;
using Umbraco.Cms.Web.Common.DependencyInjection;
using IScope = Umbraco.Cms.Infrastructure.Scoping.IScope;
namespace Umbraco.Cms.Core.Logging.Viewer;
@@ -10,6 +13,21 @@ public class LogViewerConfig : ILogViewerConfig
private readonly ILogViewerQueryRepository _logViewerQueryRepository;
private readonly IScopeProvider _scopeProvider;
[Obsolete("Use non-obsolete ctor. This will be removed in Umbraco 14.")]
public LogViewerConfig(ILogViewerQueryRepository logViewerQueryRepository, Umbraco.Cms.Core.Scoping.IScopeProvider scopeProvider)
: this(logViewerQueryRepository, StaticServiceProvider.Instance.GetRequiredService<IScopeProvider>())
{
}
//Temp ctor used by MSDI (Greedy)
[Obsolete("Use non-obsolete ctor. This will be removed in Umbraco 14.")]
public LogViewerConfig(ILogViewerQueryRepository logViewerQueryRepository, Umbraco.Cms.Core.Scoping.IScopeProvider coreScopeProvider, IScopeProvider scopeProvider)
: this(logViewerQueryRepository, scopeProvider)
{
}
public LogViewerConfig(ILogViewerQueryRepository logViewerQueryRepository, IScopeProvider scopeProvider)
{
_logViewerQueryRepository = logViewerQueryRepository;
@@ -26,15 +44,16 @@ public class LogViewerConfig : ILogViewerConfig
public IReadOnlyList<SavedLogSearch>? AddSavedSearch(string? name, string? query)
{
using IScope scope = _scopeProvider.CreateScope(autoComplete: true);
using IScope scope = _scopeProvider.CreateScope();
_logViewerQueryRepository.Save(new LogViewerQuery(name, query));
scope.Complete();
return GetSavedSearches();
}
public IReadOnlyList<SavedLogSearch>? DeleteSavedSearch(string? name, string? query)
{
using IScope scope = _scopeProvider.CreateScope(autoComplete: true);
using IScope scope = _scopeProvider.CreateScope();
ILogViewerQuery? item = name is null ? null : _logViewerQueryRepository.GetByName(name);
if (item is not null)
{
@@ -42,6 +61,8 @@ public class LogViewerConfig : ILogViewerConfig
}
// Return the updated object - so we can instantly reset the entire array from the API response
return GetSavedSearches();
IReadOnlyList<SavedLogSearch> result = GetSavedSearches()!;
scope.Complete();
return result;
}
}

View File

@@ -96,7 +96,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
throw new ArgumentNullException(nameof(user));
}
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
using ICoreScope scope = _scopeProvider.CreateCoreScope();
// create member
IMember memberEntity = _memberService.CreateMember(
@@ -150,6 +150,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
x.Value)));
}
scope.Complete();
return Task.FromResult(IdentityResult.Success);
}
catch (Exception ex)
@@ -179,7 +180,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
throw new InvalidOperationException("The user id must be an integer to work with the Umbraco");
}
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
using ICoreScope scope = _scopeProvider.CreateCoreScope();
IMember? found = _memberService.GetById(asInt);
if (found != null)
@@ -220,6 +221,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
}
}
scope.Complete();
return Task.FromResult(IdentityResult.Success);
}
catch (Exception ex)

View File

@@ -736,16 +736,22 @@ public class ContentStore
{
EnsureLocked();
IPublishedContentType?[] contentTypes = _contentTypesById
IPublishedContentType[] contentTypes = _contentTypesById
.Where(kvp =>
kvp.Value.Value != null &&
kvp.Value.Value.PropertyTypes.Any(p => dataTypeIds.Contains(p.DataType.Id)))
.Select(kvp => kvp.Value.Value)
.Select(x => getContentType(x!.Id))
.Where(x => x != null) // poof, gone, very unlikely and probably an anomaly
.WhereNotNull() // poof, gone, very unlikely and probably an anomaly
.ToArray();
var contentTypeIdsA = contentTypes.Select(x => x!.Id).ToArray();
// all content types that are affected by this data type update must be updated
foreach (IPublishedContentType contentType in contentTypes)
{
SetContentTypeLocked(contentType);
}
var contentTypeIdsA = contentTypes.Select(x => x.Id).ToArray();
var contentTypeNodes = new Dictionary<int, List<int>>();
foreach (var id in contentTypeIdsA)
{
@@ -761,7 +767,7 @@ public class ContentStore
}
}
foreach (IPublishedContentType contentType in contentTypes.WhereNotNull())
foreach (IPublishedContentType contentType in contentTypes)
{
// again, weird situation
if (contentTypeNodes.ContainsKey(contentType.Id) == false)

View File

@@ -2337,11 +2337,11 @@ public class ContentController : ContentControllerBase
return NotFound("There is no content node with id {model.NodeId}.");
}
EntityPermission? permission =
_userService.GetPermissions(_backofficeSecurityAccessor.BackOfficeSecurity?.CurrentUser, node.Path);
// Validate permissions on node
var permissions = _userService.GetAllPermissions(_backofficeSecurityAccessor.BackOfficeSecurity?.CurrentUser, node.Path);
if (permission?.AssignedPermissions.Contains(ActionAssignDomain.ActionLetter.ToString(), StringComparer.Ordinal) == false)
if (permissions.Any(x =>
x.AssignedPermissions.Contains(ActionAssignDomain.ActionLetter.ToString(), StringComparer.Ordinal) && x.EntityId == node.Id) == false)
{
HttpContext.SetReasonPhrase("Permission Denied.");
return BadRequest("You do not have permission to assign domains on that node.");

View File

@@ -0,0 +1 @@
20.9

File diff suppressed because it is too large Load Diff

View File

@@ -10,17 +10,18 @@
"build:dev": "gulp buildDev",
"dev": "gulp dev",
"fastdev": "gulp fastdev",
"watch": "gulp watch"
"watch": "gulp watch",
"lint": "eslint src"
},
"engines": {
"node": ">=14.0.0 <17",
"npm": ">=8.0.0 < 9"
"node": ">=20.9",
"npm": ">=10.1"
},
"dependencies": {
"@microsoft/signalr": "6.0.9",
"@umbraco-ui/uui": "1.3.0",
"@umbraco-ui/uui-css": "1.3.0",
"ace-builds": "1.22.1",
"@umbraco-ui/uui": "1.5.0",
"@umbraco-ui/uui-css": "1.5.0",
"ace-builds": "1.31.1",
"angular": "1.8.3",
"angular-animate": "1.8.3",
"angular-aria": "1.8.3",
@@ -42,14 +43,14 @@
"diff": "5.1.0",
"flatpickr": "4.6.13",
"font-awesome": "4.7.0",
"jquery": "3.7.0",
"jquery": "3.7.1",
"jquery-ui-dist": "1.13.2",
"jquery-ui-touch-punch": "0.2.3",
"lazyload-js": "1.0.0",
"moment": "2.29.4",
"ng-file-upload": "12.2.13",
"nouislider": "15.6.1",
"spectrum-colorpicker2": "2.0.9",
"nouislider": "15.7.1",
"spectrum-colorpicker2": "2.0.10",
"tinymce": "4.9.11",
"typeahead.js": "0.11.1",
"underscore": "1.13.6",
@@ -58,8 +59,8 @@
"devDependencies": {
"@babel/core": "7.19.1",
"@babel/preset-env": "7.19.1",
"autoprefixer": "10.4.14",
"cssnano": "5.1.13",
"autoprefixer": "10.4.16",
"cssnano": "6.0.1",
"gulp": "4.0.2",
"gulp-angular-embed-templates": "2.3.0",
"gulp-babel": "8.0.0",
@@ -78,17 +79,17 @@
"gulp-watch": "5.0.1",
"gulp-wrap": "0.15.0",
"gulp-wrap-js": "0.4.1",
"jasmine-core": "4.4.0",
"jsdom": "20.0.0",
"karma": "6.4.0",
"jasmine-core": "5.1.1",
"jsdom": "22.1.0",
"karma": "6.4.2",
"karma-jasmine": "5.1.0",
"karma-jsdom-launcher": "13.0.0",
"karma-jsdom-launcher": "15.0.0",
"karma-junit-reporter": "2.0.1",
"karma-spec-reporter": "0.0.34",
"less": "4.1.3",
"karma-spec-reporter": "0.0.36",
"less": "4.2.0",
"lodash": "4.17.21",
"merge-stream": "2.0.0",
"postcss": "8.4.16",
"postcss": "8.4.31",
"run-sequence": "2.2.1"
}
}

View File

@@ -170,7 +170,7 @@ var uSkyGridConfig = [
}, {
grid: 3,
percentage: 25
}, ]
} ]
}, {
models: [{
grid: 2,
@@ -279,7 +279,7 @@ var uSkyGridConfig = [
}, {
grid: 3,
percentage: 25
}, ]
} ]
}, {
models: [{
grid: 2,

View File

@@ -102,7 +102,7 @@ public class UmbProfileController : SurfaceController
private async Task<IdentityResult> UpdateMemberAsync(ProfileModel model, MemberIdentityUser currentMember)
{
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
using ICoreScope scope = _scopeProvider.CreateCoreScope();
currentMember.Email = model.Email;
currentMember.Name = model.Name;
@@ -112,6 +112,7 @@ public class UmbProfileController : SurfaceController
IdentityResult saveResult = await _memberManager.UpdateAsync(currentMember);
if (!saveResult.Succeeded)
{
scope.Complete();
return saveResult;
}
@@ -140,6 +141,7 @@ public class UmbProfileController : SurfaceController
_memberService.Save(member);
scope.Complete();
return saveResult;
}
}

View File

@@ -118,7 +118,7 @@ public class UmbRegisterController : SurfaceController
/// <returns>Result of registration operation.</returns>
private async Task<IdentityResult> RegisterMemberAsync(RegisterModel model)
{
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
using ICoreScope scope = _scopeProvider.CreateCoreScope();
// U4-10762 Server error with "Register Member" snippet (Cannot save member with empty name)
// If name field is empty, add the email address instead.
@@ -160,6 +160,8 @@ public class UmbRegisterController : SurfaceController
}
}
scope.Complete();
return identityResult;
}
}

View File

@@ -7,6 +7,7 @@ using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Moq;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
@@ -14,6 +15,8 @@ using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Configuration;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Diagnostics;
using Umbraco.Cms.Core.DistributedLocking;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Logging;
@@ -24,6 +27,8 @@ using Umbraco.Cms.Core.Runtime;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Cms.Infrastructure.Persistence.SqlSyntax;
using Umbraco.Cms.Infrastructure.Scoping;
using Umbraco.Cms.Infrastructure.Serialization;
using Umbraco.Cms.Tests.Common.TestHelpers;
using Umbraco.Extensions;
@@ -76,6 +81,61 @@ public abstract class TestHelperBase
public IShortStringHelper ShortStringHelper { get; } =
new DefaultShortStringHelper(new DefaultShortStringHelperConfig());
public IScopeProvider ScopeProvider
{
get
{
var loggerFactory = NullLoggerFactory.Instance;
var fileSystems = new FileSystems(
loggerFactory,
Mock.Of<IIOHelper>(),
Mock.Of<IOptions<GlobalSettings>>(),
Mock.Of<IHostingEnvironment>());
var mediaFileManager = new MediaFileManager(
Mock.Of<IFileSystem>(),
Mock.Of<IMediaPathScheme>(),
loggerFactory.CreateLogger<MediaFileManager>(),
Mock.Of<IShortStringHelper>(),
Mock.Of<IServiceProvider>(),
Options.Create(new ContentSettings()));
var databaseFactory = new Mock<IUmbracoDatabaseFactory>();
var database = new Mock<IUmbracoDatabase>();
var sqlContext = new Mock<ISqlContext>();
var lockingMechanism = new Mock<IDistributedLockingMechanism>();
lockingMechanism.Setup(x => x.ReadLock(It.IsAny<int>(), It.IsAny<TimeSpan?>()))
.Returns(Mock.Of<IDistributedLock>());
lockingMechanism.Setup(x => x.WriteLock(It.IsAny<int>(), It.IsAny<TimeSpan?>()))
.Returns(Mock.Of<IDistributedLock>());
var lockingMechanismFactory = new Mock<IDistributedLockingMechanismFactory>();
lockingMechanismFactory.Setup(x => x.DistributedLockingMechanism)
.Returns(lockingMechanism.Object);
// Setup mock of database factory to return mock of database.
databaseFactory.Setup(x => x.CreateDatabase()).Returns(database.Object);
databaseFactory.Setup(x => x.SqlContext).Returns(sqlContext.Object);
// Setup mock of database to return mock of sql SqlContext
database.Setup(x => x.SqlContext).Returns(sqlContext.Object);
var syntaxProviderMock = new Mock<ISqlSyntaxProvider>();
// Setup mock of ISqlContext to return syntaxProviderMock
sqlContext.Setup(x => x.SqlSyntax).Returns(syntaxProviderMock.Object);
return new ScopeProvider(
new AmbientScopeStack(),
new AmbientScopeContextStack(),
lockingMechanismFactory.Object,
databaseFactory.Object,
fileSystems,
new TestOptionsMonitor<CoreDebugSettings>(new CoreDebugSettings()),
mediaFileManager,
loggerFactory,
Mock.Of<IEventAggregator>());
}
}
public IJsonSerializer JsonSerializer { get; } = new JsonNetSerializer();

View File

@@ -32,6 +32,7 @@ using Umbraco.Cms.Core.Net;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Runtime;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Infrastructure.Mail;
@@ -43,6 +44,7 @@ using Umbraco.Cms.Tests.Common.Testing;
using Umbraco.Extensions;
using File = System.IO.File;
using IHostingEnvironment = Umbraco.Cms.Core.Hosting.IHostingEnvironment;
using IScopeProvider = Umbraco.Cms.Infrastructure.Scoping.IScopeProvider;
namespace Umbraco.Cms.Tests.UnitTests.TestHelpers;
@@ -59,6 +61,8 @@ public static class TestHelper
/// <value>The assembly directory.</value>
public static string WorkingDirectory => s_testHelperInternal.WorkingDirectory;
public static IScopeProvider ScopeProvider => s_testHelperInternal.ScopeProvider;
public static ICoreScopeProvider CoreScopeProvider => s_testHelperInternal.ScopeProvider;
public static IShortStringHelper ShortStringHelper => s_testHelperInternal.ShortStringHelper;
public static IJsonSerializer JsonSerializer => s_testHelperInternal.JsonSerializer;

View File

@@ -49,7 +49,7 @@ public class LogviewerTests
File.Copy(exampleLogfilePath, _newLogfilePath, true);
var logger = Mock.Of<ILogger<SerilogJsonLogViewer>>();
var logViewerConfig = new LogViewerConfig(LogViewerQueryRepository, Mock.Of<IScopeProvider>());
var logViewerConfig = new LogViewerConfig(LogViewerQueryRepository, TestHelper.ScopeProvider);
var logLevelLoader = Mock.Of<ILogLevelLoader>();
_logViewer =
new SerilogJsonLogViewer(logger, logViewerConfig, loggingConfiguration, logLevelLoader, Log.Logger);

View File

@@ -17,6 +17,7 @@ using Umbraco.Cms.Infrastructure.Scoping;
using Umbraco.Cms.Tests.Common;
using Umbraco.Cms.Tests.Common.Builders;
using Umbraco.Cms.Tests.Common.Builders.Extensions;
using Umbraco.Cms.Tests.UnitTests.TestHelpers;
using Umbraco.Cms.Web.Common.Security;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security;
@@ -33,7 +34,7 @@ public class MemberManagerTests
public MemberManager CreateSut()
{
var scopeProvider = new Mock<IScopeProvider>().Object;
var scopeProvider = TestHelper.ScopeProvider;
_mockMemberService = new Mock<IMemberService>();
var mapDefinitions = new List<IMapDefinition>

View File

@@ -15,6 +15,7 @@ using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Tests.UnitTests.TestHelpers;
using Umbraco.Cms.Tests.UnitTests.Umbraco.Core.ShortStringHelper;
using IScopeProvider = Umbraco.Cms.Infrastructure.Scoping.IScopeProvider;
@@ -28,23 +29,12 @@ public class MemberUserStoreTests
public MemberUserStore CreateSut()
{
_mockMemberService = new Mock<IMemberService>();
var mockScope = new Mock<IScope>();
var mockScopeProvider = new Mock<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);
var mockScopeProvider = TestHelper.ScopeProvider;
return new MemberUserStore(
_mockMemberService.Object,
new UmbracoMapper(new MapDefinitionCollection(() => new List<IMapDefinition>()), mockScopeProvider.Object, NullLogger<UmbracoMapper>.Instance),
mockScopeProvider.Object,
new UmbracoMapper(new MapDefinitionCollection(() => new List<IMapDefinition>()), mockScopeProvider, NullLogger<UmbracoMapper>.Instance),
mockScopeProvider,
new IdentityErrorDescriber(),
Mock.Of<IPublishedSnapshotAccessor>(),
Mock.Of<IExternalLoginWithKeyService>(),