Compare commits
103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bbe4a87784 | |||
| cbd5c295bd | |||
| 0d29e1438c | |||
| 5a1ace9362 | |||
| da85e4eb28 | |||
| fbc08d66f1 | |||
| 79f04bf939 | |||
| 9ab90595e2 | |||
| 51b618826c | |||
| 04c28e5006 | |||
| c160ce98c1 | |||
| c3a60ea0e0 | |||
| 3408efdee4 | |||
| 1f0dc7e65d | |||
| f89083c772 | |||
| 752065e540 | |||
| 82e4e50584 | |||
| 775e63148d | |||
| 4259b02b8d | |||
| 0c402310d9 | |||
| 8d92330ad6 | |||
| 44e76f741f | |||
| ecbced5c62 | |||
| e6773dafc1 | |||
| 7b8b7ed170 | |||
| c0997e1b9f | |||
| d4f862a44f | |||
| 64c983eb07 | |||
| e25222162c | |||
| e022687457 | |||
| 84db2f4d85 | |||
| ef64409a9a | |||
| f0b68ac31e | |||
| 6c80bd9eb9 | |||
| c7b7bf1510 | |||
| d1805b1448 | |||
| 780937dae9 | |||
| 9b054eaa47 | |||
| badd9ae289 | |||
| db6755a5bb | |||
| 738815170c | |||
| ef091e8c3a | |||
| 71b3810e9c | |||
| a1e62dae5e | |||
| 96c087d00f | |||
| 0568bf51f0 | |||
| e3bade4d1a | |||
| 633b0b0003 | |||
| 82adf48699 | |||
| 63be12b9fe | |||
| 33f7ed5129 | |||
| 79583c571c | |||
| a7e2c0b4dc | |||
| da48e1b392 | |||
| f535ece685 | |||
| 04e46c7cd1 | |||
| 1089aef00a | |||
| 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 |
@@ -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 ##
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -72,7 +72,7 @@
|
||||
<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="Insert">
|
||||
<providers xdt:Transform="Insert">
|
||||
<remove name="MySqlSiteMapProvider" xdt:Transform="Insert" />
|
||||
</providers>
|
||||
</siteMap>
|
||||
<httpRuntime xdt:Transform="InsertIfMissing" />
|
||||
<httpRuntime targetFramework="4.5" xdt:Transform="SetAttributes(targetFramework)" />
|
||||
<membership defaultProvider="DefaultMembershipProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove" />
|
||||
@@ -172,23 +177,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>
|
||||
|
||||
@@ -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.1
|
||||
+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.1")]
|
||||
[assembly: AssemblyInformationalVersion("7.3.1")]
|
||||
@@ -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.1");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
+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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,12 @@ using System.Text;
|
||||
using System.Configuration;
|
||||
using System.Data.Common;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading;
|
||||
|
||||
namespace Umbraco.Core.Persistence
|
||||
{
|
||||
@@ -1802,8 +1804,53 @@ namespace Umbraco.Core.Persistence
|
||||
return ObjectCache;
|
||||
}
|
||||
|
||||
static readonly ObjectCache ObjectCache = new MemoryCache("NPoco");
|
||||
|
||||
//static readonly ObjectCache ObjectCache = new MemoryCache("NPoco");
|
||||
private static readonly ObjectCache ObjectCache;
|
||||
|
||||
// this should probably happen somewhere else...f
|
||||
private static void FixCurrentCulture()
|
||||
{
|
||||
// get the current culture
|
||||
var currentCulture = CultureInfo.CurrentCulture;
|
||||
|
||||
// at the top of any culture should be the invariant culture - find it
|
||||
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 weird reason, sometimes it is not - and this breaks eg MemoryCache,
|
||||
// because it ends up in PerformanceCounterLib.IsCustomCategory which does:
|
||||
//
|
||||
// CultureInfo culture = CultureInfo.CurrentCulture;
|
||||
// while (culture != CultureInfo.InvariantCulture)
|
||||
// {
|
||||
// library = GetPerformanceCounterLib(machine, culture);
|
||||
// if (library.IsCustomCategory(category))
|
||||
// return true;
|
||||
// culture = culture.Parent;
|
||||
// }
|
||||
//
|
||||
// ie a reference comparisons = enters an endless loop and hangs everything.
|
||||
|
||||
if (ReferenceEquals(invariantCulture, CultureInfo.InvariantCulture))
|
||||
return;
|
||||
|
||||
// so if it is not the same object, replace the culture by the "fixed" version of
|
||||
// itself - this prevents MemoryCache from dying - but it is an ugly workaround and
|
||||
// does not explain why we would have different CultureInfo objects
|
||||
|
||||
var fixedCulture = CultureInfo.GetCultureInfo(currentCulture.Name);
|
||||
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = fixedCulture;
|
||||
}
|
||||
|
||||
static ManagedCache()
|
||||
{
|
||||
FixCurrentCulture();
|
||||
ObjectCache = new MemoryCache("NPoco");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class PocoData
|
||||
|
||||
@@ -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?).
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -445,6 +445,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>();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -435,6 +435,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 +463,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" />
|
||||
|
||||
@@ -1163,6 +1163,36 @@ 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();
|
||||
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");
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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']);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -81,8 +81,8 @@ ul.sections li.avatar a {
|
||||
}
|
||||
|
||||
ul.sections li.avatar a img {
|
||||
border-radius: 16px;
|
||||
width: 30px
|
||||
border-radius: 50%;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.faded ul.sections li {
|
||||
|
||||
@@ -7,6 +7,7 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
|
||||
searchText = value + "...";
|
||||
});
|
||||
|
||||
$scope.recursive = true;
|
||||
$scope.relateToOriginal = false;
|
||||
$scope.dialogTreeEventHandler = $({});
|
||||
$scope.busy = false;
|
||||
@@ -95,7 +96,7 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController",
|
||||
$scope.busy = true;
|
||||
$scope.error = false;
|
||||
|
||||
contentResource.copy({ parentId: $scope.target.id, id: node.id, relateToOriginal: $scope.relateToOriginal })
|
||||
contentResource.copy({ parentId: $scope.target.id, id: node.id, relateToOriginal: $scope.relateToOriginal, recursive: $scope.recursive })
|
||||
.then(function (path) {
|
||||
$scope.error = false;
|
||||
$scope.success = true;
|
||||
|
||||
@@ -56,6 +56,12 @@
|
||||
</umb-control-group>
|
||||
</umb-pane>
|
||||
|
||||
<umb-pane>
|
||||
<umb-control-group label="Include descendants">
|
||||
<input type="checkbox" ng-model="$parent.$parent.recursive" />
|
||||
</umb-control-group>
|
||||
</umb-pane>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<a href="#" title="{{name}}">
|
||||
<img ng-src="{{gravatar}}" />
|
||||
</a>
|
||||
@@ -5,7 +5,7 @@
|
||||
<val-property-msg property="property"></val-property-msg>
|
||||
|
||||
<div class="umb-el-wrap">
|
||||
<label class="control-label" ng-hide="property.hideLabel" for="{{property.alias}}">
|
||||
<label class="control-label" ng-hide="property.hideLabel" for="{{property.alias}}" ng-attr-title="{{propertyAlias}}">
|
||||
{{property.label}}
|
||||
<small ng-bind-html="property.description"></small>
|
||||
</label>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<ul class="sections">
|
||||
<li class="avatar">
|
||||
<a href="#" ng-click="avatarClick()" hotkey="ctrl+shift+u" title="{{user.name}}" prevent-default>
|
||||
<img id="avatar-img" ng-src="{{avatar}}" />
|
||||
<img id="avatar-img" ng-src="{{avatar[0].value}}" ng-srcset="{{avatar[1].value}} 2x, {{avatar[2].value}} 3x" />
|
||||
</a>
|
||||
</li>
|
||||
<li ng-repeat="section in sections | limitTo: maxSections" ng-class="{current: section.alias == currentSection}">
|
||||
|
||||
@@ -1,13 +1,29 @@
|
||||
angular.module('umbraco').controller("Umbraco.PropertyEditors.UrlListController",
|
||||
function($rootScope, $scope, $filter) {
|
||||
|
||||
function formatDisplayValue() {
|
||||
$scope.renderModel = _.map($scope.model.value.split(","), function (item) {
|
||||
return {
|
||||
url: item,
|
||||
urlTarget: ($scope.config && $scope.config.target) ? $scope.config.target : "_blank"
|
||||
};
|
||||
});
|
||||
function formatDisplayValue() {
|
||||
if (angular.isArray($scope.model.value)) {
|
||||
//it's the json value
|
||||
$scope.renderModel = _.map($scope.model.value, function (item) {
|
||||
return {
|
||||
url: item.url,
|
||||
linkText: item.linkText,
|
||||
urlTarget: (item.target) ? item.target : "_blank",
|
||||
icon: (item.icon) ? item.icon : "icon-out"
|
||||
};
|
||||
});
|
||||
}
|
||||
else {
|
||||
//it's the default csv value
|
||||
$scope.renderModel = _.map($scope.model.value.split(","), function (item) {
|
||||
return {
|
||||
url: item,
|
||||
linkText: "",
|
||||
urlTarget: ($scope.config && $scope.config.target) ? $scope.config.target : "_blank",
|
||||
icon: ($scope.config && $scope.config.icon) ? $scope.config.icon : "icon-out"
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$scope.getUrl = function(valueUrl) {
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<div ng-controller="Umbraco.PropertyEditors.UrlListController">
|
||||
<ul class="nav nav-stacked">
|
||||
<li ng-repeat="value in renderModel">
|
||||
<a href="{{getUrl(value.url)}}" prevent-default="{{value.url.indexOf('/') == -1}}" target="{{value.urlTarget}}"><i class="icon-out"></i> {{value.url}}</a>
|
||||
<a href="{{getUrl(value.url)}}" prevent-default="{{value.url.indexOf('/') == -1}}" target="{{value.urlTarget}}">
|
||||
<i ng-class="value.icon"></i>
|
||||
<span ng-if="value.linkText">{{value.linkText}}</span>
|
||||
<span ng-if="!value.linkText">{{value.url}}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -2411,9 +2411,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7300</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7310</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7300</IISUrl>
|
||||
<IISUrl>http://localhost:7310</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</root>
|
||||
|
||||
<appender name="rollingFile" type="log4net.Appender.RollingFileAppender">
|
||||
<file value="App_Data\Logs\UmbracoTraceLog.txt" />
|
||||
<file type="log4net.Util.PatternString" value="App_Data\Logs\UmbracoTraceLog.%property{log4net:HostName}.txt" />
|
||||
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
||||
<appendToFile value="true" />
|
||||
<rollingStyle value="Date" />
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</root>
|
||||
|
||||
<appender name="rollingFile" type="log4net.Appender.RollingFileAppender">
|
||||
<file value="App_Data\Logs\UmbracoTraceLog.txt" />
|
||||
<file type="log4net.Util.PatternString" value="App_Data\Logs\UmbracoTraceLog.%property{log4net:HostName}.txt" />
|
||||
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
||||
<appendToFile value="true" />
|
||||
<rollingStyle value="Date" />
|
||||
|
||||
@@ -16,15 +16,8 @@
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
|
||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,700,600' rel='stylesheet' type='text/css'>
|
||||
<link href='https://fonts.googleapis.com/css?family=Asap:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
|
||||
|
||||
<link rel="stylesheet" href="../../Umbraco/assets/css/nonodes.style.min.css" />
|
||||
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.7.1/modernizr.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<script type="text/javascript">
|
||||
|
||||
var parts = window.location.href.split("?redirectUrl=");
|
||||
if (parts.length != 2) {
|
||||
if (parts.length !== 2) {
|
||||
window.location.href = "/";
|
||||
}
|
||||
else {
|
||||
@@ -23,12 +23,12 @@
|
||||
parser.href = parts[1];
|
||||
|
||||
// => "http:"
|
||||
if (!parser.protocol || (parser.protocol.toLowerCase() != "http:" && parser.protocol.toLowerCase() != "https:")) {
|
||||
if (!parser.protocol || (parser.protocol.toLowerCase() !== "http:" && parser.protocol.toLowerCase() !== "https:")) {
|
||||
throw "invalid protocol";
|
||||
};
|
||||
|
||||
// => "example.com"
|
||||
if (!parser.hostname || parser.hostname == "") {
|
||||
if (!parser.hostname || parser.hostname === "") {
|
||||
throw "invalid hostname";
|
||||
}
|
||||
|
||||
@@ -37,13 +37,15 @@
|
||||
//parser.search => "?search=test"
|
||||
|
||||
// => "#hash"
|
||||
if (parser.hash && parser.hash.indexOf("#/developer/framed/") != 0) {
|
||||
if (parser.hash && parser.hash.indexOf("#/developer/framed/") !== 0) {
|
||||
throw "invalid hash";
|
||||
}
|
||||
|
||||
//parser.host; // => "example.com:3000"
|
||||
|
||||
window.location.href = parts[1];
|
||||
if (parser.host === window.location.host) {
|
||||
window.location.href = parts[1];
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
alert(e);
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<key alias="domainUpdated">Domain '%0%' has been updated</key>
|
||||
<key alias="orEdit">Edit Current Domains</key>
|
||||
<key alias="domainHelp"><![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
|
||||
"https://www.example.com/".<br /><br />One-level paths in domains are supported, eg. "example.com/en". However, they
|
||||
"https://www.example.com/". One-level paths in domains are supported, eg. "example.com/en". However, they
|
||||
should be avoided. Better use the culture setting above.]]></key>
|
||||
<key alias="inherit">Inherit</key>
|
||||
<key alias="setLanguage">Culture</key>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<key alias="domainUpdated">Domain '%0%' has been updated</key>
|
||||
<key alias="orEdit">Edit Current Domains</key>
|
||||
<key alias="domainHelp"><![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
|
||||
"https://www.example.com/".<br /><br />One-level paths in domains are supported, eg. "example.com/en". However, they
|
||||
"https://www.example.com/". One-level paths in domains are supported, eg. "example.com/en". However, they
|
||||
should be avoided. Better use the culture setting above.]]></key>
|
||||
<key alias="inherit">Inherit</key>
|
||||
<key alias="setLanguage">Culture</key>
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
|
||||
<cc1:Pane runat="server" ID="pane_domains">
|
||||
<small class="help-inline"><%=umbraco.ui.Text("assignDomain", "domainHelp") %></small>
|
||||
<cc1:PropertyPanel runat="server">
|
||||
<table class="table domains" data-bind="visible: domains().length > 0">
|
||||
<thead>
|
||||
@@ -51,7 +52,7 @@
|
||||
</thead>
|
||||
<tbody data-bind="foreach: domains">
|
||||
<tr>
|
||||
<td valign="top"><input class="domain" data-bind="value: Name, uniqueName: true" /><input type="hidden" value="0" data-bind="uniqueName: true"/></td>
|
||||
<td valign="top"><input class="domain duplicate" data-bind="value: Name, uniqueName: true" /><input type="hidden" value="" data-bind="uniqueName: true"/></td>
|
||||
<td valign="top"><select class="language" data-bind="options: $parent.languages, optionsText: 'Code', optionsValue: 'Id', value: Lang, uniqueName: true"></select></td>
|
||||
<td valign="top"><a href="#" class="btn btn-danger" data-bind="click: $parent.removeDomain"><i class="icon icon-trash"></i></a></td>
|
||||
</tr>
|
||||
@@ -60,7 +61,6 @@
|
||||
</cc1:PropertyPanel>
|
||||
|
||||
<cc1:PropertyPanel runat="server">
|
||||
<small data-bind="visible: domains().length == 0" class="help-inline"><%=umbraco.ui.Text("assignDomain", "domainHelp") %></small>
|
||||
<button class="btn" data-bind="click: addDomain"><%=umbraco.ui.Text("assignDomain", "addNew") %></button>
|
||||
</cc1:PropertyPanel>
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="../masterpages/umbracoDialog.Master" CodeBehind="RegexWs.aspx.cs" Inherits="umbraco.presentation.dialogs.RegexWs" %>
|
||||
<%@ Import Namespace="Umbraco.Web" %>
|
||||
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
|
||||
<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %>
|
||||
|
||||
@@ -40,7 +41,7 @@
|
||||
<asp:Content ContentPlaceHolderID="head" runat="server">
|
||||
<script type="text/javascript">
|
||||
function chooseRegex(regex) {
|
||||
var target = top.right.document.getElementById('<%= Request.QueryString["target"] %>');
|
||||
var target = top.right.document.getElementById('<%= Request.CleanForXss("target") %>');
|
||||
target.value = regex;
|
||||
UmbClientMgr.closeModalWindow();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
<%@ Import Namespace="Umbraco.Core" %>
|
||||
<%@ Import Namespace="Umbraco.Core.IO" %>
|
||||
<%@ Import Namespace="Umbraco.Web" %>
|
||||
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
|
||||
<%@ Register TagPrefix="umb" Namespace="ClientDependency.Core.Controls" Assembly="ClientDependency.Core" %>
|
||||
|
||||
@@ -35,7 +36,7 @@
|
||||
nameTxtBox: $("#<%= NameTxt.ClientID %>"),
|
||||
aliasTxtBox: $("#<%= AliasTxt.ClientID %>"),
|
||||
saveButton: $("#<%= ((Control)SaveButton).ClientID %>"),
|
||||
templateId: '<%= Request.QueryString["templateID"] %>',
|
||||
templateId: '<%= Request.CleanForXss("templateID") %>',
|
||||
codeEditorElementId: '<%= editorSource.ClientID %>',
|
||||
modalUrl: "<%= IOHelper.ResolveUrl(SystemDirectories.Umbraco) %>/dialogs/editMacro.aspx"
|
||||
});
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Umbraco.Web.UI.Umbraco.Settings.Views
|
||||
{
|
||||
return TreeDefinitionCollection.Instance.FindTree<PartialViewsTree>().Tree.Alias;
|
||||
}
|
||||
return Request.QueryString["treeType"];
|
||||
return Request.CleanForXss("treeType");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,9 +63,17 @@
|
||||
return ret;
|
||||
}, self._opts.invalidDomain);
|
||||
|
||||
function getDuplicateMessage(val, el) {
|
||||
var other = $(el).nextAll('input').val();
|
||||
var msg = self._opts.duplicateDomain
|
||||
if (other != "" && other != "!!!")
|
||||
msg = msg + ' (' + other + ')';
|
||||
return msg;
|
||||
}
|
||||
|
||||
$.validator.addMethod("duplicate", function (value, element, param) {
|
||||
return $(element).nextAll('input').val() == 0 && !self._isRepeated($(element));
|
||||
}, self._opts.duplicateDomain);
|
||||
return $(element).nextAll('input').val() == "" && !self._isRepeated($(element));
|
||||
}, getDuplicateMessage);
|
||||
|
||||
$.validator.addClassRules({
|
||||
domain: { domain: true },
|
||||
@@ -80,7 +88,7 @@
|
||||
|
||||
$('form input.domain').live('focus', function(event) {
|
||||
if (event.type != 'focusin') return;
|
||||
$(this).nextAll('input').val(0);
|
||||
$(this).nextAll('input').val("");
|
||||
});
|
||||
|
||||
// force validation *now*
|
||||
@@ -105,14 +113,14 @@
|
||||
}
|
||||
else {
|
||||
var inputs = $('form input.domain');
|
||||
inputs.each(function() { $(this).nextAll('input').val(0); });
|
||||
inputs.each(function() { $(this).nextAll('input').val(""); });
|
||||
for (var i = 0; i < json.Domains.length; i++) {
|
||||
var d = json.Domains[i];
|
||||
if (d.Duplicate == 1)
|
||||
if (d.Duplicate)
|
||||
inputs.each(function() {
|
||||
var input = $(this);
|
||||
if (input.val() == d.Name)
|
||||
input.nextAll('input').val(1);
|
||||
input.nextAll('input').val(d.Other ? d.Other : "!!!");
|
||||
});
|
||||
}
|
||||
$('form').valid();
|
||||
|
||||
@@ -189,8 +189,12 @@
|
||||
|
||||
top.UmbSpeechBubble.ShowMessage('save', header, msg);
|
||||
|
||||
this._opts.originalFileName = args.name;
|
||||
this._opts.treeSyncPath = args.path;
|
||||
if (args && args.name) {
|
||||
this._opts.originalFileName = args.name;
|
||||
}
|
||||
if (args && args.path) {
|
||||
this._opts.treeSyncPath = args.path;
|
||||
}
|
||||
|
||||
UmbClientMgr.mainTree().syncTree(path, true, null, newFilePath.split("/")[1]);
|
||||
}
|
||||
|
||||
@@ -150,6 +150,11 @@
|
||||
<add name="UmbracoRoleProvider" type="Umbraco.Web.Security.Providers.MembersRoleProvider" />
|
||||
</providers>
|
||||
</roleManager>
|
||||
<siteMap>
|
||||
<providers>
|
||||
<remove name="MySqlSiteMapProvider" />
|
||||
</providers>
|
||||
</siteMap>
|
||||
</system.web>
|
||||
|
||||
<system.webServer>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Sync;
|
||||
@@ -192,24 +193,27 @@ namespace Umbraco.Web.Cache
|
||||
public void RefreshAll(Guid factoryGuid)
|
||||
{
|
||||
if (factoryGuid == Guid.Empty) return;
|
||||
RefreshAll(factoryGuid, true);
|
||||
|
||||
ServerMessengerResolver.Current.Messenger.PerformRefreshAll(
|
||||
ServerRegistrarResolver.Current.Registrar.Registrations,
|
||||
GetRefresherById(factoryGuid));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the distributed cache of a global invalidation for a specified <see cref="ICacheRefresher"/>.
|
||||
/// </summary>
|
||||
/// <param name="factoryGuid">The unique identifier of the ICacheRefresher.</param>
|
||||
/// <param name="allServers">If true, all servers in the load balancing environment are notified; otherwise,
|
||||
/// only the local server is notified.</param>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("This method is no longer in use and does not work as advertised, the allServers parameter doesnt have any affect for database server messengers, do not use!")]
|
||||
public void RefreshAll(Guid factoryGuid, bool allServers)
|
||||
{
|
||||
if (factoryGuid == Guid.Empty) return;
|
||||
|
||||
ServerMessengerResolver.Current.Messenger.PerformRefreshAll(
|
||||
allServers
|
||||
? ServerRegistrarResolver.Current.Registrar.Registrations
|
||||
: Enumerable.Empty<IServerAddress>(), //this ensures it will only execute against the current server
|
||||
GetRefresherById(factoryGuid));
|
||||
if (allServers)
|
||||
{
|
||||
RefreshAll(factoryGuid);
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerMessengerResolver.Current.Messenger.PerformRefreshAll(
|
||||
Enumerable.Empty<IServerAddress>(),
|
||||
GetRefresherById(factoryGuid));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -5,6 +5,7 @@ using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using umbraco;
|
||||
using umbraco.cms.businesslogic.web;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
|
||||
namespace Umbraco.Web.Cache
|
||||
{
|
||||
@@ -262,8 +263,8 @@ namespace Umbraco.Web.Cache
|
||||
|
||||
public static void ClearAllMacroCacheOnCurrentServer(this DistributedCache dc)
|
||||
{
|
||||
// NOTE: The 'false' ensure that it will only refresh on the current server, not post to all servers
|
||||
dc.RefreshAll(DistributedCache.MacroCacheRefresherGuid, false);
|
||||
var macroRefresher = CacheRefreshersResolver.Current.GetById(DistributedCache.MacroCacheRefresherGuid);
|
||||
macroRefresher.RefreshAll();
|
||||
}
|
||||
|
||||
public static void RefreshMacroCache(this DistributedCache dc, IMacro macro)
|
||||
@@ -400,6 +401,12 @@ namespace Umbraco.Web.Cache
|
||||
dc.Remove(DistributedCache.DomainCacheRefresherGuid, domain.Id);
|
||||
}
|
||||
|
||||
public static void ClearDomainCacheOnCurrentServer(this DistributedCache dc)
|
||||
{
|
||||
var domainRefresher = CacheRefreshersResolver.Current.GetById(DistributedCache.DomainCacheRefresherGuid);
|
||||
domainRefresher.RefreshAll();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Language Cache
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace Umbraco.Web.Cache
|
||||
{
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes<IContent>();
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes<PublicAccessEntry>();
|
||||
DistributedCache.Instance.ClearDomainCacheOnCurrentServer();
|
||||
base.RefreshAll();
|
||||
}
|
||||
|
||||
@@ -87,6 +88,7 @@ namespace Umbraco.Web.Cache
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey<IContent>(id));
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes<PublicAccessEntry>();
|
||||
content.Instance.UpdateSortOrder(id);
|
||||
DistributedCache.Instance.ClearDomainCacheOnCurrentServer();
|
||||
base.Refresh(id);
|
||||
}
|
||||
|
||||
@@ -94,6 +96,7 @@ namespace Umbraco.Web.Cache
|
||||
{
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey<IContent>(id));
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes<PublicAccessEntry>();
|
||||
DistributedCache.Instance.ClearDomainCacheOnCurrentServer();
|
||||
base.Remove(id);
|
||||
}
|
||||
|
||||
@@ -103,6 +106,7 @@ namespace Umbraco.Web.Cache
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey<IContent>(instance.Id));
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes<PublicAccessEntry>();
|
||||
content.Instance.UpdateSortOrder(instance);
|
||||
DistributedCache.Instance.ClearDomainCacheOnCurrentServer();
|
||||
base.Refresh(instance);
|
||||
}
|
||||
|
||||
@@ -110,6 +114,7 @@ namespace Umbraco.Web.Cache
|
||||
{
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheItem(RepositoryBase.GetCacheIdKey<IContent>(instance.Id));
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheObjectTypes<PublicAccessEntry>();
|
||||
DistributedCache.Instance.ClearDomainCacheOnCurrentServer();
|
||||
base.Remove(instance);
|
||||
}
|
||||
|
||||
@@ -127,6 +132,8 @@ namespace Umbraco.Web.Cache
|
||||
content.Instance.UpdateSortOrder(payload.Id);
|
||||
}
|
||||
|
||||
DistributedCache.Instance.ClearDomainCacheOnCurrentServer();
|
||||
|
||||
OnCacheUpdated(Instance, new CacheRefresherEventArgs(jsonPayload, MessageType.RefreshByJson));
|
||||
}
|
||||
|
||||
|
||||
@@ -349,7 +349,9 @@ namespace Umbraco.Web.Editors
|
||||
{"trees", GetTreePluginsMetaData()}
|
||||
}
|
||||
},
|
||||
{"isDebuggingEnabled", HttpContext.IsDebuggingEnabled},
|
||||
{
|
||||
"isDebuggingEnabled", HttpContext.IsDebuggingEnabled
|
||||
},
|
||||
{
|
||||
"application", GetApplicationState()
|
||||
},
|
||||
|
||||
@@ -491,7 +491,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
var toCopy = ValidateMoveOrCopy(copy);
|
||||
|
||||
var c = Services.ContentService.Copy(toCopy, copy.ParentId, copy.RelateToOriginal);
|
||||
var c = Services.ContentService.Copy(toCopy, copy.ParentId, copy.RelateToOriginal, copy.Recursive);
|
||||
|
||||
var response = Request.CreateResponse(HttpStatusCode.OK);
|
||||
response.Content = new StringContent(c.Path, Encoding.UTF8, "application/json");
|
||||
|
||||
@@ -471,7 +471,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
tempFiles.Notifications.Add(new Notification(
|
||||
Services.TextService.Localize("speechBubbles/operationFailedHeader"),
|
||||
"Cannot upload file " + file + ", it is not an approved file type",
|
||||
"Cannot upload file " + file.Headers.ContentDisposition.FileName + ", it is not an approved file type",
|
||||
SpeechBubbleIcon.Warning));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Umbraco.Web
|
||||
}
|
||||
|
||||
|
||||
//[Obsolete("This should not be used, GetGridHtml methods accepting HtmlHelper as a parameter or GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
[Obsolete("This should not be used, GetGridHtml methods accepting HtmlHelper as a parameter or GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedProperty property, string framework = "bootstrap3")
|
||||
{
|
||||
var asString = property.Value as string;
|
||||
@@ -97,13 +97,13 @@ namespace Umbraco.Web
|
||||
return htmlHelper.GetGridHtml(property, framework);
|
||||
}
|
||||
|
||||
//[Obsolete("This should not be used, GetGridHtml methods accepting HtmlHelper as a parameter or GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
[Obsolete("This should not be used, GetGridHtml methods accepting HtmlHelper as a parameter or GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem)
|
||||
{
|
||||
return GetGridHtml(contentItem, "bodyText", "bootstrap3");
|
||||
}
|
||||
|
||||
//[Obsolete("This should not be used, GetGridHtml methods accepting HtmlHelper as a parameter or GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
[Obsolete("This should not be used, GetGridHtml methods accepting HtmlHelper as a parameter or GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem, string propertyAlias)
|
||||
{
|
||||
Mandate.ParameterNotNullOrEmpty(propertyAlias, "propertyAlias");
|
||||
@@ -111,7 +111,7 @@ namespace Umbraco.Web
|
||||
return GetGridHtml(contentItem, propertyAlias, "bootstrap3");
|
||||
}
|
||||
|
||||
//[Obsolete("This should not be used, GetGridHtml methods accepting HtmlHelper as a parameter or GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
[Obsolete("This should not be used, GetGridHtml methods accepting HtmlHelper as a parameter or GetGridHtml extensions on HtmlHelper should be used instead")]
|
||||
public static MvcHtmlString GetGridHtml(this IPublishedContent contentItem, string propertyAlias, string framework)
|
||||
{
|
||||
Mandate.ParameterNotNullOrEmpty(propertyAlias, "propertyAlias");
|
||||
@@ -127,7 +127,7 @@ namespace Umbraco.Web
|
||||
return htmlHelper.GetGridHtml(contentItem, propertyAlias, framework);
|
||||
}
|
||||
|
||||
//[Obsolete("This shouldn't need to be used but because the obsolete extension methods above don't have access to the current HtmlHelper, we need to create a fake one, unfortunately however this will not pertain the current views viewdata, tempdata or model state so should not be used")]
|
||||
[Obsolete("This shouldn't need to be used but because the obsolete extension methods above don't have access to the current HtmlHelper, we need to create a fake one, unfortunately however this will not pertain the current views viewdata, tempdata or model state so should not be used")]
|
||||
private static HtmlHelper CreateHtmlHelper(object model)
|
||||
{
|
||||
var cc = new ControllerContext
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
@@ -11,10 +10,12 @@ using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Profiling;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Mvc;
|
||||
using umbraco;
|
||||
using umbraco.cms.businesslogic.member;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
using Member = umbraco.cms.businesslogic.member.Member;
|
||||
|
||||
namespace Umbraco.Web
|
||||
{
|
||||
@@ -194,12 +195,123 @@ namespace Umbraco.Web
|
||||
return htmlHelper.Action(actionName, metaData.ControllerName, routeVals);
|
||||
}
|
||||
|
||||
#region BeginUmbracoForm
|
||||
#region GetCropUrl
|
||||
|
||||
/// <summary>
|
||||
/// Used for rendering out the Form for BeginUmbracoForm
|
||||
/// </summary>
|
||||
internal class UmbracoForm : MvcForm
|
||||
/// <summary>
|
||||
/// Gets the ImageProcessor Url of a media item by the crop alias (using default media item property alias of "umbracoFile")
|
||||
/// </summary>
|
||||
/// <param name="htmlHelper"></param>
|
||||
/// <param name="mediaItem"></param>
|
||||
/// <param name="cropAlias"></param>
|
||||
/// <returns></returns>
|
||||
public static IHtmlString GetCropUrl(this HtmlHelper htmlHelper, IPublishedContent mediaItem, string cropAlias)
|
||||
{
|
||||
return new HtmlString(mediaItem.GetCropUrl(cropAlias: cropAlias, useCropDimensions: true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ImageProcessor Url of a media item by the property alias and crop alias.
|
||||
/// </summary>
|
||||
/// <param name="htmlHelper"></param>
|
||||
/// <param name="mediaItem"></param>
|
||||
/// <param name="propertyAlias"></param>
|
||||
/// <param name="cropAlias"></param>
|
||||
/// <returns></returns>
|
||||
public static IHtmlString GetCropUrl(this HtmlHelper htmlHelper, IPublishedContent mediaItem, string propertyAlias, string cropAlias)
|
||||
{
|
||||
return new HtmlString(mediaItem.GetCropUrl(propertyAlias: propertyAlias, cropAlias: cropAlias, useCropDimensions: true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ImageProcessor Url of a media item
|
||||
/// </summary>
|
||||
/// <param name="htmlHelper"></param>
|
||||
/// <param name="mediaItem"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="propertyAlias"></param>
|
||||
/// <param name="cropAlias"></param>
|
||||
/// <param name="quality"></param>
|
||||
/// <param name="imageCropMode"></param>
|
||||
/// <param name="imageCropAnchor"></param>
|
||||
/// <param name="preferFocalPoint"></param>
|
||||
/// <param name="useCropDimensions"></param>
|
||||
/// <param name="cacheBuster"></param>
|
||||
/// <param name="furtherOptions"></param>
|
||||
/// <param name="ratioMode"></param>
|
||||
/// <param name="upScale"></param>
|
||||
/// <returns></returns>
|
||||
public static IHtmlString GetCropUrl(this HtmlHelper htmlHelper,
|
||||
IPublishedContent mediaItem,
|
||||
int? width = null,
|
||||
int? height = null,
|
||||
string propertyAlias = Constants.Conventions.Media.File,
|
||||
string cropAlias = null,
|
||||
int? quality = null,
|
||||
ImageCropMode? imageCropMode = null,
|
||||
ImageCropAnchor? imageCropAnchor = null,
|
||||
bool preferFocalPoint = false,
|
||||
bool useCropDimensions = false,
|
||||
bool cacheBuster = true,
|
||||
string furtherOptions = null,
|
||||
ImageCropRatioMode? ratioMode = null,
|
||||
bool upScale = true)
|
||||
{
|
||||
return
|
||||
new HtmlString(mediaItem.GetCropUrl(width, height, propertyAlias, cropAlias, quality, imageCropMode,
|
||||
imageCropAnchor, preferFocalPoint, useCropDimensions, cacheBuster, furtherOptions, ratioMode,
|
||||
upScale));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ImageProcessor Url from the media path
|
||||
/// </summary>
|
||||
/// <param name="htmlHelper"></param>
|
||||
/// <param name="imageUrl"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="imageCropperValue"></param>
|
||||
/// <param name="cropAlias"></param>
|
||||
/// <param name="quality"></param>
|
||||
/// <param name="imageCropMode"></param>
|
||||
/// <param name="imageCropAnchor"></param>
|
||||
/// <param name="preferFocalPoint"></param>
|
||||
/// <param name="useCropDimensions"></param>
|
||||
/// <param name="cacheBusterValue"></param>
|
||||
/// <param name="furtherOptions"></param>
|
||||
/// <param name="ratioMode"></param>
|
||||
/// <param name="upScale"></param>
|
||||
/// <returns></returns>
|
||||
public static IHtmlString GetCropUrl(this HtmlHelper htmlHelper,
|
||||
string imageUrl,
|
||||
int? width = null,
|
||||
int? height = null,
|
||||
string imageCropperValue = null,
|
||||
string cropAlias = null,
|
||||
int? quality = null,
|
||||
ImageCropMode? imageCropMode = null,
|
||||
ImageCropAnchor? imageCropAnchor = null,
|
||||
bool preferFocalPoint = false,
|
||||
bool useCropDimensions = false,
|
||||
string cacheBusterValue = null,
|
||||
string furtherOptions = null,
|
||||
ImageCropRatioMode? ratioMode = null,
|
||||
bool upScale = true)
|
||||
{
|
||||
return
|
||||
new HtmlString(imageUrl.GetCropUrl(width, height, imageCropperValue, cropAlias, quality, imageCropMode,
|
||||
imageCropAnchor, preferFocalPoint, useCropDimensions, cacheBusterValue, furtherOptions, ratioMode,
|
||||
upScale));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BeginUmbracoForm
|
||||
|
||||
/// <summary>
|
||||
/// Used for rendering out the Form for BeginUmbracoForm
|
||||
/// </summary>
|
||||
internal class UmbracoForm : MvcForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an UmbracoForm
|
||||
@@ -756,8 +868,7 @@ namespace Umbraco.Web
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Wrap
|
||||
|
||||
public static HtmlTagWrapper Wrap(this HtmlHelper html, string tag, string innerText, params IHtmlTagWrapper[] children)
|
||||
@@ -823,7 +934,71 @@ namespace Umbraco.Web
|
||||
return item;
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
}
|
||||
#region canvasdesigner
|
||||
|
||||
public static IHtmlString EnableCanvasDesigner(this HtmlHelper html,
|
||||
UrlHelper url,
|
||||
UmbracoContext umbCtx)
|
||||
{
|
||||
return html.EnableCanvasDesigner(url, umbCtx, string.Empty, string.Empty);
|
||||
}
|
||||
|
||||
public static IHtmlString EnableCanvasDesigner(this HtmlHelper html,
|
||||
UrlHelper url,
|
||||
UmbracoContext umbCtx, string canvasdesignerConfigPath)
|
||||
{
|
||||
return html.EnableCanvasDesigner(url, umbCtx, canvasdesignerConfigPath, string.Empty);
|
||||
}
|
||||
|
||||
public static IHtmlString EnableCanvasDesigner(this HtmlHelper html,
|
||||
UrlHelper url,
|
||||
UmbracoContext umbCtx, string canvasdesignerConfigPath, string canvasdesignerPalettesPath)
|
||||
{
|
||||
|
||||
var umbracoPath = url.Content(SystemDirectories.Umbraco);
|
||||
|
||||
string previewLink = @"<script src=""{0}/lib/jquery/jquery.min.js"" type=""text/javascript""></script>" +
|
||||
@"<script src=""{1}"" type=""text/javascript""></script>" +
|
||||
@"<script src=""{2}"" type=""text/javascript""></script>" +
|
||||
@"<script type=""text/javascript"">var pageId = '{3}'</script>" +
|
||||
@"<script src=""{0}/js/canvasdesigner.front.js"" type=""text/javascript""></script>";
|
||||
|
||||
string noPreviewLinks = @"<link href=""{1}"" type=""text/css"" rel=""stylesheet"" data-title=""canvasdesignerCss"" />";
|
||||
|
||||
// Get page value
|
||||
int pageId = umbCtx.PublishedContentRequest.UmbracoPage.PageID;
|
||||
string[] path = umbCtx.PublishedContentRequest.UmbracoPage.SplitPath;
|
||||
string result = string.Empty;
|
||||
string cssPath = CanvasDesignerUtility.GetStylesheetPath(path, false);
|
||||
|
||||
if (umbCtx.InPreviewMode)
|
||||
{
|
||||
canvasdesignerConfigPath = string.IsNullOrEmpty(canvasdesignerConfigPath) == false
|
||||
? canvasdesignerConfigPath
|
||||
: string.Format("{0}/js/canvasdesigner.config.js", umbracoPath);
|
||||
canvasdesignerPalettesPath = string.IsNullOrEmpty(canvasdesignerPalettesPath) == false
|
||||
? canvasdesignerPalettesPath
|
||||
: string.Format("{0}/js/canvasdesigner.palettes.js", umbracoPath);
|
||||
|
||||
if (string.IsNullOrEmpty(cssPath) == false)
|
||||
result = string.Format(noPreviewLinks, cssPath) + Environment.NewLine;
|
||||
|
||||
result = result + string.Format(previewLink, umbracoPath, canvasdesignerConfigPath, canvasdesignerPalettesPath, pageId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get css path for current page
|
||||
if (string.IsNullOrEmpty(cssPath) == false)
|
||||
result = string.Format(noPreviewLinks, cssPath);
|
||||
}
|
||||
|
||||
return new HtmlString(result);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Umbraco.Web
|
||||
/// <returns></returns>
|
||||
public static string GetItemAsString(this HttpRequest request, string key, string valueIfNotFound = "")
|
||||
{
|
||||
return new HttpRequestWrapper(request).GetItemAsString(key);
|
||||
return new HttpRequestWrapper(request).GetItemAsString(key, valueIfNotFound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -44,7 +44,7 @@ namespace Umbraco.Web
|
||||
/// <returns></returns>
|
||||
public static string GetItemAsString(this HttpRequestBase request, string key, string valueIfNotFound = "")
|
||||
{
|
||||
var val = HttpContext.Current.Request[key];
|
||||
var val = request[key];
|
||||
return !val.IsNullOrWhiteSpace() ? val : valueIfNotFound;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Umbraco.Web
|
||||
/// <returns></returns>
|
||||
public static T GetItemAs<T>(this HttpRequestBase request, string key)
|
||||
{
|
||||
var val = HttpContext.Current.Request[key];
|
||||
var val = request[key];
|
||||
var whitespaceCheck = !val.IsNullOrWhiteSpace() ? val : string.Empty;
|
||||
if (whitespaceCheck.IsNullOrWhiteSpace())
|
||||
return (T) typeof (T).GetDefaultValue();
|
||||
|
||||
@@ -34,6 +34,6 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
public bool HideLabel { get; set; }
|
||||
|
||||
[DataMember(Name = "validation")]
|
||||
public PropertyTypeValidation Validation { get; set; }
|
||||
public PropertyTypeValidation Validation { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,13 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
[DataMember(Name = "relateToOriginal", IsRequired = true)]
|
||||
[Required]
|
||||
public bool RelateToOriginal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Boolean indicating whether copying the object should be recursive
|
||||
/// </summary>
|
||||
[DataMember(Name = "recursive", IsRequired = true)]
|
||||
[Required]
|
||||
public bool Recursive { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,22 +2,16 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using AutoMapper;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Mapping;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Trees;
|
||||
using umbraco;
|
||||
using Umbraco.Web.Routing;
|
||||
using umbraco.BusinessLogic.Actions;
|
||||
|
||||
@@ -51,11 +45,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(
|
||||
dto => dto.IsContainer,
|
||||
expression => expression.MapFrom(content => content.ContentType.IsContainer))
|
||||
.ForMember(
|
||||
dto => dto.IsChildOfListView,
|
||||
//TODO: Fix this shorthand .Parent() lookup, at least have an overload to use the current
|
||||
// application context so it's testable!
|
||||
expression => expression.MapFrom(content => content.Parent().ContentType.IsContainer))
|
||||
.ForMember(display => display.IsChildOfListView, expression => expression.Ignore())
|
||||
.ForMember(
|
||||
dto => dto.Trashed,
|
||||
expression => expression.MapFrom(content => content.Trashed))
|
||||
@@ -78,7 +68,8 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(display => display.Tabs, expression => expression.ResolveUsing<TabsAndPropertiesResolver>())
|
||||
.ForMember(display => display.AllowedActions, expression => expression.ResolveUsing(
|
||||
new ActionButtonsResolver(new Lazy<IUserService>(() => applicationContext.Services.UserService))))
|
||||
.AfterMap((media, display) => AfterMap(media, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService));
|
||||
.AfterMap((media, display) => AfterMap(media, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService,
|
||||
applicationContext.Services.ContentTypeService));
|
||||
|
||||
//FROM IContent TO ContentItemBasic<ContentPropertyBasic, IContent>
|
||||
config.CreateMap<IContent, ContentItemBasic<ContentPropertyBasic, IContent>>()
|
||||
@@ -119,8 +110,37 @@ namespace Umbraco.Web.Models.Mapping
|
||||
/// <param name="display"></param>
|
||||
/// <param name="dataTypeService"></param>
|
||||
/// <param name="localizedText"></param>
|
||||
private static void AfterMap(IContent content, ContentItemDisplay display, IDataTypeService dataTypeService, ILocalizedTextService localizedText)
|
||||
/// <param name="contentTypeService"></param>
|
||||
private static void AfterMap(IContent content, ContentItemDisplay display, IDataTypeService dataTypeService,
|
||||
ILocalizedTextService localizedText, IContentTypeService contentTypeService)
|
||||
{
|
||||
//map the IsChildOfListView (this is actually if it is a descendant of a list view!)
|
||||
//TODO: Fix this shorthand .Ancestors() lookup, at least have an overload to use the current
|
||||
if (content.HasIdentity)
|
||||
{
|
||||
var ancesctorListView = content.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer);
|
||||
display.IsChildOfListView = ancesctorListView != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
//it's new so it doesn't have a path, so we need to look this up by it's parent + ancestors
|
||||
var parent = content.Parent();
|
||||
if (parent == null)
|
||||
{
|
||||
display.IsChildOfListView = false;
|
||||
}
|
||||
else if (parent.ContentType.IsContainer)
|
||||
{
|
||||
display.IsChildOfListView = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var ancesctorListView = parent.Ancestors().FirstOrDefault(x => x.ContentType.IsContainer);
|
||||
display.IsChildOfListView = ancesctorListView != null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//map the tree node url
|
||||
if (HttpContext.Current != null)
|
||||
{
|
||||
@@ -142,44 +162,77 @@ namespace Umbraco.Web.Models.Mapping
|
||||
TabsAndPropertiesResolver.AddListView(display, "content", dataTypeService);
|
||||
}
|
||||
|
||||
TabsAndPropertiesResolver.MapGenericProperties(
|
||||
content, display,
|
||||
var properties = new List<ContentPropertyDisplay>
|
||||
{
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}releasedate", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = localizedText.Localize("content/releaseDate"),
|
||||
Value = display.ReleaseDate.HasValue ? display.ReleaseDate.Value.ToIsoString() : null,
|
||||
View = "datepicker" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
|
||||
},
|
||||
{
|
||||
Alias = string.Format("{0}releasedate", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = localizedText.Localize("content/releaseDate"),
|
||||
Value = display.ReleaseDate.HasValue ? display.ReleaseDate.Value.ToIsoString() : null,
|
||||
View = "datepicker" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}expiredate", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = localizedText.Localize("content/unpublishDate"),
|
||||
Value = display.ExpireDate.HasValue ? display.ExpireDate.Value.ToIsoString() : null,
|
||||
View = "datepicker" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
|
||||
},
|
||||
{
|
||||
Alias = string.Format("{0}expiredate", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = localizedText.Localize("content/unpublishDate"),
|
||||
Value = display.ExpireDate.HasValue ? display.ExpireDate.Value.ToIsoString() : null,
|
||||
View = "datepicker" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}template", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = "Template", //TODO: localize this?
|
||||
Value = display.TemplateAlias,
|
||||
View = "dropdown", //TODO: Hard coding until we make a real dropdown property editor to lookup
|
||||
Config = new Dictionary<string, object>
|
||||
{
|
||||
Alias = string.Format("{0}template", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = "Template", //TODO: localize this?
|
||||
Value = display.TemplateAlias,
|
||||
View = "dropdown", //TODO: Hard coding until we make a real dropdown property editor to lookup
|
||||
Config = new Dictionary<string, object>
|
||||
{"items", templateItemConfig}
|
||||
}
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}urls", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = localizedText.Localize("content/urls"),
|
||||
Value = string.Join(",", display.Urls),
|
||||
View = "urllist" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
|
||||
}
|
||||
};
|
||||
|
||||
TabsAndPropertiesResolver.MapGenericProperties(content, display, properties.ToArray(),
|
||||
genericProperties =>
|
||||
{
|
||||
//TODO: This would be much nicer with the IUmbracoContextAccessor so we don't use singletons
|
||||
//If this is a web request and debugging is enabled and there's a user signed in and the
|
||||
// user has access tot he settings section, we will
|
||||
if (HttpContext.Current != null && HttpContext.Current.IsDebuggingEnabled
|
||||
&& UmbracoContext.Current != null && UmbracoContext.Current.Security.CurrentUser != null
|
||||
&& UmbracoContext.Current.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings)))
|
||||
{
|
||||
var currentDocumentType = contentTypeService.GetContentType(display.ContentTypeAlias);
|
||||
var currentDocumentTypeName = currentDocumentType == null ? string.Empty : currentDocumentType.Name;
|
||||
|
||||
var currentDocumentTypeId = currentDocumentType == null ? string.Empty : currentDocumentType.Id.ToString(CultureInfo.InvariantCulture);
|
||||
//TODO: Hard coding this is not good
|
||||
var docTypeLink = string.Format("#/settings/framed/%252Fumbraco%252Fsettings%252FeditNodeTypeNew.aspx%253Fid%253D{0}", currentDocumentTypeId);
|
||||
|
||||
//Replace the doc type property
|
||||
var docTypeProp = genericProperties.First(x => x.Alias == string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
|
||||
docTypeProp.Value = new List<object>
|
||||
{
|
||||
new
|
||||
{
|
||||
{"items", templateItemConfig}
|
||||
linkText = currentDocumentTypeName,
|
||||
url = docTypeLink,
|
||||
target = "_self", icon = "icon-item-arrangement"
|
||||
}
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}urls", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = localizedText.Localize("content/urls"),
|
||||
Value = string.Join(",", display.Urls),
|
||||
View = "urllist" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
|
||||
});
|
||||
};
|
||||
//TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
|
||||
docTypeProp.View = "urllist";
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the published date value for the IContent object
|
||||
/// </summary>
|
||||
|
||||
@@ -35,11 +35,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(
|
||||
dto => dto.ContentTypeAlias,
|
||||
expression => expression.MapFrom(content => content.ContentType.Alias))
|
||||
.ForMember(
|
||||
dto => dto.IsChildOfListView,
|
||||
//TODO: Fix this shorthand .Parent() lookup, at least have an overload to use the current
|
||||
// application context so it's testable!
|
||||
expression => expression.MapFrom(content => content.Parent().ContentType.IsContainer))
|
||||
.ForMember(display => display.IsChildOfListView, expression => expression.Ignore())
|
||||
.ForMember(
|
||||
dto => dto.Trashed,
|
||||
expression => expression.MapFrom(content => content.Trashed))
|
||||
|
||||
@@ -178,45 +178,48 @@ namespace Umbraco.Web.Models.Mapping
|
||||
display.TreeNodeUrl = url;
|
||||
}
|
||||
|
||||
TabsAndPropertiesResolver.MapGenericProperties(
|
||||
member, display,
|
||||
var genericProperties = new List<ContentPropertyDisplay>
|
||||
{
|
||||
GetLoginProperty(memberService, member, display),
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("general", "email"),
|
||||
Value = display.Email,
|
||||
View = "email",
|
||||
Validation = { Mandatory = true }
|
||||
},
|
||||
{
|
||||
Alias = string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("general", "email"),
|
||||
Value = display.Email,
|
||||
View = "email",
|
||||
Validation = {Mandatory = true}
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("password"),
|
||||
//NOTE: The value here is a json value - but the only property we care about is the generatedPassword one if it exists, the newPassword exists
|
||||
// only when creating a new member and we want to have a generated password pre-filled.
|
||||
Value = new Dictionary<string, object>
|
||||
{
|
||||
Alias = string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("password"),
|
||||
//NOTE: The value here is a json value - but the only property we care about is the generatedPassword one if it exists, the newPassword exists
|
||||
// only when creating a new member and we want to have a generated password pre-filled.
|
||||
Value = new Dictionary<string, object>
|
||||
{
|
||||
{"generatedPassword", member.GetAdditionalDataValueIgnoreCase("GeneratedPassword", null) },
|
||||
{"newPassword", member.GetAdditionalDataValueIgnoreCase("NewPassword", null) },
|
||||
},
|
||||
//TODO: Hard coding this because the changepassword doesn't necessarily need to be a resolvable (real) property editor
|
||||
View = "changepassword",
|
||||
//initialize the dictionary with the configuration from the default membership provider
|
||||
Config = new Dictionary<string, object>(membersProvider.GetConfiguration())
|
||||
{
|
||||
//the password change toggle will only be displayed if there is already a password assigned.
|
||||
{"hasPassword", member.RawPasswordValue.IsNullOrWhiteSpace() == false}
|
||||
}
|
||||
{"generatedPassword", member.GetAdditionalDataValueIgnoreCase("GeneratedPassword", null)},
|
||||
{"newPassword", member.GetAdditionalDataValueIgnoreCase("NewPassword", null)},
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
//TODO: Hard coding this because the changepassword doesn't necessarily need to be a resolvable (real) property editor
|
||||
View = "changepassword",
|
||||
//initialize the dictionary with the configuration from the default membership provider
|
||||
Config = new Dictionary<string, object>(membersProvider.GetConfiguration())
|
||||
{
|
||||
Alias = string.Format("{0}membergroup", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("content", "membergroup"),
|
||||
Value = GetMemberGroupValue(display.Username),
|
||||
View = "membergroups",
|
||||
Config = new Dictionary<string, object> { { "IsRequired", true } }
|
||||
});
|
||||
//the password change toggle will only be displayed if there is already a password assigned.
|
||||
{"hasPassword", member.RawPasswordValue.IsNullOrWhiteSpace() == false}
|
||||
}
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}membergroup", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("content", "membergroup"),
|
||||
Value = GetMemberGroupValue(display.Username),
|
||||
View = "membergroups",
|
||||
Config = new Dictionary<string, object> {{"IsRequired", true}}
|
||||
}
|
||||
};
|
||||
|
||||
TabsAndPropertiesResolver.MapGenericProperties(member, display, genericProperties);
|
||||
|
||||
//check if there's an approval field
|
||||
var provider = membersProvider as global::umbraco.providers.members.UmbracoMembershipProvider;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -17,7 +18,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
/// Creates the tabs collection with properties assigned for display models
|
||||
/// </summary>
|
||||
internal class TabsAndPropertiesResolver : ValueResolver<IContentBase, IEnumerable<Tab<ContentPropertyDisplay>>>
|
||||
{
|
||||
{
|
||||
private ICultureDictionary _cultureDictionary;
|
||||
protected IEnumerable<string> IgnoreProperties { get; set; }
|
||||
|
||||
@@ -27,7 +28,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
}
|
||||
|
||||
public TabsAndPropertiesResolver(IEnumerable<string> ignoreProperties)
|
||||
{
|
||||
{
|
||||
if (ignoreProperties == null) throw new ArgumentNullException("ignoreProperties");
|
||||
IgnoreProperties = ignoreProperties;
|
||||
}
|
||||
@@ -40,6 +41,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
/// <param name="customProperties">
|
||||
/// Any additional custom properties to assign to the generic properties tab.
|
||||
/// </param>
|
||||
/// <param name="onGenericPropertiesMapped"></param>
|
||||
/// <remarks>
|
||||
/// The generic properties tab is mapped during AfterMap and is responsible for
|
||||
/// setting up the properties such as Created date, updated date, template selected, etc...
|
||||
@@ -47,11 +49,10 @@ namespace Umbraco.Web.Models.Mapping
|
||||
public static void MapGenericProperties<TPersisted>(
|
||||
TPersisted content,
|
||||
ContentItemDisplayBase<ContentPropertyDisplay, TPersisted> display,
|
||||
params ContentPropertyDisplay[] customProperties)
|
||||
IEnumerable<ContentPropertyDisplay> customProperties = null,
|
||||
Action<List<ContentPropertyDisplay>> onGenericPropertiesMapped = null)
|
||||
where TPersisted : IContentBase
|
||||
{
|
||||
|
||||
|
||||
var genericProps = display.Tabs.Single(x => x.Id == 0);
|
||||
|
||||
//store the current props to append to the newly inserted ones
|
||||
@@ -60,56 +61,67 @@ namespace Umbraco.Web.Models.Mapping
|
||||
var labelEditor = PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View;
|
||||
|
||||
var contentProps = new List<ContentPropertyDisplay>
|
||||
{
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}id", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = "Id",
|
||||
Value = Convert.ToInt32(display.Id).ToInvariantString() + "<br/><small class='muted'>" + display.Key + "</small>",
|
||||
View = labelEditor
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}creator", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("content", "createBy"),
|
||||
Description = ui.Text("content", "createByDesc"), //TODO: Localize this
|
||||
Value = display.Owner.Name,
|
||||
View = labelEditor
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}createdate", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("content", "createDate"),
|
||||
Description = ui.Text("content", "createDateDesc"),
|
||||
Value = display.CreateDate.ToIsoString(),
|
||||
View = labelEditor
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}updatedate", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("content", "updateDate"),
|
||||
Description = ui.Text("content", "updateDateDesc"),
|
||||
Value = display.UpdateDate.ToIsoString(),
|
||||
View = labelEditor
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("content", "documentType"),
|
||||
Value = TranslateItem(display.ContentTypeName, CreateDictionary()),
|
||||
View = labelEditor
|
||||
}
|
||||
};
|
||||
Alias = string.Format("{0}id", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = "Id",
|
||||
Value = Convert.ToInt32(display.Id).ToInvariantString() + "<br/><small class='muted'>" + display.Key + "</small>",
|
||||
View = labelEditor
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}creator", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("content", "createBy"),
|
||||
Description = ui.Text("content", "createByDesc"), //TODO: Localize this
|
||||
Value = display.Owner.Name,
|
||||
View = labelEditor
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}createdate", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("content", "createDate"),
|
||||
Description = ui.Text("content", "createDateDesc"),
|
||||
Value = display.CreateDate.ToIsoString(),
|
||||
View = labelEditor
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}updatedate", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("content", "updateDate"),
|
||||
Description = ui.Text("content", "updateDateDesc"),
|
||||
Value = display.UpdateDate.ToIsoString(),
|
||||
View = labelEditor
|
||||
},
|
||||
new ContentPropertyDisplay
|
||||
{
|
||||
Alias = string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
|
||||
Label = ui.Text("content", "documentType"),
|
||||
Value = TranslateItem(display.ContentTypeName, CreateDictionary()),
|
||||
View = labelEditor
|
||||
}
|
||||
};
|
||||
|
||||
//add the custom ones
|
||||
contentProps.AddRange(customProperties);
|
||||
if (customProperties != null)
|
||||
{
|
||||
//add the custom ones
|
||||
contentProps.AddRange(customProperties);
|
||||
}
|
||||
|
||||
//now add the user props
|
||||
contentProps.AddRange(currProps);
|
||||
|
||||
//callback
|
||||
if (onGenericPropertiesMapped != null)
|
||||
{
|
||||
onGenericPropertiesMapped(contentProps);
|
||||
}
|
||||
|
||||
//re-assign
|
||||
genericProps.Properties = contentProps;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Mvc.Async;
|
||||
|
||||
@@ -10,10 +11,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// Ensures that if an action for the Template name is not explicitly defined by a user, that the 'Index' action will execute
|
||||
/// </summary>
|
||||
public class RenderActionInvoker : AsyncControllerActionInvoker
|
||||
{
|
||||
|
||||
private static readonly ConcurrentDictionary<Type, ReflectedActionDescriptor> IndexDescriptors = new ConcurrentDictionary<Type, ReflectedActionDescriptor>();
|
||||
|
||||
{
|
||||
/// <summary>
|
||||
/// Ensures that if an action for the Template name is not explicitly defined by a user, that the 'Index' action will execute
|
||||
/// </summary>
|
||||
@@ -31,17 +29,8 @@ namespace Umbraco.Web.Mvc
|
||||
//check if the controller is an instance of IRenderMvcController
|
||||
if (controllerContext.Controller is IRenderMvcController)
|
||||
{
|
||||
return IndexDescriptors.GetOrAdd(controllerContext.Controller.GetType(),
|
||||
type => new ReflectedActionDescriptor(
|
||||
controllerContext.Controller.GetType().GetMethods()
|
||||
.First(x => x.Name == "Index" &&
|
||||
x.GetCustomAttributes(typeof (NonActionAttribute), false).Any() == false),
|
||||
"Index",
|
||||
controllerDescriptor));
|
||||
|
||||
|
||||
|
||||
}
|
||||
return controllerDescriptor.FindAction(controllerContext, "Index");
|
||||
}
|
||||
}
|
||||
return ad;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace Umbraco.Web.Security.Identity
|
||||
var cookieOptions = new CookieOptions
|
||||
{
|
||||
Path = "/",
|
||||
Domain = _authOptions.CookieDomain,
|
||||
Domain = _authOptions.CookieDomain ?? "FALSE",
|
||||
Expires = DateTime.Now.AddMinutes(_authOptions.LoginTimeoutMinutes),
|
||||
HttpOnly = true,
|
||||
Secure = _authOptions.CookieSecure == CookieSecureOption.Always
|
||||
|
||||
@@ -14,6 +14,9 @@ using Umbraco.Core.Xml;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Umbraco.Core.Cache;
|
||||
|
||||
namespace Umbraco.Web
|
||||
@@ -1170,52 +1173,44 @@ namespace Umbraco.Web
|
||||
|
||||
#region canvasdesigner
|
||||
|
||||
public HtmlString EnableCanvasDesigner()
|
||||
[Obsolete("Use EnableCanvasDesigner on the HtmlHelper extensions instead")]
|
||||
public IHtmlString EnableCanvasDesigner()
|
||||
{
|
||||
return EnableCanvasDesigner(string.Empty, string.Empty);
|
||||
}
|
||||
|
||||
public HtmlString EnableCanvasDesigner(string canvasdesignerConfigPath)
|
||||
[Obsolete("Use EnableCanvasDesigner on the HtmlHelper extensions instead")]
|
||||
public IHtmlString EnableCanvasDesigner(string canvasdesignerConfigPath)
|
||||
{
|
||||
return EnableCanvasDesigner(canvasdesignerConfigPath, string.Empty);
|
||||
}
|
||||
|
||||
public HtmlString EnableCanvasDesigner(string canvasdesignerConfigPath, string canvasdesignerPalettesPath)
|
||||
[Obsolete("Use EnableCanvasDesigner on the HtmlHelper extensions instead")]
|
||||
public IHtmlString EnableCanvasDesigner(string canvasdesignerConfigPath, string canvasdesignerPalettesPath)
|
||||
{
|
||||
var html = CreateHtmlHelper("");
|
||||
var urlHelper = new UrlHelper(UmbracoContext.HttpContext.Request.RequestContext);
|
||||
return html.EnableCanvasDesigner(urlHelper, UmbracoContext, canvasdesignerConfigPath, canvasdesignerPalettesPath);
|
||||
}
|
||||
|
||||
string previewLink = @"<script src=""/Umbraco/lib/jquery/jquery.min.js"" type=""text/javascript""></script>" +
|
||||
@"<script src=""{0}"" type=""text/javascript""></script>" +
|
||||
@"<script src=""{1}"" type=""text/javascript""></script>" +
|
||||
@"<script type=""text/javascript"">var pageId = '{2}'</script>" +
|
||||
@"<script src=""/umbraco/js/canvasdesigner.front.js"" type=""text/javascript""></script>";
|
||||
|
||||
string noPreviewLinks = @"<link href=""{0}"" type=""text/css"" rel=""stylesheet"" data-title=""canvasdesignerCss"" />";
|
||||
|
||||
// Get page value
|
||||
int pageId = UmbracoContext.PublishedContentRequest.UmbracoPage.PageID;
|
||||
string[] path = UmbracoContext.PublishedContentRequest.UmbracoPage.SplitPath;
|
||||
string result = string.Empty;
|
||||
string cssPath = CanvasDesignerUtility.GetStylesheetPath(path, false);
|
||||
|
||||
if (UmbracoContext.Current.InPreviewMode)
|
||||
[Obsolete("This shouldn't need to be used but because the obsolete extension methods above don't have access to the current HtmlHelper, we need to create a fake one, unfortunately however this will not pertain the current views viewdata, tempdata or model state so should not be used")]
|
||||
private HtmlHelper CreateHtmlHelper(object model)
|
||||
{
|
||||
var cc = new ControllerContext
|
||||
{
|
||||
canvasdesignerConfigPath = !string.IsNullOrEmpty(canvasdesignerConfigPath) ? canvasdesignerConfigPath : "/umbraco/js/canvasdesigner.config.js";
|
||||
canvasdesignerPalettesPath = !string.IsNullOrEmpty(canvasdesignerPalettesPath) ? canvasdesignerPalettesPath : "/umbraco/js/canvasdesigner.palettes.js";
|
||||
|
||||
if (!string.IsNullOrEmpty(cssPath))
|
||||
result = string.Format(noPreviewLinks, cssPath) + Environment.NewLine;
|
||||
RequestContext = UmbracoContext.HttpContext.Request.RequestContext
|
||||
};
|
||||
var viewContext = new ViewContext(cc, new FakeView(), new ViewDataDictionary(model), new TempDataDictionary(), new StringWriter());
|
||||
var htmlHelper = new HtmlHelper(viewContext, new ViewPage());
|
||||
return htmlHelper;
|
||||
}
|
||||
|
||||
result = result + string.Format(previewLink, canvasdesignerConfigPath, canvasdesignerPalettesPath, pageId);
|
||||
}
|
||||
else
|
||||
[Obsolete("This shouldn't need to be used but because the obsolete extension methods above don't have access to the current HtmlHelper, we need to create a fake one, unfortunately however this will not pertain the current views viewdata, tempdata or model state so should not be used")]
|
||||
private class FakeView : IView
|
||||
{
|
||||
public void Render(ViewContext viewContext, TextWriter writer)
|
||||
{
|
||||
// Get css path for current page
|
||||
if (!string.IsNullOrEmpty(cssPath))
|
||||
result = string.Format(noPreviewLinks, cssPath);
|
||||
}
|
||||
|
||||
return new HtmlString(result);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Web.Http;
|
||||
using System.Web.Services.Description;
|
||||
using Umbraco.Core;
|
||||
@@ -113,7 +114,25 @@ namespace Umbraco.Web.WebServices
|
||||
if (domain != null)
|
||||
domain.LanguageId = language.Id;
|
||||
else if (Services.DomainService.Exists(domainModel.Name))
|
||||
{
|
||||
domainModel.Duplicate = true;
|
||||
var xdomain = Services.DomainService.GetByName(domainModel.Name);
|
||||
var xrcid = xdomain.RootContentId;
|
||||
if (xrcid.HasValue)
|
||||
{
|
||||
var xcontent = Services.ContentService.GetById(xrcid.Value);
|
||||
var xnames = new List<string>();
|
||||
while (xcontent != null)
|
||||
{
|
||||
xnames.Add(xcontent.Name);
|
||||
if (xcontent.ParentId < -1)
|
||||
xnames.Add("Recycle Bin");
|
||||
xcontent = xcontent.Parent();
|
||||
}
|
||||
xnames.Reverse();
|
||||
domainModel.Other = "/" + string.Join("/", xnames);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// yet there is a race condition here...
|
||||
@@ -159,6 +178,7 @@ namespace Umbraco.Web.WebServices
|
||||
public string Name { get; private set; }
|
||||
public int Lang { get; private set; }
|
||||
public bool Duplicate { get; set; }
|
||||
public string Other { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -258,9 +258,16 @@ namespace Umbraco.Web.WebServices
|
||||
//ignore these properties
|
||||
.Where(x => new[] {"IndexerData", "Description", "WorkingFolder"}.InvariantContains(x.Name) == false)
|
||||
.OrderBy(x => x.Name);
|
||||
|
||||
foreach (var p in props)
|
||||
{
|
||||
indexerModel.ProviderProperties.Add(p.Name, p.GetValue(indexer, null).ToString());
|
||||
var val = p.GetValue(indexer, null);
|
||||
if (val == null)
|
||||
{
|
||||
LogHelper.Warn<ExamineManagementApiController>("Property value was null when setting up property on indexer: " + indexer.Name + " property: " + p.Name);
|
||||
val = string.Empty;
|
||||
}
|
||||
indexerModel.ProviderProperties.Add(p.Name, val.ToString());
|
||||
}
|
||||
|
||||
var luceneIndexer = indexer as LuceneIndexer;
|
||||
|
||||
@@ -97,22 +97,25 @@ namespace Umbraco.Web.WebServices
|
||||
oldname = oldname.TrimStart(pathPrefix);
|
||||
}
|
||||
|
||||
var view = get(svce, oldname);
|
||||
if (view == null)
|
||||
view = new PartialView(filename);
|
||||
var currentView = oldname.IsNullOrWhiteSpace()
|
||||
? get(svce, filename)
|
||||
: get(svce, oldname);
|
||||
|
||||
if (currentView == null)
|
||||
currentView = new PartialView(filename);
|
||||
else
|
||||
view.Path = filename;
|
||||
view.Content = contents;
|
||||
currentView.Path = filename;
|
||||
currentView.Content = contents;
|
||||
|
||||
Attempt<IPartialView> attempt;
|
||||
try
|
||||
{
|
||||
var partialView = view as PartialView;
|
||||
var partialView = currentView as PartialView;
|
||||
if (partialView != null && validate != null && validate(svce, partialView) == false)
|
||||
return Failed(ui.Text("speechBubbles", "partialViewErrorText"), ui.Text("speechBubbles", "partialViewErrorHeader"),
|
||||
new FileSecurityException("File '" + view.Path + "' is not a valid partial view file."));
|
||||
new FileSecurityException("File '" + currentView.Path + "' is not a valid partial view file."));
|
||||
|
||||
attempt = save(svce, view);
|
||||
attempt = save(svce, currentView);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -602,7 +602,7 @@ namespace umbraco
|
||||
XmlDocument mXml = new XmlDocument();
|
||||
mXml.LoadXml(m.ToXml(mXml, false).OuterXml);
|
||||
XPathNavigator xp = mXml.CreateNavigator();
|
||||
return xp.Select("/node");
|
||||
return xp.Select("/node()");
|
||||
}
|
||||
|
||||
XmlDocument xd = new XmlDocument();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
@@ -71,7 +72,7 @@ namespace umbraco
|
||||
else
|
||||
tmp = new Dictionary.DictionaryItem(this.id).Children;
|
||||
|
||||
foreach (Dictionary.DictionaryItem di in tmp)
|
||||
foreach (Dictionary.DictionaryItem di in tmp.OrderBy(a => a.key))
|
||||
{
|
||||
XmlTreeNode xNode = XmlTreeNode.Create(this);
|
||||
xNode.NodeID = di.id.ToString(); //dictionary_ + id..
|
||||
|
||||
+3
-2
@@ -12,6 +12,7 @@ using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Web;
|
||||
|
||||
namespace umbraco.presentation.developer.packages {
|
||||
public partial class BrowseRepository : BasePages.UmbracoEnsuredPage {
|
||||
@@ -31,8 +32,8 @@ namespace umbraco.presentation.developer.packages {
|
||||
fb.Text = "<strong>" + ui.Text("errors", "filePermissionsError") + ":</strong><br/>" + ex.Message;
|
||||
}
|
||||
|
||||
string category = Request.QueryString["category"];
|
||||
string repoGuid = Request.QueryString["repoGuid"];
|
||||
string category = Request.CleanForXss("category");
|
||||
string repoGuid = Request.CleanForXss("repoGuid");
|
||||
|
||||
var repo = cms.businesslogic.packager.repositories.Repository.getByGuid(repoGuid);
|
||||
if (repo == null)
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace umbraco.presentation.umbraco.dialogs
|
||||
|
||||
if (IsPostBack == false)
|
||||
{
|
||||
if (Access.IsProtected(documentId, documentObject.Path) && Access.GetProtectionType(documentId) != ProtectionType.NotProtected)
|
||||
if (Access.IsProtected(documentId) && Access.GetProtectionType(documentId) != ProtectionType.NotProtected)
|
||||
{
|
||||
bt_buttonRemoveProtection.Visible = true;
|
||||
bt_buttonRemoveProtection.Attributes.Add("onClick", "return confirm('" + ui.Text("areyousure") + "')");
|
||||
@@ -263,10 +263,11 @@ namespace umbraco.presentation.umbraco.dialogs
|
||||
p_buttons.Visible = false;
|
||||
pane_advanced.Visible = false;
|
||||
pane_simple.Visible = false;
|
||||
|
||||
var content = ApplicationContext.Current.Services.ContentService.GetById(pageId);
|
||||
//reloads the current node in the tree
|
||||
ClientTools.SyncTree(content.Path, true);
|
||||
|
||||
//reloads the current node's children in the tree
|
||||
ClientTools.ReloadActionNode(false, true);
|
||||
feedback.type = global::umbraco.uicontrols.Feedback.feedbacktype.success;
|
||||
}
|
||||
}
|
||||
@@ -284,8 +285,10 @@ namespace umbraco.presentation.umbraco.dialogs
|
||||
feedback.Text = ui.Text("publicAccess", "paIsRemoved", new cms.businesslogic.CMSNode(pageId).Text) + "</p><p><a href='#' onclick='" + ClientTools.Scripts.CloseModalWindow() + "'>" + ui.Text("closeThisWindow") + "</a>";
|
||||
|
||||
var content = ApplicationContext.Current.Services.ContentService.GetById(pageId);
|
||||
//reloads the current node in the tree
|
||||
ClientTools.SyncTree(content.Path, true);
|
||||
|
||||
//reloads the current node's children in the tree
|
||||
ClientTools.ReloadActionNode(false, true);
|
||||
feedback.type = global::umbraco.uicontrols.Feedback.feedbacktype.success;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ using umbraco.BasePages;
|
||||
using umbraco.BusinessLogic;
|
||||
using umbraco.businesslogic.Exceptions;
|
||||
using umbraco.cms.businesslogic.media;
|
||||
using umbraco.cms.businesslogic.propertytype;
|
||||
using umbraco.cms.businesslogic.web;
|
||||
using umbraco.controls;
|
||||
using umbraco.presentation.channels.businesslogic;
|
||||
@@ -28,7 +27,9 @@ using umbraco.providers;
|
||||
using umbraco.cms.presentation.Trees;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using PropertyType = umbraco.cms.businesslogic.propertytype.PropertyType;
|
||||
|
||||
namespace umbraco.cms.presentation.user
|
||||
{
|
||||
@@ -106,8 +107,8 @@ namespace umbraco.cms.presentation.user
|
||||
userType.Items.Add(li);
|
||||
}
|
||||
}
|
||||
|
||||
var userCulture = Services.TextService.ConvertToSupportedCultureWithRegionCode(new CultureInfo(u.Language));
|
||||
|
||||
var userCulture = UserExtensions.GetUserCulture(u.Language, Services.TextService);
|
||||
|
||||
// Populate ui language lsit
|
||||
foreach (var lang in Services.TextService.GetSupportedCultures())
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace umbraco.presentation.umbraco.webservices
|
||||
var ext = uploadFile.FileName.Substring(uploadFile.FileName.LastIndexOf('.') + 1).ToLower();
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.DisallowedUploadFiles.Contains(ext))
|
||||
{
|
||||
LogHelper.Warn<MediaUploader>("Cannot upload file " + uploadFile + ", it is not an approved file type");
|
||||
LogHelper.Warn<MediaUploader>("Cannot upload file " + uploadFile.FileName + ", it is not approved in `disallowedUploadFiles` in ~/config/UmbracoSettings.config");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace umbraco.cms.businesslogic.web
|
||||
if (e.Cancel) return;
|
||||
|
||||
|
||||
var entry = ApplicationContext.Current.Services.PublicAccessService.AddOrUpdateRule(
|
||||
var entry = ApplicationContext.Current.Services.PublicAccessService.AddRule(
|
||||
doc.ContentEntity,
|
||||
Constants.Conventions.PublicAccess.MemberRoleRuleType,
|
||||
role);
|
||||
@@ -95,7 +95,7 @@ namespace umbraco.cms.businesslogic.web
|
||||
if (content == null)
|
||||
throw new Exception("No content found with document id " + DocumentId);
|
||||
|
||||
if (ApplicationContext.Current.Services.PublicAccessService.AddOrUpdateRule(
|
||||
if (ApplicationContext.Current.Services.PublicAccessService.AddRule(
|
||||
content,
|
||||
Constants.Conventions.PublicAccess.MemberGroupIdRuleType,
|
||||
MemberGroupId.ToString(CultureInfo.InvariantCulture)))
|
||||
@@ -113,7 +113,7 @@ namespace umbraco.cms.businesslogic.web
|
||||
if (content == null)
|
||||
throw new Exception("No content found with document id " + DocumentId);
|
||||
|
||||
if (ApplicationContext.Current.Services.PublicAccessService.AddOrUpdateRule(
|
||||
if (ApplicationContext.Current.Services.PublicAccessService.AddRule(
|
||||
content,
|
||||
Constants.Conventions.PublicAccess.MemberIdRuleType,
|
||||
MemberId.ToString(CultureInfo.InvariantCulture)))
|
||||
@@ -132,7 +132,7 @@ namespace umbraco.cms.businesslogic.web
|
||||
|
||||
if (e.Cancel) return;
|
||||
|
||||
var entry = ApplicationContext.Current.Services.PublicAccessService.AddOrUpdateRule(
|
||||
var entry = ApplicationContext.Current.Services.PublicAccessService.AddRule(
|
||||
doc.ContentEntity,
|
||||
Constants.Conventions.PublicAccess.MemberUsernameRuleType,
|
||||
membershipUserName);
|
||||
@@ -155,7 +155,7 @@ namespace umbraco.cms.businesslogic.web
|
||||
{
|
||||
var doc = new Document(DocumentId);
|
||||
|
||||
var entry = ApplicationContext.Current.Services.PublicAccessService.AddOrUpdateRule(
|
||||
var entry = ApplicationContext.Current.Services.PublicAccessService.AddRule(
|
||||
doc.ContentEntity,
|
||||
Constants.Conventions.PublicAccess.MemberGroupIdRuleType,
|
||||
MemberGroupId.ToString(CultureInfo.InvariantCulture));
|
||||
@@ -213,7 +213,7 @@ namespace umbraco.cms.businesslogic.web
|
||||
var noAccessContent = ApplicationContext.Current.Services.ContentService.GetById(ErrorDocumentId);
|
||||
if (noAccessContent == null) throw new NullReferenceException("No content item found with id " + ErrorDocumentId);
|
||||
|
||||
var entry = ApplicationContext.Current.Services.PublicAccessService.GetEntryForContent(doc.ContentEntity);
|
||||
var entry = ApplicationContext.Current.Services.PublicAccessService.GetEntryForContent(doc.ContentEntity.Id.ToString());
|
||||
if (entry != null)
|
||||
{
|
||||
if (Simple)
|
||||
@@ -420,6 +420,12 @@ namespace umbraco.cms.businesslogic.web
|
||||
return ApplicationContext.Current.Services.PublicAccessService.IsProtected(Path.EnsureEndsWith("," + DocumentId));
|
||||
}
|
||||
|
||||
//return the protection status of this exact document - not based on inheritance
|
||||
public static bool IsProtected(int DocumentId)
|
||||
{
|
||||
return ApplicationContext.Current.Services.PublicAccessService.IsProtected(DocumentId.ToString());
|
||||
}
|
||||
|
||||
public static int GetErrorPage(string Path)
|
||||
{
|
||||
var entry = ApplicationContext.Current.Services.PublicAccessService.GetEntryForContent(Path);
|
||||
|
||||
Reference in New Issue
Block a user