diff --git a/src/Umbraco.Core/Services/AuditService.cs b/src/Umbraco.Core/Services/AuditService.cs index 342e62a00430..33893dfd5dd8 100644 --- a/src/Umbraco.Core/Services/AuditService.cs +++ b/src/Umbraco.Core/Services/AuditService.cs @@ -16,9 +16,9 @@ namespace Umbraco.Cms.Core.Services.Implement; /// public sealed class AuditService : RepositoryService, IAuditService { + private readonly IUserIdKeyResolver _userIdKeyResolver; private readonly IAuditRepository _auditRepository; private readonly IEntityService _entityService; - private readonly IUserService _userService; /// /// Initializes a new instance of the class. @@ -28,37 +28,15 @@ public AuditService( ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IAuditRepository auditRepository, - IUserService userService, + IUserIdKeyResolver userIdKeyResolver, IEntityService entityService) : base(provider, loggerFactory, eventMessagesFactory) { _auditRepository = auditRepository; - _userService = userService; + _userIdKeyResolver = userIdKeyResolver; _entityService = entityService; } - /// - /// Initializes a new instance of the class. - /// - [Obsolete("Use the non-obsolete constructor. Scheduled for removal in Umbraco 19.")] - public AuditService( - ICoreScopeProvider provider, - ILoggerFactory loggerFactory, - IEventMessagesFactory eventMessagesFactory, - IAuditRepository auditRepository, - IAuditEntryRepository auditEntryRepository, - IUserService userService, - IEntityService entityService) - : this( - provider, - loggerFactory, - eventMessagesFactory, - auditRepository, - userService, - entityService) - { - } - /// public async Task> AddAsync( AuditType type, @@ -68,7 +46,9 @@ public async Task> AddAsync( string? comment = null, string? parameters = null) { - var userId = (await _userService.GetAsync(userKey))?.Id; + int? userId = await _userIdKeyResolver.TryGetAsync(userKey) is { Success: true } userIdAttempt + ? userIdAttempt.Result + : null; if (userId is null) { return Attempt.Fail(AuditLogOperationStatus.UserNotFound); @@ -245,8 +225,7 @@ public async Task> GetPagedItemsByUserAsync( ArgumentOutOfRangeException.ThrowIfNegative(skip); ArgumentOutOfRangeException.ThrowIfNegativeOrZero(take); - IUser? user = await _userService.GetAsync(userKey); - if (user is null) + if (await _userIdKeyResolver.TryGetAsync(userKey) is not { Success: true } userIdAttempt) { return new PagedModel(); } @@ -256,7 +235,7 @@ public async Task> GetPagedItemsByUserAsync( sinceDate.HasValue ? Query().Where(x => x.CreateDate >= sinceDate) : null; PagedModel result = GetItemsByUserInner( - user.Id, + userIdAttempt.Result, pageIndex, pageSize, orderDirection, @@ -418,7 +397,7 @@ private PagedModel GetItemsByUserInner( AuditType[]? auditTypeFilter = null, IQuery? customFilter = null) { - if (userId is < Constants.Security.SuperUserId) + if (userId < Constants.Security.SuperUserId) { return new PagedModel { Items = [], Total = 0 }; } @@ -434,3 +413,4 @@ private void CleanLogsInner(int maximumAgeOfLogsInMinutes) scope.Complete(); } } + diff --git a/src/Umbraco.Core/Services/ContentBlueprintContainerService.cs b/src/Umbraco.Core/Services/ContentBlueprintContainerService.cs index e8d742b70ee1..046c4756324e 100644 --- a/src/Umbraco.Core/Services/ContentBlueprintContainerService.cs +++ b/src/Umbraco.Core/Services/ContentBlueprintContainerService.cs @@ -13,10 +13,10 @@ public ContentBlueprintContainerService( ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IDocumentBlueprintContainerRepository entityContainerRepository, - IAuditRepository auditRepository, + IAuditService auditService, IEntityRepository entityRepository, IUserIdKeyResolver userIdKeyResolver) - : base(provider, loggerFactory, eventMessagesFactory, entityContainerRepository, auditRepository, entityRepository, userIdKeyResolver) + : base(provider, loggerFactory, eventMessagesFactory, entityContainerRepository, auditService, entityRepository, userIdKeyResolver) { } diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 0c3b61a1c368..246682ec14da 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.Services; /// public class ContentService : RepositoryService, IContentService { - private readonly IAuditRepository _auditRepository; + private readonly IAuditService _auditService; private readonly IContentTypeRepository _contentTypeRepository; private readonly IDocumentBlueprintRepository _documentBlueprintRepository; private readonly IDocumentRepository _documentRepository; @@ -52,7 +52,7 @@ public ContentService( IEventMessagesFactory eventMessagesFactory, IDocumentRepository documentRepository, IEntityRepository entityRepository, - IAuditRepository auditRepository, + IAuditService auditService, IContentTypeRepository contentTypeRepository, IDocumentBlueprintRepository documentBlueprintRepository, ILanguageRepository languageRepository, @@ -68,7 +68,7 @@ public ContentService( { _documentRepository = documentRepository; _entityRepository = entityRepository; - _auditRepository = auditRepository; + _auditService = auditService; _contentTypeRepository = contentTypeRepository; _documentBlueprintRepository = documentBlueprintRepository; _languageRepository = languageRepository; @@ -87,8 +87,7 @@ public ContentService( _logger = loggerFactory.CreateLogger(); } - [Obsolete("Use non-obsolete constructor. Scheduled for removal in V17.")] - + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public ContentService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -104,14 +103,16 @@ public ContentService( ICultureImpactFactory cultureImpactFactory, IUserIdKeyResolver userIdKeyResolver, PropertyEditorCollection propertyEditorCollection, - IIdKeyMap idKeyMap) + IIdKeyMap idKeyMap, + IOptionsMonitor optionsMonitor, + IRelationService relationService) : this( provider, loggerFactory, eventMessagesFactory, documentRepository, entityRepository, - auditRepository, + StaticServiceProvider.Instance.GetRequiredService(), contentTypeRepository, documentBlueprintRepository, languageRepository, @@ -121,11 +122,12 @@ public ContentService( userIdKeyResolver, propertyEditorCollection, idKeyMap, - StaticServiceProvider.Instance.GetRequiredService>(), - StaticServiceProvider.Instance.GetRequiredService()) + optionsMonitor, + relationService) { } - [Obsolete("Use non-obsolete constructor. Scheduled for removal in V17.")] + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public ContentService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -133,6 +135,7 @@ public ContentService( IDocumentRepository documentRepository, IEntityRepository entityRepository, IAuditRepository auditRepository, + IAuditService auditService, IContentTypeRepository contentTypeRepository, IDocumentBlueprintRepository documentBlueprintRepository, ILanguageRepository languageRepository, @@ -140,14 +143,17 @@ public ContentService( IShortStringHelper shortStringHelper, ICultureImpactFactory cultureImpactFactory, IUserIdKeyResolver userIdKeyResolver, - PropertyEditorCollection propertyEditorCollection) + PropertyEditorCollection propertyEditorCollection, + IIdKeyMap idKeyMap, + IOptionsMonitor optionsMonitor, + IRelationService relationService) : this( provider, loggerFactory, eventMessagesFactory, documentRepository, entityRepository, - auditRepository, + auditService, contentTypeRepository, documentBlueprintRepository, languageRepository, @@ -156,7 +162,9 @@ public ContentService( cultureImpactFactory, userIdKeyResolver, propertyEditorCollection, - StaticServiceProvider.Instance.GetRequiredService()) + idKeyMap, + optionsMonitor, + relationService) { } @@ -3084,7 +3092,20 @@ internal IEnumerable GetPublishedDescendantsLocked(IContent content) #region Private Methods private void Audit(AuditType type, int userId, int objectId, string? message = null, string? parameters = null) => - _auditRepository.Save(new AuditItem(objectId, type, userId, UmbracoObjectTypes.Document.GetName(), message, parameters)); + AuditAsync(type, userId, objectId, message, parameters).GetAwaiter().GetResult(); + + private async Task AuditAsync(AuditType type, int userId, int objectId, string? message = null, string? parameters = null) + { + Guid userKey = await _userIdKeyResolver.GetAsync(userId); + + await _auditService.AddAsync( + type, + userKey, + objectId, + UmbracoObjectTypes.Document.GetName(), + message, + parameters); + } private string GetLanguageDetailsForAuditEntry(IEnumerable affectedCultures) => GetLanguageDetailsForAuditEntry(_languageRepository.GetMany(), affectedCultures); diff --git a/src/Umbraco.Core/Services/ContentTypeContainerService.cs b/src/Umbraco.Core/Services/ContentTypeContainerService.cs index a6ac5e811f6a..6258216c8e9c 100644 --- a/src/Umbraco.Core/Services/ContentTypeContainerService.cs +++ b/src/Umbraco.Core/Services/ContentTypeContainerService.cs @@ -14,10 +14,10 @@ public ContentTypeContainerService( ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IDocumentTypeContainerRepository entityContainerRepository, - IAuditRepository auditRepository, + IAuditService auditService, IEntityRepository entityRepository, IUserIdKeyResolver userIdKeyResolver) - : base(provider, loggerFactory, eventMessagesFactory, entityContainerRepository, auditRepository, entityRepository, userIdKeyResolver) + : base(provider, loggerFactory, eventMessagesFactory, entityContainerRepository, auditService, entityRepository, userIdKeyResolver) { } diff --git a/src/Umbraco.Core/Services/ContentTypeService.cs b/src/Umbraco.Core/Services/ContentTypeService.cs index 6840d18bfe9a..cae2f1c134f8 100644 --- a/src/Umbraco.Core/Services/ContentTypeService.cs +++ b/src/Umbraco.Core/Services/ContentTypeService.cs @@ -1,4 +1,6 @@ +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; @@ -22,7 +24,7 @@ public ContentTypeService( IEventMessagesFactory eventMessagesFactory, IContentService contentService, IContentTypeRepository repository, - IAuditRepository auditRepository, + IAuditService auditService, IDocumentTypeContainerRepository entityContainerRepository, IEntityRepository entityRepository, IEventAggregator eventAggregator, @@ -33,7 +35,7 @@ public ContentTypeService( loggerFactory, eventMessagesFactory, repository, - auditRepository, + auditService, entityContainerRepository, entityRepository, eventAggregator, @@ -41,6 +43,63 @@ public ContentTypeService( contentTypeFilters) => ContentService = contentService; + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public ContentTypeService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IContentService contentService, + IContentTypeRepository repository, + IAuditRepository auditRepository, + IDocumentTypeContainerRepository entityContainerRepository, + IEntityRepository entityRepository, + IEventAggregator eventAggregator, + IUserIdKeyResolver userIdKeyResolver, + ContentTypeFilterCollection contentTypeFilters) + : this( + provider, + loggerFactory, + eventMessagesFactory, + contentService, + repository, + StaticServiceProvider.Instance.GetRequiredService(), + entityContainerRepository, + entityRepository, + eventAggregator, + userIdKeyResolver, + contentTypeFilters) + { + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public ContentTypeService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IContentService contentService, + IContentTypeRepository repository, + IAuditRepository auditRepository, + IAuditService auditService, + IDocumentTypeContainerRepository entityContainerRepository, + IEntityRepository entityRepository, + IEventAggregator eventAggregator, + IUserIdKeyResolver userIdKeyResolver, + ContentTypeFilterCollection contentTypeFilters) + : this( + provider, + loggerFactory, + eventMessagesFactory, + contentService, + repository, + auditService, + entityContainerRepository, + entityRepository, + eventAggregator, + userIdKeyResolver, + contentTypeFilters) + { + } + protected override int[] ReadLockIds => ContentTypeLocks.ReadLockIds; protected override int[] WriteLockIds => ContentTypeLocks.WriteLockIds; diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs index cd72be54ab85..58f3915d52eb 100644 --- a/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs +++ b/src/Umbraco.Core/Services/ContentTypeServiceBaseOfTRepositoryTItemTService.cs @@ -1,6 +1,8 @@ using System.Globalization; using System.Runtime.InteropServices; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Exceptions; using Umbraco.Cms.Core.Models; @@ -20,7 +22,7 @@ public abstract class ContentTypeServiceBase : ContentTypeSe where TRepository : IContentTypeRepositoryBase where TItem : class, IContentTypeComposition { - private readonly IAuditRepository _auditRepository; + private readonly IAuditService _auditService; private readonly IEntityContainerRepository _containerRepository; private readonly IEntityRepository _entityRepository; private readonly IEventAggregator _eventAggregator; @@ -32,7 +34,7 @@ protected ContentTypeServiceBase( ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, TRepository repository, - IAuditRepository auditRepository, + IAuditService auditService, IEntityContainerRepository containerRepository, IEntityRepository entityRepository, IEventAggregator eventAggregator, @@ -41,7 +43,7 @@ protected ContentTypeServiceBase( : base(provider, loggerFactory, eventMessagesFactory) { Repository = repository; - _auditRepository = auditRepository; + _auditService = auditService; _containerRepository = containerRepository; _entityRepository = entityRepository; _eventAggregator = eventAggregator; @@ -49,6 +51,32 @@ protected ContentTypeServiceBase( _contentTypeFilters = contentTypeFilters; } + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + protected ContentTypeServiceBase( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + TRepository repository, + IAuditRepository auditRepository, + IEntityContainerRepository containerRepository, + IEntityRepository entityRepository, + IEventAggregator eventAggregator, + IUserIdKeyResolver userIdKeyResolver, + ContentTypeFilterCollection contentTypeFilters) + : this( + provider, + loggerFactory, + eventMessagesFactory, + repository, + StaticServiceProvider.Instance.GetRequiredService(), + containerRepository, + entityRepository, + eventAggregator, + userIdKeyResolver, + contentTypeFilters) + { + } + protected TRepository Repository { get; } protected abstract int[] WriteLockIds { get; } protected abstract int[] ReadLockIds { get; } @@ -1398,9 +1426,18 @@ public IEnumerable GetContainers(string name, int level) #region Audit - private void Audit(AuditType type, int userId, int objectId) + private void Audit(AuditType type, int userId, int objectId) => + AuditAsync(type, userId, objectId).GetAwaiter().GetResult(); + + private async Task AuditAsync(AuditType type, int userId, int objectId) { - _auditRepository.Save(new AuditItem(objectId, type, userId, ObjectTypes.GetUmbracoObjectType(ContainedObjectType).GetName())); + Guid userKey = await _userIdKeyResolver.GetAsync(userId); + + await _auditService.AddAsync( + type, + userKey, + objectId, + ObjectTypes.GetUmbracoObjectType(ContainedObjectType).GetName()); } #endregion diff --git a/src/Umbraco.Core/Services/ContentVersionService.cs b/src/Umbraco.Core/Services/ContentVersionService.cs index 9d5d569b3a55..78ff4f347ffe 100644 --- a/src/Umbraco.Core/Services/ContentVersionService.cs +++ b/src/Umbraco.Core/Services/ContentVersionService.cs @@ -15,7 +15,7 @@ namespace Umbraco.Cms.Core.Services; internal class ContentVersionService : IContentVersionService { - private readonly IAuditRepository _auditRepository; + private readonly IAuditService _auditService; private readonly IContentVersionCleanupPolicy _contentVersionCleanupPolicy; private readonly IDocumentVersionRepository _documentVersionRepository; private readonly IEventMessagesFactory _eventMessagesFactory; @@ -32,7 +32,7 @@ public ContentVersionService( IContentVersionCleanupPolicy contentVersionCleanupPolicy, ICoreScopeProvider scopeProvider, IEventMessagesFactory eventMessagesFactory, - IAuditRepository auditRepository, + IAuditService auditService, ILanguageRepository languageRepository, IEntityService entityService, IContentService contentService, @@ -43,7 +43,7 @@ public ContentVersionService( _contentVersionCleanupPolicy = contentVersionCleanupPolicy; _scopeProvider = scopeProvider; _eventMessagesFactory = eventMessagesFactory; - _auditRepository = auditRepository; + _auditService = auditService; _languageRepository = languageRepository; _entityService = entityService; _contentService = contentService; @@ -299,16 +299,19 @@ private IReadOnlyCollection CleanupDocumentVersions(DateTime return versionsToDelete; } - private void Audit(AuditType type, int userId, int objectId, string? message = null, string? parameters = null) + private void Audit(AuditType type, int userId, int objectId, string? message = null, string? parameters = null) => + AuditAsync(type, userId, objectId, message, parameters).GetAwaiter().GetResult(); + + private async Task AuditAsync(AuditType type, int userId, int objectId, string? message = null, string? parameters = null) { - var entry = new AuditItem( - objectId, + Guid userKey = await _userIdKeyResolver.GetAsync(userId); + + await _auditService.AddAsync( type, - userId, + userKey, + objectId, UmbracoObjectTypes.Document.GetName(), message, parameters); - - _auditRepository.Save(entry); } } diff --git a/src/Umbraco.Core/Services/DataTypeContainerService.cs b/src/Umbraco.Core/Services/DataTypeContainerService.cs index 0e6292f7f1fa..8b892226efe0 100644 --- a/src/Umbraco.Core/Services/DataTypeContainerService.cs +++ b/src/Umbraco.Core/Services/DataTypeContainerService.cs @@ -13,10 +13,10 @@ public DataTypeContainerService( ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IDataTypeContainerRepository entityContainerRepository, - IAuditRepository auditRepository, + IAuditService auditService, IEntityRepository entityRepository, IUserIdKeyResolver userIdKeyResolver) - : base(provider, loggerFactory, eventMessagesFactory, entityContainerRepository, auditRepository, entityRepository, userIdKeyResolver) + : base(provider, loggerFactory, eventMessagesFactory, entityContainerRepository, auditService, entityRepository, userIdKeyResolver) { } diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs index 8b1f7f953c29..59daedcb3031 100644 --- a/src/Umbraco.Core/Services/DataTypeService.cs +++ b/src/Umbraco.Core/Services/DataTypeService.cs @@ -27,13 +27,42 @@ public class DataTypeService : RepositoryService, IDataTypeService private readonly IContentTypeRepository _contentTypeRepository; private readonly IMediaTypeRepository _mediaTypeRepository; private readonly IMemberTypeRepository _memberTypeRepository; - private readonly IAuditRepository _auditRepository; + private readonly IAuditService _auditService; private readonly IIOHelper _ioHelper; private readonly IDataTypeContainerService _dataTypeContainerService; private readonly IUserIdKeyResolver _userIdKeyResolver; private readonly Lazy _idKeyMap; - [Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 17.")] + public DataTypeService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IDataTypeRepository dataTypeRepository, + IDataValueEditorFactory dataValueEditorFactory, + IAuditService auditService, + IContentTypeRepository contentTypeRepository, + IMediaTypeRepository mediaTypeRepository, + IMemberTypeRepository memberTypeRepository, + IIOHelper ioHelper, + Lazy idKeyMap) + : base(provider, loggerFactory, eventMessagesFactory) + { + _dataValueEditorFactory = dataValueEditorFactory; + _dataTypeRepository = dataTypeRepository; + _auditService = auditService; + _contentTypeRepository = contentTypeRepository; + _mediaTypeRepository = mediaTypeRepository; + _memberTypeRepository = memberTypeRepository; + _ioHelper = ioHelper; + _idKeyMap = idKeyMap; + + // resolve dependencies for obsolete methods through the static service provider, so they don't pollute the constructor signature + _dataTypeContainerService = StaticServiceProvider.Instance.GetRequiredService(); + _dataTypeContainerRepository = StaticServiceProvider.Instance.GetRequiredService(); + _userIdKeyResolver = StaticServiceProvider.Instance.GetRequiredService(); + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public DataTypeService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -42,23 +71,26 @@ public DataTypeService( IDataValueEditorFactory dataValueEditorFactory, IAuditRepository auditRepository, IContentTypeRepository contentTypeRepository, + IMediaTypeRepository mediaTypeRepository, + IMemberTypeRepository memberTypeRepository, IIOHelper ioHelper, Lazy idKeyMap) : this( - provider, - loggerFactory, - eventMessagesFactory, - dataTypeRepository, - dataValueEditorFactory, - auditRepository, - contentTypeRepository, - StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService(), - ioHelper, - idKeyMap) + provider, + loggerFactory, + eventMessagesFactory, + dataTypeRepository, + dataValueEditorFactory, + StaticServiceProvider.Instance.GetRequiredService(), + contentTypeRepository, + mediaTypeRepository, + memberTypeRepository, + ioHelper, + idKeyMap) { } + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public DataTypeService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -66,26 +98,25 @@ public DataTypeService( IDataTypeRepository dataTypeRepository, IDataValueEditorFactory dataValueEditorFactory, IAuditRepository auditRepository, + IAuditService auditService, IContentTypeRepository contentTypeRepository, IMediaTypeRepository mediaTypeRepository, IMemberTypeRepository memberTypeRepository, IIOHelper ioHelper, Lazy idKeyMap) - : base(provider, loggerFactory, eventMessagesFactory) + : this( + provider, + loggerFactory, + eventMessagesFactory, + dataTypeRepository, + dataValueEditorFactory, + auditService, + contentTypeRepository, + mediaTypeRepository, + memberTypeRepository, + ioHelper, + idKeyMap) { - _dataValueEditorFactory = dataValueEditorFactory; - _dataTypeRepository = dataTypeRepository; - _auditRepository = auditRepository; - _contentTypeRepository = contentTypeRepository; - _mediaTypeRepository = mediaTypeRepository; - _memberTypeRepository = memberTypeRepository; - _ioHelper = ioHelper; - _idKeyMap = idKeyMap; - - // resolve dependencies for obsolete methods through the static service provider, so they don't pollute the constructor signature - _dataTypeContainerService = StaticServiceProvider.Instance.GetRequiredService(); - _dataTypeContainerRepository = StaticServiceProvider.Instance.GetRequiredService(); - _userIdKeyResolver = StaticServiceProvider.Instance.GetRequiredService(); } #region Containers @@ -474,8 +505,7 @@ public async Task> MoveAsync(IDataTy scope.Notifications.Publish(new DataTypeMovedNotification(moveEventInfo, eventMessages).WithStateFrom(movingDataTypeNotification)); - var currentUserId = await _userIdKeyResolver.GetAsync(userKey); - Audit(AuditType.Move, currentUserId, toMove.Id); + await AuditAsync(AuditType.Move, userKey, toMove.Id); scope.Complete(); } @@ -597,7 +627,7 @@ public async Task> UpdateAsync(IData : DataTypeOperationStatus.Success; }, userKey, - AuditType.New); + AuditType.Save); /// /// Saves a collection of @@ -705,8 +735,7 @@ public void Delete(IDataType dataType, int userId = Constants.Security.SuperUser scope.Notifications.Publish(new DataTypeDeletedNotification(dataType, eventMessages).WithStateFrom(deletingDataTypeNotification)); - var currentUserId = await _userIdKeyResolver.GetAsync(userKey); - Audit(AuditType.Delete, currentUserId, dataType.Id); + await AuditAsync(AuditType.Delete, userKey, dataType.Id); scope.Complete(); @@ -902,7 +931,7 @@ private async Task> SaveAsync( scope.Notifications.Publish(new DataTypeSavedNotification(dataType, eventMessages).WithStateFrom(savingDataTypeNotification)); - Audit(auditType, currentUserId, dataType.Id); + await AuditAsync(auditType, userKey, dataType.Id); scope.Complete(); return Attempt.SucceedWithStatus(DataTypeOperationStatus.Success, dataType); @@ -915,7 +944,20 @@ private async Task> SaveAsync( { Result: var intId } => _dataTypeRepository.Get(intId), }; - private void Audit(AuditType type, int userId, int objectId) - => _auditRepository.Save(new AuditItem(objectId, type, userId, ObjectTypes.GetName(UmbracoObjectTypes.DataType))); + private void Audit(AuditType type, int userId, int objectId) => + AuditAsync(type, userId, objectId).GetAwaiter().GetResult(); + + private async Task AuditAsync(AuditType type, int userId, int objectId) + { + Guid userKey = await _userIdKeyResolver.GetAsync(userId); + await AuditAsync(type, userKey, objectId); + } + + private async Task AuditAsync(AuditType type, Guid userKey, int objectId) => + await _auditService.AddAsync( + type, + userKey, + objectId, + UmbracoObjectTypes.DataType.GetName()); } } diff --git a/src/Umbraco.Core/Services/DictionaryItemService.cs b/src/Umbraco.Core/Services/DictionaryItemService.cs index 467f4ea26ac6..c8cb2605b551 100644 --- a/src/Umbraco.Core/Services/DictionaryItemService.cs +++ b/src/Umbraco.Core/Services/DictionaryItemService.cs @@ -12,7 +12,7 @@ namespace Umbraco.Cms.Core.Services; internal sealed class DictionaryItemService : RepositoryService, IDictionaryItemService { private readonly IDictionaryRepository _dictionaryRepository; - private readonly IAuditRepository _auditRepository; + private readonly IAuditService _auditService; private readonly ILanguageService _languageService; private readonly IUserIdKeyResolver _userIdKeyResolver; @@ -21,13 +21,13 @@ public DictionaryItemService( ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IDictionaryRepository dictionaryRepository, - IAuditRepository auditRepository, + IAuditService auditService, ILanguageService languageService, IUserIdKeyResolver userIdKeyResolver) : base(provider, loggerFactory, eventMessagesFactory) { _dictionaryRepository = dictionaryRepository; - _auditRepository = auditRepository; + _auditService = auditService; _languageService = languageService; _userIdKeyResolver = userIdKeyResolver; } @@ -199,8 +199,7 @@ public async Task> Updat new DictionaryItemDeletedNotification(dictionaryItem, eventMessages) .WithStateFrom(deletingNotification)); - var currentUserId = await _userIdKeyResolver.GetAsync(userKey); - Audit(AuditType.Delete, "Delete DictionaryItem", currentUserId, dictionaryItem.Id, nameof(DictionaryItem)); + await AuditAsync(AuditType.Delete, "Delete DictionaryItem", userKey, dictionaryItem.Id, nameof(DictionaryItem)); scope.Complete(); return Attempt.SucceedWithStatus(DictionaryItemOperationStatus.Success, dictionaryItem); @@ -261,8 +260,7 @@ public async Task> MoveA scope.Notifications.Publish( new DictionaryItemMovedNotification(moveEventInfo, eventMessages).WithStateFrom(movingNotification)); - var currentUserId = await _userIdKeyResolver.GetAsync(userKey); - Audit(AuditType.Move, "Move DictionaryItem", currentUserId, dictionaryItem.Id, nameof(DictionaryItem)); + await AuditAsync(AuditType.Move, "Move DictionaryItem", userKey, dictionaryItem.Id, nameof(DictionaryItem)); scope.Complete(); return Attempt.SucceedWithStatus(DictionaryItemOperationStatus.Success, dictionaryItem); @@ -322,8 +320,7 @@ private async Task> Save scope.Notifications.Publish( new DictionaryItemSavedNotification(dictionaryItem, eventMessages).WithStateFrom(savingNotification)); - var currentUserId = await _userIdKeyResolver.GetAsync(userKey); - Audit(auditType, auditMessage, currentUserId, dictionaryItem.Id, nameof(DictionaryItem)); + await AuditAsync(auditType, auditMessage, userKey, dictionaryItem.Id, nameof(DictionaryItem)); scope.Complete(); return Attempt.SucceedWithStatus(DictionaryItemOperationStatus.Success, dictionaryItem); @@ -339,8 +336,13 @@ private Task> GetByQueryAsync(IQuery - _auditRepository.Save(new AuditItem(objectId, type, userId, entityType, message)); + private async Task AuditAsync(AuditType type, string message, Guid userKey, int objectId, string? entityType) => + await _auditService.AddAsync( + type, + userKey, + objectId, + entityType, + message); private bool HasValidParent(IDictionaryItem dictionaryItem) => dictionaryItem.ParentId.HasValue == false || _dictionaryRepository.Get(dictionaryItem.ParentId.Value) != null; diff --git a/src/Umbraco.Core/Services/EntityTypeContainerService.cs b/src/Umbraco.Core/Services/EntityTypeContainerService.cs index 575ff11f2e6f..46532ad0673e 100644 --- a/src/Umbraco.Core/Services/EntityTypeContainerService.cs +++ b/src/Umbraco.Core/Services/EntityTypeContainerService.cs @@ -14,7 +14,7 @@ internal abstract class EntityTypeContainerService> GetAllAsync() _entityContainerRepository.Delete(container); - var currentUserId = await _userIdKeyResolver.GetAsync(userKey); - Audit(AuditType.Delete, currentUserId, container.Id); + await AuditAsync(AuditType.Delete, userKey, container.Id); scope.Complete(); scope.Notifications.Publish(new EntityContainerDeletedNotification(container, eventMessages).WithStateFrom(deletingEntityContainerNotification)); @@ -218,8 +217,7 @@ public Task> GetAllAsync() _entityContainerRepository.Save(container); - var currentUserId = await _userIdKeyResolver.GetAsync(userKey); - Audit(auditType, currentUserId, container.Id); + await AuditAsync(auditType, userKey, container.Id); scope.Complete(); scope.Notifications.Publish(new EntityContainerSavedNotification(container, eventMessages).WithStateFrom(savingEntityContainerNotification)); @@ -239,8 +237,12 @@ public Task> GetAllAsync() return _entityContainerRepository.Get(treeEntity.ParentId); } - private void Audit(AuditType type, int userId, int objectId) - => _auditRepository.Save(new AuditItem(objectId, type, userId, ContainerObjectType.GetName())); + private async Task AuditAsync(AuditType type, Guid userKey, int objectId) => + await _auditService.AddAsync( + type, + userKey, + objectId, + ContainerObjectType.GetName()); private void ReadLock(ICoreScope scope) { diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs index eae1944b5d79..cf0873c2e8bc 100644 --- a/src/Umbraco.Core/Services/FileService.cs +++ b/src/Umbraco.Core/Services/FileService.cs @@ -1,7 +1,9 @@ using System.Text.RegularExpressions; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.Models; @@ -22,7 +24,7 @@ namespace Umbraco.Cms.Core.Services; public class FileService : RepositoryService, IFileService { private const string PartialViewHeader = "@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage"; - private readonly IAuditRepository _auditRepository; + private readonly IAuditService _auditService; private readonly IHostingEnvironment _hostingEnvironment; private readonly IPartialViewRepository _partialViewRepository; private readonly IScriptRepository _scriptRepository; @@ -38,25 +40,84 @@ public FileService( IStylesheetRepository stylesheetRepository, IScriptRepository scriptRepository, IPartialViewRepository partialViewRepository, - IAuditRepository auditRepository, + IAuditService auditService, IHostingEnvironment hostingEnvironment, ITemplateService templateService, ITemplateRepository templateRepository, - IUserIdKeyResolver userIdKeyResolver, - IShortStringHelper shortStringHelper, - IOptions globalSettings) + IUserIdKeyResolver userIdKeyResolver) : base(uowProvider, loggerFactory, eventMessagesFactory) { _stylesheetRepository = stylesheetRepository; _scriptRepository = scriptRepository; _partialViewRepository = partialViewRepository; - _auditRepository = auditRepository; + _auditService = auditService; _hostingEnvironment = hostingEnvironment; _templateService = templateService; _templateRepository = templateRepository; _userIdKeyResolver = userIdKeyResolver; } + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public FileService( + ICoreScopeProvider uowProvider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IStylesheetRepository stylesheetRepository, + IScriptRepository scriptRepository, + IPartialViewRepository partialViewRepository, + IAuditRepository auditRepository, + IHostingEnvironment hostingEnvironment, + ITemplateService templateService, + ITemplateRepository templateRepository, + IUserIdKeyResolver userIdKeyResolver, + IShortStringHelper shortStringHelper, + IOptions globalSettings) + : this( + uowProvider, + loggerFactory, + eventMessagesFactory, + stylesheetRepository, + scriptRepository, + partialViewRepository, + StaticServiceProvider.Instance.GetRequiredService(), + hostingEnvironment, + templateService, + templateRepository, + userIdKeyResolver) + { + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public FileService( + ICoreScopeProvider uowProvider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IStylesheetRepository stylesheetRepository, + IScriptRepository scriptRepository, + IPartialViewRepository partialViewRepository, + IAuditService auditService, + IAuditRepository auditRepository, + IHostingEnvironment hostingEnvironment, + ITemplateService templateService, + ITemplateRepository templateRepository, + IUserIdKeyResolver userIdKeyResolver, + IShortStringHelper shortStringHelper, + IOptions globalSettings) + : this( + uowProvider, + loggerFactory, + eventMessagesFactory, + stylesheetRepository, + scriptRepository, + partialViewRepository, + auditService, + hostingEnvironment, + templateService, + templateRepository, + userIdKeyResolver) + { + } + #region Stylesheets /// @@ -70,7 +131,18 @@ public IEnumerable GetStylesheets(params string[] paths) } private void Audit(AuditType type, int userId, int objectId, string? entityType) => - _auditRepository.Save(new AuditItem(objectId, type, userId, entityType)); + AuditAsync(type, userId, objectId, entityType).GetAwaiter().GetResult(); + + private async Task AuditAsync(AuditType type, int userId, int objectId, string? entityType) + { + Guid userKey = await _userIdKeyResolver.GetAsync(userId); + + await _auditService.AddAsync( + type, + userKey, + objectId, + entityType); + } /// [Obsolete("Please use IStylesheetService for stylesheet operations - will be removed in Umbraco 15")] diff --git a/src/Umbraco.Core/Services/FileServiceOperationBase.cs b/src/Umbraco.Core/Services/FileServiceOperationBase.cs index e7b392d94931..88501af28a7c 100644 --- a/src/Umbraco.Core/Services/FileServiceOperationBase.cs +++ b/src/Umbraco.Core/Services/FileServiceOperationBase.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; @@ -16,14 +18,41 @@ public abstract class FileServiceOperationBase _logger; private readonly IUserIdKeyResolver _userIdKeyResolver; - private readonly IAuditRepository _auditRepository; - - protected FileServiceOperationBase(ICoreScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, TRepository repository, ILogger logger, IUserIdKeyResolver userIdKeyResolver, IAuditRepository auditRepository) + private readonly IAuditService _auditService; + + protected FileServiceOperationBase( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + TRepository repository, + ILogger logger, + IUserIdKeyResolver userIdKeyResolver, + IAuditService auditService) : base(provider, loggerFactory, eventMessagesFactory, repository) { _logger = logger; _userIdKeyResolver = userIdKeyResolver; - _auditRepository = auditRepository; + _auditService = auditService; + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + protected FileServiceOperationBase( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + TRepository repository, + ILogger logger, + IUserIdKeyResolver userIdKeyResolver, + IAuditRepository auditRepository) + : this( + provider, + loggerFactory, + eventMessagesFactory, + repository, + logger, + userIdKeyResolver, + StaticServiceProvider.Instance.GetRequiredService()) + { } protected abstract TOperationStatus Success { get; } @@ -249,10 +278,7 @@ private TOperationStatus ValidateRename(string newName, string newPath) } private async Task AuditAsync(AuditType type, Guid userKey) - { - var userId = await _userIdKeyResolver.GetAsync(userKey); - _auditRepository.Save(new AuditItem(-1, type, userId, EntityType)); - } + => await _auditService.AddAsync(type, userKey, -1, EntityType); private string GetFilePath(string? parentPath, string fileName) => Path.Join(parentPath, fileName); diff --git a/src/Umbraco.Core/Services/LanguageService.cs b/src/Umbraco.Core/Services/LanguageService.cs index 01a249dbd0ed..e32b2c988e33 100644 --- a/src/Umbraco.Core/Services/LanguageService.cs +++ b/src/Umbraco.Core/Services/LanguageService.cs @@ -13,7 +13,7 @@ namespace Umbraco.Cms.Core.Services; internal sealed class LanguageService : RepositoryService, ILanguageService { private readonly ILanguageRepository _languageRepository; - private readonly IAuditRepository _auditRepository; + private readonly IAuditService _auditService; private readonly IUserIdKeyResolver _userIdKeyResolver; private readonly IIsoCodeValidator _isoCodeValidator; @@ -22,13 +22,13 @@ public LanguageService( ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, ILanguageRepository languageRepository, - IAuditRepository auditRepository, + IAuditService auditService, IUserIdKeyResolver userIdKeyResolver, IIsoCodeValidator isoCodeValidator) : base(provider, loggerFactory, eventMessagesFactory) { _languageRepository = languageRepository; - _auditRepository = auditRepository; + _auditService = auditService; _userIdKeyResolver = userIdKeyResolver; _isoCodeValidator = isoCodeValidator; } @@ -160,8 +160,7 @@ public async Task> CreateAsync(ILang scope.Notifications.Publish( new LanguageDeletedNotification(language, eventMessages).WithStateFrom(deletingLanguageNotification)); - var currentUserId = await _userIdKeyResolver.GetAsync(userKey); - Audit(AuditType.Delete, "Delete Language", currentUserId, language.Id, UmbracoObjectTypes.Language.GetName()); + await AuditAsync(AuditType.Delete, "Delete Language", userKey, language.Id, UmbracoObjectTypes.Language.GetName()); scope.Complete(); return Attempt.SucceedWithStatus(LanguageOperationStatus.Success, language); } @@ -213,16 +212,20 @@ private async Task> SaveAsync( scope.Notifications.Publish( new LanguageSavedNotification(language, eventMessages).WithStateFrom(savingNotification)); - var currentUserId = await _userIdKeyResolver.GetAsync(userKey); - Audit(auditType, auditMessage, currentUserId, language.Id, UmbracoObjectTypes.Language.GetName()); + await AuditAsync(auditType, auditMessage, userKey, language.Id, UmbracoObjectTypes.Language.GetName()); scope.Complete(); return Attempt.SucceedWithStatus(LanguageOperationStatus.Success, language); } } - private void Audit(AuditType type, string message, int userId, int objectId, string? entityType) => - _auditRepository.Save(new AuditItem(objectId, type, userId, entityType, message)); + private async Task AuditAsync(AuditType type, string message, Guid userKey, int objectId, string? entityType) => + await _auditService.AddAsync( + type, + userKey, + objectId, + entityType, + message); private bool HasInvalidFallbackLanguage(ILanguage language) { diff --git a/src/Umbraco.Core/Services/LocalizationService.cs b/src/Umbraco.Core/Services/LocalizationService.cs index 989b8f8206db..0e0d2ad922fd 100644 --- a/src/Umbraco.Core/Services/LocalizationService.cs +++ b/src/Umbraco.Core/Services/LocalizationService.cs @@ -17,7 +17,6 @@ namespace Umbraco.Cms.Core.Services; [Obsolete("Please use ILanguageService and IDictionaryItemService for localization. Will be removed in V15.")] internal class LocalizationService : RepositoryService, ILocalizationService { - private readonly IAuditRepository _auditRepository; private readonly IDictionaryRepository _dictionaryRepository; private readonly ILanguageRepository _languageRepository; private readonly ILanguageService _languageService; @@ -30,14 +29,12 @@ public LocalizationService( ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IDictionaryRepository dictionaryRepository, - IAuditRepository auditRepository, ILanguageRepository languageRepository) : this( provider, loggerFactory, eventMessagesFactory, dictionaryRepository, - auditRepository, languageRepository, StaticServiceProvider.Instance.GetRequiredService(), StaticServiceProvider.Instance.GetRequiredService(), @@ -51,7 +48,6 @@ public LocalizationService( ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IDictionaryRepository dictionaryRepository, - IAuditRepository auditRepository, ILanguageRepository languageRepository, ILanguageService languageService, IDictionaryItemService dictionaryItemService, @@ -59,7 +55,6 @@ public LocalizationService( : base(provider, loggerFactory, eventMessagesFactory) { _dictionaryRepository = dictionaryRepository; - _auditRepository = auditRepository; _languageRepository = languageRepository; _languageService = languageService; _dictionaryItemService = dictionaryItemService; diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs index f2ee90696bf2..2ff78811f348 100644 --- a/src/Umbraco.Core/Services/MediaService.cs +++ b/src/Umbraco.Core/Services/MediaService.cs @@ -1,5 +1,7 @@ using System.Globalization; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; @@ -22,7 +24,7 @@ public class MediaService : RepositoryService, IMediaService { private readonly IMediaRepository _mediaRepository; private readonly IMediaTypeRepository _mediaTypeRepository; - private readonly IAuditRepository _auditRepository; + private readonly IAuditService _auditService; private readonly IEntityRepository _entityRepository; private readonly IShortStringHelper _shortStringHelper; private readonly IUserIdKeyResolver _userIdKeyResolver; @@ -37,7 +39,7 @@ public MediaService( ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IMediaRepository mediaRepository, - IAuditRepository auditRepository, + IAuditService auditService, IMediaTypeRepository mediaTypeRepository, IEntityRepository entityRepository, IShortStringHelper shortStringHelper, @@ -46,13 +48,66 @@ public MediaService( { _mediaFileManager = mediaFileManager; _mediaRepository = mediaRepository; - _auditRepository = auditRepository; + _auditService = auditService; _mediaTypeRepository = mediaTypeRepository; _entityRepository = entityRepository; _shortStringHelper = shortStringHelper; _userIdKeyResolver = userIdKeyResolver; } + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public MediaService( + ICoreScopeProvider provider, + MediaFileManager mediaFileManager, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IMediaRepository mediaRepository, + IAuditRepository auditRepository, + IMediaTypeRepository mediaTypeRepository, + IEntityRepository entityRepository, + IShortStringHelper shortStringHelper, + IUserIdKeyResolver userIdKeyResolver) + : this( + provider, + mediaFileManager, + loggerFactory, + eventMessagesFactory, + mediaRepository, + StaticServiceProvider.Instance.GetRequiredService(), + mediaTypeRepository, + entityRepository, + shortStringHelper, + userIdKeyResolver) + { + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public MediaService( + ICoreScopeProvider provider, + MediaFileManager mediaFileManager, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IMediaRepository mediaRepository, + IAuditService auditService, + IAuditRepository auditRepository, + IMediaTypeRepository mediaTypeRepository, + IEntityRepository entityRepository, + IShortStringHelper shortStringHelper, + IUserIdKeyResolver userIdKeyResolver) + : this( + provider, + mediaFileManager, + loggerFactory, + eventMessagesFactory, + mediaRepository, + auditService, + mediaTypeRepository, + entityRepository, + shortStringHelper, + userIdKeyResolver) + { + } + #endregion #region Count @@ -788,7 +843,7 @@ public bool HasChildren(int id) scope.Notifications.Publish(new MediaSavedNotification(mediasA, messages).WithStateFrom(savingNotification)); // TODO: See note about suppressing events in content service scope.Notifications.Publish(new MediaTreeChangeNotification(treeChanges, messages)); - Audit(AuditType.Save, userId == -1 ? 0 : userId, Constants.System.Root, "Bulk save media"); + Audit(AuditType.Save, userId, Constants.System.Root, "Bulk save media"); scope.Complete(); } @@ -1235,9 +1290,20 @@ public ContentDataIntegrityReport CheckDataIntegrity(ContentDataIntegrityReportO #region Private Methods - private void Audit(AuditType type, int userId, int objectId, string? message = null) + private void Audit(AuditType type, int userId, int objectId, string? message = null) => + AuditAsync(type, userId, objectId, message).GetAwaiter().GetResult(); + + private async Task AuditAsync(AuditType type, int userId, int objectId, string? message = null, string? parameters = null) { - _auditRepository.Save(new AuditItem(objectId, type, userId, ObjectTypes.GetName(UmbracoObjectTypes.Media), message)); + Guid userKey = await _userIdKeyResolver.GetAsync(userId); + + await _auditService.AddAsync( + type, + userKey, + objectId, + UmbracoObjectTypes.Media.GetName(), + message, + parameters); } #endregion diff --git a/src/Umbraco.Core/Services/MediaTypeContainerService.cs b/src/Umbraco.Core/Services/MediaTypeContainerService.cs index 6aeb9af4842a..548b38b70db0 100644 --- a/src/Umbraco.Core/Services/MediaTypeContainerService.cs +++ b/src/Umbraco.Core/Services/MediaTypeContainerService.cs @@ -14,10 +14,10 @@ public MediaTypeContainerService( ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IMediaTypeContainerRepository entityContainerRepository, - IAuditRepository auditRepository, + IAuditService auditService, IEntityRepository entityRepository, IUserIdKeyResolver userIdKeyResolver) - : base(provider, loggerFactory, eventMessagesFactory, entityContainerRepository, auditRepository, entityRepository, userIdKeyResolver) + : base(provider, loggerFactory, eventMessagesFactory, entityContainerRepository, auditService, entityRepository, userIdKeyResolver) { } diff --git a/src/Umbraco.Core/Services/MediaTypeService.cs b/src/Umbraco.Core/Services/MediaTypeService.cs index 2ab943a9c78d..22166dfdae22 100644 --- a/src/Umbraco.Core/Services/MediaTypeService.cs +++ b/src/Umbraco.Core/Services/MediaTypeService.cs @@ -1,4 +1,6 @@ +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; @@ -19,7 +21,7 @@ public MediaTypeService( IEventMessagesFactory eventMessagesFactory, IMediaService mediaService, IMediaTypeRepository mediaTypeRepository, - IAuditRepository auditRepository, + IAuditService auditService, IMediaTypeContainerRepository entityContainerRepository, IEntityRepository entityRepository, IEventAggregator eventAggregator, @@ -30,13 +32,72 @@ public MediaTypeService( loggerFactory, eventMessagesFactory, mediaTypeRepository, - auditRepository, + auditService, + entityContainerRepository, + entityRepository, + eventAggregator, + userIdKeyResolver, + contentTypeFilters) + { + MediaService = mediaService; + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public MediaTypeService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IMediaService mediaService, + IMediaTypeRepository mediaTypeRepository, + IAuditRepository auditRepository, + IMediaTypeContainerRepository entityContainerRepository, + IEntityRepository entityRepository, + IEventAggregator eventAggregator, + IUserIdKeyResolver userIdKeyResolver, + ContentTypeFilterCollection contentTypeFilters) + : this( + provider, + loggerFactory, + eventMessagesFactory, + mediaService, + mediaTypeRepository, + StaticServiceProvider.Instance.GetRequiredService(), entityContainerRepository, entityRepository, eventAggregator, userIdKeyResolver, - contentTypeFilters) => MediaService = mediaService; + contentTypeFilters) + { + } + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public MediaTypeService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IMediaService mediaService, + IMediaTypeRepository mediaTypeRepository, + IAuditService auditService, + IAuditRepository auditRepository, + IMediaTypeContainerRepository entityContainerRepository, + IEntityRepository entityRepository, + IEventAggregator eventAggregator, + IUserIdKeyResolver userIdKeyResolver, + ContentTypeFilterCollection contentTypeFilters) + : this( + provider, + loggerFactory, + eventMessagesFactory, + mediaService, + mediaTypeRepository, + auditService, + entityContainerRepository, + entityRepository, + eventAggregator, + userIdKeyResolver, + contentTypeFilters) + { + } protected override int[] ReadLockIds => MediaTypeLocks.ReadLockIds; diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs index c2499a9efe78..2e3ddc8b4973 100644 --- a/src/Umbraco.Core/Services/MemberService.cs +++ b/src/Umbraco.Core/Services/MemberService.cs @@ -1,4 +1,6 @@ +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Membership; @@ -19,9 +21,10 @@ public class MemberService : RepositoryService, IMemberService private readonly IMemberRepository _memberRepository; private readonly IMemberTypeRepository _memberTypeRepository; private readonly IMemberGroupRepository _memberGroupRepository; - private readonly IAuditRepository _auditRepository; + private readonly IAuditService _auditService; private readonly IMemberGroupService _memberGroupService; private readonly Lazy _idKeyMap; + private readonly IUserIdKeyResolver _userIdKeyResolver; #region Constructor @@ -33,18 +36,72 @@ public MemberService( IMemberRepository memberRepository, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, - IAuditRepository auditRepository, - Lazy idKeyMap) + IAuditService auditService, + Lazy idKeyMap, + IUserIdKeyResolver userIdKeyResolver) : base(provider, loggerFactory, eventMessagesFactory) { _memberRepository = memberRepository; _memberTypeRepository = memberTypeRepository; _memberGroupRepository = memberGroupRepository; - _auditRepository = auditRepository; + _auditService = auditService; _idKeyMap = idKeyMap; + _userIdKeyResolver = userIdKeyResolver; _memberGroupService = memberGroupService ?? throw new ArgumentNullException(nameof(memberGroupService)); } + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public MemberService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IMemberGroupService memberGroupService, + IMemberRepository memberRepository, + IMemberTypeRepository memberTypeRepository, + IMemberGroupRepository memberGroupRepository, + IAuditRepository auditRepository, + Lazy idKeyMap) + : this( + provider, + loggerFactory, + eventMessagesFactory, + memberGroupService, + memberRepository, + memberTypeRepository, + memberGroupRepository, + StaticServiceProvider.Instance.GetRequiredService(), + idKeyMap, + StaticServiceProvider.Instance.GetRequiredService()) + { + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public MemberService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IMemberGroupService memberGroupService, + IMemberRepository memberRepository, + IMemberTypeRepository memberTypeRepository, + IMemberGroupRepository memberGroupRepository, + IAuditService auditService, + IAuditRepository auditRepository, + Lazy idKeyMap, + IUserIdKeyResolver userIdKeyResolver) + : this( + provider, + loggerFactory, + eventMessagesFactory, + memberGroupService, + memberRepository, + memberTypeRepository, + memberGroupRepository, + auditService, + idKeyMap, + userIdKeyResolver) + { + } + #endregion #region Count @@ -1126,7 +1183,21 @@ public ContentDataIntegrityReport CheckDataIntegrity(ContentDataIntegrityReportO #region Private Methods - private void Audit(AuditType type, int userId, int objectId, string? message = null) => _auditRepository.Save(new AuditItem(objectId, type, userId, ObjectTypes.GetName(UmbracoObjectTypes.Member), message)); + private void Audit(AuditType type, int userId, int objectId, string? message = null) => + AuditAsync(type, userId, objectId, message).GetAwaiter().GetResult(); + + private async Task AuditAsync(AuditType type, int userId, int objectId, string? message = null, string? parameters = null) + { + Guid userKey = await _userIdKeyResolver.GetAsync(userId); + + await _auditService.AddAsync( + type, + userKey, + objectId, + UmbracoObjectTypes.Member.GetName(), + message, + parameters); + } private IMember? GetMemberFromRepository(Guid id) => _idKeyMap.Value.GetIdForKey(id, UmbracoObjectTypes.Member) switch diff --git a/src/Umbraco.Core/Services/MemberTypeService.cs b/src/Umbraco.Core/Services/MemberTypeService.cs index c8313ad61814..228a10a026d3 100644 --- a/src/Umbraco.Core/Services/MemberTypeService.cs +++ b/src/Umbraco.Core/Services/MemberTypeService.cs @@ -1,4 +1,6 @@ +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; @@ -20,7 +22,7 @@ public MemberTypeService( IEventMessagesFactory eventMessagesFactory, IMemberService memberService, IMemberTypeRepository memberTypeRepository, - IAuditRepository auditRepository, + IAuditService auditService, IMemberTypeContainerRepository entityContainerRepository, IEntityRepository entityRepository, IEventAggregator eventAggregator, @@ -31,7 +33,7 @@ public MemberTypeService( loggerFactory, eventMessagesFactory, memberTypeRepository, - auditRepository, + auditService, entityContainerRepository, entityRepository, eventAggregator, @@ -42,6 +44,63 @@ public MemberTypeService( _memberTypeRepository = memberTypeRepository; } + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public MemberTypeService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IMemberService memberService, + IMemberTypeRepository memberTypeRepository, + IAuditRepository auditRepository, + IMemberTypeContainerRepository entityContainerRepository, + IEntityRepository entityRepository, + IEventAggregator eventAggregator, + IUserIdKeyResolver userIdKeyResolver, + ContentTypeFilterCollection contentTypeFilters) + : this( + provider, + loggerFactory, + eventMessagesFactory, + memberService, + memberTypeRepository, + StaticServiceProvider.Instance.GetRequiredService(), + entityContainerRepository, + entityRepository, + eventAggregator, + userIdKeyResolver, + contentTypeFilters) + { + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public MemberTypeService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IMemberService memberService, + IMemberTypeRepository memberTypeRepository, + IAuditService auditService, + IAuditRepository auditRepository, + IMemberTypeContainerRepository entityContainerRepository, + IEntityRepository entityRepository, + IEventAggregator eventAggregator, + IUserIdKeyResolver userIdKeyResolver, + ContentTypeFilterCollection contentTypeFilters) + : this( + provider, + loggerFactory, + eventMessagesFactory, + memberService, + memberTypeRepository, + auditService, + entityContainerRepository, + entityRepository, + eventAggregator, + userIdKeyResolver, + contentTypeFilters) + { + } + // beware! order is important to avoid deadlocks protected override int[] ReadLockIds { get; } = { Constants.Locks.MemberTypes }; diff --git a/src/Umbraco.Core/Services/PartialViewService.cs b/src/Umbraco.Core/Services/PartialViewService.cs index 9543f45f2892..043eac5ac441 100644 --- a/src/Umbraco.Core/Services/PartialViewService.cs +++ b/src/Umbraco.Core/Services/PartialViewService.cs @@ -1,4 +1,6 @@ +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; @@ -21,11 +23,56 @@ public PartialViewService( IPartialViewRepository repository, ILogger logger, IUserIdKeyResolver userIdKeyResolver, - IAuditRepository auditRepository, + IAuditService auditService, PartialViewSnippetCollection snippetCollection) - : base(provider, loggerFactory, eventMessagesFactory, repository, logger, userIdKeyResolver, auditRepository) + : base(provider, loggerFactory, eventMessagesFactory, repository, logger, userIdKeyResolver, auditService) => _snippetCollection = snippetCollection; + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public PartialViewService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IPartialViewRepository repository, + ILogger logger, + IUserIdKeyResolver userIdKeyResolver, + IAuditRepository auditRepository, + PartialViewSnippetCollection snippetCollection) + : this( + provider, + loggerFactory, + eventMessagesFactory, + repository, + logger, + userIdKeyResolver, + StaticServiceProvider.Instance.GetRequiredService(), + snippetCollection) + { + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public PartialViewService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IPartialViewRepository repository, + ILogger logger, + IUserIdKeyResolver userIdKeyResolver, + IAuditService auditService, + IAuditRepository auditRepository, + PartialViewSnippetCollection snippetCollection) + : this( + provider, + loggerFactory, + eventMessagesFactory, + repository, + logger, + userIdKeyResolver, + auditService, + snippetCollection) + { + } + protected override string[] AllowedFileExtensions { get; } = { ".cshtml" }; protected override PartialViewOperationStatus Success => PartialViewOperationStatus.Success; diff --git a/src/Umbraco.Core/Services/RelationService.cs b/src/Umbraco.Core/Services/RelationService.cs index 456a3bb8dc67..35adb2e217bc 100644 --- a/src/Umbraco.Core/Services/RelationService.cs +++ b/src/Umbraco.Core/Services/RelationService.cs @@ -1,4 +1,6 @@ +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; @@ -13,7 +15,7 @@ namespace Umbraco.Cms.Core.Services; public class RelationService : RepositoryService, IRelationService { - private readonly IAuditRepository _auditRepository; + private readonly IAuditService _auditService; private readonly IUserIdKeyResolver _userIdKeyResolver; private readonly IEntityService _entityService; private readonly IRelationRepository _relationRepository; @@ -26,17 +28,62 @@ public RelationService( IEntityService entityService, IRelationRepository relationRepository, IRelationTypeRepository relationTypeRepository, - IAuditRepository auditRepository, + IAuditService auditService, IUserIdKeyResolver userIdKeyResolver) : base(uowProvider, loggerFactory, eventMessagesFactory) { _relationRepository = relationRepository; _relationTypeRepository = relationTypeRepository; - _auditRepository = auditRepository; + _auditService = auditService; _userIdKeyResolver = userIdKeyResolver; _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); } + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public RelationService( + ICoreScopeProvider uowProvider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IEntityService entityService, + IRelationRepository relationRepository, + IRelationTypeRepository relationTypeRepository, + IAuditRepository auditRepository, + IUserIdKeyResolver userIdKeyResolver) + : this( + uowProvider, + loggerFactory, + eventMessagesFactory, + entityService, + relationRepository, + relationTypeRepository, + StaticServiceProvider.Instance.GetRequiredService(), + userIdKeyResolver) + { + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public RelationService( + ICoreScopeProvider uowProvider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IEntityService entityService, + IRelationRepository relationRepository, + IRelationTypeRepository relationTypeRepository, + IAuditService auditService, + IAuditRepository auditRepository, + IUserIdKeyResolver userIdKeyResolver) + : this( + uowProvider, + loggerFactory, + eventMessagesFactory, + entityService, + relationRepository, + relationTypeRepository, + auditService, + userIdKeyResolver) + { + } + /// public IRelation? GetById(int id) { @@ -601,8 +648,7 @@ private async Task> SaveAsyn } _relationTypeRepository.Save(relationType); - var currentUser = await _userIdKeyResolver.GetAsync(userKey); - Audit(auditType, currentUser, relationType.Id, auditMessage); + await AuditAsync(auditType, userKey, relationType.Id, auditMessage); scope.Complete(); scope.Notifications.Publish( new RelationTypeSavedNotification(relationType, eventMessages).WithStateFrom(savingNotification)); @@ -666,8 +712,7 @@ public void Delete(IRelationType relationType) } _relationTypeRepository.Delete(relationType); - var currentUser = await _userIdKeyResolver.GetAsync(userKey); - Audit(AuditType.Delete, currentUser, relationType.Id, "Deleted relation type"); + await AuditAsync(AuditType.Delete, userKey, relationType.Id, "Deleted relation type"); scope.Notifications.Publish(new RelationTypeDeletedNotification(relationType, eventMessages).WithStateFrom(deletingNotification)); scope.Complete(); return Attempt.SucceedWithStatus(RelationTypeOperationStatus.Success, relationType); @@ -744,7 +789,23 @@ private List GetRelationsByListOfTypeIds(IEnumerable relationTyp } private void Audit(AuditType type, int userId, int objectId, string? message = null) => - _auditRepository.Save(new AuditItem(objectId, type, userId, UmbracoObjectTypes.RelationType.GetName(), message)); + AuditAsync(type, userId, objectId, message).GetAwaiter().GetResult(); + + private async Task AuditAsync(AuditType type, int userId, int objectId, string? message = null, string? parameters = null) + { + Guid userKey = await _userIdKeyResolver.GetAsync(userId); + + await AuditAsync(type, userKey, objectId, message, parameters); + } + + private async Task AuditAsync(AuditType type, Guid userKey, int objectId, string? message = null, string? parameters = null) => + await _auditService.AddAsync( + type, + userKey, + objectId, + UmbracoObjectTypes.RelationType.GetName(), + message, + parameters); #endregion } diff --git a/src/Umbraco.Core/Services/ScriptService.cs b/src/Umbraco.Core/Services/ScriptService.cs index e64822c1e166..91a89298b242 100644 --- a/src/Umbraco.Core/Services/ScriptService.cs +++ b/src/Umbraco.Core/Services/ScriptService.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; @@ -17,8 +19,49 @@ public ScriptService( IScriptRepository repository, ILogger logger, IUserIdKeyResolver userIdKeyResolver, + IAuditService auditService) + : base(provider, loggerFactory, eventMessagesFactory, repository, logger, userIdKeyResolver, auditService) + { + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public ScriptService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IScriptRepository repository, + ILogger logger, + IUserIdKeyResolver userIdKeyResolver, + IAuditRepository auditRepository) + : this( + provider, + loggerFactory, + eventMessagesFactory, + repository, + logger, + userIdKeyResolver, + StaticServiceProvider.Instance.GetRequiredService()) + { + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public ScriptService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IScriptRepository repository, + ILogger logger, + IUserIdKeyResolver userIdKeyResolver, + IAuditService auditService, IAuditRepository auditRepository) - : base(provider, loggerFactory, eventMessagesFactory, repository, logger, userIdKeyResolver, auditRepository) + : this( + provider, + loggerFactory, + eventMessagesFactory, + repository, + logger, + userIdKeyResolver, + auditService) { } diff --git a/src/Umbraco.Core/Services/StylesheetService.cs b/src/Umbraco.Core/Services/StylesheetService.cs index 08bab2a84a02..2137de92b8d3 100644 --- a/src/Umbraco.Core/Services/StylesheetService.cs +++ b/src/Umbraco.Core/Services/StylesheetService.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Notifications; @@ -17,8 +19,49 @@ public StylesheetService( IStylesheetRepository repository, ILogger logger, IUserIdKeyResolver userIdKeyResolver, + IAuditService auditService) + : base(provider, loggerFactory, eventMessagesFactory, repository, logger, userIdKeyResolver, auditService) + { + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public StylesheetService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IStylesheetRepository repository, + ILogger logger, + IUserIdKeyResolver userIdKeyResolver, + IAuditRepository auditRepository) + : this( + provider, + loggerFactory, + eventMessagesFactory, + repository, + logger, + userIdKeyResolver, + StaticServiceProvider.Instance.GetRequiredService()) + { + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public StylesheetService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IStylesheetRepository repository, + ILogger logger, + IUserIdKeyResolver userIdKeyResolver, + IAuditService auditService, IAuditRepository auditRepository) - : base(provider, loggerFactory, eventMessagesFactory, repository, logger, userIdKeyResolver, auditRepository) + : this( + provider, + loggerFactory, + eventMessagesFactory, + repository, + logger, + userIdKeyResolver, + auditService) { } diff --git a/src/Umbraco.Core/Services/TemplateService.cs b/src/Umbraco.Core/Services/TemplateService.cs index 80391c28b5fe..cfb70aefe565 100644 --- a/src/Umbraco.Core/Services/TemplateService.cs +++ b/src/Umbraco.Core/Services/TemplateService.cs @@ -1,4 +1,6 @@ +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Models; @@ -16,10 +18,8 @@ public class TemplateService : RepositoryService, ITemplateService { private readonly IShortStringHelper _shortStringHelper; private readonly ITemplateRepository _templateRepository; - private readonly IAuditRepository _auditRepository; + private readonly IAuditService _auditService; private readonly ITemplateContentParserService _templateContentParserService; - private readonly IUserIdKeyResolver _userIdKeyResolver; - private readonly IDefaultViewContentProvider _defaultViewContentProvider; public TemplateService( ICoreScopeProvider provider, @@ -27,18 +27,59 @@ public TemplateService( IEventMessagesFactory eventMessagesFactory, IShortStringHelper shortStringHelper, ITemplateRepository templateRepository, - IAuditRepository auditRepository, - ITemplateContentParserService templateContentParserService, - IUserIdKeyResolver userIdKeyResolver, - IDefaultViewContentProvider defaultViewContentProvider) + IAuditService auditService, + ITemplateContentParserService templateContentParserService) : base(provider, loggerFactory, eventMessagesFactory) { _shortStringHelper = shortStringHelper; _templateRepository = templateRepository; - _auditRepository = auditRepository; + _auditService = auditService; _templateContentParserService = templateContentParserService; - _userIdKeyResolver = userIdKeyResolver; - _defaultViewContentProvider = defaultViewContentProvider; + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public TemplateService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IShortStringHelper shortStringHelper, + ITemplateRepository templateRepository, + IAuditRepository auditRepository, + ITemplateContentParserService templateContentParserService, + IUserIdKeyResolver userIdKeyResolver, + IDefaultViewContentProvider defaultViewContentProvider) + : this( + provider, + loggerFactory, + eventMessagesFactory, + shortStringHelper, + templateRepository, + StaticServiceProvider.Instance.GetRequiredService(), + templateContentParserService) + { + } + + [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] + public TemplateService( + ICoreScopeProvider provider, + ILoggerFactory loggerFactory, + IEventMessagesFactory eventMessagesFactory, + IShortStringHelper shortStringHelper, + ITemplateRepository templateRepository, + IAuditService auditService, + IAuditRepository auditRepository, + ITemplateContentParserService templateContentParserService, + IUserIdKeyResolver userIdKeyResolver, + IDefaultViewContentProvider defaultViewContentProvider) + : this( + provider, + loggerFactory, + eventMessagesFactory, + shortStringHelper, + templateRepository, + auditService, + templateContentParserService) + { } /// @@ -81,8 +122,7 @@ public async Task> CreateForContentT scope.Notifications.Publish( new TemplateSavedNotification(template, eventMessages).WithStateFrom(savingEvent)); - var currentUserId = await _userIdKeyResolver.GetAsync(userKey); - Audit(AuditType.New, currentUserId, template.Id, UmbracoObjectTypes.Template.GetName()); + await Audit(AuditType.New, userKey, template.Id, UmbracoObjectTypes.Template.GetName()); scope.Complete(); } @@ -270,8 +310,7 @@ private async Task> SaveAsync(ITempl scope.Notifications.Publish( new TemplateSavedNotification(template, eventMessages).WithStateFrom(savingNotification)); - var currentUserId = await _userIdKeyResolver.GetAsync(userKey); - Audit(auditType, currentUserId, template.Id, UmbracoObjectTypes.Template.GetName()); + await Audit(auditType, userKey, template.Id, UmbracoObjectTypes.Template.GetName()); scope.Complete(); return Attempt.SucceedWithStatus(TemplateOperationStatus.Success, template); } @@ -391,8 +430,8 @@ private async Task SetMasterTemplateAsync(ITemplate template, ITemplate? masterT } } - private void Audit(AuditType type, int userId, int objectId, string? entityType) => - _auditRepository.Save(new AuditItem(objectId, type, userId, entityType)); + private Task Audit(AuditType type, Guid userKey, int objectId, string? entityType) => + _auditService.AddAsync(type, userKey, objectId, entityType); private async Task> DeleteAsync(Func> getTemplate, Guid userKey) { @@ -424,8 +463,7 @@ private void Audit(AuditType type, int userId, int objectId, string? entityType) scope.Notifications.Publish( new TemplateDeletedNotification(template, eventMessages).WithStateFrom(deletingNotification)); - var currentUserId = await _userIdKeyResolver.GetAsync(userKey); - Audit(AuditType.Delete, currentUserId, template.Id, UmbracoObjectTypes.Template.GetName()); + await Audit(AuditType.Delete, userKey, template.Id, UmbracoObjectTypes.Template.GetName()); scope.Complete(); return Attempt.SucceedWithStatus(TemplateOperationStatus.Success, template); } diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Services/AuditServiceTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Services/AuditServiceTests.cs index d5fdaa753716..ed7ad3bcd4bc 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Services/AuditServiceTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Services/AuditServiceTests.cs @@ -23,7 +23,7 @@ public class AuditServiceTests private Mock _scopeProviderMock; private Mock _auditRepositoryMock; private Mock _entityServiceMock; - private Mock _userServiceMock; + private Mock _userIdKeyResolverMock; [SetUp] public void Setup() @@ -31,14 +31,14 @@ public void Setup() _scopeProviderMock = new Mock(MockBehavior.Strict); _auditRepositoryMock = new Mock(MockBehavior.Strict); _entityServiceMock = new Mock(MockBehavior.Strict); - _userServiceMock = new Mock(MockBehavior.Strict); + _userIdKeyResolverMock = new Mock(MockBehavior.Strict); _auditService = new AuditService( _scopeProviderMock.Object, Mock.Of(MockBehavior.Strict), Mock.Of(MockBehavior.Strict), _auditRepositoryMock.Object, - _userServiceMock.Object, + _userIdKeyResolverMock.Object, _entityServiceMock.Object); } @@ -59,10 +59,8 @@ public async Task AddAsync_Calls_Repository_With_Correct_Values(AuditType type, Assert.AreEqual(parameters, item.Parameters); }); - Mock mockUser = new Mock(); - mockUser.Setup(x => x.Id).Returns(Constants.Security.SuperUserId); - - _userServiceMock.Setup(x => x.GetAsync(Constants.Security.SuperUserKey)).ReturnsAsync(mockUser.Object); + _userIdKeyResolverMock.Setup(x => x.TryGetAsync(Constants.Security.SuperUserKey)) + .ReturnsAsync(Attempt.Succeed(Constants.Security.SuperUserId)); var result = await _auditService.AddAsync( type, @@ -79,7 +77,7 @@ public async Task AddAsync_Calls_Repository_With_Correct_Values(AuditType type, [Test] public async Task AddAsync_Does_Not_Succeed_When_Non_Existing_User_Is_Provided() { - _userServiceMock.Setup(x => x.GetAsync(It.IsAny())).ReturnsAsync((IUser?)null); + _userIdKeyResolverMock.Setup(x => x.TryGetAsync(It.IsAny())).ReturnsAsync(Attempt.Fail()); var result = await _auditService.AddAsync( AuditType.Publish,