Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| adb059e0da | |||
| 4337976887 | |||
| efe5de87a6 | |||
| 389642946e | |||
| 53d30aa3cb | |||
| e233cffb9d | |||
| 9e58ebed24 | |||
| f51c4e332e | |||
| 03a0a0a0e9 | |||
| dcb381770f | |||
| 65db0e69a9 | |||
| 23c6a91e9c | |||
| a03c6dcf13 | |||
| 3029d97f33 | |||
| f41d967864 | |||
| 4a481b05d4 | |||
| 66c6b5b524 | |||
| e3b0f71549 | |||
| 973b466798 | |||
| fa0eef4333 | |||
| a343a76a26 | |||
| d0a9e3236e | |||
| b899805ec9 | |||
| 766497e355 | |||
| 67a2a9cfe4 | |||
| 766ba0c8f5 | |||
| ca71c59880 | |||
| 6c87cf729a | |||
| 5c63afa31a | |||
| fa88768c91 | |||
| bfabfd9fa5 | |||
| aa1c411c8c | |||
| c52c452b36 | |||
| 86811fe507 | |||
| 363de53b82 | |||
| 958fb66f2c | |||
| 30e12c1367 | |||
| 89ff7d85e2 | |||
| 61fbf2cfc6 | |||
| ce847e97a8 | |||
| 1e61563f79 | |||
| b4f9985695 | |||
| 82f19ede8c | |||
| 0fbc32a87f | |||
| dc2de4b5e7 | |||
| 5fce741940 | |||
| 14e4a8061c | |||
| 1b9f071581 | |||
| 79141ef86d | |||
| 08609a887c | |||
| b11932240c | |||
| d47b4517c1 | |||
| 226a13c6e1 | |||
| d78a03a610 | |||
| b7a1123319 | |||
| 7e9cad34db | |||
| c4b44ea0e3 | |||
| 3435a75e9e | |||
| bdb6c5768a | |||
| 87a3c53e22 | |||
| 898d25f3cb | |||
| 9bc3fdd555 | |||
| cbda86fe92 | |||
| b48f0f52e0 | |||
| e2eeafcbfc | |||
| ad697db42b | |||
| 9bb31e9456 | |||
| a195d33332 | |||
| 82a87cbd92 | |||
| 5b26436862 | |||
| eed61f9053 | |||
| 55c68485e9 | |||
| b9ba350a2f | |||
| 696306e7c9 | |||
| 9bf86aff09 | |||
| f50de5b049 | |||
| d734ba6136 | |||
| c49becea53 | |||
| 614aea203d | |||
| ed88bbf75f | |||
| e41d3c7e84 |
@@ -79,3 +79,5 @@ src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
|
||||
src/Umbraco.Web.UI/[Uu]ser[Cc]ontrols/
|
||||
build/_BuildOutput/
|
||||
tools/NDepend/
|
||||
src/*.vspx
|
||||
src/*.psess
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
@ECHO OFF
|
||||
SET release=6.1.3
|
||||
SET release=6.1.4
|
||||
SET comment=
|
||||
SET version=%release%
|
||||
|
||||
|
||||
+12
-1
@@ -228,7 +228,7 @@
|
||||
</Target>
|
||||
|
||||
<!-- Copy the xml documentation to the bin folder -->
|
||||
<Target Name="CopyXmlDocumentation" DependsOnTargets="CompileProjects">
|
||||
<Target Name="CopyXmlDocumentation" DependsOnTargets="CleanupPresentation">
|
||||
<ItemGroup>
|
||||
<XmlDocumentationFiles Include="$(SolutionBinFolder)*.xml" />
|
||||
</ItemGroup>
|
||||
@@ -240,6 +240,17 @@
|
||||
<Message Text="CopyXmlDocumentation" />
|
||||
</Target>
|
||||
|
||||
<!-- Unlike 2010, the VS2012 build targets file doesn't clean up the umbraco.presentation dir, do it manually -->
|
||||
<!-- Also, it places umbraco.XmlSerializers.dll in the root, even though it's also in the bin folder. Kill! -->
|
||||
<Target Name="CleanupPresentation" DependsOnTargets="CompileProjects">
|
||||
<ItemGroup>
|
||||
<PresentationFolderToDelete Include="$(WebAppFolder)umbraco.presentation" />
|
||||
<XmlSerializersDll Include="$(WebAppFolder)umbraco.XmlSerializers.dll" />
|
||||
</ItemGroup>
|
||||
<RemoveDir Directories="@(PresentationFolderToDelete)" />
|
||||
<Delete Files="@(XmlSerializersDll)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CompileProjects" DependsOnTargets="CompileExternalExamineProjects">
|
||||
|
||||
<Message Text="Compiling web project to build\$(BuildFolder)" Importance="high" />
|
||||
|
||||
@@ -7,10 +7,11 @@ The config files found in the config folder will usually not be changed for patc
|
||||
but the web.config will have to have its previous "umbracoConfigurationStatus"-appsetting and "umbracoDbDSN" connection string
|
||||
copied over (as a minimum).
|
||||
|
||||
It's not possible to create a deploy package from Visual Studio, which contains everything out of the box. This is
|
||||
due to a number of files and folders that are not added to the Visual Studio project. These folders include:
|
||||
install, umbraco and umbraco_client.
|
||||
A custom deploy script will be added in a later release.
|
||||
This nuget package includes build targets that extends the creation of a deploy package, which is generated by
|
||||
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
|
||||
Publish this won't affect you.
|
||||
These folders will now be automatically included when creating a deploy package or publishing to the file system:
|
||||
umbraco and umbraco_client.
|
||||
|
||||
Please read the release notes on our.umbraco.org:
|
||||
http://our.umbraco.org/contribute/releases
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Caching;
|
||||
using System.Web.Security;
|
||||
using System.Xml;
|
||||
using System.Configuration;
|
||||
|
||||
@@ -299,6 +300,32 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
internal static string AuthCookieName
|
||||
{
|
||||
get
|
||||
{
|
||||
var value = GetKey("/settings/security/authCookieName");
|
||||
if (string.IsNullOrEmpty(value) == false)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return "UMB_UCONTEXT";
|
||||
}
|
||||
}
|
||||
|
||||
internal static string AuthCookieDomain
|
||||
{
|
||||
get
|
||||
{
|
||||
var value = GetKey("/settings/security/authCookieDomain");
|
||||
if (string.IsNullOrEmpty(value) == false)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return FormsAuthentication.CookieDomain;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables the experimental canvas (live) editing on the frontend of the website
|
||||
/// </summary>
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("6.1.3");
|
||||
private static readonly Version Version = new Version("6.1.4");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace Umbraco.Core
|
||||
public void ConfigureEmbeddedDatabaseConnection()
|
||||
{
|
||||
const string providerName = "System.Data.SqlServerCe.4.0";
|
||||
const string connectionString = @"Data Source=|DataDirectory|\Umbraco.sdf";
|
||||
const string connectionString = @"Data Source=|DataDirectory|\Umbraco.sdf;Flush Interval=1;File Access Retry Timeout=10";
|
||||
|
||||
SaveConnectionString(connectionString, providerName);
|
||||
|
||||
@@ -296,16 +296,15 @@ namespace Umbraco.Core
|
||||
if (databaseSettings != null && string.IsNullOrWhiteSpace(databaseSettings.ConnectionString) == false && string.IsNullOrWhiteSpace(databaseSettings.ProviderName) == false)
|
||||
{
|
||||
var providerName = "System.Data.SqlClient";
|
||||
string connString = null;
|
||||
if (!string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName))
|
||||
{
|
||||
providerName = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName;
|
||||
|
||||
_connectionString =
|
||||
ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ConnectionString;
|
||||
|
||||
connString = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ConnectionString;
|
||||
}
|
||||
Initialize(providerName, connString);
|
||||
|
||||
Initialize(providerName);
|
||||
DetermineSqlServerVersion();
|
||||
}
|
||||
else if (ConfigurationManager.AppSettings.ContainsKey(GlobalSettings.UmbracoConnectionName) && string.IsNullOrEmpty(ConfigurationManager.AppSettings[GlobalSettings.UmbracoConnectionName]) == false)
|
||||
{
|
||||
@@ -342,6 +341,8 @@ namespace Umbraco.Core
|
||||
|
||||
//Remove the legacy connection string, so we don't end up in a loop if something goes wrong.
|
||||
GlobalSettings.RemoveSetting(GlobalSettings.UmbracoConnectionName);
|
||||
|
||||
DetermineSqlServerVersion();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -369,6 +370,55 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
internal void Initialize(string providerName, string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
Initialize(providerName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the lazy resolution of determining the SQL server version if that is the db type we're using
|
||||
/// </summary>
|
||||
private void DetermineSqlServerVersion()
|
||||
{
|
||||
|
||||
var sqlServerSyntax = SqlSyntaxContext.SqlSyntaxProvider as SqlServerSyntaxProvider;
|
||||
if (sqlServerSyntax != null)
|
||||
{
|
||||
//this will not execute now, it is lazy so will only execute when we need to actually know
|
||||
// the sql server version.
|
||||
sqlServerSyntax.VersionName = new Lazy<SqlServerVersionName>(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var database = this._factory.CreateDatabase();
|
||||
|
||||
var version = database.ExecuteScalar<string>("SELECT SERVERPROPERTY('productversion')");
|
||||
var firstPart = version.Split('.')[0];
|
||||
switch (firstPart)
|
||||
{
|
||||
case "11":
|
||||
return SqlServerVersionName.V2012;
|
||||
case "10":
|
||||
return SqlServerVersionName.V2008;
|
||||
case "9":
|
||||
return SqlServerVersionName.V2005;
|
||||
case "8":
|
||||
return SqlServerVersionName.V2000;
|
||||
case "7":
|
||||
return SqlServerVersionName.V7;
|
||||
default:
|
||||
return SqlServerVersionName.Other;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return SqlServerVersionName.Invalid;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
internal DatabaseSchemaResult ValidateDatabaseSchema()
|
||||
{
|
||||
if (_configured == false || (string.IsNullOrEmpty(_connectionString) || string.IsNullOrEmpty(ProviderName)))
|
||||
@@ -460,6 +510,8 @@ namespace Umbraco.Core
|
||||
message = message + "<p>Upgrade completed!</p>";
|
||||
}
|
||||
|
||||
//now that everything is done, we need to determine the version of SQL server that is executing
|
||||
|
||||
LogHelper.Info<DatabaseContext>("Database configuration status: " + message);
|
||||
|
||||
return new Result { Message = message, Success = true, Percentage = "100" };
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class RecycleBinEventArgs : CancellableEventArgs
|
||||
{
|
||||
public RecycleBinEventArgs(Guid nodeObjectType, IEnumerable<int> ids, List<string> files, bool emptiedSuccessfully)
|
||||
: base(false)
|
||||
{
|
||||
NodeObjectType = nodeObjectType;
|
||||
Ids = ids;
|
||||
Files = files;
|
||||
RecycleBinEmptiedSuccessfully = emptiedSuccessfully;
|
||||
}
|
||||
|
||||
public RecycleBinEventArgs(Guid nodeObjectType, IEnumerable<int> ids, List<string> files)
|
||||
: base(true)
|
||||
{
|
||||
NodeObjectType = nodeObjectType;
|
||||
Ids = ids;
|
||||
Files = files;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Id of the node object type of the items
|
||||
/// being deleted from the Recycle Bin.
|
||||
/// </summary>
|
||||
public Guid NodeObjectType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of Ids for each of the items being deleted from the Recycle Bin.
|
||||
/// </summary>
|
||||
public IEnumerable<int> Ids { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of Files that should be deleted as part
|
||||
/// of emptying the Recycle Bin.
|
||||
/// </summary>
|
||||
public List<string> Files { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Boolean indicating whether the Recycle Bin was emptied successfully
|
||||
/// </summary>
|
||||
public bool RecycleBinEmptiedSuccessfully { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Boolean indicating whether this event was fired for the Content's Recycle Bin.
|
||||
/// </summary>
|
||||
public bool IsContentRecycleBin
|
||||
{
|
||||
get { return NodeObjectType == new Guid(Constants.ObjectTypes.Document); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Boolean indicating whether this event was fired for the Media's Recycle Bin.
|
||||
/// </summary>
|
||||
public bool IsMediaRecycleBin
|
||||
{
|
||||
get { return NodeObjectType == new Guid(Constants.ObjectTypes.Media); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,10 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Boolean indicating whether this Content is Published or not
|
||||
/// </summary>
|
||||
/// <remarks>Setting Published to true/false should be private or internal</remarks>
|
||||
/// <remarks>
|
||||
/// Setting Published to true/false should be private or internal and should ONLY be used for wiring up the value
|
||||
/// from the db or modifying it based on changing the published state.
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
public bool Published
|
||||
{
|
||||
@@ -372,11 +375,25 @@ namespace Umbraco.Core.Models
|
||||
/// <returns>True if entity is dirty, otherwise False</returns>
|
||||
public override bool IsDirty()
|
||||
{
|
||||
bool dirtyEntity = base.IsDirty();
|
||||
return IsEntityDirty() || IsAnyUserPropertyDirty();
|
||||
}
|
||||
|
||||
bool dirtyProperties = Properties.Any(x => x.IsDirty());
|
||||
/// <summary>
|
||||
/// Returns true if only the entity properties are direty
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal bool IsEntityDirty()
|
||||
{
|
||||
return base.IsDirty();
|
||||
}
|
||||
|
||||
return dirtyEntity || dirtyProperties;
|
||||
/// <summary>
|
||||
/// Returns true if any of the properties are dirty
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal bool IsAnyUserPropertyDirty()
|
||||
{
|
||||
return Properties.Any(x => x.IsDirty());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -293,7 +293,10 @@ namespace Umbraco.Core.Models
|
||||
/// <returns><see cref="Property"/> Value as a <see cref="TPassType"/></returns>
|
||||
public virtual TPassType GetValue<TPassType>(string propertyTypeAlias)
|
||||
{
|
||||
return (TPassType)Properties[propertyTypeAlias].Value;
|
||||
if (Properties[propertyTypeAlias].Value is TPassType)
|
||||
return (TPassType)Properties[propertyTypeAlias].Value;
|
||||
|
||||
return (TPassType)Convert.ChangeType(Properties[propertyTypeAlias].Value, typeof(TPassType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -436,5 +439,20 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
public abstract void ChangeTrashedState(bool isTrashed, int parentId = -20);
|
||||
|
||||
/// <summary>
|
||||
/// We will override this method to ensure that when we reset the dirty properties that we
|
||||
/// also reset the dirty changes made to the content's Properties (user defined)
|
||||
/// </summary>
|
||||
/// <param name="rememberPreviouslyChangedProperties"></param>
|
||||
internal override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
|
||||
{
|
||||
base.ResetDirtyProperties(rememberPreviouslyChangedProperties);
|
||||
|
||||
foreach (var prop in Properties)
|
||||
{
|
||||
prop.ResetDirtyProperties(rememberPreviouslyChangedProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ using System.Xml.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Media;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Strings;
|
||||
using Umbraco.Core.Persistence;
|
||||
@@ -23,6 +24,107 @@ namespace Umbraco.Core.Models
|
||||
public static class ContentExtensions
|
||||
{
|
||||
#region IContent
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a new version should be created
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// A new version needs to be created when:
|
||||
/// * The publish status is changed
|
||||
/// * The language is changed
|
||||
/// * The item is already published and is being published again and any property value is changed (to enable a rollback)
|
||||
/// </remarks>
|
||||
internal static bool ShouldCreateNewVersion(this IContent entity)
|
||||
{
|
||||
var publishedState = ((Content)entity).PublishedState;
|
||||
return ShouldCreateNewVersion(entity, publishedState);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a new version should be created
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="publishedState"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// A new version needs to be created when:
|
||||
/// * The publish status is changed
|
||||
/// * The language is changed
|
||||
/// * The item is already published and is being published again and any property value is changed (to enable a rollback)
|
||||
/// </remarks>
|
||||
internal static bool ShouldCreateNewVersion(this IContent entity, PublishedState publishedState)
|
||||
{
|
||||
var dirtyEntity = (ICanBeDirty)entity;
|
||||
|
||||
//check if the published state has changed or the language
|
||||
var contentChanged =
|
||||
(dirtyEntity.IsPropertyDirty("Published") && publishedState != PublishedState.Unpublished)
|
||||
|| dirtyEntity.IsPropertyDirty("Language");
|
||||
|
||||
//return true if published or language has changed
|
||||
if (contentChanged)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//check if any user prop has changed
|
||||
var propertyValueChanged = ((Content) entity).IsAnyUserPropertyDirty();
|
||||
//check if any content prop has changed
|
||||
var contentDataChanged = ((Content) entity).IsEntityDirty();
|
||||
|
||||
//return true if the item is published and a property has changed or if any content property has changed
|
||||
return (propertyValueChanged && publishedState == PublishedState.Published) || contentDataChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the published db flag should be set to true for the current entity version and all other db
|
||||
/// versions should have their flag set to false.
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is determined by:
|
||||
/// * If a new version is being created and the entity is published
|
||||
/// * If the published state has changed and the entity is published OR the entity has been un-published.
|
||||
/// </remarks>
|
||||
internal static bool ShouldClearPublishedFlagForPreviousVersions(this IContent entity)
|
||||
{
|
||||
var publishedState = ((Content)entity).PublishedState;
|
||||
return entity.ShouldClearPublishedFlagForPreviousVersions(publishedState, entity.ShouldCreateNewVersion(publishedState));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the published db flag should be set to true for the current entity version and all other db
|
||||
/// versions should have their flag set to false.
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="publishedState"></param>
|
||||
/// <param name="isCreatingNewVersion"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is determined by:
|
||||
/// * If a new version is being created and the entity is published
|
||||
/// * If the published state has changed and the entity is published OR the entity has been un-published.
|
||||
/// </remarks>
|
||||
internal static bool ShouldClearPublishedFlagForPreviousVersions(this IContent entity, PublishedState publishedState, bool isCreatingNewVersion)
|
||||
{
|
||||
if (isCreatingNewVersion && entity.Published)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//If Published state has changed then previous versions should have their publish state reset.
|
||||
//If state has been changed to unpublished the previous versions publish state should also be reset.
|
||||
if (((ICanBeDirty)entity).IsPropertyDirty("Published") && (entity.Published || publishedState == PublishedState.Unpublished))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of the current contents ancestors, not including the content itself.
|
||||
/// </summary>
|
||||
|
||||
@@ -181,6 +181,38 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a clone of the current entity
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IContentType Clone(string alias)
|
||||
{
|
||||
var clone = (ContentType)this.MemberwiseClone();
|
||||
clone.Alias = alias;
|
||||
clone.Key = Guid.Empty;
|
||||
var propertyGroups = this.PropertyGroups.Select(x => x.Clone()).ToList();
|
||||
clone.PropertyGroups = new PropertyGroupCollection(propertyGroups);
|
||||
clone.PropertyTypes = this.PropertyTypeCollection.Select(x => x.Clone()).ToList();
|
||||
clone.ResetIdentity();
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
foreach (var propertyGroup in clone.PropertyGroups)
|
||||
{
|
||||
propertyGroup.ResetIdentity();
|
||||
foreach (var propertyType in propertyGroup.PropertyTypes)
|
||||
{
|
||||
propertyType.ResetIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var propertyType in clone.PropertyTypes.Where(x => x.HasIdentity))
|
||||
{
|
||||
propertyType.ResetIdentity();
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method to call when Entity is being saved
|
||||
/// </summary>
|
||||
|
||||
@@ -494,5 +494,14 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
_parentId = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PropertyTypes that are not part of a PropertyGroup
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
internal PropertyTypeCollection PropertyTypeCollection
|
||||
{
|
||||
get { return _propertyTypes; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,10 +22,15 @@ namespace Umbraco.Core.Models
|
||||
/// <returns>Xml of the property and its value</returns>
|
||||
public static XElement ToXml(this Property property)
|
||||
{
|
||||
string nodeName = UmbracoSettings.UseLegacyXmlSchema ? "data" : property.Alias.ToSafeAlias();
|
||||
return property.ToXml(ApplicationContext.Current.Services.DataTypeService);
|
||||
}
|
||||
|
||||
internal static XElement ToXml(this Property property, IDataTypeService dataTypeService)
|
||||
{
|
||||
var nodeName = UmbracoSettings.UseLegacyXmlSchema ? "data" : property.Alias.ToSafeAlias();
|
||||
|
||||
var xd = new XmlDocument();
|
||||
XmlNode xmlNode = xd.CreateNode(XmlNodeType.Element, nodeName, "");
|
||||
var xmlNode = xd.CreateNode(XmlNodeType.Element, nodeName, "");
|
||||
|
||||
//Add the property alias to the legacy schema
|
||||
if (UmbracoSettings.UseLegacyXmlSchema)
|
||||
@@ -37,9 +42,17 @@ namespace Umbraco.Core.Models
|
||||
|
||||
//This seems to fail during testing
|
||||
//SD: With the new null checks below, this shouldn't fail anymore.
|
||||
var dt = property.PropertyType.DataType(property.Id);
|
||||
var dt = property.PropertyType.DataType(property.Id, dataTypeService);
|
||||
if (dt != null && dt.Data != null)
|
||||
{
|
||||
{
|
||||
//We've already got the value for the property so we're going to give it to the
|
||||
// data type's data property so it doesn't go re-look up the value from the db again.
|
||||
var defaultData = dt.Data as IDataValueSetter;
|
||||
if (defaultData != null)
|
||||
{
|
||||
defaultData.SetValue(property.Value, property.PropertyType.DataTypeDatabaseType.ToString());
|
||||
}
|
||||
|
||||
xmlNode.AppendChild(dt.Data.ToXMl(xd));
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,23 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
internal PropertyGroup Clone()
|
||||
{
|
||||
var clone = (PropertyGroup) this.MemberwiseClone();
|
||||
var collection = new PropertyTypeCollection();
|
||||
foreach (var propertyType in this.PropertyTypes)
|
||||
{
|
||||
var property = propertyType.Clone();
|
||||
property.ResetIdentity();
|
||||
property.ResetDirtyProperties(false);
|
||||
collection.Add(property);
|
||||
}
|
||||
clone.PropertyTypes = collection;
|
||||
clone.ResetIdentity();
|
||||
clone.ResetDirtyProperties(false);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the ParentId from the lazy integer id
|
||||
/// </summary>
|
||||
|
||||
@@ -378,6 +378,14 @@ namespace Umbraco.Core.Models
|
||||
return true;
|
||||
}
|
||||
|
||||
internal PropertyType Clone()
|
||||
{
|
||||
var clone = (PropertyType) this.MemberwiseClone();
|
||||
clone.ResetIdentity();
|
||||
clone.ResetDirtyProperties(false);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public bool Equals(PropertyType other)
|
||||
{
|
||||
//Check whether the compared object is null.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using umbraco.interfaces;
|
||||
using Umbraco.Core.Services;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -9,6 +10,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
/// <param name="propertyType">PropertyType that references a DataType</param>
|
||||
/// <param name="propertyId">Id of the Property which references this DataType through its PropertyType</param>
|
||||
/// <param name="dataTypeService"></param>
|
||||
/// <returns><see cref="IDataType"/></returns>
|
||||
/// <remarks>
|
||||
/// This extension method is left internal because we don't want to take
|
||||
@@ -16,10 +18,10 @@ namespace Umbraco.Core.Models
|
||||
/// be replaced by PropertyEditors. It is however needed to generate xml
|
||||
/// for a property/propertytype when publishing.
|
||||
/// </remarks>
|
||||
internal static IDataType DataType(this PropertyType propertyType, int propertyId)
|
||||
internal static IDataType DataType(this PropertyType propertyType, int propertyId, IDataTypeService dataTypeService)
|
||||
{
|
||||
Mandate.ParameterNotNull(propertyType, "propertyType");
|
||||
var dataType = ApplicationContext.Current.Services.DataTypeService.GetDataTypeById(propertyType.DataTypeId);
|
||||
var dataType = dataTypeService.GetDataTypeById(propertyType.DataTypeId);
|
||||
if (dataType == null)
|
||||
{
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Currently just used to get the machine name in med trust and to format a machine name for use with file names
|
||||
/// </summary>
|
||||
internal class NetworkHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the machine name that is safe to use in file paths.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// see: https://github.com/Shandem/ClientDependency/issues/4
|
||||
/// </remarks>
|
||||
public static string FileSafeMachineName
|
||||
{
|
||||
get { return MachineName.ReplaceNonAlphanumericChars('-'); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current machine name
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Tries to resolve the machine name, if it cannot it uses the config section.
|
||||
/// </remarks>
|
||||
public static string MachineName
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Environment.MachineName;
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
return System.Net.Dns.GetHostName();
|
||||
}
|
||||
catch
|
||||
{
|
||||
//if we get here it means we cannot access the machine name
|
||||
throw new ApplicationException("Cannot resolve the current machine name eithe by Environment.MachineName or by Dns.GetHostname()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,9 @@ namespace Umbraco.Core.Persistence
|
||||
/// </remarks>
|
||||
internal class DefaultDatabaseFactory : DisposableObject, IDatabaseFactory
|
||||
{
|
||||
private readonly string _connectionStringName;
|
||||
private readonly string _connectionString;
|
||||
private readonly string _providerName;
|
||||
private readonly string _connectionStringName;
|
||||
public string ConnectionString { get; private set; }
|
||||
public string ProviderName { get; private set; }
|
||||
|
||||
//very important to have ThreadStatic:
|
||||
// see: http://issues.umbraco.org/issue/U4-2172
|
||||
@@ -52,8 +52,8 @@ namespace Umbraco.Core.Persistence
|
||||
{
|
||||
Mandate.ParameterNotNullOrEmpty(connectionString, "connectionString");
|
||||
Mandate.ParameterNotNullOrEmpty(providerName, "providerName");
|
||||
_connectionString = connectionString;
|
||||
_providerName = providerName;
|
||||
ConnectionString = connectionString;
|
||||
ProviderName = providerName;
|
||||
}
|
||||
|
||||
public UmbracoDatabase CreateDatabase()
|
||||
@@ -68,8 +68,8 @@ namespace Umbraco.Core.Persistence
|
||||
//double check
|
||||
if (_nonHttpInstance == null)
|
||||
{
|
||||
_nonHttpInstance = string.IsNullOrEmpty(_connectionString) == false && string.IsNullOrEmpty(_providerName) == false
|
||||
? new UmbracoDatabase(_connectionString, _providerName)
|
||||
_nonHttpInstance = string.IsNullOrEmpty(ConnectionString) == false && string.IsNullOrEmpty(ProviderName) == false
|
||||
? new UmbracoDatabase(ConnectionString, ProviderName)
|
||||
: new UmbracoDatabase(_connectionStringName);
|
||||
}
|
||||
}
|
||||
@@ -81,8 +81,8 @@ namespace Umbraco.Core.Persistence
|
||||
if (HttpContext.Current.Items.Contains(typeof(DefaultDatabaseFactory)) == false)
|
||||
{
|
||||
HttpContext.Current.Items.Add(typeof (DefaultDatabaseFactory),
|
||||
string.IsNullOrEmpty(_connectionString) == false && string.IsNullOrEmpty(_providerName) == false
|
||||
? new UmbracoDatabase(_connectionString, _providerName)
|
||||
string.IsNullOrEmpty(ConnectionString) == false && string.IsNullOrEmpty(ProviderName) == false
|
||||
? new UmbracoDatabase(ConnectionString, ProviderName)
|
||||
: new UmbracoDatabase(_connectionStringName));
|
||||
}
|
||||
return (UmbracoDatabase)HttpContext.Current.Items[typeof(DefaultDatabaseFactory)];
|
||||
|
||||
@@ -223,8 +223,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 4, DataTypeId = -88, ControlId = new Guid(Constants.PropertyEditors.Textbox), DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 5, DataTypeId = -89, ControlId = new Guid(Constants.PropertyEditors.TextboxMultiple), DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 6, DataTypeId = -90, ControlId = new Guid(Constants.PropertyEditors.UploadField), DbType = "Nvarchar" });
|
||||
//Dropdown list
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -91, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 7, DataTypeId = -92, ControlId = new Guid(Constants.PropertyEditors.NoEdit), DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 8, DataTypeId = -36, ControlId = new Guid(Constants.PropertyEditors.DateTime), DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 9, DataTypeId = -37, ControlId = new Guid(Constants.PropertyEditors.ColorPicker), DbType = "Nvarchar" });
|
||||
@@ -234,24 +232,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, ControlId = new Guid(Constants.PropertyEditors.Date), DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, ControlId = new Guid(Constants.PropertyEditors.DropDownList), DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, ControlId = new Guid(Constants.PropertyEditors.CheckBoxList), DbType = "Nvarchar" });
|
||||
// Fix for rich text editor backwards compatibility -> 83722133-f80c-4273-bdb6-1befaa04a612 TinyMCE DataType
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = -44, ControlId = new Guid("a3776494-0574-4d93-b7de-efdfdec6f2d1"), DbType = "Ntext" });
|
||||
//Radiobutton list
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 23, DataTypeId = -128, ControlId = new Guid("a52c7c1c-c330-476e-8605-d63d3b84b6a6"), DbType = "Nvarchar" });
|
||||
//Dropdown list multiple
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = -129, ControlId = new Guid("928639ed-9c73-4028-920c-1e55dbb68783"), DbType = "Nvarchar" });
|
||||
//Dropdown list
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 25, DataTypeId = -130, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" });
|
||||
//Dropdown list
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 26, DataTypeId = -131, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" });
|
||||
//Dropdown list
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 27, DataTypeId = -132, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" });
|
||||
//No edit
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 28, DataTypeId = -133, ControlId = new Guid("6c738306-4c17-4d88-b9bd-6546f3771597"), DbType = "Ntext" });
|
||||
//Dropdown list multiple
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 29, DataTypeId = -134, ControlId = new Guid("928639ed-9c73-4028-920c-1e55dbb68783"), DbType = "Nvarchar" });
|
||||
//Not found - maybe a legacy thing?
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 30, DataTypeId = -50, ControlId = new Guid("aaf99bb2-dbbe-444d-a296-185076bf0484"), DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 16, DataTypeId = 1034, ControlId = new Guid(Constants.PropertyEditors.ContentPicker), DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 17, DataTypeId = 1035, ControlId = new Guid(Constants.PropertyEditors.MediaPicker), DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 18, DataTypeId = 1036, ControlId = new Guid(Constants.PropertyEditors.MemberPicker), DbType = "Integer" });
|
||||
|
||||
@@ -6,6 +6,7 @@ using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Migrations.Initial;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence
|
||||
@@ -32,76 +33,145 @@ namespace Umbraco.Core.Persistence
|
||||
|
||||
public static void BulkInsertRecords<T>(this Database db, IEnumerable<T> collection)
|
||||
{
|
||||
//don't do anything if there are no records.
|
||||
if (collection.Any() == false)
|
||||
return;
|
||||
|
||||
using (var tr = db.GetTransaction())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (SqlSyntaxContext.SqlSyntaxProvider is SqlCeSyntaxProvider)
|
||||
{
|
||||
//SqlCe doesn't support bulk insert statements!
|
||||
|
||||
foreach (var poco in collection)
|
||||
{
|
||||
db.Insert(poco);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
string sql;
|
||||
using (var cmd = db.GenerateBulkInsertCommand(collection, db.Connection, out sql))
|
||||
{
|
||||
cmd.CommandText = sql;
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
tr.Complete();
|
||||
}
|
||||
catch
|
||||
{
|
||||
tr.Dispose();
|
||||
throw;
|
||||
}
|
||||
db.BulkInsertRecords(collection, tr);
|
||||
}
|
||||
}
|
||||
|
||||
internal static IDbCommand GenerateBulkInsertCommand<T>(this Database db, IEnumerable<T> collection, IDbConnection connection, out string sql)
|
||||
public static void BulkInsertRecords<T>(this Database db, IEnumerable<T> collection, Transaction tr)
|
||||
{
|
||||
//don't do anything if there are no records.
|
||||
if (collection.Any() == false)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
//if it is sql ce or it is a sql server version less than 2008, we need to do individual inserts.
|
||||
var sqlServerSyntax = SqlSyntaxContext.SqlSyntaxProvider as SqlServerSyntaxProvider;
|
||||
if ((sqlServerSyntax != null && (int)sqlServerSyntax.VersionName.Value < (int)SqlServerVersionName.V2008)
|
||||
|| SqlSyntaxContext.SqlSyntaxProvider is SqlCeSyntaxProvider)
|
||||
{
|
||||
//SqlCe doesn't support bulk insert statements!
|
||||
|
||||
foreach (var poco in collection)
|
||||
{
|
||||
db.Insert(poco);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] sqlStatements;
|
||||
var cmds = db.GenerateBulkInsertCommand(collection, db.Connection, out sqlStatements);
|
||||
for (var i = 0; i < sqlStatements.Length; i++)
|
||||
{
|
||||
using (var cmd = cmds[i])
|
||||
{
|
||||
cmd.CommandText = sqlStatements[i];
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr.Complete();
|
||||
}
|
||||
catch
|
||||
{
|
||||
tr.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a bulk insert command
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="db"></param>
|
||||
/// <param name="collection"></param>
|
||||
/// <param name="connection"></param>
|
||||
/// <param name="sql"></param>
|
||||
/// <returns>Sql commands with populated command parameters required to execute the sql statement</returns>
|
||||
/// <remarks>
|
||||
/// The limits for number of parameters are 2100 (in sql server, I think there's many more allowed in mysql). So
|
||||
/// we need to detect that many params and split somehow.
|
||||
/// For some reason the 2100 limit is not actually allowed even though the exception from sql server mentions 2100 as a max, perhaps it is 2099
|
||||
/// that is max. I've reduced it to 2000 anyways.
|
||||
/// </remarks>
|
||||
internal static IDbCommand[] GenerateBulkInsertCommand<T>(
|
||||
this Database db,
|
||||
IEnumerable<T> collection,
|
||||
IDbConnection connection,
|
||||
out string[] sql)
|
||||
{
|
||||
//A filter used below a few times to get all columns except result cols and not the primary key if it is auto-incremental
|
||||
Func<Database.PocoData, KeyValuePair<string, Database.PocoColumn>, bool> includeColumn = (data, column) =>
|
||||
{
|
||||
if (column.Value.ResultColumn) return false;
|
||||
if (data.TableInfo.AutoIncrement && column.Key == data.TableInfo.PrimaryKey) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
var pd = Database.PocoData.ForType(typeof(T));
|
||||
var tableName = db.EscapeTableName(pd.TableInfo.TableName);
|
||||
|
||||
//get all columns but not the primary key if it is auto-incremental
|
||||
var cols = string.Join(", ", (
|
||||
from c in pd.Columns
|
||||
where
|
||||
//don't return ResultColumns
|
||||
!c.Value.ResultColumn
|
||||
//if the table is auto-incremental, don't return the primary key
|
||||
&& (pd.TableInfo.AutoIncrement && c.Key != pd.TableInfo.PrimaryKey)
|
||||
select tableName + "." + db.EscapeSqlIdentifier(c.Key))
|
||||
.ToArray());
|
||||
//get all columns to include and format for sql
|
||||
var cols = string.Join(", ",
|
||||
pd.Columns
|
||||
.Where(c => includeColumn(pd, c))
|
||||
.Select(c => tableName + "." + db.EscapeSqlIdentifier(c.Key)).ToArray());
|
||||
|
||||
var cmd = db.CreateCommand(connection, "");
|
||||
var itemArray = collection.ToArray();
|
||||
|
||||
var pocoValues = new List<string>();
|
||||
var index = 0;
|
||||
foreach (var poco in collection)
|
||||
//calculate number of parameters per item
|
||||
var paramsPerItem = pd.Columns.Count(i => includeColumn(pd, i));
|
||||
|
||||
//Example calc:
|
||||
// Given: we have 4168 items in the itemArray, each item contains 8 command parameters (values to be inserterted)
|
||||
// 2100 / 8 = 262.5
|
||||
// Math.Floor(2100 / 8) = 262 items per trans
|
||||
// 4168 / 262 = 15.908... = there will be 16 trans in total
|
||||
|
||||
//all items will be included if we have disabled db parameters
|
||||
var itemsPerTrans = Math.Floor(2000.00 / paramsPerItem);
|
||||
//there will only be one transaction if we have disabled db parameters
|
||||
var numTrans = Math.Ceiling(itemArray.Length / itemsPerTrans);
|
||||
|
||||
var sqlQueries = new List<string>();
|
||||
var commands = new List<IDbCommand>();
|
||||
|
||||
for (var tIndex = 0; tIndex < numTrans; tIndex++)
|
||||
{
|
||||
var values = new List<string>();
|
||||
foreach (var i in pd.Columns)
|
||||
var itemsForTrans = itemArray
|
||||
.Skip(tIndex * (int)itemsPerTrans)
|
||||
.Take((int)itemsPerTrans);
|
||||
|
||||
var cmd = db.CreateCommand(connection, "");
|
||||
var pocoValues = new List<string>();
|
||||
var index = 0;
|
||||
foreach (var poco in itemsForTrans)
|
||||
{
|
||||
if (pd.TableInfo.AutoIncrement && i.Key == pd.TableInfo.PrimaryKey)
|
||||
var values = new List<string>();
|
||||
//get all columns except result cols and not the primary key if it is auto-incremental
|
||||
foreach (var i in pd.Columns.Where(x => includeColumn(pd, x)))
|
||||
{
|
||||
continue;
|
||||
db.AddParam(cmd, i.Value.GetValue(poco), "@");
|
||||
values.Add(string.Format("{0}{1}", "@", index++));
|
||||
}
|
||||
values.Add(string.Format("{0}{1}", "@", index++));
|
||||
db.AddParam(cmd, i.Value.GetValue(poco), "@");
|
||||
pocoValues.Add("(" + string.Join(",", values.ToArray()) + ")");
|
||||
}
|
||||
pocoValues.Add("(" + string.Join(",", values.ToArray()) + ")");
|
||||
|
||||
var sqlResult = string.Format("INSERT INTO {0} ({1}) VALUES {2}", tableName, cols, string.Join(", ", pocoValues));
|
||||
sqlQueries.Add(sqlResult);
|
||||
commands.Add(cmd);
|
||||
}
|
||||
sql = string.Format("INSERT INTO {0} ({1}) VALUES {2}", tableName, cols, string.Join(", ", pocoValues));
|
||||
return cmd;
|
||||
|
||||
sql = sqlQueries.ToArray();
|
||||
|
||||
return commands.ToArray();
|
||||
}
|
||||
|
||||
public static void CreateTable(this Database db, bool overwrite, Type modelType)
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
/// <summary>
|
||||
/// Logic that is shared with the expression helpers
|
||||
/// </summary>
|
||||
internal class BaseExpressionHelper
|
||||
{
|
||||
public virtual string GetQuotedValue(object value, Type fieldType, Func<object, string> escapeCallback = null, Func<Type, bool> shouldQuoteCallback = null)
|
||||
{
|
||||
if (value == null) return "NULL";
|
||||
|
||||
if (escapeCallback == null)
|
||||
{
|
||||
escapeCallback = EscapeParam;
|
||||
}
|
||||
if (shouldQuoteCallback == null)
|
||||
{
|
||||
shouldQuoteCallback = ShouldQuoteValue;
|
||||
}
|
||||
|
||||
if (!fieldType.UnderlyingSystemType.IsValueType && fieldType != typeof(string))
|
||||
{
|
||||
//if (TypeSerializer.CanCreateFromString(fieldType))
|
||||
//{
|
||||
// return "'" + EscapeParam(TypeSerializer.SerializeToString(value)) + "'";
|
||||
//}
|
||||
|
||||
throw new NotSupportedException(
|
||||
string.Format("Property of type: {0} is not supported", fieldType.FullName));
|
||||
}
|
||||
|
||||
if (fieldType == typeof(int))
|
||||
return ((int)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(float))
|
||||
return ((float)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(double))
|
||||
return ((double)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(decimal))
|
||||
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(DateTime))
|
||||
{
|
||||
return "'" + EscapeParam(((DateTime)value).ToIsoString()) + "'";
|
||||
}
|
||||
|
||||
if (fieldType == typeof(bool))
|
||||
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
|
||||
|
||||
return ShouldQuoteValue(fieldType)
|
||||
? "'" + EscapeParam(value) + "'"
|
||||
: value.ToString();
|
||||
}
|
||||
|
||||
public virtual string EscapeParam(object paramValue)
|
||||
{
|
||||
return paramValue.ToString().Replace("'", "''");
|
||||
}
|
||||
|
||||
public virtual string EscapeAtArgument(string exp)
|
||||
{
|
||||
if (exp.StartsWith("@"))
|
||||
return string.Concat("@", exp);
|
||||
|
||||
return exp;
|
||||
}
|
||||
|
||||
public virtual bool ShouldQuoteValue(Type fieldType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual string RemoveQuote(string exp)
|
||||
{
|
||||
if (exp.StartsWith("'") && exp.EndsWith("'"))
|
||||
{
|
||||
exp = exp.Remove(0, 1);
|
||||
exp = exp.Remove(exp.Length - 1, 1);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
protected virtual string RemoveQuoteFromAlias(string exp)
|
||||
{
|
||||
|
||||
if ((exp.StartsWith("\"") || exp.StartsWith("`") || exp.StartsWith("'"))
|
||||
&&
|
||||
(exp.EndsWith("\"") || exp.EndsWith("`") || exp.EndsWith("'")))
|
||||
{
|
||||
exp = exp.Remove(0, 1);
|
||||
exp = exp.Remove(exp.Length - 1, 1);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ using Umbraco.Core.Persistence.Mappers;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
internal class ModelToSqlExpressionHelper<T>
|
||||
internal class ModelToSqlExpressionHelper<T> : BaseExpressionHelper
|
||||
{
|
||||
private string sep = " ";
|
||||
private BaseMapper _mapper;
|
||||
@@ -246,7 +246,7 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
case "ToLower":
|
||||
return string.Format("lower({0})", r);
|
||||
case "StartsWith":
|
||||
return string.Format("upper({0}) like '{1}%'", r, RemoveQuote(args[0].ToString().ToUpper()));
|
||||
return string.Format("upper({0}) like '{1}%'", r, EscapeAtArgument(RemoveQuote(args[0].ToString().ToUpper())));
|
||||
case "EndsWith":
|
||||
return string.Format("upper({0}) like '%{1}'", r, RemoveQuote(args[0].ToString()).ToUpper());
|
||||
case "Contains":
|
||||
@@ -435,72 +435,7 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
|
||||
public virtual string GetQuotedValue(object value, Type fieldType)
|
||||
{
|
||||
if (value == null) return "NULL";
|
||||
|
||||
if (!fieldType.UnderlyingSystemType.IsValueType && fieldType != typeof(string))
|
||||
{
|
||||
throw new NotSupportedException(
|
||||
string.Format("Property of type: {0} is not supported", fieldType.FullName));
|
||||
}
|
||||
|
||||
if (fieldType == typeof(int))
|
||||
return ((int)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(float))
|
||||
return ((float)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(double))
|
||||
return ((double)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(decimal))
|
||||
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof (DateTime))
|
||||
{
|
||||
return "'" + EscapeParam(((DateTime)value).ToIsoString()) + "'";
|
||||
}
|
||||
|
||||
|
||||
if (fieldType == typeof(bool))
|
||||
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
|
||||
|
||||
return ShouldQuoteValue(fieldType)
|
||||
? "'" + EscapeParam(value) + "'"
|
||||
: value.ToString();
|
||||
}
|
||||
|
||||
public virtual string EscapeParam(object paramValue)
|
||||
{
|
||||
return paramValue.ToString().Replace("'", "''");
|
||||
}
|
||||
|
||||
public virtual bool ShouldQuoteValue(Type fieldType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected string RemoveQuote(string exp)
|
||||
{
|
||||
|
||||
if (exp.StartsWith("'") && exp.EndsWith("'"))
|
||||
{
|
||||
exp = exp.Remove(0, 1);
|
||||
exp = exp.Remove(exp.Length - 1, 1);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
protected string RemoveQuoteFromAlias(string exp)
|
||||
{
|
||||
|
||||
if ((exp.StartsWith("\"") || exp.StartsWith("`") || exp.StartsWith("'"))
|
||||
&&
|
||||
(exp.EndsWith("\"") || exp.EndsWith("`") || exp.EndsWith("'")))
|
||||
{
|
||||
exp = exp.Remove(0, 1);
|
||||
exp = exp.Remove(exp.Length - 1, 1);
|
||||
}
|
||||
return exp;
|
||||
return GetQuotedValue(value, fieldType, EscapeParam, ShouldQuoteValue);
|
||||
}
|
||||
|
||||
private string GetTrueExpression()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
@@ -9,7 +8,7 @@ using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
internal class PocoToSqlExpressionHelper<T>
|
||||
internal class PocoToSqlExpressionHelper<T> : BaseExpressionHelper
|
||||
{
|
||||
private string sep = " ";
|
||||
private Database.PocoData pd;
|
||||
@@ -251,7 +250,7 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
case "ToLower":
|
||||
return string.Format("lower({0})", r);
|
||||
case "StartsWith":
|
||||
return string.Format("upper({0}) like '{1}%'", r, RemoveQuote(args[0].ToString().ToUpper()));
|
||||
return string.Format("upper({0}) like '{1}%'", r, EscapeAtArgument(RemoveQuote(args[0].ToString().ToUpper())));
|
||||
case "EndsWith":
|
||||
return string.Format("upper({0}) like '%{1}'", r, RemoveQuote(args[0].ToString()).ToUpper());
|
||||
case "Contains":
|
||||
@@ -440,53 +439,7 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
|
||||
public virtual string GetQuotedValue(object value, Type fieldType)
|
||||
{
|
||||
if (value == null) return "NULL";
|
||||
|
||||
if (!fieldType.UnderlyingSystemType.IsValueType && fieldType != typeof(string))
|
||||
{
|
||||
//if (TypeSerializer.CanCreateFromString(fieldType))
|
||||
//{
|
||||
// return "'" + EscapeParam(TypeSerializer.SerializeToString(value)) + "'";
|
||||
//}
|
||||
|
||||
throw new NotSupportedException(
|
||||
string.Format("Property of type: {0} is not supported", fieldType.FullName));
|
||||
}
|
||||
|
||||
if (fieldType == typeof(int))
|
||||
return ((int)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(float))
|
||||
return ((float)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(double))
|
||||
return ((double)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof(decimal))
|
||||
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
if (fieldType == typeof (DateTime))
|
||||
{
|
||||
return "'" + EscapeParam(((DateTime)value).ToIsoString()) + "'";
|
||||
}
|
||||
|
||||
|
||||
if (fieldType == typeof(bool))
|
||||
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
|
||||
|
||||
return ShouldQuoteValue(fieldType)
|
||||
? "'" + EscapeParam(value) + "'"
|
||||
: value.ToString();
|
||||
}
|
||||
|
||||
public virtual string EscapeParam(object paramValue)
|
||||
{
|
||||
return paramValue.ToString().Replace("'", "''");
|
||||
}
|
||||
|
||||
public virtual bool ShouldQuoteValue(Type fieldType)
|
||||
{
|
||||
return true;
|
||||
return GetQuotedValue(value, fieldType, EscapeParam, ShouldQuoteValue);
|
||||
}
|
||||
|
||||
protected virtual string GetFieldName(Database.PocoData pocoData, string name)
|
||||
@@ -497,30 +450,6 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(column.Value.ColumnName));
|
||||
}
|
||||
|
||||
protected string RemoveQuote(string exp)
|
||||
{
|
||||
|
||||
if (exp.StartsWith("'") && exp.EndsWith("'"))
|
||||
{
|
||||
exp = exp.Remove(0, 1);
|
||||
exp = exp.Remove(exp.Length - 1, 1);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
protected string RemoveQuoteFromAlias(string exp)
|
||||
{
|
||||
|
||||
if ((exp.StartsWith("\"") || exp.StartsWith("`") || exp.StartsWith("'"))
|
||||
&&
|
||||
(exp.EndsWith("\"") || exp.EndsWith("`") || exp.EndsWith("'")))
|
||||
{
|
||||
exp = exp.Remove(0, 1);
|
||||
exp = exp.Remove(exp.Length - 1, 1);
|
||||
}
|
||||
return exp;
|
||||
}
|
||||
|
||||
private string GetTrueExpression()
|
||||
{
|
||||
object o = GetQuotedTrueValue();
|
||||
|
||||
@@ -275,8 +275,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
protected override void PersistUpdatedItem(IContent entity)
|
||||
{
|
||||
var publishedState = ((Content) entity).PublishedState;
|
||||
//A new version should only be created if published state (or language) has changed
|
||||
bool shouldCreateNewVersion = (((ICanBeDirty)entity).IsPropertyDirty("Published") && publishedState != PublishedState.Unpublished) || ((ICanBeDirty)entity).IsPropertyDirty("Language");
|
||||
|
||||
//check if we need to create a new version
|
||||
bool shouldCreateNewVersion = entity.ShouldCreateNewVersion(publishedState);
|
||||
if (shouldCreateNewVersion)
|
||||
{
|
||||
//Updates Modified date and Version Guid
|
||||
@@ -327,7 +328,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
//If Published state has changed then previous versions should have their publish state reset.
|
||||
//If state has been changed to unpublished the previous versions publish state should also be reset.
|
||||
if (((ICanBeDirty)entity).IsPropertyDirty("Published") && (entity.Published || publishedState == PublishedState.Unpublished))
|
||||
//if (((ICanBeDirty)entity).IsPropertyDirty("Published") && (entity.Published || publishedState == PublishedState.Unpublished))
|
||||
if (entity.ShouldClearPublishedFlagForPreviousVersions(publishedState, shouldCreateNewVersion))
|
||||
{
|
||||
var publishedDocs = Database.Fetch<DocumentDto>("WHERE nodeId = @Id AND published = @IsPublished", new { Id = entity.Id, IsPublished = true });
|
||||
foreach (var doc in publishedDocs)
|
||||
@@ -449,7 +451,19 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
yield return CreateContentFromDto(dto, dto.VersionId);
|
||||
//Check in the cache first. If it exists there AND it is published
|
||||
// then we can use that entity. Otherwise if it is not published (which can be the case
|
||||
// because we only store the 'latest' entries in the cache which might not be the published
|
||||
// version)
|
||||
var fromCache = TryGetFromCache(dto.NodeId);
|
||||
if (fromCache.Success && fromCache.Result.Published)
|
||||
{
|
||||
yield return fromCache.Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return CreateContentFromDto(dto, dto.VersionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +483,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Private method to create a content object from a DocumentDto, which is used by Get and GetByVersion.
|
||||
/// </summary>
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sql = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId).Append(GetGroupBy(isContent, isMedia));
|
||||
var sql = GetBaseWhere(GetBase, isContent, isMedia, string.Empty, objectTypeId).Append(GetGroupBy(isContent, isMedia));
|
||||
var dtos = isMedia
|
||||
? _work.Database.Fetch<UmbracoEntityDto, UmbracoPropertyDto, UmbracoEntityDto>(
|
||||
new UmbracoEntityRelator().Map, sql)
|
||||
@@ -101,7 +101,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetByQuery(IQuery<IUmbracoEntity> query)
|
||||
{
|
||||
var sqlClause = GetBase(false, false);
|
||||
var wheres = string.Concat(" AND ", string.Join(" AND ", ((Query<IUmbracoEntity>) query).WhereClauses()));
|
||||
var sqlClause = GetBase(false, false, wheres);
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var sql = translator.Translate().Append(GetGroupBy(false, false));
|
||||
|
||||
@@ -117,7 +118,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId);
|
||||
|
||||
var wheres = string.Concat(" AND ", string.Join(" AND ", ((Query<IUmbracoEntity>)query).WhereClauses()));
|
||||
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, wheres, objectTypeId);
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var sql = translator.Translate().Append(GetGroupBy(isContent, isMedia));
|
||||
|
||||
@@ -136,7 +139,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
#region Sql Statements
|
||||
|
||||
protected virtual Sql GetBase(bool isContent, bool isMedia)
|
||||
protected virtual Sql GetBase(bool isContent, bool isMedia, string additionWhereStatement = "")
|
||||
{
|
||||
var columns = new List<object>
|
||||
{
|
||||
@@ -187,42 +190,38 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.On("umbracoNode.id = latest.nodeId");
|
||||
}
|
||||
|
||||
/*if (isContent)
|
||||
{
|
||||
sql.LeftJoin(
|
||||
"(SELECT contentNodeId, versionId, dataNvarchar, controlId FROM cmsPropertyData INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid" +
|
||||
" INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId) as property")
|
||||
.On("umbracoNode.id = property.contentNodeId AND latest.versionId = property.versionId");
|
||||
}*/
|
||||
if (isMedia)
|
||||
{
|
||||
sql.LeftJoin(
|
||||
"(SELECT contentNodeId, versionId, dataNvarchar, controlId FROM cmsPropertyData INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid" +
|
||||
" INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId) as property")
|
||||
"(SELECT contentNodeId, versionId, dataNvarchar, controlId FROM cmsPropertyData " +
|
||||
"INNER JOIN umbracoNode ON cmsPropertyData.contentNodeId = umbracoNode.id " +
|
||||
"INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid " +
|
||||
"INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId "+
|
||||
"WHERE umbracoNode.nodeObjectType = '" + Constants.ObjectTypes.Media + "'" + additionWhereStatement + ") as property")
|
||||
.On("umbracoNode.id = property.contentNodeId");
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Sql> baseQuery, bool isContent, bool isMedia, Guid id)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, string additionWhereStatement, Guid id)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia)
|
||||
var sql = baseQuery(isContent, isMedia, additionWhereStatement)
|
||||
.Where("umbracoNode.nodeObjectType = @NodeObjectType", new { NodeObjectType = id });
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Sql> baseQuery, bool isContent, bool isMedia, int id)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, int id)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia)
|
||||
var sql = baseQuery(isContent, isMedia, " AND umbracoNode.id = '"+ id +"'")
|
||||
.Where("umbracoNode.id = @Id", new { Id = id })
|
||||
.Append(GetGroupBy(isContent, isMedia));
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Sql> baseQuery, bool isContent, bool isMedia, Guid objectId, int id)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, Guid objectId, int id)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia)
|
||||
var sql = baseQuery(isContent, isMedia, " AND umbracoNode.id = '"+ id +"'")
|
||||
.Where("umbracoNode.id = @Id AND umbracoNode.nodeObjectType = @NodeObjectType",
|
||||
new {Id = id, NodeObjectType = objectId});
|
||||
return sql;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
|
||||
@@ -15,7 +16,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
IContent GetByLanguage(int id, string language);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all published Content byh the specified query
|
||||
/// Gets all published Content by the specified query
|
||||
/// </summary>
|
||||
/// <param name="query">Query to execute against published versions</param>
|
||||
/// <returns>An enumerable list of <see cref="IContent"/></returns>
|
||||
|
||||
@@ -4,6 +4,5 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IMediaRepository : IRepositoryVersionable<int, IMedia>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a repository specific to the Recycle Bins
|
||||
/// available for Content and Media.
|
||||
/// </summary>
|
||||
internal class RecycleBinRepository : DisposableObject
|
||||
{
|
||||
private readonly IDatabaseUnitOfWork _unitOfWork;
|
||||
|
||||
public RecycleBinRepository(IDatabaseUnitOfWork unitOfWork)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of files, which are referenced on items in the Recycle Bin.
|
||||
/// The list is generated by the convention that a file is referenced by
|
||||
/// the Upload data type or a property type with the alias 'umbracoFile'.
|
||||
/// </summary>
|
||||
/// <param name="nodeObjectType"></param>
|
||||
/// <returns></returns>
|
||||
public List<string> GetFilesInRecycleBin(Guid nodeObjectType)
|
||||
{
|
||||
var db = _unitOfWork.Database;
|
||||
|
||||
//Issue query to get all trashed content or media that has the Upload field as a property
|
||||
//The value for each field is stored in a list: FilesToDelete<string>()
|
||||
//Alias: Constants.Conventions.Media.File and ControlId: Constants.PropertyEditors.UploadField
|
||||
var sql = new Sql();
|
||||
sql.Select("DISTINCT(dataNvarchar)")
|
||||
.From<PropertyDataDto>()
|
||||
.InnerJoin<NodeDto>().On<PropertyDataDto, NodeDto>(left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<PropertyTypeDto>().On<PropertyDataDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
|
||||
.InnerJoin<DataTypeDto>().On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.DataTypeId)
|
||||
.Where("umbracoNode.trashed = '1' AND umbracoNode.nodeObjectType = @NodeObjectType AND dataNvarchar IS NOT NULL AND (cmsPropertyType.Alias = @FileAlias OR cmsDataType.controlId = @ControlId)",
|
||||
new { FileAlias = Constants.Conventions.Media.File, NodeObjectType = nodeObjectType, ControlId = Constants.PropertyEditors.UploadField });
|
||||
|
||||
var files = db.Fetch<string>(sql);
|
||||
return files;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of Ids for each of the items in the Recycle Bin.
|
||||
/// </summary>
|
||||
/// <param name="nodeObjectType"></param>
|
||||
/// <returns></returns>
|
||||
public List<int> GetIdsOfItemsInRecycleBin(Guid nodeObjectType)
|
||||
{
|
||||
var db = _unitOfWork.Database;
|
||||
|
||||
var idsSql = new Sql();
|
||||
idsSql.Select("DISTINCT(id)")
|
||||
.From<NodeDto>()
|
||||
.Where<NodeDto>(x => x.Trashed && x.NodeObjectType == nodeObjectType);
|
||||
|
||||
var ids = db.Fetch<int>(idsSql);
|
||||
return ids;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Empties the Recycle Bin by running single bulk-Delete queries
|
||||
/// against the Content- or Media's Recycle Bin.
|
||||
/// </summary>
|
||||
/// <param name="nodeObjectType"></param>
|
||||
/// <returns></returns>
|
||||
public bool EmptyRecycleBin(Guid nodeObjectType)
|
||||
{
|
||||
var db = _unitOfWork.Database;
|
||||
|
||||
//Construct and execute delete statements for all trashed items by 'nodeObjectType'
|
||||
var deletes = new List<string>
|
||||
{
|
||||
FormatDeleteStatement("umbracoUser2NodeNotify", "nodeId"),
|
||||
FormatDeleteStatement("umbracoUser2NodePermission", "nodeId"),
|
||||
FormatDeleteStatement("umbracoRelation", "parentId"),
|
||||
FormatDeleteStatement("umbracoRelation", "childId"),
|
||||
FormatDeleteStatement("cmsTagRelationship", "nodeId"),
|
||||
FormatDeleteStatement("umbracoDomains", "domainRootStructureID"),
|
||||
FormatDeleteStatement("cmsDocument", "NodeId"),
|
||||
FormatDeleteStatement("cmsPropertyData", "contentNodeId"),
|
||||
FormatDeleteStatement("cmsPreviewXml", "nodeId"),
|
||||
FormatDeleteStatement("cmsContentVersion", "ContentId"),
|
||||
FormatDeleteStatement("cmsContentXml", "nodeID"),
|
||||
FormatDeleteStatement("cmsContent", "NodeId"),
|
||||
"UPDATE umbracoNode SET parentID = '-20' WHERE trashed = '1' AND nodeObjectType = @NodeObjectType",
|
||||
"DELETE FROM umbracoNode WHERE trashed = '1' AND nodeObjectType = @NodeObjectType"
|
||||
};
|
||||
|
||||
//Wraps in transaction - this improves performance and also ensures
|
||||
// that if any of the deletions fails that the whole thing is rolled back.
|
||||
using (var trans = db.GetTransaction())
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var delete in deletes)
|
||||
{
|
||||
db.Execute(delete, new { NodeObjectType = nodeObjectType });
|
||||
}
|
||||
|
||||
trans.Complete();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
trans.Dispose();
|
||||
LogHelper.Error<RecycleBinRepository>("An error occurred while emptying the Recycle Bin: " + ex.Message, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all files passed in.
|
||||
/// </summary>
|
||||
/// <param name="files"></param>
|
||||
/// <returns></returns>
|
||||
public bool DeleteFiles(IEnumerable<string> files)
|
||||
{
|
||||
try
|
||||
{
|
||||
var fs = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>();
|
||||
Parallel.ForEach(files, file =>
|
||||
{
|
||||
if (UmbracoSettings.UploadAllowDirectories)
|
||||
{
|
||||
var relativeFilePath = fs.GetRelativePath(file);
|
||||
var parentDirectory = System.IO.Path.GetDirectoryName(relativeFilePath);
|
||||
fs.DeleteDirectory(parentDirectory, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
fs.DeleteFile(file, true);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<RecycleBinRepository>("An error occurred while deleting files attached to deleted nodes: " + ex.Message, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private string FormatDeleteStatement(string tableName, string keyName)
|
||||
{
|
||||
//This query works with sql ce and sql server:
|
||||
//DELETE FROM umbracoUser2NodeNotify WHERE umbracoUser2NodeNotify.nodeId IN
|
||||
//(SELECT nodeId FROM umbracoUser2NodeNotify as TB1 INNER JOIN umbracoNode as TB2 ON TB1.nodeId = TB2.id WHERE TB2.trashed = '1' AND TB2.nodeObjectType = 'C66BA18E-EAF3-4CFF-8A22-41B16D66A972')
|
||||
return
|
||||
string.Format(
|
||||
"DELETE FROM {0} WHERE {0}.{1} IN (SELECT TB1.{1} FROM {0} as TB1 INNER JOIN umbracoNode as TB2 ON TB1.{1} = TB2.id WHERE TB2.trashed = '1' AND TB2.nodeObjectType = @NodeObjectType)",
|
||||
tableName, keyName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose disposable properties
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Ensure the unit of work is disposed
|
||||
/// </remarks>
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
_unitOfWork.DisposeIfDisposable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,11 +85,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <returns></returns>
|
||||
public TEntity Get(TId id)
|
||||
{
|
||||
Guid key = id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString());
|
||||
var rEntity = _cache.GetById(typeof(TEntity), key);
|
||||
if (rEntity != null)
|
||||
var fromCache = TryGetFromCache(id);
|
||||
if (fromCache.Success)
|
||||
{
|
||||
return (TEntity)rEntity;
|
||||
return fromCache.Result;
|
||||
}
|
||||
|
||||
var entity = PerformGet(id);
|
||||
@@ -112,6 +111,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return entity;
|
||||
}
|
||||
|
||||
protected Attempt<TEntity> TryGetFromCache(TId id)
|
||||
{
|
||||
Guid key = id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString());
|
||||
var rEntity = _cache.GetById(typeof(TEntity), key);
|
||||
if (rEntity != null)
|
||||
{
|
||||
return new Attempt<TEntity>(true, (TEntity) rEntity);
|
||||
}
|
||||
return Attempt<TEntity>.False;
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<TEntity> PerformGetAll(params TId[] ids);
|
||||
/// <summary>
|
||||
/// Gets all entities of type TEntity or a list according to the passed in Ids
|
||||
@@ -173,14 +183,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <returns></returns>
|
||||
public bool Exists(TId id)
|
||||
{
|
||||
Guid key = id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString());
|
||||
var rEntity = _cache.GetById(typeof(TEntity), key);
|
||||
if (rEntity != null)
|
||||
var fromCache = TryGetFromCache(id);
|
||||
if (fromCache.Success)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return PerformExists(id);
|
||||
return PerformExists(id);
|
||||
}
|
||||
|
||||
protected abstract int PerformCount(IQuery<TEntity> query);
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public int Compare(string x, string y)
|
||||
{
|
||||
if (x.LastIndexOf(')') == x.Length - 1 && y.LastIndexOf(')') == y.Length - 1)
|
||||
if (x.LastIndexOf('(') != -1 && x.LastIndexOf(')') == x.Length - 1 && y.LastIndexOf(')') == y.Length - 1)
|
||||
{
|
||||
if (x.ToLower().Substring(0, x.LastIndexOf('(')) == y.ToLower().Substring(0, y.LastIndexOf('(')))
|
||||
{
|
||||
|
||||
@@ -9,34 +9,6 @@ namespace Umbraco.Core.Persistence
|
||||
/// </summary>
|
||||
public class RepositoryFactory
|
||||
{
|
||||
|
||||
internal virtual ServerRegistrationRepository CreateServerRegistrationRepository(IDatabaseUnitOfWork uow)
|
||||
{
|
||||
return new ServerRegistrationRepository(
|
||||
uow,
|
||||
NullCacheProvider.Current);
|
||||
}
|
||||
|
||||
internal virtual IUserTypeRepository CreateUserTypeRepository(IDatabaseUnitOfWork uow)
|
||||
{
|
||||
return new UserTypeRepository(
|
||||
uow,
|
||||
NullCacheProvider.Current);
|
||||
}
|
||||
|
||||
internal virtual IUserRepository CreateUserRepository(IDatabaseUnitOfWork uow)
|
||||
{
|
||||
return new UserRepository(
|
||||
uow,
|
||||
NullCacheProvider.Current,
|
||||
CreateUserTypeRepository(uow));
|
||||
}
|
||||
|
||||
internal virtual IEntityRepository CreateEntityRepository(IDatabaseUnitOfWork uow)
|
||||
{
|
||||
return new EntityRepository(uow);
|
||||
}
|
||||
|
||||
public virtual IContentRepository CreateContentRepository(IDatabaseUnitOfWork uow)
|
||||
{
|
||||
return new ContentRepository(
|
||||
@@ -120,5 +92,37 @@ namespace Umbraco.Core.Persistence
|
||||
{
|
||||
return new TemplateRepository(uow, RuntimeCacheProvider.Current);
|
||||
}
|
||||
|
||||
internal virtual ServerRegistrationRepository CreateServerRegistrationRepository(IDatabaseUnitOfWork uow)
|
||||
{
|
||||
return new ServerRegistrationRepository(
|
||||
uow,
|
||||
NullCacheProvider.Current);
|
||||
}
|
||||
|
||||
internal virtual IUserTypeRepository CreateUserTypeRepository(IDatabaseUnitOfWork uow)
|
||||
{
|
||||
return new UserTypeRepository(
|
||||
uow,
|
||||
NullCacheProvider.Current);
|
||||
}
|
||||
|
||||
internal virtual IUserRepository CreateUserRepository(IDatabaseUnitOfWork uow)
|
||||
{
|
||||
return new UserRepository(
|
||||
uow,
|
||||
NullCacheProvider.Current,
|
||||
CreateUserTypeRepository(uow));
|
||||
}
|
||||
|
||||
internal virtual IEntityRepository CreateEntityRepository(IDatabaseUnitOfWork uow)
|
||||
{
|
||||
return new EntityRepository(uow);
|
||||
}
|
||||
|
||||
internal virtual RecycleBinRepository CreateRecycleBinRepository(IDatabaseUnitOfWork uow)
|
||||
{
|
||||
return new RecycleBinRepository(uow);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,20 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
public static ISqlSyntaxProvider Provider { get { return new SqlServerSyntaxProvider(); } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the version name of SQL server (i.e. the year 2008, 2005, etc...)
|
||||
/// </summary>
|
||||
internal enum SqlServerVersionName
|
||||
{
|
||||
Invalid = -1,
|
||||
V7 = 0,
|
||||
V2000 = 1,
|
||||
V2005 = 2,
|
||||
V2008 = 3,
|
||||
V2012 = 4,
|
||||
Other = 5
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an SqlSyntaxProvider for Sql Server
|
||||
/// </summary>
|
||||
@@ -36,6 +50,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax
|
||||
InitColumnTypeMap();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the version of the current SQL server instance
|
||||
/// </summary>
|
||||
internal Lazy<SqlServerVersionName> VersionName { get; set; }
|
||||
|
||||
public override string GetQuotedTableName(string tableName)
|
||||
{
|
||||
return string.Format("[{0}]", tableName);
|
||||
|
||||
@@ -20,7 +20,6 @@ using File = System.IO.File;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Used to resolve all plugin types and cache them and is also used to instantiate plugin types
|
||||
/// </summary>
|
||||
@@ -37,6 +36,7 @@ namespace Umbraco.Core
|
||||
internal class PluginManager
|
||||
{
|
||||
private readonly ApplicationContext _appContext;
|
||||
private const string CacheKey = "umbraco-plugins.list";
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new PluginManager with an ApplicationContext instance which ensures that the plugin xml
|
||||
@@ -251,7 +251,7 @@ namespace Umbraco.Core
|
||||
XDocument xml;
|
||||
if (_appContext != null)
|
||||
{
|
||||
xml = _appContext.ApplicationCache.GetCacheItem("umbraco-plugins.list",
|
||||
xml = _appContext.ApplicationCache.GetCacheItem(CacheKey,
|
||||
new TimeSpan(0, 0, 5, 0),
|
||||
() => XDocument.Load(filePath));
|
||||
}
|
||||
@@ -304,18 +304,18 @@ namespace Umbraco.Core
|
||||
|
||||
if (_appContext != null)
|
||||
{
|
||||
_appContext.ApplicationCache.ClearCacheItem("umbraco-plugins.list");
|
||||
_appContext.ApplicationCache.ClearCacheItem(CacheKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string GetPluginListFilePath()
|
||||
{
|
||||
return Path.Combine(_tempFolder, "umbraco-plugins.list");
|
||||
return Path.Combine(_tempFolder, string.Format("umbraco-plugins.{0}.list", NetworkHelper.FileSafeMachineName));
|
||||
}
|
||||
|
||||
private string GetPluginHashFilePath()
|
||||
{
|
||||
return Path.Combine(_tempFolder, "umbraco-plugins.hash");
|
||||
return Path.Combine(_tempFolder, string.Format("umbraco-plugins.{0}.hash", NetworkHelper.FileSafeMachineName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -8,15 +8,14 @@ namespace Umbraco.Core.Publishing
|
||||
/// </summary>
|
||||
internal class PublishStatus
|
||||
{
|
||||
public IContent ContentItem { get; private set; }
|
||||
public PublishStatusType StatusType { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets sets the invalid properties if the status failed due to validation.
|
||||
/// </summary>
|
||||
public IEnumerable<Property> InvalidProperties { get; set; }
|
||||
public PublishStatus()
|
||||
{
|
||||
//initialize
|
||||
InvalidProperties = new List<Property>();
|
||||
}
|
||||
|
||||
public PublishStatus(IContent content, PublishStatusType statusType)
|
||||
: this()
|
||||
{
|
||||
ContentItem = content;
|
||||
StatusType = statusType;
|
||||
@@ -29,6 +28,13 @@ namespace Umbraco.Core.Publishing
|
||||
: this(content, PublishStatusType.Success)
|
||||
{
|
||||
}
|
||||
|
||||
public IContent ContentItem { get; private set; }
|
||||
public PublishStatusType StatusType { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets sets the invalid properties if the status failed due to validation.
|
||||
/// </summary>
|
||||
public IEnumerable<Property> InvalidProperties { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
internal static class FormsAuthenticationTicketExtensions
|
||||
{
|
||||
public static UmbracoBackOfficeIdentity CreateUmbracoIdentity(this FormsAuthenticationTicket ticket)
|
||||
{
|
||||
try
|
||||
{
|
||||
//create the Umbraco user identity
|
||||
return new UmbracoBackOfficeIdentity(ticket);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//This might occur if we cannot decrypt the value in which case we'll just ignore it, it will
|
||||
// be handled by the base pages
|
||||
LogHelper.Error(typeof(FormsAuthenticationTicketExtensions), "An error occurred decrypting the user's ticket", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extensions to create and renew and remove authentication tickets for the Umbraco back office
|
||||
/// </summary>
|
||||
internal static class AuthenticationExtensions
|
||||
{
|
||||
//public static UmbracoBackOfficeIdentity GetCurrentIdentity(this HttpContextBase http)
|
||||
//{
|
||||
// return http.User.Identity as UmbracoBackOfficeIdentity;
|
||||
//}
|
||||
|
||||
//internal static UmbracoBackOfficeIdentity GetCurrentIdentity(this HttpContext http)
|
||||
//{
|
||||
// return new HttpContextWrapper(http).GetCurrentIdentity();
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// This clears the authentication cookie
|
||||
/// </summary>
|
||||
public static void UmbracoLogout(this HttpContextBase http)
|
||||
{
|
||||
Logout(http, UmbracoSettings.AuthCookieName);
|
||||
}
|
||||
|
||||
internal static void UmbracoLogout(this HttpContext http)
|
||||
{
|
||||
new HttpContextWrapper(http).UmbracoLogout();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the umbraco authentication ticket
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <param name="userdata"></param>
|
||||
public static void CreateUmbracoAuthTicket(this HttpContextBase http, UserData userdata)
|
||||
{
|
||||
CreateAuthTicket(
|
||||
http,
|
||||
userdata,
|
||||
//This is one full day... this is how Umbraco has always created this cookie, it is setup to always
|
||||
//expire one day from issue and it never gets updated.
|
||||
1440,
|
||||
"/",
|
||||
UmbracoSettings.AuthCookieName,
|
||||
UmbracoSettings.AuthCookieDomain);
|
||||
}
|
||||
|
||||
internal static void CreateUmbracoAuthTicket(this HttpContext http, UserData userdata)
|
||||
{
|
||||
new HttpContextWrapper(http).CreateUmbracoAuthTicket(userdata);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the umbraco auth ticket
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <returns></returns>
|
||||
public static FormsAuthenticationTicket GetUmbracoAuthTicket(this HttpContextBase http)
|
||||
{
|
||||
return GetAuthTicket(http, UmbracoSettings.AuthCookieName);
|
||||
}
|
||||
|
||||
internal static FormsAuthenticationTicket GetUmbracoAuthTicket(this HttpContext http)
|
||||
{
|
||||
return new HttpContextWrapper(http).GetUmbracoAuthTicket();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This clears the authentication cookie
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <param name="cookieName"></param>
|
||||
private static void Logout(this HttpContextBase http, string cookieName)
|
||||
{
|
||||
//remove from the request
|
||||
http.Request.Cookies.Remove(cookieName);
|
||||
|
||||
//expire from the response
|
||||
var formsCookie = http.Response.Cookies[cookieName];
|
||||
if (formsCookie != null)
|
||||
{
|
||||
//this will expire immediately and be removed from the browser
|
||||
formsCookie.Expires = DateTime.Now.AddYears(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//ensure there's def an expired cookie
|
||||
http.Response.Cookies.Add(new HttpCookie(cookieName) { Expires = DateTime.Now.AddYears(-1) });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// In v6 this is a custom cookie, in v7 this is a real formsauth cookie.
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <param name="cookieName"></param>
|
||||
/// <returns></returns>
|
||||
private static FormsAuthenticationTicket GetAuthTicket(this HttpContextBase http, string cookieName)
|
||||
{
|
||||
var formsCookie = http.Request.Cookies[cookieName];
|
||||
if (formsCookie == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
//get the cookie value
|
||||
var cookieVal = formsCookie.Value.DecryptWithMachineKey();
|
||||
|
||||
//here we need to see if the cookie val can be serialized into UserData, if not it means it's probably an old cookie
|
||||
var deserialized = JsonConvert.DeserializeObject<UserData>(cookieVal);
|
||||
|
||||
//in v6, we're not using real FormsAuth but our own custom cookie and then we just return a custom FormsAuth ticket
|
||||
// for this request.
|
||||
return new FormsAuthenticationTicket(
|
||||
4,
|
||||
deserialized.RealName,
|
||||
DateTime.Now,
|
||||
DateTime.Now.AddMinutes(GlobalSettings.TimeOutInMinutes),
|
||||
false,
|
||||
cookieVal,
|
||||
"/");
|
||||
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//occurs when decryption fails
|
||||
http.Logout(cookieName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a custom umbraco auth cookie with the data specified
|
||||
/// </summary>
|
||||
/// <param name="http">The HTTP.</param>
|
||||
/// <param name="userData">The user data.</param>
|
||||
/// <param name="minutesPersisted">The minutes persisted.</param>
|
||||
/// <param name="cookiePath">The cookie path.</param>
|
||||
/// <param name="cookieName">Name of the cookie.</param>
|
||||
/// <param name="cookieDomain">The cookie domain.</param>
|
||||
private static void CreateAuthTicket(this HttpContextBase http,
|
||||
UserData userData,
|
||||
int minutesPersisted,
|
||||
string cookiePath,
|
||||
string cookieName,
|
||||
string cookieDomain)
|
||||
{
|
||||
var cookie = new HttpCookie(cookieName);
|
||||
|
||||
if (GlobalSettings.UseSSL)
|
||||
cookie.Secure = true;
|
||||
|
||||
//ensure http only, this should only be able to be accessed via the server
|
||||
cookie.HttpOnly = true;
|
||||
cookie.Path = cookiePath;
|
||||
cookie.Domain = cookieDomain;
|
||||
cookie.Expires = DateTime.Now.AddMinutes(minutesPersisted);
|
||||
|
||||
//serialize the user data
|
||||
var json = JsonConvert.SerializeObject(userData);
|
||||
//encrypt it
|
||||
var encTicket = json.EncryptWithMachineKey();
|
||||
|
||||
//set the cookie value
|
||||
cookie.Value = encTicket;
|
||||
|
||||
http.Response.Cookies.Set(cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// A custom user identity for the Umbraco backoffice
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// All values are lazy loaded for performance reasons as the constructor is called for every single request
|
||||
/// </remarks>
|
||||
internal class UmbracoBackOfficeIdentity : FormsIdentity
|
||||
{
|
||||
public UmbracoBackOfficeIdentity(FormsAuthenticationTicket ticket)
|
||||
: base(ticket)
|
||||
{
|
||||
UserData = ticket.UserData;
|
||||
EnsureDeserialized();
|
||||
}
|
||||
|
||||
protected readonly string UserData;
|
||||
internal UserData DeserializedData;
|
||||
|
||||
public string UserContextId
|
||||
{
|
||||
get { return DeserializedData.UserContextId; }
|
||||
}
|
||||
|
||||
public int StartContentNode
|
||||
{
|
||||
get { return DeserializedData.StartContentNode; }
|
||||
}
|
||||
|
||||
public int StartMediaNode
|
||||
{
|
||||
get { return DeserializedData.StartMediaNode; }
|
||||
}
|
||||
|
||||
public string[] AllowedApplications
|
||||
{
|
||||
get { return DeserializedData.AllowedApplications; }
|
||||
}
|
||||
|
||||
public object Id
|
||||
{
|
||||
get { return DeserializedData.Id; }
|
||||
}
|
||||
|
||||
public string RealName
|
||||
{
|
||||
get { return DeserializedData.RealName; }
|
||||
}
|
||||
|
||||
public string Culture
|
||||
{
|
||||
get { return DeserializedData.Culture; }
|
||||
}
|
||||
|
||||
//public int SessionTimeout
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// EnsureDeserialized();
|
||||
// return DeserializedData.SessionTimeout;
|
||||
// }
|
||||
//}
|
||||
|
||||
public string[] Roles
|
||||
{
|
||||
get { return DeserializedData.Roles; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will ensure we only deserialize once
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For performance reasons, we'll also check if there's an http context available,
|
||||
/// if so, we'll chuck our instance in there so that we only deserialize once per request.
|
||||
/// </remarks>
|
||||
protected void EnsureDeserialized()
|
||||
{
|
||||
if (DeserializedData != null)
|
||||
return;
|
||||
|
||||
if (HttpContext.Current != null)
|
||||
{
|
||||
//check if we've already done this in this request
|
||||
var data = HttpContext.Current.Items[typeof(UmbracoBackOfficeIdentity)] as UserData;
|
||||
if (data != null)
|
||||
{
|
||||
DeserializedData = data;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(UserData))
|
||||
{
|
||||
throw new NullReferenceException("The " + typeof(UserData) + " found in the ticket cannot be empty");
|
||||
}
|
||||
DeserializedData = JsonConvert.DeserializeObject<UserData>(UserData);
|
||||
|
||||
if (HttpContext.Current != null)
|
||||
{
|
||||
HttpContext.Current.Items[typeof (UmbracoBackOfficeIdentity)] = DeserializedData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// Data structure used to store information in the authentication cookie
|
||||
/// </summary>
|
||||
[DataContract(Name = "userData", Namespace = "")]
|
||||
internal class UserData
|
||||
{
|
||||
public UserData()
|
||||
{
|
||||
AllowedApplications = new string[] {};
|
||||
Roles = new string[] {};
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// When their session is going to expire (in ticks)
|
||||
///// </summary>
|
||||
//[DataMember(Name = "timeout")]
|
||||
//public long Timeout { get; set; }
|
||||
|
||||
[DataMember(Name = "userContextId")]
|
||||
public string UserContextId { get; set; }
|
||||
|
||||
[DataMember(Name = "id")]
|
||||
public object Id { get; set; }
|
||||
|
||||
[DataMember(Name = "roles")]
|
||||
public string[] Roles { get; set; }
|
||||
|
||||
[DataMember(Name = "username")]
|
||||
public string Username { get; set; }
|
||||
|
||||
[DataMember(Name = "name")]
|
||||
public string RealName { get; set; }
|
||||
|
||||
[DataMember(Name = "startContent")]
|
||||
public int StartContentNode { get; set; }
|
||||
|
||||
[DataMember(Name = "startMedia")]
|
||||
public int StartMediaNode { get; set; }
|
||||
|
||||
[DataMember(Name = "allowedApps")]
|
||||
public string[] AllowedApplications { get; set; }
|
||||
|
||||
[DataMember(Name = "culture")]
|
||||
public string Culture { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Publishing;
|
||||
|
||||
@@ -250,6 +251,17 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<IContent> GetPublishedContentOfContentType(int id)
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
var query = Query<IContent>.Builder.Where(x => x.ContentTypeId == id);
|
||||
var contents = repository.GetByPublishedVersion(query);
|
||||
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of <see cref="IContent"/> objects by Level
|
||||
/// </summary>
|
||||
@@ -431,6 +443,19 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all published content items
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal IEnumerable<IContent> GetAllPublished()
|
||||
{
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
var query = Query<IContent>.Builder.Where(x => x.Trashed == false);
|
||||
return repository.GetByPublishedVersion(query);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of <see cref="IContent"/> objects, which has an expiration date less than or equal to today.
|
||||
/// </summary>
|
||||
@@ -986,27 +1011,29 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public void EmptyRecycleBin()
|
||||
{
|
||||
//TODO: Why don't we have a base class to share between MediaService/ContentService as some of this is exacty the same?
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(uow))
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var query = Query<IContent>.Builder.Where(x => x.Trashed == true);
|
||||
var contents = repository.GetByQuery(query).OrderByDescending(x => x.Level);
|
||||
List<int> ids;
|
||||
List<string> files;
|
||||
bool success;
|
||||
var nodeObjectType = new Guid(Constants.ObjectTypes.Document);
|
||||
|
||||
foreach (var content in contents)
|
||||
using (var repository = _repositoryFactory.CreateRecycleBinRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IContent>(content), this))
|
||||
continue;
|
||||
ids = repository.GetIdsOfItemsInRecycleBin(nodeObjectType);
|
||||
files = repository.GetFilesInRecycleBin(nodeObjectType);
|
||||
|
||||
repository.Delete(content);
|
||||
if (EmptyingRecycleBin.IsRaisedEventCancelled(new RecycleBinEventArgs(nodeObjectType, ids, files), this))
|
||||
return;
|
||||
|
||||
Deleted.RaiseEvent(new DeleteEventArgs<IContent>(content, false), this);
|
||||
success = repository.EmptyRecycleBin(nodeObjectType);
|
||||
if (success)
|
||||
repository.DeleteFiles(files);
|
||||
}
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
Audit.Add(AuditTypes.Delete, "Empty Recycle Bin performed by user", 0, -20);
|
||||
EmptiedRecycleBin.RaiseEvent(new RecycleBinEventArgs(nodeObjectType, ids, files, success), this);
|
||||
}
|
||||
Audit.Add(AuditTypes.Delete, "Empty Content Recycle Bin performed by user", 0, -20);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1353,46 +1380,45 @@ namespace Umbraco.Core.Services
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentRepository(uow))
|
||||
{
|
||||
if (contentTypeIds.Any() == false)
|
||||
{
|
||||
//Remove all Document records from the cmsContentXml table (DO NOT REMOVE Media/Members!)
|
||||
uow.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
|
||||
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
|
||||
INNER JOIN cmsDocument ON cmsContentXml.nodeId = cmsDocument.nodeId)");
|
||||
|
||||
//get all content items that are published
|
||||
// Consider creating a Path query instead of recursive method:
|
||||
// var query = Query<IContent>.Builder.Where(x => x.Path.StartsWith("-1"));
|
||||
var rootContent = GetRootContent();
|
||||
foreach (var content in rootContent.Where(content => content.Published))
|
||||
{
|
||||
list.Add(content);
|
||||
list.AddRange(GetPublishedDescendants(content));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var id in contentTypeIds)
|
||||
{
|
||||
//first we'll clear out the data from the cmsContentXml table for this type
|
||||
uow.Database.Execute(@"delete from cmsContentXml where nodeId in
|
||||
(select cmsDocument.nodeId from cmsDocument
|
||||
inner join cmsContent on cmsDocument.nodeId = cmsContent.nodeId
|
||||
where published = 1 and contentType = @contentTypeId)", new {contentTypeId = id});
|
||||
//First we're going to get the data that needs to be inserted before clearing anything, this
|
||||
//ensures that we don't accidentally leave the content xml table empty if something happens
|
||||
//during the lookup process.
|
||||
|
||||
//now get all published content objects of this type and add to the list
|
||||
list.AddRange(GetContentOfContentType(id).Where(content => content.Published));
|
||||
}
|
||||
}
|
||||
list.AddRange(contentTypeIds.Any() == false
|
||||
? GetAllPublished()
|
||||
: contentTypeIds.SelectMany(GetPublishedContentOfContentType));
|
||||
|
||||
var xmlItems = new List<ContentXmlDto>();
|
||||
foreach (var c in list)
|
||||
{
|
||||
//generate the xml
|
||||
var xml = c.ToXml();
|
||||
//create the dto to insert
|
||||
var poco = new ContentXmlDto { NodeId = c.Id, Xml = xml.ToString(SaveOptions.None) };
|
||||
//insert it into the database
|
||||
uow.Database.Insert(poco);
|
||||
xmlItems.Add(new ContentXmlDto {NodeId = c.Id, Xml = xml.ToString(SaveOptions.None)});
|
||||
}
|
||||
|
||||
//Ok, now we need to remove the data and re-insert it, we'll do this all in one transaction too.
|
||||
using (var tr = uow.Database.GetTransaction())
|
||||
{
|
||||
if (contentTypeIds.Any() == false)
|
||||
{
|
||||
//Remove all Document records from the cmsContentXml table (DO NOT REMOVE Media/Members!)
|
||||
uow.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
|
||||
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
|
||||
INNER JOIN cmsDocument ON cmsContentXml.nodeId = cmsDocument.nodeId)");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var id in contentTypeIds)
|
||||
{
|
||||
//first we'll clear out the data from the cmsContentXml table for this type
|
||||
uow.Database.Execute(@"delete from cmsContentXml where nodeId in
|
||||
(select cmsDocument.nodeId from cmsDocument
|
||||
inner join cmsContent on cmsDocument.nodeId = cmsContent.nodeId
|
||||
where published = 1 and contentType = @contentTypeId)", new { contentTypeId = id });
|
||||
}
|
||||
}
|
||||
|
||||
//bulk insert it into the database
|
||||
uow.Database.BulkInsertRecords(xmlItems, tr);
|
||||
}
|
||||
}
|
||||
Audit.Add(AuditTypes.Publish, "RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
|
||||
@@ -1436,7 +1462,12 @@ namespace Umbraco.Core.Services
|
||||
LogHelper.Info<ContentService>(
|
||||
string.Format("Content '{0}' with Id '{1}' could not be published because of invalid properties.",
|
||||
content.Name, content.Id));
|
||||
result.Add(new Attempt<PublishStatus>(false, new PublishStatus(content, PublishStatusType.FailedContentInvalid)));
|
||||
result.Add(
|
||||
new Attempt<PublishStatus>(false,
|
||||
new PublishStatus(content, PublishStatusType.FailedContentInvalid)
|
||||
{
|
||||
InvalidProperties = ((ContentBase) content).LastInvalidProperties
|
||||
}));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1854,7 +1885,7 @@ namespace Umbraco.Core.Services
|
||||
/// Occurs after Create
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Please note that the Content object has been created, but not saved
|
||||
/// Please note that the Content object has been created, but might not have been saved
|
||||
/// so it does not have an identity yet (meaning no Id has been set).
|
||||
/// </remarks>
|
||||
public static event TypedEventHandler<IContentService, NewEventArgs<IContent>> Created;
|
||||
@@ -1908,6 +1939,16 @@ namespace Umbraco.Core.Services
|
||||
/// Occurs after Send to Publish
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentService, SendToPublishEventArgs<IContent>> SentToPublish;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before the Recycle Bin is emptied
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentService, RecycleBinEventArgs> EmptyingRecycleBin;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after the Recycle Bin has been Emptied
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentService, RecycleBinEventArgs> EmptiedRecycleBin;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,11 @@ using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Publishing;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Represents the Media Service, which is an easy access to operations involving <see cref="IMedia"/>
|
||||
/// </summary>
|
||||
public class MediaService : IMediaService
|
||||
@@ -536,27 +537,29 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public void EmptyRecycleBin()
|
||||
{
|
||||
//TODO: Why don't we have a base class to share between MediaService/ContentService as some of this is exacty the same?
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
List<int> ids;
|
||||
List<string> files;
|
||||
bool success;
|
||||
var nodeObjectType = new Guid(Constants.ObjectTypes.Media);
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(uow))
|
||||
{
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Trashed == true);
|
||||
var contents = repository.GetByQuery(query).OrderByDescending(x => x.Level);
|
||||
using (var repository = _repositoryFactory.CreateRecycleBinRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
ids = repository.GetIdsOfItemsInRecycleBin(nodeObjectType);
|
||||
files = repository.GetFilesInRecycleBin(nodeObjectType);
|
||||
|
||||
foreach (var content in contents)
|
||||
{
|
||||
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IMedia>(content), this))
|
||||
continue;
|
||||
if (EmptyingRecycleBin.IsRaisedEventCancelled(new RecycleBinEventArgs(nodeObjectType, ids, files), this))
|
||||
return;
|
||||
|
||||
repository.Delete(content);
|
||||
success = repository.EmptyRecycleBin(nodeObjectType);
|
||||
if (success)
|
||||
repository.DeleteFiles(files);
|
||||
}
|
||||
|
||||
Deleted.RaiseEvent(new DeleteEventArgs<IMedia>(content, false), this);
|
||||
}
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
Audit.Add(AuditTypes.Delete, "Empty Recycle Bin performed by user", 0, -20);
|
||||
EmptiedRecycleBin.RaiseEvent(new RecycleBinEventArgs(nodeObjectType, ids, files, success), this);
|
||||
}
|
||||
Audit.Add(AuditTypes.Delete, "Empty Media Recycle Bin performed by user", 0, -21);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -875,15 +878,16 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
var xmlItems = new List<ContentXmlDto>();
|
||||
foreach (var c in list)
|
||||
{
|
||||
//generate the xml
|
||||
var xml = c.ToXml();
|
||||
//create the dto to insert
|
||||
var poco = new ContentXmlDto { NodeId = c.Id, Xml = xml.ToString(SaveOptions.None) };
|
||||
//insert it into the database
|
||||
uow.Database.Insert(poco);
|
||||
xmlItems.Add(new ContentXmlDto { NodeId = c.Id, Xml = xml.ToString(SaveOptions.None) });
|
||||
}
|
||||
//bulk insert it into the database
|
||||
uow.Database.BulkInsertRecords(xmlItems);
|
||||
}
|
||||
Audit.Add(AuditTypes.Publish, "RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
|
||||
}
|
||||
@@ -1009,6 +1013,16 @@ namespace Umbraco.Core.Services
|
||||
/// Occurs after Move
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IMediaService, MoveEventArgs<IMedia>> Moved;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before the Recycle Bin is emptied
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IMediaService, RecycleBinEventArgs> EmptyingRecycleBin;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after the Recycle Bin has been Emptied
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IMediaService, RecycleBinEventArgs> EmptiedRecycleBin;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -43,13 +43,13 @@ namespace Umbraco.Core.Services
|
||||
public IProfile GetProfileById(int id)
|
||||
{
|
||||
var user = GetUserById(id);
|
||||
return new Profile(user.Id, user.Username);
|
||||
return new Profile(user.Id, user.Name);
|
||||
}
|
||||
|
||||
public IProfile GetProfileByUserName(string username)
|
||||
{
|
||||
var user = GetUserByUserName(username);
|
||||
return new Profile(user.Id, user.Username);
|
||||
return new Profile(user.Id, user.Name);
|
||||
}
|
||||
|
||||
public IUser GetUserByUserName(string username)
|
||||
|
||||
@@ -28,6 +28,27 @@ namespace Umbraco.Core
|
||||
[UmbracoWillObsolete("Do not use this constants. See IShortStringHelper.CleanStringForSafeAliasJavaScriptCode.")]
|
||||
public const string UmbracoInvalidFirstCharacters = "01234567890";
|
||||
|
||||
internal static string ReplaceNonAlphanumericChars(this string input, char replacement)
|
||||
{
|
||||
//any character that is not alphanumeric, convert to a hyphen
|
||||
var mName = input;
|
||||
foreach (var c in mName.ToCharArray().Where(c => !char.IsLetterOrDigit(c)))
|
||||
{
|
||||
mName = mName.Replace(c, replacement);
|
||||
}
|
||||
return mName;
|
||||
}
|
||||
|
||||
public static string ExceptChars(this string str, HashSet<char> toExclude)
|
||||
{
|
||||
var sb = new StringBuilder(str.Length);
|
||||
foreach (var c in str.Where(c => toExclude.Contains(c) == false))
|
||||
{
|
||||
sb.Append(c);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypt the string using the MachineKey in medium trust
|
||||
/// </summary>
|
||||
|
||||
@@ -156,6 +156,7 @@
|
||||
<Compile Include="Events\EventExtensions.cs" />
|
||||
<Compile Include="Events\MigrationEventArgs.cs" />
|
||||
<Compile Include="Events\PublishEventArgs.cs" />
|
||||
<Compile Include="Events\RecycleBinEventArgs.cs" />
|
||||
<Compile Include="Events\TypedEventHandler.cs" />
|
||||
<Compile Include="Events\MoveEventArgs.cs" />
|
||||
<Compile Include="Events\NewEventArgs.cs" />
|
||||
@@ -237,6 +238,7 @@
|
||||
<Compile Include="Models\UmbracoEntity.cs" />
|
||||
<Compile Include="Models\UmbracoObjectTypes.cs" />
|
||||
<Compile Include="Models\UmbracoObjectTypesExtensions.cs" />
|
||||
<Compile Include="NetworkHelper.cs" />
|
||||
<Compile Include="ObjectResolution\ApplicationEventsResolver.cs" />
|
||||
<Compile Include="ObjectResolution\ResolverCollection.cs" />
|
||||
<Compile Include="Persistence\Caching\InMemoryCacheProvider.cs" />
|
||||
@@ -458,6 +460,7 @@
|
||||
<Compile Include="Persistence\PetaPocoConnectionExtensions.cs" />
|
||||
<Compile Include="Persistence\PetaPocoExtensions.cs" />
|
||||
<Compile Include="Persistence\PetaPocoSqlExtensions.cs" />
|
||||
<Compile Include="Persistence\Querying\BaseExpressionHelper.cs" />
|
||||
<Compile Include="Persistence\Querying\PocoToSqlExpressionHelper.cs" />
|
||||
<Compile Include="Persistence\Querying\IQuery.cs" />
|
||||
<Compile Include="Persistence\Querying\ModelToSqlExpressionHelper.cs" />
|
||||
@@ -496,6 +499,7 @@
|
||||
<Compile Include="Persistence\Repositories\MediaTypeRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\PermissionRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\PetaPocoRepositoryBase.cs" />
|
||||
<Compile Include="Persistence\Repositories\RecycleBinRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\RelationRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\RelationTypeRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\RepositoryBase.cs" />
|
||||
@@ -665,6 +669,9 @@
|
||||
<Compile Include="Publishing\PublishStatus.cs" />
|
||||
<Compile Include="Publishing\PublishStatusType.cs" />
|
||||
<Compile Include="RenderingEngine.cs" />
|
||||
<Compile Include="Security\AuthenticationExtensions.cs" />
|
||||
<Compile Include="Security\UmbracoBackOfficeIdentity.cs" />
|
||||
<Compile Include="Security\UserData.cs" />
|
||||
<Compile Include="Serialization\AbstractSerializationService.cs" />
|
||||
<Compile Include="Serialization\Formatter.cs" />
|
||||
<Compile Include="Serialization\IFormatter.cs" />
|
||||
|
||||
@@ -2,6 +2,8 @@ using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -10,6 +12,42 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public static class UriExtensions
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the current uri is a back office request
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool IsBackOfficeRequest(this Uri url)
|
||||
{
|
||||
|
||||
var authority = url.GetLeftPart(UriPartial.Authority);
|
||||
var afterAuthority = url.GetLeftPart(UriPartial.Query)
|
||||
.TrimStart(authority)
|
||||
.TrimStart("/");
|
||||
|
||||
|
||||
|
||||
//check if this is in the umbraco back office
|
||||
return afterAuthority.InvariantStartsWith(GlobalSettings.Path.TrimStart("/"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the current uri is an install request
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool IsInstallerRequest(this Uri url)
|
||||
{
|
||||
var authority = url.GetLeftPart(UriPartial.Authority);
|
||||
var afterAuthority = url.GetLeftPart(UriPartial.Query)
|
||||
.TrimStart(authority)
|
||||
.TrimStart("/");
|
||||
|
||||
//check if this is in the umbraco back office
|
||||
return afterAuthority.InvariantStartsWith(IOHelper.ResolveUrl("~/install").TrimStart("/"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is a performance tweak to check if this is a .css, .js or .ico, .jpg, .jpeg, .png, .gif file request since
|
||||
/// .Net will pass these requests through to the module when in integrated mode.
|
||||
@@ -19,7 +57,7 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
internal static bool IsClientSideRequest(this Uri url)
|
||||
{
|
||||
var toIgnore = new[] { ".js", ".css", ".ico", ".png", ".jpg", ".jpeg", ".gif" };
|
||||
var toIgnore = new[] { ".js", ".css", ".ico", ".png", ".jpg", ".jpeg", ".gif", ".html", ".svg" };
|
||||
return toIgnore.Any(x => Path.GetExtension(url.LocalPath).InvariantEquals(x));
|
||||
}
|
||||
|
||||
@@ -31,14 +69,14 @@ namespace Umbraco.Core
|
||||
/// <returns>The rewritten uri.</returns>
|
||||
/// <remarks>Everything else remains unchanged, except for the fragment which is removed.</remarks>
|
||||
public static Uri Rewrite(this Uri uri, string path)
|
||||
{
|
||||
{
|
||||
if (!path.StartsWith("/"))
|
||||
throw new ArgumentException("Path must start with a slash.", "path");
|
||||
|
||||
return uri.IsAbsoluteUri
|
||||
? new Uri(uri.GetLeftPart(UriPartial.Authority) + path + uri.Query)
|
||||
return uri.IsAbsoluteUri
|
||||
? new Uri(uri.GetLeftPart(UriPartial.Authority) + path + uri.Query)
|
||||
: new Uri(path + uri.GetSafeQuery(), UriKind.Relative);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rewrites the path and query of a uri.
|
||||
@@ -49,18 +87,18 @@ namespace Umbraco.Core
|
||||
/// <returns>The rewritten uri.</returns>
|
||||
/// <remarks>Everything else remains unchanged, except for the fragment which is removed.</remarks>
|
||||
public static Uri Rewrite(this Uri uri, string path, string query)
|
||||
{
|
||||
{
|
||||
if (!path.StartsWith("/"))
|
||||
throw new ArgumentException("Path must start with a slash.", "path");
|
||||
if (query.Length > 0 && !query.StartsWith("?"))
|
||||
throw new ArgumentException("Query must start with a question mark.", "query");
|
||||
if (query == "?")
|
||||
query = "";
|
||||
|
||||
return uri.IsAbsoluteUri
|
||||
? new Uri(uri.GetLeftPart(UriPartial.Authority) + path + query)
|
||||
|
||||
return uri.IsAbsoluteUri
|
||||
? new Uri(uri.GetLeftPart(UriPartial.Authority) + path + query)
|
||||
: new Uri(path + query, UriKind.Relative);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the absolute path of the uri, even if the uri is relative.
|
||||
@@ -68,10 +106,10 @@ namespace Umbraco.Core
|
||||
/// <param name="uri">The uri.</param>
|
||||
/// <returns>The absolute path of the uri.</returns>
|
||||
/// <remarks>Default uri.AbsolutePath does not support relative uris.</remarks>
|
||||
public static string GetSafeAbsolutePath(this Uri uri)
|
||||
{
|
||||
if (uri.IsAbsoluteUri)
|
||||
return uri.AbsolutePath;
|
||||
public static string GetSafeAbsolutePath(this Uri uri)
|
||||
{
|
||||
if (uri.IsAbsoluteUri)
|
||||
return uri.AbsolutePath;
|
||||
|
||||
// cannot get .AbsolutePath on relative uri (InvalidOperation)
|
||||
var s = uri.OriginalString;
|
||||
@@ -80,7 +118,7 @@ namespace Umbraco.Core
|
||||
var pos = posq > 0 ? posq : (posf > 0 ? posf : 0);
|
||||
var path = pos > 0 ? s.Substring(0, pos) : s;
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the decoded, absolute path of the uri.
|
||||
@@ -89,9 +127,9 @@ namespace Umbraco.Core
|
||||
/// <returns>The absolute path of the uri.</returns>
|
||||
/// <remarks>Only for absolute uris.</remarks>
|
||||
public static string GetAbsolutePathDecoded(this Uri uri)
|
||||
{
|
||||
return System.Web.HttpUtility.UrlDecode(uri.AbsolutePath);
|
||||
}
|
||||
{
|
||||
return System.Web.HttpUtility.UrlDecode(uri.AbsolutePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the decoded, absolute path of the uri, even if the uri is relative.
|
||||
@@ -100,32 +138,32 @@ namespace Umbraco.Core
|
||||
/// <returns>The absolute path of the uri.</returns>
|
||||
/// <remarks>Default uri.AbsolutePath does not support relative uris.</remarks>
|
||||
public static string GetSafeAbsolutePathDecoded(this Uri uri)
|
||||
{
|
||||
return System.Web.HttpUtility.UrlDecode(uri.GetSafeAbsolutePath());
|
||||
}
|
||||
{
|
||||
return System.Web.HttpUtility.UrlDecode(uri.GetSafeAbsolutePath());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rewrites the path of the uri so it ends with a slash.
|
||||
/// </summary>
|
||||
/// <param name="uri">The uri.</param>
|
||||
/// <returns>The rewritten uri.</returns>
|
||||
/// <remarks>Everything else remains unchanged.</remarks>
|
||||
/// <summary>
|
||||
/// Rewrites the path of the uri so it ends with a slash.
|
||||
/// </summary>
|
||||
/// <param name="uri">The uri.</param>
|
||||
/// <returns>The rewritten uri.</returns>
|
||||
/// <remarks>Everything else remains unchanged.</remarks>
|
||||
public static Uri EndPathWithSlash(this Uri uri)
|
||||
{
|
||||
var path = uri.GetSafeAbsolutePath();
|
||||
if (uri.IsAbsoluteUri)
|
||||
{
|
||||
if (path != "/" && !path.EndsWith("/"))
|
||||
uri = new Uri(uri.GetLeftPart(UriPartial.Authority) + path + "/" + uri.Query);
|
||||
return uri;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path != "/" && !path.EndsWith("/"))
|
||||
uri = new Uri(path + "/" + uri.Query, UriKind.Relative);
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
{
|
||||
var path = uri.GetSafeAbsolutePath();
|
||||
if (uri.IsAbsoluteUri)
|
||||
{
|
||||
if (path != "/" && !path.EndsWith("/"))
|
||||
uri = new Uri(uri.GetLeftPart(UriPartial.Authority) + path + "/" + uri.Query);
|
||||
return uri;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path != "/" && !path.EndsWith("/"))
|
||||
uri = new Uri(path + "/" + uri.Query, UriKind.Relative);
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rewrites the path of the uri so it does not end with a slash.
|
||||
@@ -134,20 +172,20 @@ namespace Umbraco.Core
|
||||
/// <returns>The rewritten uri.</returns>
|
||||
/// <remarks>Everything else remains unchanged.</remarks>
|
||||
public static Uri TrimPathEndSlash(this Uri uri)
|
||||
{
|
||||
var path = uri.GetSafeAbsolutePath();
|
||||
if (uri.IsAbsoluteUri)
|
||||
{
|
||||
if (path != "/")
|
||||
uri = new Uri(uri.GetLeftPart(UriPartial.Authority) + path.TrimEnd('/') + uri.Query);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path != "/")
|
||||
uri = new Uri(path.TrimEnd('/') + uri.Query, UriKind.Relative);
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
{
|
||||
var path = uri.GetSafeAbsolutePath();
|
||||
if (uri.IsAbsoluteUri)
|
||||
{
|
||||
if (path != "/")
|
||||
uri = new Uri(uri.GetLeftPart(UriPartial.Authority) + path.TrimEnd('/') + uri.Query);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path != "/")
|
||||
uri = new Uri(path.TrimEnd('/') + uri.Query, UriKind.Relative);
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a relative uri into an absolute uri.
|
||||
@@ -155,13 +193,13 @@ namespace Umbraco.Core
|
||||
/// <param name="uri">The relative uri.</param>
|
||||
/// <param name="baseUri">The base absolute uri.</param>
|
||||
/// <returns>The absolute uri.</returns>
|
||||
public static Uri MakeAbsolute(this Uri uri, Uri baseUri)
|
||||
{
|
||||
if (uri.IsAbsoluteUri)
|
||||
throw new ArgumentException("Uri is already absolute.", "uri");
|
||||
public static Uri MakeAbsolute(this Uri uri, Uri baseUri)
|
||||
{
|
||||
if (uri.IsAbsoluteUri)
|
||||
throw new ArgumentException("Uri is already absolute.", "uri");
|
||||
|
||||
return new Uri(baseUri.GetLeftPart(UriPartial.Authority) + uri.GetSafeAbsolutePath() + uri.GetSafeQuery());
|
||||
}
|
||||
return new Uri(baseUri.GetLeftPart(UriPartial.Authority) + uri.GetSafeAbsolutePath() + uri.GetSafeQuery());
|
||||
}
|
||||
|
||||
static string GetSafeQuery(this Uri uri)
|
||||
{
|
||||
@@ -176,5 +214,5 @@ namespace Umbraco.Core
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
</appSettings>
|
||||
|
||||
<connectionStrings>
|
||||
<add name="umbracoDbDSN" connectionString="Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf" providerName="System.Data.SqlServerCe.4.0"/>
|
||||
<add name="umbracoDbDSN" connectionString="Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;File Access Retry Timeout=10" providerName="System.Data.SqlServerCe.4.0"/>
|
||||
</connectionStrings>
|
||||
|
||||
<FileSystemProviders>
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Umbraco.Tests.BusinessLogic
|
||||
|
||||
private void InitializeDatabase()
|
||||
{
|
||||
ConfigurationManager.AppSettings.Set(Core.Configuration.GlobalSettings.UmbracoConnectionName, @"datalayer=SQLCE4Umbraco.SqlCEHelper,SQLCE4Umbraco;data source=|DataDirectory|\UmbracoPetaPocoTests.sdf");
|
||||
ConfigurationManager.AppSettings.Set(Core.Configuration.GlobalSettings.UmbracoConnectionName, @"datalayer=SQLCE4Umbraco.SqlCEHelper,SQLCE4Umbraco;data source=|DataDirectory|\UmbracoPetaPocoTests.sdf;Flush Interval=1;File Access Retry Timeout=10");
|
||||
|
||||
ClearDatabase();
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Umbraco.Tests.Migrations.Upgrades
|
||||
|
||||
public override UmbracoDatabase GetConfiguredDatabase()
|
||||
{
|
||||
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf", "System.Data.SqlServerCe.4.0");
|
||||
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;File Access Retry Timeout=10", "System.Data.SqlServerCe.4.0");
|
||||
}
|
||||
|
||||
public override DatabaseProviders GetDatabaseProvider()
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Umbraco.Tests.Migrations.Upgrades
|
||||
|
||||
public override UmbracoDatabase GetConfiguredDatabase()
|
||||
{
|
||||
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf", "System.Data.SqlServerCe.4.0");
|
||||
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;File Access Retry Timeout=10", "System.Data.SqlServerCe.4.0");
|
||||
}
|
||||
|
||||
public override DatabaseProviders GetDatabaseProvider()
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace Umbraco.Tests.Migrations.Upgrades
|
||||
|
||||
public UmbracoDatabase GetConfiguredDatabase()
|
||||
{
|
||||
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf", "System.Data.SqlServerCe.4.0");
|
||||
return new UmbracoDatabase("Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;File Access Retry Timeout=10", "System.Data.SqlServerCe.4.0");
|
||||
}
|
||||
|
||||
public string GetDatabaseSpecificSqlScript()
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
|
||||
namespace Umbraco.Tests.Models
|
||||
{
|
||||
[TestFixture]
|
||||
public class ContentExtensionsTests
|
||||
{
|
||||
[Test]
|
||||
public void Should_Create_New_Version_When_Publishing()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.ChangePublishedState(PublishedState.Published);
|
||||
Assert.IsTrue(content.ShouldCreateNewVersion());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Should_Create_New_Version_When_Saving_After_Publishing()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
content.ChangePublishedState(PublishedState.Published);
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.ChangePublishedState(PublishedState.Saved);
|
||||
Assert.IsTrue(content.ShouldCreateNewVersion());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Should_Create_New_Version_When_Language_Changed()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.Language = "en-AU";
|
||||
Assert.IsTrue(content.ShouldCreateNewVersion(PublishedState.Unpublished));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Should_Create_New_Version_When_Any_Property_Value_Changed_And_Its_Already_Published()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.Properties.First().Value = "hello world";
|
||||
Assert.IsTrue(content.ShouldCreateNewVersion(PublishedState.Published));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Should_Not_Create_New_Version_When_Published_Status_Not_Changed()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
Assert.IsFalse(content.ShouldCreateNewVersion(PublishedState.Unpublished));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Should_Not_Create_New_Version_When_Not_Published_And_Property_Changed()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.Properties.First().Value = "hello world";
|
||||
Assert.IsFalse(content.ShouldCreateNewVersion(PublishedState.Unpublished));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Should_Clear_Published_Flag_When_Newly_Published_Version()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.ChangePublishedState(PublishedState.Published);
|
||||
Assert.IsTrue(content.ShouldClearPublishedFlagForPreviousVersions());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Should_Not_Clear_Published_Flag_When_Saving_Version()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
content.ChangePublishedState(PublishedState.Published);
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.ChangePublishedState(PublishedState.Saved);
|
||||
Assert.IsFalse(content.ShouldClearPublishedFlagForPreviousVersions());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Should_Clear_Published_Flag_When_Unpublishing_From_Published()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
content.ChangePublishedState(PublishedState.Published);
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.ChangePublishedState(PublishedState.Unpublished);
|
||||
Assert.IsTrue(content.ShouldClearPublishedFlagForPreviousVersions());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Should_Not_Clear_Published_Flag_When_Unpublishing_From_Saved()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
content.ChangePublishedState(PublishedState.Saved);
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.ChangePublishedState(PublishedState.Unpublished);
|
||||
Assert.IsFalse(content.ShouldClearPublishedFlagForPreviousVersions());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,21 @@ namespace Umbraco.Tests.Models
|
||||
[TestFixture]
|
||||
public class ContentTests
|
||||
{
|
||||
[Test]
|
||||
public void All_Dirty_Properties_Get_Reset()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
Assert.IsFalse(content.IsDirty());
|
||||
foreach (var prop in content.Properties)
|
||||
{
|
||||
Assert.IsFalse(prop.IsDirty());
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Verify_Mocked_Content()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Xml;
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
using Rhino.Mocks.Interfaces;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Strings;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using umbraco.cms.businesslogic.datatype;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Tests.Models
|
||||
{
|
||||
[TestFixture]
|
||||
public class DataValueSetterTests : BaseUmbracoApplicationTest
|
||||
{
|
||||
protected override void FreezeResolution()
|
||||
{
|
||||
ShortStringHelperResolver.Current = new ShortStringHelperResolver(new DefaultShortStringHelper());
|
||||
base.FreezeResolution();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LoadValueFromDatabase_Is_Not_Called_When_SetValue_Is_Used()
|
||||
{
|
||||
// Arrange
|
||||
var baseDataType = MockRepository.GenerateStub<BaseDataType>();
|
||||
var dataTypeData = MockRepository.GenerateMock<DefaultData>(baseDataType);
|
||||
dataTypeData.Stub(x => x.Value).CallOriginalMethod(OriginalCallOptions.NoExpectation);
|
||||
|
||||
// Act
|
||||
|
||||
((IDataValueSetter)dataTypeData).SetValue("Hello world", DataTypeDatabaseType.Nvarchar.ToString());
|
||||
var val = dataTypeData.Value;
|
||||
|
||||
// Assert
|
||||
|
||||
dataTypeData.AssertWasNotCalled(data => data.LoadValueFromDatabase());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LoadValueFromDatabase_Is_Called_When_SetValue_Is_Not_Used()
|
||||
{
|
||||
// Arrange
|
||||
var baseDataType = MockRepository.GenerateStub<BaseDataType>();
|
||||
var dataTypeData = MockRepository.GenerateMock<DefaultData>(baseDataType);
|
||||
dataTypeData
|
||||
.Stub(data => data.LoadValueFromDatabase()).WhenCalled(invocation => Debug.WriteLine("asdf"));
|
||||
dataTypeData.Stub(x => x.Value).CallOriginalMethod(OriginalCallOptions.NoExpectation);
|
||||
|
||||
// Act
|
||||
|
||||
var val = dataTypeData.Value;
|
||||
|
||||
// Assert
|
||||
|
||||
dataTypeData.AssertWasCalled(data => data.LoadValueFromDatabase());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetValue_Is_Called_When_Executing_ToXml_On_A_Property_With_DataType_That_Implements_IDataValueSetter()
|
||||
{
|
||||
// Arrange
|
||||
var dataTypeId = Guid.NewGuid();
|
||||
|
||||
var dataTypeData = MockRepository.GenerateMock<IData, IDataValueSetter>();
|
||||
dataTypeData
|
||||
.Stub(data => data.ToXMl(Arg<XmlDocument>.Is.Anything))
|
||||
.Return(null) // you have to call Return() even though we're about to override it
|
||||
.WhenCalled(invocation =>
|
||||
{
|
||||
var xmlDoc = (XmlDocument) invocation.Arguments[0];
|
||||
invocation.ReturnValue = xmlDoc.CreateElement("test");
|
||||
});
|
||||
|
||||
var dataType = MockRepository.GenerateStub<IDataType>();
|
||||
dataType.Stub(type => type.Data).Return(dataTypeData);
|
||||
|
||||
var dataTypeSvc = MockRepository.GenerateStub<IDataTypeService>();
|
||||
dataTypeSvc.Stub(service => service.GetDataTypeById(dataTypeId)).Return(dataType);
|
||||
|
||||
var property = new Property(
|
||||
1234,
|
||||
Guid.NewGuid(),
|
||||
new PropertyType(dataTypeId, DataTypeDatabaseType.Nvarchar)
|
||||
{
|
||||
Alias = "test"
|
||||
}, "Hello world");
|
||||
|
||||
// Act
|
||||
|
||||
var xml = property.ToXml(dataTypeSvc);
|
||||
|
||||
// Assert
|
||||
|
||||
((IDataValueSetter)dataTypeData).AssertWasCalled(setter => setter.SetValue("Hello world", DataTypeDatabaseType.Nvarchar.ToString()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ namespace Umbraco.Tests.Persistence
|
||||
//Get the connectionstring settings from config
|
||||
var settings = ConfigurationManager.ConnectionStrings[Core.Configuration.GlobalSettings.UmbracoConnectionName];
|
||||
|
||||
//by default the conn string is: Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf
|
||||
//by default the conn string is: Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;File Access Retry Timeout=10
|
||||
//we'll just replace the sdf file with our custom one:
|
||||
//Create the Sql CE database
|
||||
var engine = new SqlCeEngine(settings.ConnectionString.Replace("UmbracoPetaPocoTests", "DatabaseContextTests"));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
@@ -73,13 +74,47 @@ namespace Umbraco.Tests.Persistence
|
||||
db.OpenSharedConnection();
|
||||
|
||||
// Act
|
||||
string sql;
|
||||
string[] sql;
|
||||
db.GenerateBulkInsertCommand(servers, db.Connection, out sql);
|
||||
db.CloseSharedConnection();
|
||||
|
||||
// Assert
|
||||
Assert.That(sql,
|
||||
Assert.That(sql[0],
|
||||
Is.EqualTo("INSERT INTO [umbracoServer] ([umbracoServer].[address], [umbracoServer].[computerName], [umbracoServer].[registeredDate], [umbracoServer].[lastNotifiedDate], [umbracoServer].[isActive]) VALUES (@0,@1,@2,@3,@4), (@5,@6,@7,@8,@9)"));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Generate_Bulk_Import_Sql_Exceeding_Max_Params()
|
||||
{
|
||||
// Arrange
|
||||
var db = DatabaseContext.Database;
|
||||
|
||||
var servers = new List<ServerRegistrationDto>();
|
||||
for (var i = 0; i < 1500; i++)
|
||||
{
|
||||
servers.Add(new ServerRegistrationDto
|
||||
{
|
||||
Address = "address" + i,
|
||||
ComputerName = "computer" + i,
|
||||
DateRegistered = DateTime.Now,
|
||||
IsActive = true,
|
||||
LastNotified = DateTime.Now
|
||||
});
|
||||
}
|
||||
db.OpenSharedConnection();
|
||||
|
||||
// Act
|
||||
string[] sql;
|
||||
db.GenerateBulkInsertCommand(servers, db.Connection, out sql);
|
||||
db.CloseSharedConnection();
|
||||
|
||||
// Assert
|
||||
Assert.That(sql.Length, Is.EqualTo(4));
|
||||
foreach (var s in sql)
|
||||
{
|
||||
Assert.LessOrEqual(Regex.Matches(s, "@\\d+").Count, 2000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,12 +35,12 @@ namespace Umbraco.Tests.Persistence
|
||||
}
|
||||
|
||||
//Create the Sql CE database
|
||||
var engine = new SqlCeEngine("Datasource=|DataDirectory|test.sdf");
|
||||
var engine = new SqlCeEngine("Datasource=|DataDirectory|test.sdf;Flush Interval=1;File Access Retry Timeout=10");
|
||||
engine.CreateDatabase();
|
||||
|
||||
SqlSyntaxContext.SqlSyntaxProvider = SqlCeSyntax.Provider;
|
||||
|
||||
_database = new Database("Datasource=|DataDirectory|test.sdf",
|
||||
_database = new Database("Datasource=|DataDirectory|test.sdf;Flush Interval=1;File Access Retry Timeout=10",
|
||||
"System.Data.SqlServerCe.4.0");
|
||||
}
|
||||
|
||||
|
||||
@@ -160,14 +160,15 @@ namespace Umbraco.Tests
|
||||
{
|
||||
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
|
||||
var manager = new PluginManager(false);
|
||||
var filePath = Path.Combine(tempFolder, "umbraco-plugins.list");
|
||||
var filePath= Path.Combine(tempFolder, string.Format("umbraco-plugins.{0}.list", NetworkHelper.FileSafeMachineName));
|
||||
|
||||
File.WriteAllText(filePath, @"<?xml version=""1.0"" encoding=""utf-8""?>
|
||||
<plugins>
|
||||
<baseType type=""umbraco.interfaces.ICacheRefresher"">
|
||||
<add type=""umbraco.macroCacheRefresh, umbraco, Version=6.0.0.0, Culture=neutral, PublicKeyToken=null"" />
|
||||
</baseType>
|
||||
</plugins>");
|
||||
|
||||
|
||||
Assert.IsTrue(manager.DetectLegacyPluginListFile());
|
||||
|
||||
File.Delete(filePath);
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Umbraco.Tests.PublishedCache
|
||||
Assert.AreEqual(mRoot.Id, publishedMedia.Id);
|
||||
Assert.AreEqual(mRoot.CreateDateTime.ToString("dd/MM/yyyy HH:mm:ss"), publishedMedia.CreateDate.ToString("dd/MM/yyyy HH:mm:ss"));
|
||||
Assert.AreEqual(mRoot.User.Id, publishedMedia.CreatorId);
|
||||
Assert.AreEqual(mRoot.User.LoginName, publishedMedia.CreatorName);
|
||||
Assert.AreEqual(mRoot.User.Name, publishedMedia.CreatorName);
|
||||
Assert.AreEqual(mRoot.ContentType.Alias, publishedMedia.DocumentTypeAlias);
|
||||
Assert.AreEqual(mRoot.ContentType.Id, publishedMedia.DocumentTypeId);
|
||||
Assert.AreEqual(mRoot.Level, publishedMedia.Level);
|
||||
|
||||
@@ -306,12 +306,13 @@ namespace Umbraco.Tests.Services
|
||||
public void Can_RePublish_All_Content()
|
||||
{
|
||||
// Arrange
|
||||
var contentService = ServiceContext.ContentService;
|
||||
var contentService = (ContentService)ServiceContext.ContentService;
|
||||
var rootContent = contentService.GetRootContent();
|
||||
foreach (var c in rootContent)
|
||||
{
|
||||
contentService.PublishWithChildren(c);
|
||||
}
|
||||
var allContent = rootContent.Concat(rootContent.SelectMany(x => x.Descendants()));
|
||||
//for testing we need to clear out the contentXml table so we can see if it worked
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var uow = provider.GetUnitOfWork();
|
||||
@@ -319,13 +320,49 @@ namespace Umbraco.Tests.Services
|
||||
{
|
||||
uow.Database.TruncateTable("cmsContentXml");
|
||||
}
|
||||
|
||||
//for this test we are also going to save a revision for a content item that is not published, this is to ensure
|
||||
//that it's published version still makes it into the cmsContentXml table!
|
||||
contentService.Save(allContent.Last());
|
||||
|
||||
// Act
|
||||
var published = contentService.RePublishAll(0);
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(published);
|
||||
uow = provider.GetUnitOfWork();
|
||||
using (var repo = RepositoryResolver.Current.ResolveByType<IContentRepository>(uow))
|
||||
{
|
||||
Assert.AreEqual(allContent.Count(), uow.Database.ExecuteScalar<int>("select count(*) from cmsContentXml"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_RePublish_All_Content_Of_Type()
|
||||
{
|
||||
// Arrange
|
||||
var contentService = (ContentService)ServiceContext.ContentService;
|
||||
var rootContent = contentService.GetRootContent();
|
||||
foreach (var c in rootContent)
|
||||
{
|
||||
contentService.PublishWithChildren(c);
|
||||
}
|
||||
var allContent = rootContent.Concat(rootContent.SelectMany(x => x.Descendants()));
|
||||
//for testing we need to clear out the contentXml table so we can see if it worked
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var uow = provider.GetUnitOfWork();
|
||||
using (RepositoryResolver.Current.ResolveByType<IContentRepository>(uow))
|
||||
{
|
||||
uow.Database.TruncateTable("cmsContentXml");
|
||||
}
|
||||
//for this test we are also going to save a revision for a content item that is not published, this is to ensure
|
||||
//that it's published version still makes it into the cmsContentXml table!
|
||||
contentService.Save(allContent.Last());
|
||||
|
||||
|
||||
// Act
|
||||
contentService.RePublishAll(new int[]{allContent.Last().ContentTypeId});
|
||||
|
||||
// Assert
|
||||
uow = provider.GetUnitOfWork();
|
||||
using (var repo = RepositoryResolver.Current.ResolveByType<IContentRepository>(uow))
|
||||
{
|
||||
@@ -688,15 +725,21 @@ namespace Umbraco.Tests.Services
|
||||
{
|
||||
// Arrange
|
||||
var contentService = ServiceContext.ContentService;
|
||||
var content = contentService.GetById(1048);
|
||||
var temp = contentService.GetById(1048);
|
||||
|
||||
// Act
|
||||
var copy = contentService.Copy(content, content.ParentId, false, 0);
|
||||
var copy = contentService.Copy(temp, temp.ParentId, false, 0);
|
||||
var content = contentService.GetById(1048);
|
||||
|
||||
// Assert
|
||||
Assert.That(copy, Is.Not.Null);
|
||||
Assert.That(copy.Id, Is.Not.EqualTo(content.Id));
|
||||
Assert.AreNotSame(content, copy);
|
||||
foreach (var property in copy.Properties)
|
||||
{
|
||||
Assert.AreNotEqual(property.Id, content.Properties[property.Alias].Id);
|
||||
Assert.AreEqual(property.Value, content.Properties[property.Alias].Value);
|
||||
}
|
||||
//Assert.AreNotEqual(content.Name, copy.Name);
|
||||
}
|
||||
|
||||
@@ -776,6 +819,48 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(hasPublishedVersion, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Verify_Property_Types_On_Content()
|
||||
{
|
||||
// Arrange
|
||||
var contentTypeService = ServiceContext.ContentTypeService;
|
||||
var contentType = MockedContentTypes.CreateAllTypesContentType("allDataTypes", "All DataTypes");
|
||||
contentTypeService.Save(contentType);
|
||||
var contentService = ServiceContext.ContentService;
|
||||
var content = MockedContent.CreateAllTypesContent(contentType, "Random Content", -1);
|
||||
contentService.Save(content);
|
||||
var id = content.Id;
|
||||
|
||||
// Act
|
||||
var sut = contentService.GetById(id);
|
||||
|
||||
// Arrange
|
||||
Assert.That(sut.GetValue<bool>("isTrue"), Is.True);
|
||||
Assert.That(sut.GetValue<int>("number"), Is.EqualTo(42));
|
||||
Assert.That(sut.GetValue<string>("bodyText"), Is.EqualTo("Lorem Ipsum Body Text Test"));
|
||||
Assert.That(sut.GetValue<string>("singleLineText"), Is.EqualTo("Single Line Text Test"));
|
||||
Assert.That(sut.GetValue<string>("multilineText"), Is.EqualTo("Multiple lines \n in one box"));
|
||||
Assert.That(sut.GetValue<string>("upload"), Is.EqualTo("/media/1234/koala.jpg"));
|
||||
Assert.That(sut.GetValue<string>("label"), Is.EqualTo("Non-editable label"));
|
||||
Assert.That(sut.GetValue<DateTime>("dateTime"), Is.EqualTo(content.GetValue<DateTime>("dateTime")));
|
||||
Assert.That(sut.GetValue<string>("colorPicker"), Is.EqualTo("black"));
|
||||
Assert.That(sut.GetValue<string>("folderBrowser"), Is.Empty);
|
||||
Assert.That(sut.GetValue<string>("ddlMultiple"), Is.EqualTo("1234,1235"));
|
||||
Assert.That(sut.GetValue<string>("rbList"), Is.EqualTo("random"));
|
||||
Assert.That(sut.GetValue<DateTime>("date"), Is.EqualTo(content.GetValue<DateTime>("date")));
|
||||
Assert.That(sut.GetValue<string>("ddl"), Is.EqualTo("1234"));
|
||||
Assert.That(sut.GetValue<string>("chklist"), Is.EqualTo("randomc"));
|
||||
Assert.That(sut.GetValue<int>("contentPicker"), Is.EqualTo(1090));
|
||||
Assert.That(sut.GetValue<int>("mediaPicker"), Is.EqualTo(1091));
|
||||
Assert.That(sut.GetValue<int>("memberPicker"), Is.EqualTo(1092));
|
||||
Assert.That(sut.GetValue<string>("simpleEditor"), Is.EqualTo("This is simply edited"));
|
||||
Assert.That(sut.GetValue<string>("ultimatePicker"), Is.EqualTo("1234,1235"));
|
||||
Assert.That(sut.GetValue<string>("relatedLinks"), Is.EqualTo("<links><link title=\"google\" link=\"http://google.com\" type=\"external\" newwindow=\"0\" /></links>"));
|
||||
Assert.That(sut.GetValue<string>("tags"), Is.EqualTo("this,is,tags"));
|
||||
Assert.That(sut.GetValue<string>("macroContainer"), Is.Empty);
|
||||
Assert.That(sut.GetValue<string>("imgCropper"), Is.Empty);
|
||||
}
|
||||
|
||||
private IEnumerable<IContent> CreateContentHierarchy()
|
||||
{
|
||||
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
|
||||
|
||||
@@ -263,6 +263,41 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(homepage.CompositionPropertyTypes.Count(), Is.EqualTo(4));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Copy_ContentType_By_Performing_Clone()
|
||||
{
|
||||
// Arrange
|
||||
var service = ServiceContext.ContentTypeService;
|
||||
var metaContentType = MockedContentTypes.CreateMetaContentType();
|
||||
service.Save(metaContentType);
|
||||
|
||||
var simpleContentType = MockedContentTypes.CreateSimpleContentType("category", "Category", metaContentType);
|
||||
service.Save(simpleContentType);
|
||||
var categoryId = simpleContentType.Id;
|
||||
|
||||
// Act
|
||||
var sut = simpleContentType.Clone("newcategory");
|
||||
service.Save(sut);
|
||||
|
||||
// Assert
|
||||
Assert.That(sut.HasIdentity, Is.True);
|
||||
|
||||
var contentType = service.GetContentType(sut.Id);
|
||||
var category = service.GetContentType(categoryId);
|
||||
|
||||
Assert.That(contentType.CompositionAliases().Any(x => x.Equals("meta")), Is.True);
|
||||
Assert.AreEqual(contentType.ParentId, category.ParentId);
|
||||
Assert.AreEqual(contentType.Level, category.Level);
|
||||
Assert.AreEqual(contentType.PropertyTypes.Count(), category.PropertyTypes.Count());
|
||||
Assert.AreNotEqual(contentType.Id, category.Id);
|
||||
Assert.AreNotEqual(contentType.Key, category.Key);
|
||||
Assert.AreNotEqual(contentType.Path, category.Path);
|
||||
Assert.AreNotEqual(contentType.SortOrder, category.SortOrder);
|
||||
Assert.AreNotEqual(contentType.PropertyTypes.First(x => x.Alias.Equals("title")).Id, category.PropertyTypes.First(x => x.Alias.Equals("title")).Id);
|
||||
Assert.AreNotEqual(contentType.PropertyGroups.First(x => x.Name.Equals("Content")).Id, category.PropertyGroups.First(x => x.Name.Equals("Content")).Id);
|
||||
|
||||
}
|
||||
|
||||
private ContentType CreateComponent()
|
||||
{
|
||||
var component = new ContentType(-1)
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
|
||||
namespace Umbraco.Tests.Services
|
||||
{
|
||||
//[TestFixture]
|
||||
//public class PackagingServiceTests : BaseServiceTest
|
||||
//{
|
||||
// [Test]
|
||||
// public void Export_Content()
|
||||
// {
|
||||
// var yesNo = DataTypesResolver.Current.GetById(new Guid(Constants.PropertyEditors.TrueFalse));
|
||||
// var txtField = DataTypesResolver.Current.GetById(new Guid(Constants.PropertyEditors.Textbox));
|
||||
|
||||
// var contentWithDataType = MockedContentTypes.CreateSimpleContentType(
|
||||
// "test",
|
||||
// "Test",
|
||||
// new PropertyTypeCollection(
|
||||
// new PropertyType[]
|
||||
// {
|
||||
// new PropertyType(new DataTypeDefinition(-1, txtField.Id)
|
||||
// {
|
||||
// Name = "Testing Textfield", DatabaseType = DataTypeDatabaseType.Ntext
|
||||
// }),
|
||||
// new PropertyType(new DataTypeDefinition(-1, yesNo.Id)
|
||||
// {
|
||||
// Name = "Testing intfield", DatabaseType = DataTypeDatabaseType.Integer
|
||||
// })
|
||||
// }));
|
||||
|
||||
// var content = MockedContent.CreateSimpleContent(contentWithDataType);
|
||||
// content.Name = "Test";
|
||||
|
||||
// var exported = ServiceContext.PackagingService.Export(content);
|
||||
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data.SqlServerCe;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Xml.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
|
||||
namespace Umbraco.Tests.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests covering all methods in the ContentService class.
|
||||
/// This is more of an integration test as it involves multiple layers
|
||||
/// as well as configuration.
|
||||
/// </summary>
|
||||
[TestFixture, RequiresSTA]
|
||||
[NUnit.Framework.Ignore("These should not be run by the server, only directly as they are only benchmark tests")]
|
||||
public class PerformanceTests : BaseDatabaseFactoryTest
|
||||
{
|
||||
[SetUp]
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
protected override string GetDbConnectionString()
|
||||
{
|
||||
return @"server=.\SQLEXPRESS;database=UmbTest;user id=sa;password=test";
|
||||
}
|
||||
|
||||
protected override string GetDbProviderName()
|
||||
{
|
||||
return "System.Data.SqlClient";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// new schema per test
|
||||
/// </summary>
|
||||
protected override DatabaseBehavior DatabaseTestBehavior
|
||||
{
|
||||
get { return DatabaseBehavior.NewSchemaPerTest; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// don't create anything, we're testing against our own server
|
||||
/// </summary>
|
||||
protected override void CreateSqlCeDatabase()
|
||||
{
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_All_Published_Content()
|
||||
{
|
||||
var result = PrimeDbWithLotsOfContent();
|
||||
var contentSvc = (ContentService) ServiceContext.ContentService;
|
||||
|
||||
var countOfPublished = result.Count(x => x.Published);
|
||||
var contentTypeId = result.First().ContentTypeId;
|
||||
|
||||
using (DisposableTimer.DebugDuration<PerformanceTests>("Getting published content normally"))
|
||||
{
|
||||
//do this 10x!
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
//clear the cache to make this test valid
|
||||
RuntimeCacheProvider.Current.Clear();
|
||||
|
||||
var published = new List<IContent>();
|
||||
//get all content items that are published
|
||||
var rootContent = contentSvc.GetRootContent();
|
||||
foreach (var content in rootContent.Where(content => content.Published))
|
||||
{
|
||||
published.Add(content);
|
||||
published.AddRange(contentSvc.GetPublishedDescendants(content));
|
||||
}
|
||||
Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using (DisposableTimer.DebugDuration<PerformanceTests>("Getting published content optimized"))
|
||||
{
|
||||
|
||||
//do this 10x!
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
//clear the cache to make this test valid
|
||||
RuntimeCacheProvider.Current.Clear();
|
||||
|
||||
//get all content items that are published
|
||||
var published = contentSvc.GetAllPublished();
|
||||
|
||||
Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_All_Published_Content_Of_Type()
|
||||
{
|
||||
var result = PrimeDbWithLotsOfContent();
|
||||
var contentSvc = (ContentService)ServiceContext.ContentService;
|
||||
|
||||
var countOfPublished = result.Count(x => x.Published);
|
||||
var contentTypeId = result.First().ContentTypeId;
|
||||
|
||||
using (DisposableTimer.DebugDuration<PerformanceTests>("Getting published content of type normally"))
|
||||
{
|
||||
//do this 10x!
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
//clear the cache to make this test valid
|
||||
RuntimeCacheProvider.Current.Clear();
|
||||
//get all content items that are published of this type
|
||||
var published = contentSvc.GetContentOfContentType(contentTypeId).Where(content => content.Published);
|
||||
Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId));
|
||||
}
|
||||
}
|
||||
|
||||
using (DisposableTimer.DebugDuration<PerformanceTests>("Getting published content of type optimized"))
|
||||
{
|
||||
|
||||
//do this 10x!
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
//clear the cache to make this test valid
|
||||
RuntimeCacheProvider.Current.Clear();
|
||||
//get all content items that are published of this type
|
||||
var published = contentSvc.GetPublishedContentOfContentType(contentTypeId);
|
||||
Assert.AreEqual(countOfPublished, published.Count(x => x.ContentTypeId == contentTypeId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Truncate_Insert_Vs_Update_Insert()
|
||||
{
|
||||
var customObjectType = Guid.NewGuid();
|
||||
//chuck lots of data in the db
|
||||
var nodes = PrimeDbWithLotsOfContentXmlRecords(customObjectType);
|
||||
|
||||
//now we need to test the difference between truncating all records and re-inserting them as we do now,
|
||||
//vs updating them (which might result in checking if they exist for or listening on an exception).
|
||||
using (DisposableTimer.DebugDuration<PerformanceTests>("Starting truncate + normal insert test"))
|
||||
{
|
||||
//do this 10x!
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
//clear all the xml entries
|
||||
DatabaseContext.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
|
||||
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
|
||||
INNER JOIN cmsContent ON cmsContentXml.nodeId = cmsContent.nodeId)");
|
||||
|
||||
//now we insert each record for the ones we've deleted like we do in the content service.
|
||||
var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = UpdatedXmlStructure }).ToList();
|
||||
foreach (var xml in xmlItems)
|
||||
{
|
||||
var result = DatabaseContext.Database.Insert(xml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//now, isntead of truncating, we'll attempt to update and if it doesn't work then we insert
|
||||
using (DisposableTimer.DebugDuration<PerformanceTests>("Starting update test"))
|
||||
{
|
||||
//do this 10x!
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
//now we insert each record for the ones we've deleted like we do in the content service.
|
||||
var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = UpdatedXmlStructure }).ToList();
|
||||
foreach (var xml in xmlItems)
|
||||
{
|
||||
var result = DatabaseContext.Database.Update(xml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//now, test truncating but then do bulk insertion of records
|
||||
using (DisposableTimer.DebugDuration<PerformanceTests>("Starting truncate + bulk insert test"))
|
||||
{
|
||||
//do this 10x!
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
//clear all the xml entries
|
||||
DatabaseContext.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
|
||||
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
|
||||
INNER JOIN cmsContent ON cmsContentXml.nodeId = cmsContent.nodeId)");
|
||||
|
||||
//now we insert each record for the ones we've deleted like we do in the content service.
|
||||
var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = UpdatedXmlStructure }).ToList();
|
||||
DatabaseContext.Database.BulkInsertRecords(xmlItems);
|
||||
}
|
||||
}
|
||||
|
||||
//now, test truncating but then do bulk insertion of records
|
||||
using (DisposableTimer.DebugDuration<PerformanceTests>("Starting truncate + bulk insert test in one transaction"))
|
||||
{
|
||||
//do this 10x!
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
//now we insert each record for the ones we've deleted like we do in the content service.
|
||||
var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = UpdatedXmlStructure }).ToList();
|
||||
|
||||
using (var tr = DatabaseContext.Database.GetTransaction())
|
||||
{
|
||||
//clear all the xml entries
|
||||
DatabaseContext.Database.Execute(@"DELETE FROM cmsContentXml WHERE nodeId IN
|
||||
(SELECT DISTINCT cmsContentXml.nodeId FROM cmsContentXml
|
||||
INNER JOIN cmsContent ON cmsContentXml.nodeId = cmsContent.nodeId)");
|
||||
|
||||
|
||||
DatabaseContext.Database.BulkInsertRecords(xmlItems, tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private IEnumerable<IContent> PrimeDbWithLotsOfContent()
|
||||
{
|
||||
var contentType1 = MockedContentTypes.CreateSimpleContentType();
|
||||
contentType1.AllowedAsRoot = true;
|
||||
ServiceContext.ContentTypeService.Save(contentType1);
|
||||
contentType1.AllowedContentTypes = new List<ContentTypeSort>
|
||||
{
|
||||
new ContentTypeSort
|
||||
{
|
||||
Alias = contentType1.Alias,
|
||||
Id = new Lazy<int>(() => contentType1.Id),
|
||||
SortOrder = 0
|
||||
}
|
||||
};
|
||||
var result = new List<IContent>();
|
||||
ServiceContext.ContentTypeService.Save(contentType1);
|
||||
IContent lastParent = MockedContent.CreateSimpleContent(contentType1);
|
||||
ServiceContext.ContentService.SaveAndPublish(lastParent);
|
||||
result.Add(lastParent);
|
||||
//create 20 deep
|
||||
for (var i = 0; i < 20; i++)
|
||||
{
|
||||
//for each level, create 20
|
||||
IContent content = null;
|
||||
for (var j = 1; j <= 10; j++)
|
||||
{
|
||||
content = MockedContent.CreateSimpleContent(contentType1, "Name" + j, lastParent);
|
||||
//only publish evens
|
||||
if (j % 2 == 0)
|
||||
{
|
||||
ServiceContext.ContentService.SaveAndPublish(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
ServiceContext.ContentService.Save(content);
|
||||
}
|
||||
result.Add(content);
|
||||
}
|
||||
|
||||
//assign the last one as the next parent
|
||||
lastParent = content;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private IEnumerable<NodeDto> PrimeDbWithLotsOfContentXmlRecords(Guid customObjectType)
|
||||
{
|
||||
var nodes = new List<NodeDto>();
|
||||
for (var i = 1; i < 10000; i++)
|
||||
{
|
||||
nodes.Add(new NodeDto
|
||||
{
|
||||
Level = 1,
|
||||
ParentId = -1,
|
||||
NodeObjectType = customObjectType,
|
||||
Text = i.ToString(CultureInfo.InvariantCulture),
|
||||
UserId = 0,
|
||||
CreateDate = DateTime.Now,
|
||||
Trashed = false,
|
||||
SortOrder = 0,
|
||||
Path = ""
|
||||
});
|
||||
}
|
||||
DatabaseContext.Database.BulkInsertRecords(nodes);
|
||||
|
||||
//re-get the nodes with ids
|
||||
var sql = new Sql();
|
||||
sql.Select("*").From<NodeDto>().Where<NodeDto>(x => x.NodeObjectType == customObjectType);
|
||||
nodes = DatabaseContext.Database.Fetch<NodeDto>(sql);
|
||||
|
||||
//create the cmsContent data, each with a new content type id (so we can query on it later if needed)
|
||||
var contentTypeId = 0;
|
||||
var cmsContentItems = nodes.Select(node => new ContentDto { NodeId = node.NodeId, ContentTypeId = contentTypeId++ }).ToList();
|
||||
DatabaseContext.Database.BulkInsertRecords(cmsContentItems);
|
||||
|
||||
//create the xml data
|
||||
var xmlItems = nodes.Select(node => new ContentXmlDto { NodeId = node.NodeId, Xml = TestXmlStructure }).ToList();
|
||||
DatabaseContext.Database.BulkInsertRecords(xmlItems);
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private const string TestXmlStructure = @"<Homepage id='1231' parentID='-1' level='1' creatorID='0' sortOrder='0' createDate='2013-07-05T12:05:28' updateDate='2013-07-26T11:58:52' nodeName='Home (1)' urlName='home-(1)' path='-1,1231' isDoc='' nodeType='1221' creatorName='admin' writerName='admin' writerID='0' template='2629' nodeTypeAlias='Homepage'>
|
||||
<umbracoNaviHide>0</umbracoNaviHide>
|
||||
<title>Standard Site for Umbraco by Koiak</title>
|
||||
<description><![CDATA[]]></description>
|
||||
<keywords><![CDATA[]]></keywords>
|
||||
<slideshow><![CDATA[1250,1251,1252]]></slideshow>
|
||||
<panelContent1><![CDATA[<h2>Built by Creative Founds</h2>
|
||||
<p><img src='/images/web_applications.jpg' alt='Web Applications' class='fr'/><strong>Creative Founds</strong> design and build first class software solutions that deliver big results. We provide ASP.NET web and mobile applications, Umbraco development service & technical consultancy.</p>
|
||||
<p><a href='http://www.creativefounds.co.uk' target='_blank'>www.creativefounds.co.uk</a></p>]]></panelContent1>
|
||||
<panelContent2><![CDATA[<h2>Umbraco Development</h2>
|
||||
<p><img src='/images/umbraco_square.jpg' alt='Umbraco' class='fr'/>Umbraco the the leading ASP.NET open source CMS, under pinning over 150,000 websites. Our Certified Developers are experts in developing high performance and feature rich websites.</p>]]></panelContent2>
|
||||
<panelContent3><![CDATA[<h2>Contact Us</h2>
|
||||
<p><a href='http://www.twitter.com/chriskoiak' target='_blank'><img src='/images/twitter_square.png' alt='Contact Us on Twitter' class='fr'/></a>We'd love to hear how this package has helped you and how it can be improved. Get in touch on the <a href='http://our.umbraco.org/projects/starter-kits/standard-website-mvc' target='_blank'>project website</a> or via <a href='http://www.twitter.com/chriskoiak' target='_blank'>twitter</a></p>]]></panelContent3>
|
||||
<primaryNavigation><![CDATA[1231,1232,1236,1238,1239]]></primaryNavigation>
|
||||
<address>Standard Website MVC, Company Address, Glasgow, Postcode</address>
|
||||
<copyright>Copyright &copy; 2012 Your Company</copyright>
|
||||
<affiliationLink1>http://www.umbraco.org</affiliationLink1>
|
||||
<affiliationImage1>/media/1477/umbraco_logo.png</affiliationImage1>
|
||||
<affiliationLink2></affiliationLink2>
|
||||
<affiliationImage2></affiliationImage2>
|
||||
<affiliationLink3></affiliationLink3>
|
||||
<affiliationImage3></affiliationImage3>
|
||||
<headerNavigation><![CDATA[1242,1243]]></headerNavigation>
|
||||
<myList><![CDATA[]]></myList>
|
||||
<myDate>2013-07-01T00:00:00</myDate>
|
||||
</Homepage>";
|
||||
|
||||
private const string UpdatedXmlStructure = @"<Standard id='1238' parentID='1231' level='2' creatorID='0' sortOrder='2' createDate='2013-07-05T12:05:29' updateDate='2013-07-05T12:05:34' nodeName='Clients' urlName='clients' path='-1,1231,1238' isDoc='' nodeType='1217' creatorName='admin' writerName='admin' writerID='0' template='1213' nodeTypeAlias='Standard'>
|
||||
<umbracoNaviHide>0</umbracoNaviHide>
|
||||
<title></title>
|
||||
<description><![CDATA[]]></description>
|
||||
<keywords><![CDATA[]]></keywords>
|
||||
<bodyText><![CDATA[<h2>Clients</h2>
|
||||
<p><strong>This is a standard content page.</strong></p>
|
||||
<p><span>Vestibulum malesuada aliquet ante, vitae ullamcorper felis faucibus vel. Vestibulum condimentum faucibus tellus porta ultrices. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. </span></p>
|
||||
<p><span>Cras at auctor orci. Praesent facilisis erat nec odio consequat at posuere ligula pretium. Nulla eget felis id nisl volutpat pellentesque. Ut id augue id ligula placerat rutrum a nec purus. Maecenas sed lectus ac mi pellentesque luctus quis sit amet turpis. Vestibulum adipiscing convallis vestibulum. </span></p>
|
||||
<p><span>Duis condimentum lectus at orci placerat vitae imperdiet lorem cursus. Duis hendrerit porta lorem, non suscipit quam consectetur vitae. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean elit augue, tincidunt nec tincidunt id, elementum vel est.</span></p>]]></bodyText>
|
||||
<contentPanels><![CDATA[]]></contentPanels>
|
||||
</Standard>";
|
||||
|
||||
}
|
||||
}
|
||||
@@ -46,37 +46,47 @@ namespace Umbraco.Tests.TestHelpers
|
||||
//Used to flag if its the first test in the current fixture
|
||||
private bool _isFirstTestInFixture = false;
|
||||
|
||||
private ApplicationContext _appContext;
|
||||
|
||||
[SetUp]
|
||||
public override void Initialize()
|
||||
{
|
||||
InitializeFirstRunFlags();
|
||||
|
||||
base.Initialize();
|
||||
|
||||
|
||||
var path = TestHelper.CurrentAssemblyDirectory;
|
||||
AppDomain.CurrentDomain.SetData("DataDirectory", path);
|
||||
|
||||
ApplicationContext.Current = new ApplicationContext(
|
||||
var dbFactory = new DefaultDatabaseFactory(
|
||||
GetDbConnectionString(),
|
||||
GetDbProviderName());
|
||||
_appContext = new ApplicationContext(
|
||||
//assign the db context
|
||||
new DatabaseContext(new DefaultDatabaseFactory()),
|
||||
new DatabaseContext(dbFactory),
|
||||
//assign the service context
|
||||
new ServiceContext(new PetaPocoUnitOfWorkProvider(), new FileUnitOfWorkProvider(), new PublishingStrategy()),
|
||||
new ServiceContext(new PetaPocoUnitOfWorkProvider(dbFactory), new FileUnitOfWorkProvider(), new PublishingStrategy()),
|
||||
//disable cache
|
||||
false)
|
||||
{
|
||||
IsReady = true
|
||||
};
|
||||
|
||||
DatabaseContext.Initialize();
|
||||
base.Initialize();
|
||||
|
||||
CreateDatabase();
|
||||
DatabaseContext.Initialize(dbFactory.ProviderName, dbFactory.ConnectionString);
|
||||
|
||||
CreateSqlCeDatabase();
|
||||
|
||||
InitializeDatabase();
|
||||
|
||||
//ensure the configuration matches the current version for tests
|
||||
SettingsForTests.ConfigurationStatus = UmbracoVersion.Current.ToString(3);
|
||||
}
|
||||
|
||||
|
||||
protected override void SetupApplicationContext()
|
||||
{
|
||||
ApplicationContext.Current = _appContext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The database behavior to use for the test/fixture
|
||||
/// </summary>
|
||||
@@ -85,10 +95,23 @@ namespace Umbraco.Tests.TestHelpers
|
||||
get { return DatabaseBehavior.NewSchemaPerTest; }
|
||||
}
|
||||
|
||||
protected virtual string GetDbProviderName()
|
||||
{
|
||||
return "System.Data.SqlServerCe.4.0";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the db conn string
|
||||
/// </summary>
|
||||
protected virtual string GetDbConnectionString()
|
||||
{
|
||||
return @"Datasource=|DataDirectory|UmbracoPetaPocoTests.sdf;Flush Interval=1;File Access Retry Timeout=10";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the SqlCe database if required
|
||||
/// </summary>
|
||||
protected virtual void CreateDatabase()
|
||||
protected virtual void CreateSqlCeDatabase()
|
||||
{
|
||||
if (DatabaseTestBehavior == DatabaseBehavior.NoDatabasePerFixture)
|
||||
return;
|
||||
@@ -97,7 +120,9 @@ namespace Umbraco.Tests.TestHelpers
|
||||
|
||||
//Get the connectionstring settings from config
|
||||
var settings = ConfigurationManager.ConnectionStrings[Core.Configuration.GlobalSettings.UmbracoConnectionName];
|
||||
ConfigurationManager.AppSettings.Set(Core.Configuration.GlobalSettings.UmbracoConnectionName, @"datalayer=SQLCE4Umbraco.SqlCEHelper,SQLCE4Umbraco;data source=|DataDirectory|\UmbracoPetaPocoTests.sdf");
|
||||
ConfigurationManager.AppSettings.Set(
|
||||
Core.Configuration.GlobalSettings.UmbracoConnectionName,
|
||||
GetDbConnectionString());
|
||||
|
||||
string dbFilePath = string.Concat(path, "\\UmbracoPetaPocoTests.sdf");
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace Umbraco.Tests.TestHelpers
|
||||
|
||||
SetupPluginManager();
|
||||
|
||||
SetupApplicationContext();
|
||||
|
||||
FreezeResolution();
|
||||
}
|
||||
|
||||
@@ -40,7 +42,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
ApplicationContext.Current = null;
|
||||
ResetPluginManager();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// By default this returns false which means the plugin manager will not be reset so it doesn't need to re-scan
|
||||
/// all of the assemblies. Inheritors can override this if plugin manager resetting is required, generally needs
|
||||
|
||||
@@ -79,6 +79,38 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
return content;
|
||||
}
|
||||
|
||||
public static Content CreateAllTypesContent(IContentType contentType, string name, int parentId)
|
||||
{
|
||||
var content = new Content("Random Content Name", parentId, contentType) { Language = "en-US", Level = 1, SortOrder = 1, CreatorId = 0, WriterId = 0 };
|
||||
|
||||
content.SetValue("isTrue", true);
|
||||
content.SetValue("number", 42);
|
||||
content.SetValue("bodyText", "Lorem Ipsum Body Text Test");
|
||||
content.SetValue("singleLineText", "Single Line Text Test");
|
||||
content.SetValue("multilineText", "Multiple lines \n in one box");
|
||||
content.SetValue("upload", "/media/1234/koala.jpg");
|
||||
content.SetValue("label", "Non-editable label");
|
||||
content.SetValue("dateTime", DateTime.Now.AddDays(-20));
|
||||
content.SetValue("colorPicker", "black");
|
||||
content.SetValue("folderBrowser", "");
|
||||
content.SetValue("ddlMultiple", "1234,1235");
|
||||
content.SetValue("rbList", "random");
|
||||
content.SetValue("date", DateTime.Now.AddDays(-10));
|
||||
content.SetValue("ddl", "1234");
|
||||
content.SetValue("chklist", "randomc");
|
||||
content.SetValue("contentPicker", 1090);
|
||||
content.SetValue("mediaPicker", 1091);
|
||||
content.SetValue("memberPicker", 1092);
|
||||
content.SetValue("simpleEditor", "This is simply edited");
|
||||
content.SetValue("ultimatePicker", "1234,1235");
|
||||
content.SetValue("relatedLinks", "<links><link title=\"google\" link=\"http://google.com\" type=\"external\" newwindow=\"0\" /></links>");
|
||||
content.SetValue("tags", "this,is,tags");
|
||||
content.SetValue("macroContainer", "");
|
||||
content.SetValue("imgCropper", "");
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
public static IEnumerable<Content> CreateTextpageContent(IContentType contentType, int parentId, int amount)
|
||||
{
|
||||
var list = new List<Content>();
|
||||
|
||||
@@ -166,6 +166,51 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateAllTypesContentType(string alias, string name)
|
||||
{
|
||||
var contentType = new ContentType(-1)
|
||||
{
|
||||
Alias = alias,
|
||||
Name = name,
|
||||
Description = "ContentType containing all standard DataTypes",
|
||||
Icon = ".sprTreeDoc3",
|
||||
Thumbnail = "doc.png",
|
||||
SortOrder = 1,
|
||||
CreatorId = 0,
|
||||
Trashed = false
|
||||
};
|
||||
|
||||
var contentCollection = new PropertyTypeCollection();
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.TrueFalse), DataTypeDatabaseType.Integer) { Alias = "isTrue", Name = "Is True or False", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -49 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.Integer), DataTypeDatabaseType.Integer) { Alias = "number", Name = "Number", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -51 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.TinyMCEv3), DataTypeDatabaseType.Ntext) { Alias = "bodyText", Name = "Body Text", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -87 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.Textbox), DataTypeDatabaseType.Nvarchar) { Alias = "singleLineText", Name = "Text String", Mandatory = false, SortOrder = 4, DataTypeDefinitionId = -88 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.TextboxMultiple), DataTypeDatabaseType.Ntext) { Alias = "multilineText", Name = "Multiple Text Strings", Mandatory = false, SortOrder = 5, DataTypeDefinitionId = -89 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.UploadField), DataTypeDatabaseType.Nvarchar) { Alias = "upload", Name = "Upload Field", Mandatory = false, SortOrder = 6, DataTypeDefinitionId = -90 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.NoEdit), DataTypeDatabaseType.Nvarchar) { Alias = "label", Name = "Label", Mandatory = false, SortOrder = 7, DataTypeDefinitionId = -92 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.DateTime), DataTypeDatabaseType.Date) { Alias = "dateTime", Name = "Date Time", Mandatory = false, SortOrder = 8, DataTypeDefinitionId = -36 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.ColorPicker), DataTypeDatabaseType.Nvarchar) { Alias = "colorPicker", Name = "Color Picker", Mandatory = false, SortOrder = 9, DataTypeDefinitionId = -37 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.FolderBrowser), DataTypeDatabaseType.Nvarchar) { Alias = "folderBrowser", Name = "Folder Browser", Mandatory = false, SortOrder = 10, DataTypeDefinitionId = -38 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.DropDownListMultiple), DataTypeDatabaseType.Nvarchar) { Alias = "ddlMultiple", Name = "Dropdown List Multiple", Mandatory = false, SortOrder = 11, DataTypeDefinitionId = -39 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.RadioButtonList), DataTypeDatabaseType.Nvarchar) { Alias = "rbList", Name = "Radio Button List", Mandatory = false, SortOrder = 12, DataTypeDefinitionId = -40 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.Date), DataTypeDatabaseType.Date) { Alias = "date", Name = "Date", Mandatory = false, SortOrder = 13, DataTypeDefinitionId = -41 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.DropDownList), DataTypeDatabaseType.Integer) { Alias = "ddl", Name = "Dropdown List", Mandatory = false, SortOrder = 14, DataTypeDefinitionId = -42 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.CheckBoxList), DataTypeDatabaseType.Nvarchar) { Alias = "chklist", Name = "Checkbox List", Mandatory = false, SortOrder = 15, DataTypeDefinitionId = -43 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.ContentPicker), DataTypeDatabaseType.Integer) { Alias = "contentPicker", Name = "Content Picker", Mandatory = false, SortOrder = 16, DataTypeDefinitionId = 1034 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.MediaPicker), DataTypeDatabaseType.Integer) { Alias = "mediaPicker", Name = "Media Picker", Mandatory = false, SortOrder = 17, DataTypeDefinitionId = 1035 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.MemberPicker), DataTypeDatabaseType.Integer) { Alias = "memberPicker", Name = "Member Picker", Mandatory = false, SortOrder = 18, DataTypeDefinitionId = 1036 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.UltraSimpleEditor), DataTypeDatabaseType.Ntext) { Alias = "simpleEditor", Name = "Ultra Simple Editor", Mandatory = false, SortOrder = 19, DataTypeDefinitionId = 1038 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.UltimatePicker), DataTypeDatabaseType.Ntext) { Alias = "ultimatePicker", Name = "Ultimate Picker", Mandatory = false, SortOrder = 20, DataTypeDefinitionId = 1039 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.RelatedLinks), DataTypeDatabaseType.Ntext) { Alias = "relatedLinks", Name = "Related Links", Mandatory = false, SortOrder = 21, DataTypeDefinitionId = 1040 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.Tags), DataTypeDatabaseType.Ntext) { Alias = "tags", Name = "Tags", Mandatory = false, SortOrder = 22, DataTypeDefinitionId = 1041 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.MacroContainer), DataTypeDatabaseType.Ntext) { Alias = "macroContainer", Name = "Macro Container", Mandatory = false, SortOrder = 23, DataTypeDefinitionId = 1042 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.ImageCropper), DataTypeDatabaseType.Ntext) { Alias = "imgCropper", Name = "Image Cropper", Mandatory = false, SortOrder = 24, DataTypeDefinitionId = 1043 });
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 });
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static MediaType CreateVideoMediaType()
|
||||
{
|
||||
var mediaType = new MediaType(-1)
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
/// </summary>
|
||||
public static void InitializeDatabase()
|
||||
{
|
||||
ConfigurationManager.AppSettings.Set(Core.Configuration.GlobalSettings.UmbracoConnectionName, @"datalayer=SQLCE4Umbraco.SqlCEHelper,SQLCE4Umbraco;data source=|DataDirectory|\UmbracoPetaPocoTests.sdf");
|
||||
ConfigurationManager.AppSettings.Set(Core.Configuration.GlobalSettings.UmbracoConnectionName, @"datalayer=SQLCE4Umbraco.SqlCEHelper,SQLCE4Umbraco;data source=|DataDirectory|\UmbracoPetaPocoTests.sdf;Flush Interval=1;File Access Retry Timeout=10");
|
||||
|
||||
ClearDatabase();
|
||||
|
||||
|
||||
@@ -48,9 +48,9 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
|
||||
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -185,9 +185,13 @@
|
||||
<Compile Include="Configurations\FileSystemProviderTests.cs" />
|
||||
<Compile Include="CoreXml\FrameworkXmlTests.cs" />
|
||||
<Compile Include="Integration\CreateContent.cs" />
|
||||
<Compile Include="Models\ContentExtensionsTests.cs" />
|
||||
<Compile Include="Models\DataValueSetterTests.cs" />
|
||||
<Compile Include="Persistence\PetaPocoExtensionsTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\UserRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\UserTypeRepositoryTest.cs" />
|
||||
<Compile Include="Services\PackagingServiceTests.cs" />
|
||||
<Compile Include="Services\PerformanceTests.cs" />
|
||||
<Compile Include="Services\UserServiceTests.cs" />
|
||||
<Compile Include="TestHelpers\BaseSeleniumTest.cs" />
|
||||
<Compile Include="Integration\InstallPackage.cs" />
|
||||
|
||||
@@ -10,6 +10,38 @@ namespace Umbraco.Tests
|
||||
[TestFixture]
|
||||
public class UriExtensionsTests
|
||||
{
|
||||
[TestCase("http://www.domain.com/umbraco", true)]
|
||||
[TestCase("http://www.domain.com/Umbraco/", true)]
|
||||
[TestCase("http://www.domain.com/umbraco/default.aspx", true)]
|
||||
[TestCase("http://www.domain.com/umbraco/test/test", true)]
|
||||
[TestCase("http://www.domain.com/Umbraco/test/test.aspx", true)]
|
||||
[TestCase("http://www.domain.com/umbraco/test/test.js", true)]
|
||||
[TestCase("http://www.domain.com/umbrac", false)]
|
||||
[TestCase("http://www.domain.com/test", false)]
|
||||
[TestCase("http://www.domain.com/test/umbraco", false)]
|
||||
[TestCase("http://www.domain.com/test/umbraco.aspx", false)]
|
||||
public void Is_Back_Office_Request(string input, bool expected)
|
||||
{
|
||||
var source = new Uri(input);
|
||||
Assert.AreEqual(expected, source.IsBackOfficeRequest());
|
||||
}
|
||||
|
||||
[TestCase("http://www.domain.com/install", true)]
|
||||
[TestCase("http://www.domain.com/Install/", true)]
|
||||
[TestCase("http://www.domain.com/install/default.aspx", true)]
|
||||
[TestCase("http://www.domain.com/install/test/test", true)]
|
||||
[TestCase("http://www.domain.com/Install/test/test.aspx", true)]
|
||||
[TestCase("http://www.domain.com/install/test/test.js", true)]
|
||||
[TestCase("http://www.domain.com/instal", false)]
|
||||
[TestCase("http://www.domain.com/umbraco", false)]
|
||||
[TestCase("http://www.domain.com/umbraco/umbraco", false)]
|
||||
[TestCase("http://www.domain.com/test/umbraco.aspx", false)]
|
||||
public void Is_Installer_Request(string input, bool expected)
|
||||
{
|
||||
var source = new Uri(input);
|
||||
Assert.AreEqual(expected, source.IsInstallerRequest());
|
||||
}
|
||||
|
||||
[TestCase("http://www.domain.com/foo/bar", "/", "http://www.domain.com/")]
|
||||
[TestCase("http://www.domain.com/foo/bar#hop", "/", "http://www.domain.com/")]
|
||||
[TestCase("http://www.domain.com/foo/bar?q=2#hop", "/", "http://www.domain.com/?q=2")]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
|
||||
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
<appender-ref ref="ConsoleAppender" />
|
||||
</root>
|
||||
|
||||
<logger name="Umbraco.Core.Publishing.PublishingStrategy">
|
||||
<level value="WARN" />
|
||||
</logger>
|
||||
|
||||
<logger name="Umbraco.Core.PluginManager">
|
||||
<level value="WARN" />
|
||||
</logger>
|
||||
@@ -13,6 +17,10 @@
|
||||
<level value="WARN" />
|
||||
</logger>
|
||||
|
||||
<logger name="Umbraco.Core.Persistence.Migrations.Initial.DatabaseSchemaCreation">
|
||||
<level value="WARN" />
|
||||
</logger>
|
||||
|
||||
<logger name="Umbraco.Core.Persistence.Migrations.Initial.BaseDataCreation">
|
||||
<level value="WARN" />
|
||||
</logger>
|
||||
|
||||
@@ -108,9 +108,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\ClientDependency-Mvc.1.7.0.4\lib\ClientDependency.Core.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
|
||||
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=1.2.11.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -916,6 +916,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Langs\no.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Langs\pl.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Langs\pt.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Langs\ru.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Langs\sv.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Langs\zh.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\license.txt" />
|
||||
@@ -936,6 +937,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\Langs\no_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\Langs\pl_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\Langs\pt_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advhr\rule.htm" />
|
||||
@@ -958,6 +960,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advimage\Langs\no_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advimage\Langs\pl_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advimage\Langs\pt_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advimage\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advimage\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advimage\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Css\advlink.css" />
|
||||
@@ -977,6 +980,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Langs\no_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Langs\pl_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Langs\pt_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Advlink\link.htm" />
|
||||
@@ -1029,6 +1033,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Emotions\Langs\no_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Emotions\Langs\pl_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Emotions\Langs\pt_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Emotions\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Emotions\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Emotions\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Example\dialog.htm" />
|
||||
@@ -1058,6 +1063,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullpage\Langs\no_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullpage\Langs\pl_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullpage\Langs\pt_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullpage\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullpage\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullpage\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Fullscreen\editor_plugin.js" />
|
||||
@@ -1091,6 +1097,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Layer\editor_plugin_src.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Legacyoutput\editor_plugin.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Legacyoutput\editor_plugin_src.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Media\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Lists\editor_plugin.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Lists\editor_plugin_src.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Media\Css\media.css" />
|
||||
@@ -1140,6 +1147,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\Langs\no_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\Langs\pl_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\Langs\pt_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Paste\pastetext.htm" />
|
||||
@@ -1170,6 +1178,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\Langs\no_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\Langs\pl_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\Langs\pt_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Searchreplace\searchreplace.htm" />
|
||||
@@ -1194,6 +1203,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\Langs\no_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\Langs\pl_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\Langs\pt_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Style\props.htm" />
|
||||
@@ -1223,6 +1233,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\Langs\no_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\Langs\pl_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\Langs\pt_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Table\merge_cells.htm" />
|
||||
@@ -1246,6 +1257,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\Langs\no_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\Langs\pl_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\Langs\pt_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Template\template.htm" />
|
||||
@@ -1260,8 +1272,12 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\en_us_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\it.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\it_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\ja.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\ja_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\ru.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\sv.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\zh.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracocss\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\dialog.htm" />
|
||||
@@ -1270,6 +1286,8 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Img\ajax-loader.gif" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Img\embed.gif" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Js\dialog.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\da.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\da_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\de.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\de_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\en.js" />
|
||||
@@ -1278,8 +1296,12 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\en_us_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\it.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\it_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\ja.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\ja_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\ru.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\sv.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\zh.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoembed\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\editor_plugin_src.js" />
|
||||
@@ -1287,8 +1309,10 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\en_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\en_us_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\he_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\it_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\ja_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracoimg\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\editor_plugin_src.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\Js\umbracolink.js" />
|
||||
@@ -1297,6 +1321,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\Langs\he_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\Langs\ja_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracolink\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\dialog.htm" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\editor_plugin_src.js" />
|
||||
@@ -1312,6 +1337,8 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\ja_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\ru.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\sv.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\zh.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracomacro\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Umbracopaste\editor_plugin_src.js" />
|
||||
@@ -1353,6 +1380,7 @@
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Xhtmlxtras\Langs\no_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Xhtmlxtras\Langs\pl_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Xhtmlxtras\Langs\pt_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Xhtmlxtras\Langs\ru_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Xhtmlxtras\Langs\sv_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Plugins\Xhtmlxtras\Langs\zh_dlg.js" />
|
||||
<Content Include="Umbraco_Client\Tinymce3\Themes\Advanced\about.htm" />
|
||||
@@ -2574,9 +2602,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>6130</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>6140</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:6130</IISUrl>
|
||||
<IISUrl>http://localhost:6140</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -21,7 +21,7 @@ More information and documentation can be found on CodePlex: http://umbracoexami
|
||||
|
||||
<!-- default external indexer, which excludes protected and published pages-->
|
||||
<add name="ExternalIndexer" type="UmbracoExamine.UmbracoContentIndexer, UmbracoExamine"/>
|
||||
|
||||
|
||||
</providers>
|
||||
</ExamineIndexProviders>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<user>0</user>
|
||||
<startNode>1080</startNode>
|
||||
<fullTree>False</fullTree>
|
||||
<documentTypeAlias>Home</documentTypeAlias>
|
||||
<documentTypeAlias>Base</documentTypeAlias>
|
||||
<fields>
|
||||
<categories>
|
||||
</categories>
|
||||
@@ -14,6 +14,6 @@
|
||||
<excerpt>
|
||||
</excerpt>
|
||||
</fields>
|
||||
<mediaObjectSupport enabled="True" folderId="-1" mediaTypeAlias="image" mediaTypeFileProperty="umbracoFile" />
|
||||
<mediaObjectSupport enabled="True" folderId="-1" mediaTypeAlias="Image" mediaTypeFileProperty="umbracoFile" />
|
||||
</channel>
|
||||
</metablogapi>
|
||||
@@ -2,7 +2,7 @@
|
||||
<packages>
|
||||
<package id="ClientDependency" version="1.7.0.4" targetFramework="net40" />
|
||||
<package id="ClientDependency-Mvc" version="1.7.0.4" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
|
||||
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
|
||||
|
||||
@@ -406,7 +406,7 @@
|
||||
<key alias="renewSession">Förnya nu för att spara ditt arbete</key>
|
||||
</area>
|
||||
<area alias="login">
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - {0} <br /><a href="http://umbraco.org" style="text-decoration: none" target="_blank">umbraco.org</a></p> ]]></key>
|
||||
<key alias="bottomText"><![CDATA[<p style="text-align:right;">© 2001 - %0% <br /><a href="http://umbraco.org" style="text-decoration: none" target="_blank">umbraco.org</a></p> ]]></key>
|
||||
<key alias="topText">Välkommen till umbraco, skriv ditt användarnamn och lösenord i textfälten nedan:</key>
|
||||
</area>
|
||||
<area alias="main">
|
||||
@@ -757,4 +757,4 @@
|
||||
<key alias="userTypes">Användartyper</key>
|
||||
<key alias="writer">Skribent</key>
|
||||
</area>
|
||||
</language>
|
||||
</language>
|
||||
|
||||
@@ -1,16 +1,34 @@
|
||||
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="passwordChanger.ascx.cs" Inherits="umbraco.controls.passwordChanger" %>
|
||||
|
||||
<a href="#" onclick="if (document.getElementById('umbPasswordChanger').style.display == '' || document.getElementById('umbPasswordChanger').style.display == 'none') {document.getElementById('umbPasswordChanger').style.display = 'block'; this.style.display = 'none';}">Change password</a><br />
|
||||
<script type="text/javascript">
|
||||
(function ($) {
|
||||
Umbraco.Sys.registerNamespace("Umbraco.Controls");
|
||||
Umbraco.Controls.PasswordChanger = {
|
||||
toggle: function (e) {
|
||||
if (!$("#umbPasswordChanger").is(":visible")) {
|
||||
ValidatorEnable(document.getElementById('<%=CompareValidator1.ClientID %>'), true);
|
||||
$(e).closest(".propertyItem").replaceWith($("#umbPasswordChanger"));
|
||||
$("#umbPasswordChanger").show();
|
||||
$(e).hide();
|
||||
}
|
||||
}
|
||||
};
|
||||
})(jQuery);
|
||||
</script>
|
||||
|
||||
<div id="umbPasswordChanger" style="display: none;">
|
||||
<table>
|
||||
<tr><th style="width: 270px;"><%=umbraco.ui.GetText("user", "newPassword")%>:</th><td style="width: 359px">
|
||||
<asp:TextBox ID="umbPasswordChanger_passwordNew" autocomplete="off" AutoCompleteType="None" TextMode="password" runat="server"></asp:TextBox>
|
||||
</td></tr>
|
||||
<tr><th><%=umbraco.ui.GetText("user", "confirmNewPassword")%>:</th><td style="width: 359px">
|
||||
<asp:TextBox ID="umbPasswordChanger_passwordNewConfirm" autocomplete="off" AutoCompleteType="None" TextMode="password" runat="server"></asp:TextBox>
|
||||
<asp:CompareValidator ID="CompareValidator1" runat="server" ErrorMessage="Passwords must match" ControlToValidate="umbPasswordChanger_passwordNew"
|
||||
ControlToCompare="umbPasswordChanger_passwordNewConfirm" Operator="Equal"></asp:CompareValidator>
|
||||
</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<a href="#" onclick="Umbraco.Controls.PasswordChanger.toggle(this);">Change password</a><br />
|
||||
|
||||
<div class="propertyItem" id="umbPasswordChanger" style="display: none;">
|
||||
|
||||
<div class="propertyItemheader"><%=umbraco.ui.GetText("user", "newPassword")%></div>
|
||||
<div class="propertyItemContent">
|
||||
<asp:TextBox ID="umbPasswordChanger_passwordNew" autocomplete="off" AutoCompleteType="None" TextMode="password" runat="server"></asp:TextBox>
|
||||
</div>
|
||||
|
||||
<div class="propertyItemheader"><%=umbraco.ui.GetText("user", "confirmNewPassword")%></div>
|
||||
<div class="propertyItemContent">
|
||||
<asp:TextBox ID="umbPasswordChanger_passwordNewConfirm" autocomplete="off" AutoCompleteType="None" TextMode="password" runat="server"></asp:TextBox>
|
||||
<asp:CompareValidator ID="CompareValidator1" runat="server" Enabled="False" ErrorMessage="Passwords must match" ControlToValidate="umbPasswordChanger_passwordNew"
|
||||
ControlToCompare="umbPasswordChanger_passwordNewConfirm" Operator="Equal"></asp:CompareValidator>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<%@ Page Language="c#" CodeBehind="EditNodeTypeNew.aspx.cs" AutoEventWireup="True"
|
||||
<%@ Page Language="c#" CodeBehind="EditNodeTypeNew.aspx.cs" AutoEventWireup="True" ValidateRequest="false"
|
||||
Async="true" AsyncTimeOut="300" Trace="false" Inherits="Umbraco.Web.UI.Umbraco.Settings.EditNodeTypeNew" MasterPageFile="../masterpages/umbracoPage.Master" %>
|
||||
|
||||
<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
|
||||
|
||||
@@ -64,7 +64,16 @@
|
||||
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||
</dependentAssembly>
|
||||
|
||||
|
||||
<dependentAssembly xdt:Transform="Remove"
|
||||
xdt:Locator="Condition(_defaultNamespace:assemblyIdentity[@name='HtmlAgilityPack']])"/>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="1.4.5.0-1.4.6.0" newVersion="1.4.6.0" />
|
||||
</dependentAssembly>
|
||||
|
||||
</assemblyBinding>
|
||||
|
||||
</runtime>
|
||||
|
||||
</configuration>
|
||||
@@ -269,6 +269,12 @@
|
||||
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35"/>
|
||||
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
|
||||
<!-- Ensure correct version of HtmlAgilityPack -->
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="1.4.5.0-1.4.6.0" newVersion="1.4.6.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
|
||||
@@ -466,7 +466,7 @@ namespace Umbraco.Web
|
||||
Mandate.ParameterNotNullOrEmpty(action, "action");
|
||||
Mandate.ParameterNotNullOrEmpty(controllerName, "controllerName");
|
||||
|
||||
var formAction = UmbracoContext.Current.OriginalRequestUrl.ToString();
|
||||
var formAction = UmbracoContext.Current.OriginalRequestUrl.PathAndQuery;
|
||||
return html.RenderForm(formAction, FormMethod.Post, htmlAttributes, controllerName, action, area, additionalRouteVals);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,9 +13,23 @@ namespace Umbraco.Web.Install
|
||||
/// </summary>
|
||||
internal class UmbracoInstallAuthorizeAttribute : AuthorizeAttribute
|
||||
{
|
||||
private readonly ApplicationContext _applicationContext;
|
||||
private readonly ApplicationContext _applicationContext;
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
|
||||
private ApplicationContext GetApplicationContext()
|
||||
{
|
||||
return _applicationContext ?? ApplicationContext.Current;
|
||||
}
|
||||
|
||||
private UmbracoContext GetUmbracoContext()
|
||||
{
|
||||
return _umbracoContext ?? UmbracoContext.Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// THIS SHOULD BE ONLY USED FOR UNIT TESTS
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
public UmbracoInstallAuthorizeAttribute(UmbracoContext umbracoContext)
|
||||
{
|
||||
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
|
||||
@@ -23,11 +37,9 @@ namespace Umbraco.Web.Install
|
||||
_applicationContext = _umbracoContext.Application;
|
||||
}
|
||||
|
||||
public UmbracoInstallAuthorizeAttribute()
|
||||
: this(UmbracoContext.Current)
|
||||
{
|
||||
|
||||
}
|
||||
public UmbracoInstallAuthorizeAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the user must be logged in or that the application is not configured just yet.
|
||||
@@ -41,13 +53,13 @@ namespace Umbraco.Web.Install
|
||||
try
|
||||
{
|
||||
//if its not configured then we can continue
|
||||
if (!_applicationContext.IsConfigured)
|
||||
if (!GetApplicationContext().IsConfigured)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var umbCtx = GetUmbracoContext();
|
||||
//otherwise we need to ensure that a user is logged in
|
||||
var isLoggedIn = _umbracoContext.Security.ValidateUserContextId(_umbracoContext.Security.UmbracoUserContextId);
|
||||
var isLoggedIn = umbCtx.Security.ValidateUserContextId(umbCtx.Security.UmbracoUserContextId);
|
||||
if (isLoggedIn)
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -18,18 +18,24 @@ namespace Umbraco.Web.Mvc
|
||||
public sealed class MemberAuthorizeAttribute : AuthorizeAttribute
|
||||
{
|
||||
|
||||
private readonly ApplicationContext _applicationContext;
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
|
||||
private UmbracoContext GetUmbracoContext()
|
||||
{
|
||||
return _umbracoContext ?? UmbracoContext.Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// THIS SHOULD BE ONLY USED FOR UNIT TESTS
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
public MemberAuthorizeAttribute(UmbracoContext umbracoContext)
|
||||
{
|
||||
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
|
||||
_umbracoContext = umbracoContext;
|
||||
_applicationContext = _umbracoContext.Application;
|
||||
}
|
||||
|
||||
public MemberAuthorizeAttribute()
|
||||
: this(UmbracoContext.Current)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -76,7 +82,7 @@ namespace Umbraco.Web.Mvc
|
||||
}
|
||||
}
|
||||
|
||||
return _umbracoContext.Security.IsMemberAuthorized(AllowAll,
|
||||
return GetUmbracoContext().Security.IsMemberAuthorized(AllowAll,
|
||||
AllowType.Split(','),
|
||||
AllowGroup.Split(','),
|
||||
members);
|
||||
|
||||
@@ -15,6 +15,20 @@ namespace Umbraco.Web.Mvc
|
||||
private readonly ApplicationContext _applicationContext;
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
|
||||
private ApplicationContext GetApplicationContext()
|
||||
{
|
||||
return _applicationContext ?? ApplicationContext.Current;
|
||||
}
|
||||
|
||||
private UmbracoContext GetUmbracoContext()
|
||||
{
|
||||
return _umbracoContext ?? UmbracoContext.Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// THIS SHOULD BE ONLY USED FOR UNIT TESTS
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
public UmbracoAuthorizeAttribute(UmbracoContext umbracoContext)
|
||||
{
|
||||
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
|
||||
@@ -22,11 +36,9 @@ namespace Umbraco.Web.Mvc
|
||||
_applicationContext = _umbracoContext.Application;
|
||||
}
|
||||
|
||||
public UmbracoAuthorizeAttribute()
|
||||
: this(UmbracoContext.Current)
|
||||
{
|
||||
|
||||
}
|
||||
public UmbracoAuthorizeAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the user must be in the Administrator or the Install role
|
||||
@@ -40,9 +52,10 @@ namespace Umbraco.Web.Mvc
|
||||
try
|
||||
{
|
||||
//we need to that the app is configured and that a user is logged in
|
||||
if (!_applicationContext.IsConfigured)
|
||||
if (!GetApplicationContext().IsConfigured)
|
||||
return false;
|
||||
var isLoggedIn = _umbracoContext.Security.ValidateUserContextId(_umbracoContext.Security.UmbracoUserContextId);
|
||||
var umbCtx = GetUmbracoContext();
|
||||
var isLoggedIn = umbCtx.Security.ValidateUserContextId(umbCtx.Security.UmbracoUserContextId);
|
||||
return isLoggedIn;
|
||||
}
|
||||
catch (Exception)
|
||||
|
||||
@@ -20,20 +20,8 @@ namespace Umbraco.Web.Mvc
|
||||
[UmbracoAuthorize]
|
||||
public abstract class UmbracoAuthorizedController : UmbracoController
|
||||
{
|
||||
|
||||
private User _user;
|
||||
private bool _userisValidated = false;
|
||||
|
||||
/// <summary>
|
||||
/// The current user ID
|
||||
/// </summary>
|
||||
private int _uid = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The page timeout in seconds.
|
||||
/// </summary>
|
||||
private long _timeout = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the currently logged in Umbraco User
|
||||
/// </summary>
|
||||
@@ -41,40 +29,15 @@ namespace Umbraco.Web.Mvc
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_userisValidated) ValidateUser();
|
||||
return _user;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateUser()
|
||||
{
|
||||
if ((UmbracoContext.Security.UmbracoUserContextId != ""))
|
||||
{
|
||||
_uid = UmbracoContext.Security.GetUserId(UmbracoContext.Security.UmbracoUserContextId);
|
||||
_timeout = UmbracoContext.Security.GetTimeout(UmbracoContext.Security.UmbracoUserContextId);
|
||||
|
||||
if (_timeout > DateTime.Now.Ticks)
|
||||
//throw exceptions if not valid (true)
|
||||
if (!_userisValidated)
|
||||
{
|
||||
_user = global::umbraco.BusinessLogic.User.GetUser(_uid);
|
||||
|
||||
// Check for console access
|
||||
if (_user.Disabled || (_user.NoConsole && GlobalSettings.RequestIsInUmbracoApplication(HttpContext) && !GlobalSettings.RequestIsLiveEditRedirector(HttpContext)))
|
||||
{
|
||||
throw new ArgumentException("You have no priviledges to the umbraco console. Please contact your administrator");
|
||||
}
|
||||
Security.ValidateCurrentUser(HttpContext, true);
|
||||
_userisValidated = true;
|
||||
UmbracoContext.Security.UpdateLogin(_timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("User has timed out!!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("The user has no umbraco contextid - try logging in");
|
||||
}
|
||||
|
||||
return Security.CurrentUser;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// Releases the specified controller.
|
||||
/// </summary>
|
||||
/// <param name="controller">The controller.</param>
|
||||
public void ReleaseController(IController controller)
|
||||
public virtual void ReleaseController(IController controller)
|
||||
{
|
||||
_innerFactory.ReleaseController(controller);
|
||||
}
|
||||
|
||||
@@ -71,46 +71,5 @@ namespace Umbraco.Web.Mvc
|
||||
: new UmbracoHelper(UmbracoContext, Model.Content));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will detect the end /body tag and insert the preview badge if in preview mode
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public override void WriteLiteral(object value)
|
||||
{
|
||||
// filter / add preview banner
|
||||
if (Response.ContentType.InvariantEquals("text/html")) // ASP.NET default value
|
||||
{
|
||||
|
||||
if (UmbracoContext.Current.IsDebug || UmbracoContext.Current.InPreviewMode)
|
||||
{
|
||||
var text = value.ToString().ToLowerInvariant();
|
||||
int pos = text.IndexOf("</body>");
|
||||
if (pos > -1)
|
||||
{
|
||||
if (UmbracoContext.Current.InPreviewMode)
|
||||
{
|
||||
var htmlBadge =
|
||||
String.Format(UmbracoSettings.PreviewBadge,
|
||||
IOHelper.ResolveUrl(SystemDirectories.Umbraco),
|
||||
IOHelper.ResolveUrl(SystemDirectories.UmbracoClient),
|
||||
Server.UrlEncode(UmbracoContext.Current.HttpContext.Request.Path));
|
||||
|
||||
text = text.Substring(0, pos) + htmlBadge + text.Substring(pos, text.Length - pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
var profilerMarkup = this.Html.RenderProfiler();
|
||||
text = text.Substring(0, pos) + profilerMarkup + text.Substring(pos, text.Length - pos);
|
||||
}
|
||||
base.WriteLiteral(text);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.WriteLiteral(value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Web.Routing;
|
||||
|
||||
namespace Umbraco.Web.Mvc
|
||||
@@ -112,5 +116,49 @@ namespace Umbraco.Web.Mvc
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will detect the end /body tag and insert the preview badge if in preview mode
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public override void WriteLiteral(object value)
|
||||
{
|
||||
// filter / add preview banner
|
||||
if (Response.ContentType.InvariantEquals("text/html")) // ASP.NET default value
|
||||
{
|
||||
if (UmbracoContext.Current.IsDebug || UmbracoContext.Current.InPreviewMode)
|
||||
{
|
||||
var text = value.ToString().ToLowerInvariant();
|
||||
var pos = text.IndexOf("</body>", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
if (pos > -1)
|
||||
{
|
||||
string markupToInject;
|
||||
|
||||
if (UmbracoContext.Current.InPreviewMode)
|
||||
{
|
||||
// creating previewBadge markup
|
||||
markupToInject =
|
||||
String.Format(UmbracoSettings.PreviewBadge,
|
||||
IOHelper.ResolveUrl(SystemDirectories.Umbraco),
|
||||
IOHelper.ResolveUrl(SystemDirectories.UmbracoClient),
|
||||
Server.UrlEncode(UmbracoContext.Current.HttpContext.Request.Path));
|
||||
}
|
||||
else
|
||||
{
|
||||
// creating mini-profiler markup
|
||||
markupToInject = Html.RenderProfiler().ToHtmlString();
|
||||
}
|
||||
|
||||
var sb = new StringBuilder(text);
|
||||
sb.Insert(pos, markupToInject);
|
||||
|
||||
base.WriteLiteral(sb.ToString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.WriteLiteral(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ namespace Umbraco.Web.Routing
|
||||
|
||||
response.Write("<html><body><h1>Page not found</h1>");
|
||||
response.Write("<h3>");
|
||||
response.Write(string.Format(reason, HttpUtility.HtmlEncode(UmbracoContext.Current.OriginalRequestUrl)));
|
||||
response.Write(string.Format(reason, HttpUtility.HtmlEncode(UmbracoContext.Current.OriginalRequestUrl.PathAndQuery)));
|
||||
response.Write("</h3>");
|
||||
if (!string.IsNullOrWhiteSpace(_message))
|
||||
response.Write("<p>" + _message + "</p>");
|
||||
|
||||
@@ -5,12 +5,15 @@ using System.Web;
|
||||
using System.Web.Security;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Security;
|
||||
using umbraco;
|
||||
using umbraco.BusinessLogic;
|
||||
using umbraco.DataLayer;
|
||||
using umbraco.businesslogic.Exceptions;
|
||||
using umbraco.cms.businesslogic.member;
|
||||
using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings;
|
||||
using UmbracoSettings = Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Web.Security
|
||||
{
|
||||
@@ -128,7 +131,7 @@ namespace Umbraco.Web.Security
|
||||
SqlHelper.CreateParameter("@contextId", retVal));
|
||||
UmbracoUserContextId = retVal.ToString();
|
||||
|
||||
LogHelper.Info(typeof(WebSecurity), "User Id: {0} logged in", () => userId);
|
||||
LogHelper.Info<WebSecurity>("User Id: {0} logged in", () => userId);
|
||||
|
||||
}
|
||||
|
||||
@@ -147,8 +150,11 @@ namespace Umbraco.Web.Security
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error(typeof(WebSecurity), string.Format("Login with contextId {0} didn't exist in the database", UmbracoUserContextId), ex);
|
||||
LogHelper.Error<WebSecurity>(string.Format("Login with contextId {0} didn't exist in the database", UmbracoUserContextId), ex);
|
||||
}
|
||||
|
||||
//this clears the cookie
|
||||
UmbracoUserContextId = "";
|
||||
}
|
||||
|
||||
public void RenewLoginTimeout()
|
||||
@@ -366,53 +372,51 @@ namespace Umbraco.Web.Security
|
||||
/// </summary>
|
||||
/// <value>The umbraco user context ID.</value>
|
||||
public string UmbracoUserContextId
|
||||
{
|
||||
{
|
||||
get
|
||||
{
|
||||
if (StateHelper.Cookies.HasCookies && StateHelper.Cookies.UserContext.HasValue)
|
||||
var authTicket = HttpContext.Current.GetUmbracoAuthTicket();
|
||||
if (authTicket == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var encTicket = StateHelper.Cookies.UserContext.GetValue();
|
||||
if (string.IsNullOrEmpty(encTicket) == false)
|
||||
{
|
||||
return encTicket.DecryptWithMachineKey();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is ArgumentException || ex is FormatException || ex is HttpException)
|
||||
{
|
||||
StateHelper.Cookies.UserContext.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
var identity = authTicket.CreateUmbracoIdentity();
|
||||
if (identity == null)
|
||||
{
|
||||
HttpContext.Current.UmbracoLogout();
|
||||
return "";
|
||||
}
|
||||
return identity.UserContextId;
|
||||
}
|
||||
set
|
||||
{
|
||||
// zb-00004 #29956 : refactor cookies names & handling
|
||||
if (StateHelper.Cookies.HasCookies)
|
||||
if (value.IsNullOrWhiteSpace())
|
||||
{
|
||||
// Clearing all old cookies before setting a new one.
|
||||
if (StateHelper.Cookies.UserContext.HasValue)
|
||||
StateHelper.Cookies.ClearAll();
|
||||
|
||||
if (string.IsNullOrEmpty(value) == false)
|
||||
HttpContext.Current.UmbracoLogout();
|
||||
}
|
||||
else
|
||||
{
|
||||
var uid = GetUserId(value);
|
||||
if (uid == -1)
|
||||
{
|
||||
// Encrypt the value
|
||||
var encTicket = value.EncryptWithMachineKey();
|
||||
|
||||
// Create new cookie.
|
||||
StateHelper.Cookies.UserContext.SetValue(encTicket, 1);
|
||||
HttpContext.Current.UmbracoLogout();
|
||||
}
|
||||
else
|
||||
{
|
||||
StateHelper.Cookies.UserContext.Clear();
|
||||
var user = User.GetUser(uid);
|
||||
HttpContext.Current.CreateUmbracoAuthTicket(
|
||||
new UserData
|
||||
{
|
||||
Id = uid,
|
||||
AllowedApplications = user.Applications.Select(x => x.alias).ToArray(),
|
||||
Culture = ui.Culture(user),
|
||||
RealName = user.Name,
|
||||
Roles = new string[] { user.UserType.Alias },
|
||||
StartContentNode = user.StartNodeId,
|
||||
StartMediaNode = user.StartMediaId,
|
||||
UserContextId = value,
|
||||
Username = user.LoginName
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,13 +77,8 @@ namespace Umbraco.Web.Strategies
|
||||
//if it is not a document request, we'll check if it is a back end request
|
||||
if (e.Outcome == EnsureRoutableOutcome.NotDocumentRequest)
|
||||
{
|
||||
var authority = e.HttpContext.Request.Url.GetLeftPart(UriPartial.Authority);
|
||||
var afterAuthority = e.HttpContext.Request.Url.GetLeftPart(UriPartial.Query)
|
||||
.TrimStart(authority)
|
||||
.TrimStart("/");
|
||||
|
||||
//check if this is in the umbraco back office
|
||||
if (afterAuthority.InvariantStartsWith(GlobalSettings.Path.TrimStart("/")))
|
||||
if (e.HttpContext.Request.Url.IsBackOfficeRequest())
|
||||
{
|
||||
//yup it's a back office request!
|
||||
using (var lck = new UpgradeableReadLock(Locker))
|
||||
|
||||
@@ -51,14 +51,6 @@ namespace Umbraco.Web.UI.Pages
|
||||
Response.Redirect(SystemDirectories.Umbraco + "/logout.aspx?redir=" + Server.UrlEncode(Request.RawUrl), true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInit(EventArgs e)
|
||||
{
|
||||
base.OnInit(e);
|
||||
|
||||
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(ui.Culture(Security.CurrentUser));
|
||||
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the app that this page is assigned to
|
||||
|
||||
@@ -101,9 +101,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\xmlrpcnet.2.5.0\lib\net20\CookComputing.XmlRpcV2.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
|
||||
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.6.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -1935,7 +1935,9 @@
|
||||
</Content>
|
||||
<Content Include="umbraco.presentation\umbraco\developer\Macros\assemblyBrowser.aspx" />
|
||||
<Content Include="umbraco.presentation\umbraco\developer\autoDoc.aspx" />
|
||||
<Content Include="umbraco.presentation\umbraco\developer\DataTypes\editDatatype.aspx" />
|
||||
<Content Include="umbraco.presentation\umbraco\developer\DataTypes\editDatatype.aspx">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Content>
|
||||
<Content Include="umbraco.presentation\umbraco\developer\Xslt\getXsltStatus.asmx" />
|
||||
<Content Include="umbraco.presentation\umbraco\developer\Cache\viewCacheItem.aspx" />
|
||||
<Content Include="umbraco.presentation\umbraco\developer\Xslt\xsltChooseExtension.aspx" />
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Umbraco.Web
|
||||
/// <summary>
|
||||
/// Class that encapsulates Umbraco information of a specific HTTP request
|
||||
/// </summary>
|
||||
public class UmbracoContext
|
||||
public class UmbracoContext : DisposableObject
|
||||
{
|
||||
private const string HttpContextItemName = "Umbraco.Web.UmbracoContext";
|
||||
private static readonly object Locker = new object();
|
||||
@@ -361,7 +361,17 @@ namespace Umbraco.Web
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
Security.DisposeIfDisposable();
|
||||
Security = null;
|
||||
_previewContent = null;
|
||||
_umbracoContext = null;
|
||||
//ensure not to dispose this!
|
||||
Application = null;
|
||||
ContentCache = null;
|
||||
MediaCache = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,18 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Routing;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Web.Routing;
|
||||
using umbraco;
|
||||
using umbraco.BasePages;
|
||||
using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings;
|
||||
using UmbracoSettings = Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Web.Configuration;
|
||||
@@ -28,7 +33,7 @@ namespace Umbraco.Web
|
||||
/// Begins to process a request.
|
||||
/// </summary>
|
||||
/// <param name="httpContext"></param>
|
||||
void BeginRequest(HttpContextBase httpContext)
|
||||
static void BeginRequest(HttpContextBase httpContext)
|
||||
{
|
||||
//we need to set the initial url in our ApplicationContext, this is so our keep alive service works and this must
|
||||
//exist on a global context because the keep alive service doesn't run in a web context.
|
||||
@@ -118,6 +123,58 @@ namespace Umbraco.Web
|
||||
RewriteToUmbracoHandler(httpContext, pcr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the request is authenticated, if it is it sets the thread culture to the currently logged in user
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
static void AuthenticateRequest(object sender, EventArgs e)
|
||||
{
|
||||
var app = (HttpApplication)sender;
|
||||
var http = new HttpContextWrapper(app.Context);
|
||||
|
||||
// do not process if client-side request
|
||||
if (http.Request.Url.IsClientSideRequest())
|
||||
return;
|
||||
|
||||
if (app.Request.Url.IsBackOfficeRequest() || app.Request.Url.IsInstallerRequest())
|
||||
{
|
||||
var ticket = http.GetUmbracoAuthTicket();
|
||||
if (ticket != null)
|
||||
{
|
||||
//create the Umbraco user identity
|
||||
var identity = ticket.CreateUmbracoIdentity();
|
||||
if (identity != null)
|
||||
{
|
||||
|
||||
//We'll leave setting custom identies/principals for 6.2, for now we'll just ensure that the cultures, etc.. are set
|
||||
////set the principal object
|
||||
////now we need to see if their session is still valid
|
||||
//var timeout = BasePage.GetTimeout(identity.UserContextId);
|
||||
//if (timeout > DateTime.Now.Ticks)
|
||||
//{
|
||||
//var principal = new GenericPrincipal(identity, identity.Roles);
|
||||
////It is actually not good enough to set this on the current app Context and the thread, it also needs
|
||||
//// to be set explicitly on the HttpContext.Current !! This is a strange web api thing that is actually
|
||||
//// an underlying fault of asp.net not propogating the User correctly.
|
||||
//if (HttpContext.Current != null)
|
||||
//{
|
||||
// HttpContext.Current.User = principal;
|
||||
//}
|
||||
//app.Context.User = principal;
|
||||
//Thread.CurrentPrincipal = principal;
|
||||
//}
|
||||
|
||||
//This is a back office/installer request, we will also set the culture/ui culture
|
||||
Thread.CurrentThread.CurrentCulture =
|
||||
Thread.CurrentThread.CurrentUICulture =
|
||||
new System.Globalization.CultureInfo(identity.Culture);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// returns a value indicating whether redirection took place and the request has
|
||||
// been completed - because we don't want to Response.End() here to terminate
|
||||
// everything properly.
|
||||
@@ -166,23 +223,6 @@ namespace Umbraco.Web
|
||||
return end;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the xml cache file needs to be updated/persisted
|
||||
/// </summary>
|
||||
/// <param name="httpContext"></param>
|
||||
/// <remarks>
|
||||
/// TODO: This needs an overhaul, see the error report created here:
|
||||
/// https://docs.google.com/document/d/1neGE3q3grB4lVJfgID1keWY2v9JYqf-pw75sxUUJiyo/edit
|
||||
/// </remarks>
|
||||
void PersistXmlCache(HttpContextBase httpContext)
|
||||
{
|
||||
if (content.Instance.IsXmlQueuedForPersistenceToFile)
|
||||
{
|
||||
content.Instance.RemoveXmlFilePersistenceQueue();
|
||||
content.Instance.PersistXmlToFile();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Route helper methods
|
||||
@@ -350,7 +390,7 @@ namespace Umbraco.Web
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="pcr"> </param>
|
||||
private void RewriteToUmbracoHandler(HttpContextBase context, PublishedContentRequest pcr)
|
||||
private static void RewriteToUmbracoHandler(HttpContextBase context, PublishedContentRequest pcr)
|
||||
{
|
||||
// NOTE: we do not want to use TransferRequest even though many docs say it is better with IIS7, turns out this is
|
||||
// not what we need. The purpose of TransferRequest is to ensure that .net processes all of the rules for the newly
|
||||
@@ -402,6 +442,36 @@ namespace Umbraco.Web
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the xml cache file needs to be updated/persisted
|
||||
/// </summary>
|
||||
/// <param name="httpContext"></param>
|
||||
/// <remarks>
|
||||
/// TODO: This needs an overhaul, see the error report created here:
|
||||
/// https://docs.google.com/document/d/1neGE3q3grB4lVJfgID1keWY2v9JYqf-pw75sxUUJiyo/edit
|
||||
/// </remarks>
|
||||
static void PersistXmlCache(HttpContextBase httpContext)
|
||||
{
|
||||
if (content.Instance.IsXmlQueuedForPersistenceToFile)
|
||||
{
|
||||
content.Instance.RemoveXmlFilePersistenceQueue();
|
||||
content.Instance.PersistXmlToFile();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Any object that is in the HttpContext.Items collection that is IDisposable will get disposed on the end of the request
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
private static void DisposeHttpContextItems(HttpContext http)
|
||||
{
|
||||
foreach (DictionaryEntry i in http.Items)
|
||||
{
|
||||
i.Value.DisposeIfDisposable();
|
||||
i.Key.DisposeIfDisposable();
|
||||
}
|
||||
}
|
||||
|
||||
#region IHttpModule
|
||||
|
||||
/// <summary>
|
||||
@@ -419,6 +489,8 @@ namespace Umbraco.Web
|
||||
BeginRequest(new HttpContextWrapper(httpContext));
|
||||
};
|
||||
|
||||
app.AuthenticateRequest += AuthenticateRequest;
|
||||
|
||||
app.PostResolveRequestCache += (sender, e) =>
|
||||
{
|
||||
var httpContext = ((HttpApplication)sender).Context;
|
||||
@@ -469,18 +541,6 @@ namespace Umbraco.Web
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Any object that is in the HttpContext.Items collection that is IDisposable will get disposed on the end of the request
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
private static void DisposeHttpContextItems(HttpContext http)
|
||||
{
|
||||
foreach(var i in http.Items)
|
||||
{
|
||||
i.DisposeIfDisposable();
|
||||
}
|
||||
}
|
||||
|
||||
#region Events
|
||||
internal static event EventHandler<RoutableAttemptEventArgs> RouteAttempt;
|
||||
private void OnRouteAttempt(RoutableAttemptEventArgs args)
|
||||
|
||||
@@ -16,21 +16,27 @@ namespace Umbraco.Web.WebApi
|
||||
public sealed class MemberAuthorizeAttribute : AuthorizeAttribute
|
||||
{
|
||||
|
||||
private readonly ApplicationContext _applicationContext;
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
|
||||
private UmbracoContext GetUmbracoContext()
|
||||
{
|
||||
return _umbracoContext ?? UmbracoContext.Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// THIS SHOULD BE ONLY USED FOR UNIT TESTS
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
public MemberAuthorizeAttribute(UmbracoContext umbracoContext)
|
||||
{
|
||||
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
|
||||
_umbracoContext = umbracoContext;
|
||||
_applicationContext = _umbracoContext.Application;
|
||||
}
|
||||
|
||||
public MemberAuthorizeAttribute()
|
||||
: this(UmbracoContext.Current)
|
||||
{
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flag for whether to allow all site visitors or just authenticated members
|
||||
@@ -74,7 +80,7 @@ namespace Umbraco.Web.WebApi
|
||||
}
|
||||
}
|
||||
|
||||
return _umbracoContext.Security.IsMemberAuthorized(AllowAll,
|
||||
return GetUmbracoContext().Security.IsMemberAuthorized(AllowAll,
|
||||
AllowType.Split(','),
|
||||
AllowGroup.Split(','),
|
||||
members);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -22,6 +23,29 @@ namespace Umbraco.Web.WebApi
|
||||
Umbraco = new UmbracoHelper(umbracoContext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to retreive the current HttpContext if one exists.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected Attempt<HttpContextBase> TryGetHttpContext()
|
||||
{
|
||||
object context;
|
||||
if (Request.Properties.TryGetValue("MS_HttpContext", out context))
|
||||
{
|
||||
var httpContext = context as HttpContextBase;
|
||||
if (httpContext != null)
|
||||
{
|
||||
return new Attempt<HttpContextBase>(true, httpContext);
|
||||
}
|
||||
}
|
||||
if (HttpContext.Current != null)
|
||||
{
|
||||
return new Attempt<HttpContextBase>(true, new HttpContextWrapper(HttpContext.Current));
|
||||
}
|
||||
|
||||
return Attempt<HttpContextBase>.False;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current ApplicationContext
|
||||
/// </summary>
|
||||
|
||||
@@ -13,6 +13,20 @@ namespace Umbraco.Web.WebApi
|
||||
private readonly ApplicationContext _applicationContext;
|
||||
private readonly UmbracoContext _umbracoContext;
|
||||
|
||||
private ApplicationContext GetApplicationContext()
|
||||
{
|
||||
return _applicationContext ?? ApplicationContext.Current;
|
||||
}
|
||||
|
||||
private UmbracoContext GetUmbracoContext()
|
||||
{
|
||||
return _umbracoContext ?? UmbracoContext.Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// THIS SHOULD BE ONLY USED FOR UNIT TESTS
|
||||
/// </summary>
|
||||
/// <param name="umbracoContext"></param>
|
||||
public UmbracoAuthorizeAttribute(UmbracoContext umbracoContext)
|
||||
{
|
||||
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
|
||||
@@ -21,9 +35,7 @@ namespace Umbraco.Web.WebApi
|
||||
}
|
||||
|
||||
public UmbracoAuthorizeAttribute()
|
||||
: this(UmbracoContext.Current)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
|
||||
@@ -31,9 +43,10 @@ namespace Umbraco.Web.WebApi
|
||||
try
|
||||
{
|
||||
//we need to that the app is configured and that a user is logged in
|
||||
if (!_applicationContext.IsConfigured)
|
||||
if (!GetApplicationContext().IsConfigured)
|
||||
return false;
|
||||
var isLoggedIn = _umbracoContext.Security.ValidateUserContextId(_umbracoContext.Security.UmbracoUserContextId);
|
||||
var umbCtx = GetUmbracoContext();
|
||||
var isLoggedIn = umbCtx.Security.ValidateUserContextId(umbCtx.Security.UmbracoUserContextId);
|
||||
return isLoggedIn;
|
||||
}
|
||||
catch (Exception)
|
||||
|
||||
@@ -19,20 +19,9 @@ namespace Umbraco.Web.WebApi
|
||||
: base(umbracoContext)
|
||||
{
|
||||
}
|
||||
|
||||
private User _user;
|
||||
|
||||
private bool _userisValidated = false;
|
||||
|
||||
/// <summary>
|
||||
/// The current user ID
|
||||
/// </summary>
|
||||
private int _uid = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The page timeout in seconds.
|
||||
/// </summary>
|
||||
private long _timeout = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the currently logged in Umbraco User
|
||||
/// </summary>
|
||||
@@ -40,40 +29,19 @@ namespace Umbraco.Web.WebApi
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_userisValidated) ValidateUser();
|
||||
return _user;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateUser()
|
||||
{
|
||||
if ((UmbracoContext.Security.UmbracoUserContextId != ""))
|
||||
{
|
||||
_uid = UmbracoContext.Security.GetUserId(UmbracoContext.Security.UmbracoUserContextId);
|
||||
_timeout = UmbracoContext.Security.GetTimeout(UmbracoContext.Security.UmbracoUserContextId);
|
||||
|
||||
if (_timeout > DateTime.Now.Ticks)
|
||||
//throw exceptions if not valid (true)
|
||||
if (!_userisValidated)
|
||||
{
|
||||
_user = global::umbraco.BusinessLogic.User.GetUser(_uid);
|
||||
|
||||
// Check for console access
|
||||
if (_user.Disabled || (_user.NoConsole && GlobalSettings.RequestIsInUmbracoApplication(HttpContext.Current) && !GlobalSettings.RequestIsLiveEditRedirector(HttpContext.Current)))
|
||||
{
|
||||
throw new ArgumentException("You have no priviledges to the umbraco console. Please contact your administrator");
|
||||
}
|
||||
var ctx = TryGetHttpContext();
|
||||
if (ctx.Success == false)
|
||||
throw new InvalidOperationException("To get a current user, this method must occur in a web request");
|
||||
Security.ValidateCurrentUser(ctx.Result, true);
|
||||
_userisValidated = true;
|
||||
UmbracoContext.Security.UpdateLogin(_timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("User has timed out!!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("The user has no umbraco contextid - try logging in");
|
||||
}
|
||||
|
||||
return Security.CurrentUser;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
<packages>
|
||||
<package id="ClientDependency" version="1.7.0.4" targetFramework="net40" />
|
||||
<package id="CodeSharp.Package.AspNetWebPage" version="1.0" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
|
||||
<package id="HtmlAgilityPack" version="1.4.6" targetFramework="net40" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
|
||||
|
||||
-6
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using umbraco.presentation.LiveEditing.Modules;
|
||||
using ClientDependency.Core;
|
||||
using System.Web.UI.WebControls;
|
||||
@@ -13,9 +10,6 @@ using ClientDependency.Core.Controls;
|
||||
using umbraco.presentation.umbraco.controls;
|
||||
using HtmlAgilityPack;
|
||||
using umbraco.cms.businesslogic.template;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
|
||||
namespace umbraco.presentation.umbraco.LiveEditing.Modules.SkinModule
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user