Compare commits
340 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 64dac39bae | |||
| 6040d149ec | |||
| bfbc6595fb | |||
| 25d8fc7a13 | |||
| e11b5c3fdb | |||
| 87100feb3d | |||
| eae74b0e20 | |||
| 610efe552d | |||
| c4860a490f | |||
| 8e6bbc3df9 | |||
| c16d0b77c2 | |||
| 2c4403f892 | |||
| fd66f08520 | |||
| 8e50f4968f | |||
| 9acbe09449 | |||
| 4baaafd006 | |||
| 3f7293304d | |||
| f62581bd38 | |||
| 9782e3711e | |||
| 1f4ba9cfdc | |||
| ba4f0cc6a4 | |||
| fc84821e8b | |||
| 0fcf0b505a | |||
| d300146cf6 | |||
| c8482b9f59 | |||
| b7795e19ef | |||
| c97617f5b5 | |||
| 14265fc964 | |||
| 18c3345e47 | |||
| 924a016ffe | |||
| a02b41e9d2 | |||
| 068c4a0b16 | |||
| f7d28d769a | |||
| 9a07e206d8 | |||
| 0edb71f4aa | |||
| b376207ef6 | |||
| 6d0aa824ad | |||
| 89afacf161 | |||
| 0fa6940bb6 | |||
| 1353b0a592 | |||
| 617fec171f | |||
| 2c63866cb3 | |||
| 18d3aa9ee2 | |||
| f83c966e55 | |||
| de41a1f1ca | |||
| c9f57c6ce3 | |||
| 54ab26e2ed | |||
| 31dc1b2cdb | |||
| d4b9a711c6 | |||
| 9521742254 | |||
| 9fee3f5873 | |||
| cb10578e19 | |||
| cdc4435f2d | |||
| a885840b9f | |||
| 62173cef58 | |||
| e5b0a4d98c | |||
| 9479d63cba | |||
| 4c544acb42 | |||
| c7c5f481f1 | |||
| 5e8e62cbf7 | |||
| 555b520a0c | |||
| 8053db32b6 | |||
| 3e2d59e526 | |||
| 9d3e967c2a | |||
| 71ec09486d | |||
| 8dadc92aa8 | |||
| f472f5d950 | |||
| 775a6f80ea | |||
| 5bf8b8ecba | |||
| 397ef32665 | |||
| 2634e33f51 | |||
| 6e27caa547 | |||
| 9c027dcdbc | |||
| f3876b86dc | |||
| 58c3dfac1c | |||
| dcf59d2b17 | |||
| 71099514cb | |||
| 887111318f | |||
| bf9755b27c | |||
| aca181b32e | |||
| 886347e763 | |||
| 9fa606e065 | |||
| e40ac44afd | |||
| 48603fb840 | |||
| f824439180 | |||
| b3616c9f8c | |||
| 48383f2e7a | |||
| cb98385242 | |||
| 916bad82df | |||
| 29ec8cb2d3 | |||
| 04900337c7 | |||
| 1433685160 | |||
| c5994ed54a | |||
| 9fd80d791a | |||
| f5f9cb676c | |||
| 04e2d2370a | |||
| 8d00d931b0 | |||
| 2998ad8cea | |||
| 46c15ef28f | |||
| 2b369a57d8 | |||
| c37a6bb928 | |||
| 6e53291877 | |||
| bb78f756c7 | |||
| ffb0de4050 | |||
| 0fecad9867 | |||
| 3045068d68 | |||
| 37a6668313 | |||
| 36814d746f | |||
| a72f6edb6b | |||
| e01cbcd405 | |||
| 012ed6cf16 | |||
| eb3ff12916 | |||
| 1ebff69358 | |||
| 5435c44ea9 | |||
| 76fa477c35 | |||
| 1f6f36d8c8 | |||
| c46ac11125 | |||
| 73d5a3f993 | |||
| 5a99a6903d | |||
| 775639da41 | |||
| 2375ede161 | |||
| fcd00599da | |||
| d3f5090150 | |||
| 6a7faf457b | |||
| ec247d2b27 | |||
| f32479bb10 | |||
| 371269436f | |||
| ef13e4112f | |||
| ce5b6861bb | |||
| eaf64d1814 | |||
| 6bf1ecdb11 | |||
| fdd0ff2c23 | |||
| bade8e42ba | |||
| cfdf2768e6 | |||
| c3ca006f14 | |||
| 6c47c8f792 | |||
| 63160e2e2d | |||
| edc58fe8a5 | |||
| 23632dc0c3 | |||
| d739b9fb31 | |||
| 2ae4ede258 | |||
| cacd08b57c | |||
| 4eddfb4cf5 | |||
| f2b3d7c041 | |||
| 5d97a94dcb | |||
| de6e7dd28d | |||
| 420c029bf7 | |||
| 61441dd436 | |||
| 5c24867925 | |||
| 0409cbe613 | |||
| bbbea99ced | |||
| 3d213342bf | |||
| 48fdb75d96 | |||
| a97094458d | |||
| f81353af0b | |||
| f0e1460550 | |||
| d15c09ad2a | |||
| 5813202892 | |||
| 82f6b6a66d | |||
| eec6ee79aa | |||
| 5ed4f262cd | |||
| e5d7f6fd04 | |||
| a9ad0ae8eb | |||
| 9cd64a9061 | |||
| 839c0d011b | |||
| 15c9aadcdc | |||
| 36a1c0a9e0 | |||
| 30f0c96052 | |||
| cfab30a1ef | |||
| 1dd0086eb5 | |||
| a7f06ebc56 | |||
| 9498bc4bfd | |||
| 38b13bf6ce | |||
| c8cb5b26b0 | |||
| 5749f80a7f | |||
| 5d9a935621 | |||
| 1ff4fe26dd | |||
| bd69820028 | |||
| 3c9953979a | |||
| 2f6189ae24 | |||
| 5ff329778d | |||
| befb2b4d2f | |||
| f4ae45d8f2 | |||
| 7b73ed1796 | |||
| 0eacbcb7cb | |||
| f871de61d5 | |||
| e02693e46b | |||
| db62d14b1a | |||
| c096ab9e54 | |||
| ada5a031b4 | |||
| 9c8b9f8bb4 | |||
| a4bd3abfbe | |||
| a8a768a50f | |||
| 62b99ffc59 | |||
| 6b0c94948e | |||
| 25f049e167 | |||
| f7979fa19d | |||
| 6fd1784337 | |||
| a7bb8e0d00 | |||
| ed4a9f84f0 | |||
| bbe4a87784 | |||
| cbd5c295bd | |||
| 0d29e1438c | |||
| 4796827f02 | |||
| c6f7ece764 | |||
| e86aaefaaf | |||
| 97e9cd4be0 | |||
| 63af822bad | |||
| b65f653c91 | |||
| 3b404a2f76 | |||
| e9567e7adc | |||
| 697daab4d7 | |||
| 6c29ad854c | |||
| 93d89535aa | |||
| eb093ca4a6 | |||
| 1040f234dc | |||
| 5a1ace9362 | |||
| 3f835fe19c | |||
| bf43ce3281 | |||
| c37ba0dc8a | |||
| 7b5ad9a5c6 | |||
| f0afa701bc | |||
| 71dc1110d8 | |||
| 4de4eb9cc8 | |||
| 308d5ba344 | |||
| 74dac71e8a | |||
| 64518774c6 | |||
| f65b0df3e2 | |||
| 5cfe9e85f8 | |||
| 61044b6018 | |||
| 00fc5a5bb2 | |||
| da85e4eb28 | |||
| 3f23865e0a | |||
| fbc08d66f1 | |||
| 79f04bf939 | |||
| 9ab90595e2 | |||
| aac208c0e8 | |||
| f8e101ec13 | |||
| 23fcc1ac55 | |||
| 6356531207 | |||
| 51b618826c | |||
| 04c28e5006 | |||
| e9ef9b9d75 | |||
| c160ce98c1 | |||
| c3a60ea0e0 | |||
| 3408efdee4 | |||
| 1f0dc7e65d | |||
| f89083c772 | |||
| 752065e540 | |||
| 82e4e50584 | |||
| 775e63148d | |||
| 4259b02b8d | |||
| 0c402310d9 | |||
| 8d92330ad6 | |||
| 44e76f741f | |||
| ecbced5c62 | |||
| e6773dafc1 | |||
| 7b8b7ed170 | |||
| c0997e1b9f | |||
| d4f862a44f | |||
| 64c983eb07 | |||
| e25222162c | |||
| e022687457 | |||
| 84db2f4d85 | |||
| ef64409a9a | |||
| f0b68ac31e | |||
| dba7bcf60a | |||
| 6c80bd9eb9 | |||
| c7b7bf1510 | |||
| d1805b1448 | |||
| 780937dae9 | |||
| 9b054eaa47 | |||
| 1584530615 | |||
| 100ca5caa6 | |||
| badd9ae289 | |||
| db6755a5bb | |||
| 738815170c | |||
| ef091e8c3a | |||
| 71b3810e9c | |||
| a1e62dae5e | |||
| 96c087d00f | |||
| 0568bf51f0 | |||
| e3bade4d1a | |||
| 633b0b0003 | |||
| 82adf48699 | |||
| 63be12b9fe | |||
| 33f7ed5129 | |||
| 79583c571c | |||
| a7e2c0b4dc | |||
| da48e1b392 | |||
| f535ece685 | |||
| 04e46c7cd1 | |||
| 1089aef00a | |||
| 0288d6ec89 | |||
| 8950d94b25 | |||
| bb6299cc01 | |||
| 2176f2a1c9 | |||
| 6a351bede1 | |||
| efc1aae0ae | |||
| df39e027fd | |||
| 64f05e4c97 | |||
| 30bc89ba93 | |||
| 841c8d69fc | |||
| aa780d2b8a | |||
| 59f15f1618 | |||
| b2f0a9f23d | |||
| 40cd07f3f4 | |||
| 99e7f84f79 | |||
| 3a5a32c65f | |||
| c2627f3a2a | |||
| 22b8d41aee | |||
| ee47ea2026 | |||
| 57622cef9a | |||
| 30ad3f5aa6 | |||
| 2c11f0be0f | |||
| c514ce8da3 | |||
| 65d421b619 | |||
| 62897f7064 | |||
| e0619edabb | |||
| 4142f47861 | |||
| 7135f9a268 | |||
| a75a58b719 | |||
| 7b969fc167 | |||
| 78475b0686 | |||
| 4925d55e8f | |||
| 52d2306e17 | |||
| 5e5207d4f3 | |||
| 96d46c82fe | |||
| 86bf50db12 | |||
| 14778422e6 | |||
| 6a931273a6 | |||
| 5fab1ea436 | |||
| 5310ce38fd | |||
| 7abbfbcfcc | |||
| a22b97643a | |||
| 80be614731 | |||
| e25886180a | |||
| d5a41d41e9 | |||
| 2e43a34812 | |||
| 1b9afc961b |
@@ -131,3 +131,4 @@ src/*.boltdata/
|
||||
src/umbraco.sln.ide/*
|
||||
build/UmbracoCms.*/
|
||||
src/.vs/
|
||||
src/Umbraco.Web.UI/umbraco/js/install.loader.js
|
||||
|
||||
@@ -7,9 +7,9 @@ The easiest way to get started is to run `build/build.bat` which will build both
|
||||
|
||||
If you're interested in making changes to Belle make sure to read the [Belle ReadMe file](src/Umbraco.Web.UI.Client/README.md). Note that you can always [download a nightly build](http://nightly.umbraco.org/umbraco%207.0.0/) so you don't have to build the code yourself.
|
||||
|
||||
## Watch a five minute introduction video ##
|
||||
## Watch a introduction video ##
|
||||
|
||||
[](http://umbraco.org/help-and-support/video-tutorials/getting-started/what-is-umbraco)
|
||||
[](https://umbraco.tv/videos/umbraco-v7/content-editor/basics/introduction/cms-explanation/)
|
||||
|
||||
## Umbraco - the simple, flexible and friendly ASP.NET CMS ##
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<dependency id="HtmlAgilityPack" version="[1.4.9, 2.0.0)" />
|
||||
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
|
||||
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.7, 7.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.8, 7.0.0)" />
|
||||
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.8.4, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0, 2.0.0)" />
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Target Name="CopyUmbracoFilesToWebRootForDeploy" AfterTargets="CopyAllFilesToSingleFolderForMsdeploy">
|
||||
<PropertyGroup>
|
||||
<UmbracoFilesFolder>$(MSBuildThisFileDirectory)..\UmbracoFiles\</UmbracoFilesFolder>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<UmbracoFiles Include="$(UmbracoFilesFolder)**\*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="%(UmbracoFiles.FullPath)" DestinationFiles="$(_PackageTempDir)\%(RecursiveDir)%(Filename)%(Extension)" Condition="!Exists('%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
</Target>
|
||||
<Target Name="CopyUmbracoFilesToWebRoot" BeforeTargets="AfterBuild">
|
||||
<!-- This copies the files listed in `AddUmbracoFilesToOutput` to the webroot during NuGet install and should -->
|
||||
<!-- not be altered to support automated builds, use `CopyUmbracoFilesToWebRootForDeploy` for that instead -->
|
||||
<PropertyGroup>
|
||||
<UmbracoFilesFolder>$(MSBuildThisFileDirectory)..\UmbracoFiles\</UmbracoFilesFolder>
|
||||
</PropertyGroup>
|
||||
@@ -47,4 +58,4 @@
|
||||
</FilesForPackagingFromProject>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<dashBoard xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<section alias="StartupSettingsDashboardSection" xdt:Locator="Match(alias)">
|
||||
<section alias="StartupSettingsDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
|
||||
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
<tab caption="Welcome" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing">
|
||||
<control showOnce="true" addPanel="true" panelCaption="" xdt:Transform="InsertIfMissing">
|
||||
@@ -20,7 +20,7 @@
|
||||
</tab>
|
||||
</section>
|
||||
|
||||
<section alias="StartupDeveloperDashboardSection" xdt:Locator="Match(alias)">
|
||||
<section alias="StartupDeveloperDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
|
||||
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Replace">
|
||||
<control showOnce="true" addPanel="true" panelCaption="">
|
||||
views/dashboard/developer/developerdashboardvideos.html
|
||||
@@ -29,7 +29,7 @@
|
||||
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
</section>
|
||||
|
||||
<section alias="StartupDeveloperDashboardSection" xdt:Locator="Match(alias)">
|
||||
<section alias="StartupDeveloperDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
|
||||
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing">
|
||||
<control>
|
||||
views/dashboard/developer/examinemanagement.html
|
||||
@@ -39,10 +39,10 @@
|
||||
<control>
|
||||
views/dashboard/developer/xmldataintegrityreport.html
|
||||
</control>
|
||||
</tab>
|
||||
</tab>
|
||||
</section>
|
||||
|
||||
<section alias="StartupMediaDashboardSection" xdt:Locator="Match(alias)">
|
||||
<section alias="StartupMediaDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
|
||||
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
<tab caption="Content" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing" />
|
||||
<tab caption="Content" xdt:Locator="Match(caption)" xdt:Transform="Replace">
|
||||
@@ -52,7 +52,7 @@
|
||||
</tab>
|
||||
</section>
|
||||
|
||||
<section alias="StartupDashboardSection" xdt:Locator="Match(alias)">
|
||||
<section alias="StartupDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
|
||||
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
<tab caption="Get Started" xdt:Transform="Insert">
|
||||
<access>
|
||||
@@ -62,17 +62,10 @@
|
||||
views/dashboard/default/startupdashboardintro.html
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Change password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
<tab caption="Change Password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
<tab caption="Change Password" xdt:Transform="Insert">
|
||||
<control showOnce="false" addPanel="false" panelCaption="">
|
||||
views/dashboard/ChangePassword.html
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Last Edits" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
</section>
|
||||
|
||||
<section alias="StartupMemberDashboardSection" xdt:Locator="Match(alias)">
|
||||
<section alias="StartupMemberDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
|
||||
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
<tab caption="Get Started" xdt:Transform="Insert">
|
||||
<control showOnce="true" addPanel="true" panelCaption="">
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -48,6 +48,11 @@
|
||||
<system.web xdt:Transform="InsertIfMissing" />
|
||||
<system.web>
|
||||
<siteMap xdt:Transform="Remove" />
|
||||
<siteMap xdt:Transform="InsertIfMissing">
|
||||
<providers xdt:Transform="InsertIfMissing">
|
||||
<remove name="MySqlSiteMapProvider" xdt:Transform="InsertIfMissing" />
|
||||
</providers>
|
||||
</siteMap>
|
||||
<httpRuntime xdt:Transform="InsertIfMissing" />
|
||||
<httpRuntime targetFramework="4.5" xdt:Transform="SetAttributes(targetFramework)" />
|
||||
<membership defaultProvider="DefaultMembershipProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove" />
|
||||
@@ -76,6 +81,10 @@
|
||||
</compilation>
|
||||
|
||||
<compilation>
|
||||
<assemblies>
|
||||
<remove assembly="System.Web.Http" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Net.Http" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
</assemblies>
|
||||
<assemblies>
|
||||
<remove assembly="System.Web.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Net.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
@@ -172,23 +181,23 @@
|
||||
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
|
||||
@@ -63,6 +63,7 @@ if ($project) {
|
||||
if(Test-Path $umbracoBinFolder\MiniProfiler.dll) { Remove-Item $umbracoBinFolder\MiniProfiler.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\MySql.Data.dll) { Remove-Item $umbracoBinFolder\MySql.Data.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Newtonsoft.Json.dll) { Remove-Item $umbracoBinFolder\Newtonsoft.Json.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.Helpers.dll) { Remove-Item $umbracoBinFolder\System.Web.Helpers.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Net.Http.Formatting.dll) { Remove-Item $umbracoBinFolder\System.Net.Http.Formatting.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.Http.dll) { Remove-Item $umbracoBinFolder\System.Web.Http.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\System.Web.Http.WebHost.dll) { Remove-Item $umbracoBinFolder\System.Web.Http.WebHost.dll -Force -Confirm:$false }
|
||||
|
||||
@@ -45,9 +45,6 @@ del ..\src\Umbraco.Web.UI\UserControls\*.*
|
||||
echo Removing masterpage files
|
||||
del ..\src\Umbraco.Web.UI\masterpages\*.*
|
||||
|
||||
echo Removing view files
|
||||
del ..\src\Umbraco.Web.UI\Views\*.*
|
||||
|
||||
echo Removing razor files
|
||||
del ..\src\Umbraco.Web.UI\macroScripts\*.*
|
||||
|
||||
@@ -104,7 +101,9 @@ echo Removing user control files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\usercontrols\*.*) DO DEL %%A
|
||||
|
||||
echo Removing view files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\Views\*.*) DO DEL %%A
|
||||
ATTRIB +H ..\src\Umbraco.Web.UI\Views\Partials\Grid\*.cshtml /S
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\Views\) DO DEL /Q /S *.cshtml -H
|
||||
ATTRIB -H ..\src\Umbraco.Web.UI\Views\Partials\Grid\*.cshtml /S
|
||||
|
||||
echo Removing razor files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\macroScripts\*.*) DO DEL %%A
|
||||
|
||||
@@ -54,9 +54,6 @@ del ..\src\Umbraco.Web.UI\UserControls\*.*
|
||||
echo Removing masterpage files
|
||||
del ..\src\Umbraco.Web.UI\masterpages\*.*
|
||||
|
||||
echo Removing view files
|
||||
del ..\src\Umbraco.Web.UI\Views\*.*
|
||||
|
||||
echo Removing razor files
|
||||
del ..\src\Umbraco.Web.UI\macroScripts\*.*
|
||||
|
||||
@@ -122,7 +119,9 @@ echo Removing user control files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\usercontrols\*.*) DO DEL %%A
|
||||
|
||||
echo Removing view files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\Views\*.*) DO DEL %%A
|
||||
ATTRIB +H ..\src\Umbraco.Web.UI\Views\Partials\Grid\*.cshtml /S
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\Views\) DO DEL /Q /S *.cshtml -H
|
||||
ATTRIB -H ..\src\Umbraco.Web.UI\Views\Partials\Grid\*.cshtml /S
|
||||
|
||||
echo Removing razor files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\macroScripts\*.*) DO DEL %%A
|
||||
@@ -151,6 +150,9 @@ rmdir "..\src\Umbraco.Web.UI\usercontrols\umbracoContour\" /S /Q
|
||||
echo Start with a clean web.config
|
||||
copy ..\src\Umbraco.Web.UI\web.Template.config ..\src\Umbraco.Web.UI\web.config /Y
|
||||
|
||||
echo Start with a clean web.config
|
||||
copy ..\src\Umbraco.Web.UI\web.Template.config ..\src\Umbraco.Web.UI\web.config /Y
|
||||
|
||||
echo "Umbraco install reverted to clean install"
|
||||
pause
|
||||
exit
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.3.0
|
||||
7.3.3
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.3.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.3.0")]
|
||||
[assembly: AssemblyFileVersion("7.3.3")]
|
||||
[assembly: AssemblyInformationalVersion("7.3.3")]
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// A resolver to return all IAction objects
|
||||
/// </summary>
|
||||
internal sealed class ActionsResolver : LazyManyObjectsResolverBase<ActionsResolver, IAction>
|
||||
public sealed class ActionsResolver : LazyManyObjectsResolverBase<ActionsResolver, IAction>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
|
||||
@@ -283,7 +283,12 @@ namespace Umbraco.Core
|
||||
{
|
||||
var configStatus = ConfigurationStatus;
|
||||
var currentVersion = UmbracoVersion.GetSemanticVersion();
|
||||
var ok = configStatus == currentVersion;
|
||||
|
||||
var ok =
|
||||
//we are not configured if this is null
|
||||
string.IsNullOrWhiteSpace(configStatus) == false
|
||||
//they must match
|
||||
&& configStatus == currentVersion;
|
||||
|
||||
if (ok)
|
||||
{
|
||||
@@ -308,8 +313,9 @@ namespace Umbraco.Core
|
||||
|
||||
return ok;
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<ApplicationContext>("Error determining if application is configured, returning false", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -117,38 +118,55 @@ namespace Umbraco.Core
|
||||
private class NamedSemaphoreReleaser : CriticalFinalizerObject, IDisposable
|
||||
{
|
||||
private readonly Semaphore _semaphore;
|
||||
private GCHandle _handle;
|
||||
|
||||
internal NamedSemaphoreReleaser(Semaphore semaphore)
|
||||
{
|
||||
_semaphore = semaphore;
|
||||
_handle = GCHandle.Alloc(_semaphore);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
GC.SuppressFinalize(this); // finalize will not run
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
// critical
|
||||
_handle.Free();
|
||||
_semaphore.Release();
|
||||
_semaphore.Dispose();
|
||||
}
|
||||
|
||||
// we WANT to release the semaphore because it's a system object
|
||||
// ie a critical non-managed resource - so we inherit from CriticalFinalizerObject
|
||||
// which means that the finalizer "should" run in all situations
|
||||
// we WANT to release the semaphore because it's a system object, ie a critical
|
||||
// non-managed resource - and if it is not released then noone else can acquire
|
||||
// the lock - so we inherit from CriticalFinalizerObject which means that the
|
||||
// finalizer "should" run in all situations - there is always a chance that it
|
||||
// does not run and the semaphore remains "acquired" but then chances are the
|
||||
// whole process (w3wp.exe...) is going down, at which point the semaphore will
|
||||
// be destroyed by Windows.
|
||||
|
||||
// however... that can fail with System.ObjectDisposedException because the
|
||||
// underlying handle was closed... because we cannot guarantee that the semaphore
|
||||
// is not gone already... unless we get a GCHandle = GCHandle.Alloc(_semaphore);
|
||||
// which should keep it around and then we free the handle?
|
||||
// however, the semaphore is a managed object, and so when the finalizer runs it
|
||||
// might have been finalized already, and then we get a, ObjectDisposedException
|
||||
// in the finalizer - which is bad.
|
||||
|
||||
// so... I'm not sure this is safe really...
|
||||
// in order to prevent this we do two things
|
||||
// - use a GCHandler to ensure the semaphore is still there when the finalizer
|
||||
// runs, so we can actually release it
|
||||
// - wrap the finalizer code in a try...catch to make sure it never throws
|
||||
|
||||
~NamedSemaphoreReleaser()
|
||||
{
|
||||
Dispose(false);
|
||||
try
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// we do NOT want the finalizer to throw - never ever
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Configuration
|
||||
//make this volatile so that we can ensure thread safety with a double check lock
|
||||
private static volatile string _reservedUrlsCache;
|
||||
private static string _reservedPathsCache;
|
||||
private static StartsWithContainer _reservedList = new StartsWithContainer();
|
||||
private static HashSet<string> _reservedList = new HashSet<string>();
|
||||
private static string _reservedPaths;
|
||||
private static string _reservedUrls;
|
||||
//ensure the built on (non-changeable) reserved paths are there at all times
|
||||
@@ -767,38 +767,31 @@ namespace Umbraco.Core.Configuration
|
||||
// store references to strings to determine changes
|
||||
_reservedPathsCache = GlobalSettings.ReservedPaths;
|
||||
_reservedUrlsCache = GlobalSettings.ReservedUrls;
|
||||
|
||||
string _root = SystemDirectories.Root.Trim().ToLower();
|
||||
|
||||
|
||||
// add URLs and paths to a new list
|
||||
StartsWithContainer _newReservedList = new StartsWithContainer();
|
||||
foreach (string reservedUrl in _reservedUrlsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
|
||||
var newReservedList = new HashSet<string>();
|
||||
foreach (var reservedUrlTrimmed in _reservedUrlsCache
|
||||
.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(x => x.Trim().ToLowerInvariant())
|
||||
.Where(x => x.IsNullOrWhiteSpace() == false)
|
||||
.Select(reservedUrl => IOHelper.ResolveUrl(reservedUrl).Trim().EnsureStartsWith("/"))
|
||||
.Where(reservedUrlTrimmed => reservedUrlTrimmed.IsNullOrWhiteSpace() == false))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(reservedUrl))
|
||||
continue;
|
||||
|
||||
|
||||
//resolves the url to support tilde chars
|
||||
string reservedUrlTrimmed = IOHelper.ResolveUrl(reservedUrl.Trim()).Trim().ToLower();
|
||||
if (reservedUrlTrimmed.Length > 0)
|
||||
_newReservedList.Add(reservedUrlTrimmed);
|
||||
newReservedList.Add(reservedUrlTrimmed);
|
||||
}
|
||||
|
||||
foreach (string reservedPath in _reservedPathsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
|
||||
foreach (var reservedPathTrimmed in _reservedPathsCache
|
||||
.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(x => x.Trim().ToLowerInvariant())
|
||||
.Where(x => x.IsNullOrWhiteSpace() == false)
|
||||
.Select(reservedPath => IOHelper.ResolveUrl(reservedPath).Trim().EnsureStartsWith("/").EnsureEndsWith("/"))
|
||||
.Where(reservedPathTrimmed => reservedPathTrimmed.IsNullOrWhiteSpace() == false))
|
||||
{
|
||||
bool trimEnd = !reservedPath.EndsWith("/");
|
||||
if (string.IsNullOrWhiteSpace(reservedPath))
|
||||
continue;
|
||||
|
||||
//resolves the url to support tilde chars
|
||||
string reservedPathTrimmed = IOHelper.ResolveUrl(reservedPath.Trim()).Trim().ToLower();
|
||||
|
||||
if (reservedPathTrimmed.Length > 0)
|
||||
_newReservedList.Add(reservedPathTrimmed + (reservedPathTrimmed.EndsWith("/") ? "" : "/"));
|
||||
newReservedList.Add(reservedPathTrimmed);
|
||||
}
|
||||
|
||||
// use the new list from now on
|
||||
_reservedList = _newReservedList;
|
||||
_reservedList = newReservedList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -806,107 +799,17 @@ namespace Umbraco.Core.Configuration
|
||||
//The url should be cleaned up before checking:
|
||||
// * If it doesn't contain an '.' in the path then we assume it is a path based URL, if that is the case we should add an trailing '/' because all of our reservedPaths use a trailing '/'
|
||||
// * We shouldn't be comparing the query at all
|
||||
var pathPart = url.Split('?')[0];
|
||||
if (!pathPart.Contains(".") && !pathPart.EndsWith("/"))
|
||||
var pathPart = url.Split(new[] {'?'}, StringSplitOptions.RemoveEmptyEntries)[0].ToLowerInvariant();
|
||||
if (pathPart.Contains(".") == false)
|
||||
{
|
||||
pathPart += "/";
|
||||
pathPart = pathPart.EnsureEndsWith('/');
|
||||
}
|
||||
|
||||
// return true if url starts with an element of the reserved list
|
||||
return _reservedList.StartsWith(pathPart.ToLowerInvariant());
|
||||
return _reservedList.Any(x => pathPart.InvariantStartsWith(x));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Structure that checks in logarithmic time
|
||||
/// if a given string starts with one of the added keys.
|
||||
/// </summary>
|
||||
private class StartsWithContainer
|
||||
{
|
||||
/// <summary>Internal sorted list of keys.</summary>
|
||||
public SortedList<string, string> _list
|
||||
= new SortedList<string, string>(StartsWithComparator.Instance);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified new key.
|
||||
/// </summary>
|
||||
/// <param name="newKey">The new key.</param>
|
||||
public void Add(string newKey)
|
||||
{
|
||||
// if the list already contains an element that begins with newKey, return
|
||||
if (String.IsNullOrEmpty(newKey) || StartsWith(newKey))
|
||||
return;
|
||||
|
||||
// create a new collection, so the old one can still be accessed
|
||||
SortedList<string, string> newList
|
||||
= new SortedList<string, string>(_list.Count + 1, StartsWithComparator.Instance);
|
||||
|
||||
// add only keys that don't already start with newKey, others are unnecessary
|
||||
foreach (string key in _list.Keys)
|
||||
if (!key.StartsWith(newKey))
|
||||
newList.Add(key, null);
|
||||
// add the new key
|
||||
newList.Add(newKey, null);
|
||||
|
||||
// update the list (thread safe, _list was never in incomplete state)
|
||||
_list = newList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the given string starts with any of the added keys.
|
||||
/// </summary>
|
||||
/// <param name="target">The target.</param>
|
||||
/// <returns>true if a key is found that matches the start of target</returns>
|
||||
/// <remarks>
|
||||
/// Runs in O(s*log(n)), with n the number of keys and s the length of target.
|
||||
/// </remarks>
|
||||
public bool StartsWith(string target)
|
||||
{
|
||||
return _list.ContainsKey(target);
|
||||
}
|
||||
|
||||
/// <summary>Comparator that tests if a string starts with another.</summary>
|
||||
/// <remarks>Not a real comparator, since it is not reflexive. (x==y does not imply y==x)</remarks>
|
||||
private sealed class StartsWithComparator : IComparer<string>
|
||||
{
|
||||
/// <summary>Default string comparer.</summary>
|
||||
private readonly static Comparer<string> _stringComparer = Comparer<string>.Default;
|
||||
|
||||
/// <summary>Gets an instance of the StartsWithComparator.</summary>
|
||||
public static readonly StartsWithComparator Instance = new StartsWithComparator();
|
||||
|
||||
/// <summary>
|
||||
/// Tests if whole begins with all characters of part.
|
||||
/// </summary>
|
||||
/// <param name="part">The part.</param>
|
||||
/// <param name="whole">The whole.</param>
|
||||
/// <returns>
|
||||
/// Returns 0 if whole starts with part, otherwise performs standard string comparison.
|
||||
/// </returns>
|
||||
public int Compare(string part, string whole)
|
||||
{
|
||||
// let the default string comparer deal with null or when part is not smaller then whole
|
||||
if (part == null || whole == null || part.Length >= whole.Length)
|
||||
return _stringComparer.Compare(part, whole);
|
||||
|
||||
////ensure both have a / on the end
|
||||
//part = part.EndsWith("/") ? part : part + "/";
|
||||
//whole = whole.EndsWith("/") ? whole : whole + "/";
|
||||
//if (part.Length >= whole.Length)
|
||||
// return _stringComparer.Compare(part, whole);
|
||||
|
||||
// loop through all characters that part and whole have in common
|
||||
int pos = 0;
|
||||
bool match;
|
||||
do
|
||||
{
|
||||
match = (part[pos] == whole[pos]);
|
||||
} while (match && ++pos < part.Length);
|
||||
|
||||
// return result of last comparison
|
||||
return match ? 0 : (part[pos] < whole[pos] ? -1 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.3.0");
|
||||
private static readonly Version Version = new Version("7.3.3");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
public const string Users = "users";
|
||||
|
||||
/// <summary>
|
||||
/// Application alias for the users section.
|
||||
/// Application alias for the forms section.
|
||||
/// </summary>
|
||||
public const string Forms = "forms";
|
||||
}
|
||||
|
||||
@@ -310,13 +310,13 @@ namespace Umbraco.Core
|
||||
public const string TextboxAlias = "Umbraco.Textbox";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Textbox multiple datatype.
|
||||
/// Guid for the Textarea datatype.
|
||||
/// </summary>
|
||||
[Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")]
|
||||
public const string TextboxMultiple = "67DB8357-EF57-493E-91AC-936D305E0F2A";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Textbox multiple datatype.
|
||||
/// Alias for the Textarea datatype.
|
||||
/// </summary>
|
||||
public const string TextboxMultipleAlias = "Umbraco.TextboxMultiple";
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace Umbraco.Core
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
@@ -15,6 +18,8 @@
|
||||
/// <summary>
|
||||
/// The auth cookie name
|
||||
/// </summary>
|
||||
[Obsolete("DO NOT USE THIS, USE ISecuritySection.AuthCookieName, this will be removed in future versions")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string AuthCookieName = "UMB_UCONTEXT";
|
||||
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
get
|
||||
{
|
||||
return IOHelper.ReturnPath("umbracoWebservicesPath", "~/umbraco/webservices");
|
||||
return IOHelper.ReturnPath("umbracoWebservicesPath", Umbraco.EnsureEndsWith("/") + "webservices");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -560,8 +560,7 @@ namespace Umbraco.Core.Models
|
||||
//Additional thumbnails configured as prevalues on the DataType
|
||||
if (thumbnailSizes != null)
|
||||
{
|
||||
var sep = (thumbnailSizes.Contains("") == false && thumbnailSizes.Contains(",")) ? ',' : ';';
|
||||
foreach (var thumb in thumbnailSizes.Split(sep))
|
||||
foreach (var thumb in thumbnailSizes.Split(new[] { ";", "," }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
int thumbSize;
|
||||
if (thumb != "" && int.TryParse(thumb, out thumbSize))
|
||||
|
||||
@@ -533,6 +533,18 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="propertyGroupName">Name of the <see cref="PropertyGroup"/> to remove</param>
|
||||
public void RemovePropertyGroup(string propertyGroupName)
|
||||
{
|
||||
// if no group exists with that name, do nothing
|
||||
var group = PropertyGroups[propertyGroupName];
|
||||
if (group == null) return;
|
||||
|
||||
// re-assign the group's properties to no group
|
||||
foreach (var property in group.PropertyTypes)
|
||||
{
|
||||
property.PropertyGroupId = new Lazy<int>(() => 0);
|
||||
_propertyTypes.Add(property);
|
||||
}
|
||||
|
||||
// actually remove the group
|
||||
PropertyGroups.RemoveItem(propertyGroupName);
|
||||
OnPropertyChanged(PropertyGroupCollectionSelector);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using AutoMapper;
|
||||
|
||||
using Umbraco.Core.Models.Mapping;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
namespace Umbraco.Core.Models.Identity
|
||||
{
|
||||
@@ -24,6 +25,18 @@ namespace Umbraco.Core.Models.Identity
|
||||
.ForMember(user => user.UserTypeAlias, expression => expression.MapFrom(user => user.UserType.Alias))
|
||||
.ForMember(user => user.AccessFailedCount, expression => expression.MapFrom(user => user.FailedPasswordAttempts))
|
||||
.ForMember(user => user.AllowedSections, expression => expression.MapFrom(user => user.AllowedSections.ToArray()));
|
||||
|
||||
config.CreateMap<BackOfficeIdentityUser, UserData>()
|
||||
.ConstructUsing((BackOfficeIdentityUser user) => new UserData(Guid.NewGuid().ToString("N"))) //this is the 'session id'
|
||||
.ForMember(detail => detail.Id, opt => opt.MapFrom(user => user.Id))
|
||||
.ForMember(detail => detail.AllowedApplications, opt => opt.MapFrom(user => user.AllowedSections))
|
||||
.ForMember(detail => detail.RealName, opt => opt.MapFrom(user => user.Name))
|
||||
.ForMember(detail => detail.Roles, opt => opt.MapFrom(user => new[] { user.UserTypeAlias }))
|
||||
.ForMember(detail => detail.StartContentNode, opt => opt.MapFrom(user => user.StartContentId))
|
||||
.ForMember(detail => detail.StartMediaNode, opt => opt.MapFrom(user => user.StartMediaId))
|
||||
.ForMember(detail => detail.Username, opt => opt.MapFrom(user => user.UserName))
|
||||
.ForMember(detail => detail.Culture, opt => opt.MapFrom(user => user.Culture))
|
||||
.ForMember(detail => detail.SessionId, opt => opt.MapFrom(user => user.SecurityStamp.IsNullOrWhiteSpace() ? Guid.NewGuid().ToString("N") : user.SecurityStamp));
|
||||
}
|
||||
|
||||
private string GetPasswordHash(string storedPass)
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Umbraco.Core.Models
|
||||
[IgnoreDataMember]
|
||||
public CultureInfo CultureInfo
|
||||
{
|
||||
get { return CultureInfo.CreateSpecificCulture(IsoCode); }
|
||||
get { return CultureInfo.GetCultureInfo(IsoCode); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,7 +280,7 @@ namespace Umbraco.Core.Models
|
||||
//This is the default value if the prop is not found
|
||||
true);
|
||||
if (a.Success == false) return a.Result;
|
||||
|
||||
if (Properties[Constants.Conventions.Member.IsApproved].Value == null) return true;
|
||||
var tryConvert = Properties[Constants.Conventions.Member.IsApproved].Value.TryConvertTo<bool>();
|
||||
if (tryConvert.Success)
|
||||
{
|
||||
@@ -313,7 +313,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.IsLockedOut, "IsLockedOut", false);
|
||||
if (a.Success == false) return a.Result;
|
||||
|
||||
if (Properties[Constants.Conventions.Member.IsLockedOut].Value == null) return false;
|
||||
var tryConvert = Properties[Constants.Conventions.Member.IsLockedOut].Value.TryConvertTo<bool>();
|
||||
if (tryConvert.Success)
|
||||
{
|
||||
@@ -346,7 +346,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.LastLoginDate, "LastLoginDate", default(DateTime));
|
||||
if (a.Success == false) return a.Result;
|
||||
|
||||
if (Properties[Constants.Conventions.Member.LastLoginDate].Value == null) return default(DateTime);
|
||||
var tryConvert = Properties[Constants.Conventions.Member.LastLoginDate].Value.TryConvertTo<DateTime>();
|
||||
if (tryConvert.Success)
|
||||
{
|
||||
@@ -379,7 +379,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.LastPasswordChangeDate, "LastPasswordChangeDate", default(DateTime));
|
||||
if (a.Success == false) return a.Result;
|
||||
|
||||
if (Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value == null) return default(DateTime);
|
||||
var tryConvert = Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value.TryConvertTo<DateTime>();
|
||||
if (tryConvert.Success)
|
||||
{
|
||||
@@ -412,7 +412,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.LastLockoutDate, "LastLockoutDate", default(DateTime));
|
||||
if (a.Success == false) return a.Result;
|
||||
|
||||
if (Properties[Constants.Conventions.Member.LastLockoutDate].Value == null) return default(DateTime);
|
||||
var tryConvert = Properties[Constants.Conventions.Member.LastLockoutDate].Value.TryConvertTo<DateTime>();
|
||||
if (tryConvert.Success)
|
||||
{
|
||||
@@ -446,7 +446,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.FailedPasswordAttempts, "FailedPasswordAttempts", 0);
|
||||
if (a.Success == false) return a.Result;
|
||||
|
||||
if (Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value == null) return default(int);
|
||||
var tryConvert = Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value.TryConvertTo<int>();
|
||||
if (tryConvert.Success)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
internal class MigrationDto
|
||||
{
|
||||
[Column("id")]
|
||||
[PrimaryKeyColumn(AutoIncrement = true)]
|
||||
[PrimaryKeyColumn(AutoIncrement = true, IdentitySeed = 100)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("name")]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using System.Collections.Concurrent;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Mappers
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a <see cref="TaskType"/> to DTO mapper used to translate the properties of the public api
|
||||
/// implementation to that of the database's DTO as sql: [tableName].[columnName].
|
||||
/// </summary>
|
||||
[MapperFor(typeof(TaskType))]
|
||||
public sealed class TaskTypeMapper : BaseMapper
|
||||
{
|
||||
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
|
||||
|
||||
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
|
||||
// otherwise that would fail because there is no public constructor.
|
||||
public TaskTypeMapper()
|
||||
{
|
||||
BuildMap();
|
||||
}
|
||||
|
||||
#region Overrides of BaseMapper
|
||||
|
||||
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
|
||||
{
|
||||
get { return PropertyInfoCacheInstance; }
|
||||
}
|
||||
|
||||
internal override void BuildMap()
|
||||
{
|
||||
CacheMap<TaskType, TaskTypeDto>(src => src.Id, dto => dto.Id);
|
||||
CacheMap<TaskType, TaskTypeDto>(src => src.Alias, dto => dto.Alias);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -21, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1,-21", SortOrder = 0, UniqueId = new Guid("BF7C7CBC-952F-4518-97A2-69E9C7B33842"), Text = "Recycle Bin", NodeObjectType = new Guid(Constants.ObjectTypes.MediaRecycleBin), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -92, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-92", SortOrder = 35, UniqueId = new Guid("f0bc4bfb-b499-40d6-ba86-058885a5178c"), Text = "Label", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -90, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-90", SortOrder = 34, UniqueId = new Guid("84c6b441-31df-4ffe-b67e-67d5bc3ae65a"), Text = "Upload", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -89, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-89", SortOrder = 33, UniqueId = new Guid("c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3"), Text = "Textbox multiple", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -89, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-89", SortOrder = 33, UniqueId = new Guid("c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3"), Text = "Textarea", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -88, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-88", SortOrder = 32, UniqueId = new Guid("0cc0eba1-9960-42c9-bf9b-60e150b429ae"), Text = "Textstring", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -87, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-87", SortOrder = 4, UniqueId = new Guid("ca90c950-0aff-4e72-b976-a30b1ac57dad"), Text = "Richtext editor", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -51, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-51", SortOrder = 2, UniqueId = new Guid("2e6d3631-066e-44b8-aec4-96f09099b2b5"), Text = "Numeric", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeOne
|
||||
{
|
||||
/// <summary>
|
||||
/// This fixes the storage of user languages from the old format like en_us to en-US
|
||||
/// </summary>
|
||||
[Migration("7.3.1", 0, GlobalSettings.UmbracoMigrationName)]
|
||||
public class UpdateUserLanguagesToIsoCode : MigrationBase
|
||||
{
|
||||
public UpdateUserLanguagesToIsoCode(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
var userData = Context.Database.Fetch<UserDto>(new Sql().Select("*").From<UserDto>(SqlSyntax));
|
||||
foreach (var user in userData.Where(x => x.UserLanguage.Contains("_")))
|
||||
{
|
||||
var languageParts = user.UserLanguage.Split('_');
|
||||
if (languageParts.Length == 2)
|
||||
{
|
||||
Update.Table("umbracoUser")
|
||||
.Set(new {userLanguage = languageParts[0] + "-" + languageParts[1].ToUpperInvariant()})
|
||||
.Where(new {id = user.Id});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeTwo
|
||||
{
|
||||
/// <summary>
|
||||
/// This reinserts all migrations in the migrations table to account for initial rows inserted
|
||||
/// on creation without identity enabled.
|
||||
/// </summary>
|
||||
[Migration("7.3.2", 0, GlobalSettings.UmbracoMigrationName)]
|
||||
public class EnsureMigrationsTableIdentityIsCorrect : MigrationBase
|
||||
{
|
||||
public EnsureMigrationsTableIdentityIsCorrect(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
// Due to the delayed execution of migrations, we have to wrap this code in Execute.Code to ensure the previous
|
||||
// migration steps (esp. creating the migrations table) have completed before trying to fetch migrations from
|
||||
// this table.
|
||||
List<MigrationDto> migrations = null;
|
||||
Execute.Code(db =>
|
||||
{
|
||||
migrations = Context.Database.Fetch<MigrationDto>(new Sql().Select("*").From<MigrationDto>(SqlSyntax));
|
||||
return string.Empty;
|
||||
});
|
||||
Delete.FromTable("umbracoMigration").AllRows();
|
||||
Execute.Code(database =>
|
||||
{
|
||||
if (migrations != null)
|
||||
{
|
||||
foreach (var migration in migrations)
|
||||
{
|
||||
database.Insert("umbracoMigration", "id", true,
|
||||
new {name = migration.Name, createDate = migration.CreateDate, version = migration.Version});
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
});
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -28,37 +28,38 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixZeroOne
|
||||
{
|
||||
if (database != null)
|
||||
{
|
||||
//Fetch all PropertyTypes that belongs to a PropertyTypeGroup
|
||||
//Fetch all PropertyTypes that belongs to a PropertyTypeGroup
|
||||
//NOTE: We are writing the full query because we've added a column to the PropertyTypeDto in later versions so one of the columns
|
||||
// won't exist yet
|
||||
var propertyTypes = database.Fetch<PropertyTypeDto>("SELECT * FROM cmsPropertyType WHERE propertyTypeGroupId > 0");
|
||||
//NOTE: We're using dynamic to avoid having this migration fail due to the UniqueId column added in 7.3 (this column is not added
|
||||
// in the table yet and will make the mapping of done by Fetch fail when the actual type is used here).
|
||||
var propertyTypes = database.Fetch<dynamic>("SELECT * FROM cmsPropertyType WHERE propertyTypeGroupId > 0");
|
||||
|
||||
var propertyGroups = database.Fetch<PropertyTypeGroupDto>("WHERE id > 0");
|
||||
|
||||
foreach (var propertyType in propertyTypes)
|
||||
{
|
||||
//Get the PropertyTypeGroup that the current PropertyType references
|
||||
var parentPropertyTypeGroup = propertyGroups.FirstOrDefault(x => x.Id == propertyType.PropertyTypeGroupId);
|
||||
var parentPropertyTypeGroup = propertyGroups.FirstOrDefault(x => x.Id == propertyType.propertyTypeGroupId);
|
||||
if (parentPropertyTypeGroup != null)
|
||||
{
|
||||
//If the ContentType is the same on the PropertyType and the PropertyTypeGroup the group is valid and we skip to the next
|
||||
if (parentPropertyTypeGroup.ContentTypeNodeId == propertyType.ContentTypeId) continue;
|
||||
if (parentPropertyTypeGroup.ContentTypeNodeId == propertyType.contentTypeId) continue;
|
||||
|
||||
//Check if the 'new' PropertyTypeGroup has already been created
|
||||
var existingPropertyTypeGroup =
|
||||
propertyGroups.FirstOrDefault(
|
||||
x =>
|
||||
x.ParentGroupId == parentPropertyTypeGroup.Id && x.Text == parentPropertyTypeGroup.Text &&
|
||||
x.ContentTypeNodeId == propertyType.ContentTypeId);
|
||||
x.ContentTypeNodeId == propertyType.contentTypeId);
|
||||
|
||||
//This should ensure that we don't create duplicate groups for a single ContentType
|
||||
if (existingPropertyTypeGroup == null)
|
||||
{
|
||||
|
||||
//Create a new PropertyTypeGroup that references the parent group that the PropertyType was referencing pre-6.0.1
|
||||
var propertyGroup = new PropertyTypeGroupDto
|
||||
{
|
||||
ContentTypeNodeId = propertyType.ContentTypeId,
|
||||
ContentTypeNodeId = propertyType.contentTypeId,
|
||||
ParentGroupId = parentPropertyTypeGroup.Id,
|
||||
Text = parentPropertyTypeGroup.Text,
|
||||
SortOrder = parentPropertyTypeGroup.SortOrder
|
||||
@@ -69,19 +70,18 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixZeroOne
|
||||
propertyGroup.Id = id;
|
||||
propertyGroups.Add(propertyGroup);
|
||||
//Update the reference to the new PropertyTypeGroup on the current PropertyType
|
||||
propertyType.PropertyTypeGroupId = id;
|
||||
database.Update(propertyType);
|
||||
propertyType.propertyTypeGroupId = id;
|
||||
database.Update("cmsPropertyType", "id", propertyType);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Update the reference to the existing PropertyTypeGroup on the current PropertyType
|
||||
propertyType.PropertyTypeGroupId = existingPropertyTypeGroup.Id;
|
||||
database.Update(propertyType);
|
||||
//Update the reference to the existing PropertyTypeGroup on the current PropertyType
|
||||
propertyType.propertyTypeGroupId = existingPropertyTypeGroup.Id;
|
||||
database.Update("cmsPropertyType", "id", propertyType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,7 +297,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
//If there's a GetAll zero count cache, ensure it is cleared
|
||||
RuntimeCache.ClearCacheItem(GetCacheTypeKey<TEntity>());
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
//if an exception is thrown we need to remove the entry from cache, this is ONLY a work around because of the way
|
||||
// that we cache entities: http://issues.umbraco.org/issue/U4-4259
|
||||
|
||||
@@ -682,14 +682,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
public RenderingEngine DetermineTemplateRenderingEngine(ITemplate template)
|
||||
{
|
||||
var engine = _templateConfig.DefaultRenderingEngine;
|
||||
|
||||
if (template.Content.IsNullOrWhiteSpace() == false && MasterPageHelper.IsMasterPageSyntax(template.Content))
|
||||
var viewHelper = new ViewHelper(_viewsFileSystem);
|
||||
if (!viewHelper.ViewExists(template))
|
||||
{
|
||||
//there is a design but its definitely a webforms design
|
||||
return RenderingEngine.WebForms;
|
||||
if (template.Content.IsNullOrWhiteSpace() == false && MasterPageHelper.IsMasterPageSyntax(template.Content))
|
||||
{
|
||||
//there is a design but its definitely a webforms design and we haven't got a MVC view already for it
|
||||
return RenderingEngine.WebForms;
|
||||
}
|
||||
}
|
||||
|
||||
var viewHelper = new ViewHelper(_viewsFileSystem);
|
||||
var masterPageHelper = new MasterPageHelper(_masterpagesFileSystem);
|
||||
|
||||
switch (engine)
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace Umbraco.Core.Persistence
|
||||
|
||||
public override void OnException(Exception x)
|
||||
{
|
||||
_logger.Info<UmbracoDatabase>(x.StackTrace);
|
||||
_logger.Error<UmbracoDatabase>("Database exception occurred", x);
|
||||
base.OnException(x);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Maps a property source value to a data object.
|
||||
/// </summary>
|
||||
// todo: drop IPropertyEditorValueConverter support (when?).
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
@@ -15,7 +16,6 @@ using Microsoft.Owin;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Microsoft.Owin;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
@@ -157,9 +157,6 @@ namespace Umbraco.Core.Security
|
||||
return new HttpContextWrapper(http).GetCurrentIdentity(authenticateRequestIfNotFound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This clears the forms authentication cookie
|
||||
/// </summary>
|
||||
public static void UmbracoLogout(this HttpContextBase http)
|
||||
{
|
||||
if (http == null) throw new ArgumentNullException("http");
|
||||
@@ -170,6 +167,8 @@ namespace Umbraco.Core.Security
|
||||
/// This clears the forms authentication cookie for webapi since cookies are handled differently
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
[Obsolete("Use OWIN IAuthenticationManager.SignOut instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public static void UmbracoLogoutWebApi(this HttpResponseMessage response)
|
||||
{
|
||||
if (response == null) throw new ArgumentNullException("response");
|
||||
@@ -195,11 +194,8 @@ namespace Umbraco.Core.Security
|
||||
response.Headers.AddCookies(new[] { authCookie, prevCookie, extLoginCookie });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This adds the forms authentication cookie for webapi since cookies are handled differently
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
/// <param name="user"></param>
|
||||
[Obsolete("Use WebSecurity.SetPrincipalForRequest")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public static FormsAuthenticationTicket UmbracoLoginWebApi(this HttpResponseMessage response, IUser user)
|
||||
{
|
||||
if (response == null) throw new ArgumentNullException("response");
|
||||
@@ -250,26 +246,29 @@ namespace Umbraco.Core.Security
|
||||
if (http == null) throw new ArgumentNullException("http");
|
||||
new HttpContextWrapper(http).UmbracoLogout();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Renews the Umbraco authentication ticket
|
||||
/// This will force ticket renewal in the OWIN pipeline
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <returns></returns>
|
||||
public static bool RenewUmbracoAuthTicket(this HttpContextBase http)
|
||||
{
|
||||
if (http == null) throw new ArgumentNullException("http");
|
||||
return RenewAuthTicket(http,
|
||||
UmbracoConfig.For.UmbracoSettings().Security.AuthCookieName,
|
||||
UmbracoConfig.For.UmbracoSettings().Security.AuthCookieDomain,
|
||||
//Umbraco has always persisted it's original cookie for 1 day so we'll keep it that way
|
||||
1440);
|
||||
http.Items["umbraco-force-auth"] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will force ticket renewal in the OWIN pipeline
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool RenewUmbracoAuthTicket(this HttpContext http)
|
||||
{
|
||||
if (http == null) throw new ArgumentNullException("http");
|
||||
return new HttpContextWrapper(http).RenewUmbracoAuthTicket();
|
||||
http.Items["umbraco-force-auth"] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -390,8 +389,7 @@ namespace Umbraco.Core.Security
|
||||
//ensure there's def an expired cookie
|
||||
http.Response.Cookies.Add(new HttpCookie(c) { Expires = DateTime.Now.AddYears(-1) });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static FormsAuthenticationTicket GetAuthTicket(this HttpContextBase http, string cookieName)
|
||||
@@ -432,51 +430,6 @@ namespace Umbraco.Core.Security
|
||||
return FormsAuthentication.Decrypt(formsCookie);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renews the forms authentication ticket & cookie
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <param name="cookieName"></param>
|
||||
/// <param name="cookieDomain"></param>
|
||||
/// <param name="minutesPersisted"></param>
|
||||
/// <returns>true if there was a ticket to renew otherwise false if there was no ticket</returns>
|
||||
private static bool RenewAuthTicket(this HttpContextBase http, string cookieName, string cookieDomain, int minutesPersisted)
|
||||
{
|
||||
if (http == null) throw new ArgumentNullException("http");
|
||||
//get the ticket
|
||||
var ticket = GetAuthTicket(http, cookieName);
|
||||
//renew the ticket
|
||||
var renewed = FormsAuthentication.RenewTicketIfOld(ticket);
|
||||
if (renewed == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//get the request cookie to get it's expiry date,
|
||||
//NOTE: this will never be null becaues we already do this
|
||||
// check in teh GetAuthTicket.
|
||||
var formsCookie = http.Request.Cookies[cookieName];
|
||||
|
||||
//encrypt it
|
||||
var hash = FormsAuthentication.Encrypt(renewed);
|
||||
//write it to the response
|
||||
var cookie = new HttpCookie(cookieName, hash)
|
||||
{
|
||||
Expires = DateTime.Now.AddMinutes(minutesPersisted),
|
||||
Domain = cookieDomain
|
||||
};
|
||||
|
||||
if (GlobalSettings.UseSSL)
|
||||
cookie.Secure = true;
|
||||
|
||||
//ensure http only, this should only be able to be accessed via the server
|
||||
cookie.HttpOnly = true;
|
||||
|
||||
//rewrite the cooke
|
||||
http.Response.Cookies.Set(cookie);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a custom FormsAuthentication ticket with the data specified
|
||||
/// </summary>
|
||||
|
||||
@@ -1,12 +1,38 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Owin;
|
||||
using Microsoft.Owin.Security.Cookies;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
public class BackOfficeCookieAuthenticationProvider : CookieAuthenticationProvider
|
||||
{
|
||||
public override void ResponseSignOut(CookieResponseSignOutContext context)
|
||||
{
|
||||
base.ResponseSignOut(context);
|
||||
|
||||
//Make sure the definitely all of these cookies are cleared when signing out with cookies
|
||||
context.Response.Cookies.Append(UmbracoConfig.For.UmbracoSettings().Security.AuthCookieName, "", new CookieOptions
|
||||
{
|
||||
Expires = DateTime.Now.AddYears(-1),
|
||||
Path = "/"
|
||||
});
|
||||
context.Response.Cookies.Append(Constants.Web.PreviewCookieName, "", new CookieOptions
|
||||
{
|
||||
Expires = DateTime.Now.AddYears(-1),
|
||||
Path = "/"
|
||||
});
|
||||
context.Response.Cookies.Append(Constants.Security.BackOfficeExternalCookieName, "", new CookieOptions
|
||||
{
|
||||
Expires = DateTime.Now.AddYears(-1),
|
||||
Path = "/"
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the culture is set correctly for the current back office user
|
||||
/// </summary>
|
||||
|
||||
@@ -53,6 +53,11 @@ namespace Umbraco.Core.Security
|
||||
switch (result)
|
||||
{
|
||||
case SignInStatus.Success:
|
||||
_logger.WriteCore(TraceEventType.Information, 0,
|
||||
string.Format(
|
||||
"User: {0} logged in from IP address {1}",
|
||||
userName,
|
||||
_request.RemoteIpAddress), null, null);
|
||||
break;
|
||||
case SignInStatus.LockedOut:
|
||||
_logger.WriteCore(TraceEventType.Information, 0,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Security;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.AspNet.Identity.Owin;
|
||||
@@ -9,8 +10,6 @@ using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default back office user manager
|
||||
/// </summary>
|
||||
@@ -21,6 +20,18 @@ namespace Umbraco.Core.Security
|
||||
{
|
||||
}
|
||||
|
||||
public BackOfficeUserManager(
|
||||
IUserStore<BackOfficeIdentityUser, int> store,
|
||||
IdentityFactoryOptions<BackOfficeUserManager> options,
|
||||
MembershipProviderBase membershipProvider)
|
||||
: base(store)
|
||||
{
|
||||
if (options == null) throw new ArgumentNullException("options");
|
||||
var manager = new BackOfficeUserManager(store);
|
||||
InitUserManager(manager, membershipProvider, options);
|
||||
}
|
||||
|
||||
#region Static Create methods
|
||||
/// <summary>
|
||||
/// Creates a BackOfficeUserManager instance with all default options and the default BackOfficeUserManager
|
||||
/// </summary>
|
||||
@@ -40,8 +51,8 @@ namespace Umbraco.Core.Security
|
||||
if (externalLoginService == null) throw new ArgumentNullException("externalLoginService");
|
||||
|
||||
var manager = new BackOfficeUserManager(new BackOfficeUserStore(userService, externalLoginService, membershipProvider));
|
||||
|
||||
return InitUserManager(manager, membershipProvider, options);
|
||||
manager.InitUserManager(manager, membershipProvider, options);
|
||||
return manager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -56,13 +67,10 @@ namespace Umbraco.Core.Security
|
||||
BackOfficeUserStore customUserStore,
|
||||
MembershipProviderBase membershipProvider)
|
||||
{
|
||||
if (options == null) throw new ArgumentNullException("options");
|
||||
if (customUserStore == null) throw new ArgumentNullException("customUserStore");
|
||||
|
||||
var manager = new BackOfficeUserManager(customUserStore);
|
||||
|
||||
return InitUserManager(manager, membershipProvider, options);
|
||||
}
|
||||
var manager = new BackOfficeUserManager(customUserStore, options, membershipProvider);
|
||||
return manager;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the user manager with the correct options
|
||||
@@ -71,7 +79,7 @@ namespace Umbraco.Core.Security
|
||||
/// <param name="membershipProvider"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
private static BackOfficeUserManager InitUserManager(BackOfficeUserManager manager, MembershipProviderBase membershipProvider, IdentityFactoryOptions<BackOfficeUserManager> options)
|
||||
protected void InitUserManager(BackOfficeUserManager manager, MembershipProviderBase membershipProvider, IdentityFactoryOptions<BackOfficeUserManager> options)
|
||||
{
|
||||
// Configure validation logic for usernames
|
||||
manager.UserValidator = new UserValidator<BackOfficeIdentityUser, int>(manager)
|
||||
@@ -125,10 +133,10 @@ namespace Umbraco.Core.Security
|
||||
//});
|
||||
|
||||
//manager.EmailService = new EmailService();
|
||||
//manager.SmsService = new SmsService();
|
||||
|
||||
return manager;
|
||||
//manager.SmsService = new SmsService();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -171,5 +179,44 @@ namespace Umbraco.Core.Security
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Logic used to validate a username and password
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="password"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// By default this uses the standard ASP.Net Identity approach which is:
|
||||
/// * Get password store
|
||||
/// * Call VerifyPasswordAsync with the password store + user + password
|
||||
/// * Uses the PasswordHasher.VerifyHashedPassword to compare the stored password
|
||||
///
|
||||
/// In some cases people want simple custom control over the username/password check, for simplicity
|
||||
/// sake, developers would like the users to simply validate against an LDAP directory but the user
|
||||
/// data remains stored inside of Umbraco.
|
||||
/// See: http://issues.umbraco.org/issue/U4-7032 for the use cases.
|
||||
///
|
||||
/// We've allowed this check to be overridden with a simple callback so that developers don't actually
|
||||
/// have to implement/override this class.
|
||||
/// </remarks>
|
||||
public async override Task<bool> CheckPasswordAsync(T user, string password)
|
||||
{
|
||||
if (BackOfficeUserPasswordChecker != null)
|
||||
{
|
||||
var result = await BackOfficeUserPasswordChecker.CheckPasswordAsync(user, password);
|
||||
//if the result indicates to not fallback to the default, then return true if the credentials are valid
|
||||
if (result != BackOfficeUserPasswordCheckerResult.FallbackToDefaultChecker)
|
||||
{
|
||||
return result == BackOfficeUserPasswordCheckerResult.ValidCredentials;
|
||||
}
|
||||
}
|
||||
//use the default behavior
|
||||
return await base.CheckPasswordAsync(user, password);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the default back office user password checker
|
||||
/// </summary>
|
||||
public IBackOfficeUserPasswordChecker BackOfficeUserPasswordChecker { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// The result returned from the IBackOfficeUserPasswordChecker
|
||||
/// </summary>
|
||||
public enum BackOfficeUserPasswordCheckerResult
|
||||
{
|
||||
ValidCredentials,
|
||||
InvalidCredentials,
|
||||
FallbackToDefaultChecker
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// Used by the BackOfficeUserManager to check the username/password which allows for developers to more easily
|
||||
/// set the logic for this procedure.
|
||||
/// </summary>
|
||||
public interface IBackOfficeUserPasswordChecker
|
||||
{
|
||||
Task<BackOfficeUserPasswordCheckerResult> CheckPasswordAsync(BackOfficeIdentityUser user, string password);
|
||||
}
|
||||
}
|
||||
@@ -152,6 +152,9 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
var contentType = FindContentTypeByAlias(contentTypeAlias);
|
||||
var content = new Content(name, parentId, contentType);
|
||||
var parent = GetById(content.ParentId);
|
||||
content.Path = string.Concat(parent.IfNotNull(x => x.Path, content.ParentId.ToString()), ",", content.Id);
|
||||
|
||||
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IContent>(content, contentTypeAlias, parentId), this))
|
||||
{
|
||||
@@ -190,8 +193,11 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IContent"/></returns>
|
||||
public IContent CreateContent(string name, IContent parent, string contentTypeAlias, int userId = 0)
|
||||
{
|
||||
if (parent == null) throw new ArgumentNullException("parent");
|
||||
|
||||
var contentType = FindContentTypeByAlias(contentTypeAlias);
|
||||
var content = new Content(name, parent, contentType);
|
||||
content.Path = string.Concat(parent.Path, ",", content.Id);
|
||||
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IContent>(content, contentTypeAlias, parent), this))
|
||||
{
|
||||
@@ -225,7 +231,7 @@ namespace Umbraco.Core.Services
|
||||
public IContent CreateContentWithIdentity(string name, int parentId, string contentTypeAlias, int userId = 0)
|
||||
{
|
||||
var contentType = FindContentTypeByAlias(contentTypeAlias);
|
||||
var content = new Content(name, parentId, contentType);
|
||||
var content = new Content(name, parentId, contentType);
|
||||
|
||||
//NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
|
||||
// out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now.
|
||||
@@ -276,6 +282,8 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IContent"/></returns>
|
||||
public IContent CreateContentWithIdentity(string name, IContent parent, string contentTypeAlias, int userId = 0)
|
||||
{
|
||||
if (parent == null) throw new ArgumentNullException("parent");
|
||||
|
||||
var contentType = FindContentTypeByAlias(contentTypeAlias);
|
||||
var content = new Content(name, parent, contentType);
|
||||
|
||||
@@ -445,6 +453,9 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
|
||||
public IEnumerable<IContent> GetAncestors(IContent content)
|
||||
{
|
||||
//null check otherwise we get exceptions
|
||||
if (content.Path.IsNullOrWhiteSpace()) return Enumerable.Empty<IContent>();
|
||||
|
||||
var ids = content.Path.Split(',').Where(x => x != Constants.System.Root.ToInvariantString() && x != content.Id.ToString(CultureInfo.InvariantCulture)).Select(int.Parse).ToArray();
|
||||
if (ids.Any() == false)
|
||||
return new List<IContent>();
|
||||
|
||||
@@ -100,6 +100,8 @@ namespace Umbraco.Core.Services
|
||||
|
||||
xml.Add(new XAttribute("loginName", member.Username));
|
||||
xml.Add(new XAttribute("email", member.Email));
|
||||
|
||||
xml.Add(new XAttribute("icon", member.ContentType.Icon));
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
@@ -42,14 +43,18 @@ namespace Umbraco.Core.Services
|
||||
/// <returns></returns>
|
||||
Attempt<PublicAccessEntry> IsProtected(string contentPath);
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use AddRule instead, this method will be removed in future versions")]
|
||||
Attempt<OperationStatus<PublicAccessEntry, OperationStatusType>> AddOrUpdateRule(IContent content, string ruleType, string ruleValue);
|
||||
|
||||
/// <summary>
|
||||
/// Adds/updates a rule, if an entry doesn't exist one will be created with the new rule
|
||||
/// Adds a rule if the entry doesn't already exist
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="ruleType"></param>
|
||||
/// <param name="newRuleValue"></param>
|
||||
/// <param name="ruleValue"></param>
|
||||
/// <returns></returns>
|
||||
Attempt<OperationStatus<PublicAccessEntry, OperationStatusType>> AddOrUpdateRule(IContent content, string ruleType, string newRuleValue);
|
||||
Attempt<OperationStatus<PublicAccessEntry, OperationStatusType>> AddRule(IContent content, string ruleType, string ruleValue);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a rule
|
||||
|
||||
@@ -63,6 +63,8 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
|
||||
var media = new Models.Media(name, parentId, mediaType);
|
||||
var parent = GetById(media.ParentId);
|
||||
media.Path = string.Concat(parent.IfNotNull(x => x.Path, media.ParentId.ToString()), ",", media.Id);
|
||||
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId), this))
|
||||
{
|
||||
@@ -95,8 +97,12 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IMedia"/></returns>
|
||||
public IMedia CreateMedia(string name, IMedia parent, string mediaTypeAlias, int userId = 0)
|
||||
{
|
||||
if (parent == null) throw new ArgumentNullException("parent");
|
||||
|
||||
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
|
||||
var media = new Models.Media(name, parent, mediaType);
|
||||
media.Path = string.Concat(parent.Path, ",", media.Id);
|
||||
|
||||
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parent), this))
|
||||
{
|
||||
media.WasCancelled = true;
|
||||
@@ -184,6 +190,8 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IMedia"/></returns>
|
||||
public IMedia CreateMediaWithIdentity(string name, IMedia parent, string mediaTypeAlias, int userId = 0)
|
||||
{
|
||||
if (parent == null) throw new ArgumentNullException("parent");
|
||||
|
||||
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
|
||||
var media = new Models.Media(name, parent, mediaType);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Logging;
|
||||
@@ -104,14 +105,21 @@ namespace Umbraco.Core.Services
|
||||
return Attempt.If(result != null, result);
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use AddRule instead, this method will be removed in future versions")]
|
||||
public Attempt<OperationStatus<PublicAccessEntry, OperationStatusType>> AddOrUpdateRule(IContent content, string ruleType, string ruleValue)
|
||||
{
|
||||
return AddRule(content, ruleType, ruleValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds/updates a rule
|
||||
/// Adds a rule
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="ruleType"></param>
|
||||
/// <param name="newRuleValue"></param>
|
||||
/// <param name="ruleValue"></param>
|
||||
/// <returns></returns>
|
||||
public Attempt<OperationStatus<PublicAccessEntry, OperationStatusType>> AddOrUpdateRule(IContent content, string ruleType, string newRuleValue)
|
||||
public Attempt<OperationStatus<PublicAccessEntry, OperationStatusType>> AddRule(IContent content, string ruleType, string ruleValue)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
@@ -121,15 +129,16 @@ namespace Umbraco.Core.Services
|
||||
if (entry == null)
|
||||
return Attempt<OperationStatus<PublicAccessEntry, OperationStatusType>>.Fail();
|
||||
|
||||
var existingRule = entry.Rules.FirstOrDefault(x => x.RuleType == ruleType);
|
||||
var existingRule = entry.Rules.FirstOrDefault(x => x.RuleType == ruleType && x.RuleValue == ruleValue);
|
||||
if (existingRule == null)
|
||||
{
|
||||
entry.AddRule(newRuleValue, ruleType);
|
||||
entry.AddRule(ruleValue, ruleType);
|
||||
}
|
||||
else
|
||||
{
|
||||
existingRule.RuleType = ruleType;
|
||||
existingRule.RuleValue = newRuleValue;
|
||||
//If they are both the same already then there's nothing to update, exit
|
||||
return Attempt<OperationStatus<PublicAccessEntry, OperationStatusType>>.Succeed(
|
||||
new OperationStatus<PublicAccessEntry, OperationStatusType>(entry, OperationStatusType.Success, evtMsgs));
|
||||
}
|
||||
|
||||
if (Saving.IsRaisedEventCancelled(
|
||||
|
||||
@@ -146,6 +146,9 @@ namespace Umbraco.Core.Services
|
||||
IsLockedOut = false,
|
||||
IsApproved = true
|
||||
};
|
||||
//adding default sections content and media
|
||||
user.AddAllowedSection("content");
|
||||
user.AddAllowedSection("media");
|
||||
|
||||
if (SavingUser.IsRaisedEventCancelled(new SaveEventArgs<IUser>(user), this))
|
||||
return user;
|
||||
|
||||
@@ -187,7 +187,13 @@ namespace Umbraco.Core.Sync
|
||||
using (_profilingLogger.DebugDuration<DatabaseServerMessenger>("Syncing from database..."))
|
||||
{
|
||||
ProcessDatabaseInstructions();
|
||||
PruneOldInstructions();
|
||||
switch (_appContext.GetCurrentServerRole())
|
||||
{
|
||||
case ServerRole.Single:
|
||||
case ServerRole.Master:
|
||||
PruneOldInstructions();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -214,9 +220,9 @@ namespace Umbraco.Core.Sync
|
||||
// FIXME not true if we're running on a background thread, assuming we can?
|
||||
|
||||
var sql = new Sql().Select("*")
|
||||
.From<CacheInstructionDto>()
|
||||
.From<CacheInstructionDto>(_appContext.DatabaseContext.SqlSyntax)
|
||||
.Where<CacheInstructionDto>(dto => dto.Id > _lastId)
|
||||
.OrderBy<CacheInstructionDto>(dto => dto.Id);
|
||||
.OrderBy<CacheInstructionDto>(dto => dto.Id, _appContext.DatabaseContext.SqlSyntax);
|
||||
|
||||
var dtos = _appContext.DatabaseContext.Database.Fetch<CacheInstructionDto>(sql);
|
||||
if (dtos.Count <= 0) return;
|
||||
@@ -288,7 +294,7 @@ namespace Umbraco.Core.Sync
|
||||
private void EnsureInstructions()
|
||||
{
|
||||
var sql = new Sql().Select("*")
|
||||
.From<CacheInstructionDto>()
|
||||
.From<CacheInstructionDto>(_appContext.DatabaseContext.SqlSyntax)
|
||||
.Where<CacheInstructionDto>(dto => dto.Id == _lastId);
|
||||
|
||||
var dtos = _appContext.DatabaseContext.Database.Fetch<CacheInstructionDto>(sql);
|
||||
|
||||
@@ -15,7 +15,12 @@ namespace Umbraco.Core.Sync
|
||||
// but at the moment it is exposed in CacheRefresher webservice
|
||||
// so for the time being we keep it as-is for backward compatibility reasons
|
||||
|
||||
// need the public one so it can be de-serialized
|
||||
// need this public, parameter-less constructor so the web service messenger
|
||||
// can de-serialize the instructions it receives
|
||||
public RefreshInstruction()
|
||||
{ }
|
||||
|
||||
// need this public one so it can be de-serialized - used by the Json thing
|
||||
// otherwise, should use GetInstructions(...)
|
||||
public RefreshInstruction(Guid refresherId, RefreshMethodType refreshType, Guid guidId, int intId, string jsonIds, string jsonPayload)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
static class ThreadExtensions
|
||||
{
|
||||
public static void SanitizeThreadCulture(this Thread thread)
|
||||
{
|
||||
// get the current culture
|
||||
var currentCulture = CultureInfo.CurrentCulture;
|
||||
|
||||
// at the top of any culture should be the invariant culture - find it
|
||||
// doing an .Equals comparison ensure that we *will* find it and not loop
|
||||
// endlessly
|
||||
var invariantCulture = currentCulture;
|
||||
while (invariantCulture.Equals(CultureInfo.InvariantCulture) == false)
|
||||
invariantCulture = invariantCulture.Parent;
|
||||
|
||||
// now that invariant culture should be the same object as CultureInfo.InvariantCulture
|
||||
// yet for some reasons, sometimes it is not - and this breaks anything that loops on
|
||||
// culture.Parent until a reference equality to CultureInfo.InvariantCulture. See, for
|
||||
// example, the following code in PerformanceCounterLib.IsCustomCategory:
|
||||
//
|
||||
// CultureInfo culture = CultureInfo.CurrentCulture;
|
||||
// while (culture != CultureInfo.InvariantCulture)
|
||||
// {
|
||||
// library = GetPerformanceCounterLib(machine, culture);
|
||||
// if (library.IsCustomCategory(category))
|
||||
// return true;
|
||||
// culture = culture.Parent;
|
||||
// }
|
||||
//
|
||||
// The reference comparisons never succeeds, hence the loop never ends, and the
|
||||
// application hangs.
|
||||
//
|
||||
// granted, that comparison should probably be a .Equals comparison, but who knows
|
||||
// how many times the framework assumes that it can do a reference comparison? So,
|
||||
// better fix the cultures.
|
||||
|
||||
if (ReferenceEquals(invariantCulture, CultureInfo.InvariantCulture))
|
||||
return;
|
||||
|
||||
// if we do not have equality, fix cultures by replacing them with a culture with
|
||||
// the same name, but obtained here and now, with a proper invariant top culture
|
||||
|
||||
thread.CurrentCulture = CultureInfo.GetCultureInfo(thread.CurrentCulture.Name);
|
||||
thread.CurrentUICulture = CultureInfo.GetCultureInfo(thread.CurrentUICulture.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@
|
||||
</Reference>
|
||||
<Reference Include="MySql.Data">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\MySql.Data.6.9.7\lib\net45\MySql.Data.dll</HintPath>
|
||||
<HintPath>..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
@@ -404,6 +404,8 @@
|
||||
<Compile Include="Persistence\Mappers\AccessMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\DomainMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\MigrationEntryMapper.cs" />
|
||||
<Compile Include="Persistence\Mappers\TaskTypeMapper.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeTwo\EnsureMigrationsTableIdentityIsCorrect.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddExternalLoginsTable.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddForeignKeysForLanguageAndDictionaryTables.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeZero\AddServerRegistrationColumnsAndLock.cs" />
|
||||
@@ -435,6 +437,7 @@
|
||||
<Compile Include="Media\Exif\TIFFHeader.cs" />
|
||||
<Compile Include="Media\Exif\TIFFStrip.cs" />
|
||||
<Compile Include="Media\Exif\Utility.cs" />
|
||||
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeOne\UpdateUserLanguagesToIsoCode.cs" />
|
||||
<Compile Include="Persistence\RecordPersistenceType.cs" />
|
||||
<Compile Include="Persistence\Relators\AccessRulesRelator.cs" />
|
||||
<Compile Include="Persistence\Repositories\AuditRepository.cs" />
|
||||
@@ -462,7 +465,9 @@
|
||||
<Compile Include="Security\BackOfficeCookieAuthenticationProvider.cs" />
|
||||
<Compile Include="Security\BackOfficeSignInManager.cs" />
|
||||
<Compile Include="Security\BackOfficeUserManager.cs" />
|
||||
<Compile Include="Security\BackOfficeUserPasswordCheckerResult.cs" />
|
||||
<Compile Include="Security\BackOfficeUserStore.cs" />
|
||||
<Compile Include="Security\IBackOfficeUserPasswordChecker.cs" />
|
||||
<Compile Include="Security\MembershipPasswordHasher.cs" />
|
||||
<Compile Include="SemVersionExtensions.cs" />
|
||||
<Compile Include="ServiceProviderExtensions.cs" />
|
||||
@@ -1275,6 +1280,7 @@
|
||||
<Compile Include="Sync\ApplicationUrlHelper.cs" />
|
||||
<Compile Include="Sync\RefreshMethodType.cs" />
|
||||
<Compile Include="Sync\ServerMessengerBase.cs" />
|
||||
<Compile Include="ThreadExtensions.cs" />
|
||||
<Compile Include="TopologicalSorter.cs" />
|
||||
<Compile Include="Strings\DefaultUrlSegmentProvider.cs" />
|
||||
<Compile Include="Strings\IUrlSegmentProvider.cs" />
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Hosting;
|
||||
using log4net;
|
||||
@@ -64,6 +65,7 @@ namespace Umbraco.Core
|
||||
/// <param name="e"></param>
|
||||
protected void Application_Start(object sender, EventArgs e)
|
||||
{
|
||||
Thread.CurrentThread.SanitizeThreadCulture();
|
||||
StartApplication(sender, e);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<package id="Microsoft.Owin.Security.Cookies" version="3.0.1" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security.OAuth" version="3.0.1" targetFramework="net45" />
|
||||
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
|
||||
<package id="MySql.Data" version="6.9.7" targetFramework="net45" />
|
||||
<package id="MySql.Data" version="6.9.8" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="semver" version="1.1.2" targetFramework="net45" />
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<appSettings>
|
||||
<add key="umbracoConfigurationStatus" value="6.0.0" />
|
||||
<add key="umbracoReservedUrls" value="~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd" />
|
||||
<add key="umbracoReservedPaths" value="~/umbraco,~/install/" />
|
||||
<add key="umbracoReservedPaths" value="~/install/" />
|
||||
<add key="umbracoPath" value="~/umbraco" />
|
||||
<add key="umbracoHideTopLevelNodeFromPath" value="true" />
|
||||
<add key="umbracoUseDirectoryUrls" value="false" />
|
||||
@@ -203,4 +203,4 @@
|
||||
</assemblyBinding>
|
||||
|
||||
</runtime>
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Examine Management">
|
||||
<control>/umbraco/dashboard/ExamineManagement.ascx</control>
|
||||
<control>dashboard/ExamineManagement.ascx</control>
|
||||
</tab>
|
||||
</section>
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Last Edits">
|
||||
<control addPanel="true" MaxRecords="30">/umbraco/dashboard/latestEdits.ascx</control>
|
||||
<control addPanel="true" MaxRecords="30">dashboard/latestEdits.ascx</control>
|
||||
</tab>
|
||||
<tab caption="Change Password">
|
||||
<control addPanel="true">
|
||||
@@ -104,11 +104,11 @@
|
||||
views/dashboard/members/membersdashboardintro.html
|
||||
</control>
|
||||
<control showOnce="true" addPanel="true" panelCaption="">
|
||||
/umbraco/members/membersearch.ascx
|
||||
members/membersearch.ascx
|
||||
</control>
|
||||
<control showOnce="true" addPanel="true" panelCaption="">
|
||||
views/dashboard/members/membersdashboardvideos.html
|
||||
</control>
|
||||
</tab>
|
||||
</section>
|
||||
</dashBoard>
|
||||
</dashBoard>
|
||||
|
||||
@@ -173,7 +173,8 @@ namespace Umbraco.Tests.Logging
|
||||
Console.WriteLine("Flushed {0} events during shutdown", numberLoggedAfterClose - numberLoggedBeforeClose);
|
||||
}
|
||||
|
||||
[Test, Explicit("Long-running")]
|
||||
[NUnit.Framework.Ignore("Keeps failing very randomly")]
|
||||
[Test]
|
||||
public void WillShutdownIfBufferCannotBeFlushedFastEnough()
|
||||
{
|
||||
const int testSize = 250;
|
||||
|
||||
@@ -482,7 +482,7 @@ ALTER TABLE umbracoUser2NodePermission ADD CONSTRAINT PK_umbracoUser2NodePermiss
|
||||
INSERT INTO umbracoNode (id, trashed, parentID, nodeUser, level, path, sortOrder, uniqueID, text, nodeObjectType, createDate) VALUES
|
||||
(-92, 0, -1, 0, 11, '-1,-92', 37, 'f0bc4bfb-b499-40d6-ba86-058885a5178c', 'Label', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
(-90, 0, -1, 0, 11, '-1,-90', 35, '84c6b441-31df-4ffe-b67e-67d5bc3ae65a', 'Upload', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
(-89, 0, -1, 0, 11, '-1,-89', 34, 'c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3', 'Textbox multiple', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
(-89, 0, -1, 0, 11, '-1,-89', 34, 'c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3', 'Textarea', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
(-88, 0, -1, 0, 11, '-1,-88', 33, '0cc0eba1-9960-42c9-bf9b-60e150b429ae', 'Textstring', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
(-87, 0, -1, 0, 11, '-1,-87', 32, 'ca90c950-0aff-4e72-b976-a30b1ac57dad', 'Richtext editor', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
(-51, 0, -1, 0, 11, '-1,-51', 4, '2e6d3631-066e-44b8-aec4-96f09099b2b5', 'Numeric', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '2004/09/30 14:01:49.920'),
|
||||
|
||||
Binary file not shown.
@@ -624,7 +624,7 @@ ALTER TABLE [umbracoNode] DROP CONSTRAINT [FK_umbracoNode_umbracoNode]
|
||||
SET IDENTITY_INSERT [umbracoNode] ON
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-92, 0, -1, 0, 11, N'-1,-92', 37, 'f0bc4bfb-b499-40d6-ba86-058885a5178c', N'Label', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-90, 0, -1, 0, 11, N'-1,-90', 35, '84c6b441-31df-4ffe-b67e-67d5bc3ae65a', N'Upload', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-89, 0, -1, 0, 11, N'-1,-89', 34, 'c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3', N'Textbox multiple', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-89, 0, -1, 0, 11, N'-1,-89', 34, 'c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3', N'Textarea', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-88, 0, -1, 0, 11, N'-1,-88', 33, '0cc0eba1-9960-42c9-bf9b-60e150b429ae', N'Textstring', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-87, 0, -1, 0, 11, N'-1,-87', 32, 'ca90c950-0aff-4e72-b976-a30b1ac57dad', N'Richtext editor', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
INSERT INTO [umbracoNode] ([id], [trashed], [parentID], [nodeUser], [level], [path], [sortOrder], [uniqueID], [text], [nodeObjectType], [createDate]) VALUES (-51, 0, -1, 0, 11, N'-1,-51', 4, '2e6d3631-066e-44b8-aec4-96f09099b2b5', N'Numeric', '30a2a501-1978-4ddb-a57b-f7efed43ba3c', '20040930 14:01:49.920')
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Profiling;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
|
||||
namespace Umbraco.Tests.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
public class RenderIndexActionSelectorAttributeTests
|
||||
{
|
||||
private MethodInfo GetRenderMvcControllerIndexMethodFromCurrentType(Type currType)
|
||||
{
|
||||
return currType.GetMethods().Single(x =>
|
||||
{
|
||||
if (x.Name != "Index") return false;
|
||||
if (x.ReturnParameter == null || x.ReturnParameter.ParameterType != typeof (ActionResult)) return false;
|
||||
var p = x.GetParameters();
|
||||
if (p.Length != 1) return false;
|
||||
if (p[0].ParameterType != typeof (RenderModel)) return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matches_Default_Index()
|
||||
{
|
||||
var attr = new RenderIndexActionSelectorAttribute();
|
||||
var req = new RequestContext();
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var umbCtx = UmbracoContext.EnsureContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new Mock<WebSecurity>(null, null).Object,
|
||||
Mock.Of<IUmbracoSettingsSection>(),
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
true);
|
||||
var ctrl = new MatchesDefaultIndexController(umbCtx);
|
||||
var controllerCtx = new ControllerContext(req, ctrl);
|
||||
var result = attr.IsValidForRequest(controllerCtx,
|
||||
GetRenderMvcControllerIndexMethodFromCurrentType(ctrl.GetType()));
|
||||
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matches_Overriden_Index()
|
||||
{
|
||||
var attr = new RenderIndexActionSelectorAttribute();
|
||||
var req = new RequestContext();
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var umbCtx = UmbracoContext.EnsureContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new Mock<WebSecurity>(null, null).Object,
|
||||
Mock.Of<IUmbracoSettingsSection>(),
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
true);
|
||||
var ctrl = new MatchesOverriddenIndexController(umbCtx);
|
||||
var controllerCtx = new ControllerContext(req, ctrl);
|
||||
var result = attr.IsValidForRequest(controllerCtx,
|
||||
GetRenderMvcControllerIndexMethodFromCurrentType(ctrl.GetType()));
|
||||
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matches_Custom_Index()
|
||||
{
|
||||
var attr = new RenderIndexActionSelectorAttribute();
|
||||
var req = new RequestContext();
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var umbCtx = UmbracoContext.EnsureContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new Mock<WebSecurity>(null, null).Object,
|
||||
Mock.Of<IUmbracoSettingsSection>(),
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
true);
|
||||
var ctrl = new MatchesCustomIndexController(umbCtx);
|
||||
var controllerCtx = new ControllerContext(req, ctrl);
|
||||
var result = attr.IsValidForRequest(controllerCtx,
|
||||
GetRenderMvcControllerIndexMethodFromCurrentType(ctrl.GetType()));
|
||||
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Matches_Async_Index_Same_Signature()
|
||||
{
|
||||
var attr = new RenderIndexActionSelectorAttribute();
|
||||
var req = new RequestContext();
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var umbCtx = UmbracoContext.EnsureContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new Mock<WebSecurity>(null, null).Object,
|
||||
Mock.Of<IUmbracoSettingsSection>(),
|
||||
Enumerable.Empty<IUrlProvider>(),
|
||||
true);
|
||||
var ctrl = new MatchesAsyncIndexController(umbCtx);
|
||||
var controllerCtx = new ControllerContext(req, ctrl);
|
||||
var result = attr.IsValidForRequest(controllerCtx,
|
||||
GetRenderMvcControllerIndexMethodFromCurrentType(ctrl.GetType()));
|
||||
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
public class MatchesDefaultIndexController : RenderMvcController
|
||||
{
|
||||
public MatchesDefaultIndexController(UmbracoContext umbracoContext) : base(umbracoContext)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class MatchesOverriddenIndexController : RenderMvcController
|
||||
{
|
||||
public MatchesOverriddenIndexController(UmbracoContext umbracoContext) : base(umbracoContext)
|
||||
{
|
||||
}
|
||||
|
||||
public override ActionResult Index(RenderModel model)
|
||||
{
|
||||
return base.Index(model);
|
||||
}
|
||||
}
|
||||
|
||||
public class MatchesCustomIndexController : RenderMvcController
|
||||
{
|
||||
public MatchesCustomIndexController(UmbracoContext umbracoContext) : base(umbracoContext)
|
||||
{
|
||||
}
|
||||
|
||||
public ActionResult Index(RenderModel model, int page)
|
||||
{
|
||||
return base.Index(model);
|
||||
}
|
||||
}
|
||||
|
||||
public class MatchesAsyncIndexController : RenderMvcController
|
||||
{
|
||||
public MatchesAsyncIndexController(UmbracoContext umbracoContext) : base(umbracoContext)
|
||||
{
|
||||
}
|
||||
|
||||
public new async Task<ActionResult> Index(RenderModel model)
|
||||
{
|
||||
return await Task.FromResult(base.Index(model));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using NUnit.Framework;
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace Umbraco.Tests.Plugins
|
||||
public void Resolves_Assigned_Mappers()
|
||||
{
|
||||
var foundTypes1 = _manager.ResolveAssignedMapperTypes();
|
||||
Assert.AreEqual(27, foundTypes1.Count());
|
||||
Assert.AreEqual(28, foundTypes1.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -141,6 +141,20 @@ namespace Umbraco.Tests.Services
|
||||
Assert.AreEqual(20, contentService.CountDescendants(parent.Id));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetAncestors_Returns_Empty_List_When_Path_Is_Null()
|
||||
{
|
||||
// Arrange
|
||||
var contentService = ServiceContext.ContentService;
|
||||
|
||||
// Act
|
||||
var current = new Mock<IContent>();
|
||||
var res = contentService.GetAncestors(current.Object);
|
||||
|
||||
// Assert
|
||||
Assert.IsEmpty(res);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Tags_For_Entity_Are_Not_Exposed_Via_Tag_Api_When_Content_Is_Recycled()
|
||||
{
|
||||
|
||||
@@ -1163,6 +1163,48 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(propertyGroup.ParentId.HasValue, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Remove_PropertyGroup_Without_Removing_Property_Types()
|
||||
{
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var basePage = (IContentType)MockedContentTypes.CreateBasicContentType();
|
||||
basePage.AddPropertyGroup("Content");
|
||||
basePage.AddPropertyGroup("Meta");
|
||||
service.Save(basePage);
|
||||
|
||||
var authorPropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "author")
|
||||
{
|
||||
Name = "Author",
|
||||
Description = "",
|
||||
Mandatory = false,
|
||||
SortOrder = 1,
|
||||
DataTypeDefinitionId = -88
|
||||
};
|
||||
var authorAdded = basePage.AddPropertyType(authorPropertyType, "Content");
|
||||
var titlePropertyType = new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, "title")
|
||||
{
|
||||
Name = "Title",
|
||||
Description = "",
|
||||
Mandatory = false,
|
||||
SortOrder = 1,
|
||||
DataTypeDefinitionId = -88
|
||||
};
|
||||
var titleAdded = basePage.AddPropertyType(authorPropertyType, "Meta");
|
||||
|
||||
service.Save(basePage);
|
||||
|
||||
basePage = service.GetContentType(basePage.Id);
|
||||
|
||||
var totalPt = basePage.PropertyTypes.Count();
|
||||
|
||||
basePage.RemovePropertyGroup("Content");
|
||||
service.Save(basePage);
|
||||
|
||||
basePage = service.GetContentType(basePage.Id);
|
||||
|
||||
Assert.AreEqual(totalPt, basePage.PropertyTypes.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Add_PropertyGroup_With_Same_Name_On_Parent_and_Child()
|
||||
{
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace Umbraco.Tests.Services
|
||||
publicAccessService.Save(entry);
|
||||
|
||||
// Act
|
||||
var updated = publicAccessService.AddOrUpdateRule(c, "TestType2", "AnotherVal");
|
||||
var updated = publicAccessService.AddRule(c, "TestType2", "AnotherVal");
|
||||
//re-get
|
||||
entry = publicAccessService.GetEntryForContent(c);
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace Umbraco.Tests.Services
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Update_Rule()
|
||||
public void Can_Add_Multiple_Value_For_Same_Rule_Type()
|
||||
{
|
||||
// Arrange
|
||||
var contentService = ServiceContext.ContentService;
|
||||
@@ -106,21 +106,63 @@ namespace Umbraco.Tests.Services
|
||||
new PublicAccessRule()
|
||||
{
|
||||
RuleType = "TestType",
|
||||
RuleValue = "TestValue"
|
||||
RuleValue = "TestVal"
|
||||
},
|
||||
});
|
||||
publicAccessService.Save(entry);
|
||||
|
||||
// Act
|
||||
var updated = publicAccessService.AddOrUpdateRule(c, "TestType", "AnotherVal");
|
||||
var updated1 = publicAccessService.AddRule(c, "TestType", "AnotherVal1");
|
||||
var updated2 = publicAccessService.AddRule(c, "TestType", "AnotherVal2");
|
||||
|
||||
//re-get
|
||||
entry = publicAccessService.GetEntryForContent(c);
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(updated.Success);
|
||||
Assert.AreEqual(OperationStatusType.Success, updated.Result.StatusType);
|
||||
Assert.AreEqual(1, entry.Rules.Count());
|
||||
Assert.AreEqual("AnotherVal", entry.Rules.ElementAt(0).RuleValue);
|
||||
Assert.IsTrue(updated1.Success);
|
||||
Assert.IsTrue(updated2.Success);
|
||||
Assert.AreEqual(OperationStatusType.Success, updated1.Result.StatusType);
|
||||
Assert.AreEqual(OperationStatusType.Success, updated2.Result.StatusType);
|
||||
Assert.AreEqual(3, entry.Rules.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Remove_Rule()
|
||||
{
|
||||
// Arrange
|
||||
var contentService = ServiceContext.ContentService;
|
||||
var contentTypeService = ServiceContext.ContentTypeService;
|
||||
var ct = MockedContentTypes.CreateSimpleContentType("blah", "Blah");
|
||||
contentTypeService.Save(ct);
|
||||
var c = MockedContent.CreateSimpleContent(ct, "Test", -1);
|
||||
contentService.Save(c);
|
||||
var publicAccessService = ServiceContext.PublicAccessService;
|
||||
var entry = new PublicAccessEntry(c, c, c, new[]
|
||||
{
|
||||
new PublicAccessRule()
|
||||
{
|
||||
RuleType = "TestType",
|
||||
RuleValue = "TestValue1"
|
||||
},
|
||||
new PublicAccessRule()
|
||||
{
|
||||
RuleType = "TestType",
|
||||
RuleValue = "TestValue2"
|
||||
},
|
||||
});
|
||||
publicAccessService.Save(entry);
|
||||
|
||||
// Act
|
||||
var removed = publicAccessService.RemoveRule(c, "TestType", "TestValue1");
|
||||
//re-get
|
||||
entry = publicAccessService.GetEntryForContent(c);
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(removed.Success);
|
||||
Assert.AreEqual(OperationStatusType.Success, removed.Result.StatusType);
|
||||
Assert.AreEqual(1, entry.Rules.Count());
|
||||
Assert.AreEqual("TestValue2", entry.Rules.ElementAt(0).RuleValue);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -398,6 +398,10 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
var user1 = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", userType);
|
||||
|
||||
var result1 = ServiceContext.UserService.GetUserById((int)user1.Id);
|
||||
//expect 2 sections by default
|
||||
Assert.AreEqual(2, result1.AllowedSections.Count());
|
||||
|
||||
//adds some allowed sections
|
||||
user1.AddAllowedSection("test1");
|
||||
user1.AddAllowedSection("test2");
|
||||
@@ -405,8 +409,9 @@ namespace Umbraco.Tests.Services
|
||||
user1.AddAllowedSection("test4");
|
||||
ServiceContext.UserService.Save(user1);
|
||||
|
||||
var result1 = ServiceContext.UserService.GetUserById((int)user1.Id);
|
||||
Assert.AreEqual(4, result1.AllowedSections.Count());
|
||||
result1 = ServiceContext.UserService.GetUserById((int)user1.Id);
|
||||
//expect 6 sections including the two default sections
|
||||
Assert.AreEqual(6, result1.AllowedSections.Count());
|
||||
|
||||
//simulate clearing the sections
|
||||
foreach (var s in user1.AllowedSections)
|
||||
@@ -419,11 +424,9 @@ namespace Umbraco.Tests.Services
|
||||
ServiceContext.UserService.Save(result1);
|
||||
|
||||
//assert
|
||||
|
||||
//re-get
|
||||
result1 = ServiceContext.UserService.GetUserById((int)user1.Id);
|
||||
Assert.AreEqual(2, result1.AllowedSections.Count());
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -448,7 +451,6 @@ namespace Umbraco.Tests.Services
|
||||
var result2 = ServiceContext.UserService.GetUserById((int)user2.Id);
|
||||
Assert.IsFalse(result1.AllowedSections.Contains("test"));
|
||||
Assert.IsFalse(result2.AllowedSections.Contains("test"));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -546,7 +548,7 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(updatedItem.StartMediaId, Is.EqualTo(originalUser.StartMediaId));
|
||||
Assert.That(updatedItem.Email, Is.EqualTo(originalUser.Email));
|
||||
Assert.That(updatedItem.Username, Is.EqualTo(originalUser.Username));
|
||||
Assert.That(updatedItem.AllowedSections.Count(), Is.EqualTo(0));
|
||||
Assert.That(updatedItem.AllowedSections.Count(), Is.EqualTo(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Tests.Templates
|
||||
{
|
||||
[TestFixture]
|
||||
public class TemplateRepositoryTests
|
||||
{
|
||||
private readonly Mock<IDatabaseUnitOfWork> _unitOfWorkMock = new Mock<IDatabaseUnitOfWork>();
|
||||
private readonly Mock<CacheHelper> _cacheMock = new Mock<CacheHelper>();
|
||||
private TemplateRepository _templateRepository;
|
||||
private readonly Mock<IFileSystem> _viewFileSystemMock = new Mock<IFileSystem>();
|
||||
private readonly Mock<IFileSystem> _masterpageFileSystemMock = new Mock<IFileSystem>();
|
||||
private readonly Mock<ITemplatesSection> _templateConfigMock = new Mock<Core.Configuration.UmbracoSettings.ITemplatesSection>();
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var loggerMock = new Mock<ILogger>();
|
||||
var sqlSyntaxMock = new Mock<ISqlSyntaxProvider>();
|
||||
_templateRepository = new TemplateRepository(_unitOfWorkMock.Object, _cacheMock.Object, loggerMock.Object, sqlSyntaxMock.Object, _masterpageFileSystemMock.Object, _viewFileSystemMock.Object, _templateConfigMock.Object);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DetermineTemplateRenderingEngine_Returns_MVC_When_ViewFile_Exists_And_Content_Has_Webform_Markup()
|
||||
{
|
||||
// Project in MVC mode
|
||||
_templateConfigMock.Setup(x => x.DefaultRenderingEngine).Returns(RenderingEngine.Mvc);
|
||||
|
||||
// Template has masterpage content
|
||||
var templateMock = new Mock<ITemplate>();
|
||||
templateMock.Setup(x => x.Alias).Returns("Something");
|
||||
templateMock.Setup(x => x.Content).Returns("<asp:Content />");
|
||||
|
||||
// but MVC View already exists
|
||||
_viewFileSystemMock.Setup(x => x.FileExists(It.IsAny<string>())).Returns(true);
|
||||
|
||||
var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object);
|
||||
Assert.AreEqual(RenderingEngine.Mvc, res);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DetermineTemplateRenderingEngine_Returns_WebForms_When_ViewFile_Doesnt_Exist_And_Content_Has_Webform_Markup()
|
||||
{
|
||||
// Project in MVC mode
|
||||
_templateConfigMock.Setup(x => x.DefaultRenderingEngine).Returns(RenderingEngine.Mvc);
|
||||
|
||||
// Template has masterpage content
|
||||
var templateMock = new Mock<ITemplate>();
|
||||
templateMock.Setup(x => x.Alias).Returns("Something");
|
||||
templateMock.Setup(x => x.Content).Returns("<asp:Content />");
|
||||
|
||||
// MVC View doesn't exist
|
||||
_viewFileSystemMock.Setup(x => x.FileExists(It.IsAny<string>())).Returns(false);
|
||||
|
||||
var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object);
|
||||
Assert.AreEqual(RenderingEngine.WebForms, res);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DetermineTemplateRenderingEngine_Returns_WebForms_When_MasterPage_Exists_And_In_Mvc_Mode()
|
||||
{
|
||||
// Project in MVC mode
|
||||
_templateConfigMock.Setup(x => x.DefaultRenderingEngine).Returns(RenderingEngine.Mvc);
|
||||
|
||||
var templateMock = new Mock<ITemplate>();
|
||||
templateMock.Setup(x => x.Alias).Returns("Something");
|
||||
|
||||
// but masterpage already exists
|
||||
_viewFileSystemMock.Setup(x => x.FileExists(It.IsAny<string>())).Returns(false);
|
||||
_masterpageFileSystemMock.Setup(x => x.FileExists(It.IsAny<string>())).Returns(true);
|
||||
|
||||
var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object);
|
||||
Assert.AreEqual(RenderingEngine.WebForms, res);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DetermineTemplateRenderingEngine_Returns_Mvc_When_ViewPage_Exists_And_In_Webforms_Mode()
|
||||
{
|
||||
// Project in WebForms mode
|
||||
_templateConfigMock.Setup(x => x.DefaultRenderingEngine).Returns(RenderingEngine.WebForms);
|
||||
|
||||
var templateMock = new Mock<ITemplate>();
|
||||
templateMock.Setup(x => x.Alias).Returns("Something");
|
||||
|
||||
// but MVC View already exists
|
||||
_viewFileSystemMock.Setup(x => x.FileExists(It.IsAny<string>())).Returns(true);
|
||||
_masterpageFileSystemMock.Setup(x => x.FileExists(It.IsAny<string>())).Returns(false);
|
||||
|
||||
var res = _templateRepository.DetermineTemplateRenderingEngine(templateMock.Object);
|
||||
Assert.AreEqual(RenderingEngine.Mvc, res);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using System.Web;
|
||||
using System.Web.Routing;
|
||||
using Moq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Tests.TestHelpers
|
||||
{
|
||||
@@ -60,7 +61,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
|
||||
//Cookie collection
|
||||
var cookieCollection = new HttpCookieCollection();
|
||||
cookieCollection.Add(new HttpCookie(Constants.Web.AuthCookieName, "FBA996E7-D6BE-489B-B199-2B0F3D2DD826"));
|
||||
cookieCollection.Add(new HttpCookie("UMB_UCONTEXT", "FBA996E7-D6BE-489B-B199-2B0F3D2DD826"));
|
||||
|
||||
//Request
|
||||
var requestMock = new Mock<HttpRequestBase>();
|
||||
|
||||
@@ -180,6 +180,7 @@
|
||||
<Compile Include="Logging\AsyncRollingFileAppenderTest.cs" />
|
||||
<Compile Include="Logging\DebugAppender.cs" />
|
||||
<Compile Include="Logging\ParallelForwarderTest.cs" />
|
||||
<Compile Include="Mvc\RenderIndexActionSelectorAttributeTests.cs" />
|
||||
<Compile Include="Persistence\Repositories\AuditRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\DomainRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\PartialViewRepositoryTests.cs" />
|
||||
@@ -361,6 +362,7 @@
|
||||
<Compile Include="Services\MacroServiceTests.cs" />
|
||||
<Compile Include="Services\UserServiceTests.cs" />
|
||||
<Compile Include="Manifest\ManifestParserTests.cs" />
|
||||
<Compile Include="Templates\TemplateRepositoryTests.cs" />
|
||||
<Compile Include="TestHelpers\BaseSeleniumTest.cs" />
|
||||
<Compile Include="Integration\InstallPackage.cs" />
|
||||
<Compile Include="CoreXml\NavigableNavigatorTests.cs" />
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"jquery": "2.0.3",
|
||||
"jquery-file-upload": "~9.4.0",
|
||||
"jquery-ui": "1.10.3",
|
||||
"angular-dynamic-locale": "~0.1.27",
|
||||
"angular-dynamic-locale": "0.1.27",
|
||||
"tinymce": "~4.1.10",
|
||||
"codemirror": "~5.3.0"
|
||||
}
|
||||
|
||||
@@ -1 +1,17 @@
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url('../fonts/opensans/OpenSans-Regular-webfont.eot');
|
||||
src: local('Open Sans'), local('OpenSans'), url('../fonts/opensans/OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'), url('../fonts/opensans/OpenSans-Regular-webfont.ttf') format('truetype'), url('../fonts/opensans/OpenSans-Regular-webfont.svg#open_sansregular') format('svg');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: url('../fonts/opensans/OpenSans-Semibold-webfont.eot');
|
||||
src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url('../fonts/opensans/OpenSans-Semibold-webfont.eot?#iefix') format('embedded-opentype'), url('../fonts/opensans/OpenSans-Semibold-webfont.ttf') format('truetype'), url('../fonts/opensans/OpenSans-Semibold-webfont.svg#open_sanssemibold') format('svg');
|
||||
}
|
||||
|
||||
abbr,address,article,aside,audio,b,blockquote,body,canvas,caption,cite,code,dd,del,details,dfn,div,dl,dt,em,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,p,pre,q,samp,section,small,span,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,ul,var,video{margin:0;padding:0;outline:0;border:0;background:0 0;vertical-align:baseline;font-size:100%}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}nav ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:'';content:none}a{margin:0;padding:0;background:0 0;vertical-align:baseline;font-size:100%}ins{background-color:#ff9;color:#000;text-decoration:none}mark{background-color:#ff9;color:#000;font-weight:700;font-style:italic}del{text-decoration:line-through}abbr[title],dfn[title]{border-bottom:1px dotted;cursor:help}table{border-spacing:0;border-collapse:collapse}hr{display:block;margin:1em 0;padding:0;height:1px;border:0;border-top:1px solid #ccc}input,select{vertical-align:middle}html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,:after,:before{box-sizing:border-box}body,html{height:100%;width:100%;color:#fff;font-family:'Open Sans',sans-serif;font-weight:400;font-size:.9375em;line-height:1.5}h1{font-size:1.7em;margin:40px auto 10px;font-weight:700}h2{font-size:1.35em;margin:0 auto .4em;font-weight:700}h3{font-size:1em;font-weight:400;font-style:italic}p{font-size:1em;line-height:1.6}p+a{margin-top:1rem;display:inline-block}a,a:active,a:visited{text-decoration:none}.cta{margin:4.5em auto 1.5em;padding-bottom:4.5em}.button,.button:visited{padding:.9375em 1.875em;border-radius:.1em;font-weight:600;font-size:1.2em;background:#2e99f4;color:#fff;display:inline-block;border:none;transition:all 200ms ease-in-out}.button:hover,.button:visited:hover{border-bottom:none;background:#0c80e3}section{background:url(../img/nonodesbg.jpg) center center/cover;height:100%;width:100%;display:table;padding:3em 1.75em}section a,section a:focus,section a:visited{color:#46a5f5;font-size:1.1625em;border-bottom:1px solid transparent;transition:border-bottom 100ms ease-in-out}section a:focus:hover,section a:hover,section a:visited:hover{border-bottom:1px solid}section:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.17);background:linear-gradient(45deg,rgba(85,98,112,.1) 10%,rgba(255,107,107,.1) 95%);z-index:0}section article{display:table-cell;vertical-align:middle;margin:0 auto;text-align:center;position:relative;z-index:100}section article>div{max-width:60em;margin:0 auto}section .logo{background:url(../img/logo.png) no-repeat;width:91px;height:91px;margin:0 auto}section .row{overflow:hidden}section .row .col{text-align:left;width:100%}section .row .col:nth-child(2){margin-top:3em}@media screen and (min-width:48em){body,html{font-size:1em}h1{font-size:2.5em;margin:70px auto 0;letter-spacing:.5px}h2{font-size:1.4375em;margin:0 auto 1em}h3{font-size:1.2em}a{font-size:1.1rem;font-weight:600}p+a{margin-top:3rem}.cta{margin:7.5em auto 2.5em;border-bottom:1px solid rgba(255,255,255,.5);padding-bottom:7.5em}section{padding:0 15px}section .row .col{float:left;width:50%;padding-right:5%;display:inline-block}section .row .col:nth-child(2){padding-right:0;padding-left:5%;margin-top:0}.button{font-size:1.1625em}}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 367 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
@@ -1,16 +1,17 @@
|
||||
LazyLoad.js([
|
||||
'/Umbraco/lib/jquery/jquery.min.js',
|
||||
'/Umbraco/lib/jquery-ui/jquery-ui.min.js',
|
||||
'/Umbraco/lib/angular/1.1.5/angular.min.js',
|
||||
'/Umbraco/lib/underscore/underscore-min.js',
|
||||
'/Umbraco/js/app.js',
|
||||
'/Umbraco/js/umbraco.resources.js',
|
||||
'/Umbraco/js/umbraco.services.js',
|
||||
'/Umbraco/js/umbraco.security.js',
|
||||
'/Umbraco/ServerVariables',
|
||||
'/Umbraco/lib/spectrum/spectrum.js',
|
||||
'https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js',
|
||||
'/umbraco/js/canvasdesigner.panel.js',
|
||||
'../lib/jquery/jquery.min.js',
|
||||
'../lib/jquery-ui/jquery-ui.min.js',
|
||||
'../lib/angular/1.1.5/angular.min.js',
|
||||
'../lib/underscore/underscore-min.js',
|
||||
'../lib/umbraco/Extensions.js',
|
||||
'../js/app.js',
|
||||
'../js/umbraco.resources.js',
|
||||
'../js/umbraco.services.js',
|
||||
'../js/umbraco.security.js',
|
||||
'../ServerVariables',
|
||||
'../lib/spectrum/spectrum.js',
|
||||
|
||||
'../js/canvasdesigner.panel.js',
|
||||
], function () {
|
||||
jQuery(document).ready(function () {
|
||||
angular.bootstrap(document, ['Umbraco.canvasdesigner']);
|
||||
|
||||
@@ -24,7 +24,7 @@ var app = angular.module("Umbraco.canvasdesigner", ['colorpicker', 'ui.slider',
|
||||
];
|
||||
$scope.previewDevice = $scope.devices[0];
|
||||
|
||||
var apiController = "/Umbraco/Api/Canvasdesigner/";
|
||||
var apiController = "../Api/Canvasdesigner/";
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Preview devices */
|
||||
@@ -40,7 +40,7 @@ var app = angular.module("Umbraco.canvasdesigner", ['colorpicker', 'ui.slider',
|
||||
/*****************************************************************************/
|
||||
|
||||
$scope.exitPreview = function () {
|
||||
window.top.location.href = "/umbraco/endPreview.aspx?redir=%2f" + $scope.pageId;
|
||||
window.top.location.href = "../endPreview.aspx?redir=%2f" + $scope.pageId;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -9,11 +9,6 @@ var canvasdesignerConfig = {
|
||||
schema: "body",
|
||||
selector: "body",
|
||||
editors: [
|
||||
{
|
||||
type: "wide",
|
||||
category: "Dimension",
|
||||
name: "Layout"
|
||||
},
|
||||
{
|
||||
type: "background",
|
||||
category: "Color",
|
||||
|
||||
@@ -104,6 +104,30 @@ angular.module("Umbraco.canvasdesigner")
|
||||
}
|
||||
};
|
||||
|
||||
function loadFont(font, variant) {
|
||||
WebFont.load({
|
||||
google: {
|
||||
families: [font.fontFamily + ":" + variant]
|
||||
},
|
||||
loading: function () {
|
||||
console.log('loading');
|
||||
},
|
||||
active: function () {
|
||||
$scope.selectedFont = font;
|
||||
$scope.selectedFont.fontWeight = googleGetWeight(variant);
|
||||
$scope.selectedFont.fontStyle = googleGetStyle(variant);
|
||||
// If $apply isn't called, the new font family isn't applied until the next user click.
|
||||
$scope.change({
|
||||
fontFamily: $scope.selectedFont.fontFamily,
|
||||
fontType: $scope.selectedFont.fontType,
|
||||
fontWeight: $scope.selectedFont.fontWeight,
|
||||
fontStyle: $scope.selectedFont.fontStyle,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var webFontScriptLoaded = false;
|
||||
$scope.showFontPreview = function (font, variant) {
|
||||
|
||||
if (!variant)
|
||||
@@ -114,27 +138,19 @@ angular.module("Umbraco.canvasdesigner")
|
||||
// Font needs to be independently loaded in the iframe for live preview to work.
|
||||
document.getElementById("resultFrame").contentWindow.getFont(font.fontFamily + ":" + variant);
|
||||
|
||||
WebFont.load({
|
||||
google: {
|
||||
families: [font.fontFamily + ":" + variant]
|
||||
},
|
||||
loading: function () {
|
||||
console.log('loading');
|
||||
},
|
||||
active: function () {
|
||||
$scope.selectedFont = font;
|
||||
$scope.selectedFont.fontWeight = googleGetWeight(variant);
|
||||
$scope.selectedFont.fontStyle = googleGetStyle(variant);
|
||||
// If $apply isn't called, the new font family isn't applied until the next user click.
|
||||
$scope.change({
|
||||
fontFamily: $scope.selectedFont.fontFamily,
|
||||
fontType: $scope.selectedFont.fontType,
|
||||
fontWeight: $scope.selectedFont.fontWeight,
|
||||
fontStyle: $scope.selectedFont.fontStyle,
|
||||
if (!webFontScriptLoaded) {
|
||||
$.getScript('https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js')
|
||||
.done(function() {
|
||||
webFontScriptLoaded = true;
|
||||
loadFont(font, variant);
|
||||
})
|
||||
.fail(function() {
|
||||
console.log('error loading webfont');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
loadFont(font, variant);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Umbraco Canvas Designer</title>
|
||||
<link href="/Umbraco/assets/css/canvasdesigner.css" type="text/css" rel="stylesheet" />
|
||||
<link href="/Umbraco/lib/spectrum/spectrum.css" type="text/css" rel="stylesheet" />
|
||||
<link href="/Umbraco/lib/jquery-ui/jquery-ui-1.10.4.custom.min.css" type="text/css" rel="stylesheet" />
|
||||
<link href="../assets/css/canvasdesigner.css" type="text/css" rel="stylesheet" />
|
||||
<link href="../lib/spectrum/spectrum.css" type="text/css" rel="stylesheet" />
|
||||
<link href="../lib/jquery-ui/jquery-ui-1.10.4.custom.min.css" type="text/css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body id="canvasdesignerPanel" ng-mouseover="outlinePositionHide()" ng-class="{ leftOpen: (showStyleEditor || showPalettePicker) && !showDevicesPreview }" ng-controller="Umbraco.canvasdesignerController">
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="fix-left-menu selected">
|
||||
|
||||
<div class="avatar">
|
||||
<img ng-src="/umbraco/assets/img/application/logo.png">
|
||||
<img ng-src="../assets/img/application/logo.png">
|
||||
</div>
|
||||
|
||||
<ul class="sections" ng-class="{selected: showDevicesPreview}">
|
||||
@@ -125,7 +125,7 @@
|
||||
<div class="canvasdesigner-panel-container" ng-show="categoriesVisibility[category] === true">
|
||||
<div class="canvasdesigner-panel-property" ng-repeat="item in configItem.editors" ng-show="item.category == category">
|
||||
<h5>{{item.name}} <i class="icon icon-help-alt"></i></h5>
|
||||
<div ng-include="'/Umbraco/preview/editors/' + item.type + '.html'"></div>
|
||||
<div ng-include="'../preview/editors/' + item.type + '.html'"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -154,8 +154,8 @@
|
||||
<p>Styles saved and published</p>
|
||||
</div>
|
||||
|
||||
<script src="/umbraco/lib/rgrove-lazyload/lazyload.js"></script>
|
||||
<script src="/umbraco/js/canvasdesigner.loader.js"></script>
|
||||
<script src="../lib/rgrove-lazyload/lazyload.js"></script>
|
||||
<script src="../js/canvasdesigner.loader.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ angular.module("umbraco.directives")
|
||||
if(scope.configuration && scope.configuration.stylesheets){
|
||||
angular.forEach(scope.configuration.stylesheets, function(stylesheet, key){
|
||||
|
||||
stylesheets.push("/css/" + stylesheet + ".css");
|
||||
stylesheets.push(Umbraco.Sys.ServerVariables.umbracoSettings.cssPath + "/" + stylesheet + ".css");
|
||||
await.push(stylesheetResource.getRulesByName(stylesheet).then(function (rules) {
|
||||
angular.forEach(rules, function (rule) {
|
||||
var r = {};
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbAvatar
|
||||
* @restrict E
|
||||
**/
|
||||
function avatarDirective() {
|
||||
return {
|
||||
restrict: "E", // restrict to an element
|
||||
replace: true, // replace the html element with the template
|
||||
templateUrl: 'views/directives/umb-avatar.html',
|
||||
scope: {
|
||||
name: '@',
|
||||
email: '@',
|
||||
hash: '@'
|
||||
},
|
||||
link: function(scope, element, attr, ctrl) {
|
||||
|
||||
scope.$watch("hash", function (val) {
|
||||
//set the gravatar url
|
||||
scope.gravatar = "https://www.gravatar.com/avatar/" + val + "?s=40";
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive("umbAvatar", avatarDirective);
|
||||
@@ -13,14 +13,16 @@ angular.module("umbraco.directives")
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/directives/umb-property.html',
|
||||
|
||||
link: function(scope) {
|
||||
scope.propertyAlias = Umbraco.Sys.ServerVariables.isDebuggingEnabled === true ? scope.property.alias : null;
|
||||
},
|
||||
//Define a controller for this directive to expose APIs to other directives
|
||||
controller: function ($scope, $timeout) {
|
||||
|
||||
var self = this;
|
||||
|
||||
//set the API properties/methods
|
||||
|
||||
|
||||
self.property = $scope.property;
|
||||
self.setPropertyError = function(errorMsg) {
|
||||
$scope.property.propertyErrorMessage = errorMsg;
|
||||
|
||||
@@ -94,14 +94,24 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se
|
||||
navigationService.showHelpDialog();
|
||||
};
|
||||
|
||||
scope.sectionClick = function (section) {
|
||||
scope.sectionClick = function (event, section) {
|
||||
|
||||
if (event.ctrlKey ||
|
||||
event.shiftKey ||
|
||||
event.metaKey || // apple
|
||||
(event.button && event.button === 1) // middle click, >IE9 + everyone else
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (navigationService.userDialog) {
|
||||
navigationService.userDialog.close();
|
||||
}
|
||||
if (navigationService.helpDialog) {
|
||||
navigationService.helpDialog.close();
|
||||
}
|
||||
|
||||
|
||||
navigationService.hideSearch();
|
||||
navigationService.showTree(section.alias);
|
||||
$location.path("/" + section.alias);
|
||||
|
||||
@@ -38,9 +38,9 @@ angular.module("umbraco.directives")
|
||||
'<div ng-class="getNodeCssClass(node)" ng-swipe-right="options(node, $event)" >' +
|
||||
//NOTE: This ins element is used to display the search icon if the node is a container/listview and the tree is currently in dialog
|
||||
//'<ins ng-if="tree.enablelistviewsearch && node.metaData.isContainer" class="umb-tree-node-search icon-search" ng-click="searchNode(node, $event)" alt="searchAltText"></ins>' +
|
||||
'<ins ng-class="{\'icon-navigation-right\': !node.expanded, \'icon-navigation-down\': node.expanded}" ng-click="load(node)"></ins>' +
|
||||
'<i class="icon umb-tree-icon sprTree"></i>' +
|
||||
'<a ng-click="select(node, $event)"></a>' +
|
||||
'<ins ng-class="{\'icon-navigation-right\': !node.expanded, \'icon-navigation-down\': node.expanded}" ng-click="load(node)"> </ins>' +
|
||||
'<i class="icon umb-tree-icon sprTree" ng-click="select(node, $event)"></i>' +
|
||||
'<a href="#/{{node.routePath}}" ng-click="select(node, $event)"></a>' +
|
||||
//NOTE: These are the 'option' elipses
|
||||
'<a class="umb-options" ng-click="options(node, $event)"><i></i><i></i><i></i></a>' +
|
||||
'<div ng-show="node.loading" class="l"><div></div></div>' +
|
||||
@@ -148,8 +148,17 @@ angular.module("umbraco.directives")
|
||||
and emits it as a treeNodeSelect element if there is a callback object
|
||||
defined on the tree
|
||||
*/
|
||||
scope.select = function(n, ev) {
|
||||
scope.select = function (n, ev) {
|
||||
if (ev.ctrlKey ||
|
||||
ev.shiftKey ||
|
||||
ev.metaKey || // apple
|
||||
(ev.button && ev.button === 1) // middle click, >IE9 + everyone else
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
emitEvent("treeNodeSelect", { element: element, tree: scope.tree, node: n, event: ev });
|
||||
ev.preventDefault();
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @description Utillity directives for key and field events
|
||||
* @description Utility directives for key and field events
|
||||
**/
|
||||
angular.module('umbraco.directives')
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@ angular.module("umbraco.directives").directive('focusWhen', function ($timeout)
|
||||
link: function (scope, elm, attrs, ctrl) {
|
||||
attrs.$observe("focusWhen", function (newValue) {
|
||||
if (newValue === "true") {
|
||||
elm.focus();
|
||||
$timeout(function() {
|
||||
elm.focus();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -139,6 +139,12 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
_.each(ids, function(item) {
|
||||
query += "ids=" + item + "&";
|
||||
});
|
||||
|
||||
// if ids array is empty we need a empty variable in the querystring otherwise the service returns a error
|
||||
if (ids.length === 0) {
|
||||
query += "ids=&";
|
||||
}
|
||||
|
||||
query += "type=" + type;
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
|
||||
@@ -36,7 +36,7 @@ function macroResource($q, $http, umbRequestHelper) {
|
||||
* @methodOf umbraco.resources.macroResource
|
||||
*
|
||||
* @description
|
||||
* Gets the result of a macro as html to display in the rich text editor
|
||||
* Gets the result of a macro as html to display in the rich text editor or in the Grid
|
||||
*
|
||||
* @param {int} macroId The macro id to get parameters for
|
||||
* @param {int} pageId The current page id
|
||||
@@ -45,39 +45,17 @@ function macroResource($q, $http, umbRequestHelper) {
|
||||
*/
|
||||
getMacroResultAsHtmlForEditor: function (macroAlias, pageId, macroParamDictionary) {
|
||||
|
||||
//need to format the query string for the custom dictionary
|
||||
var query = "macroAlias=" + macroAlias + "&pageId=" + pageId;
|
||||
if (macroParamDictionary) {
|
||||
var counter = 0;
|
||||
_.each(macroParamDictionary, function (val, key) {
|
||||
//check for null
|
||||
val = val ? val : "";
|
||||
//need to detect if the val is a string or an object
|
||||
if (!angular.isString(val)) {
|
||||
//if it's not a string we'll send it through the json serializer
|
||||
var json = angular.toJson(val);
|
||||
//then we need to url encode it so that it's safe
|
||||
val = encodeURIComponent(json);
|
||||
}
|
||||
else {
|
||||
//we still need to encode the string, it could contain line breaks, etc...
|
||||
val = encodeURIComponent(val);
|
||||
}
|
||||
|
||||
query += "¯oParams[" + counter + "].key=" + key + "¯oParams[" + counter + "].value=" + val;
|
||||
counter++;
|
||||
});
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"macroApiBaseUrl",
|
||||
"GetMacroResultAsHtmlForEditor",
|
||||
query)),
|
||||
'Failed to retrieve macro result for macro with alias ' + macroAlias);
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"macroApiBaseUrl",
|
||||
"GetMacroResultAsHtmlForEditor"), {
|
||||
macroAlias: macroAlias,
|
||||
pageId: pageId,
|
||||
macroParams: macroParamDictionary
|
||||
}),
|
||||
'Failed to retrieve macro result for macro with alias ' + macroAlias);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue'])
|
||||
// This http interceptor listens for authentication successes and failures
|
||||
.factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', function ($injector, queue, notifications) {
|
||||
.factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', 'requestInterceptorFilter', function ($injector, queue, notifications, requestInterceptorFilter) {
|
||||
return function(promise) {
|
||||
|
||||
return promise.then(
|
||||
@@ -19,6 +19,19 @@ angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue'])
|
||||
return promise;
|
||||
}, function(originalResponse) {
|
||||
// Intercept failed requests
|
||||
|
||||
//Here we'll check if we should ignore the error, this will be based on an original header set
|
||||
var headers = originalResponse.config ? originalResponse.config.headers : {};
|
||||
if (headers["x-umb-ignore-error"] === "ignore") {
|
||||
//exit/ignore
|
||||
return promise;
|
||||
}
|
||||
var filtered = _.find(requestInterceptorFilter(), function(val) {
|
||||
return originalResponse.config.url.indexOf(val) > 0;
|
||||
});
|
||||
if (filtered) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
//A 401 means that the user is not logged in
|
||||
if (originalResponse.status === 401) {
|
||||
@@ -72,6 +85,10 @@ angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue'])
|
||||
};
|
||||
}])
|
||||
|
||||
.value('requestInterceptorFilter', function() {
|
||||
return ["www.gravatar.com"];
|
||||
})
|
||||
|
||||
// We have to add the interceptor to the queue as a string because the interceptor depends upon service instances that are not available in the config block.
|
||||
.config(['$httpProvider', function ($httpProvider) {
|
||||
$httpProvider.responseInterceptors.push('securityInterceptor');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
angular.module('umbraco.services')
|
||||
.factory('userService', function ($rootScope, eventsService, $q, $location, $log, securityRetryQueue, authResource, dialogService, $timeout, angularHelper) {
|
||||
.factory('userService', function ($rootScope, eventsService, $q, $location, $log, securityRetryQueue, authResource, dialogService, $timeout, angularHelper, $http) {
|
||||
|
||||
var currentUser = null;
|
||||
var lastUserId = null;
|
||||
@@ -250,7 +250,7 @@ angular.module('umbraco.services')
|
||||
}
|
||||
|
||||
setCurrentUser(data);
|
||||
currentUser.avatar = 'https://www.gravatar.com/avatar/' + data.emailHash + '?s=40&d=404';
|
||||
|
||||
deferred.resolve(currentUser);
|
||||
});
|
||||
|
||||
|
||||
@@ -372,9 +372,6 @@ function xmlhelper($http) {
|
||||
fromJson: function (json) {
|
||||
var xml = x2js.json2xml_str(json);
|
||||
return xml;
|
||||
},
|
||||
parseFeed: function (url) {
|
||||
return $http.jsonp('//ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=50&callback=JSON_CALLBACK&q=' + encodeURIComponent(url));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,7 +13,11 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $
|
||||
//the null is important because we do an explicit bool check on this in the view
|
||||
//the avatar is by default the umbraco logo
|
||||
$scope.authenticated = null;
|
||||
$scope.avatar = "assets/img/application/logo.png";
|
||||
$scope.avatar = [
|
||||
{ value: "assets/img/application/logo.png" },
|
||||
{ value: "assets/img/application/logo@2x.png" },
|
||||
{ value: "assets/img/application/logo@3x.png" }
|
||||
];
|
||||
$scope.touchDevice = appState.getGlobalState("touchDevice");
|
||||
|
||||
|
||||
@@ -84,20 +88,32 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $
|
||||
tmhDynamicLocale.set($scope.user.locale);
|
||||
}
|
||||
|
||||
if($scope.user.emailHash){
|
||||
$timeout(function () {
|
||||
//yes this is wrong..
|
||||
$("#avatar-img").fadeTo(1000, 0, function () {
|
||||
$timeout(function () {
|
||||
//this can be null if they time out
|
||||
if ($scope.user && $scope.user.emailHash) {
|
||||
$scope.avatar = "https://www.gravatar.com/avatar/" + $scope.user.emailHash + ".jpg?s=64&d=mm";
|
||||
}
|
||||
if ($scope.user.emailHash) {
|
||||
|
||||
//let's attempt to load the avatar, it might not exist or we might not have
|
||||
// internet access so we'll detect it first
|
||||
$http.get("https://www.gravatar.com/avatar/" + $scope.user.emailHash + ".jpg?s=64&d=404")
|
||||
.then(
|
||||
function successCallback(response) {
|
||||
$("#avatar-img").fadeTo(1000, 0, function () {
|
||||
$scope.$apply(function () {
|
||||
//this can be null if they time out
|
||||
if ($scope.user && $scope.user.emailHash) {
|
||||
var avatarBaseUrl = "https://www.gravatar.com/avatar/",
|
||||
hash = $scope.user.emailHash;
|
||||
|
||||
$scope.avatar = [
|
||||
{ value: avatarBaseUrl + hash + ".jpg?s=30&d=mm" },
|
||||
{ value: avatarBaseUrl + hash + ".jpg?s=60&d=mm" },
|
||||
{ value: avatarBaseUrl + hash + ".jpg?s=90&d=mm" }
|
||||
];
|
||||
}
|
||||
});
|
||||
$("#avatar-img").fadeTo(1000, 1);
|
||||
});
|
||||
}, function errorCallback(response) {
|
||||
//cannot load it from the server so we cannot do anything
|
||||
});
|
||||
$("#avatar-img").fadeTo(1000, 1);
|
||||
});
|
||||
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
@@ -17,9 +17,9 @@ angular.module("umbraco.install").factory('installerService', function($rootScop
|
||||
|
||||
//add to umbraco installer facts here
|
||||
var facts = ['Umbraco helped millions of people watch a man jump from the edge of space',
|
||||
'Over 250.000 websites are currently powered by Umbraco',
|
||||
'Over 300 000 websites are currently powered by Umbraco',
|
||||
"At least 2 people have named their cat 'Umbraco'",
|
||||
'On an average day, more than 1.000 people download Umbraco',
|
||||
'On an average day, more than 1000 people download Umbraco',
|
||||
'<a target="_blank" href="http://umbraco.tv">umbraco.tv</a> is the premier source of Umbraco video tutorials to get you started',
|
||||
'You can find the world\'s friendliest CMS community at <a target="_blank" href="http://our.umbraco.org">our.umbraco.org</a>',
|
||||
'You can become a certified Umbraco developer by attending one of the official courses',
|
||||
@@ -31,7 +31,7 @@ angular.module("umbraco.install").factory('installerService', function($rootScop
|
||||
"At least 4 people have the Umbraco logo tattooed on them",
|
||||
"'Umbraco' is the danish name for an allen key",
|
||||
"Umbraco has been around since 2005, that's a looong time in IT",
|
||||
"More than 400 people from all over the world meet each year in Denmark in June for our annual conference <a target='_blank' href='http://codegarden14.com'>CodeGarden</a>",
|
||||
"More than 400 people from all over the world meet each year in Denmark in June for our annual conference <a target='_blank' href='http://codegarden15.com'>CodeGarden</a>",
|
||||
"While you are installing Umbraco someone else on the other side of the planet is probably doing it too",
|
||||
"You can extend Umbraco without modifying the source code and using either JavaScript or C#"
|
||||
];
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="server">Server</label>
|
||||
<div class="controls">
|
||||
<input type="text" name="server" placeholder="127.0.0.1/SQLEXPRESS" required ng-model="installer.current.model.server" />
|
||||
<input type="text" name="server" placeholder="127.0.0.1\SQLEXPRESS" required ng-model="installer.current.model.server" />
|
||||
<small class="inline-help">Enter server domain or IP</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
/******* font-face *******/
|
||||
|
||||
@font-face {
|
||||
src: url('/Umbraco/assets/fonts/helveticons/helveticons.eot') !important;
|
||||
src: url('/Umbraco/assets/fonts/helveticons/helveticons.eot?#iefix') format('embedded-opentype'), url('/Umbraco/assets/fonts/helveticons/helveticons.ttf') format('truetype'), url('/Umbraco/assets/fonts/helveticons/helveticons.svg#icomoon') format('svg') !important;
|
||||
src: url('assets/fonts/helveticons/helveticons.eot') !important;
|
||||
src: url('assets/fonts/helveticons/helveticons.eot?#iefix') format('embedded-opentype'), url('assets/fonts/helveticons/helveticons.ttf') format('truetype'), url('assets/fonts/helveticons/helveticons.svg#icomoon') format('svg') !important;
|
||||
}
|
||||
|
||||
/****************************/
|
||||
|
||||
@@ -155,7 +155,7 @@ body {
|
||||
}
|
||||
|
||||
#speechbubble {
|
||||
z-index: 1000;
|
||||
z-index: 1060;
|
||||
position: absolute;
|
||||
bottom: 100px;
|
||||
left: 0;
|
||||
@@ -266,4 +266,4 @@ body {
|
||||
margin-left: 40px;
|
||||
width: 85%!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
background-size: 30px 30px !important;
|
||||
color: @white;
|
||||
position: absolute;
|
||||
z-index: 2000;
|
||||
z-index: 10000;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
margin: 0 !Important;
|
||||
|
||||
@@ -133,7 +133,7 @@ h5{
|
||||
.umb-control-group label.control-label {
|
||||
text-align: left
|
||||
}
|
||||
.umb-control-group label .help-block,
|
||||
.umb-control-group label .help-block,
|
||||
.umb-control-group label small {
|
||||
font-size: 11px;
|
||||
color: #a0a0a0;
|
||||
@@ -148,6 +148,11 @@ h5{
|
||||
padding-top: 5px;
|
||||
margin-left: 240px;
|
||||
}
|
||||
|
||||
.umb-user-panel .controls-row {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.controls-row label {
|
||||
display: inline-block
|
||||
}
|
||||
@@ -189,7 +194,7 @@ h5{
|
||||
|
||||
.umb-dashboard-control a{text-decoration: underline;}
|
||||
|
||||
.umb-dashboard-control
|
||||
.umb-dashboard-control
|
||||
iframe{ position: absolute; display: block; width: 99%; height: 99%; overflow: auto !important;}
|
||||
|
||||
|
||||
@@ -234,16 +239,16 @@ table thead a {
|
||||
|
||||
.umb-table tbody.ui-sortable tr.ui-sortable-helper {
|
||||
background-color: @sortableHelperBg;
|
||||
border: none;
|
||||
border: none;
|
||||
}
|
||||
.umb-table tbody.ui-sortable tr.ui-sortable-helper td
|
||||
.umb-table tbody.ui-sortable tr.ui-sortable-helper td
|
||||
{
|
||||
border:none;
|
||||
}
|
||||
|
||||
.umb-table tbody.ui-sortable tr.ui-sortable-placeholder {
|
||||
background-color: @sortablePlaceholderBg;
|
||||
border:none;
|
||||
border:none;
|
||||
}
|
||||
|
||||
.umb-table tbody.ui-sortable tr.ui-sortable-placeholder td
|
||||
@@ -363,7 +368,7 @@ table thead a {
|
||||
background: @inputBorder;
|
||||
height: 1px;
|
||||
margin: 20px 0 0 0;
|
||||
width: 82%;
|
||||
width: 82%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
@@ -432,7 +437,7 @@ table thead a {
|
||||
color:@green;
|
||||
}
|
||||
|
||||
// Loading Animation
|
||||
// Loading Animation
|
||||
// ------------------------
|
||||
|
||||
.umb-loader{
|
||||
@@ -518,11 +523,67 @@ height:1px;
|
||||
}
|
||||
|
||||
.umb-loader-wrapper {
|
||||
|
||||
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
margin: 10px 0;
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Helpers
|
||||
|
||||
.strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
|
||||
// Input label styles
|
||||
// @Simon: not sure where to put this part yet
|
||||
// --- TODO Needs to be divided into the right .less directories
|
||||
|
||||
|
||||
// Titles for input fields
|
||||
.input-label--title {
|
||||
font-weight: bold;
|
||||
color: @black;
|
||||
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
|
||||
// Used for input checkmark fields
|
||||
.input-label--small {
|
||||
display: inline;
|
||||
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: fade(@black, 70);
|
||||
|
||||
&:hover {
|
||||
color: @black;
|
||||
}
|
||||
}
|
||||
|
||||
input[type=checkbox]:checked + .input-label--small {
|
||||
color: @blue;
|
||||
}
|
||||
|
||||
|
||||
// Use this for headers in the panels
|
||||
.panel-dialog--header {
|
||||
border-bottom: 1px solid @gray;
|
||||
|
||||
margin: 10px 0;
|
||||
padding-bottom: 10px;
|
||||
|
||||
font-size: @fontSizeLarge;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user