Merge remote-tracking branch 'origin/temp8-MOAR-LOGGING' into temp8-logviewer

This commit is contained in:
Warren Buckley
2018-09-10 10:31:16 +01:00
293 changed files with 5396 additions and 4248 deletions
+7 -1
View File
@@ -27,4 +27,10 @@ dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
dotnet_naming_style.prefix_underscore.capitalization = camel_case
dotnet_naming_style.prefix_underscore.required_prefix = _
dotnet_naming_style.prefix_underscore.required_prefix = _
# https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/ide/editorconfig-code-style-settings-reference.md
[*.cs]
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = true:suggestion
View File
View File
@@ -129,7 +129,7 @@ We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-fl
The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 (version 15.3 or higher, [the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
![Gulp build in Visual Studio](img/gulpbuild.png)
@@ -156,4 +156,4 @@ git rebase upstream/dev-v7
In this command we're syncing with the `dev-v7` 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))
(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))
+66
View File
@@ -0,0 +1,66 @@
---
name: 🐛 Bug Report
about: File a bug report, if you've discovered a problem in Umbraco.
---
A brief description of the issue goes here.
<!--
If you haven't yet done so, please read the "contributing guidelines"
thoroughly. Then, proceed by filling out the rest of the details in the issue
template below. The more details you can give us, the easier it will be for us
to determine the cause of a problem.
See: https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md
-->
Reproduction
------------
If you're filing a bug, please describe how to reproduce it. Include as much
relevant information as possible, such as:
### Bug summary
<!--
* Write a short summary of the bug
* Try to pinpoint it as much as possible
* Try to state the _actual problem_, and not just what you _think_ the
solution might be.
-->
### Specifics
<!--
* Mention the URL where this bug occurs, if applicable
* What version of Umbraco are you using (down to the very last digit!)
* What browser and version you are using
* Please mention if you've checked it in other browsers as well
* Please include *full error messages* and *screenshots* if possible
-->
### Steps to reproduce
<!--
* Clearly mention the steps to reproduce the bug
-->
### Expected result
<!--
* What did you _expect_ that would happen on your Umbraco site?
* Describe the intended/desired outcome after you did the steps mentioned.
-->
### Actual result
<!--
* What is the actual result of the above steps?
* Describe the behaviour of the bug
* Please, please include **error messages** and screenshots. They might mean
nothing to you, but they are _very_ helpful to us.
-->
@@ -0,0 +1,31 @@
---
name: 📮 Feature Request
about: Open a feature request, if you want to propose a new feature.
---
A brief description of your feature request goes here.
<!--
If you want to discuss the feature you're imagining, please make sure to keep
those discussions on the forum at https://our.umbraco.com/ (choose the
category "Contributing to Umbraco", Umbraco HQ follows all new topics there).
Once you've come to a conclusion in the discussion, feel free to propose the
new feature here.
-->
How can you help?
-------------------------------
<!--
The resources (read: available time and effort) of Umbraco's core team are
limited.
If we can not work on your suggestion, please don't take it personally. Most
likely, it's either:
- We think your idea is valid, but we can't find the time to work on it.
- Your idea might be better suited as a package, if it's not suitable for
the majority of users.
-->
@@ -0,0 +1,9 @@
---
name: ⁉️ Support Question
about: Having trouble with Umbraco? -> https://our.umbraco.com
---
This issue tracker is NOT meant for support questions. If you have a question,
please join us on the forum at https://our.umbraco.com.
Thanks!
@@ -0,0 +1,9 @@
---
name: 📖 Documentation Issue
about: See https://github.com/umbraco/UmbracoDocs/issues for documentation issues
---
The Umbraco documentation has its own dedicated repository. Please open your
documentation-related issue at https://github.com/umbraco/UmbracoDocs/issues
Thanks!
@@ -0,0 +1,31 @@
---
name: 🔐 Security Issue
about: Discovered a Security Issue in Umbraco?
---
⚠️ PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, SEE BELOW.
If you have found a security issue in Umbraco, please send the details to
security@umbraco.com and don't disclose it publicly until we can provide a fix for
it. If you wish, we'll credit you for finding verified issues, when we release
the patched version.
❗ Please read more about how to report security issues on https://umbraco.com/security
A note on "Self XSS"
--------------------
Umbraco is a CMS, that allows users to edit content on a website. As such,
all _authenticated users_ can:
- Edit content, and (depending on the field types) insert HTML and CSS in that
content, with a variety of allowed attributes.
- Depending on the user level: Edit template files, and insert C#, HTML, CSS and
javascript in so on.
- Upload files to the site, which will become publicly available.
We see these functionalities as _features_, and not as security issues. Please
report the mentioned items only if they can be performed by non-authorized
users, or other exploitable vulnerabilities.
Thanks!
+11
View File
@@ -0,0 +1,11 @@
### Prerequisites
- [ ] I have [created an issue](https://github.com/umbraco/Umbraco-CMS/issues) for the proposed changes in this PR, the link is:
- [ ] I have added steps to test this contribution in the description below
### Description
<!-- A description of the changes proposed in the pull-request -->
<!-- Make sure to link to the related issue number so we can easily find it in the issue tracker -->
<!-- Thanks for contributing to Umbraco CMS! -->

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

+51 -87
View File
@@ -1,92 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="3.4.4">
<id>UmbracoCms.Core</id>
<version>8.0.0</version>
<title>Umbraco Cms Core Binaries</title>
<authors>Umbraco HQ</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms-package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<!--
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
not want this to happen as the alpha of the next major is, really, the next major already.
-->
<dependency id="AutoMapper" version="[7.0.1,7.999999)" />
<dependency id="ClientDependency" version="[1.9.6,1.999999)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0,1.999999)" />
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
<dependency id="Examine" version="[1.0.0-beta025,1.999999)" />
<dependency id="HtmlAgilityPack" version="[1.7.2,1.999999)" />
<dependency id="ImageProcessor" version="[2.6.1.19,2.999999)" />
<dependency id="ImageProcessor.Web" version="[4.9.2.19,4.999999)" />
<dependency id="ImageProcessor.Web.Config" version="[2.4.1.19,2.999999)" />
<dependency id="LightInject" version="[5.1.2,5.999999)" />
<dependency id="LightInject.Annotation" version="[1.1.0,1.999999)" />
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
<dependency id="LightInject.WebApi" version="[2.0.0,2.999999)" />
<dependency id="Lucene.Net.Contrib" version="[3.0.3,3.999999)" />
<dependency id="Markdown" version="[2.2.1,2.999999)" />
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.1,2.999999)" />
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.6,5.999999)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3,2.999999)" />
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.6,5.999999)" />
<dependency id="Microsoft.CodeAnalysis.CSharp" version="[2.8.0,2.999999)" />
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[1.0.8,1.999999)" />
<dependency id="Microsoft.Net.Compilers" version="[2.8.0,2.999999)" />
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[4.0.0,4.999999)" />
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.0,4.999999)" />
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0,4.999999)" />
<dependency id="Microsoft.Web.Xdt" version="[2.1.2,2.999999)" />
<dependency id="MiniProfiler" version="[3.2.0.157,3.999999)" />
<dependency id="MySql.Data" version="[6.10.7,6.999999)" />
<dependency id="Newtonsoft.Json" version="[11.0.2,11.999999)" />
<dependency id="NPoco" version="[3.9.3,3.999999)" />
<dependency id="Semver" version="[2.0.4,2.999999)" />
<dependency id="Serilog" version="[2.7.1,2.999999)" />
<dependency id="Serilog.Enrichers.Process" version="[2.0.1,2.999999)" />
<dependency id="Serilog.Enrichers.Thread" version="[3.0.0,3.999999)" />
<dependency id="Serilog.Filters.Expressions" version="[2.0.0,2.999999)" />
<dependency id="Serilog.Formatting.Compact" version="[1.0.0,1.999999)" />
<dependency id="Serilog.Settings.AppSettings" version="[2.1.2,2.999999)" />
<dependency id="Serilog.Sinks.File" version="[4.0.0,4.999999)" />
<dependency id="System.Reflection.Primitives" version="[4.3.0,4.999999)" />
<dependency id="System.Runtime.Handles" version="[4.3.0,4.999999)" />
<dependency id="System.Security.Cryptography.X509Certificates" version="[4.3.2,4.999999)" />
<dependency id="System.Threading.Tasks.Dataflow" version="[4.8.0,4.999999)" />
<dependency id="Umbraco.SqlServerCE" version="[4.0.0.1,4.999999)" />
</dependencies>
</metadata>
<files>
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.dll" target="lib\net472\Umbraco.Core.dll" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.dll" target="lib\net472\Umbraco.Web.dll" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.dll" target="lib\net472\Umbraco.Web.UI.dll" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\net472\Umbraco.Examine.dll" />
<metadata minClientVersion="3.4.4">
<id>UmbracoCms.Core</id>
<version>8.0.0</version>
<title>Umbraco Cms Core Binaries</title>
<authors>Umbraco HQ</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<!--
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
not want this to happen as the alpha of the next major is, really, the next major already.
-->
<dependency id="AutoMapper" version="[7.0.1,7.999999)" />
<dependency id="LightInject" version="[5.1.2,5.999999)" />
<dependency id="LightInject.Annotation" version="[1.1.0,1.999999)" />
<dependency id="LightInject.Web" version="[2.0.0,2.999999)" />
<dependency id="Microsoft.AspNet.Identity.Core" version="[2.2.2,2.999999)" />
<dependency id="Microsoft.AspNet.WebApi.Client" version="[5.2.6,5.999999)" />
<dependency id="Microsoft.Owin" version="[4.0.0,4.999999)" />
<dependency id="MiniProfiler" version="[3.2.0.157,3.999999)" />
<dependency id="MySql.Data" version="[6.10.7,6.999999)" />
<dependency id="Newtonsoft.Json" version="[11.0.2,11.999999)" />
<dependency id="Semver" version="[2.0.4,2.999999)" />
<dependency id="Serilog" version="[2.7.1,2.999999)" />
<dependency id="Serilog.Enrichers.Process" version="[2.0.1,2.999999)" />
<dependency id="Serilog.Enrichers.Thread" version="[3.0.0,3.999999)" />
<dependency id="Serilog.Filters.Expressions" version="[2.0.0,2.999999)" />
<dependency id="Serilog.Formatting.Compact" version="[1.0.0,1.999999)" />
<dependency id="Serilog.Settings.AppSettings" version="[2.1.2,2.999999)" />
<dependency id="Serilog.Sinks.File" version="[4.0.0,4.999999)" />
<dependency id="Umbraco.SqlServerCE" version="[4.0.0.1,4.999999)" />
<dependency id="NPoco" version="[3.9.4,3.999999)" />
</dependencies>
</metadata>
<files>
<!-- libs -->
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.dll" target="lib\net472\Umbraco.Core.dll" />
<!-- docs -->
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\Umbraco.Web.xml" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\Umbraco.Examine.xml" />
<!-- docs -->
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
<file src="tools\install.core.ps1" target="tools\install.ps1" />
<!-- symbols -->
<file src="$BuildTmp$\bin\Umbraco.Core.pdb" target="lib" />
<file src="$BuildTmp$\..\src\Umbraco.Core\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib" />
<file src="$BuildTmp$\..\src\Umbraco.Web\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
<file src="$BuildTmp$\bin\Umbraco.Web.UI.pdb" target="lib" />
<file src="$BuildTmp$\..\src\Umbraco.Web.UI\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web.UI" />
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib" />
<file src="$BuildTmp$\..\src\Umbraco.Examine\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Examine" />
</files>
<!-- symbols -->
<file src="$BuildTmp$\bin\Umbraco.Core.pdb" target="lib" />
<file src="$BuildTmp$\..\src\Umbraco.Core\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
</files>
</package>
+62
View File
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="3.4.4">
<id>UmbracoCms.Web</id>
<version>8.0.0</version>
<title>Umbraco Cms Core Binaries</title>
<authors>Umbraco HQ</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Contains the web assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<!--
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
not want this to happen as the alpha of the next major is, really, the next major already.
-->
<dependency id="UmbracoCms.Core" version="[$version$]" />
<dependency id="AutoMapper" version="[7.0.1,7.999999)" />
<dependency id="ClientDependency" version="[1.9.6,1.999999)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0,1.999999)" />
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
<dependency id="Examine" version="[1.0.0-beta025,1.999999)" />
<dependency id="Lucene.Net.Contrib" version="[3.0.3,3.999999)" />
<dependency id="HtmlAgilityPack" version="[1.7.2,1.999999)" />
<dependency id="ImageProcessor" version="[2.6.2.25,2.999999)" />
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
<dependency id="LightInject.WebApi" version="[2.0.0,2.999999)" />
<dependency id="Markdown" version="[2.2.1,2.999999)" />
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.2,2.999999)" />
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.6,5.999999)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3,2.999999)" />
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.6,5.999999)" />
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[4.0.0,4.999999)" />
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.0,4.999999)" />
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0,4.999999)" />
<dependency id="System.Threading.Tasks.Dataflow" version="[4.8.0,4.999999)" />
</dependencies>
</metadata>
<files>
<!-- libs -->
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.dll" target="lib\net472\Umbraco.Web.dll" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.dll" target="lib\net472\Umbraco.Web.UI.dll" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\net472\Umbraco.Examine.dll" />
<!-- docs -->
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\Umbraco.Web.xml" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\Umbraco.Examine.xml" />
<!-- symbols -->
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib" />
<file src="$BuildTmp$\..\src\Umbraco.Web\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib" />
<file src="$BuildTmp$\..\src\Umbraco.Examine\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Examine" />
</files>
</package>
+60 -52
View File
@@ -1,58 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="3.4.4">
<id>UmbracoCms</id>
<version>8.0.0</version>
<title>Umbraco Cms</title>
<authors>Umbraco HQ</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Installs Umbraco Cms in your Visual Studio ASP.NET project</description>
<summary>Installs Umbraco Cms in your Visual Studio ASP.NET project</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependency id="UmbracoCms.Core" version="[$version$]" />
<!--
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
not want this to happen as the alpha of the next major is, really, the next major already.
-->
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3, 2.999999)" />
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.0.0-alpha.20]" />
</dependencies>
</metadata>
<files>
<file src="$BuildTmp$\Configs\**" target="Content\Config" exclude="$BuildTmp$\Configs\Web.config.transform" />
<file src="$BuildTmp$\WebApp\Views\**" target="Content\Views" exclude="$BuildTmp$\WebApp\Views\Web.config" />
<file src="$BuildTmp$\WebApp\default.aspx" target="Content\default.aspx" />
<file src="$BuildTmp$\WebApp\Global.asax" target="Content\Global.asax" />
<file src="$BuildTmp$\WebApp\Web.config" target="UmbracoFiles\Web.config" />
<file src="$BuildTmp$\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
<file src="$BuildTmp$\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
<file src="$BuildTmp$\WebApp\config\BackOfficeTours\**" target="Content\Config\BackOfficeTours" />
<file src="$BuildTmp$\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
<file src="$BuildTmp$\WebApp\Media\Web.config" target="Content\Media\Web.config" />
<metadata minClientVersion="3.4.4">
<id>UmbracoCms</id>
<version>8.0.0</version>
<title>Umbraco Cms</title>
<authors>Umbraco HQ</authors>
<owners>Umbraco HQ</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>http://umbraco.com/</projectUrl>
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Installs Umbraco Cms in your Visual Studio ASP.NET project</description>
<summary>Installs Umbraco Cms in your Visual Studio ASP.NET project</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependency id="UmbracoCms.Web" version="[$version$]" />
<!--
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
not want this to happen as the alpha of the next major is, really, the next major already.
-->
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3, 2.999999)" />
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.0.0-alpha.22]" />
<dependency id="ImageProcessor.Web" version="[4.9.3.25,4.999999)" />
<dependency id="ImageProcessor.Web.Config" version="[2.4.1.19,2.999999)" />
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[2.0.0,2.999999)" />
<dependency id="Microsoft.Net.Compilers" version="[2.9.0,2.999999)" />
</dependencies>
</metadata>
<files>
<!-- files -->
<file src="$BuildTmp$\Configs\**" target="Content\Config" exclude="$BuildTmp$\Configs\Web.config.transform" />
<file src="$BuildTmp$\WebApp\Views\**" target="Content\Views" exclude="$BuildTmp$\WebApp\Views\Web.config" />
<file src="$BuildTmp$\WebApp\default.aspx" target="Content\default.aspx" />
<file src="$BuildTmp$\WebApp\Global.asax" target="Content\Global.asax" />
<file src="$BuildTmp$\WebApp\config\BackOfficeTours\**" target="Content\Config\BackOfficeTours" />
<file src="$BuildTmp$\WebApp\Media\Web.config" target="Content\Media\Web.config" />
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.htm" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.htm" />
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.controller.js" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.controller.js" />
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.resource.js" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.resource.js" />
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\package.manifest" target="Content\App_Plugins\ModelsBuilder\package.manifest" />
<!-- these files are copied by install.ps1 -->
<file src="$BuildTmp$\WebApp\Web.config" target="UmbracoFiles\Web.config" />
<file src="$BuildTmp$\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
<file src="$BuildTmp$\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
<file src="$BuildTmp$\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
<file src="tools\install.ps1" target="tools\install.ps1" />
<file src="tools\Readme.txt" target="tools\Readme.txt" />
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
<file src="tools\applications.config.install.xdt" target="Content\config\applications.config.install.xdt" />
<file src="tools\ClientDependency.config.install.xdt" target="Content\config\ClientDependency.config.install.xdt" />
<file src="tools\Dashboard.config.install.xdt" target="Content\config\Dashboard.config.install.xdt" />
<file src="tools\trees.config.install.xdt" target="Content\config\trees.config.install.xdt" />
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" />
<!-- tools -->
<!-- beware! install.ps1 not supported by PackageReference -->
<file src="tools\install.ps1" target="tools\install.ps1" />
<file src="tools\Readme.txt" target="tools\Readme.txt" />
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
<file src="build\**" target="build" />
</files>
<!-- config transforms -->
<!-- beware! config transforms not supported by PackageReference -->
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
<file src="tools\applications.config.install.xdt" target="Content\config\applications.config.install.xdt" />
<file src="tools\ClientDependency.config.install.xdt" target="Content\config\ClientDependency.config.install.xdt" />
<file src="tools\Dashboard.config.install.xdt" target="Content\config\Dashboard.config.install.xdt" />
<file src="tools\trees.config.install.xdt" target="Content\config\trees.config.install.xdt" />
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" /> <!-- FIXME Content\ !! and then... transform?! -->
<!-- UmbracoCms props and targets -->
<file src="build\**" target="build" />
</files>
</package>
-3
View File
@@ -47,9 +47,6 @@
<CustomFilesToInclude Include=".\umbraco\**\*">
<Dir>umbraco</Dir>
</CustomFilesToInclude>
<CustomFilesToInclude Include=".\umbraco_client\**\*">
<Dir>umbraco_client</Dir>
</CustomFilesToInclude>
<CustomFilesToInclude Include=".\Global.asax">
<Dir>.</Dir>
</CustomFilesToInclude>
+10 -10
View File
@@ -1,26 +1,26 @@
_ _ __ __ ____ _____ _____ ____
| | | | \/ | _ \| __ \ /\ / ____/ __ \
_ _ __ __ ____ _____ _____ ____
| | | | \/ | _ \| __ \ /\ / ____/ __ \
| | | | \ / | |_) | |__) | / \ | | | | | |
| | | | |\/| | _ <| _ / / /\ \| | | | | |
| |__| | | | | |_) | | \ \ / ____ | |___| |__| |
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
----------------------------------------------------
Don't forget to build!
When upgrading your website using NuGet you should answer "No" to the questions to overwrite the Web.config
file (and config files in the config folder).
When upgrading your website using NuGet you should answer "No" to the questions to overwrite the Web.config
file (and config files in the config folder).
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
Publish this won't affect you.
The following items will now be automatically included when creating a deploy package or publishing to the file
system: umbraco, umbraco_client, config\splashes and global.asax.
The following items will now be automatically included when creating a deploy package or publishing to the file
system: umbraco, config\splashes and global.asax.
Please read the release notes on our.umbraco.com:
http://our.umbraco.com/contribute/releases
- Umbraco
- Umbraco
+11 -20
View File
@@ -1,39 +1,30 @@
_ _ __ __ ____ _____ _____ ____
| | | | \/ | _ \| __ \ /\ / ____/ __ \
_ _ __ __ ____ _____ _____ ____
| | | | \/ | _ \| __ \ /\ / ____/ __ \
| | | | \ / | |_) | |__) | / \ | | | | | |
| | | | |\/| | _ <| _ / / /\ \| | | | | |
| |__| | | | | |_) | | \ \ / ____ | |___| |__| |
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
----------------------------------------------------
*** IMPORTANT NOTICE FOR UPGRADES FROM VERSIONS BELOW 7.7.0 ***
Be sure to read the version specific upgrade information before proceeding:
https://our.umbraco.com/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-7-0
Depending on the version you are upgrading from, you may need to make some changes to your web.config
and you will need to be aware of the breaking changes listed there to see if these affect your installation.
Don't forget to build!
We've done our best to transform your configuration files but in case something is not quite right: remember we
backed up your files in App_Data\NuGetBackup so you can find the original files before they were transformed.
We've overwritten all the files in the Umbraco and Umbraco_Client folder, these have been backed up in
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or
a package might have added. Only the existing files were overwritten. If you customized anything then make
We've overwritten all the files in the Umbraco folder, these have been backed up in
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or
a package might have added. Only the existing files were overwritten. If you customized anything then make
sure to do a compare and merge with the NuGetBackup folder.
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
Publish this won't affect you.
The following items will now be automatically included when creating a deploy package or publishing to the file
system: umbraco, umbraco_client, config\splashes and global.asax.
The following items will now be automatically included when creating a deploy package or publishing to the file
system: umbraco, config\splashes and global.asax.
Please read the release notes on our.umbraco.com:
http://our.umbraco.com/contribute/releases
- Umbraco
- Umbraco
@@ -150,10 +150,6 @@
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
+2 -18
View File
@@ -44,14 +44,6 @@ if ($project) {
robocopy $umbracoFolder $umbracoBackupPath /e /LOG:$copyLogsPath\UmbracoBackup.log
robocopy $umbracoFolderSource $umbracoFolder /is /it /e /xf UI.xml /LOG:$copyLogsPath\UmbracoCopy.log
$umbracoClientFolder = Join-Path $projectPath "Umbraco_Client"
New-Item -ItemType Directory -Force -Path $umbracoClientFolder
$umbracoClientFolderSource = Join-Path $installPath "UmbracoFiles\Umbraco_Client"
$umbracoClientBackupPath = Join-Path $backupPath "Umbraco_Client"
New-Item -ItemType Directory -Force -Path $umbracoClientBackupPath
robocopy $umbracoClientFolder $umbracoClientBackupPath /e /LOG:$copyLogsPath\UmbracoClientBackup.log
robocopy $umbracoClientFolderSource $umbracoClientFolder /is /it /e /LOG:$copyLogsPath\UmbracoClientCopy.log
$copyWebconfig = $true
$destinationWebConfig = Join-Path $projectPath "Web.config"
@@ -85,15 +77,7 @@ if ($project) {
$splashesDestination = Join-Path $projectPath "Config\splashes\"
New-Item $splashesDestination -Type directory
Copy-Item $splashesSource $splashesDestination -Force
$sqlCe64Source = Join-Path $installPath "UmbracoFiles\bin\amd64\*"
$sqlCe64Destination = Join-Path $projectPath "bin\amd64\"
Copy-Item $sqlCe64Source $sqlCe64Destination -Force
$sqlCex86Source = Join-Path $installPath "UmbracoFiles\bin\x86\*"
$sqlCex86Destination = Join-Path $projectPath "bin\x86\"
Copy-Item $sqlCex86source $sqlCex86Destination -Force
$umbracoUIXMLSource = Join-Path $installPath "UmbracoFiles\Umbraco\Config\Create\UI.xml"
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
@@ -159,4 +143,4 @@ if ($project) {
{
$DTE.ItemOperations.OpenFile($toolsPath + '\ReadmeUpgrade.txt')
}
}
}
+16 -5
View File
@@ -69,6 +69,9 @@
$global:node_nodepath = $this.ClearEnvVar("NODEPATH")
$global:node_npmcache = $this.ClearEnvVar("NPM_CONFIG_CACHE")
$global:node_npmprefix = $this.ClearEnvVar("NPM_CONFIG_PREFIX")
# https://github.com/gruntjs/grunt-contrib-connect/issues/235
$this.SetEnvVar("NODE_NO_HTTP2", "1")
})
$ubuild.DefineMethod("RestoreNode",
@@ -78,6 +81,8 @@
$this.SetEnvVar("NODEPATH", $node_nodepath)
$this.SetEnvVar("NPM_CONFIG_CACHE", $node_npmcache)
$this.SetEnvVar("NPM_CONFIG_PREFIX", $node_npmprefix)
$ignore = $this.ClearEnvVar("NODE_NO_HTTP2")
})
$ubuild.DefineMethod("CompileBelle",
@@ -124,7 +129,7 @@
Write-Output "### install gulp-cli" >> $log 2>&1
&npm install -g gulp-cli --quiet >> $log 2>&1
if (-not $?) { throw "Failed to install gulp-cli" } # that one is expected to work
$error.Clear() # that one fails 'cos some files not being removed - ignore
Write-Output "### gulp build for version $($this.Version.Release)" >> $log 2>&1
&gulp build --buildversion=$this.Version.Release >> $log 2>&1
@@ -399,9 +404,15 @@
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmscore.log"
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Core." }
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.Web.nuspec" `
-Properties BuildTmp="$($this.BuildTemp)" `
-Version "$($this.Version.Semver.ToString())" `
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmsweb.log"
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Web." }
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.nuspec" `
-Properties BuildTmp="$($this.BuildTemp)" `
-Version $this.Version.Semver.ToString() `
-Version "$($this.Version.Semver.ToString())" `
-Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cms.log"
if (-not $?) { throw "Failed to pack NuGet UmbracoCms." }
@@ -417,7 +428,7 @@
$ubuild.DefineMethod("VerifyNuGet",
{
$this.VerifyNuGetConsistency(
("UmbracoCms", "UmbracoCms.Core"),
("UmbracoCms", "UmbracoCms.Core", "UmbracoCms.Web"),
("Umbraco.Core", "Umbraco.Web", "Umbraco.Web.UI", "Umbraco.Examine"))
if ($this.OnError()) { return }
})
@@ -427,7 +438,7 @@
Write-Host "Prepare Azure Gallery"
$this.CopyFile("$($this.SolutionRoot)\build\Azure\azuregalleryrelease.ps1", $this.BuildOutput)
})
$ubuild.DefineMethod("Build",
{
$error.Clear()
@@ -457,6 +468,7 @@
if ($this.OnError()) { return }
$this.PrepareAzureGallery()
if ($this.OnError()) { return }
Write-Host "Done"
})
# ################################################################
@@ -472,5 +484,4 @@
$ubuild.Build()
if ($ubuild.OnError()) { return }
}
Write-Host "Done"
if ($get) { return $ubuild }
-11
View File
@@ -1,11 +0,0 @@
### Prerequisites
- [ ] I have written a descriptive pull-request title
- [ ] I have linked this PR to an issue on the tracker at http://issues.umbraco.org
### Description
<!-- A description of the changes proposed in the pull-request -->
<!-- Thanks for contributing to Umbraco CMS! -->
+1 -1
View File
@@ -19,4 +19,4 @@ using System.Resources;
// these are FYI and changed automatically
[assembly: AssemblyFileVersion("8.0.0")]
[assembly: AssemblyInformationalVersion("8.0.0-alpha.44")]
[assembly: AssemblyInformationalVersion("8.0.0-alpha.50")]
@@ -3,7 +3,6 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using Umbraco.Core.Components;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
@@ -11,7 +10,7 @@ using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
namespace Umbraco.Core.Auditing
namespace Umbraco.Core.Components
{
public sealed class AuditEventsComponent : UmbracoComponentBase, IUmbracoCoreComponent
{
@@ -53,18 +52,6 @@ namespace Umbraco.Core.Auditing
_userService = userService;
_entityService = entityService;
//BackOfficeUserManager.AccountLocked += ;
//BackOfficeUserManager.AccountUnlocked += ;
BackOfficeUserManager.ForgotPasswordRequested += OnForgotPasswordRequest;
BackOfficeUserManager.ForgotPasswordChangedSuccess += OnForgotPasswordChange;
BackOfficeUserManager.LoginFailed += OnLoginFailed;
//BackOfficeUserManager.LoginRequiresVerification += ;
BackOfficeUserManager.LoginSuccess += OnLoginSuccess;
BackOfficeUserManager.LogoutSuccess += OnLogoutSuccess;
BackOfficeUserManager.PasswordChanged += OnPasswordChanged;
BackOfficeUserManager.PasswordReset += OnPasswordReset;
//BackOfficeUserManager.ResetAccessFailedCount += ;
UserService.SavedUserGroup += OnSavedUserGroupWithUsers;
UserService.SavedUser += OnSavedUser;
@@ -255,64 +242,6 @@ namespace Umbraco.Core.Auditing
"umbraco/user/delete", "delete user");
}
private void OnLoginSuccess(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs)
{
var performingUser = GetPerformingUser(identityArgs.PerformingUser);
WriteAudit(performingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/sign-in/login", "login success");
}
}
private void OnLogoutSuccess(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs)
{
var performingUser = GetPerformingUser(identityArgs.PerformingUser);
WriteAudit(performingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/sign-in/logout", "logout success");
}
}
private void OnPasswordReset(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/reset", "password reset");
}
}
private void OnPasswordChanged(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/change", "password change");
}
}
private void OnLoginFailed(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, 0, identityArgs.IpAddress, "umbraco/user/sign-in/failed", "login failed", affectedDetails: "");
}
}
private void OnForgotPasswordChange(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/forgot/change", "password forgot/change");
}
}
private void OnForgotPasswordRequest(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/forgot/request", "password forgot/request");
}
}
private void WriteAudit(int performingId, int affectedId, string ipAddress, string eventType, string eventDetails, string affectedDetails = null)
{
var performingUser = _userService.GetUserById(performingId);
@@ -1,11 +1,9 @@
using System.IO;
using Umbraco.Core.Components;
using Umbraco.Core.Composing;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
namespace Umbraco.Core.Strategies
namespace Umbraco.Core.Components
{
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public class ManifestWatcherComponent : UmbracoComponentBase, IUmbracoCoreComponent
@@ -1,11 +1,9 @@
using System;
using Umbraco.Core.Components;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
namespace Umbraco.Core.Strategies
namespace Umbraco.Core.Components
{
//TODO: This should just exist in the content service/repo!
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
@@ -1,13 +1,11 @@
using System;
using System.Linq;
using Umbraco.Core.Components;
using System.Linq;
using Umbraco.Core.Composing;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
namespace Umbraco.Core.Strategies
namespace Umbraco.Core.Components
{
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public sealed class RelateOnTrashComponent : UmbracoComponentBase, IUmbracoCoreComponent
+1
View File
@@ -58,6 +58,7 @@ namespace Umbraco.Core.Composing
// resets *everything* that is 'current'
internal static void Reset()
{
_container?.Dispose();
_container = null;
_shortStringHelper = null;
@@ -1,9 +1,24 @@
using System.Linq;
using System;
using System.Linq;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public static class ContentSectionExtensions
{
/// <summary>
/// Gets a value indicating whether the file extension corresponds to an image.
/// </summary>
/// <param name="extension">The file extension.</param>
/// <param name="contentConfig"></param>
/// <returns>A value indicating whether the file extension corresponds to an image.</returns>
public static bool IsImageFile(this IContentSection contentConfig, string extension)
{
if (contentConfig == null) throw new ArgumentNullException(nameof(contentConfig));
if (extension == null) return false;
extension = extension.TrimStart('.');
return contentConfig.ImageFileTypes.InvariantContains(extension);
}
/// <summary>
/// Determines if file extension is allowed for upload based on (optional) white list and black list
/// held in settings.
@@ -15,5 +30,17 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
(contentSection.AllowedUploadFiles.Any() == false &&
contentSection.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension)) == false);
}
/// <summary>
/// Gets the auto-fill configuration for a specified property alias.
/// </summary>
/// <param name="contentSection"></param>
/// <param name="propertyTypeAlias">The property type alias.</param>
/// <returns>The auto-fill configuration for the specified property alias, or null.</returns>
public static IImagingAutoFillUploadField GetConfig(this IContentSection contentSection, string propertyTypeAlias)
{
var autoFillConfigs = contentSection.ImageAutoFillProperties;
return autoFillConfigs?.FirstOrDefault(x => x.Alias == propertyTypeAlias);
}
}
}
@@ -8,6 +8,8 @@
bool DisableAlternativeTemplates { get; }
bool ValidateAlternativeTemplates { get; }
bool DisableFindContentByIdPath { get; }
bool DisableRedirectUrlTracking { get; }
@@ -16,5 +18,4 @@
string UmbracoApplicationUrl { get; }
}
}
@@ -5,44 +5,27 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
internal class WebRoutingElement : ConfigurationElement, IWebRoutingSection
{
[ConfigurationProperty("trySkipIisCustomErrors", DefaultValue = "false")]
public bool TrySkipIisCustomErrors
{
get { return (bool) base["trySkipIisCustomErrors"]; }
}
public bool TrySkipIisCustomErrors => (bool) base["trySkipIisCustomErrors"];
[ConfigurationProperty("internalRedirectPreservesTemplate", DefaultValue = "false")]
public bool InternalRedirectPreservesTemplate
{
get { return (bool) base["internalRedirectPreservesTemplate"]; }
}
public bool InternalRedirectPreservesTemplate => (bool) base["internalRedirectPreservesTemplate"];
[ConfigurationProperty("disableAlternativeTemplates", DefaultValue = "false")]
public bool DisableAlternativeTemplates
{
get { return (bool) base["disableAlternativeTemplates"]; }
}
public bool DisableAlternativeTemplates => (bool) base["disableAlternativeTemplates"];
[ConfigurationProperty("validateAlternativeTemplates", DefaultValue = "false")]
public bool ValidateAlternativeTemplates => (bool) base["validateAlternativeTemplates"];
[ConfigurationProperty("disableFindContentByIdPath", DefaultValue = "false")]
public bool DisableFindContentByIdPath
{
get { return (bool) base["disableFindContentByIdPath"]; }
}
public bool DisableFindContentByIdPath => (bool) base["disableFindContentByIdPath"];
[ConfigurationProperty("disableRedirectUrlTracking", DefaultValue = "false")]
public bool DisableRedirectUrlTracking
{
get { return (bool) base["disableRedirectUrlTracking"]; }
}
public bool DisableRedirectUrlTracking => (bool) base["disableRedirectUrlTracking"];
[ConfigurationProperty("urlProviderMode", DefaultValue = "AutoLegacy")]
public string UrlProviderMode
{
get { return (string) base["urlProviderMode"]; }
}
public string UrlProviderMode => (string) base["urlProviderMode"];
[ConfigurationProperty("umbracoApplicationUrl", DefaultValue = null)]
public string UmbracoApplicationUrl
{
get { return (string)base["umbracoApplicationUrl"]; }
}
public string UmbracoApplicationUrl => (string)base["umbracoApplicationUrl"];
}
}
@@ -22,7 +22,7 @@ namespace Umbraco.Core.Configuration
/// <summary>
/// Gets the version comment of the executing code (eg "beta").
/// </summary>
public static string CurrentComment => "alpha.44";
public static string CurrentComment => "alpha.50";
/// <summary>
/// Gets the assembly version of Umbraco.Code.dll.
@@ -7,12 +7,13 @@ using System.Web;
using System.Xml.Linq;
using Umbraco.Core.Composing;
using Umbraco.Core.IO;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
namespace Umbraco.Core.Models
namespace Umbraco.Core
{
public static class ContentExtensions
{
@@ -241,30 +242,6 @@ namespace Umbraco.Core.Models
#region SetValue for setting file contents
/// <summary>
/// Sets the posted file value of a property.
/// </summary>
public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileBase value, string culture = null, string segment = null)
{
// ensure we get the filename without the path in IE in intranet mode
// http://stackoverflow.com/questions/382464/httppostedfile-filename-different-from-ie
var filename = value.FileName;
var pos = filename.LastIndexOf(@"\", StringComparison.InvariantCulture);
if (pos > 0)
filename = filename.Substring(pos + 1);
// strip any directory info
pos = filename.LastIndexOf(IOHelper.DirSepChar);
if (pos > 0)
filename = filename.Substring(pos + 1);
// get a safe & clean filename
filename = IOHelper.SafeFileName(filename);
if (string.IsNullOrWhiteSpace(filename)) return;
filename = filename.ToLower(); // fixme - er... why?
MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, value.InputStream, culture, segment);
}
/// <summary>
/// Sets the posted file value of a property.
@@ -281,7 +258,31 @@ namespace Umbraco.Core.Models
if (string.IsNullOrWhiteSpace(filename)) return;
filename = filename.ToLower(); // fixme - er... why?
MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, filestream, culture, segment);
SetUploadFile(content, propertyTypeAlias, filename, filestream, culture, segment);
}
private static void SetUploadFile(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
{
var property = GetProperty(content, propertyTypeAlias);
var oldpath = property.GetValue(culture, segment) is string svalue ? MediaFileSystem.GetRelativePath(svalue) : null;
var filepath = MediaFileSystem.StoreFile(content, property.PropertyType, filename, filestream, oldpath);
property.SetValue(MediaFileSystem.GetUrl(filepath), culture, segment);
}
// gets or creates a property for a content item.
private static Property GetProperty(IContentBase content, string propertyTypeAlias)
{
var property = content.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
if (property != null) return property;
var propertyType = content.GetContentType().CompositionPropertyTypes
.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
if (propertyType == null)
throw new Exception("No property type exists with alias " + propertyTypeAlias + ".");
property = new Property(propertyType);
content.Properties.Add(property);
return property;
}
/// <summary>
+4 -117
View File
@@ -1,20 +1,15 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using LightInject;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Composing;
using Umbraco.Core.Exceptions;
using Umbraco.Core.IO.MediaPathSchemes;
using Umbraco.Core.Logging;
using Umbraco.Core.Media;
using Umbraco.Core.Media.Exif;
using Umbraco.Core.Models;
namespace Umbraco.Core.IO
@@ -32,8 +27,6 @@ namespace Umbraco.Core.IO
// dependencies, so we have to rely on property injection for anything we might need
Current.Container.InjectProperties(this);
MediaPathScheme.Initialize(this);
UploadAutoFillProperties = new UploadAutoFillProperties(this, Logger, ContentConfig);
}
[Inject]
@@ -44,9 +37,7 @@ namespace Umbraco.Core.IO
[Inject]
internal ILogger Logger { get; set; }
internal UploadAutoFillProperties UploadAutoFillProperties { get; }
/// <summary>
/// Deletes all files passed in.
/// </summary>
@@ -213,113 +204,9 @@ namespace Umbraco.Core.IO
return filepath;
}
// gets or creates a property for a content item.
private static Property GetProperty(IContentBase content, string propertyTypeAlias)
{
var property = content.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
if (property != null) return property;
var propertyType = content.GetContentType().CompositionPropertyTypes
.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
if (propertyType == null)
throw new Exception("No property type exists with alias " + propertyTypeAlias + ".");
property = new Property(propertyType);
content.Properties.Add(property);
return property;
}
// fixme - what's below belongs to the upload property editor, not the media filesystem!
public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
{
var property = GetProperty(content, propertyTypeAlias);
var oldpath = property.GetValue(culture, segment) is string svalue ? GetRelativePath(svalue) : null;
var filepath = StoreFile(content, property.PropertyType, filename, filestream, oldpath);
property.SetValue(GetUrl(filepath), culture, segment);
SetUploadFile(content, property, filepath, filestream, culture, segment);
}
public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filepath, string culture = null, string segment = null)
{
var property = GetProperty(content, propertyTypeAlias);
// fixme delete?
var oldpath = property.GetValue(culture, segment) is string svalue ? GetRelativePath(svalue) : null;
if (string.IsNullOrWhiteSpace(oldpath) == false && oldpath != filepath)
DeleteFile(oldpath);
property.SetValue(GetUrl(filepath), culture, segment);
using (var filestream = OpenFile(filepath))
{
SetUploadFile(content, property, filepath, filestream, culture, segment);
}
}
// sets a file for the FileUpload property editor
// ie generates thumbnails and populates autofill properties
private void SetUploadFile(IContentBase content, Property property, string filepath, Stream filestream, string culture = null, string segment = null)
{
// will use filepath for extension, and filestream for length
UploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, culture, segment);
}
#endregion
#region Image
/// <summary>
/// Gets a value indicating whether the file extension corresponds to an image.
/// </summary>
/// <param name="extension">The file extension.</param>
/// <returns>A value indicating whether the file extension corresponds to an image.</returns>
public bool IsImageFile(string extension)
{
if (extension == null) return false;
extension = extension.TrimStart('.');
return ContentConfig.ImageFileTypes.InvariantContains(extension);
}
/// <summary>
/// Gets the dimensions of an image.
/// </summary>
/// <param name="stream">A stream containing the image bytes.</param>
/// <returns>The dimension of the image.</returns>
/// <remarks>First try with EXIF as it is faster and does not load the entire image
/// in memory. Fallback to GDI which means loading the image in memory and thus
/// use potentially large amounts of memory.</remarks>
public Size GetDimensions(Stream stream)
{
//Try to load with exif
try
{
var jpgInfo = ImageFile.FromStream(stream);
if (jpgInfo.Format != ImageFileFormat.Unknown
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelYDimension)
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelXDimension))
{
var height = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelYDimension].Value);
var width = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelXDimension].Value);
if (height > 0 && width > 0)
{
return new Size(width, height);
}
}
}
catch (Exception)
{
//We will just swallow, just means we can't read exif data, we don't want to log an error either
}
//we have no choice but to try to read in via GDI
using (var image = Image.FromStream(stream))
{
var fileWidth = image.Width;
var fileHeight = image.Height;
return new Size(fileWidth, fileHeight);
}
}
#endregion
}
}
+1
View File
@@ -40,6 +40,7 @@ namespace Umbraco.Core.IO
public static string Umbraco => IOHelper.ReturnPath("umbracoPath", "~/umbraco");
[Obsolete("This will be removed, there is no more umbraco_client folder")]
public static string UmbracoClient => IOHelper.ReturnPath("umbracoClientPath", "~/umbraco_client");
public static string UserControls => IOHelper.ReturnPath("umbracoUsercontrolsPath", "~/usercontrols");
@@ -7,6 +7,9 @@ namespace Umbraco.Core.Logging
/// </summary>
public class DebugDiagnosticsLogger : ILogger
{
public bool IsEnabled(Type reporting, LogLevel level)
=> true;
/// <inheritdoc/>
public void Fatal(Type reporting, Exception exception, string message)
{
@@ -26,15 +29,15 @@ namespace Umbraco.Core.Logging
}
/// <inheritdoc/>
public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] args)
public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
System.Diagnostics.Debug.WriteLine(string.Format(messageTemplate, args) + Environment.NewLine + exception, reporting.FullName);
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName);
}
/// <inheritdoc/>
public void Fatal(Type reporting, string messageTemplate, params object[] args)
public void Fatal(Type reporting, string messageTemplate, params object[] propertyValues)
{
System.Diagnostics.Debug.WriteLine(messageTemplate, args);
System.Diagnostics.Debug.WriteLine(messageTemplate, propertyValues);
}
/// <inheritdoc/>
@@ -56,27 +59,27 @@ namespace Umbraco.Core.Logging
}
/// <inheritdoc/>
public void Error(Type reporting, Exception exception, string messageTemplate, params object[] args)
public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
System.Diagnostics.Debug.WriteLine(string.Format(messageTemplate, args) + Environment.NewLine + exception, reporting.FullName);
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues) + Environment.NewLine + exception, reporting.FullName);
}
/// <inheritdoc/>
public void Error(Type reporting, string messageTemplate, params object[] args)
public void Error(Type reporting, string messageTemplate, params object[] propertyValues)
{
System.Diagnostics.Debug.WriteLine(messageTemplate, args);
System.Diagnostics.Debug.WriteLine(messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Warn(Type reporting, string format)
public void Warn(Type reporting, string message)
{
System.Diagnostics.Debug.WriteLine(format, reporting.FullName);
System.Diagnostics.Debug.WriteLine(message, reporting.FullName);
}
/// <inheritdoc/>
public void Warn(Type reporting, string format, params object[] args)
public void Warn(Type reporting, string message, params object[] propertyValues)
{
System.Diagnostics.Debug.WriteLine(string.Format(format, args), reporting.FullName);
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(message, propertyValues), reporting.FullName);
}
/// <inheritdoc/>
@@ -86,9 +89,9 @@ namespace Umbraco.Core.Logging
}
/// <inheritdoc/>
public void Warn(Type reporting, Exception exception, string format, params object[] args)
public void Warn(Type reporting, Exception exception, string message, params object[] propertyValues)
{
System.Diagnostics.Debug.WriteLine(string.Format(format + Environment.NewLine + exception, args), reporting.FullName);
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(message + Environment.NewLine + exception, propertyValues), reporting.FullName);
}
/// <inheritdoc/>
@@ -98,9 +101,9 @@ namespace Umbraco.Core.Logging
}
/// <inheritdoc/>
public void Info(Type reporting, string format, params object[] args)
public void Info(Type reporting, string messageTemplate, params object[] propertyValues)
{
System.Diagnostics.Debug.WriteLine(string.Format(format, args), reporting.FullName);
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
}
/// <inheritdoc/>
@@ -110,9 +113,9 @@ namespace Umbraco.Core.Logging
}
/// <inheritdoc/>
public void Debug(Type reporting, string format, params object[] args)
public void Debug(Type reporting, string messageTemplate, params object[] propertyValues)
{
System.Diagnostics.Debug.WriteLine(string.Format(format, args), reporting.FullName);
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
}
/// <inheritdoc/>
@@ -122,10 +125,9 @@ namespace Umbraco.Core.Logging
}
/// <inheritdoc/>
public void Verbose(Type reporting, string format, params object[] args)
public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues)
{
System.Diagnostics.Debug.WriteLine(string.Format(format, args), reporting.FullName);
System.Diagnostics.Debug.WriteLine(MessageTemplates.Render(messageTemplate, propertyValues), reporting.FullName);
}
}
}
+16 -24
View File
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Logging
public class DisposableTimer : DisposableObjectSlim
{
private readonly ILogger _logger;
private readonly LogType? _logType;
private readonly LogLevel _level;
private readonly Type _loggerType;
private readonly int _thresholdMilliseconds;
private readonly IDisposable _profilerStep;
@@ -19,22 +19,14 @@ namespace Umbraco.Core.Logging
private bool _failed;
private readonly string _timingId;
internal enum LogType
{
Debug, Info
}
// internal - created by profiling logger
internal DisposableTimer(ILogger logger, LogType logType, IProfiler profiler, Type loggerType,
internal DisposableTimer(ILogger logger, LogLevel level, IProfiler profiler, Type loggerType,
string startMessage, string endMessage, string failMessage = null,
int thresholdMilliseconds = 0)
{
if (logger == null) throw new ArgumentNullException(nameof(logger));
if (loggerType == null) throw new ArgumentNullException(nameof(loggerType));
_logger = logger;
_logType = logType;
_loggerType = loggerType;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_level = level;
_loggerType = loggerType ?? throw new ArgumentNullException(nameof(loggerType));
_endMessage = endMessage;
_failMessage = failMessage;
_thresholdMilliseconds = thresholdMilliseconds < 0 ? 0 : thresholdMilliseconds;
@@ -42,16 +34,16 @@ namespace Umbraco.Core.Logging
if (thresholdMilliseconds == 0)
{
switch (logType)
switch (_level)
{
case LogType.Debug:
case LogLevel.Debug:
logger.Debug(loggerType, "[Timing {TimingId}] {StartMessage}", _timingId, startMessage);
break;
case LogType.Info:
case LogLevel.Information:
logger.Info(loggerType, "[Timing {TimingId}] {StartMessage}", _timingId, startMessage);
break;
default:
throw new ArgumentOutOfRangeException(nameof(logType));
throw new ArgumentOutOfRangeException(nameof(level));
}
}
@@ -87,20 +79,20 @@ namespace Umbraco.Core.Logging
_profilerStep?.Dispose();
if ((Stopwatch.ElapsedMilliseconds >= _thresholdMilliseconds || _failed)
&& _logType.HasValue && _loggerType != null && _logger != null
&& _loggerType != null && _logger != null
&& (_endMessage.IsNullOrWhiteSpace() == false || _failed))
{
if (_failed)
{
_logger.Error(_loggerType, _failException, "[Timing {TimingId}] {FailMessage} ({TimingDuration}ms)", _timingId, _failMessage, Stopwatch.ElapsedMilliseconds);
_logger.Error(_loggerType, _failException, "[Timing {TimingId}] {FailMessage} ({Duration}ms)", _timingId, _failMessage, Stopwatch.ElapsedMilliseconds);
}
else switch (_logType)
else switch (_level)
{
case LogType.Debug:
_logger.Debug(_loggerType, "[Timing {TimingId}] {EndMessage} ({TimingDuration}ms)", _timingId, _endMessage, Stopwatch.ElapsedMilliseconds);
case LogLevel.Debug:
_logger.Debug(_loggerType, "[Timing {TimingId}] {EndMessage} ({Duration}ms)", _timingId, _endMessage, Stopwatch.ElapsedMilliseconds);
break;
case LogType.Info:
_logger.Info(_loggerType, "[Timing {TimingId}] {EndMessage} ({TimingDuration}ms)", _timingId, _endMessage, Stopwatch.ElapsedMilliseconds);
case LogLevel.Information:
_logger.Info(_loggerType, "[Timing {TimingId}] {EndMessage} ({Duration}ms)", _timingId, _endMessage, Stopwatch.ElapsedMilliseconds);
break;
// filtered in the ctor
//default:
+50 -35
View File
@@ -5,10 +5,24 @@ namespace Umbraco.Core.Logging
/// <summary>
/// Defines the logging service.
/// </summary>
/// <remarks>
/// <para>Message templates in logging methods follow the Message Templates specification
/// available at https://messagetemplates.org/ in order to support structured logging.</para>
/// <para>Implementations must ensure that they support these templates. Note that the
/// specification includes support for traditional C# numeric placeholders.</para>
/// <para>For instance, "Processed {Input} in {Time}ms."</para>
/// </remarks>
public interface ILogger
{
/// <summary>
/// Logs a fatal message.
/// Determines if logging is enabled at a specified level, for a reporting type.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="level">The level.</param>
bool IsEnabled(Type reporting, LogLevel level);
/// <summary>
/// Logs a fatal message with an exception.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="exception">An exception.</param>
@@ -16,38 +30,39 @@ namespace Umbraco.Core.Logging
void Fatal(Type reporting, Exception exception, string message);
/// <summary>
/// Logs a fatal message NOTE: This will log an empty message string
/// Logs a fatal exception.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="exception">An exception.</param>
/// <remarks>The message string is unspecified and is implementation-specific.</remarks>
void Fatal(Type reporting, Exception exception);
/// <summary>
/// Logs a fatal message WITHOUT EX
/// Logs a fatal message.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="message">A message.</param>
void Fatal(Type reporting, string message);
/// <summary>
/// Logs a fatal message - using a structured log message
/// Logs a fatal message with an exception.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="exception">An exception.</param>
/// <param name="messageTemplate">The message template that includes property values</param>
/// <param name="propertyValues">Property values to log & update in message template</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues);
/// <summary>
/// Logs a fatal message WITHOUT EX - using a structured log message
/// Logs a fatal message.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="messageTemplate">The message template that includes property values</param>
/// <param name="propertyValues">Property values to log & update in message template</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
void Fatal(Type reporting, string messageTemplate, params object[] propertyValues);
/// <summary>
/// Logs an error message.
/// Logs an error message with an exception.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="exception">An exception.</param>
@@ -55,34 +70,35 @@ namespace Umbraco.Core.Logging
void Error(Type reporting, Exception exception, string message);
/// <summary>
/// Logs an error message NOTE: This will log an empty message string
/// Logs an error exception.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="exception">An exception.</param>
/// <remarks>The message string is unspecified and is implementation-specific.</remarks>
void Error(Type reporting, Exception exception);
/// <summary>
/// Logs an error message WITHOUT EX
/// Logs an error message.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="message">A message.</param>
void Error(Type reporting, string message);
/// <summary>
/// Logs an error message - using a structured log message
/// Logs an error message with an exception.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="exception">An exception.</param>
/// <param name="messageTemplate">The message template that includes property values</param>
/// <param name="propertyValues">Property values to log & update in message template</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues);
/// <summary>
/// Logs an error message WITHOUT EX - using a structured log message
/// Logs an error message.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="messageTemplate">The message template that includes property values</param>
/// <param name="propertyValues">Property values to log & update in message template</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
void Error(Type reporting, string messageTemplate, params object[] propertyValues);
/// <summary>
@@ -93,11 +109,11 @@ namespace Umbraco.Core.Logging
void Warn(Type reporting, string message);
/// <summary>
/// Logs a warning message - using a structured log message
/// Logs a warning message.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="messageTemplate">The message template that includes property values</param>
/// <param name="propertyValues">Property values to log & update in message template</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
void Warn(Type reporting, string messageTemplate, params object[] propertyValues);
/// <summary>
@@ -109,12 +125,12 @@ namespace Umbraco.Core.Logging
void Warn(Type reporting, Exception exception, string message);
/// <summary>
/// Logs a warning message with an exception - using a structured log message
/// Logs a warning message with an exception.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="exception">An exception.</param>
/// <param name="messageTemplate">The message template that includes property values</param>
/// <param name="propertyValues">Property values to log & update in message template</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
void Warn(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues);
/// <summary>
@@ -125,11 +141,11 @@ namespace Umbraco.Core.Logging
void Info(Type reporting, string message);
/// <summary>
/// Logs a info message - using a structured log message
/// Logs a info message.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="messageTemplate">The message template that includes property values</param>
/// <param name="propertyValues">Property values to log & update in message template</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
void Info(Type reporting, string messageTemplate, params object[] propertyValues);
/// <summary>
@@ -138,13 +154,13 @@ namespace Umbraco.Core.Logging
/// <param name="reporting">The reporting type.</param>
/// <param name="message">A message.</param>
void Debug(Type reporting, string message);
/// <summary>
/// Logs a debug message - using a structured log message
/// Logs a debug message.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="messageTemplate">The message template that includes property values</param>
/// <param name="propertyValues">Property values to log & update in message template</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
void Debug(Type reporting, string messageTemplate, params object[] propertyValues);
/// <summary>
@@ -155,12 +171,11 @@ namespace Umbraco.Core.Logging
void Verbose(Type reporting, string message);
/// <summary>
/// Logs a verbose message - using a structured log message
/// Logs a verbose message.
/// </summary>
/// <param name="reporting">The reporting type.</param>
/// <param name="messageTemplate">The message template that includes property values</param>
/// <param name="propertyValues">Property values to log & update in message template</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
void Verbose(Type reporting, string messageTemplate, params object[] propertyValues);
}
}
+15
View File
@@ -0,0 +1,15 @@
namespace Umbraco.Core.Logging
{
/// <summary>
/// Specifies the level of a log event.
/// </summary>
public enum LogLevel
{
Verbose,
Debug,
Information,
Warning,
Error,
Fatal
}
}
+70 -98
View File
@@ -8,63 +8,62 @@ namespace Umbraco.Core.Logging
public static class LoggerExtensions
{
/// <summary>
/// Logs an error message
/// Determines if logging is enabled at a specified level, for a reporting type.
/// </summary>
/// <typeparam name="T">The reporting type.</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="level">The level.</param>
public static bool IsEnabled<T>(this ILogger logger, LogLevel level)
=> logger.IsEnabled(typeof(T), level);
/// <summary>
/// Logs an error message with an exception.
/// </summary>
/// <typeparam name="T">The reporting type.</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="message">A message.</param>
/// <param name="exception">An exception.</param>
public static void Error<T>(this ILogger logger, Exception exception, string message)
{
logger.Error(typeof(T), exception, message);
}
=> logger.Error(typeof(T), exception, message);
/// <summary>
/// Logs an error message with a structured message template
/// Logs an error message with an exception.
/// </summary>
/// <typeparam name="T">The reporting type</typeparam>
/// <typeparam name="T">The reporting type.</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="messageTemplate">A structured message template</param>
/// <param name="exception">An exception</param>
/// <param name="propertyValues">Message property values</param>
/// <param name="exception">An exception.</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
public static void Error<T>(this ILogger logger, Exception exception, string messageTemplate, params object[] propertyValues)
{
logger.Error(typeof(T), exception, messageTemplate, propertyValues);
}
=> logger.Error(typeof(T), exception, messageTemplate, propertyValues);
/// <summary>
/// Logs an error message NOTE: This will log an empty message string
/// Logs an error exception.
/// </summary>
/// <typeparam name="T">The reporting type</typeparam>
/// <typeparam name="T">The reporting type.</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="exception">An exception</param>
/// <param name="exception">An exception.</param>
public static void Error<T>(this ILogger logger, Exception exception)
{
logger.Error(typeof(T), exception);
}
=> logger.Error(typeof(T), exception);
/// <summary>
/// Logs an error message WITHOUT EX
/// Logs an error message.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="logger"></param>
/// <param name="message"></param>
public static void Error<T>(this ILogger logger, string message)
{
logger.Error(typeof(T), message);
}
/// <summary>
/// Logs an error message - using a structured log message
/// </summary>
/// <typeparam name="T">The reporting type</typeparam>
/// <typeparam name="T">The reporting type.</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="messageTemplate">A structured message template</param>
/// <param name="propertyValues">Message property values</param>
/// <param name="message">A message.</param>
public static void Error<T>(this ILogger logger, string message)
=> logger.Error(typeof(T), message);
/// <summary>
/// Logs an error message.
/// </summary>
/// <typeparam name="T">The reporting type.</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
public static void Error<T>(this ILogger logger, string messageTemplate, params object[] propertyValues)
{
logger.Error(typeof(T), messageTemplate, propertyValues);
}
=> logger.Error(typeof(T), messageTemplate, propertyValues);
/// <summary>
/// Logs a warning message.
@@ -73,46 +72,38 @@ namespace Umbraco.Core.Logging
/// <param name="logger">The logger.</param>
/// <param name="message">A message.</param>
public static void Warn<T>(this ILogger logger, string message)
{
logger.Warn(typeof(T), message);
}
=> logger.Warn(typeof(T), message);
/// <summary>
/// Logs a warning message with a structured message template
/// Logs a warning message.
/// </summary>
/// <typeparam name="T">The reporting type</typeparam>
/// <typeparam name="T">The reporting type.</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="messageTemplate">A structured message template</param>
/// <param name="propertyValues">Message property values</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
public static void Warn<T>(this ILogger logger, string messageTemplate, params object[] propertyValues)
{
logger.Warn(typeof(T), messageTemplate, propertyValues);
}
=> logger.Warn(typeof(T), messageTemplate, propertyValues);
/// <summary>
/// Logs a formatted warning message with an exception.
/// Logs a warning message with an exception.
/// </summary>
/// <typeparam name="T">The reporting type.</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="exception">An exception.</param>
/// <param name="message">A message.</param>
public static void Warn<T>(this ILogger logger, Exception exception, string message)
{
logger.Warn(typeof(T), exception, message);
}
=> logger.Warn(typeof(T), exception, message);
/// <summary>
/// Logs a warning message with an exception with a structured message template
/// Logs a warning message with an exception.
/// </summary>
/// <typeparam name="T">The reporting type</typeparam>
/// <typeparam name="T">The reporting type.</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="exception">An exception</param>
/// <param name="messageTemplate">A structured message template</param>
/// <param name="propertyValues">Message property values</param>
/// <param name="exception">An exception.</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
public static void Warn<T>(this ILogger logger, Exception exception, string messageTemplate, params object[] propertyValues)
{
logger.Warn(typeof(T), exception, messageTemplate, propertyValues);
}
=> logger.Warn(typeof(T), exception, messageTemplate, propertyValues);
/// <summary>
/// Logs an information message.
@@ -121,21 +112,17 @@ namespace Umbraco.Core.Logging
/// <param name="logger">The logger.</param>
/// <param name="message">A message.</param>
public static void Info<T>(this ILogger logger, string message)
{
logger.Info(typeof(T), message);
}
=> logger.Info(typeof(T), message);
/// <summary>
/// Logs a information message with a structured message template
/// Logs a information message.
/// </summary>
/// <typeparam name="T">The reporting type</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="messageTemplate">A structured message template</param>
/// <param name="propertyValues">Message property values</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
public static void Info<T>(this ILogger logger, string messageTemplate, params object[] propertyValues)
{
logger.Info(typeof(T), messageTemplate, propertyValues);
}
=> logger.Info(typeof(T), messageTemplate, propertyValues);
/// <summary>
/// Logs a debugging message.
@@ -144,21 +131,17 @@ namespace Umbraco.Core.Logging
/// <param name="logger">The logger.</param>
/// <param name="message">A message.</param>
public static void Debug<T>(this ILogger logger, string message)
{
logger.Debug(typeof(T), message);
}
=> logger.Debug(typeof(T), message);
/// <summary>
/// Logs a debugging message with a structured message template
/// Logs a debugging message.
/// </summary>
/// <typeparam name="T">The reporting type</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="messageTemplate">A structured message template</param>
/// <param name="propertyValues">Message property values</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
public static void Debug<T>(this ILogger logger, string messageTemplate, params object[] propertyValues)
{
logger.Debug(typeof(T), messageTemplate, propertyValues);
}
=> logger.Debug(typeof(T), messageTemplate, propertyValues);
/// <summary>
/// Logs a verbose message.
@@ -167,22 +150,17 @@ namespace Umbraco.Core.Logging
/// <param name="logger">The logger.</param>
/// <param name="message">A message.</param>
public static void Verbose<T>(this ILogger logger, string message)
{
logger.Verbose(typeof(T), message);
}
=> logger.Verbose(typeof(T), message);
/// <summary>
/// Logs a Verbose message with a structured message template
/// Logs a verbose message.
/// </summary>
/// <typeparam name="T">The reporting type</typeparam>
/// <typeparam name="T">The reporting type.</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="messageTemplate">A structured message template</param>
/// <param name="propertyValues">Message property values</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
public static void Verbose<T>(this ILogger logger, string messageTemplate, params object[] propertyValues)
{
logger.Verbose(typeof(T), messageTemplate, propertyValues);
}
=> logger.Verbose(typeof(T), messageTemplate, propertyValues);
/// <summary>
/// Logs a fatal message.
@@ -192,23 +170,17 @@ namespace Umbraco.Core.Logging
/// <param name="exception">An exception.</param>
/// <param name="message">A message.</param>
public static void Fatal<T>(this ILogger logger, Exception exception, string message)
{
logger.Fatal(typeof(T), exception, message);
}
=> logger.Fatal(typeof(T), exception, message);
/// <summary>
/// Logs a fatal message with a structured message template
/// Logs a fatal message.
/// </summary>
/// <typeparam name="T">The reporting type.</typeparam>
/// <param name="logger">The logger.</param>
/// <param name="exception">An exception.</param>
/// <param name="messageTemplate">A structured message template</param>
/// <param name="propertyValues">Message property values</param>
/// <param name="messageTemplate">A message template.</param>
/// <param name="propertyValues">Property values.</param>
public static void Fatal<T>(this ILogger logger, Exception exception, string messageTemplate, params object[] propertyValues)
{
logger.Fatal(typeof(T), exception, messageTemplate, propertyValues);
}
=> logger.Fatal(typeof(T), exception, messageTemplate, propertyValues);
}
}
@@ -0,0 +1,35 @@
using System;
using System.Linq;
using Serilog;
namespace Umbraco.Core.Logging
{
/// <summary>
/// Provides tools to support message templates.
/// </summary>
public static class MessageTemplates
{
// Umbraco now uses Message Templates (https://messagetemplates.org/) for logging, which means
// we cannot plainly use string.Format() to format them. There is a work-in-progress C# lib,
// derived from Serilog, which should help (https://github.com/messagetemplates/messagetemplates-csharp)
// but it only has a pre-release NuGet package. So, we've got to use Serilog's code, which
// means we cannot get rid of Serilog entirely. We may want to revisit this at some point.
private static readonly Lazy<global::Serilog.ILogger> MinimalLogger = new Lazy<global::Serilog.ILogger>(() => new LoggerConfiguration().CreateLogger());
public static string Render(string messageTemplate, params object[] args)
{
// by default, unless initialized otherwise, Log.Logger is SilentLogger which cannot bind message
// templates. Log.Logger is set to a true Logger when initializing Umbraco's logger, but in case
// that has not been done already - use a temp minimal logger (eg for tests).
var logger = Log.Logger as global::Serilog.Core.Logger ?? MinimalLogger.Value;
var bound = logger.BindMessageTemplate(messageTemplate, args, out var parsedTemplate, out var boundProperties);
if (!bound)
throw new FormatException($"Could not format message \"{messageTemplate}\" with {args.Length} args.");
return parsedTemplate.Render(boundProperties.ToDictionary(x => x.Name, x => x.Value));
}
}
}
+13 -9
View File
@@ -13,10 +13,8 @@ namespace Umbraco.Core.Logging
public ProfilingLogger(ILogger logger, IProfiler profiler)
{
if (logger == null) throw new ArgumentNullException(nameof(logger));
if (profiler == null) throw new ArgumentNullException(nameof(profiler));
Logger = logger;
Profiler = profiler;
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
Profiler = profiler ?? throw new ArgumentNullException(nameof(profiler));
}
public DisposableTimer TraceDuration<T>(string startMessage)
@@ -26,27 +24,33 @@ namespace Umbraco.Core.Logging
public DisposableTimer TraceDuration<T>(string startMessage, string completeMessage, string failMessage = null)
{
return new DisposableTimer(Logger, DisposableTimer.LogType.Info, Profiler, typeof(T), startMessage, completeMessage, failMessage);
return new DisposableTimer(Logger, LogLevel.Information, Profiler, typeof(T), startMessage, completeMessage, failMessage);
}
public DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null)
{
return new DisposableTimer(Logger, DisposableTimer.LogType.Info, Profiler, loggerType, startMessage, completeMessage, failMessage);
return new DisposableTimer(Logger, LogLevel.Information, Profiler, loggerType, startMessage, completeMessage, failMessage);
}
public DisposableTimer DebugDuration<T>(string startMessage)
{
return DebugDuration<T>(startMessage, "Completed.");
return Logger.IsEnabled<T>(LogLevel.Debug)
? DebugDuration<T>(startMessage, "Completed.")
: null;
}
public DisposableTimer DebugDuration<T>(string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0)
{
return new DisposableTimer(Logger, DisposableTimer.LogType.Debug, Profiler, typeof(T), startMessage, completeMessage, failMessage, thresholdMilliseconds);
return Logger.IsEnabled<T>(LogLevel.Debug)
? new DisposableTimer(Logger, LogLevel.Debug, Profiler, typeof(T), startMessage, completeMessage, failMessage, thresholdMilliseconds)
: null;
}
public DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage, string failMessage = null, int thresholdMilliseconds = 0)
{
return new DisposableTimer(Logger, DisposableTimer.LogType.Debug, Profiler, loggerType, startMessage, completeMessage, failMessage, thresholdMilliseconds);
return Logger.IsEnabled(loggerType, LogLevel.Debug)
? new DisposableTimer(Logger, LogLevel.Debug, Profiler, loggerType, startMessage, completeMessage, failMessage, thresholdMilliseconds)
: null;
}
}
}
@@ -0,0 +1,61 @@
using System;
using System.Web;
using Serilog.Core;
using Serilog.Events;
namespace Umbraco.Core.Logging.Serilog.Enrichers
{
/// <summary>
/// Enrich log events with a HttpRequestId GUID.
/// Original source - https://github.com/serilog-web/classic/blob/master/src/SerilogWeb.Classic/Classic/Enrichers/HttpRequestIdEnricher.cs
/// Nupkg: 'Serilog.Web.Classic' contains handlers & extra bits we do not want
/// </summary>
internal class HttpRequestIdEnricher : ILogEventEnricher
{
/// <summary>
/// The property name added to enriched log events.
/// </summary>
public const string HttpRequestIdPropertyName = "HttpRequestId";
static readonly string RequestIdItemName = typeof(HttpRequestIdEnricher).Name + "+RequestId";
/// <summary>
/// Enrich the log event with an id assigned to the currently-executing HTTP request, if any.
/// </summary>
/// <param name="logEvent">The log event to enrich.</param>
/// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
if (logEvent == null) throw new ArgumentNullException("logEvent");
Guid requestId;
if (!TryGetCurrentHttpRequestId(out requestId))
return;
var requestIdProperty = new LogEventProperty(HttpRequestIdPropertyName, new ScalarValue(requestId));
logEvent.AddPropertyIfAbsent(requestIdProperty);
}
/// <summary>
/// Retrieve the id assigned to the currently-executing HTTP request, if any.
/// </summary>
/// <param name="requestId">The request id.</param>
/// <returns><c>true</c> if there is a request in progress; <c>false</c> otherwise.</returns>
public static bool TryGetCurrentHttpRequestId(out Guid requestId)
{
if (HttpContext.Current == null)
{
requestId = default(Guid);
return false;
}
var requestIdItem = HttpContext.Current.Items[RequestIdItemName];
if (requestIdItem == null)
HttpContext.Current.Items[RequestIdItemName] = requestId = Guid.NewGuid();
else
requestId = (Guid)requestIdItem;
return true;
}
}
}
@@ -0,0 +1,48 @@
using System;
using System.Threading;
using System.Web;
using Serilog.Core;
using Serilog.Events;
namespace Umbraco.Core.Logging.Serilog.Enrichers
{
/// <summary>
/// Enrich log events with a HttpRequestNumber unique within the current
/// logging session.
/// Original source - https://github.com/serilog-web/classic/blob/master/src/SerilogWeb.Classic/Classic/Enrichers/HttpRequestNumberEnricher.cs
/// Nupkg: 'Serilog.Web.Classic' contains handlers & extra bits we do not want
/// </summary>
internal class HttpRequestNumberEnricher : ILogEventEnricher
{
/// <summary>
/// The property name added to enriched log events.
/// </summary>
public const string HttpRequestNumberPropertyName = "HttpRequestNumber";
static int _lastRequestNumber;
static readonly string RequestNumberItemName = typeof(HttpRequestNumberEnricher).Name + "+RequestNumber";
/// <summary>
/// Enrich the log event with the number assigned to the currently-executing HTTP request, if any.
/// </summary>
/// <param name="logEvent">The log event to enrich.</param>
/// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
if (logEvent == null) throw new ArgumentNullException("logEvent");
if (HttpContext.Current == null)
return;
int requestNumber;
var requestNumberItem = HttpContext.Current.Items[RequestNumberItemName];
if (requestNumberItem == null)
HttpContext.Current.Items[RequestNumberItemName] = requestNumber = Interlocked.Increment(ref _lastRequestNumber);
else
requestNumber = (int)requestNumberItem;
var requestNumberProperty = new LogEventProperty(HttpRequestNumberPropertyName, new ScalarValue(requestNumber));
logEvent.AddPropertyIfAbsent(requestNumberProperty);
}
}
}
@@ -0,0 +1,39 @@
using Serilog.Core;
using Serilog.Events;
using System;
using System.Web;
namespace Umbraco.Core.Logging.Serilog.Enrichers
{
/// <summary>
/// Enrich log events with the HttpSessionId property.
/// Original source - https://github.com/serilog-web/classic/blob/master/src/SerilogWeb.Classic/Classic/Enrichers/HttpSessionIdEnricher.cs
/// Nupkg: 'Serilog.Web.Classic' contains handlers & extra bits we do not want
/// </summary>
internal class HttpSessionIdEnricher : ILogEventEnricher
{
/// <summary>
/// The property name added to enriched log events.
/// </summary>
public const string HttpSessionIdPropertyName = "HttpSessionId";
/// <summary>
/// Enrich the log event with the current ASP.NET session id, if sessions are enabled.</summary>
/// <param name="logEvent">The log event to enrich.</param>
/// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
if (logEvent == null) throw new ArgumentNullException("logEvent");
if (HttpContext.Current == null)
return;
if (HttpContext.Current.Session == null)
return;
var sessionId = HttpContext.Current.Session.SessionID;
var sessionIdProperty = new LogEventProperty(HttpSessionIdPropertyName, new ScalarValue(sessionId));
logEvent.AddPropertyIfAbsent(sessionIdProperty);
}
}
}
@@ -1,7 +1,7 @@
using Serilog.Core;
using Serilog.Events;
namespace Umbraco.Core.Logging.SerilogExtensions
namespace Umbraco.Core.Logging.Serilog.Enrichers
{
/// <summary>
/// This is used to create a new property in Logs called 'Log4NetLevel'
@@ -3,8 +3,9 @@ using System.Web;
using Serilog;
using Serilog.Events;
using Serilog.Formatting.Compact;
using Umbraco.Core.Logging.Serilog.Enrichers;
namespace Umbraco.Core.Logging.SerilogExtensions
namespace Umbraco.Core.Logging.Serilog
{
public static class LoggerConfigExtensions
{
@@ -16,12 +17,12 @@ namespace Umbraco.Core.Logging.SerilogExtensions
/// <param name="logConfig">A Serilog LoggerConfiguration</param>
public static LoggerConfiguration MinimalConfiguration(this LoggerConfiguration logConfig)
{
Serilog.Debugging.SelfLog.Enable(msg => System.Diagnostics.Debug.WriteLine(msg));
global::Serilog.Debugging.SelfLog.Enable(msg => System.Diagnostics.Debug.WriteLine(msg));
//Set this environment variable - so that it can be used in external config file
//add key="serilog:write-to:RollingFile.pathFormat" value="%BASEDIR%\logs\log.txt" />
Environment.SetEnvironmentVariable("BASEDIR", AppDomain.CurrentDomain.BaseDirectory, EnvironmentVariableTarget.Process);
logConfig.MinimumLevel.Verbose() //Set to highest level of logging (as any sinks may want to restrict it to Errors only)
.Enrich.WithProcessId()
.Enrich.WithProcessName()
@@ -29,8 +30,11 @@ namespace Umbraco.Core.Logging.SerilogExtensions
.Enrich.WithProperty("AppDomainId", AppDomain.CurrentDomain.Id)
.Enrich.WithProperty("AppDomainAppId", HttpRuntime.AppDomainAppId.ReplaceNonAlphanumericChars(string.Empty))
.Enrich.WithProperty("MachineName", Environment.MachineName)
.Enrich.With<Log4NetLevelMapperEnricher>();
.Enrich.With<Log4NetLevelMapperEnricher>()
.Enrich.With<HttpSessionIdEnricher>()
.Enrich.With<HttpRequestNumberEnricher>()
.Enrich.With<HttpRequestIdEnricher>();
return logConfig;
}
@@ -2,41 +2,40 @@
using System.IO;
using System.Reflection;
using System.Threading;
using Umbraco.Core.Configuration;
using Umbraco.Core.Diagnostics;
using Serilog;
using Serilog.Events;
using Umbraco.Core.Logging.SerilogExtensions;
using Umbraco.Core.Configuration;
using Umbraco.Core.Diagnostics;
namespace Umbraco.Core.Logging
namespace Umbraco.Core.Logging.Serilog
{
///<summary>
/// Implements <see cref="ILogger"/> on top of Serilog.
///</summary>
public class Logger : ILogger
public class SerilogLogger : ILogger
{
/// <summary>
/// Initialize a new instance of the <see cref="Logger"/> class with a configuration file.
/// Initialize a new instance of the <see cref="SerilogLogger"/> class with a configuration file.
/// </summary>
/// <param name="logConfigFile"></param>
public Logger(FileInfo logConfigFile)
public SerilogLogger(FileInfo logConfigFile)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.AppSettings(filePath: AppDomain.CurrentDomain.BaseDirectory + logConfigFile)
.CreateLogger();
}
public Logger(LoggerConfiguration logConfig)
public SerilogLogger(LoggerConfiguration logConfig)
{
//Configure Serilog static global logger with config passed in
Log.Logger = logConfig.CreateLogger();
}
/// <summary>
/// Creates a logger with some pre-definied configuration and remainder from config file
/// Creates a logger with some pre-defined configuration and remainder from config file
/// </summary>
/// <remarks>Used by UmbracoApplicationBase to get its logger.</remarks>
public static Logger CreateWithDefaultConfiguration()
public static SerilogLogger CreateWithDefaultConfiguration()
{
var loggerConfig = new LoggerConfiguration();
loggerConfig
@@ -46,78 +45,118 @@ namespace Umbraco.Core.Logging
.ReadFromConfigFile()
.ReadFromUserConfigFile();
return new Logger(loggerConfig);
return new SerilogLogger(loggerConfig);
}
/// <summary>
/// Gets a contextualized logger.
/// </summary>
private global::Serilog.ILogger LoggerFor(Type reporting)
=> Log.Logger.ForContext(reporting);
/// <summary>
/// Maps Umbraco's log level to Serilog's.
/// </summary>
private LogEventLevel MapLevel(LogLevel level)
{
switch (level)
{
case LogLevel.Debug:
return LogEventLevel.Debug;
case LogLevel.Error:
return LogEventLevel.Error;
case LogLevel.Fatal:
return LogEventLevel.Fatal;
case LogLevel.Information:
return LogEventLevel.Information;
case LogLevel.Verbose:
return LogEventLevel.Verbose;
case LogLevel.Warning:
return LogEventLevel.Warning;
}
throw new NotSupportedException($"LogLevel \"{level}\" is not supported.");
}
/// <inheritdoc/>
public bool IsEnabled(Type reporting, LogLevel level)
=> LoggerFor(reporting).IsEnabled(MapLevel(level));
/// <inheritdoc/>
public void Fatal(Type reporting, Exception exception, string message)
{
Fatal(reporting, exception, message, null);
var logger = LoggerFor(reporting);
DumpThreadAborts(logger, LogEventLevel.Fatal, exception, ref message);
logger.Fatal(exception, message);
}
/// <inheritdoc/>
public void Fatal(Type reporting, Exception exception)
{
Fatal(reporting, exception, string.Empty);
var logger = LoggerFor(reporting);
var message = "Exception.";
DumpThreadAborts(logger, LogEventLevel.Fatal, exception, ref message);
logger.Fatal(exception, message);
}
/// <inheritdoc/>
public void Fatal(Type reporting, string message)
{
//Sometimes we need to throw an error without an ex
Fatal(reporting, null, message);
LoggerFor(reporting).Fatal(message);
}
/// <inheritdoc/>
public void Fatal(Type reporting, string messageTemplate, params object[] propertyValues)
{
//Log a structured message WITHOUT an ex
Fatal(reporting, null, messageTemplate, propertyValues);
LoggerFor(reporting).Fatal(messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
ErrorOrFatal(Fatal, exception, ref messageTemplate);
var logger = Log.Logger;
logger?.ForContext(reporting).Fatal(exception, messageTemplate, propertyValues);
var logger = LoggerFor(reporting);
DumpThreadAborts(logger, LogEventLevel.Fatal, exception, ref messageTemplate);
logger.Fatal(exception, messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Error(Type reporting, Exception exception, string message)
{
Error(reporting, exception, message, null);
var logger = LoggerFor(reporting);
DumpThreadAborts(logger, LogEventLevel.Error, exception, ref message);
logger.Error(exception, message);
}
/// <inheritdoc/>
public void Error(Type reporting, Exception exception)
{
Error(reporting, exception, string.Empty);
var logger = LoggerFor(reporting);
var message = "Exception";
DumpThreadAborts(logger, LogEventLevel.Error, exception, ref message);
logger.Error(exception, message);
}
/// <inheritdoc/>
public void Error(Type reporting, string message)
{
//Sometimes we need to throw an error without an ex
Error(reporting, null, message);
LoggerFor(reporting).Error(message);
}
/// <inheritdoc/>
public void Error(Type reporting, string messageTemplate, params object[] propertyValues)
{
//Log a structured message WITHOUT an ex
Error(reporting, null, messageTemplate, propertyValues);
LoggerFor(reporting).Error(messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
ErrorOrFatal(Error, exception, ref messageTemplate);
var logger = Log.Logger;
logger?.ForContext(reporting).Error(exception, messageTemplate, propertyValues);
var logger = LoggerFor(reporting);
DumpThreadAborts(logger, LogEventLevel.Error, exception, ref messageTemplate);
logger.Error(exception, messageTemplate, propertyValues);
}
private static void ErrorOrFatal(Action<Type, Exception, string, object[]> logAction, Exception exception, ref string messageTemplate)
private static void DumpThreadAborts(global::Serilog.ILogger logger, LogEventLevel level, Exception exception, ref string messageTemplate)
{
var dump = false;
@@ -143,8 +182,10 @@ namespace Umbraco.Core.Logging
}
catch (Exception ex)
{
messageTemplate += "\r\nFailed to create a minidump";
//Log a new entry (as opposed to appending to same log entry)
logAction(ex.GetType(), ex, "Failed to create a minidump at App_Data/MiniDump ({ExType}: {ExMessage}",
logger.Write(level, ex, "Failed to create a minidump ({ExType}: {ExMessage})",
new object[]{ ex.GetType().FullName, ex.Message });
}
}
@@ -174,69 +215,63 @@ namespace Umbraco.Core.Logging
}
/// <inheritdoc/>
public void Warn(Type reporting, string format)
public void Warn(Type reporting, string message)
{
Warn(reporting, null, format);
LoggerFor(reporting).Warning(message);
}
/// <inheritdoc/>
public void Warn(Type reporting, string messageTemplate, params object[] propertyValues)
public void Warn(Type reporting, string message, params object[] propertyValues)
{
Warn(reporting, null, messageTemplate, propertyValues);
LoggerFor(reporting).Warning(message, propertyValues);
}
/// <inheritdoc/>
public void Warn(Type reporting, Exception exception, string message)
{
Warn(reporting, exception, message, Array.Empty<object>());
LoggerFor(reporting).Warning(exception, message);
}
/// <inheritdoc/>
public void Warn(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
var logger = Log.Logger;
logger?.ForContext(reporting).Warning(exception, messageTemplate, propertyValues);
LoggerFor(reporting).Warning(exception, messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Info(Type reporting, string message)
{
Info(reporting, message, Array.Empty<object>());
LoggerFor(reporting).Information(message);
}
/// <inheritdoc/>
public void Info(Type reporting, string messageTemplate, params object[] propertyValues)
{
var logger = Log.Logger;
logger?.ForContext(reporting).Information(messageTemplate, propertyValues);
LoggerFor(reporting).Information(messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Debug(Type reporting, string message)
{
Debug(reporting, message, Array.Empty<object>());
LoggerFor(reporting).Debug(message);
}
/// <inheritdoc/>
public void Debug(Type reporting, string messageTemplate, params object[] propertyValues)
{
var logger = Log.Logger;
logger?.ForContext(reporting).Debug(messageTemplate, propertyValues);
LoggerFor(reporting).Debug(messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Verbose(Type reporting, string message)
{
Verbose(reporting, message, Array.Empty<object>());
LoggerFor(reporting).Verbose(message);
}
/// <inheritdoc/>
public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues)
{
var logger = Log.Logger;
logger?.ForContext(reporting).Verbose(messageTemplate, propertyValues);
LoggerFor(reporting).Verbose(messageTemplate, propertyValues);
}
}
}
-21
View File
@@ -1,21 +0,0 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
namespace Umbraco.Core.Media
{
public static class ImageExtensions
{
/// <summary>
/// Gets the MIME type of an image.
/// </summary>
/// <param name="image">The image.</param>
/// <returns>The MIME type of the image.</returns>
public static string GetMimeType(this Image image)
{
var format = image.RawFormat;
var codec = ImageCodecInfo.GetImageDecoders().First(c => c.FormatID == format.Guid);
return codec.MimeType;
}
}
}
+11 -7
View File
@@ -32,6 +32,7 @@ namespace Umbraco.Core.Models
/// <param name="name">Name of the content</param>
/// <param name="parent">Parent <see cref="IContent"/> object</param>
/// <param name="contentType">ContentType for the current Content object</param>
/// <param name="culture">An optional culture.</param>
public Content(string name, IContent parent, IContentType contentType, string culture = null)
: this(name, parent, contentType, new PropertyCollection(), culture)
{ }
@@ -43,6 +44,7 @@ namespace Umbraco.Core.Models
/// <param name="parent">Parent <see cref="IContent"/> object</param>
/// <param name="contentType">ContentType for the current Content object</param>
/// <param name="properties">Collection of properties</param>
/// <param name="culture">An optional culture.</param>
public Content(string name, IContent parent, IContentType contentType, PropertyCollection properties, string culture = null)
: base(name, parent, contentType, properties, culture)
{
@@ -57,6 +59,7 @@ namespace Umbraco.Core.Models
/// <param name="name">Name of the content</param>
/// <param name="parentId">Id of the Parent content</param>
/// <param name="contentType">ContentType for the current Content object</param>
/// <param name="culture">An optional culture.</param>
public Content(string name, int parentId, IContentType contentType, string culture = null)
: this(name, parentId, contentType, new PropertyCollection(), culture)
{ }
@@ -68,6 +71,7 @@ namespace Umbraco.Core.Models
/// <param name="parentId">Id of the Parent content</param>
/// <param name="contentType">ContentType for the current Content object</param>
/// <param name="properties">Collection of properties</param>
/// <param name="culture">An optional culture.</param>
public Content(string name, int parentId, IContentType contentType, PropertyCollection properties, string culture = null)
: base(name, parentId, contentType, properties, culture)
{
@@ -213,23 +217,23 @@ namespace Umbraco.Core.Models
[IgnoreDataMember]
public IEnumerable<string> PublishedCultures => _publishInfos?.Keys ?? Enumerable.Empty<string>();
//fixme should this return false if ID == 0?
//fixme should this return false if IsCultureAvailable(culture) is false?
/// <inheritdoc />
public bool IsCulturePublished(string culture)
// just check _publishInfos
// a non-available culture could not become published anyways
=> _publishInfos != null && _publishInfos.ContainsKey(culture);
//fixme should this return false if ID == 0?
//fixme should this return false if IsCultureAvailable(culture) is false?
/// <inheritdoc />
public bool WasCulturePublished(string culture)
// just check _publishInfosOrig - a copy of _publishInfos
// a non-available culture could not become published anyways
=> _publishInfosOrig != null && _publishInfosOrig.ContainsKey(culture);
//fixme should this return false if ID == 0?
//fixme should this return false if IsCultureAvailable(culture) is false?
/// <inheritdoc />
public bool IsCultureEdited(string culture)
=> !IsCulturePublished(culture) || (_editedCultures != null && _editedCultures.Contains(culture));
=> IsCultureAvailable(culture) && // is available, and
(!IsCulturePublished(culture) || // is not published, or
(_editedCultures != null && _editedCultures.Contains(culture))); // is edited
/// <inheritdoc/>
[IgnoreDataMember]
-20
View File
@@ -280,26 +280,6 @@ namespace Umbraco.Core.Models
Properties.Add(property);
}
// HttpPostedFileBase is the base class that can be mocked
// HttpPostedFile is what we get in ASP.NET
// HttpPostedFileWrapper wraps sealed HttpPostedFile as HttpPostedFileBase
/// <summary>
/// Sets the posted file value of a property.
/// </summary>
public virtual void SetValue(string propertyTypeAlias, HttpPostedFile value, string culture = null, string segment = null)
{
ContentExtensions.SetValue(this, propertyTypeAlias, new HttpPostedFileWrapper(value), culture, segment);
}
/// <summary>
/// Sets the posted file value of a property.
/// </summary>
public virtual void SetValue(string propertyTypeAlias, HttpPostedFileBase value, string culture = null, string segment = null)
{
ContentExtensions.SetValue(this, propertyTypeAlias, value, culture, segment);
}
#endregion
#region Copy
+24
View File
@@ -98,6 +98,30 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Determines if AllowedTemplates contains templateId
/// </summary>
/// <param name="templateId">The template id to check</param>
/// <returns>True if AllowedTemplates contains the templateId else False</returns>
public bool IsAllowedTemplate(int templateId)
{
return AllowedTemplates == null
? false
: AllowedTemplates.Any(t => t.Id == templateId);
}
/// <summary>
/// Determines if AllowedTemplates contains templateId
/// </summary>
/// <param name="templateAlias">The template alias to check</param>
/// <returns>True if AllowedTemplates contains the templateAlias else False</returns>
public bool IsAllowedTemplate(string templateAlias)
{
return AllowedTemplates == null
? false
: AllowedTemplates.Any(t => t.Alias.Equals(templateAlias, StringComparison.InvariantCultureIgnoreCase));
}
/// <summary>
/// Sets the default template for the ContentType
/// </summary>
+6 -4
View File
@@ -87,6 +87,8 @@ namespace Umbraco.Core.Models
/// <para>A culture becomes published whenever values for this culture are published,
/// and the content published name for this culture is non-null. It becomes non-published
/// whenever values for this culture are unpublished.</para>
/// <para>A culture becomes published as soon as PublishCulture has been invoked,
/// even though the document might now have been saved yet (and can have no identity).</para>
/// </remarks>
bool IsCulturePublished(string culture);
@@ -107,8 +109,9 @@ namespace Umbraco.Core.Models
/// Gets a value indicated whether a given culture is edited.
/// </summary>
/// <remarks>
/// <para>A culture is edited when it is not published, or when it is published but
/// it has changes.</para>
/// <para>A culture is edited when it is available, and not published or published but
/// with changes.</para>
/// <para>A culture can be edited even though the document might now have been saved yet (and can have no identity).</para>
/// </remarks>
bool IsCultureEdited(string culture);
@@ -169,10 +172,9 @@ namespace Umbraco.Core.Models
/// </summary>
/// <returns>A value indicating whether the culture can be published.</returns>
/// <remarks>
/// <para>Fails if values cannot be published, e.g. if some values are not valid.</para>
/// <para>Fails if properties don't pass variant validtion rules.</para>
/// <para>Publishing must be finalized via the content service SavePublishing method.</para>
/// </remarks>
// fixme - should return an attempt with error results
bool PublishCulture(string culture = "*");
/// <summary>
+1 -1
View File
@@ -139,7 +139,7 @@ namespace Umbraco.Core.Models
// fixme validate published cultures?
/// <summary>
/// Validates the content item's properties.
/// Validates the content item's properties pass variant rules
/// </summary>
/// <para>If the content type is variant, then culture can be either '*' or an actual culture, but neither 'null' nor
/// 'empty'. If the content type is invariant, then culture can be either '*' or null or empty.</para>
+14
View File
@@ -17,6 +17,20 @@ namespace Umbraco.Core.Models
/// </summary>
IEnumerable<ITemplate> AllowedTemplates { get; set; }
/// <summary>
/// Determines if AllowedTemplates contains templateId
/// </summary>
/// <param name="templateId">The template id to check</param>
/// <returns>True if AllowedTemplates contains the templateId else False</returns>
bool IsAllowedTemplate(int templateId);
/// <summary>
/// Determines if AllowedTemplates contains templateId
/// </summary>
/// <param name="templateAlias">The template alias to check</param>
/// <returns>True if AllowedTemplates contains the templateAlias else False</returns>
bool IsAllowedTemplate(string templateAlias);
/// <summary>
/// Sets the default template for the ContentType
/// </summary>
@@ -93,14 +93,6 @@ namespace Umbraco.Core.Models.Identity
_roles.CollectionChanged += _roles_CollectionChanged;
}
public virtual async Task<ClaimsIdentity> GenerateUserIdentityAsync(BackOfficeUserManager<BackOfficeIdentityUser> manager)
{
// NOTE the authenticationType must match the umbraco one
// defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, Constants.Security.BackOfficeAuthenticationType);
return userIdentity;
}
/// <summary>
/// Returns true if an Id has been set on this object this will be false if the object is new and not peristed to the database
/// </summary>
+5 -1
View File
@@ -260,7 +260,7 @@ namespace Umbraco.Core.Models.Membership
{
get
{
if (LastLoginDate == default(DateTime) && IsApproved == false && InvitedDate != null)
if (LastLoginDate == default && IsApproved == false && InvitedDate != null)
return UserState.Invited;
if (IsLockedOut)
@@ -268,6 +268,10 @@ namespace Umbraco.Core.Models.Membership
if (IsApproved == false)
return UserState.Disabled;
// User is not disabled or locked and has never logged in before
if (LastLoginDate == default && IsApproved && IsLockedOut == false)
return UserState.Inactive;
return UserState.Active;
}
}
@@ -9,6 +9,7 @@
Active = 0,
Disabled = 1,
LockedOut = 2,
Invited = 3
Invited = 3,
Inactive = 4
}
}
-8
View File
@@ -1,14 +1,6 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Services;
using Umbraco.Core.Strings;
namespace Umbraco.Core.Models
-3
View File
@@ -10,9 +10,6 @@ namespace Umbraco.Core
/// <summary>
/// Returns the machine name that is safe to use in file paths.
/// </summary>
/// <remarks>
/// see: https://github.com/Shandem/ClientDependency/issues/4
/// </remarks>
public static string FileSafeMachineName
{
get { return MachineName.ReplaceNonAlphanumericChars('-'); }
@@ -1073,7 +1073,10 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
NodeId = content.Id,
LanguageId = LanguageRepository.GetIdByIsoCode(culture) ?? throw new InvalidOperationException("Not a valid culture."),
Culture = culture,
Edited = !content.IsCulturePublished(culture) || (editedCultures != null && editedCultures.Contains(culture)) // if not published, always edited
// if not published, always edited
// no need to check for availability: it *is* available since it is in content.CultureNames
Edited = !content.IsCulturePublished(culture) || (editedCultures != null && editedCultures.Contains(culture))
};
}
@@ -150,6 +150,8 @@ UNION
SELECT '4CountOfLockedOut' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userNoConsole = 1
UNION
SELECT '5CountOfInvited' AS colName, COUNT(id) AS num FROM umbracoUser WHERE lastLoginDate IS NULL AND userDisabled = 1 AND invitedDate IS NOT NULL
UNION
SELECT '6CountOfDisabled' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NULL
ORDER BY colName";
var result = Database.Fetch<dynamic>(sql);
@@ -160,7 +162,8 @@ ORDER BY colName";
{UserState.Active, (int) result[1].num},
{UserState.Disabled, (int) result[2].num},
{UserState.LockedOut, (int) result[3].num},
{UserState.Invited, (int) result[4].num}
{UserState.Invited, (int) result[4].num},
{UserState.Inactive, (int) result[5].num}
};
}
@@ -766,6 +769,12 @@ ORDER BY colName";
sb.Append("(userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NOT NULL)");
appended = true;
}
if (userState.Contains(UserState.Inactive))
{
if (appended) sb.Append(" OR ");
sb.Append("(userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NULL)");
appended = true;
}
if (userState.Contains(UserState.Disabled))
{
if (appended) sb.Append(" OR ");
@@ -143,19 +143,19 @@ namespace Umbraco.Core.Persistence.SqlSyntax
/// <returns></returns>
public IEnumerable<Tuple<string, string, string, string>> GetDefaultConstraintsPerColumn(IDatabase db)
{
var items = db.Fetch<dynamic>("SELECT TableName = t.Name,ColumnName = c.Name,dc.Name,dc.[Definition] FROM sys.tables t INNER JOIN sys.default_constraints dc ON t.object_id = dc.parent_object_id INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id");
var items = db.Fetch<dynamic>("SELECT TableName = t.Name, ColumnName = c.Name, dc.Name, dc.[Definition] FROM sys.tables t INNER JOIN sys.default_constraints dc ON t.object_id = dc.parent_object_id INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id INNER JOIN sys.schemas as s on t.[schema_id] = s.[schema_id] WHERE s.name = (SELECT SCHEMA_NAME())");
return items.Select(x => new Tuple<string, string, string, string>(x.TableName, x.ColumnName, x.Name, x.Definition));
}
public override IEnumerable<string> GetTablesInSchema(IDatabase db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES");
var items = db.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
return items.Select(x => x.TABLE_NAME).Cast<string>().ToList();
}
public override IEnumerable<ColumnInfo> GetColumnsInSchema(IDatabase db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS");
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
return
items.Select(
item =>
@@ -168,7 +168,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
{
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE");
"SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
return items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList();
}
@@ -177,7 +177,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
{
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE");
"SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
return items.Select(item => new Tuple<string, string, string>(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)).ToList();
}
@@ -191,7 +191,8 @@ CASE WHEN I.is_unique_constraint = 1 OR I.is_unique = 1 THEN 1 ELSE 0 END AS [U
from sys.tables as T inner join sys.indexes as I on T.[object_id] = I.[object_id]
inner join sys.index_columns as IC on IC.[object_id] = I.[object_id] and IC.[index_id] = I.[index_id]
inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id]
WHERE I.is_primary_key = 0
inner join sys.schemas as S on T.[schema_id] = S.[schema_id]
WHERE S.name = (SELECT SCHEMA_NAME()) AND I.is_primary_key = 0
order by T.name, I.name");
return items.Select(item => new Tuple<string, string, string, bool>(item.TABLE_NAME, item.INDEX_NAME, item.COLUMN_NAME,
item.UNIQUE == 1)).ToList();
@@ -201,7 +202,7 @@ order by T.name, I.name");
public override bool DoesTableExist(IDatabase db, string tableName)
{
var result =
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName",
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName AND TABLE_SCHEMA = (SELECT SCHEMA_NAME())",
new { TableName = tableName });
return result > 0;
@@ -138,7 +138,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters // fixme MOVE TO MODELS O
/// </summary>
/// <returns></returns>
public bool HasFocalPoint()
=> FocalPoint != null && FocalPoint.Left != 0.5m && FocalPoint.Top != 0.5m;
=> FocalPoint != null && (FocalPoint.Left != 0.5m || FocalPoint.Top != 0.5m);
/// <summary>
/// Determines whether the value has a specified crop.
@@ -720,7 +720,7 @@ namespace Umbraco.Core.Security
}
else
{
//if the salt bytes is too long for the required key length for the algorithm, extend it
//if the salt bytes is too short for the required key length for the algorithm, extend it
var numArray2 = new byte[keyedHashAlgorithm.Key.Length];
var dstOffset = 0;
while (dstOffset < numArray2.Length)
@@ -645,7 +645,7 @@ namespace Umbraco.Core.Services.Implement
{
using (var scope = ScopeProvider.CreateScope(autoComplete: true))
{
return _userRepository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, member => member.Username);
return _userRepository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, member => member.Name);
}
}
+10 -1
View File
@@ -11,6 +11,10 @@ namespace Umbraco.Core.Services
/// Represents the result of a service operation.
/// </summary>
/// <typeparam name="TResultType">The type of the result type.</typeparam>
/// <remarks>Type <typeparamref name="TResultType"/> must be an enumeration, and its
/// underlying type must be byte. Values indicating success should be in the 0-127
/// range, while values indicating failure should be in the 128-255 range. See
/// <see cref="OperationResultType"/> for a base implementation.</remarks>
public class OperationResult<TResultType>
where TResultType : struct
{
@@ -56,6 +60,10 @@ namespace Umbraco.Core.Services
/// </summary>
/// <typeparam name="TResultType">The type of the result type.</typeparam>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <remarks>Type <typeparamref name="TResultType"/> must be an enumeration, and its
/// underlying type must be byte. Values indicating success should be in the 0-127
/// range, while values indicating failure should be in the 128-255 range. See
/// <see cref="OperationResultType"/> for a base implementation.</remarks>
public class OperationResult<TResultType, TEntity> : OperationResult<TResultType>
where TResultType : struct
{
@@ -111,7 +119,8 @@ namespace Umbraco.Core.Services
return new OperationResult(OperationResultType.FailedCancelledByEvent, eventMessages);
}
// fixme wtf?
// fixme - this exists to support services that still return Attempt<OperationResult>
// these services should directly return an OperationResult, and then this static class should be deleted
internal static class Attempt
{
/// <summary>
+26 -64
View File
@@ -38,8 +38,6 @@
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data.Entity" />
<Reference Include="System.DirectoryServices.AccountManagement" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Runtime.Caching" />
@@ -58,21 +56,22 @@
<ItemGroup>
<!-- note: NuGet deals with transitive references now -->
<PackageReference Include="AutoMapper" Version="7.0.1" />
<PackageReference Include="ClientDependency" Version="1.9.6" />
<PackageReference Include="HtmlAgilityPack" Version="1.7.2" />
<PackageReference Include="ImageProcessor" Version="2.6.1.19" />
<PackageReference Include="LightInject" Version="5.1.2" />
<PackageReference Include="LightInject.Annotation" Version="1.1.0" />
<PackageReference Include="LightInject.Web" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNet.Identity.Owin" Version="2.2.1" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.6" />
<PackageReference Include="Microsoft.Owin.Security.Cookies" Version="4.0.0" />
<PackageReference Include="Microsoft.Owin.Security.OAuth" Version="4.0.0" />
<PackageReference Include="Microsoft.Web.Xdt" Version="2.1.2" />
<PackageReference Include="Microsoft.AspNet.Identity.Core">
<Version>2.2.2</Version>
</PackageReference>
<PackageReference Include="Microsoft.AspNet.WebApi.Client">
<Version>5.2.6</Version>
</PackageReference>
<PackageReference Include="Microsoft.Owin">
<Version>4.0.0</Version>
</PackageReference>
<PackageReference Include="MiniProfiler" Version="3.2.0.157" />
<PackageReference Include="MySql.Data" Version="6.10.7" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="NPoco" Version="3.9.3" />
<PackageReference Include="NPoco" Version="3.9.4" />
<PackageReference Include="Semver" Version="2.0.4" />
<PackageReference Include="Serilog">
<Version>2.7.1</Version>
@@ -113,8 +112,7 @@
<Compile Include="Attempt.cs" />
<Compile Include="AttemptOfTResult.cs" />
<Compile Include="AttemptOfTResultTStatus.cs" />
<Compile Include="Auditing\AuditEventsComponent.cs" />
<Compile Include="Auditing\IdentityAuditEventArgs.cs" />
<Compile Include="Components\AuditEventsComponent.cs" />
<Compile Include="BindingRedirects.cs" />
<Compile Include="ByteArrayExtensions.cs" />
<Compile Include="Cache\CacheHelper.cs" />
@@ -197,7 +195,6 @@
<Compile Include="Composing\WeightAttribute.cs" />
<Compile Include="Composing\WeightedCollectionBuilderBase.cs" />
<Compile Include="Configuration\CaseInsensitiveEnumConfigConverter.cs" />
<Compile Include="Configuration\ClientDependencyConfiguration.cs" />
<Compile Include="Configuration\CommaDelimitedConfigurationElement.cs" />
<Compile Include="Configuration\CoreDebug.cs" />
<Compile Include="Configuration\Dashboard\AccessElement.cs" />
@@ -341,6 +338,13 @@
<Compile Include="Logging\Viewer\LogMessage.cs" />
<Compile Include="Logging\Viewer\LogViewerComponent.cs" />
<Compile Include="Logging\Viewer\LogViewerSourceBase.cs" />
<Compile Include="Logging\LogLevel.cs" />
<Compile Include="Logging\MessageTemplates.cs" />
<Compile Include="Logging\Serilog\Enrichers\HttpRequestIdEnricher.cs" />
<Compile Include="Logging\Serilog\Enrichers\HttpRequestNumberEnricher.cs" />
<Compile Include="Logging\Serilog\Enrichers\HttpSessionIdEnricher.cs" />
<Compile Include="Logging\Serilog\LoggerConfigExtensions.cs" />
<Compile Include="Logging\Serilog\Enrichers\Log4NetLevelMapperEnricher.cs" />
<Compile Include="Migrations\MigrationBase_Extra.cs" />
<Compile Include="Migrations\Upgrade\V_7_10_0\RenamePreviewFolder.cs" />
<Compile Include="Migrations\Upgrade\V_7_12_0\AddRelationTypeForMediaFolderOnDelete.cs" />
@@ -577,9 +581,8 @@
<Compile Include="ListExtensions.cs" />
<Compile Include="Logging\DebugDiagnosticsLogger.cs" />
<Compile Include="Logging\ILogger.cs" />
<Compile Include="Logging\ImageProcessorLogger.cs" />
<Compile Include="Logging\IProfiler.cs" />
<Compile Include="Logging\Logger.cs" />
<Compile Include="Logging\Serilog\SerilogLogger.cs" />
<Compile Include="Logging\LoggerExtensions.cs" />
<Compile Include="Logging\LoggingTaskExtension.cs" />
<Compile Include="Logging\LogProfiler.cs" />
@@ -592,49 +595,17 @@
<Compile Include="Logging\WebProfilerComponent.cs" />
<Compile Include="Logging\WebProfilerProvider.cs" />
<Compile Include="Macros\MacroErrorBehaviour.cs" />
<Compile Include="Macros\MacroTagParser.cs" />
<Compile Include="MainDom.cs" />
<Compile Include="Manifest\ManifestParser.cs" />
<Compile Include="Manifest\ValueValidatorConverter.cs" />
<Compile Include="Manifest\ManifestWatcher.cs" />
<Compile Include="Manifest\PackageManifest.cs" />
<Compile Include="Manifest\DataEditorConverter.cs" />
<Compile Include="Media\Exif\BitConverterEx.cs" />
<Compile Include="Media\Exif\ExifBitConverter.cs" />
<Compile Include="Media\Exif\ExifEnums.cs" />
<Compile Include="Media\Exif\ExifExceptions.cs" />
<Compile Include="Media\Exif\ExifExtendedProperty.cs" />
<Compile Include="Media\Exif\ExifFileTypeDescriptor.cs" />
<Compile Include="Media\Exif\ExifInterOperability.cs" />
<Compile Include="Media\Exif\ExifProperty.cs" />
<Compile Include="Media\Exif\ExifPropertyCollection.cs" />
<Compile Include="Media\Exif\ExifPropertyFactory.cs" />
<Compile Include="Media\Exif\ExifTag.cs" />
<Compile Include="Media\Exif\ExifTagFactory.cs" />
<Compile Include="Media\Exif\IFD.cs" />
<Compile Include="Media\Exif\ImageFile.cs" />
<Compile Include="Media\Exif\ImageFileDirectory.cs" />
<Compile Include="Media\Exif\ImageFileDirectoryEntry.cs" />
<Compile Include="Media\Exif\ImageFileFormat.cs" />
<Compile Include="Media\Exif\JFIFEnums.cs" />
<Compile Include="Media\Exif\JFIFExtendedProperty.cs" />
<Compile Include="Media\Exif\JFIFThumbnail.cs" />
<Compile Include="Media\Exif\JPEGExceptions.cs" />
<Compile Include="Media\Exif\JPEGFile.cs" />
<Compile Include="Media\Exif\JPEGMarker.cs" />
<Compile Include="Media\Exif\JPEGSection.cs" />
<Compile Include="Media\Exif\MathEx.cs" />
<Compile Include="Media\Exif\TIFFFile.cs" />
<Compile Include="Media\Exif\TIFFHeader.cs" />
<Compile Include="Media\Exif\TIFFStrip.cs" />
<Compile Include="Media\Exif\Utility.cs" />
<Compile Include="Media\IEmbedProvider.cs" />
<Compile Include="Media\IEmbedSettingProvider.cs" />
<Compile Include="Media\ImageExtensions.cs" />
<Compile Include="Media\ProviderSetting.cs" />
<Compile Include="Media\Result.cs" />
<Compile Include="Media\Status.cs" />
<Compile Include="Media\UploadAutoFillProperties.cs" />
<Compile Include="Migrations\IPostMigration.cs" />
<Compile Include="Migrations\MigrationBuilder.cs" />
<Compile Include="Migrations\MigrationPlan.cs" />
@@ -651,7 +622,7 @@
<Compile Include="Models\AuditType.cs" />
<Compile Include="Models\Content.cs" />
<Compile Include="Models\ContentBase.cs" />
<Compile Include="Models\ContentExtensions.cs" />
<Compile Include="ContentExtensions.cs" />
<Compile Include="Models\ContentStatus.cs" />
<Compile Include="Models\ContentType.cs" />
<Compile Include="Models\ContentTypeAvailableCompositionsResult.cs" />
@@ -1316,19 +1287,10 @@
<Compile Include="Scoping\ScopeContextualBase.cs" />
<Compile Include="Scoping\ScopeProvider.cs" />
<Compile Include="Scoping\ScopeReference.cs" />
<Compile Include="Security\ActiveDirectoryBackOfficeUserPasswordChecker.cs" />
<Compile Include="Security\AuthenticationExtensions.cs" />
<Compile Include="Security\BackOfficeClaimsIdentityFactory.cs" />
<Compile Include="Security\BackOfficeCookieAuthenticationProvider.cs" />
<Compile Include="Security\BackOfficeSignInManager.cs" />
<Compile Include="Security\BackOfficeUserManager.cs" />
<Compile Include="Security\BackOfficeUserManagerMarker.cs" />
<Compile Include="Security\BackOfficeUserPasswordCheckerResult.cs" />
<Compile Include="Security\BackOfficeUserStore.cs" />
<Compile Include="Security\BackOfficeUserValidator.cs" />
<Compile Include="Security\EmailService.cs" />
<Compile Include="Security\IBackOfficeUserManagerMarker.cs" />
<Compile Include="Security\IBackOfficeUserPasswordChecker.cs" />
<Compile Include="Security\IMembershipProviderPasswordHasher.cs" />
<Compile Include="Security\IUmbracoMemberTypeMembershipProvider.cs" />
<Compile Include="Security\IUserAwarePasswordHasher.cs" />
@@ -1339,8 +1301,6 @@
<Compile Include="Security\MembershipProviderExtensions.cs" />
<Compile Include="Security\MembershipProviderPasswordHasher.cs" />
<Compile Include="Security\MembershipProviderPasswordValidator.cs" />
<Compile Include="Security\OwinExtensions.cs" />
<Compile Include="Security\SessionIdValidator.cs" />
<Compile Include="Security\UmbracoBackOfficeIdentity.cs" />
<Compile Include="Security\UmbracoEmailMessage.cs" />
<Compile Include="Security\UmbracoMembershipProviderBase.cs" />
@@ -1457,9 +1417,9 @@
<Compile Include="Services\UnpublishResultType.cs" />
<Compile Include="Services\UserServiceExtensions.cs" />
<Compile Include="Settable.cs" />
<Compile Include="Strategies\ManifestWatcherComponent.cs" />
<Compile Include="Strategies\RelateOnCopyComponent.cs" />
<Compile Include="Strategies\RelateOnTrashComponent.cs" />
<Compile Include="Components\ManifestWatcherComponent.cs" />
<Compile Include="Components\RelateOnCopyComponent.cs" />
<Compile Include="Components\RelateOnTrashComponent.cs" />
<Compile Include="StringExtensions.cs" />
<Compile Include="Strings\CleanStringType.cs" />
<Compile Include="Strings\ContentBaseExtensions.cs" />
@@ -1541,6 +1501,8 @@
<ItemGroup>
<EmbeddedResource Include="FileResources\Files.resx" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Folder Include="Auditing\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+8 -17
View File
@@ -4,10 +4,9 @@ using System.Threading;
using System.Web;
using System.Web.Hosting;
using LightInject;
using Serilog;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using ILogger = Umbraco.Core.Logging.ILogger;
using Umbraco.Core.Logging.Serilog;
namespace Umbraco.Core
{
@@ -28,7 +27,7 @@ namespace Umbraco.Core
/// </summary>
protected virtual ILogger GetLogger()
{
return Logger.CreateWithDefaultConfiguration();
return SerilogLogger.CreateWithDefaultConfiguration();
}
// events - in the order they trigger
@@ -161,13 +160,6 @@ namespace Umbraco.Core
_runtime = null;
}
// dispose the container and everything
// but first, capture the looger!
var logger = Current.Logger;
Current.Reset();
if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted) return;
// try to log the detailed shutdown message (typical asp.net hack: http://weblogs.asp.net/scottgu/433194)
try
{
@@ -185,7 +177,7 @@ namespace Umbraco.Core
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField,
null, runtime, null);
logger.Info<UmbracoApplicationBase>("Application shutdown. Details: {ShutdownReason}\r\n\r\n_shutDownMessage={ShutdownMessage}\r\n\r\n_shutDownStack={ShutdownStack}",
Current.Logger.Info<UmbracoApplicationBase>("Application shutdown. Details: {ShutdownReason}\r\n\r\n_shutDownMessage={ShutdownMessage}\r\n\r\n_shutDownStack={ShutdownStack}",
HostingEnvironment.ShutdownReason,
shutDownMessage,
shutDownStack);
@@ -193,20 +185,19 @@ namespace Umbraco.Core
catch (Exception)
{
//if for some reason that fails, then log the normal output
logger.Info<UmbracoApplicationBase>("Application shutdown. Reason: {ShutdownReason}", HostingEnvironment.ShutdownReason);
Current.Logger.Info<UmbracoApplicationBase>("Application shutdown. Reason: {ShutdownReason}", HostingEnvironment.ShutdownReason);
}
// dispose the container and everything
Current.Reset();
}
// called by ASP.NET (auto event wireup) once per app domain
// sender is System.Web.HttpApplicationFactory, evargs is EventArgs.Empty
protected void Application_End(object sender, EventArgs evargs)
{
HandleApplicationEnd();
OnApplicationEnd(sender, evargs);
//Not sure if we need to do this - as my POC approach I never had to deal with this
//As the LightInject container when tearing down will dispose of Serilog AFAIK
Log.CloseAndFlush();
HandleApplicationEnd();
}
#endregion
+1 -1
View File
@@ -50,7 +50,7 @@
<!-- note: NuGet deals with transitive references now -->
<PackageReference Include="Examine" Version="1.0.0-beta025" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="NPoco" Version="3.9.3" />
<PackageReference Include="NPoco" Version="3.9.4" />
</ItemGroup>
<ItemGroup>
<Compile Include="Config\ConfigIndexCriteria.cs" />
@@ -61,19 +61,17 @@
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.10.13" />
<PackageReference Include="BenchmarkDotNet.Toolchains.Roslyn" Version="0.10.13" />
<PackageReference Include="Castle.Core" Version="4.2.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.8.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="2.8.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.9.0" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.11" />
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.0" />
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="2.0.4" />
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
<PackageReference Include="Moq" Version="4.8.2" />
<PackageReference Include="NPoco" Version="3.9.3" />
<PackageReference Include="NPoco" Version="3.9.4" />
<PackageReference Include="Umbraco.SqlServerCE" Version="4.0.0.1" />
<PackageReference Include="System.AppContext" Version="4.3.0" />
<PackageReference Include="System.Collections" Version="4.3.0" />
<PackageReference Include="System.Collections.Concurrent" Version="4.3.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
<PackageReference Include="System.Console" Version="4.3.0" />
<PackageReference Include="System.Diagnostics.Debug" Version="4.3.0" />
<PackageReference Include="System.Diagnostics.FileVersionInfo" Version="4.3.0" />
@@ -87,7 +85,6 @@
<PackageReference Include="System.Linq" Version="4.3.0" />
<PackageReference Include="System.Linq.Expressions" Version="4.3.0" />
<PackageReference Include="System.Reflection" Version="4.3.0" />
<PackageReference Include="System.Reflection.Metadata" Version="1.5.0" />
<PackageReference Include="System.Reflection.Primitives" Version="4.3.0" />
<PackageReference Include="System.Resources.ResourceManager" Version="4.3.0" />
<PackageReference Include="System.Runtime" Version="4.3.0" />
+5 -5
View File
@@ -7,11 +7,11 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.8.0.0" newVersion="2.8.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-2.9.0.0" newVersion="2.9.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.8.0.0" newVersion="2.8.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-2.9.0.0" newVersion="2.9.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Diagnostics.Tracing.TraceEvent" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
@@ -55,7 +55,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.2.2.0" newVersion="1.2.2.0"/>
<bindingRedirect oldVersion="0.0.0.0-1.2.3.0" newVersion="1.2.3.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
@@ -167,7 +167,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.4.2.0" newVersion="1.4.2.0"/>
<bindingRedirect oldVersion="0.0.0.0-1.4.3.0" newVersion="1.4.3.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Reflection.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
@@ -267,7 +267,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
@@ -23,6 +23,12 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings
Assert.IsTrue(SettingsSection.WebRouting.DisableAlternativeTemplates == false);
}
[Test]
public void ValidateAlternativeTemplates()
{
Assert.IsTrue(SettingsSection.WebRouting.ValidateAlternativeTemplates == false);
}
[Test]
public void DisableFindContentByIdPath()
{
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using NUnit.Framework;
using Umbraco.Core.Macros;
using Umbraco.Web.Macros;
namespace Umbraco.Tests.Macros
{
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Tests.Testing;
+1
View File
@@ -7,6 +7,7 @@ using System.Linq;
using System.Web;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
+1 -1
View File
@@ -29,7 +29,7 @@ namespace Umbraco.Tests.Models
// reference, so static ctor runs, so event handlers register
// and then, this will reset the width, height... because the file does not exist, of course ;-(
var ignored = new FileUploadPropertyEditor(Mock.Of<ILogger>(), new MediaFileSystem(Mock.Of<IFileSystem>()));
var ignored = new FileUploadPropertyEditor(Mock.Of<ILogger>(), new MediaFileSystem(Mock.Of<IFileSystem>()), Mock.Of<IContentSection>());
var media = MockedMedia.CreateMediaImage(mediaType, -1);
media.WriterId = -1; // else it's zero and that's not a user and it breaks the tests
+5 -4
View File
@@ -430,14 +430,15 @@ namespace Umbraco.Tests.Models
Assert.IsTrue(content.IsCultureAvailable(langUk));
Assert.IsFalse(content.IsCulturePublished(langUk));
Assert.IsNull(content.GetPublishName(langUk));
Assert.IsNull(content.GetPublishDate(langUk)); // not published
Assert.IsTrue(content.IsCultureEdited(langEs)); // not published, so... edited
Assert.IsNull(content.GetPublishDate(langUk)); // not published
Assert.IsFalse(content.IsCultureAvailable(langEs));
Assert.IsFalse(content.IsCultureEdited(langEs)); // not avail, so... not edited
Assert.IsFalse(content.IsCulturePublished(langEs));
// not published!
Assert.IsNull(content.GetPublishName(langEs));
Assert.IsNull(content.GetPublishDate(langEs)); // not published!
Assert.IsTrue(content.IsCultureEdited(langEs)); // not published, so... edited
Assert.IsNull(content.GetPublishDate(langEs));
// cannot test IsCultureEdited here - as that requires the content service and repository
// see: ContentServiceTests.Can_SaveRead_Variations
@@ -45,7 +45,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Assert
Assert.That(language, Is.Not.Null);
Assert.That(language.HasIdentity, Is.True);
Assert.That(language.CultureName, Is.EqualTo("en-US"));
Assert.That(language.CultureName, Is.EqualTo("English (United States)"));
Assert.That(language.IsoCode, Is.EqualTo("en-US"));
}
}
@@ -222,7 +222,7 @@ namespace Umbraco.Tests.Persistence.Repositories
using (var scope = provider.CreateScope())
{
var repository = CreateRepository(provider);
var languageBR = (ILanguage)new Language("pt-BR") { CultureName = "pt-BR", IsDefaultVariantLanguage = true, Mandatory = true };
repository.Save(languageBR);
var languageEN = new Language("en-AU") { CultureName = "en-AU" };
@@ -15,6 +15,7 @@ using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.PropertyEditors.ValueConverters;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web.Models;
using Umbraco.Web;
@@ -77,7 +78,7 @@ namespace Umbraco.Tests.PropertyEditors
var mediaFileSystem = new MediaFileSystem(Mock.Of<IFileSystem>());
var dataTypeService = new TestObjects.TestDataTypeService(
new DataType(new ImageCropperPropertyEditor(Mock.Of<ILogger>(), mediaFileSystem, Mock.Of<IContentSection>())) { Id = 1 });
new DataType(new ImageCropperPropertyEditor(Mock.Of<ILogger>(), mediaFileSystem, Mock.Of<IContentSection>(), Mock.Of<IDataTypeService>())) { Id = 1 });
var factory = new PublishedContentTypeFactory(Mock.Of<IPublishedModelFactory>(), new PropertyValueConverterCollection(Array.Empty<IPropertyValueConverter>()), dataTypeService);
@@ -14,7 +14,7 @@ using Umbraco.Web;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
using Umbraco.Web.Security.Identity;
namespace Umbraco.Tests.Security
{
@@ -2624,9 +2624,9 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, false), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, false), (langDe, false));
// not published => must be edited
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
// not published => must be edited, if available
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
// act
@@ -2666,8 +2666,8 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, true), (langUk, true), (langDe, false));
// fr and uk, published without changes, not edited
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, false), (langUk, false), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, false), (langUk, false), (langDe, true));
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, false), (langUk, false), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, false), (langUk, false), (langDe, false));
AssertPerCulture(content, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
AssertPerCulture(content2, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
@@ -2726,8 +2726,8 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, true), (langUk, true), (langDe, false));
// we have changed values so now fr and uk are edited
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
AssertPerCulture(content2, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
@@ -2770,8 +2770,8 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
// and so, fr has to be edited
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
AssertPerCulture(content2, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
@@ -2817,8 +2817,8 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
// and so, fr has to be edited - uk still is
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
AssertPerCulture(content2, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
@@ -2859,8 +2859,8 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
// no change, back to published
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
AssertPerCulture(content2, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
@@ -2882,8 +2882,8 @@ namespace Umbraco.Tests.Services
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
// now, uk is no more edited
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, false), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, false), (langDe, true));
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, false), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, false), (langDe, false));
AssertPerCulture(content, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
AssertPerCulture(content2, (x, c) => x.GetPublishDate(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
+22 -19
View File
@@ -5,6 +5,9 @@ namespace Umbraco.Tests.TestHelpers
{
public class ConsoleLogger : ILogger
{
public bool IsEnabled(Type reporting, LogLevel level)
=> true;
public void Fatal(Type reporting, Exception exception, string message)
{
Console.WriteLine("FATAL {0} - {1}", reporting.Name, message);
@@ -22,15 +25,15 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine("FATAL {0} - {1}", reporting.Name, message);
}
public void Fatal(Type reporting, Exception exception, string format, params object[] args)
public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
Console.WriteLine("FATAL {0} - {1}", reporting.Name, string.Format(format, args));
Console.WriteLine("FATAL {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
Console.WriteLine(exception);
}
public void Fatal(Type reporting, string format, params object[] args)
public void Fatal(Type reporting, string messageTemplate, params object[] propertyValues)
{
Console.WriteLine("FATAL {0} - {1}", reporting.Name, string.Format(format, args));
Console.WriteLine("FATAL {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
}
public void Error(Type reporting, Exception exception, string message)
@@ -50,15 +53,15 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine("ERROR {0} - {1}", reporting.Name, message);
}
public void Error(Type reporting, Exception exception, string format, params object[] args)
public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
Console.WriteLine("ERROR {0} - {1}", reporting.Name, string.Format(format, args));
Console.WriteLine("ERROR {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
Console.WriteLine(exception);
}
public void Error(Type reporting, string format, params object[] args)
public void Error(Type reporting, string messageTemplate, params object[] propertyValues)
{
Console.WriteLine("ERROR {0} - {1}", reporting.Name, string.Format(format, args));
Console.WriteLine("ERROR {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
}
public void Warn(Type reporting, string message)
@@ -66,9 +69,9 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine("WARN {0} - {1}", reporting.Name, message);
}
public void Warn(Type reporting, string format, params object[] args)
public void Warn(Type reporting, string message, params object[] propertyValues)
{
Console.WriteLine("WARN {0} - {1}", reporting.Name, string.Format(format, args));
Console.WriteLine("WARN {0} - {1}", reporting.Name, MessageTemplates.Render(message, propertyValues));
}
public void Warn(Type reporting, Exception exception, string message)
@@ -76,16 +79,16 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine("WARN {0} - {1}", reporting.Name, message);
Console.WriteLine(exception);
}
public void Warn(Type reporting, Exception exception, string format, params object[] args)
public void Warn(Type reporting, Exception exception, string message, params object[] propertyValues)
{
Console.WriteLine("WARN {0} - {1}", reporting.Name, string.Format(format, args));
Console.WriteLine("WARN {0} - {1}", reporting.Name, MessageTemplates.Render(message, propertyValues));
Console.WriteLine(exception);
}
public void Info(Type reporting, string format, params object[] args)
public void Info(Type reporting, string messageTemplate, params object[] propertyValues)
{
Console.WriteLine("INFO {0} - {1}", reporting.Name, string.Format(format, args));
Console.WriteLine("INFO {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
}
public void Info(Type reporting, string message)
@@ -98,9 +101,9 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine("DEBUG {0} - {1}", reporting.Name, message);
}
public void Debug(Type reporting, string format, params object[] args)
public void Debug(Type reporting, string messageTemplate, params object[] propertyValues)
{
Console.WriteLine("DEBUG {0} - {1}", reporting.Name, string.Format(format, args));
Console.WriteLine("DEBUG {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
}
public void Verbose(Type reporting, string message)
@@ -108,9 +111,9 @@ namespace Umbraco.Tests.TestHelpers
Console.WriteLine("VERBOSE {0} - {1}", reporting.Name, message);
}
public void Verbose(Type reporting, string format, params object[] args)
public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues)
{
Console.WriteLine("VERBOSE {0} - {1}", reporting.Name, string.Format(format, args));
Console.WriteLine("VERBOSE {0} - {1}", reporting.Name, MessageTemplates.Render(messageTemplate, propertyValues));
}
}
}
@@ -96,7 +96,11 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
var httpContext = Mock.Of<HttpContextBase>(
http => http.User == owinContext.Authentication.User
//ensure the request exists with a cookies collection
&& http.Request == Mock.Of<HttpRequestBase>(r => r.Cookies == new HttpCookieCollection())
&& http.Request == Mock.Of<HttpRequestBase>(r => r.Cookies == new HttpCookieCollection()
&& r.RequestContext == new System.Web.Routing.RequestContext
{
RouteData = new System.Web.Routing.RouteData()
})
//ensure the request exists with an items collection
&& http.Items == httpContextItems);
//chuck it into the props since this is what MS does when hosted and it's needed there
@@ -58,14 +58,14 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
var response = await server.HttpClient.SendAsync(request);
Console.WriteLine(response);
var json = "";
if (response.IsSuccessStatusCode == false)
{
WriteResponseError(response);
}
else
var json = (await ((StreamContent)response.Content).ReadAsStringAsync()).TrimStart(AngularJsonMediaTypeFormatter.XsrfPrefix);
if (!json.IsNullOrWhiteSpace())
{
json = (await ((StreamContent) response.Content).ReadAsStringAsync()).TrimStart(AngularJsonMediaTypeFormatter.XsrfPrefix);
var deserialized = JsonConvert.DeserializeObject(json);
Console.Write(JsonConvert.SerializeObject(deserialized, Formatting.Indented));
}
@@ -127,6 +127,11 @@ namespace Umbraco.Tests.TestHelpers
{
if (!(expected is string) && expected is IEnumerable)
{
// sort property collection by alias, not by property ids
// on members, built-in properties don't have ids (always zero)
if (expected is PropertyCollection)
sorter = e => ((PropertyCollection) e).OrderBy(x => x.Alias);
// compare lists
AssertListsAreEqual(property, (IEnumerable) actual, (IEnumerable) expected, sorter, dateDeltaMilliseconds);
}
@@ -168,6 +173,8 @@ namespace Umbraco.Tests.TestHelpers
private static void AssertListsAreEqual(PropertyInfo property, IEnumerable expected, IEnumerable actual, Func<IEnumerable, IEnumerable> sorter = null, int dateDeltaMilliseconds = 0)
{
if (sorter == null)
{
// this is pretty hackerific but saves us some code to write
+2 -1
View File
@@ -17,6 +17,7 @@ using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.IO.MediaPathSchemes;
using Umbraco.Core.Logging;
using Umbraco.Core.Logging.Serilog;
using Umbraco.Core.Manifest;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Persistence;
@@ -167,7 +168,7 @@ namespace Umbraco.Tests.Testing
}
else if (option == UmbracoTestOptions.Logger.Serilog)
{
Container.RegisterSingleton<ILogger>(f => new Logger(new FileInfo(TestHelper.MapPathForTest("~/unit-test.config"))));
Container.RegisterSingleton<ILogger>(f => new SerilogLogger(new FileInfo(TestHelper.MapPathForTest("~/unit-test.config"))));
Container.RegisterSingleton<IProfiler>(f => new LogProfiler(f.GetInstance<ILogger>()));
}
+2 -2
View File
@@ -82,7 +82,7 @@
<PackageReference Include="LightInject.Annotation" Version="1.1.0" />
<PackageReference Include="Lucene.Net" Version="3.0.3" />
<PackageReference Include="Lucene.Net.Contrib" Version="3.0.3" />
<PackageReference Include="Microsoft.AspNet.Identity.Core" Version="2.2.1" />
<PackageReference Include="Microsoft.AspNet.Identity.Core" Version="2.2.2" />
<PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.6" />
<PackageReference Include="Microsoft.AspNet.WebApi" Version="5.2.6" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.6" />
@@ -96,7 +96,7 @@
<PackageReference Include="Microsoft.Web.Infrastructure" Version="1.0.0.0" />
<PackageReference Include="MiniProfiler" Version="3.2.0.157" />
<PackageReference Include="Moq" Version="4.8.2" />
<PackageReference Include="NPoco" Version="3.9.3" />
<PackageReference Include="NPoco" Version="3.9.4" />
<PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
@@ -1,15 +1,10 @@
using Moq;
using System.IO;
using LightInject;
using System.IO;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Profiling;
using Umbraco.Core.Logging.Serilog;
using Umbraco.Core.Strings;
using Umbraco.Tests.TestHelpers;
using Umbraco.Examine;
namespace Umbraco.Tests.UmbracoExamine
{
@@ -19,18 +14,12 @@ namespace Umbraco.Tests.UmbracoExamine
[OneTimeSetUp]
public void InitializeFixture()
{
var logger = new Logger(new FileInfo(TestHelper.MapPathForTest("~/unit-test.config")));
var logger = new SerilogLogger(new FileInfo(TestHelper.MapPathForTest("~/unit-test.config")));
_profilingLogger = new ProfilingLogger(logger, new LogProfiler(logger));
}
private ProfilingLogger _profilingLogger;
protected override ProfilingLogger ProfilingLogger
{
get
{
return _profilingLogger;
}
}
protected override ProfilingLogger ProfilingLogger => _profilingLogger;
/// <summary>
/// sets up resolvers before resolution is frozen
@@ -24,6 +24,12 @@ using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.PublishedCache;
using Umbraco.Web._Legacy.Actions;
using Task = System.Threading.Tasks.Task;
using Umbraco.Core.Dictionary;
using Umbraco.Web.PropertyEditors;
using System;
using Umbraco.Web.WebApi;
using Umbraco.Web.Trees;
using System.Globalization;
namespace Umbraco.Tests.Web.Controllers
{
@@ -40,6 +46,8 @@ namespace Umbraco.Tests.Web.Controllers
var userServiceMock = new Mock<IUserService>();
userServiceMock.Setup(service => service.GetUserById(It.IsAny<int>()))
.Returns((int id) => id == 1234 ? new User(1234, "Test", "test@test.com", "test@test.com", "", new List<IReadOnlyUserGroup>(), new int[0], new int[0]) : null);
userServiceMock.Setup(x => x.GetProfileById(It.IsAny<int>()))
.Returns((int id) => id == 1234 ? new User(1234, "Test", "test@test.com", "test@test.com", "", new List<IReadOnlyUserGroup>(), new int[0], new int[0]) : null);
userServiceMock.Setup(service => service.GetPermissionsForPath(It.IsAny<IUser>(), It.IsAny<string>()))
.Returns(new EntityPermissionSet(123, new EntityPermissionCollection(new[]
{
@@ -54,23 +62,34 @@ namespace Umbraco.Tests.Web.Controllers
var entityService = new Mock<IEntityService>();
entityService.Setup(x => x.GetAllPaths(UmbracoObjectTypes.Document, It.IsAny<int[]>()))
.Returns((UmbracoObjectTypes objType, int[] ids) => ids.Select(x => new TreeEntityPath {Path = $"-1,{x}", Id = x}).ToList());
.Returns((UmbracoObjectTypes objType, int[] ids) => ids.Select(x => new TreeEntityPath { Path = $"-1,{x}", Id = x }).ToList());
var dataTypeService = new Mock<IDataTypeService>();
dataTypeService.Setup(service => service.GetDataType(It.IsAny<int>()))
.Returns(MockedDataType());
.Returns(Mock.Of<IDataType>(type => type.Id == 9876 && type.Name == "text"));
dataTypeService.Setup(service => service.GetDataType(-87)) //the RTE
.Returns(Mock.Of<IDataType>(type => type.Id == -87 && type.Name == "Rich text" && type.Configuration == new RichTextConfiguration()));
var langService = new Mock<ILocalizationService>();
langService.Setup(x => x.GetAllLanguages()).Returns(new[] {
Mock.Of<ILanguage>(x => x.IsoCode == "en-US"),
Mock.Of<ILanguage>(x => x.IsoCode == "es-ES"),
Mock.Of<ILanguage>(x => x.IsoCode == "fr-FR")
});
var textService = new Mock<ILocalizedTextService>();
textService.Setup(x => x.Localize(It.IsAny<string>(), It.IsAny<CultureInfo>(), It.IsAny<IDictionary<string, string>>())).Returns("");
Container.RegisterSingleton(f => Mock.Of<IContentService>());
Container.RegisterSingleton(f => userServiceMock.Object);
Container.RegisterSingleton(f => entityService.Object);
Container.RegisterSingleton(f => dataTypeService.Object);
Container.RegisterSingleton(f => langService.Object);
Container.RegisterSingleton(f => textService.Object);
Container.RegisterSingleton(f => Mock.Of<ICultureDictionaryFactory>());
Container.RegisterSingleton(f => new UmbracoApiControllerTypeCollection(new[] { typeof(ContentTreeController) }));
}
private IDataType MockedDataType()
{
return Mock.Of<IDataType>(type => type.Id == 9876 && type.Name == "text");
}
private MultipartFormDataContent GetMultiPartRequestContent(string json)
{
var multiPartBoundary = "----WebKitFormBoundary123456789";
@@ -89,14 +108,34 @@ namespace Umbraco.Tests.Web.Controllers
};
}
private const string PublishJson1 = @"{
private IContent GetMockedContent()
{
var content = MockedContent.CreateSimpleContent(MockedContentTypes.CreateSimpleContentType());
content.Id = 123;
content.Path = "-1,123";
//ensure things have ids
var ids = 888;
foreach (var g in content.PropertyGroups)
{
g.Id = ids;
ids++;
}
foreach (var p in content.PropertyTypes)
{
p.Id = ids;
ids++;
}
return content;
}
private const string PublishJsonInvariant = @"{
""id"": 123,
""contentTypeAlias"": ""page"",
""parentId"": -1,
""action"": ""save"",
""variants"": [
{
""name"": null,
""name"": ""asdf"",
""properties"": [
{
""id"": 1,
@@ -104,10 +143,34 @@ namespace Umbraco.Tests.Web.Controllers
""value"": ""asdf""
}
],
""culture"": ""en-US""
""culture"": null,
""save"": true,
""publish"": true
}
]
}";
private const string PublishJsonVariant = @"{
""id"": 123,
""contentTypeAlias"": ""page"",
""parentId"": -1,
""action"": ""save"",
""variants"": [
{
""name"": ""asdf"",
""properties"": [
{
""id"": 1,
""alias"": ""title"",
""value"": ""asdf""
}
],
""culture"": ""en-US"",
""save"": true,
""publish"": true
},
{
""name"": null,
""name"": ""asdf"",
""properties"": [
{
""id"": 1,
@@ -115,7 +178,9 @@ namespace Umbraco.Tests.Web.Controllers
""value"": ""asdf""
}
],
""culture"": ""fr-FR""
""culture"": ""fr-FR"",
""save"": true,
""publish"": true
},
{
""name"": ""asdf"",
@@ -142,12 +207,8 @@ namespace Umbraco.Tests.Web.Controllers
{
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
{
//var content = MockedContent.CreateSimpleContent(MockedContentTypes.CreateSimpleContentType());
//content.Id = 999999999; //this will not be found
//content.Path = "-1,999999999";
var contentServiceMock = Mock.Get(Current.Services.ContentService);
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => null);
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => null); //do not find it
var publishedSnapshot = Mock.Of<IPublishedSnapshotService>();
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
@@ -158,7 +219,7 @@ namespace Umbraco.Tests.Web.Controllers
var runner = new TestRunner(Factory);
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
content: GetMultiPartRequestContent(PublishJson1),
content: GetMultiPartRequestContent(PublishJsonInvariant),
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
assertOkResponse: false);
@@ -175,7 +236,7 @@ namespace Umbraco.Tests.Web.Controllers
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
{
var contentServiceMock = Mock.Get(Current.Services.ContentService);
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => null);
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => GetMockedContent());
var publishedSnapshot = Mock.Of<IPublishedSnapshotService>();
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
@@ -184,9 +245,9 @@ namespace Umbraco.Tests.Web.Controllers
return usersController;
}
var json = JsonConvert.DeserializeObject<JObject>(PublishJson1);
var json = JsonConvert.DeserializeObject<JObject>(PublishJsonInvariant);
//remove all save flaggs
((JArray)json["variants"])[2]["save"] = false;
((JArray)json["variants"])[0]["save"] = false;
var runner = new TestRunner(Factory);
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
@@ -202,20 +263,52 @@ namespace Umbraco.Tests.Web.Controllers
/// Returns 404 if any of the posted properties dont actually exist
/// </summary>
/// <returns></returns>
[Test, Ignore("Not implemented yet")]
[Test]
public async Task PostSave_Validate_Properties_Exist()
{
//TODO: Make this work! to finish it, we need to include a property in the POST data that doesn't exist on the content type
// or change the content type below to not include one of the posted ones
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
{
var contentServiceMock = Mock.Get(Current.Services.ContentService);
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => GetMockedContent());
var publishedSnapshot = Mock.Of<IPublishedSnapshotService>();
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var usersController = new ContentController(publishedSnapshot, propertyEditorCollection);
Container.InjectProperties(usersController);
return usersController;
}
var json = JsonConvert.DeserializeObject<JObject>(PublishJsonInvariant);
//add a non-existent property to a variant being saved
var variantProps = (JArray)json["variants"].ElementAt(0)["properties"];
variantProps.Add(JObject.FromObject(new
{
id = 2,
alias = "doesntExist",
value = "hello"
}));
var runner = new TestRunner(Factory);
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
content: GetMultiPartRequestContent(JsonConvert.SerializeObject(json)),
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
assertOkResponse: false);
Assert.AreEqual(HttpStatusCode.NotFound, response.Item1.StatusCode);
}
[Test]
public async Task PostSave_Simple_Invariant()
{
var content = GetMockedContent();
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
{
var content = MockedContent.CreateSimpleContent(MockedContentTypes.CreateSimpleContentType());
content.Id = 123;
content.Path = "-1,123";
var contentServiceMock = Mock.Get(Current.Services.ContentService);
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => null);
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => content);
contentServiceMock.Setup(x => x.Save(It.IsAny<IContent>(), It.IsAny<int>(), It.IsAny<bool>()))
.Returns(new OperationResult(OperationResultType.Success, new Core.Events.EventMessages())); //success
var publishedSnapshot = Mock.Of<IPublishedSnapshotService>();
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
@@ -226,14 +319,92 @@ namespace Umbraco.Tests.Web.Controllers
var runner = new TestRunner(Factory);
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
content: GetMultiPartRequestContent(PublishJson1),
content: GetMultiPartRequestContent(PublishJsonInvariant),
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
assertOkResponse: false);
Assert.AreEqual(HttpStatusCode.NotFound, response.Item1.StatusCode);
//var obj = JsonConvert.DeserializeObject<PagedResult<UserDisplay>>(response.Item2);
//Assert.AreEqual(0, obj.TotalItems);
Assert.AreEqual(HttpStatusCode.OK, response.Item1.StatusCode);
var display = JsonConvert.DeserializeObject<ContentItemDisplay>(response.Item2);
Assert.AreEqual(1, display.Variants.Count());
Assert.AreEqual(content.PropertyGroups.Count(), display.Variants.ElementAt(0).Tabs.Count());
Assert.AreEqual(content.PropertyTypes.Count(), display.Variants.ElementAt(0).Tabs.ElementAt(0).Properties.Count());
}
[Test]
public async Task PostSave_Validate_Empty_Name()
{
var content = GetMockedContent();
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
{
var contentServiceMock = Mock.Get(Current.Services.ContentService);
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => content);
contentServiceMock.Setup(x => x.Save(It.IsAny<IContent>(), It.IsAny<int>(), It.IsAny<bool>()))
.Returns(new OperationResult(OperationResultType.Success, new Core.Events.EventMessages())); //success
var publishedSnapshot = Mock.Of<IPublishedSnapshotService>();
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var usersController = new ContentController(publishedSnapshot, propertyEditorCollection);
Container.InjectProperties(usersController);
return usersController;
}
//clear out the name
var json = JsonConvert.DeserializeObject<JObject>(PublishJsonInvariant);
json["variants"].ElementAt(0)["name"] = null;
var runner = new TestRunner(Factory);
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
content: GetMultiPartRequestContent(JsonConvert.SerializeObject(json)),
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
assertOkResponse: false);
Assert.AreEqual(HttpStatusCode.BadRequest, response.Item1.StatusCode);
var display = JsonConvert.DeserializeObject<ContentItemDisplay>(response.Item2);
Assert.AreEqual(1, display.Errors.Count());
Assert.IsTrue(display.Errors.ContainsKey("Variants[0].Name"));
//ModelState":{"Variants[0].Name":["Required"]}
}
[Test]
public async Task PostSave_Validate_Variants_Empty_Name()
{
var content = GetMockedContent();
ApiController Factory(HttpRequestMessage message, UmbracoHelper helper)
{
var contentServiceMock = Mock.Get(Current.Services.ContentService);
contentServiceMock.Setup(x => x.GetById(123)).Returns(() => content);
contentServiceMock.Setup(x => x.Save(It.IsAny<IContent>(), It.IsAny<int>(), It.IsAny<bool>()))
.Returns(new OperationResult(OperationResultType.Success, new Core.Events.EventMessages())); //success
var publishedSnapshot = Mock.Of<IPublishedSnapshotService>();
var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty<DataEditor>()));
var usersController = new ContentController(publishedSnapshot, propertyEditorCollection);
Container.InjectProperties(usersController);
return usersController;
}
//clear out one of the names
var json = JsonConvert.DeserializeObject<JObject>(PublishJsonVariant);
json["variants"].ElementAt(0)["name"] = null;
var runner = new TestRunner(Factory);
var response = await runner.Execute("Content", "PostSave", HttpMethod.Post,
content: GetMultiPartRequestContent(JsonConvert.SerializeObject(json)),
mediaTypeHeader: new MediaTypeWithQualityHeaderValue("multipart/form-data"),
assertOkResponse: false);
Assert.AreEqual(HttpStatusCode.BadRequest, response.Item1.StatusCode);
var display = JsonConvert.DeserializeObject<ContentItemDisplay>(response.Item2);
Assert.AreEqual(2, display.Errors.Count());
Assert.IsTrue(display.Errors.ContainsKey("Variants[0].Name"));
Assert.IsTrue(display.Errors.ContainsKey("_content_variant_en-US_"));
}
//TODO: There are SOOOOO many more tests we should write - a lot of them to do with validation
}
}

Some files were not shown because too many files have changed in this diff Show More