Use audit service instead of repository directly in services (#19357)

* Introduce new AuditEntryService

- Moved logic related to the IAuditEntryRepository from the AuditService to the new service
- Introduced new Async methods
  - Using ids (for easier transition from the previous Write method)
  - Using keys
- Moved and updated integration tests related to the audit entries to a new test class `AuditEntryServiceTests`
- Added unit tests class `AuditEntryServiceTests` and added a few unit tests
- Added migration to add columns for `performingUserKey` and `affectedUserKey` and convert existing user ids
- Adjusted usages of the old AuditService.Write method to use the new one (mostly notification handlers)

* Audit service rework

- Added new async and paged methods
- Marked (now) redundant methods as obsolete
- Updated all of the usages to use the non-obsolete methods
- Added unit tests class `AuditServiceTests` and some unit tests
- Updated existing integration test

* Use the audit service instead of the repository directly in services

* Apply suggestions from code review

* Small improvement

* Update src/Umbraco.Core/Services/AuditService.cs

* Some minor adjustments following the merge

* Delete unnecessary file

* Small cleanup on the tests

* Remove changing user id to 0 (on audit) if user id is admin in media bulk save

* Remove reference to unused IUserIdKeyResolver in TemplateService

* Remove references to unused IShortStringHelper and GlobalSettings in FileService
This commit is contained in:
Laura Neto
2025-07-24 14:52:17 +02:00
committed by GitHub
parent a50ad893a8
commit c1ac80653b
26 changed files with 942 additions and 213 deletions

View File

@@ -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<TRepository, TEntity, TOperationS
{
private readonly ILogger<StylesheetService> _logger;
private readonly IUserIdKeyResolver _userIdKeyResolver;
private readonly IAuditRepository _auditRepository;
private readonly IAuditService _auditService;
protected FileServiceOperationBase(ICoreScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, TRepository repository, ILogger<StylesheetService> logger, IUserIdKeyResolver userIdKeyResolver, IAuditRepository auditRepository)
protected FileServiceOperationBase(
ICoreScopeProvider provider,
ILoggerFactory loggerFactory,
IEventMessagesFactory eventMessagesFactory,
TRepository repository,
ILogger<StylesheetService> 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<StylesheetService> logger,
IUserIdKeyResolver userIdKeyResolver,
IAuditRepository auditRepository)
: this(
provider,
loggerFactory,
eventMessagesFactory,
repository,
logger,
userIdKeyResolver,
StaticServiceProvider.Instance.GetRequiredService<IAuditService>())
{
}
protected abstract TOperationStatus Success { get; }
@@ -249,10 +278,7 @@ public abstract class FileServiceOperationBase<TRepository, TEntity, TOperationS
}
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);