Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ protected IActionResult PartialViewOperationStatusResult(PartialViewOperationSta
.WithDetail("The partial view name is invalid.")
.Build()),
PartialViewOperationStatus.NotFound => PartialViewNotFound(),
PartialViewOperationStatus.NotAllowedInProductionMode => BadRequest(problemDetailsBuilder
.WithTitle("Not allowed in production mode")
.WithDetail("Partial view modifications are not allowed when running in production mode.")
.Build()),
_ => StatusCode(StatusCodes.Status500InternalServerError, problemDetailsBuilder
.WithTitle("Unknown partial view operation status.")
.Build()),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Common.Builders;
Expand Down Expand Up @@ -42,6 +42,14 @@ protected IActionResult TemplateOperationStatusResult(TemplateOperationStatus st
.WithTitle("Master template cannot be deleted")
.WithDetail("The master templates cannot be deleted. Please ensure the template is not a master template before you delete.")
.Build()),
TemplateOperationStatus.NotAllowedInProductionMode => BadRequest(problemDetailsBuilder
.WithTitle("Not allowed in production mode")
.WithDetail("Template modifications are not allowed when running in production mode.")
.Build()),
TemplateOperationStatus.ContentChangeNotAllowedInProductionMode => BadRequest(problemDetailsBuilder
.WithTitle("Content change not allowed in production mode")
.WithDetail("Template content changes are not allowed when running in production mode. Metadata updates are permitted.")
.Build()),
_ => StatusCode(StatusCodes.Status500InternalServerError, problemDetailsBuilder
.WithTitle("Unknown template operation status.")
.Build()),
Expand Down
4 changes: 2 additions & 2 deletions src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,11 +316,11 @@ private void AddCoreServices()
Services.AddUnique<IContentTypeEditingService, ContentTypeEditingService>();
Services.AddUnique<IMediaTypeEditingService, MediaTypeEditingService>();
Services.AddUnique<IFileService, FileService>();
Services.AddUnique<ITemplateService, TemplateService>();
Services.AddUnique<ITemplateService>(sp => ActivatorUtilities.CreateInstance<TemplateService>(sp));
Services.AddUnique<IScriptService, ScriptService>();
Services.AddUnique<IStylesheetService, StylesheetService>();
Services.AddUnique<IStylesheetFolderService, StylesheetFolderService>();
Services.AddUnique<IPartialViewService, PartialViewService>();
Services.AddUnique<IPartialViewService>(sp => ActivatorUtilities.CreateInstance<PartialViewService>(sp));
Services.AddUnique<IScriptFolderService, ScriptFolderService>();
Services.AddUnique<IPartialViewFolderService, PartialViewFolderService>();
Services.AddUnique<ITemporaryFileService, TemporaryFileService>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ public enum PartialViewOperationStatus
InvalidFileExtension,
PathTooLong,
CancelledByNotification,
NotFound
NotFound,
NotAllowedInProductionMode
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ public enum TemplateOperationStatus
MasterTemplateNotFound,
CircularMasterTemplateReference,
MasterTemplateCannotBeDeleted,
NotAllowedInProductionMode,
ContentChangeNotAllowedInProductionMode,
}
90 changes: 80 additions & 10 deletions src/Umbraco.Core/Services/PartialViewService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
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.Models;
Expand All @@ -15,7 +17,16 @@
public class PartialViewService : FileServiceOperationBase<IPartialViewRepository, IPartialView, PartialViewOperationStatus>, IPartialViewService
{
private readonly PartialViewSnippetCollection _snippetCollection;
private readonly IOptions<RuntimeSettings> _runtimeSettings;

// TODO (V18): Remove obsolete constructors and the ActivatorUtilitiesConstructor attribute.
// Also update UmbracoBuilder where this service is registered using:
// Services.AddUnique<IPartialViewService>(sp => ActivatorUtilities.CreateInstance<PartialViewService>(sp));
// We do this to allow the ActivatorUtilitiesConstructor to be used (it's otherwise ignored by AddUnique).
// Revert it to:
// Services.AddUnique<IPartialViewService, PartialViewService>();

[ActivatorUtilitiesConstructor]
public PartialViewService(
ICoreScopeProvider provider,
ILoggerFactory loggerFactory,
Expand All @@ -24,11 +35,15 @@
ILogger<StylesheetService> logger,
IUserIdKeyResolver userIdKeyResolver,
IAuditService auditService,
PartialViewSnippetCollection snippetCollection)
PartialViewSnippetCollection snippetCollection,
IOptions<RuntimeSettings> runtimeSettings)
: base(provider, loggerFactory, eventMessagesFactory, repository, logger, userIdKeyResolver, auditService)
=> _snippetCollection = snippetCollection;
{
_snippetCollection = snippetCollection;
_runtimeSettings = runtimeSettings;
}

[Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")]
[Obsolete("Use the non-obsolete constructor instead. Scheduled for removal in Umbraco 18.")]
public PartialViewService(
ICoreScopeProvider provider,
ILoggerFactory loggerFactory,
Expand All @@ -46,11 +61,12 @@
logger,
userIdKeyResolver,
StaticServiceProvider.Instance.GetRequiredService<IAuditService>(),
snippetCollection)
snippetCollection,
StaticServiceProvider.Instance.GetRequiredService<IOptions<RuntimeSettings>>())

Check warning on line 65 in src/Umbraco.Core/Services/PartialViewService.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

❌ New issue: Code Duplication

The module contains 3 functions with similar structure: PartialViewService,PartialViewService,PartialViewService. Avoid duplicated, aka copy-pasted, code inside the module. More duplication lowers the code health.

Check notice on line 65 in src/Umbraco.Core/Services/PartialViewService.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

✅ Getting better: Constructor Over-Injection

PartialViewService decreases from 9 to 8 arguments, max arguments = 5. This constructor has too many arguments, indicating an object with low cohesion or missing function argument abstraction. Avoid adding more arguments.
{
}

[Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")]
[Obsolete("Use the non-obsolete constructor instead. Scheduled for removal in Umbraco 18.")]
public PartialViewService(
ICoreScopeProvider provider,
ILoggerFactory loggerFactory,
Expand All @@ -69,12 +85,38 @@
logger,
userIdKeyResolver,
auditService,
snippetCollection)
snippetCollection,
StaticServiceProvider.Instance.GetRequiredService<IOptions<RuntimeSettings>>())
{
}

[Obsolete("Use the non-obsolete constructor instead. Scheduled for removal in Umbraco 18.")]
public PartialViewService(
ICoreScopeProvider provider,
ILoggerFactory loggerFactory,
IEventMessagesFactory eventMessagesFactory,
IPartialViewRepository repository,
ILogger<StylesheetService> logger,
IUserIdKeyResolver userIdKeyResolver,
IAuditService auditService,
PartialViewSnippetCollection snippetCollection)
: this(
provider,
loggerFactory,
eventMessagesFactory,
repository,
logger,
userIdKeyResolver,
auditService,
snippetCollection,
StaticServiceProvider.Instance.GetRequiredService<IOptions<RuntimeSettings>>())
{
}

protected override string[] AllowedFileExtensions { get; } = { ".cshtml" };

private bool IsProductionMode => _runtimeSettings.Value.Mode == RuntimeMode.Production;

protected override PartialViewOperationStatus Success => PartialViewOperationStatus.Success;

protected override PartialViewOperationStatus NotFound => PartialViewOperationStatus.NotFound;
Expand Down Expand Up @@ -132,17 +174,45 @@

/// <inheritdoc />
public async Task<PartialViewOperationStatus> DeleteAsync(string path, Guid userKey)
=> await HandleDeleteAsync(path, userKey);
{
if (IsProductionMode)
{
return PartialViewOperationStatus.NotAllowedInProductionMode;
}

return await HandleDeleteAsync(path, userKey);
}

/// <inheritdoc />
public async Task<Attempt<IPartialView?, PartialViewOperationStatus>> CreateAsync(PartialViewCreateModel createModel, Guid userKey)
=> await HandleCreateAsync(createModel.Name, createModel.ParentPath, createModel.Content, userKey);
{
if (IsProductionMode)
{
return Attempt.FailWithStatus<IPartialView?, PartialViewOperationStatus>(PartialViewOperationStatus.NotAllowedInProductionMode, null);
}

return await HandleCreateAsync(createModel.Name, createModel.ParentPath, createModel.Content, userKey);
}

/// <inheritdoc />
public async Task<Attempt<IPartialView?, PartialViewOperationStatus>> UpdateAsync(string path, PartialViewUpdateModel updateModel, Guid userKey)
=> await HandleUpdateAsync(path, updateModel.Content, userKey);
{
if (IsProductionMode)
{
return Attempt.FailWithStatus<IPartialView?, PartialViewOperationStatus>(PartialViewOperationStatus.NotAllowedInProductionMode, null);
}

return await HandleUpdateAsync(path, updateModel.Content, userKey);
}

/// <inheritdoc />
public async Task<Attempt<IPartialView?, PartialViewOperationStatus>> RenameAsync(string path, PartialViewRenameModel renameModel, Guid userKey)
=> await HandleRenameAsync(path, renameModel.Name, userKey);
{
if (IsProductionMode)
{
return Attempt.FailWithStatus<IPartialView?, PartialViewOperationStatus>(PartialViewOperationStatus.NotAllowedInProductionMode, null);
}

return await HandleRenameAsync(path, renameModel.Name, userKey);
}
}
Loading
Loading