From 465e9545e0d560af99914ad91d7c481ccbbc87c9 Mon Sep 17 00:00:00 2001
From: julian-code <54644662+julian-code@users.noreply.github.com>
Date: Sat, 2 Oct 2021 15:58:27 +0200
Subject: [PATCH 001/137] Update CONTRIBUTING.md (#11248)
---
.github/CONTRIBUTING.md | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 72ad5acb96..a0e0d977a3 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -72,10 +72,10 @@ Great question! The short version goes like this:

- * **Switch to the correct branch** - switch to the `v8/contrib` branch
+ * **Switch to the correct branch** - switch to the `v9/contrib` branch
* **Build** - build your fork of Umbraco locally as described in [building Umbraco from source code](BUILD.md)
* **Change** - make your changes, experiment, have fun, explore and learn, and don't be afraid. We welcome all contributions and will [happily give feedback](#questions)
- * **Commit** - done? Yay! 🎉 **Important:** create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `12345`. When you have a branch, commit your changes. Don't commit to `v8/contrib`, create a new branch first.
+ * **Commit** - done? Yay! 🎉 **Important:** create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `12345`. When you have a branch, commit your changes. Don't commit to `v9/contrib`, create a new branch first.
* **Push** - great, now you can push the changes up to your fork on GitHub
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress - you can now make use of GitHub's draft pull request status, detailed [here](https://github.blog/2019-02-14-introducing-draft-pull-requests/)). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
@@ -173,7 +173,7 @@ To find the general areas for something you're looking to fix or improve, have a
### Which branch should I target for my contributions?
-We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-flow/), but don't worry if you are not familiar with it. The most important thing you need to know is that when you fork the Umbraco repository, the default branch is set to something, usually `v8/contrib`. If you are working on v8, this is the branch you should be targetting. For v7 contributions, please target 'v7/dev'.
+We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-flow/), but don't worry if you are not familiar with it. The most important thing you need to know is that when you fork the Umbraco repository, the default branch is set to something, usually `v9/contrib`. If you are working on v9, this is the branch you should be targetting. For v8 contributions, please target 'v8/contrib'
Please note: we are no longer accepting features for v7 but will continue to merge bug fixes as and when they arise.
@@ -199,10 +199,10 @@ Then when you want to get the changes from the main repository:
```
git fetch upstream
-git rebase upstream/v8/contrib
+git rebase upstream/v9/contrib
```
-In this command we're syncing with the `v8/contrib` branch, but you can of course choose another one if needed.
+In this command we're syncing with the `v9/contrib` branch, but you can of course choose another one if needed.
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
From e416f060c28680c06752edcf659598e68874d347 Mon Sep 17 00:00:00 2001
From: Louis JR <17555062+louisjrdev@users.noreply.github.com>
Date: Mon, 4 Oct 2021 18:48:52 +0100
Subject: [PATCH 002/137] Change template helper to use async partials (#11243)
---
.../src/common/services/templatehelper.service.js | 2 +-
.../test/unit/common/services/template-helper.spec.js | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/templatehelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/templatehelper.service.js
index 1a2f0735ce..aa10d5bf2f 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/templatehelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/templatehelper.service.js
@@ -16,7 +16,7 @@
partialViewName = parentId + "/" + partialViewName;
}
- return "@Html.Partial(\"" + partialViewName + "\")";
+ return "@await Html.PartialAsync(\"" + partialViewName + "\")";
}
function getQuerySnippet(queryExpression) {
diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/services/template-helper.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/services/template-helper.spec.js
index 316cfa7c59..69da0ce786 100644
--- a/src/Umbraco.Web.UI.Client/test/unit/common/services/template-helper.spec.js
+++ b/src/Umbraco.Web.UI.Client/test/unit/common/services/template-helper.spec.js
@@ -26,28 +26,28 @@ describe('service: templateHelper', function () {
it('should return the snippet for inserting a partial from the root', function () {
var parentId = "";
var nodeName = "Footer.cshtml";
- var snippet = '@Html.Partial("Footer")';
+ var snippet = '@await Html.PartialAsync("Footer")';
expect(templateHelper.getInsertPartialSnippet(parentId, nodeName)).toBe(snippet);
});
it('should return the snippet for inserting a partial from a folder', function () {
var parentId = "Folder";
var nodeName = "Footer.cshtml";
- var snippet = '@Html.Partial("Folder/Footer")';
+ var snippet = '@await Html.PartialAsync("Folder/Footer")';
expect(templateHelper.getInsertPartialSnippet(parentId, nodeName)).toBe(snippet);
});
it('should return the snippet for inserting a partial from a nested folder', function () {
var parentId = "Folder/NestedFolder";
var nodeName = "Footer.cshtml";
- var snippet = '@Html.Partial("Folder/NestedFolder/Footer")';
+ var snippet = '@await Html.PartialAsync("Folder/NestedFolder/Footer")';
expect(templateHelper.getInsertPartialSnippet(parentId, nodeName)).toBe(snippet);
});
it('should return the snippet for inserting a partial from a folder with spaces in its name', function () {
var parentId = "Folder with spaces";
var nodeName = "Footer.cshtml";
- var snippet = '@Html.Partial("Folder with spaces/Footer")';
+ var snippet = '@await Html.PartialAsync("Folder with spaces/Footer")';
expect(templateHelper.getInsertPartialSnippet(parentId, nodeName)).toBe(snippet);
});
From 9abd0714575ceacd548630c256e02b9ed191bede Mon Sep 17 00:00:00 2001
From: Jeavon Leopold
Date: Wed, 29 Sep 2021 12:45:36 +0100
Subject: [PATCH 003/137] Fix for Excessive header checker when excluding
Cloudflare
---
.../HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs
index cdd8a0493f..34c76f2b6d 100644
--- a/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs
+++ b/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs
@@ -65,7 +65,7 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Security
var headersToCheckFor = new List {"Server", "X-Powered-By", "X-AspNet-Version", "X-AspNetMvc-Version" };
// Ignore if server header is present and it's set to cloudflare
- if (allHeaders.InvariantContains("Server") && response.Headers.TryGetValues("Server", out var serverHeaders) && serverHeaders.ToString().InvariantEquals("cloudflare"))
+ if (allHeaders.InvariantContains("Server") && response.Headers.TryGetValues("Server", out var serverHeaders) && serverHeaders.FirstOrDefault().InvariantEquals("cloudflare"))
{
headersToCheckFor.Remove("Server");
}
From f29bda645593e6dc71f877ac1730946cea7afb5c Mon Sep 17 00:00:00 2001
From: Jesper Mayntzhusen <79840720+jemayn@users.noreply.github.com>
Date: Tue, 5 Oct 2021 02:20:51 +0200
Subject: [PATCH 004/137] Cypress test for textbox max length (#11245)
* add test for textbox max length
* remove leftover comment
Co-authored-by: Jesper
---
.../integration/DataTypes/dataTypes.ts | 43 +++++++++++++++++++
.../integration/Members/memberGroups.js | 2 +-
2 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/DataTypes/dataTypes.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/DataTypes/dataTypes.ts
index 9e1e6cc185..942d42a9bf 100644
--- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/DataTypes/dataTypes.ts
+++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/DataTypes/dataTypes.ts
@@ -2,6 +2,7 @@
import {
AliasHelper,
ApprovedColorPickerDataTypeBuilder,
+ TextBoxDataTypeBuilder,
} from 'umbraco-cypress-testhelpers';
context('DataTypes', () => {
@@ -61,6 +62,48 @@ context('DataTypes', () => {
cy.umbracoEnsureTemplateNameNotExists(name);
});
+ it('Tests Textbox Maxlength', () => {
+ cy.deleteAllContent();
+ const name = 'Textbox Maxlength Test';
+ const alias = AliasHelper.toAlias(name);
+
+ cy.umbracoEnsureDocumentTypeNameNotExists(name);
+ cy.umbracoEnsureDataTypeNameNotExists(name);
+
+ const textBoxDataType = new TextBoxDataTypeBuilder()
+ .withName(name)
+ .withMaxChars(10)
+ .build()
+
+ cy.umbracoCreateDocTypeWithContent(name, alias, textBoxDataType);
+
+ // Act
+ // Enter content
+ // Assert no helptext with (max-2) chars & can save
+ cy.umbracoRefreshContentTree();
+ cy.umbracoTreeItem("content", [name]).click();
+ cy.get('input[name="textbox"]').type('12345678');
+ cy.get('localize[key="textbox_characters_left"]').should('not.exist');
+ cy.umbracoButtonByLabelKey('buttons_saveAndPublish').click();
+ cy.umbracoSuccessNotification().should('be.visible');
+ cy.get('.property-error').should('not.be.visible');
+
+ // Add char and assert helptext appears - no publish to save time & has been asserted above & below
+ cy.get('input[name="textbox"]').type('9');
+ cy.get('localize[key="textbox_characters_left"]').contains('characters left').should('exist');
+ cy.get('.property-error').should('not.be.visible');
+
+ // Add char and assert errortext appears and can't save
+ cy.get('input[name="textbox"]').type('10'); // 1 char over max
+ cy.get('localize[key="textbox_characters_exceed"]').contains('too many').should('exist');
+ cy.umbracoButtonByLabelKey('buttons_saveAndPublish').click();
+ cy.get('.property-error').should('be.visible');
+
+ // Clean
+ cy.umbracoEnsureDataTypeNameNotExists(name);
+ cy.umbracoEnsureDocumentTypeNameNotExists(name);
+ })
+
// it('Tests Checkbox List', () => {
// const name = 'CheckBox List';
// const alias = AliasHelper.toAlias(name);
diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Members/memberGroups.js b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Members/memberGroups.js
index be9b93134d..6add16b4ee 100644
--- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Members/memberGroups.js
+++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Members/memberGroups.js
@@ -1,4 +1,4 @@
-context('User Groups', () => {
+context('Member Groups', () => {
beforeEach(() => {
cy.umbracoLogin(Cypress.env('username'), Cypress.env('password'));
From bdfa54af11fbe5c85631455b39e912836e913226 Mon Sep 17 00:00:00 2001
From: Paul Seal
Date: Tue, 5 Oct 2021 08:14:50 +0100
Subject: [PATCH 005/137] Changed the case of BlockList to blocklist as it
breaks on *nix systems (#11219)
Changed the case of `BlockList` to `blocklist` as it breaks on Unix/Linux.
---
src/Umbraco.Web.UI/Views/Partials/blocklist/default.cshtml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI/Views/Partials/blocklist/default.cshtml b/src/Umbraco.Web.UI/Views/Partials/blocklist/default.cshtml
index fffd5e58bb..d5944b93c3 100644
--- a/src/Umbraco.Web.UI/Views/Partials/blocklist/default.cshtml
+++ b/src/Umbraco.Web.UI/Views/Partials/blocklist/default.cshtml
@@ -8,6 +8,6 @@
if (block?.ContentUdi == null) { continue; }
var data = block.Content;
- @await Html.PartialAsync("BlockList/Components/" + data.ContentType.Alias, block)
+ @await Html.PartialAsync("blocklist/Components/" + data.ContentType.Alias, block)
}
From 23d21062773889916fbe2c14f32158dce282e1f1 Mon Sep 17 00:00:00 2001
From: Laura Neto <12862535+lauraneto@users.noreply.github.com>
Date: Tue, 5 Oct 2021 09:39:56 +0200
Subject: [PATCH 006/137] Fixed missing null check in BlockEditorPropertyEditor
(#11184)
Thanks @lauraneto - reviewed this and your fix solves the issue. #h5yr
---
.../PropertyEditors/BlockEditorPropertyEditor.cs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyEditor.cs
index 550a64b14d..93e7d5be50 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/BlockEditorPropertyEditor.cs
@@ -7,7 +7,6 @@ using System.ComponentModel.DataAnnotations;
using System.Linq;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
-using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Blocks;
@@ -264,7 +263,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
_textService.Localize("validation", "entriesShort", new[]
{
validationLimit.Min.ToString(),
- (validationLimit.Min - blockEditorData.Layout.Count()).ToString()
+ (validationLimit.Min - (blockEditorData?.Layout.Count() ?? 0)).ToString()
}),
new[] { "minCount" });
}
From a3744f90deb63fa559d7a1cd0529fa745f84b451 Mon Sep 17 00:00:00 2001
From: Jeavon Leopold
Date: Fri, 1 Oct 2021 16:15:49 +0100
Subject: [PATCH 007/137] Remove all ImageSharp.Web Processors and the re-add
in the correct order
---
.../DependencyInjection/UmbracoBuilder.ImageSharp.cs | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilder.ImageSharp.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilder.ImageSharp.cs
index 62573cfc7b..6755159fc1 100644
--- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilder.ImageSharp.cs
+++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilder.ImageSharp.cs
@@ -54,8 +54,14 @@ namespace Umbraco.Extensions
.Configure(options => options.CacheFolder = builder.BuilderHostingEnvironment.MapPathContentRoot(imagingSettings.Cache.CacheFolder))
// We need to add CropWebProcessor before ResizeWebProcessor (until https://github.com/SixLabors/ImageSharp.Web/issues/182 is fixed)
.RemoveProcessor()
+ .RemoveProcessor()
+ .RemoveProcessor()
+ .RemoveProcessor()
.AddProcessor()
- .AddProcessor();
+ .AddProcessor()
+ .AddProcessor()
+ .AddProcessor()
+ .AddProcessor();
builder.Services.AddTransient, ImageSharpConfigurationOptions>();
From 56c97e1c29bf7d60db87845a6d54868b182a0be6 Mon Sep 17 00:00:00 2001
From: Jason Elkin
Date: Thu, 7 Oct 2021 00:10:44 +0100
Subject: [PATCH 008/137] Add ModelsBuilder unit tests to cover Inheritance and
Composition (#11261)
* Add ModelsBuilder unit tests to cover Inheritance and Composition
* add name to GenerateSimpleType test
---
.../BuilderTests.cs | 388 ++++++++++++++++++
1 file changed, 388 insertions(+)
diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.ModelsBuilder.Embedded/BuilderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.ModelsBuilder.Embedded/BuilderTests.cs
index 4dea81facb..73f38da362 100644
--- a/src/Umbraco.Tests.UnitTests/Umbraco.ModelsBuilder.Embedded/BuilderTests.cs
+++ b/src/Umbraco.Tests.UnitTests/Umbraco.ModelsBuilder.Embedded/BuilderTests.cs
@@ -26,6 +26,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.ModelsBuilder.Embedded
Id = 1,
Alias = "type1",
ClrName = "Type1",
+ Name = "type1Name",
ParentId = 0,
BaseType = null,
ItemType = TypeModel.ItemTypes.Content,
@@ -34,6 +35,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.ModelsBuilder.Embedded
{
Alias = "prop1",
ClrName = "Prop1",
+ Name = "prop1Name",
ModelClrType = typeof(string),
});
@@ -67,6 +69,7 @@ using Umbraco.Extensions;
namespace Umbraco.Cms.Web.Common.PublishedModels
{
+ /// type1Name
[PublishedModel(""type1"")]
public partial class Type1 : PublishedContentModel
{
@@ -97,6 +100,9 @@ namespace Umbraco.Cms.Web.Common.PublishedModels
// properties
+ ///
+ /// prop1Name
+ ///
[global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
[global::System.Diagnostics.CodeAnalysis.MaybeNull]
[ImplementPropertyType(""prop1"")]
@@ -271,6 +277,388 @@ namespace Umbraco.Cms.Web.Common.PublishedModels
Assert.IsTrue(gen.Contains(" global::Umbraco.Cms.Core.Exceptions.BootFailedException Prop3"));
}
+ [Test]
+ public void GenerateInheritedType()
+ {
+ var parentType = new TypeModel
+ {
+ Id = 1,
+ Alias = "parentType",
+ ClrName = "ParentType",
+ Name = "parentTypeName",
+ ParentId = 0,
+ IsParent = true,
+ BaseType = null,
+ ItemType = TypeModel.ItemTypes.Content,
+ };
+ parentType.Properties.Add(new PropertyModel
+ {
+ Alias = "prop1",
+ ClrName = "Prop1",
+ Name = "prop1Name",
+ ModelClrType = typeof(string),
+ });
+
+ var childType = new TypeModel
+ {
+ Id = 2,
+ Alias = "childType",
+ ClrName = "ChildType",
+ Name = "childTypeName",
+ ParentId = 1,
+ BaseType = parentType,
+ ItemType = TypeModel.ItemTypes.Content,
+ };
+
+ TypeModel[] docTypes = new[] { parentType, childType };
+
+ var modelsBuilderConfig = new ModelsBuilderSettings();
+ var builder = new TextBuilder(modelsBuilderConfig, docTypes);
+
+ var sb = new StringBuilder();
+ builder.Generate(sb, builder.GetModelsToGenerate().First());
+ var genParent = sb.ToString();
+
+ SemVersion version = ApiVersion.Current.Version;
+
+ var expectedParent = @"//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Umbraco.ModelsBuilder.Embedded v" + version + @"
+//
+// Changes to this file will be lost if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+using System;
+using System.Linq.Expressions;
+using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.PublishedCache;
+using Umbraco.Cms.Infrastructure.ModelsBuilder;
+using Umbraco.Cms.Core;
+using Umbraco.Extensions;
+
+namespace Umbraco.Cms.Web.Common.PublishedModels
+{
+ /// parentTypeName
+ [PublishedModel(""parentType"")]
+ public partial class ParentType : PublishedContentModel
+ {
+ // helpers
+#pragma warning disable 0109 // new is redundant
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ public new const string ModelTypeAlias = ""parentType"";
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ public new const PublishedItemType ModelItemType = PublishedItemType.Content;
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [return: global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ public new static IPublishedContentType GetModelContentType(IPublishedSnapshotAccessor publishedSnapshotAccessor)
+ => PublishedModelUtility.GetModelContentType(publishedSnapshotAccessor, ModelItemType, ModelTypeAlias);
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [return: global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ public static IPublishedPropertyType GetModelPropertyType(IPublishedSnapshotAccessor publishedSnapshotAccessor, Expression> selector)
+ => PublishedModelUtility.GetModelPropertyType(GetModelContentType(publishedSnapshotAccessor), selector);
+#pragma warning restore 0109
+
+ private IPublishedValueFallback _publishedValueFallback;
+
+ // ctor
+ public ParentType(IPublishedContent content, IPublishedValueFallback publishedValueFallback)
+ : base(content, publishedValueFallback)
+ {
+ _publishedValueFallback = publishedValueFallback;
+ }
+
+ // properties
+
+ ///
+ /// prop1Name
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ [ImplementPropertyType(""prop1"")]
+ public virtual string Prop1 => this.Value(_publishedValueFallback, ""prop1"");
+ }
+}
+";
+ Console.WriteLine(genParent);
+ Assert.AreEqual(expectedParent.ClearLf(), genParent);
+
+ var sb2 = new StringBuilder();
+ builder.Generate(sb2, builder.GetModelsToGenerate().Skip(1).First());
+ var genChild = sb2.ToString();
+
+ var expectedChild = @"//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Umbraco.ModelsBuilder.Embedded v" + version + @"
+//
+// Changes to this file will be lost if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+using System;
+using System.Linq.Expressions;
+using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.PublishedCache;
+using Umbraco.Cms.Infrastructure.ModelsBuilder;
+using Umbraco.Cms.Core;
+using Umbraco.Extensions;
+
+namespace Umbraco.Cms.Web.Common.PublishedModels
+{
+ /// childTypeName
+ [PublishedModel(""childType"")]
+ public partial class ChildType : ParentType
+ {
+ // helpers
+#pragma warning disable 0109 // new is redundant
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ public new const string ModelTypeAlias = ""childType"";
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ public new const PublishedItemType ModelItemType = PublishedItemType.Content;
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [return: global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ public new static IPublishedContentType GetModelContentType(IPublishedSnapshotAccessor publishedSnapshotAccessor)
+ => PublishedModelUtility.GetModelContentType(publishedSnapshotAccessor, ModelItemType, ModelTypeAlias);
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [return: global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ public static IPublishedPropertyType GetModelPropertyType(IPublishedSnapshotAccessor publishedSnapshotAccessor, Expression> selector)
+ => PublishedModelUtility.GetModelPropertyType(GetModelContentType(publishedSnapshotAccessor), selector);
+#pragma warning restore 0109
+
+ private IPublishedValueFallback _publishedValueFallback;
+
+ // ctor
+ public ChildType(IPublishedContent content, IPublishedValueFallback publishedValueFallback)
+ : base(content, publishedValueFallback)
+ {
+ _publishedValueFallback = publishedValueFallback;
+ }
+
+ // properties
+ }
+}
+";
+
+ Console.WriteLine(genChild);
+ Assert.AreEqual(expectedChild.ClearLf(), genChild);
+
+ }
+
+ [Test]
+ public void GenerateComposedType()
+ {
+ // Umbraco returns nice, pascal-cased names.
+ var composition1 = new TypeModel
+ {
+ Id = 2,
+ Alias = "composition1",
+ ClrName = "Composition1",
+ Name = "composition1Name",
+ ParentId = 0,
+ BaseType = null,
+ ItemType = TypeModel.ItemTypes.Content,
+ IsMixin = true,
+ };
+ composition1.Properties.Add(new PropertyModel
+ {
+ Alias = "compositionProp",
+ ClrName = "CompositionProp",
+ Name = "compositionPropName",
+ ModelClrType = typeof(string),
+ ClrTypeName = typeof(string).FullName
+ });
+
+ var type1 = new TypeModel
+ {
+ Id = 1,
+ Alias = "type1",
+ ClrName = "Type1",
+ Name = "type1Name",
+ ParentId = 0,
+ BaseType = null,
+ ItemType = TypeModel.ItemTypes.Content,
+ };
+ type1.Properties.Add(new PropertyModel
+ {
+ Alias = "prop1",
+ ClrName = "Prop1",
+ Name = "prop1Name",
+ ModelClrType = typeof(string),
+ });
+ type1.MixinTypes.Add(composition1);
+
+ TypeModel[] types = new[] { type1, composition1 };
+
+ var modelsBuilderConfig = new ModelsBuilderSettings();
+ var builder = new TextBuilder(modelsBuilderConfig, types);
+
+ SemVersion version = ApiVersion.Current.Version;
+
+ var sb = new StringBuilder();
+ builder.Generate(sb, builder.GetModelsToGenerate().First());
+ var genComposed = sb.ToString();
+
+ var expectedComposed = @"//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Umbraco.ModelsBuilder.Embedded v" + version + @"
+//
+// Changes to this file will be lost if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+using System;
+using System.Linq.Expressions;
+using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.PublishedCache;
+using Umbraco.Cms.Infrastructure.ModelsBuilder;
+using Umbraco.Cms.Core;
+using Umbraco.Extensions;
+
+namespace Umbraco.Cms.Web.Common.PublishedModels
+{
+ /// type1Name
+ [PublishedModel(""type1"")]
+ public partial class Type1 : PublishedContentModel, IComposition1
+ {
+ // helpers
+#pragma warning disable 0109 // new is redundant
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ public new const string ModelTypeAlias = ""type1"";
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ public new const PublishedItemType ModelItemType = PublishedItemType.Content;
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [return: global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ public new static IPublishedContentType GetModelContentType(IPublishedSnapshotAccessor publishedSnapshotAccessor)
+ => PublishedModelUtility.GetModelContentType(publishedSnapshotAccessor, ModelItemType, ModelTypeAlias);
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [return: global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ public static IPublishedPropertyType GetModelPropertyType(IPublishedSnapshotAccessor publishedSnapshotAccessor, Expression> selector)
+ => PublishedModelUtility.GetModelPropertyType(GetModelContentType(publishedSnapshotAccessor), selector);
+#pragma warning restore 0109
+
+ private IPublishedValueFallback _publishedValueFallback;
+
+ // ctor
+ public Type1(IPublishedContent content, IPublishedValueFallback publishedValueFallback)
+ : base(content, publishedValueFallback)
+ {
+ _publishedValueFallback = publishedValueFallback;
+ }
+
+ // properties
+
+ ///
+ /// prop1Name
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ [ImplementPropertyType(""prop1"")]
+ public virtual string Prop1 => this.Value(_publishedValueFallback, ""prop1"");
+
+ ///
+ /// compositionPropName
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ [ImplementPropertyType(""compositionProp"")]
+ public virtual string CompositionProp => global::Umbraco.Cms.Web.Common.PublishedModels.Composition1.GetCompositionProp(this, _publishedValueFallback);
+ }
+}
+";
+ Console.WriteLine(genComposed);
+ Assert.AreEqual(expectedComposed.ClearLf(), genComposed);
+
+ var sb2 = new StringBuilder();
+ builder.Generate(sb2, builder.GetModelsToGenerate().Skip(1).First());
+ var genComposition = sb2.ToString();
+
+ var expectedComposition = @"//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Umbraco.ModelsBuilder.Embedded v" + version + @"
+//
+// Changes to this file will be lost if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+using System;
+using System.Linq.Expressions;
+using Umbraco.Cms.Core.Models.PublishedContent;
+using Umbraco.Cms.Core.PublishedCache;
+using Umbraco.Cms.Infrastructure.ModelsBuilder;
+using Umbraco.Cms.Core;
+using Umbraco.Extensions;
+
+namespace Umbraco.Cms.Web.Common.PublishedModels
+{
+ // Mixin Content Type with alias ""composition1""
+ /// composition1Name
+ public partial interface IComposition1 : IPublishedContent
+ {
+ /// compositionPropName
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ string CompositionProp { get; }
+ }
+
+ /// composition1Name
+ [PublishedModel(""composition1"")]
+ public partial class Composition1 : PublishedContentModel, IComposition1
+ {
+ // helpers
+#pragma warning disable 0109 // new is redundant
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ public new const string ModelTypeAlias = ""composition1"";
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ public new const PublishedItemType ModelItemType = PublishedItemType.Content;
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [return: global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ public new static IPublishedContentType GetModelContentType(IPublishedSnapshotAccessor publishedSnapshotAccessor)
+ => PublishedModelUtility.GetModelContentType(publishedSnapshotAccessor, ModelItemType, ModelTypeAlias);
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [return: global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ public static IPublishedPropertyType GetModelPropertyType(IPublishedSnapshotAccessor publishedSnapshotAccessor, Expression> selector)
+ => PublishedModelUtility.GetModelPropertyType(GetModelContentType(publishedSnapshotAccessor), selector);
+#pragma warning restore 0109
+
+ private IPublishedValueFallback _publishedValueFallback;
+
+ // ctor
+ public Composition1(IPublishedContent content, IPublishedValueFallback publishedValueFallback)
+ : base(content, publishedValueFallback)
+ {
+ _publishedValueFallback = publishedValueFallback;
+ }
+
+ // properties
+
+ ///
+ /// compositionPropName
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ [ImplementPropertyType(""compositionProp"")]
+ public virtual string CompositionProp => GetCompositionProp(this, _publishedValueFallback);
+
+ /// Static getter for compositionPropName
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")]
+ [return: global::System.Diagnostics.CodeAnalysis.MaybeNull]
+ public static string GetCompositionProp(IComposition1 that, IPublishedValueFallback publishedValueFallback) => that.Value(publishedValueFallback, ""compositionProp"");
+ }
+}
+";
+
+ Console.WriteLine(genComposition);
+ Assert.AreEqual(expectedComposition.ClearLf(), genComposition);
+ }
+
[TestCase("int", typeof(int))]
[TestCase("global::System.Collections.Generic.IEnumerable", typeof(IEnumerable))]
[TestCase("global::Umbraco.Cms.Tests.UnitTests.Umbraco.ModelsBuilder.Embedded.BuilderTestsClass1", typeof(BuilderTestsClass1))]
From b74bed380daf42baaa98b7dd07683c885a078101 Mon Sep 17 00:00:00 2001
From: Jesper
Date: Mon, 4 Oct 2021 21:15:21 +0200
Subject: [PATCH 009/137] Add test to update user
---
.../cypress/integration/Users/users.ts | 55 ++++++++++++++++++-
1 file changed, 54 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Users/users.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Users/users.ts
index e122b21564..9a8d59e5b2 100644
--- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Users/users.ts
+++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Users/users.ts
@@ -32,4 +32,57 @@ context('Users', () => {
});
-});
+ it('Update user', () => {
+ // Set userdata
+ const name = "Alice Bobson";
+ const email = "alice-bobson@acceptancetest.umbraco";
+ const startContentIds = [];
+ const startMediaIds = [];
+ const userGroups = ["admin"];
+
+ var userData =
+ {
+ "id": -1,
+ "parentId": -1,
+ "name": name,
+ "username": email,
+ "culture": "en-US",
+ "email": email,
+ "startContentIds": startContentIds,
+ "startMediaIds": startMediaIds,
+ "userGroups": userGroups,
+ "message": ""
+ };
+
+ // Ensure user doesn't exist
+ cy.umbracoEnsureUserEmailNotExists(email);
+
+ // Create user through API
+ cy.getCookie('UMB-XSRF-TOKEN', { log: false }).then((token) => {
+ cy.request({
+ method: 'POST',
+ url: '/umbraco/backoffice/umbracoapi/users/PostCreateUser',
+ followRedirect: true,
+ headers: {
+ Accept: 'application/json',
+ 'X-UMB-XSRF-TOKEN': token.value,
+ },
+ body: userData,
+ log: false,
+ }).then((response) => {
+ return;
+ });
+ });
+
+ // Go to the user and edit their name
+ cy.umbracoSection('users');
+ cy.get('.umb-user-card__name').contains(name).click();
+ cy.get('#headerName').type('{movetoend}son');
+ cy.umbracoButtonByLabelKey('buttons_save').click();
+
+ // assert save succeeds
+ cy.umbracoSuccessNotification().should('be.visible');
+ cy.umbracoEnsureUserEmailNotExists(email);
+ })
+
+});
\ No newline at end of file
From 5801ba4b8140aaae93ff3a69117a19a6409e2c6e Mon Sep 17 00:00:00 2001
From: Matthew Care
Date: Thu, 7 Oct 2021 21:05:43 +0100
Subject: [PATCH 010/137] Add Default View Content Provider
Add the ability to register your own content provider, so that you can change the content which is injeted into new templates
Obsolete old static method
Register new interfaces / classes (hopefully in the correct buidler)
---
.../IO/DefaultViewContentProvider.cs | 62 +++++++++++++++
.../IO/IDefaultViewContentProvider.cs | 8 ++
src/Umbraco.Core/IO/IViewHelper.cs | 13 ++++
src/Umbraco.Core/IO/ViewHelper.cs | 76 ++++---------------
.../UmbracoBuilder.FileSystems.cs | 3 +
.../Implement/TemplateRepository.cs | 6 +-
.../Controllers/TemplateController.cs | 7 +-
.../ModelsBuilderNotificationHandler.cs | 6 +-
8 files changed, 113 insertions(+), 68 deletions(-)
create mode 100644 src/Umbraco.Core/IO/DefaultViewContentProvider.cs
create mode 100644 src/Umbraco.Core/IO/IDefaultViewContentProvider.cs
create mode 100644 src/Umbraco.Core/IO/IViewHelper.cs
diff --git a/src/Umbraco.Core/IO/DefaultViewContentProvider.cs b/src/Umbraco.Core/IO/DefaultViewContentProvider.cs
new file mode 100644
index 0000000000..7c42255971
--- /dev/null
+++ b/src/Umbraco.Core/IO/DefaultViewContentProvider.cs
@@ -0,0 +1,62 @@
+using System.Text;
+using Umbraco.Extensions;
+
+namespace Umbraco.Cms.Core.IO
+{
+ public class DefaultViewContentProvider : IDefaultViewContentProvider
+ {
+ public string GetDefaultFileContent(string layoutPageAlias = null, string modelClassName = null, string modelNamespace = null, string modelNamespaceAlias = null)
+ {
+ var content = new StringBuilder();
+
+ if (string.IsNullOrWhiteSpace(modelNamespaceAlias))
+ modelNamespaceAlias = "ContentModels";
+
+ // either
+ // @inherits Umbraco.Web.Mvc.UmbracoViewPage
+ // @inherits Umbraco.Web.Mvc.UmbracoViewPage
+ content.AppendLine("@using Umbraco.Cms.Web.Common.PublishedModels;");
+ content.Append("@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage");
+ if (modelClassName.IsNullOrWhiteSpace() == false)
+ {
+ content.Append("<");
+ if (modelNamespace.IsNullOrWhiteSpace() == false)
+ {
+ content.Append(modelNamespaceAlias);
+ content.Append(".");
+ }
+ content.Append(modelClassName);
+ content.Append(">");
+ }
+ content.Append("\r\n");
+
+ // if required, add
+ // @using ContentModels = ModelNamespace;
+ if (modelClassName.IsNullOrWhiteSpace() == false && modelNamespace.IsNullOrWhiteSpace() == false)
+ {
+ content.Append("@using ");
+ content.Append(modelNamespaceAlias);
+ content.Append(" = ");
+ content.Append(modelNamespace);
+ content.Append(";\r\n");
+ }
+
+ // either
+ // Layout = null;
+ // Layout = "layoutPage.cshtml";
+ content.Append("@{\r\n\tLayout = ");
+ if (layoutPageAlias.IsNullOrWhiteSpace())
+ {
+ content.Append("null");
+ }
+ else
+ {
+ content.Append("\"");
+ content.Append(layoutPageAlias);
+ content.Append(".cshtml\"");
+ }
+ content.Append(";\r\n}");
+ return content.ToString();
+ }
+ }
+}
diff --git a/src/Umbraco.Core/IO/IDefaultViewContentProvider.cs b/src/Umbraco.Core/IO/IDefaultViewContentProvider.cs
new file mode 100644
index 0000000000..8c1a775d7c
--- /dev/null
+++ b/src/Umbraco.Core/IO/IDefaultViewContentProvider.cs
@@ -0,0 +1,8 @@
+namespace Umbraco.Cms.Core.IO
+{
+ public interface IDefaultViewContentProvider
+ {
+ string GetDefaultFileContent(string layoutPageAlias = null, string modelClassName = null,
+ string modelNamespace = null, string modelNamespaceAlias = null);
+ }
+}
diff --git a/src/Umbraco.Core/IO/IViewHelper.cs b/src/Umbraco.Core/IO/IViewHelper.cs
new file mode 100644
index 0000000000..d53dcbf2b9
--- /dev/null
+++ b/src/Umbraco.Core/IO/IViewHelper.cs
@@ -0,0 +1,13 @@
+using Umbraco.Cms.Core.Models;
+
+namespace Umbraco.Cms.Core.IO
+{
+ public interface IViewHelper
+ {
+ bool ViewExists(ITemplate t);
+ string GetFileContents(ITemplate t);
+ string CreateView(ITemplate t, bool overWrite = false);
+ string UpdateViewFile(ITemplate t, string currentAlias = null);
+ string ViewPath(string alias);
+ }
+}
diff --git a/src/Umbraco.Core/IO/ViewHelper.cs b/src/Umbraco.Core/IO/ViewHelper.cs
index 258c4a7f64..11d40e4862 100644
--- a/src/Umbraco.Core/IO/ViewHelper.cs
+++ b/src/Umbraco.Core/IO/ViewHelper.cs
@@ -7,20 +7,19 @@ using Umbraco.Extensions;
namespace Umbraco.Cms.Core.IO
{
- public class ViewHelper
+ public class ViewHelper : IViewHelper
{
private readonly IFileSystem _viewFileSystem;
+ private readonly IDefaultViewContentProvider _defaultViewContentProvider;
- public ViewHelper(IFileSystem viewFileSystem)
+ public ViewHelper(FileSystems fileSystems, IDefaultViewContentProvider defaultViewContentProvider)
{
- if (viewFileSystem == null) throw new ArgumentNullException(nameof(viewFileSystem));
- _viewFileSystem = viewFileSystem;
+ _viewFileSystem = fileSystems.MvcViewsFileSystem ?? throw new ArgumentNullException(nameof(fileSystems));
+ _defaultViewContentProvider = defaultViewContentProvider ?? throw new ArgumentNullException(nameof(defaultViewContentProvider));
}
- internal bool ViewExists(ITemplate t)
- {
- return _viewFileSystem.FileExists(ViewPath(t.Alias));
- }
+ public bool ViewExists(ITemplate t) => _viewFileSystem.FileExists(ViewPath(t.Alias));
+
public string GetFileContents(ITemplate t)
{
@@ -60,58 +59,13 @@ namespace Umbraco.Cms.Core.IO
return viewContent;
}
- public static string GetDefaultFileContent(string layoutPageAlias = null, string modelClassName = null, string modelNamespace = null, string modelNamespaceAlias = null)
+ [Obsolete("Inject IDefaultViewContentProvider instead")]
+ public static string GetDefaultFileContent(string layoutPageAlias = null, string modelClassName = null,
+ string modelNamespace = null, string modelNamespaceAlias = null)
{
- var content = new StringBuilder();
-
- if (string.IsNullOrWhiteSpace(modelNamespaceAlias))
- modelNamespaceAlias = "ContentModels";
-
- // either
- // @inherits Umbraco.Web.Mvc.UmbracoViewPage
- // @inherits Umbraco.Web.Mvc.UmbracoViewPage
- content.AppendLine("@using Umbraco.Cms.Web.Common.PublishedModels;");
- content.Append("@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage");
- if (modelClassName.IsNullOrWhiteSpace() == false)
- {
- content.Append("<");
- if (modelNamespace.IsNullOrWhiteSpace() == false)
- {
- content.Append(modelNamespaceAlias);
- content.Append(".");
- }
- content.Append(modelClassName);
- content.Append(">");
- }
- content.Append("\r\n");
-
- // if required, add
- // @using ContentModels = ModelNamespace;
- if (modelClassName.IsNullOrWhiteSpace() == false && modelNamespace.IsNullOrWhiteSpace() == false)
- {
- content.Append("@using ");
- content.Append(modelNamespaceAlias);
- content.Append(" = ");
- content.Append(modelNamespace);
- content.Append(";\r\n");
- }
-
- // either
- // Layout = null;
- // Layout = "layoutPage.cshtml";
- content.Append("@{\r\n\tLayout = ");
- if (layoutPageAlias.IsNullOrWhiteSpace())
- {
- content.Append("null");
- }
- else
- {
- content.Append("\"");
- content.Append(layoutPageAlias);
- content.Append(".cshtml\"");
- }
- content.Append(";\r\n}");
- return content.ToString();
+ var viewContentProvider = new DefaultViewContentProvider();
+ return viewContentProvider.GetDefaultFileContent(layoutPageAlias, modelClassName, modelNamespace,
+ modelNamespaceAlias);
}
private string SaveTemplateToFile(ITemplate template)
@@ -157,12 +111,12 @@ namespace Umbraco.Cms.Core.IO
return _viewFileSystem.GetRelativePath(alias.Replace(" ", "") + ".cshtml");
}
- private static string EnsureInheritedLayout(ITemplate template)
+ private string EnsureInheritedLayout(ITemplate template)
{
var design = template.Content;
if (string.IsNullOrEmpty(design))
- design = GetDefaultFileContent(template.MasterTemplateAlias);
+ design = _defaultViewContentProvider.GetDefaultFileContent(template.MasterTemplateAlias);
return design;
}
diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.FileSystems.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.FileSystems.cs
index edb8033f3d..6582cfb0c6 100644
--- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.FileSystems.cs
+++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.FileSystems.cs
@@ -39,6 +39,9 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
// register the scheme for media paths
builder.Services.AddUnique();
+ builder.Services.AddUnique();
+ builder.Services.AddUnique();
+
builder.SetMediaFileSystem(factory =>
{
IIOHelper ioHelper = factory.GetRequiredService();
diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TemplateRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TemplateRepository.cs
index b0cabe5312..52ecd1f779 100644
--- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TemplateRepository.cs
+++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TemplateRepository.cs
@@ -29,15 +29,15 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
private readonly IIOHelper _ioHelper;
private readonly IShortStringHelper _shortStringHelper;
private readonly IFileSystem _viewsFileSystem;
- private readonly ViewHelper _viewHelper;
+ private readonly IViewHelper _viewHelper;
- public TemplateRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, FileSystems fileSystems, IIOHelper ioHelper, IShortStringHelper shortStringHelper)
+ public TemplateRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, FileSystems fileSystems, IIOHelper ioHelper, IShortStringHelper shortStringHelper, IViewHelper viewHelper)
: base(scopeAccessor, cache, logger)
{
_ioHelper = ioHelper;
_shortStringHelper = shortStringHelper;
_viewsFileSystem = fileSystems.MvcViewsFileSystem;
- _viewHelper = new ViewHelper(_viewsFileSystem);
+ _viewHelper = viewHelper;
}
protected override IRepositoryCachePolicy CreateCachePolicy() =>
diff --git a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
index 0a800693f8..a5b33b5d04 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
@@ -24,15 +24,18 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
private readonly IFileService _fileService;
private readonly IUmbracoMapper _umbracoMapper;
private readonly IShortStringHelper _shortStringHelper;
+ private readonly IDefaultViewContentProvider _defaultViewContentProvider;
public TemplateController(
IFileService fileService,
IUmbracoMapper umbracoMapper,
- IShortStringHelper shortStringHelper)
+ IShortStringHelper shortStringHelper,
+ IDefaultViewContentProvider defaultViewContentProvider)
{
_fileService = fileService ?? throw new ArgumentNullException(nameof(fileService));
_umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper));
_shortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper));
+ _defaultViewContentProvider = defaultViewContentProvider ?? throw new ArgumentNullException(nameof(defaultViewContentProvider));
}
///
@@ -136,7 +139,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
}
}
- var content = ViewHelper.GetDefaultFileContent( layoutPageAlias: dt.MasterTemplateAlias );
+ var content = _defaultViewContentProvider.GetDefaultFileContent( layoutPageAlias: dt.MasterTemplateAlias );
var scaffold = _umbracoMapper.Map(dt);
scaffold.Content = content + "\r\n\r\n@* the fun starts here *@\r\n\r\n";
diff --git a/src/Umbraco.Web.Common/ModelsBuilder/ModelsBuilderNotificationHandler.cs b/src/Umbraco.Web.Common/ModelsBuilder/ModelsBuilderNotificationHandler.cs
index 90a48c4017..ea8408b212 100644
--- a/src/Umbraco.Web.Common/ModelsBuilder/ModelsBuilderNotificationHandler.cs
+++ b/src/Umbraco.Web.Common/ModelsBuilder/ModelsBuilderNotificationHandler.cs
@@ -26,15 +26,17 @@ namespace Umbraco.Cms.Web.Common.ModelsBuilder
private readonly ModelsBuilderSettings _config;
private readonly IShortStringHelper _shortStringHelper;
private readonly IModelsBuilderDashboardProvider _modelsBuilderDashboardProvider;
+ private readonly IDefaultViewContentProvider _defaultViewContentProvider;
public ModelsBuilderNotificationHandler(
IOptions config,
IShortStringHelper shortStringHelper,
- IModelsBuilderDashboardProvider modelsBuilderDashboardProvider)
+ IModelsBuilderDashboardProvider modelsBuilderDashboardProvider, IDefaultViewContentProvider defaultViewContentProvider)
{
_config = config.Value;
_shortStringHelper = shortStringHelper;
_modelsBuilderDashboardProvider = modelsBuilderDashboardProvider;
+ _defaultViewContentProvider = defaultViewContentProvider;
}
///
@@ -123,7 +125,7 @@ namespace Umbraco.Cms.Web.Common.ModelsBuilder
// we do not support configuring this at the moment, so just let Umbraco use its default value
// var modelNamespaceAlias = ...;
- var markup = ViewHelper.GetDefaultFileContent(
+ var markup = _defaultViewContentProvider.GetDefaultFileContent(
modelClassName: className,
modelNamespace: modelNamespace/*,
modelNamespaceAlias: modelNamespaceAlias*/);
From dc536b011bec0caba05c2535690f5eae6c805261 Mon Sep 17 00:00:00 2001
From: Matthew Care
Date: Thu, 7 Oct 2021 21:06:39 +0100
Subject: [PATCH 011/137] Add Umbraco Builder unique
Follow the convention of having a method on IUmbracoBuilder which allows you to set a custom content provider
---
.../DependencyInjection/UmbracoBuilder.Uniques.cs | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Uniques.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Uniques.cs
index b311b1f0da..e3839e152b 100644
--- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Uniques.cs
+++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Uniques.cs
@@ -27,6 +27,19 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
return builder;
}
+ ///
+ /// Sets the default view content provider
+ ///
+ /// The type of the provider.
+ /// The builder.
+ ///
+ public static IUmbracoBuilder SetDefaultViewContentProvider(this IUmbracoBuilder builder)
+ where T : class, IDefaultViewContentProvider
+ {
+ builder.Services.AddUnique();
+ return builder;
+ }
+
///
/// Sets the culture dictionary factory.
///
From 44c25cd016fffc1f8b42b438ec835f7f52ef4f1b Mon Sep 17 00:00:00 2001
From: Matthew Care
Date: Thu, 7 Oct 2021 21:08:35 +0100
Subject: [PATCH 012/137] Update tests
Fix all of the unit / integration tests
Update integration tests to remove references to ViewHelper, to make the tests more focused on what they should be testing
---
.../Repositories/ContentTypeRepositoryTest.cs | 3 ++-
.../Repositories/DocumentRepositoryTest.cs | 2 +-
.../Repositories/TemplateRepositoryTest.cs | 25 +++++++++----------
....cs => DefaultViewContentProviderTests.cs} | 18 +++++++------
4 files changed, 25 insertions(+), 23 deletions(-)
rename src/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/{ViewHelperTests.cs => DefaultViewContentProviderTests.cs} (71%)
diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs
index dfe799e2b8..de1a5d3fb5 100644
--- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs
+++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Logging;
+using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.IO;
@@ -73,7 +74,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repos
IScopeProvider provider = ScopeProvider;
using (IScope scope = provider.CreateScope())
{
- var templateRepo = new TemplateRepository((IScopeAccessor)provider, AppCaches.Disabled, LoggerFactory.CreateLogger(), FileSystems, IOHelper, ShortStringHelper);
+ var templateRepo = new TemplateRepository((IScopeAccessor)provider, AppCaches.Disabled, LoggerFactory.CreateLogger(), FileSystems, IOHelper, ShortStringHelper, Mock.Of());
ContentTypeRepository repository = ContentTypeRepository;
Template[] templates = new[]
{
diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/DocumentRepositoryTest.cs
index a7e1641839..7207718071 100644
--- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/DocumentRepositoryTest.cs
+++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/DocumentRepositoryTest.cs
@@ -114,7 +114,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repos
appCaches ??= AppCaches;
- templateRepository = new TemplateRepository(scopeAccessor, appCaches, LoggerFactory.CreateLogger(), FileSystems, IOHelper, ShortStringHelper);
+ templateRepository = new TemplateRepository(scopeAccessor, appCaches, LoggerFactory.CreateLogger(), FileSystems, IOHelper, ShortStringHelper, Mock.Of());
var tagRepository = new TagRepository(scopeAccessor, appCaches, LoggerFactory.CreateLogger());
var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, appCaches, ShortStringHelper);
var languageRepository = new LanguageRepository(scopeAccessor, appCaches, LoggerFactory.CreateLogger(), globalSettings);
diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/TemplateRepositoryTest.cs
index d137ef8d05..80eb61d21f 100644
--- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/TemplateRepositoryTest.cs
+++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/TemplateRepositoryTest.cs
@@ -38,10 +38,11 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repos
private IHostingEnvironment HostingEnvironment => GetRequiredService();
private FileSystems FileSystems => GetRequiredService();
+ private IViewHelper ViewHelper => GetRequiredService();
private ITemplateRepository CreateRepository(IScopeProvider provider) =>
- new TemplateRepository((IScopeAccessor)provider, AppCaches.Disabled, LoggerFactory.CreateLogger(), FileSystems, IOHelper, ShortStringHelper);
-
+ new TemplateRepository((IScopeAccessor)provider, AppCaches.Disabled, LoggerFactory.CreateLogger(), FileSystems, IOHelper, ShortStringHelper, ViewHelper);
+
[Test]
public void Can_Instantiate_Repository()
{
@@ -90,16 +91,14 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repos
// Act
var template = new Template(ShortStringHelper, "test", "test")
{
- Content = ViewHelper.GetDefaultFileContent()
+ Content = "mock-content"
};
repository.Save(template);
// Assert
Assert.That(repository.Get("test"), Is.Not.Null);
Assert.That(FileSystems.MvcViewsFileSystem.FileExists("test.cshtml"), Is.True);
- Assert.AreEqual(
- @"@usingUmbraco.Cms.Web.Common.PublishedModels;@inheritsUmbraco.Cms.Web.Common.Views.UmbracoViewPage@{Layout=null;}".StripWhitespace(),
- template.Content.StripWhitespace());
+ Assert.AreEqual("mock-content", template.Content.StripWhitespace());
}
}
@@ -144,13 +143,13 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repos
// Act
var template = new Template(ShortStringHelper, "test", "test")
{
- Content = ViewHelper.GetDefaultFileContent()
+ Content = "mock-content"
};
repository.Save(template);
var template2 = new Template(ShortStringHelper, "test", "test")
{
- Content = ViewHelper.GetDefaultFileContent()
+ Content = "mock-content"
};
repository.Save(template2);
@@ -172,13 +171,13 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repos
// Act
var template = new Template(ShortStringHelper, "test", "test")
{
- Content = ViewHelper.GetDefaultFileContent()
+ Content = "mock-content"
};
repository.Save(template);
var template2 = new Template(ShortStringHelper, "test1", "test1")
{
- Content = ViewHelper.GetDefaultFileContent()
+ Content = "mock-content"
};
repository.Save(template2);
@@ -205,7 +204,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repos
// Act
var template = new Template(ShortStringHelper, "test", "test")
{
- Content = ViewHelper.GetDefaultFileContent()
+ Content = "mock-content"
};
repository.Save(template);
@@ -216,7 +215,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repos
// Assert
Assert.That(FileSystems.MvcViewsFileSystem.FileExists("test.cshtml"), Is.True);
- Assert.That(updated.Content, Is.EqualTo(ViewHelper.GetDefaultFileContent() + ""));
+ Assert.That(updated.Content, Is.EqualTo("mock-content" + ""));
}
}
@@ -232,7 +231,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repos
var template = new Template(ShortStringHelper, "test", "test")
{
- Content = ViewHelper.GetDefaultFileContent()
+ Content = "mock-content"
};
repository.Save(template);
diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/ViewHelperTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/DefaultViewContentProviderTests.cs
similarity index 71%
rename from src/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/ViewHelperTests.cs
rename to src/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/DefaultViewContentProviderTests.cs
index 446659467b..d43d88f001 100644
--- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/ViewHelperTests.cs
+++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Templates/DefaultViewContentProviderTests.cs
@@ -7,12 +7,14 @@ using Umbraco.Cms.Core.IO;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Templates
{
[TestFixture]
- public class ViewHelperTests
+ public class DefaultViewContentProviderTests
{
+ private IDefaultViewContentProvider DefaultViewContentProvider => new DefaultViewContentProvider();
+
[Test]
public void NoOptions()
{
- var view = ViewHelper.GetDefaultFileContent();
+ var view = DefaultViewContentProvider.GetDefaultFileContent();
Assert.AreEqual(
FixView(@"@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@@ -24,7 +26,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Templates
[Test]
public void Layout()
{
- var view = ViewHelper.GetDefaultFileContent(layoutPageAlias: "Dharznoik");
+ var view = DefaultViewContentProvider.GetDefaultFileContent(layoutPageAlias: "Dharznoik");
Assert.AreEqual(
FixView(@"@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@@ -36,7 +38,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Templates
[Test]
public void ClassName()
{
- var view = ViewHelper.GetDefaultFileContent(modelClassName: "ClassName");
+ var view = DefaultViewContentProvider.GetDefaultFileContent(modelClassName: "ClassName");
Assert.AreEqual(
FixView(@"@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@@ -48,7 +50,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Templates
[Test]
public void Namespace()
{
- var view = ViewHelper.GetDefaultFileContent(modelNamespace: "Models");
+ var view = DefaultViewContentProvider.GetDefaultFileContent(modelNamespace: "Models");
Assert.AreEqual(
FixView(@"@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@@ -60,7 +62,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Templates
[Test]
public void ClassNameAndNamespace()
{
- var view = ViewHelper.GetDefaultFileContent(modelClassName: "ClassName", modelNamespace: "My.Models");
+ var view = DefaultViewContentProvider.GetDefaultFileContent(modelClassName: "ClassName", modelNamespace: "My.Models");
Assert.AreEqual(
FixView(@"@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@@ -73,7 +75,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Templates
[Test]
public void ClassNameAndNamespaceAndAlias()
{
- var view = ViewHelper.GetDefaultFileContent(modelClassName: "ClassName", modelNamespace: "My.Models", modelNamespaceAlias: "MyModels");
+ var view = DefaultViewContentProvider.GetDefaultFileContent(modelClassName: "ClassName", modelNamespace: "My.Models", modelNamespaceAlias: "MyModels");
Assert.AreEqual(
FixView(@"@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@@ -86,7 +88,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Templates
[Test]
public void Combined()
{
- var view = ViewHelper.GetDefaultFileContent(layoutPageAlias: "Dharznoik", modelClassName: "ClassName", modelNamespace: "My.Models", modelNamespaceAlias: "MyModels");
+ var view = DefaultViewContentProvider.GetDefaultFileContent(layoutPageAlias: "Dharznoik", modelClassName: "ClassName", modelNamespace: "My.Models", modelNamespaceAlias: "MyModels");
Assert.AreEqual(
FixView(@"@using Umbraco.Cms.Web.Common.PublishedModels;
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
From 8dfec54b2ae0f6d02d913ac54d36642cbb7f11d0 Mon Sep 17 00:00:00 2001
From: Matthew Care
Date: Thu, 7 Oct 2021 21:09:14 +0100
Subject: [PATCH 013/137] Remove string
Remove a string that gets appended to the default file content.
---
src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
index a5b33b5d04..46a770428e 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs
@@ -142,7 +142,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers
var content = _defaultViewContentProvider.GetDefaultFileContent( layoutPageAlias: dt.MasterTemplateAlias );
var scaffold = _umbracoMapper.Map(dt);
- scaffold.Content = content + "\r\n\r\n@* the fun starts here *@\r\n\r\n";
+ scaffold.Content = content;
return scaffold;
}
From 4456bf4a3bedcef0fe7a804d707c2a4df2ecece9 Mon Sep 17 00:00:00 2001
From: Matthew Care
Date: Fri, 8 Oct 2021 11:33:39 +0100
Subject: [PATCH 014/137] Re-add original ctor
Add original ctor in case someone was using it, else this would be a breaking change
---
src/Umbraco.Core/IO/ViewHelper.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/Umbraco.Core/IO/ViewHelper.cs b/src/Umbraco.Core/IO/ViewHelper.cs
index 11d40e4862..80ff48a943 100644
--- a/src/Umbraco.Core/IO/ViewHelper.cs
+++ b/src/Umbraco.Core/IO/ViewHelper.cs
@@ -12,6 +12,9 @@ namespace Umbraco.Cms.Core.IO
private readonly IFileSystem _viewFileSystem;
private readonly IDefaultViewContentProvider _defaultViewContentProvider;
+ [Obsolete("Inject IViewHelper instead")]
+ public ViewHelper(IFileSystem viewFileSystem) => _viewFileSystem = viewFileSystem ?? throw new ArgumentNullException(nameof(viewFileSystem));
+
public ViewHelper(FileSystems fileSystems, IDefaultViewContentProvider defaultViewContentProvider)
{
_viewFileSystem = fileSystems.MvcViewsFileSystem ?? throw new ArgumentNullException(nameof(fileSystems));
From e7da8558e55fe297e7156691a79a87df2d211ea4 Mon Sep 17 00:00:00 2001
From: Louis JR <17555062+louisjrdev@users.noreply.github.com>
Date: Sat, 9 Oct 2021 02:30:58 +0100
Subject: [PATCH 015/137] Added support for Smtp PickupDirectory (#11253)
* Added support for Smtp PickupDirectory
* Add reference to the implementation outline by MailKit
Co-authored-by: Bjarke Berg
Co-authored-by: Bjarke Berg
---
.../Mail/EmailSender.cs | 51 ++++++++++++++++++-
1 file changed, 50 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Infrastructure/Mail/EmailSender.cs b/src/Umbraco.Infrastructure/Mail/EmailSender.cs
index e5fbde2aac..4ca3506fa9 100644
--- a/src/Umbraco.Infrastructure/Mail/EmailSender.cs
+++ b/src/Umbraco.Infrastructure/Mail/EmailSender.cs
@@ -1,10 +1,15 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
+using System;
+using System.IO;
using System.Net.Mail;
using System.Threading.Tasks;
+using MailKit.Net.Smtp;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
+using MimeKit;
+using MimeKit.IO;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Mail;
@@ -70,12 +75,56 @@ namespace Umbraco.Cms.Infrastructure.Mail
}
}
- if (_globalSettings.IsSmtpServerConfigured == false)
+ var isPickupDirectoryConfigured = !string.IsNullOrWhiteSpace(_globalSettings.Smtp?.PickupDirectoryLocation);
+
+ if (_globalSettings.IsSmtpServerConfigured == false && !isPickupDirectoryConfigured)
{
_logger.LogDebug("Could not send email for {Subject}. It was not handled by a notification handler and there is no SMTP configured.", message.Subject);
return;
}
+ if (isPickupDirectoryConfigured && !string.IsNullOrWhiteSpace(_globalSettings.Smtp?.From))
+ {
+ // The following code snippet is the recommended way to handle PickupDirectoryLocation.
+ // See more https://github.com/jstedfast/MailKit/blob/master/FAQ.md#q-how-can-i-send-email-to-a-specifiedpickupdirectory
+ do {
+ var path = Path.Combine(_globalSettings.Smtp?.PickupDirectoryLocation, Guid.NewGuid () + ".eml");
+ Stream stream;
+
+ try
+ {
+ stream = File.Open(path, FileMode.CreateNew);
+ }
+ catch (IOException)
+ {
+ if (File.Exists(path))
+ {
+ continue;
+ }
+ throw;
+ }
+
+ try {
+ using (stream)
+ {
+ using var filtered = new FilteredStream(stream);
+ filtered.Add(new SmtpDataFilter());
+
+ FormatOptions options = FormatOptions.Default.Clone();
+ options.NewLineFormat = NewLineFormat.Dos;
+
+ await message.ToMimeMessage(_globalSettings.Smtp?.From).WriteToAsync(options, filtered);
+ filtered.Flush();
+ return;
+
+ }
+ } catch {
+ File.Delete(path);
+ throw;
+ }
+ } while (true);
+ }
+
using var client = new SmtpClient();
await client.ConnectAsync(_globalSettings.Smtp.Host,
From bea143fa9640a1845774d6cb5adef503880f0e45 Mon Sep 17 00:00:00 2001
From: Jose Marcenaro
Date: Fri, 1 Oct 2021 10:40:28 -0300
Subject: [PATCH 016/137] Allow local API when using AspNetCore identity
---
.../Authorization/FeatureAuthorizeHandler.cs | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/Umbraco.Web.Common/Authorization/FeatureAuthorizeHandler.cs b/src/Umbraco.Web.Common/Authorization/FeatureAuthorizeHandler.cs
index 0a4981d6c6..283accb085 100644
--- a/src/Umbraco.Web.Common/Authorization/FeatureAuthorizeHandler.cs
+++ b/src/Umbraco.Web.Common/Authorization/FeatureAuthorizeHandler.cs
@@ -47,6 +47,13 @@ namespace Umbraco.Cms.Web.Common.Authorization
break;
}
+ case Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext authorizationFilterContext:
+ {
+ IEndpointFeature endpointFeature = authorizationFilterContext.HttpContext.Features.Get();
+ endpoint = endpointFeature.Endpoint;
+ break;
+ }
+
case Endpoint resourceEndpoint:
{
endpoint = resourceEndpoint;
From 9f72b7b7102dee55f8d94a66895ae0d711b5c35e Mon Sep 17 00:00:00 2001
From: Louis JR <17555062+louisjrdev@users.noreply.github.com>
Date: Sun, 10 Oct 2021 13:32:27 +0100
Subject: [PATCH 017/137] Change references of Web.config to be
appsettings.json (#11244)
---
src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 26 +++++++++----------
.../umbraco/config/lang/en_us.xml | 25 +++++++++---------
2 files changed, 25 insertions(+), 26 deletions(-)
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
index dbb8a7a6b6..27137c0a5e 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
@@ -811,7 +811,7 @@
The installer cannot connect to the database.
- Could not save the web.config file. Please modify the connection string manually.
+ Could not save the appsettings.json file. Please modify the connection string manually.
Your database has been found and is identified as
Database configuration
@@ -820,12 +820,12 @@
]]>
Next to proceed.]]>
- Database not found! Please check that the information in the "connection string" of the "web.config" file is correct.
- To proceed, please edit the "web.config" file (using Visual Studio or your favourite text editor), scroll to the bottom, add the connection string for your database in the key named "UmbracoDbDSN" and save the file.
+ Database not found! Please check that the information in the "ConnectionStrings" property of the "appsettings.json" file is correct.
+ To proceed, please edit the "appsettings.json" file (using Visual Studio or your favourite text editor), add the connection string for your database in the key named "umbracoDbDSN" and save the file.
Click the retry button when
- done.
- More information on editing web.config here.
]]>
+ done.
+ More information on editing appsettings.json here.]]>
Please contact your ISP if necessary.
If you're installing on a local machine or server you might need information from your system administrator.]]>
@@ -844,7 +844,7 @@
The Default user's password has been successfully changed since the installation!No further actions needs to be taken. Click Next to proceed.]]>
The password is changed!
Get a great start, watch our introduction videos
- By clicking the next button (or modifying the umbracoConfigurationStatus in web.config), you accept the license for this software as specified in the box below. Notice that this Umbraco distribution consists of two different licenses, the open source MIT license for the framework and the Umbraco freeware license that covers the UI.
+ By clicking the next button, you accept the license for this software as specified in the box below. Notice that this Umbraco distribution consists of two different licenses, the open source MIT license for the framework and the Umbraco freeware license that covers the UI.
Not installed yet.
Affected files and folders
More information on setting up permissions for Umbraco here
@@ -907,8 +907,8 @@ You installed Runway, so why not see how your new website looks.]]>
Further help and information
Get help from our award winning community, browse the documentation or watch some free videos on how to build a simple site, how to use packages and a quick guide to the Umbraco terminology]]>
Umbraco %0% is installed and ready for use
- /web.config file and update the AppSetting key UmbracoConfigurationStatus in the bottom to the value of '%0%'.]]>
+
+
started instantly by clicking the "Launch Umbraco" button below.
If you are new to Umbraco,
you can find plenty of resources on our getting started pages.]]>
Launch Umbraco
@@ -2044,8 +2044,8 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
Your website's SSL certificate is expiring in %0% days.
Error pinging the URL %0% - '%1%'
You are currently %0% viewing the site using the HTTPS scheme.
- The appSetting 'Umbraco.Core.UseHttps' is set to 'false' in your web.config file. Once you access this site using the HTTPS scheme, that should be set to 'true'.
- The appSetting 'Umbraco.Core.UseHttps' is set to '%0%' in your web.config file, your cookies are %1% marked as secure.
+ The appSetting 'Umbraco:CMS:Global:UseHttps' is set to 'false' in your appsettings.json file. Once you access this site using the HTTPS scheme, that should be set to 'true'.
+ The appSetting 'Umbraco:CMS:Global:UseHttps' is set to '%0%' in your appsettings.json file, your cookies are %1% marked as secure.
Debug compilation mode is disabled.
Debug compilation mode is currently enabled. It is recommended to disable this setting before go live.
@@ -2071,10 +2071,10 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
-->
%0%.]]>
No headers revealing information about the website technology were found.
- In the Web.config file, system.net/mailsettings could not be found.
- In the Web.config file system.net/mailsettings section, the host is not configured.
+ In the appsettings.json file, Umbraco:CMS:Global:Smtp could not be found.
+ In the appsettings.json file Umbraco:CMS:Global:Smtp section, the host is not configured.
SMTP settings are configured correctly and the service is operating as expected.
- The SMTP server configured with host '%0%' and port '%1%' could not be reached. Please check to ensure the SMTP settings in the Web.config file system.net/mailsettings are correct.
+ The SMTP server configured with host '%0%' and port '%1%' could not be reached. Please check to ensure the SMTP settings in the appsettings.json file Umbraco:CMS:Global:Smtp are correct.
%0%.]]>
%0%.]]>
Results of the scheduled Umbraco Health Checks run on %0% at %1% are as follows:
%2%