diff --git a/build/NuSpecs/tools/Web.config.install.xdt b/build/NuSpecs/tools/Web.config.install.xdt index 6579717a60..2b79f95c70 100644 --- a/build/NuSpecs/tools/Web.config.install.xdt +++ b/build/NuSpecs/tools/Web.config.install.xdt @@ -14,6 +14,7 @@ + diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs index f351721e56..1fdb64c62a 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs @@ -1,9 +1,4 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using Umbraco.Core; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Web.Editors; +using Umbraco.ModelsBuilder.Embedded.Configuration; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.ModelsBuilder.Embedded.BackOffice @@ -12,70 +7,11 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice /// Used to validate the aliases for the content type when MB is enabled to ensure that /// no illegal aliases are used /// + // ReSharper disable once UnusedMember.Global - This is typed scanned public class ContentTypeModelValidator : ContentTypeModelValidatorBase - { } - - /// - /// Used to validate the aliases for the content type when MB is enabled to ensure that - /// no illegal aliases are used - /// - public class MediaTypeModelValidator : ContentTypeModelValidatorBase - { } - - /// - /// Used to validate the aliases for the content type when MB is enabled to ensure that - /// no illegal aliases are used - /// - public class MemberTypeModelValidator : ContentTypeModelValidatorBase - { } - - public abstract class ContentTypeModelValidatorBase : EditorValidator - where TModel : ContentTypeSave - where TProperty : PropertyTypeBasic { - protected override IEnumerable Validate(TModel model) + public ContentTypeModelValidator(IModelsBuilderConfig config) : base(config) { - var properties = model.Groups.SelectMany(x => x.Properties) - .Where(x => x.Inherited == false) - .ToArray(); - - foreach (var prop in properties) - { - var propertyGroup = model.Groups.Single(x => x.Properties.Contains(prop)); - - if (model.Alias.ToLowerInvariant() == prop.Alias.ToLowerInvariant()) - yield return new ValidationResult(string.Format("With Models Builder enabled, you can't have a property with a the alias \"{0}\" when the content type alias is also \"{0}\".", prop.Alias), new[] - { - string.Format("Groups[{0}].Properties[{1}].Alias", model.Groups.IndexOf(propertyGroup), propertyGroup.Properties.IndexOf(prop)) - }); - - //we need to return the field name with an index so it's wired up correctly - var groupIndex = model.Groups.IndexOf(propertyGroup); - var propertyIndex = propertyGroup.Properties.IndexOf(prop); - - var validationResult = ValidateProperty(prop, groupIndex, propertyIndex); - if (validationResult != null) - yield return validationResult; - } - } - - private ValidationResult ValidateProperty(PropertyTypeBasic property, int groupIndex, int propertyIndex) - { - //don't let them match any properties or methods in IPublishedContent - //TODO: There are probably more! - var reservedProperties = typeof(IPublishedContent).GetProperties().Select(x => x.Name).ToArray(); - var reservedMethods = typeof(IPublishedContent).GetMethods().Select(x => x.Name).ToArray(); - - var alias = property.Alias; - - if (reservedProperties.InvariantContains(alias) || reservedMethods.InvariantContains(alias)) - return new ValidationResult( - string.Format("The alias {0} is a reserved term and cannot be used", alias), new[] - { - string.Format("Groups[{0}].Properties[{1}].Alias", groupIndex, propertyIndex) - }); - - return null; } } } diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs new file mode 100644 index 0000000000..15ca2cca24 --- /dev/null +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using Umbraco.Core; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.ModelsBuilder.Embedded.Configuration; +using Umbraco.Web.Editors; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.ModelsBuilder.Embedded.BackOffice +{ + public abstract class ContentTypeModelValidatorBase : EditorValidator + where TModel : ContentTypeSave + where TProperty : PropertyTypeBasic + { + private readonly IModelsBuilderConfig _config; + + public ContentTypeModelValidatorBase(IModelsBuilderConfig config) + { + _config = config; + } + + protected override IEnumerable Validate(TModel model) + { + //don't do anything if we're not enabled + if (!_config.Enable) yield break; + + var properties = model.Groups.SelectMany(x => x.Properties) + .Where(x => x.Inherited == false) + .ToArray(); + + foreach (var prop in properties) + { + var propertyGroup = model.Groups.Single(x => x.Properties.Contains(prop)); + + if (model.Alias.ToLowerInvariant() == prop.Alias.ToLowerInvariant()) + yield return new ValidationResult(string.Format("With Models Builder enabled, you can't have a property with a the alias \"{0}\" when the content type alias is also \"{0}\".", prop.Alias), new[] + { + $"Groups[{model.Groups.IndexOf(propertyGroup)}].Properties[{propertyGroup.Properties.IndexOf(prop)}].Alias" + }); + + //we need to return the field name with an index so it's wired up correctly + var groupIndex = model.Groups.IndexOf(propertyGroup); + var propertyIndex = propertyGroup.Properties.IndexOf(prop); + + var validationResult = ValidateProperty(prop, groupIndex, propertyIndex); + if (validationResult != null) + yield return validationResult; + } + } + + private ValidationResult ValidateProperty(PropertyTypeBasic property, int groupIndex, int propertyIndex) + { + //don't let them match any properties or methods in IPublishedContent + //TODO: There are probably more! + var reservedProperties = typeof(IPublishedContent).GetProperties().Select(x => x.Name).ToArray(); + var reservedMethods = typeof(IPublishedContent).GetMethods().Select(x => x.Name).ToArray(); + + var alias = property.Alias; + + if (reservedProperties.InvariantContains(alias) || reservedMethods.InvariantContains(alias)) + return new ValidationResult( + $"The alias {alias} is a reserved term and cannot be used", new[] + { + $"Groups[{groupIndex}].Properties[{propertyIndex}].Alias" + }); + + return null; + } + } +} diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs index e4c45aaf3e..25ddc838e8 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs @@ -24,6 +24,9 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice public string Text() { + if (!_config.Enable) + return "Version: " + ApiVersion.Current.Version + "
 
ModelsBuilder is disabled
(the .Enable key is missing, or its value is not 'true')."; + var sb = new StringBuilder(); sb.Append("Version: "); diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs new file mode 100644 index 0000000000..9dc1ea6c20 --- /dev/null +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs @@ -0,0 +1,17 @@ +using Umbraco.ModelsBuilder.Embedded.Configuration; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.ModelsBuilder.Embedded.BackOffice +{ + /// + /// Used to validate the aliases for the content type when MB is enabled to ensure that + /// no illegal aliases are used + /// + // ReSharper disable once UnusedMember.Global - This is typed scanned + public class MediaTypeModelValidator : ContentTypeModelValidatorBase + { + public MediaTypeModelValidator(IModelsBuilderConfig config) : base(config) + { + } + } +} diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MemberTypeModelValidator.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MemberTypeModelValidator.cs new file mode 100644 index 0000000000..8d0a98eeab --- /dev/null +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MemberTypeModelValidator.cs @@ -0,0 +1,17 @@ +using Umbraco.ModelsBuilder.Embedded.Configuration; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.ModelsBuilder.Embedded.BackOffice +{ + /// + /// Used to validate the aliases for the content type when MB is enabled to ensure that + /// no illegal aliases are used + /// + // ReSharper disable once UnusedMember.Global - This is typed scanned + public class MemberTypeModelValidator : ContentTypeModelValidatorBase + { + public MemberTypeModelValidator(IModelsBuilderConfig config) : base(config) + { + } + } +} diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs index 44260d6719..1d9de265e9 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs @@ -97,7 +97,7 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice { return new Dashboard { - Enable = true, + Enable = _config.Enable, Text = _dashboardReport.Text(), CanGenerate = _dashboardReport.CanGenerate(), OutOfDateModels = _dashboardReport.AreModelsOutOfDate(), diff --git a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs index be73393994..0e41c9ac62 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs @@ -39,7 +39,8 @@ namespace Umbraco.ModelsBuilder.Embedded.Compose ContentModelBinder.ModelBindingException += ContentModelBinder_ModelBindingException; - FileService.SavingTemplate += FileService_SavingTemplate; + if (_config.Enable) + FileService.SavingTemplate += FileService_SavingTemplate; if (_config.ModelsMode.IsLiveNotPure()) _liveModelsProvider.Install(); @@ -81,7 +82,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Compose { var settings = new Dictionary { - {"enabled", true} + {"enabled", _config.Enable} }; return settings; diff --git a/src/Umbraco.ModelsBuilder.Embedded/Configuration/IModelsBuilderConfig.cs b/src/Umbraco.ModelsBuilder.Embedded/Configuration/IModelsBuilderConfig.cs index d8a81f0458..7e96aec60e 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Configuration/IModelsBuilderConfig.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Configuration/IModelsBuilderConfig.cs @@ -2,6 +2,7 @@ { public interface IModelsBuilderConfig { + bool Enable { get; } bool AcceptUnsafeModelsDirectory { get; } int DebugLevel { get; } bool EnableFactory { get; } diff --git a/src/Umbraco.ModelsBuilder.Embedded/Configuration/ModelsBuilderConfig.cs b/src/Umbraco.ModelsBuilder.Embedded/Configuration/ModelsBuilderConfig.cs index 881c4f97b8..c6bccdcf87 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Configuration/ModelsBuilderConfig.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Configuration/ModelsBuilderConfig.cs @@ -22,11 +22,18 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration { const string prefix = "Umbraco.ModelsBuilder."; + // giant kill switch, default: false + // must be explicitely set to true for anything else to happen + Enable = ConfigurationManager.AppSettings[prefix + "Enable"] == "true"; + // ensure defaults are initialized for tests ModelsNamespace = DefaultModelsNamespace; ModelsDirectory = IOHelper.MapPath(DefaultModelsDirectory); DebugLevel = 0; + // stop here, everything is false + if (!Enable) return; + // mode var modelsMode = ConfigurationManager.AppSettings[prefix + "ModelsMode"]; if (!string.IsNullOrWhiteSpace(modelsMode)) @@ -94,6 +101,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration /// Initializes a new instance of the class. /// public ModelsBuilderConfig( + bool enable = false, ModelsMode modelsMode = ModelsMode.Nothing, string modelsNamespace = null, bool enableFactory = true, @@ -102,6 +110,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration bool acceptUnsafeModelsDirectory = false, int debugLevel = 0) { + Enable = enable; ModelsMode = modelsMode; ModelsNamespace = string.IsNullOrWhiteSpace(modelsNamespace) ? DefaultModelsNamespace : modelsNamespace; @@ -143,6 +152,15 @@ namespace Umbraco.ModelsBuilder.Embedded.Configuration throw new ConfigurationErrorsException($"Invalid models directory \"{config}\"."); } + /// + /// Gets a value indicating whether the whole models experience is enabled. + /// + /// + /// If this is false then absolutely nothing happens. + /// Default value is false which means that unless we have this setting, nothing happens. + /// + public bool Enable { get; } + /// /// Gets the models mode. /// diff --git a/src/Umbraco.ModelsBuilder.Embedded/Configuration/ModelsMode.cs b/src/Umbraco.ModelsBuilder.Embedded/Configuration/ModelsMode.cs index 145508991a..e0286fdab1 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Configuration/ModelsMode.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Configuration/ModelsMode.cs @@ -8,7 +8,7 @@ /// /// Do not generate models. /// - Nothing = 0, // default value //TODO: This doesn't make sense since we cannot actualy disable MB since Umbraco would die + Nothing = 0, // default value /// /// Generate models in memory. diff --git a/src/Umbraco.ModelsBuilder.Embedded/Umbraco.ModelsBuilder.Embedded.csproj b/src/Umbraco.ModelsBuilder.Embedded/Umbraco.ModelsBuilder.Embedded.csproj index 4c22566c05..c09703ecfb 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Umbraco.ModelsBuilder.Embedded.csproj +++ b/src/Umbraco.ModelsBuilder.Embedded/Umbraco.ModelsBuilder.Embedded.csproj @@ -50,6 +50,9 @@ Properties\SolutionInfo.cs + + + diff --git a/src/Umbraco.Web.UI/web.Template.config b/src/Umbraco.Web.UI/web.Template.config index 8759fc6459..f0abbfde52 100644 --- a/src/Umbraco.Web.UI/web.Template.config +++ b/src/Umbraco.Web.UI/web.Template.config @@ -47,6 +47,7 @@ + diff --git a/src/Umbraco.Web/Editors/IEditorValidator.cs b/src/Umbraco.Web/Editors/IEditorValidator.cs index d469d9d9eb..2d655e3506 100644 --- a/src/Umbraco.Web/Editors/IEditorValidator.cs +++ b/src/Umbraco.Web/Editors/IEditorValidator.cs @@ -14,9 +14,7 @@ namespace Umbraco.Web.Editors // initialized with all IEditorValidator instances // // validation is used exclusively in ContentTypeControllerBase - // the whole thing is internal at the moment, never released - // and, there are no IEditorValidator implementation in Core - // so... this all mechanism is basically useless + // currently the only implementations are for Models Builder. /// /// Provides a general object validator.