Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a91669abc0 | |||
| 3b9db8a92f | |||
| 1bfc1229bd | |||
| 3d6fd2d785 | |||
| e56881abc6 | |||
| d32991c30a | |||
| 8758f9649b | |||
| 6f0f1ab2c3 | |||
| cd28240172 | |||
| 7002291c41 | |||
| 51bbf7ceb5 | |||
| 82297a6ff1 | |||
| cc5ac1a84c | |||
| 6373add383 | |||
| 180099b718 | |||
| 65f15125e1 | |||
| 856c345905 | |||
| b2cd5dfb85 | |||
| 462f7a59b5 | |||
| 22689d24ec | |||
| 4055afdf05 | |||
| a1c70a219a | |||
| 3151515855 | |||
| 25df9da715 | |||
| 9c2f438476 | |||
| 0de3be42cf | |||
| 1545e0eed7 | |||
| 42a7ed6877 | |||
| 98b8aedc4d | |||
| c7a2b54d1c | |||
| 6583ff4439 | |||
| 7b08b3e936 | |||
| bd2fc71dc5 | |||
| 0af97f63e2 | |||
| 1db635f24c | |||
| 6e27b3d6d4 | |||
| 1dea0edcf1 | |||
| 1abab41955 |
+2
-2
@@ -175,8 +175,8 @@
|
||||
<!-- Copy SQL CE -->
|
||||
<ItemGroup>
|
||||
<SQLCE4Files
|
||||
Include="..\src\packages\SqlServerCE.4.0.0.0\**\*.*"
|
||||
Exclude="..\src\packages\SqlServerCE.4.0.0.0\lib\**\*;..\src\packages\SqlServerCE.4.0.0.0\**\*.nu*"
|
||||
Include="..\src\packages\SqlServerCE.4.0.0.1\**\*.*"
|
||||
Exclude="..\src\packages\SqlServerCE.4.0.0.1\lib\**\*;..\src\packages\SqlServerCE.4.0.0.1\**\*.nu*"
|
||||
/>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.3.6
|
||||
7.3.8
|
||||
@@ -47,13 +47,15 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="SqlServerCE" version="4.0.0.0" targetFramework="net40" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
</packages>
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.3.6")]
|
||||
[assembly: AssemblyInformationalVersion("7.3.6")]
|
||||
[assembly: AssemblyFileVersion("7.3.8")]
|
||||
[assembly: AssemblyInformationalVersion("7.3.8")]
|
||||
@@ -7,14 +7,22 @@ using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface describing this cache provider as a wrapper for another
|
||||
/// </summary>
|
||||
internal interface IRuntimeCacheProviderWrapper
|
||||
{
|
||||
IRuntimeCacheProvider InnerProvider { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A wrapper for any IRuntimeCacheProvider that ensures that all inserts and returns
|
||||
/// are a deep cloned copy of the item when the item is IDeepCloneable and that tracks changes are
|
||||
/// reset if the object is TracksChangesEntityBase
|
||||
/// </summary>
|
||||
internal class DeepCloneRuntimeCacheProvider : IRuntimeCacheProvider
|
||||
internal class DeepCloneRuntimeCacheProvider : IRuntimeCacheProvider, IRuntimeCacheProviderWrapper
|
||||
{
|
||||
internal IRuntimeCacheProvider InnerProvider { get; private set; }
|
||||
public IRuntimeCacheProvider InnerProvider { get; private set; }
|
||||
|
||||
public DeepCloneRuntimeCacheProvider(IRuntimeCacheProvider innerProvider)
|
||||
{
|
||||
|
||||
@@ -15,35 +15,31 @@ namespace Umbraco.Core.Cache
|
||||
/// This cache policy uses sliding expiration and caches instances for 5 minutes. However if allow zero count is true, then we use the
|
||||
/// default policy with no expiry.
|
||||
/// </remarks>
|
||||
internal class DefaultRepositoryCachePolicy<TEntity, TId> : DisposableObject, IRepositoryCachePolicy<TEntity, TId>
|
||||
internal class DefaultRepositoryCachePolicy<TEntity, TId> : RepositoryCachePolicyBase<TEntity, TId>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
private readonly RepositoryCachePolicyOptions _options;
|
||||
protected IRuntimeCacheProvider Cache { get; private set; }
|
||||
private Action _action;
|
||||
|
||||
public DefaultRepositoryCachePolicy(IRuntimeCacheProvider cache, RepositoryCachePolicyOptions options)
|
||||
{
|
||||
if (cache == null) throw new ArgumentNullException("cache");
|
||||
: base(cache)
|
||||
{
|
||||
if (options == null) throw new ArgumentNullException("options");
|
||||
|
||||
_options = options;
|
||||
Cache = cache;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public string GetCacheIdKey(object id)
|
||||
protected string GetCacheIdKey(object id)
|
||||
{
|
||||
if (id == null) throw new ArgumentNullException("id");
|
||||
|
||||
return string.Format("{0}{1}", GetCacheTypeKey(), id);
|
||||
}
|
||||
|
||||
public string GetCacheTypeKey()
|
||||
protected string GetCacheTypeKey()
|
||||
{
|
||||
return string.Format("uRepo_{0}_", typeof(TEntity).Name);
|
||||
}
|
||||
|
||||
public void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod)
|
||||
public override void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
if (persistMethod == null) throw new ArgumentNullException("persistMethod");
|
||||
@@ -85,24 +81,29 @@ namespace Umbraco.Core.Cache
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(TEntity entity, Action<TEntity> persistMethod)
|
||||
public override void Remove(TEntity entity, Action<TEntity> persistMethod)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
if (persistMethod == null) throw new ArgumentNullException("persistMethod");
|
||||
|
||||
persistMethod(entity);
|
||||
|
||||
//set the disposal action
|
||||
var cacheKey = GetCacheIdKey(entity.Id);
|
||||
SetCacheAction(() =>
|
||||
try
|
||||
{
|
||||
Cache.ClearCacheItem(cacheKey);
|
||||
//If there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
|
||||
Cache.ClearCacheItem(GetCacheTypeKey());
|
||||
});
|
||||
persistMethod(entity);
|
||||
}
|
||||
finally
|
||||
{
|
||||
//set the disposal action
|
||||
var cacheKey = GetCacheIdKey(entity.Id);
|
||||
SetCacheAction(() =>
|
||||
{
|
||||
Cache.ClearCacheItem(cacheKey);
|
||||
//If there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
|
||||
Cache.ClearCacheItem(GetCacheTypeKey());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public TEntity Get(TId id, Func<TId, TEntity> getFromRepo)
|
||||
public override TEntity Get(TId id, Func<TId, TEntity> getFromRepo)
|
||||
{
|
||||
if (getFromRepo == null) throw new ArgumentNullException("getFromRepo");
|
||||
|
||||
@@ -119,13 +120,13 @@ namespace Umbraco.Core.Cache
|
||||
return entity;
|
||||
}
|
||||
|
||||
public TEntity Get(TId id)
|
||||
public override TEntity Get(TId id)
|
||||
{
|
||||
var cacheKey = GetCacheIdKey(id);
|
||||
return Cache.GetCacheItem<TEntity>(cacheKey);
|
||||
}
|
||||
|
||||
public bool Exists(TId id, Func<TId, bool> getFromRepo)
|
||||
public override bool Exists(TId id, Func<TId, bool> getFromRepo)
|
||||
{
|
||||
if (getFromRepo == null) throw new ArgumentNullException("getFromRepo");
|
||||
|
||||
@@ -134,7 +135,7 @@ namespace Umbraco.Core.Cache
|
||||
return fromCache != null || getFromRepo(id);
|
||||
}
|
||||
|
||||
public virtual TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo)
|
||||
public override TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo)
|
||||
{
|
||||
if (getFromRepo == null) throw new ArgumentNullException("getFromRepo");
|
||||
|
||||
@@ -188,7 +189,7 @@ namespace Umbraco.Core.Cache
|
||||
/// Looks up the zero count cache, must return null if it doesn't exist
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual bool HasZeroCountCache()
|
||||
protected bool HasZeroCountCache()
|
||||
{
|
||||
var zeroCount = Cache.GetCacheItem<TEntity[]>(GetCacheTypeKey());
|
||||
return (zeroCount != null && zeroCount.Any() == false);
|
||||
@@ -198,24 +199,13 @@ namespace Umbraco.Core.Cache
|
||||
/// Performs the lookup for all entities of this type from the cache
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual TEntity[] GetAllFromCache()
|
||||
protected TEntity[] GetAllFromCache()
|
||||
{
|
||||
var allEntities = Cache.GetCacheItemsByKeySearch<TEntity>(GetCacheTypeKey())
|
||||
.WhereNotNull()
|
||||
.ToArray();
|
||||
return allEntities.Any() ? allEntities : new TEntity[] {};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The disposal performs the caching
|
||||
/// </summary>
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
if (_action != null)
|
||||
{
|
||||
_action();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the action to execute on disposal for a single entity
|
||||
@@ -273,14 +263,6 @@ namespace Umbraco.Core.Cache
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the action to execute on disposal
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
protected void SetCacheAction(Action action)
|
||||
{
|
||||
_action = action;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,40 +11,157 @@ namespace Umbraco.Core.Cache
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <typeparam name="TId"></typeparam>
|
||||
/// <remarks>
|
||||
/// This caching policy has no sliding expiration but uses the default ObjectCache.InfiniteAbsoluteExpiration as it's timeout, so it
|
||||
/// should not leave the cache unless the cache memory is exceeded and it gets thrown out.
|
||||
/// </remarks>
|
||||
internal class FullDataSetRepositoryCachePolicy<TEntity, TId> : DefaultRepositoryCachePolicy<TEntity, TId>
|
||||
internal class FullDataSetRepositoryCachePolicy<TEntity, TId> : RepositoryCachePolicyBase<TEntity, TId>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
private readonly Func<TEntity, TId> _getEntityId;
|
||||
private readonly Func<IEnumerable<TEntity>> _getAllFromRepo;
|
||||
private readonly bool _expires;
|
||||
|
||||
public FullDataSetRepositoryCachePolicy(IRuntimeCacheProvider cache, Func<TEntity, TId> getEntityId) : base(cache,
|
||||
new RepositoryCachePolicyOptions
|
||||
{
|
||||
//Definitely allow zero'd cache entires since this is a full set, in many cases there will be none,
|
||||
// and we must cache this!
|
||||
GetAllCacheAllowZeroCount = true
|
||||
})
|
||||
public FullDataSetRepositoryCachePolicy(IRuntimeCacheProvider cache, Func<TEntity, TId> getEntityId, Func<IEnumerable<TEntity>> getAllFromRepo, bool expires)
|
||||
: base(cache)
|
||||
{
|
||||
_getEntityId = getEntityId;
|
||||
_getAllFromRepo = getAllFromRepo;
|
||||
_expires = expires;
|
||||
}
|
||||
|
||||
private bool? _hasZeroCountCache;
|
||||
|
||||
|
||||
protected string GetCacheTypeKey()
|
||||
{
|
||||
return string.Format("uRepo_{0}_", typeof(TEntity).Name);
|
||||
}
|
||||
|
||||
public override void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
if (persistMethod == null) throw new ArgumentNullException("persistMethod");
|
||||
|
||||
try
|
||||
{
|
||||
persistMethod(entity);
|
||||
|
||||
//set the disposal action
|
||||
SetCacheAction(() =>
|
||||
{
|
||||
//Clear all
|
||||
Cache.ClearCacheItem(GetCacheTypeKey());
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
//set the disposal action
|
||||
SetCacheAction(() =>
|
||||
{
|
||||
//Clear all
|
||||
Cache.ClearCacheItem(GetCacheTypeKey());
|
||||
});
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Remove(TEntity entity, Action<TEntity> persistMethod)
|
||||
{
|
||||
if (entity == null) throw new ArgumentNullException("entity");
|
||||
if (persistMethod == null) throw new ArgumentNullException("persistMethod");
|
||||
|
||||
try
|
||||
{
|
||||
persistMethod(entity);
|
||||
}
|
||||
finally
|
||||
{
|
||||
//set the disposal action
|
||||
SetCacheAction(() =>
|
||||
{
|
||||
//Clear all
|
||||
Cache.ClearCacheItem(GetCacheTypeKey());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override TEntity Get(TId id, Func<TId, TEntity> getFromRepo)
|
||||
{
|
||||
//Force get all with cache
|
||||
var found = GetAll(new TId[] { }, ids => _getAllFromRepo().WhereNotNull());
|
||||
|
||||
//we don't have anything in cache (this should never happen), just return from the repo
|
||||
if (found == null) return getFromRepo(id);
|
||||
var entity = found.FirstOrDefault(x => _getEntityId(x).Equals(id));
|
||||
if (entity == null) return null;
|
||||
|
||||
//We must ensure to deep clone each one out manually since the deep clone list only clones one way
|
||||
return (TEntity)entity.DeepClone();
|
||||
}
|
||||
|
||||
public override TEntity Get(TId id)
|
||||
{
|
||||
//Force get all with cache
|
||||
var found = GetAll(new TId[] { }, ids => _getAllFromRepo().WhereNotNull());
|
||||
|
||||
//we don't have anything in cache (this should never happen), just return null
|
||||
if (found == null) return null;
|
||||
var entity = found.FirstOrDefault(x => _getEntityId(x).Equals(id));
|
||||
if (entity == null) return null;
|
||||
|
||||
//We must ensure to deep clone each one out manually since the deep clone list only clones one way
|
||||
return (TEntity)entity.DeepClone();
|
||||
}
|
||||
|
||||
public override bool Exists(TId id, Func<TId, bool> getFromRepo)
|
||||
{
|
||||
//Force get all with cache
|
||||
var found = GetAll(new TId[] {}, ids => _getAllFromRepo().WhereNotNull());
|
||||
|
||||
//we don't have anything in cache (this should never happen), just return from the repo
|
||||
return found == null
|
||||
? getFromRepo(id)
|
||||
: found.Any(x => _getEntityId(x).Equals(id));
|
||||
}
|
||||
|
||||
public override TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo)
|
||||
{
|
||||
//process the base logic without any Ids - we want to cache them all!
|
||||
var result = base.GetAll(new TId[] { }, getFromRepo);
|
||||
//process getting all including setting the cache callback
|
||||
var result = PerformGetAll(getFromRepo);
|
||||
|
||||
//now that the base result has been calculated, they will all be cached.
|
||||
// Now we can just filter by ids if they have been supplied
|
||||
|
||||
return ids.Any()
|
||||
return (ids.Any()
|
||||
? result.Where(x => ids.Contains(_getEntityId(x))).ToArray()
|
||||
: result;
|
||||
: result)
|
||||
//We must ensure to deep clone each one out manually since the deep clone list only clones one way
|
||||
.Select(x => (TEntity)x.DeepClone())
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private TEntity[] PerformGetAll(Func<TId[], IEnumerable<TEntity>> getFromRepo)
|
||||
{
|
||||
var allEntities = GetAllFromCache();
|
||||
if (allEntities.Any())
|
||||
{
|
||||
return allEntities;
|
||||
}
|
||||
|
||||
//check the zero count cache
|
||||
if (HasZeroCountCache())
|
||||
{
|
||||
//there is a zero count cache so return an empty list
|
||||
return new TEntity[] { };
|
||||
}
|
||||
|
||||
//we need to do the lookup from the repo
|
||||
var entityCollection = getFromRepo(new TId[] {})
|
||||
//ensure we don't include any null refs in the returned collection!
|
||||
.WhereNotNull()
|
||||
.ToArray();
|
||||
|
||||
//set the disposal action
|
||||
SetCacheAction(entityCollection);
|
||||
|
||||
return entityCollection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -52,26 +169,32 @@ namespace Umbraco.Core.Cache
|
||||
/// </summary>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="entity"></param>
|
||||
protected override void SetCacheAction(string cacheKey, TEntity entity)
|
||||
protected void SetCacheAction(string cacheKey, TEntity entity)
|
||||
{
|
||||
//do nothing
|
||||
//No-op
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the action to execute on disposal for an entity collection
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <param name="entityCollection"></param>
|
||||
protected override void SetCacheAction(TId[] ids, TEntity[] entityCollection)
|
||||
protected void SetCacheAction(TEntity[] entityCollection)
|
||||
{
|
||||
//for this type of caching policy, we don't want to cache any GetAll request containing specific Ids
|
||||
if (ids.Any()) return;
|
||||
|
||||
//set the disposal action
|
||||
SetCacheAction(() =>
|
||||
{
|
||||
//We want to cache the result as a single collection
|
||||
Cache.InsertCacheItem(GetCacheTypeKey(), () => new DeepCloneableList<TEntity>(entityCollection));
|
||||
|
||||
if (_expires)
|
||||
{
|
||||
Cache.InsertCacheItem(GetCacheTypeKey(), () => new DeepCloneableList<TEntity>(entityCollection),
|
||||
timeout: TimeSpan.FromMinutes(5),
|
||||
isSliding: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Cache.InsertCacheItem(GetCacheTypeKey(), () => new DeepCloneableList<TEntity>(entityCollection));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,7 +202,7 @@ namespace Umbraco.Core.Cache
|
||||
/// Looks up the zero count cache, must return null if it doesn't exist
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override bool HasZeroCountCache()
|
||||
protected bool HasZeroCountCache()
|
||||
{
|
||||
if (_hasZeroCountCache.HasValue)
|
||||
return _hasZeroCountCache.Value;
|
||||
@@ -92,7 +215,7 @@ namespace Umbraco.Core.Cache
|
||||
/// This policy will cache the full data set as a single collection
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override TEntity[] GetAllFromCache()
|
||||
protected TEntity[] GetAllFromCache()
|
||||
{
|
||||
var found = Cache.GetCacheItem<DeepCloneableList<TEntity>>(GetCacheTypeKey());
|
||||
|
||||
@@ -101,5 +224,6 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
return found == null ? new TEntity[] { } : found.WhereNotNull().ToArray();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
@@ -13,16 +14,20 @@ namespace Umbraco.Core.Cache
|
||||
{
|
||||
private readonly IRuntimeCacheProvider _runtimeCache;
|
||||
private readonly Func<TEntity, TId> _getEntityId;
|
||||
private readonly Func<IEnumerable<TEntity>> _getAllFromRepo;
|
||||
private readonly bool _expires;
|
||||
|
||||
public FullDataSetRepositoryCachePolicyFactory(IRuntimeCacheProvider runtimeCache, Func<TEntity, TId> getEntityId)
|
||||
public FullDataSetRepositoryCachePolicyFactory(IRuntimeCacheProvider runtimeCache, Func<TEntity, TId> getEntityId, Func<IEnumerable<TEntity>> getAllFromRepo, bool expires)
|
||||
{
|
||||
_runtimeCache = runtimeCache;
|
||||
_getEntityId = getEntityId;
|
||||
_getAllFromRepo = getAllFromRepo;
|
||||
_expires = expires;
|
||||
}
|
||||
|
||||
public virtual IRepositoryCachePolicy<TEntity, TId> CreatePolicy()
|
||||
{
|
||||
return new FullDataSetRepositoryCachePolicy<TEntity, TId>(_runtimeCache, _getEntityId);
|
||||
return new FullDataSetRepositoryCachePolicy<TEntity, TId>(_runtimeCache, _getEntityId, _getAllFromRepo, _expires);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,7 @@ namespace Umbraco.Core.Cache
|
||||
TEntity Get(TId id, Func<TId, TEntity> getFromRepo);
|
||||
TEntity Get(TId id);
|
||||
bool Exists(TId id, Func<TId, bool> getFromRepo);
|
||||
|
||||
string GetCacheIdKey(object id);
|
||||
string GetCacheTypeKey();
|
||||
|
||||
void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod);
|
||||
void Remove(TEntity entity, Action<TEntity> persistMethod);
|
||||
TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo);
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
internal abstract class RepositoryCachePolicyBase<TEntity, TId> : DisposableObject, IRepositoryCachePolicy<TEntity, TId>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
private Action _action;
|
||||
|
||||
protected RepositoryCachePolicyBase(IRuntimeCacheProvider cache)
|
||||
{
|
||||
if (cache == null) throw new ArgumentNullException("cache");
|
||||
|
||||
Cache = cache;
|
||||
}
|
||||
|
||||
protected IRuntimeCacheProvider Cache { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The disposal performs the caching
|
||||
/// </summary>
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
if (_action != null)
|
||||
{
|
||||
_action();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the action to execute on disposal
|
||||
/// </summary>
|
||||
/// <param name="action"></param>
|
||||
protected void SetCacheAction(Action action)
|
||||
{
|
||||
_action = action;
|
||||
}
|
||||
|
||||
public abstract TEntity Get(TId id, Func<TId, TEntity> getFromRepo);
|
||||
public abstract TEntity Get(TId id);
|
||||
public abstract bool Exists(TId id, Func<TId, bool> getFromRepo);
|
||||
public abstract void CreateOrUpdate(TEntity entity, Action<TEntity> persistMethod);
|
||||
public abstract void Remove(TEntity entity, Action<TEntity> persistMethod);
|
||||
public abstract TEntity[] GetAll(TId[] ids, Func<TId[], IEnumerable<TEntity>> getFromRepo);
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
protected override void SetCacheAction(TId[] ids, TEntity[] entityCollection)
|
||||
{
|
||||
//do nothing
|
||||
//no-op
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,7 +290,7 @@ namespace Umbraco.Core
|
||||
TimeSpan timeout,
|
||||
Func<TT> getCacheItem)
|
||||
{
|
||||
var cache = RuntimeCache as HttpRuntimeCacheProvider;
|
||||
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
|
||||
if (cache != null)
|
||||
{
|
||||
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
|
||||
@@ -314,7 +314,7 @@ namespace Umbraco.Core
|
||||
CacheDependency cacheDependency,
|
||||
Func<TT> getCacheItem)
|
||||
{
|
||||
var cache = RuntimeCache as HttpRuntimeCacheProvider;
|
||||
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
|
||||
if (cache != null)
|
||||
{
|
||||
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), null, false, priority, null, cacheDependency);
|
||||
@@ -374,7 +374,7 @@ namespace Umbraco.Core
|
||||
TimeSpan timeout,
|
||||
Func<T> getCacheItem)
|
||||
{
|
||||
var cache = RuntimeCache as HttpRuntimeCacheProvider;
|
||||
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
|
||||
if (cache != null)
|
||||
{
|
||||
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, null, cacheDependency);
|
||||
@@ -400,7 +400,7 @@ namespace Umbraco.Core
|
||||
TimeSpan? timeout,
|
||||
Func<T> getCacheItem)
|
||||
{
|
||||
var cache = RuntimeCache as HttpRuntimeCacheProvider;
|
||||
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
|
||||
if (cache != null)
|
||||
{
|
||||
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
|
||||
@@ -409,6 +409,20 @@ namespace Umbraco.Core
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
private HttpRuntimeCacheProvider GetHttpRuntimeCacheProvider(IRuntimeCacheProvider runtimeCache)
|
||||
{
|
||||
HttpRuntimeCacheProvider cache;
|
||||
var wrapper = RuntimeCache as IRuntimeCacheProviderWrapper;
|
||||
if (wrapper != null)
|
||||
{
|
||||
cache = wrapper.InnerProvider as HttpRuntimeCacheProvider;
|
||||
}
|
||||
else
|
||||
{
|
||||
cache = RuntimeCache as HttpRuntimeCacheProvider;
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,18 +14,24 @@ namespace Umbraco.Core.Collections
|
||||
/// <typeparam name="T"></typeparam>
|
||||
internal class DeepCloneableList<T> : List<T>, IDeepCloneable, IRememberBeingDirty
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:System.Collections.Generic.List`1"/> class that is empty and has the default initial capacity.
|
||||
/// </summary>
|
||||
public DeepCloneableList()
|
||||
private readonly ListCloneBehavior _listCloneBehavior;
|
||||
|
||||
public DeepCloneableList(ListCloneBehavior listCloneBehavior)
|
||||
{
|
||||
_listCloneBehavior = listCloneBehavior;
|
||||
}
|
||||
|
||||
public DeepCloneableList(IEnumerable<T> collection, ListCloneBehavior listCloneBehavior) : base(collection)
|
||||
{
|
||||
_listCloneBehavior = listCloneBehavior;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:System.Collections.Generic.List`1"/> class that contains elements copied from the specified collection and has sufficient capacity to accommodate the number of elements copied.
|
||||
/// Default behavior is CloneOnce
|
||||
/// </summary>
|
||||
/// <param name="collection">The collection whose elements are copied to the new list.</param><exception cref="T:System.ArgumentNullException"><paramref name="collection"/> is null.</exception>
|
||||
public DeepCloneableList(IEnumerable<T> collection) : base(collection)
|
||||
/// <param name="collection"></param>
|
||||
public DeepCloneableList(IEnumerable<T> collection)
|
||||
: this(collection, ListCloneBehavior.CloneOnce)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -35,20 +41,47 @@ namespace Umbraco.Core.Collections
|
||||
/// <returns></returns>
|
||||
public object DeepClone()
|
||||
{
|
||||
var newList = new DeepCloneableList<T>();
|
||||
foreach (var item in this)
|
||||
switch (_listCloneBehavior)
|
||||
{
|
||||
var dc = item as IDeepCloneable;
|
||||
if (dc != null)
|
||||
{
|
||||
newList.Add((T) dc.DeepClone());
|
||||
}
|
||||
else
|
||||
{
|
||||
newList.Add(item);
|
||||
}
|
||||
case ListCloneBehavior.CloneOnce:
|
||||
//we are cloning once, so create a new list in none mode
|
||||
// and deep clone all items into it
|
||||
var newList = new DeepCloneableList<T>(ListCloneBehavior.None);
|
||||
foreach (var item in this)
|
||||
{
|
||||
var dc = item as IDeepCloneable;
|
||||
if (dc != null)
|
||||
{
|
||||
newList.Add((T)dc.DeepClone());
|
||||
}
|
||||
else
|
||||
{
|
||||
newList.Add(item);
|
||||
}
|
||||
}
|
||||
return newList;
|
||||
case ListCloneBehavior.None:
|
||||
//we are in none mode, so just return a new list with the same items
|
||||
return new DeepCloneableList<T>(this, ListCloneBehavior.None);
|
||||
case ListCloneBehavior.Always:
|
||||
//always clone to new list
|
||||
var newList2 = new DeepCloneableList<T>(ListCloneBehavior.Always);
|
||||
foreach (var item in this)
|
||||
{
|
||||
var dc = item as IDeepCloneable;
|
||||
if (dc != null)
|
||||
{
|
||||
newList2.Add((T)dc.DeepClone());
|
||||
}
|
||||
else
|
||||
{
|
||||
newList2.Add(item);
|
||||
}
|
||||
}
|
||||
return newList2;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
return newList;
|
||||
}
|
||||
|
||||
public bool IsDirty()
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Umbraco.Core.Collections
|
||||
{
|
||||
internal enum ListCloneBehavior
|
||||
{
|
||||
/// <summary>
|
||||
/// When set, DeepClone will clone the items one time and the result list behavior will be None
|
||||
/// </summary>
|
||||
CloneOnce,
|
||||
|
||||
/// <summary>
|
||||
/// When set, DeepClone will not clone any items
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// When set, DeepClone will always clone all items
|
||||
/// </summary>
|
||||
Always
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.3.6");
|
||||
private static readonly Version Version = new Version("7.3.8");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -10,6 +10,12 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public static class Web
|
||||
{
|
||||
public const string UmbracoContextDataToken = "umbraco-context";
|
||||
public const string UmbracoDataToken = "umbraco";
|
||||
public const string PublishedDocumentRequestDataToken = "umbraco-doc-request";
|
||||
public const string CustomRouteDataToken = "umbraco-custom-route";
|
||||
public const string UmbracoRouteDefinitionDataToken = "umbraco-route-def";
|
||||
|
||||
/// <summary>
|
||||
/// The preview cookie name
|
||||
/// </summary>
|
||||
|
||||
@@ -9,10 +9,30 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
public static class DeepCloneHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores the metadata for the properties for a given type so we know how to create them
|
||||
/// </summary>
|
||||
private struct ClonePropertyInfo
|
||||
{
|
||||
public ClonePropertyInfo(PropertyInfo propertyInfo) : this()
|
||||
{
|
||||
if (propertyInfo == null) throw new ArgumentNullException("propertyInfo");
|
||||
PropertyInfo = propertyInfo;
|
||||
}
|
||||
|
||||
public PropertyInfo PropertyInfo { get; private set; }
|
||||
public bool IsDeepCloneable { get; set; }
|
||||
public Type GenericListType { get; set; }
|
||||
public bool IsList
|
||||
{
|
||||
get { return GenericListType != null; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to avoid constant reflection (perf)
|
||||
/// </summary>
|
||||
private static readonly ConcurrentDictionary<Type, PropertyInfo[]> PropCache = new ConcurrentDictionary<Type, PropertyInfo[]>();
|
||||
private static readonly ConcurrentDictionary<Type, ClonePropertyInfo[]> PropCache = new ConcurrentDictionary<Type, ClonePropertyInfo[]>();
|
||||
|
||||
/// <summary>
|
||||
/// Used to deep clone any reference properties on the object (should be done after a MemberwiseClone for which the outcome is 'output')
|
||||
@@ -30,81 +50,99 @@ namespace Umbraco.Core.Models
|
||||
throw new InvalidOperationException("Both the input and output types must be the same");
|
||||
}
|
||||
|
||||
//get the property metadata from cache so we only have to figure this out once per type
|
||||
var refProperties = PropCache.GetOrAdd(inputType, type =>
|
||||
inputType.GetProperties()
|
||||
.Where(x =>
|
||||
//is not attributed with the ignore clone attribute
|
||||
x.GetCustomAttribute<DoNotCloneAttribute>() == null
|
||||
.Select<PropertyInfo, ClonePropertyInfo?>(propertyInfo =>
|
||||
{
|
||||
if (
|
||||
//is not attributed with the ignore clone attribute
|
||||
propertyInfo.GetCustomAttribute<DoNotCloneAttribute>() != null
|
||||
//reference type but not string
|
||||
&& x.PropertyType.IsValueType == false && x.PropertyType != typeof (string)
|
||||
|| propertyInfo.PropertyType.IsValueType || propertyInfo.PropertyType == typeof (string)
|
||||
//settable
|
||||
&& x.CanWrite
|
||||
|| propertyInfo.CanWrite == false
|
||||
//non-indexed
|
||||
&& x.GetIndexParameters().Any() == false)
|
||||
|| propertyInfo.GetIndexParameters().Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if (TypeHelper.IsTypeAssignableFrom<IDeepCloneable>(propertyInfo.PropertyType))
|
||||
{
|
||||
return new ClonePropertyInfo(propertyInfo) { IsDeepCloneable = true };
|
||||
}
|
||||
|
||||
if (TypeHelper.IsTypeAssignableFrom<IEnumerable>(propertyInfo.PropertyType)
|
||||
&& TypeHelper.IsTypeAssignableFrom<string>(propertyInfo.PropertyType) == false)
|
||||
{
|
||||
if (propertyInfo.PropertyType.IsGenericType
|
||||
&& (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
|
||||
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>)
|
||||
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
|
||||
{
|
||||
//if it is a IEnumerable<>, IList<T> or ICollection<> we'll use a List<>
|
||||
var genericType = typeof(List<>).MakeGenericType(propertyInfo.PropertyType.GetGenericArguments());
|
||||
return new ClonePropertyInfo(propertyInfo) { GenericListType = genericType };
|
||||
}
|
||||
if (propertyInfo.PropertyType.IsArray
|
||||
|| (propertyInfo.PropertyType.IsInterface && propertyInfo.PropertyType.IsGenericType == false))
|
||||
{
|
||||
//if its an array, we'll create a list to work with first and then convert to array later
|
||||
//otherwise if its just a regular derivitave of IEnumerable, we can use a list too
|
||||
return new ClonePropertyInfo(propertyInfo) { GenericListType = typeof(List<object>) };
|
||||
}
|
||||
//skip instead of trying to create instance of abstract or interface
|
||||
if (propertyInfo.PropertyType.IsAbstract || propertyInfo.PropertyType.IsInterface)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//its a custom IEnumerable, we'll try to create it
|
||||
try
|
||||
{
|
||||
var custom = Activator.CreateInstance(propertyInfo.PropertyType);
|
||||
//if it's an IList we can work with it, otherwise we cannot
|
||||
var newList = custom as IList;
|
||||
if (newList == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new ClonePropertyInfo(propertyInfo) {GenericListType = propertyInfo.PropertyType};
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//could not create this type so we'll skip it
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new ClonePropertyInfo(propertyInfo);
|
||||
})
|
||||
.Where(x => x.HasValue)
|
||||
.Select(x => x.Value)
|
||||
.ToArray());
|
||||
|
||||
foreach (var propertyInfo in refProperties)
|
||||
foreach (var clonePropertyInfo in refProperties)
|
||||
{
|
||||
if (TypeHelper.IsTypeAssignableFrom<IDeepCloneable>(propertyInfo.PropertyType))
|
||||
if (clonePropertyInfo.IsDeepCloneable)
|
||||
{
|
||||
//this ref property is also deep cloneable so clone it
|
||||
var result = (IDeepCloneable)propertyInfo.GetValue(input, null);
|
||||
var result = (IDeepCloneable)clonePropertyInfo.PropertyInfo.GetValue(input, null);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
//set the cloned value to the property
|
||||
propertyInfo.SetValue(output, result.DeepClone(), null);
|
||||
clonePropertyInfo.PropertyInfo.SetValue(output, result.DeepClone(), null);
|
||||
}
|
||||
}
|
||||
else if (TypeHelper.IsTypeAssignableFrom<IEnumerable>(propertyInfo.PropertyType)
|
||||
&& TypeHelper.IsTypeAssignableFrom<string>(propertyInfo.PropertyType) == false)
|
||||
else if (clonePropertyInfo.IsList)
|
||||
{
|
||||
IList newList;
|
||||
if (propertyInfo.PropertyType.IsGenericType
|
||||
&& (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
|
||||
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>)
|
||||
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
|
||||
{
|
||||
//if it is a IEnumerable<>, IList<T> or ICollection<> we'll use a List<>
|
||||
var genericType = typeof(List<>).MakeGenericType(propertyInfo.PropertyType.GetGenericArguments());
|
||||
newList = (IList)Activator.CreateInstance(genericType);
|
||||
}
|
||||
else if (propertyInfo.PropertyType.IsArray
|
||||
|| (propertyInfo.PropertyType.IsInterface && propertyInfo.PropertyType.IsGenericType == false))
|
||||
{
|
||||
//if its an array, we'll create a list to work with first and then convert to array later
|
||||
//otherwise if its just a regular derivitave of IEnumerable, we can use a list too
|
||||
newList = new List<object>();
|
||||
}
|
||||
else
|
||||
{
|
||||
//skip instead of trying to create instance of abstract or interface
|
||||
if (propertyInfo.PropertyType.IsAbstract || propertyInfo.PropertyType.IsInterface)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//its a custom IEnumerable, we'll try to create it
|
||||
try
|
||||
{
|
||||
var custom = Activator.CreateInstance(propertyInfo.PropertyType);
|
||||
//if it's an IList we can work with it, otherwise we cannot
|
||||
newList = custom as IList;
|
||||
if (newList == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//could not create this type so we'll skip it
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var enumerable = (IEnumerable)propertyInfo.GetValue(input, null);
|
||||
var enumerable = (IEnumerable)clonePropertyInfo.PropertyInfo.GetValue(input, null);
|
||||
if (enumerable == null) continue;
|
||||
|
||||
var newList = (IList)Activator.CreateInstance(clonePropertyInfo.GenericListType);
|
||||
|
||||
var isUsableType = true;
|
||||
|
||||
//now clone each item
|
||||
@@ -136,21 +174,21 @@ namespace Umbraco.Core.Models
|
||||
continue;
|
||||
}
|
||||
|
||||
if (propertyInfo.PropertyType.IsArray)
|
||||
if (clonePropertyInfo.PropertyInfo.PropertyType.IsArray)
|
||||
{
|
||||
//need to convert to array
|
||||
var arr = (object[])Activator.CreateInstance(propertyInfo.PropertyType, newList.Count);
|
||||
var arr = (object[])Activator.CreateInstance(clonePropertyInfo.PropertyInfo.PropertyType, newList.Count);
|
||||
for (int i = 0; i < newList.Count; i++)
|
||||
{
|
||||
arr[i] = newList[i];
|
||||
}
|
||||
//set the cloned collection
|
||||
propertyInfo.SetValue(output, arr, null);
|
||||
clonePropertyInfo.PropertyInfo.SetValue(output, arr, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
//set the cloned collection
|
||||
propertyInfo.SetValue(output, newList, null);
|
||||
clonePropertyInfo.PropertyInfo.SetValue(output, newList, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -98,10 +98,45 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Cache
|
||||
|
||||
// these methods are called by ContentTypeCacheRefresher and DataTypeCacheRefresher
|
||||
|
||||
internal static void ClearAll()
|
||||
{
|
||||
Logging.LogHelper.Debug<PublishedContentType>("Clear all.");
|
||||
// ok and faster to do it by types, assuming noone else caches PublishedContentType instances
|
||||
//ApplicationContext.Current.ApplicationCache.ClearStaticCacheByKeySearch("PublishedContentType_");
|
||||
ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheObjectTypes<PublishedContentType>();
|
||||
}
|
||||
|
||||
internal static void ClearContentType(int id)
|
||||
{
|
||||
Logging.LogHelper.Debug<PublishedContentType>("Clear content type w/id {0}.", () => id);
|
||||
// requires a predicate because the key does not contain the ID
|
||||
// faster than key strings comparisons anyway
|
||||
ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheObjectTypes<PublishedContentType>(
|
||||
(key, value) => value.Id == id);
|
||||
}
|
||||
|
||||
internal static void ClearDataType(int id)
|
||||
{
|
||||
Logging.LogHelper.Debug<PublishedContentType>("Clear data type w/id {0}.", () => id);
|
||||
// there is no recursion to handle here because a PublishedContentType contains *all* its
|
||||
// properties ie both its own properties and those that were inherited (it's based upon an
|
||||
// IContentTypeComposition) and so every PublishedContentType having a property based upon
|
||||
// the cleared data type, be it local or inherited, will be cleared.
|
||||
ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheObjectTypes<PublishedContentType>(
|
||||
(key, value) => value.PropertyTypes.Any(x => x.DataTypeId == id));
|
||||
}
|
||||
|
||||
public static PublishedContentType Get(PublishedItemType itemType, string alias)
|
||||
{
|
||||
var type = CreatePublishedContentType(itemType, alias);
|
||||
var key = string.Format("PublishedContentType_{0}_{1}",
|
||||
itemType.ToString().ToLowerInvariant(), alias.ToLowerInvariant());
|
||||
|
||||
var type = ApplicationContext.Current.ApplicationCache.StaticCache.GetCacheItem<PublishedContentType>(key,
|
||||
() => CreatePublishedContentType(itemType, alias));
|
||||
|
||||
return type;
|
||||
}
|
||||
@@ -134,8 +169,21 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
return new PublishedContentType(contentType);
|
||||
}
|
||||
|
||||
// for unit tests
|
||||
internal static Func<string, PublishedContentType> GetPublishedContentTypeCallback { get; set; }
|
||||
|
||||
// for unit tests - changing the callback must reset the cache obviously
|
||||
private static Func<string, PublishedContentType> _getPublishedContentTypeCallBack;
|
||||
internal static Func<string, PublishedContentType> GetPublishedContentTypeCallback
|
||||
{
|
||||
get { return _getPublishedContentTypeCallBack; }
|
||||
set
|
||||
{
|
||||
// see note above
|
||||
//ClearAll();
|
||||
ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheByKeySearch("PublishedContentType_");
|
||||
|
||||
_getPublishedContentTypeCallBack = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,13 +230,13 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
_sourceCacheLevel = converterMeta.GetPropertyCacheLevel(this, PropertyCacheValue.Source);
|
||||
_objectCacheLevel = converterMeta.GetPropertyCacheLevel(this, PropertyCacheValue.Object);
|
||||
_objectCacheLevel = converterMeta.GetPropertyCacheLevel(this, PropertyCacheValue.XPath);
|
||||
_xpathCacheLevel = converterMeta.GetPropertyCacheLevel(this, PropertyCacheValue.XPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
_sourceCacheLevel = GetCacheLevel(_converter, PropertyCacheValue.Source);
|
||||
_objectCacheLevel = GetCacheLevel(_converter, PropertyCacheValue.Object);
|
||||
_objectCacheLevel = GetCacheLevel(_converter, PropertyCacheValue.XPath);
|
||||
_xpathCacheLevel = GetCacheLevel(_converter, PropertyCacheValue.XPath);
|
||||
}
|
||||
if (_objectCacheLevel < _sourceCacheLevel) _objectCacheLevel = _sourceCacheLevel;
|
||||
if (_xpathCacheLevel < _sourceCacheLevel) _xpathCacheLevel = _sourceCacheLevel;
|
||||
|
||||
@@ -289,7 +289,7 @@ namespace Umbraco.Core.Persistence.Migrations
|
||||
//NOTE: We CANNOT do this as part of the transaction!!! This is because when upgrading to 7.3, we cannot
|
||||
// create the migrations table and then add data to it in the same transaction without issuing things like GO
|
||||
// commands and since we need to support all Dbs, we need to just do this after the fact.
|
||||
var exists = _migrationEntryService.FindEntry(GlobalSettings.UmbracoMigrationName, _targetVersion);
|
||||
var exists = _migrationEntryService.FindEntry(_productName, _targetVersion);
|
||||
if (exists == null)
|
||||
{
|
||||
_migrationEntryService.CreateEntry(_productName, _targetVersion);
|
||||
|
||||
@@ -834,7 +834,7 @@ namespace Umbraco.Core.Persistence
|
||||
var pd = PocoData.ForType(typeof(T));
|
||||
try
|
||||
{
|
||||
r = cmd.ExecuteReader();
|
||||
r = cmd.ExecuteReaderWithRetry();
|
||||
OnExecutedCommand(cmd);
|
||||
}
|
||||
catch (Exception x)
|
||||
|
||||
@@ -34,7 +34,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
get
|
||||
{
|
||||
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IContentType, int>(RuntimeCache, GetEntityId));
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IContentType, int>(
|
||||
RuntimeCache, GetEntityId, () => PerformGetAll(),
|
||||
//allow this cache to expire
|
||||
expires:true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,13 +63,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
var sqlClause = GetBaseQuery(false);
|
||||
var translator = new SqlTranslator<IContentType>(sqlClause, query);
|
||||
var sql = translator.Translate()
|
||||
.OrderBy<NodeDto>(x => x.Text);
|
||||
var sql = translator.Translate();
|
||||
|
||||
var dtos = Database.Fetch<DocumentTypeDto, ContentTypeDto, NodeDto>(sql);
|
||||
return dtos.Any()
|
||||
? GetAll(dtos.DistinctBy(x => x.ContentTypeDto.NodeId).Select(x => x.ContentTypeDto.NodeId).ToArray())
|
||||
: Enumerable.Empty<IContentType>();
|
||||
|
||||
return
|
||||
//This returns a lookup from the GetAll cached looup
|
||||
(dtos.Any()
|
||||
? GetAll(dtos.DistinctBy(x => x.ContentTypeDto.NodeId).Select(x => x.ContentTypeDto.NodeId).ToArray())
|
||||
: Enumerable.Empty<IContentType>())
|
||||
//order the result by name
|
||||
.OrderBy(x => x.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -29,7 +29,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
get
|
||||
{
|
||||
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IDomain, int>(RuntimeCache, GetEntityId));
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IDomain, int>(
|
||||
RuntimeCache, GetEntityId, () => PerformGetAll(), false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
get
|
||||
{
|
||||
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<ILanguage, int>(RuntimeCache, GetEntityId));
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<ILanguage, int>(
|
||||
RuntimeCache, GetEntityId, () => PerformGetAll(), false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
get
|
||||
{
|
||||
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IMediaType, int>(RuntimeCache, GetEntityId));
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IMediaType, int>(
|
||||
RuntimeCache, GetEntityId, () => PerformGetAll(),
|
||||
//allow this cache to expire
|
||||
expires: true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,13 +60,17 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
var sqlClause = GetBaseQuery(false);
|
||||
var translator = new SqlTranslator<IMediaType>(sqlClause, query);
|
||||
var sql = translator.Translate()
|
||||
.OrderBy<NodeDto>(x => x.Text);
|
||||
var sql = translator.Translate();
|
||||
|
||||
var dtos = Database.Fetch<ContentTypeDto, NodeDto>(sql);
|
||||
return dtos.Any()
|
||||
? GetAll(dtos.DistinctBy(x => x.NodeId).Select(x => x.NodeId).ToArray())
|
||||
: Enumerable.Empty<IMediaType>();
|
||||
|
||||
return
|
||||
//This returns a lookup from the GetAll cached looup
|
||||
(dtos.Any()
|
||||
? GetAll(dtos.DistinctBy(x => x.NodeId).Select(x => x.NodeId).ToArray())
|
||||
: Enumerable.Empty<IMediaType>())
|
||||
//order the result by name
|
||||
.OrderBy(x => x.Name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
get
|
||||
{
|
||||
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IMemberType, int>(RuntimeCache, GetEntityId));
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<IMemberType, int>(
|
||||
RuntimeCache, GetEntityId, () => PerformGetAll(),
|
||||
//allow this cache to expire
|
||||
expires: true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
get
|
||||
{
|
||||
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<PublicAccessEntry, Guid>(RuntimeCache, GetEntityId));
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<PublicAccessEntry, Guid>(
|
||||
RuntimeCache, GetEntityId, () => PerformGetAll(), false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
get
|
||||
{
|
||||
//Use a FullDataSet cache policy - this will cache the entire GetAll result in a single collection
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<ITemplate, int>(RuntimeCache, GetEntityId));
|
||||
return _cachePolicyFactory ?? (_cachePolicyFactory = new FullDataSetRepositoryCachePolicyFactory<ITemplate, int>(
|
||||
RuntimeCache, GetEntityId, () => PerformGetAll(), false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
/// <summary>
|
||||
/// We need this property converter so that we always force the value of a label to be a string
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Without a property converter defined for the label type, the value will be converted with
|
||||
/// the `ConvertUsingDarkMagic` method which will try to parse the value into it's correct type, but this
|
||||
/// can cause issues if the string is detected as a number and then strips leading zeros.
|
||||
/// Example: http://issues.umbraco.org/issue/U4-7929
|
||||
/// </remarks>
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof (string))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class LabelValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
return Constants.PropertyEditors.NoEditAlias.Equals(propertyType.PropertyEditorAlias);
|
||||
}
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
return source == null ? string.Empty : source.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,12 @@ namespace Umbraco.Core.Security
|
||||
{
|
||||
public class BackOfficeClaimsIdentityFactory : ClaimsIdentityFactory<BackOfficeIdentityUser, int>
|
||||
{
|
||||
public BackOfficeClaimsIdentityFactory()
|
||||
{
|
||||
SecurityStampClaimType = Constants.Security.SessionIdClaimType;
|
||||
UserNameClaimType = ClaimTypes.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a ClaimsIdentity from a user
|
||||
/// </summary>
|
||||
@@ -20,7 +26,7 @@ namespace Umbraco.Core.Security
|
||||
|
||||
var umbracoIdentity = new UmbracoBackOfficeIdentity(baseIdentity,
|
||||
//set a new session id
|
||||
new UserData(Guid.NewGuid().ToString("N"))
|
||||
new UserData
|
||||
{
|
||||
Id = user.Id,
|
||||
Username = user.UserName,
|
||||
@@ -29,7 +35,8 @@ namespace Umbraco.Core.Security
|
||||
Culture = user.Culture,
|
||||
Roles = user.Roles.Select(x => x.RoleId).ToArray(),
|
||||
StartContentNode = user.StartContentId,
|
||||
StartMediaNode = user.StartMediaId
|
||||
StartMediaNode = user.StartMediaId,
|
||||
SessionId = user.SecurityStamp
|
||||
});
|
||||
|
||||
return umbracoIdentity;
|
||||
|
||||
@@ -209,17 +209,19 @@ namespace Umbraco.Core.Security
|
||||
|
||||
if (HasClaim(x => x.Type == ClaimTypes.Locality) == false)
|
||||
AddClaim(new Claim(ClaimTypes.Locality, Culture, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
|
||||
////TODO: Not sure why this is null sometimes, it shouldn't be. Somewhere it's not being set
|
||||
/// I think it's due to some bug I had in chrome, we'll see
|
||||
//if (UserData.SessionId.IsNullOrWhiteSpace())
|
||||
//{
|
||||
// UserData.SessionId = Guid.NewGuid().ToString();
|
||||
//}
|
||||
|
||||
if (HasClaim(x => x.Type == Constants.Security.SessionIdClaimType) == false)
|
||||
if (HasClaim(x => x.Type == Constants.Security.SessionIdClaimType) == false && SessionId.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
AddClaim(new Claim(Constants.Security.SessionIdClaimType, SessionId, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
|
||||
//The security stamp claim is also required... this is because this claim type is hard coded
|
||||
// by the SecurityStampValidator, see: https://katanaproject.codeplex.com/workitem/444
|
||||
if (HasClaim(x => x.Type == Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType) == false)
|
||||
{
|
||||
AddClaim(new Claim(Microsoft.AspNet.Identity.Constants.DefaultSecurityStampClaimType, SessionId, ClaimValueTypes.String, Issuer, Issuer, this));
|
||||
}
|
||||
}
|
||||
|
||||
//Add each app as a separate claim
|
||||
if (HasClaim(x => x.Type == Constants.Security.AllowedApplicationsClaimType) == false)
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Security
|
||||
/// Use this constructor to create/assign new UserData to the ticket
|
||||
/// </summary>
|
||||
/// <param name="sessionId">
|
||||
/// A unique id that is assigned to this ticket
|
||||
/// The security stamp for the user
|
||||
/// </param>
|
||||
public UserData(string sessionId)
|
||||
{
|
||||
@@ -30,8 +30,7 @@ namespace Umbraco.Core.Security
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used to Id the current ticket which we can then use to mitigate csrf attacks
|
||||
/// and other things that require request validation.
|
||||
/// This is the 'security stamp' for validation
|
||||
/// </summary>
|
||||
[DataMember(Name = "sessionId")]
|
||||
public string SessionId { get; set; }
|
||||
@@ -42,8 +41,6 @@ namespace Umbraco.Core.Security
|
||||
[DataMember(Name = "roles")]
|
||||
public string[] Roles { get; set; }
|
||||
|
||||
//public int SessionTimeout { get; set; }
|
||||
|
||||
[DataMember(Name = "username")]
|
||||
public string Username { get; set; }
|
||||
|
||||
|
||||
@@ -41,6 +41,16 @@ namespace Umbraco.Core
|
||||
ToCSharpEscapeChars[escape[0]] = escape[1];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes new lines and tabs
|
||||
/// </summary>
|
||||
/// <param name="txt"></param>
|
||||
/// <returns></returns>
|
||||
internal static string StripWhitespace(this string txt)
|
||||
{
|
||||
return Regex.Replace(txt, @"\s", string.Empty);
|
||||
}
|
||||
|
||||
internal static string StripFileExtension(this string fileName)
|
||||
{
|
||||
//filenames cannot contain line breaks
|
||||
|
||||
@@ -198,7 +198,7 @@ namespace Umbraco.Core.Sync
|
||||
if (_released)
|
||||
return;
|
||||
|
||||
if ((DateTime.UtcNow - _lastSync).Seconds <= _options.ThrottleSeconds)
|
||||
if ((DateTime.UtcNow - _lastSync).TotalSeconds <= _options.ThrottleSeconds)
|
||||
return;
|
||||
|
||||
_syncing = true;
|
||||
|
||||
@@ -102,13 +102,13 @@
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Data.Entity" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
@@ -175,6 +175,7 @@
|
||||
<Compile Include="Cache\IJsonCacheRefresher.cs" />
|
||||
<Compile Include="Cache\JsonCacheRefresherBase.cs" />
|
||||
<Compile Include="Cache\NullCacheProvider.cs" />
|
||||
<Compile Include="Cache\RepositoryCachePolicyBase.cs" />
|
||||
<Compile Include="Cache\SingleItemsOnlyRepositoryCachePolicy.cs" />
|
||||
<Compile Include="Cache\OnlySingleItemsRepositoryCachePolicyFactory.cs" />
|
||||
<Compile Include="Cache\PayloadCacheRefresherBase.cs" />
|
||||
@@ -187,6 +188,7 @@
|
||||
<Compile Include="CodeAnnotations\UmbracoExperimentalFeatureAttribute.cs" />
|
||||
<Compile Include="CodeAnnotations\UmbracoProposedPublicAttribute.cs" />
|
||||
<Compile Include="Collections\DeepCloneableList.cs" />
|
||||
<Compile Include="Collections\ListCloneBehavior.cs" />
|
||||
<Compile Include="ConcurrentHashSet.cs" />
|
||||
<Compile Include="Configuration\BaseRest\IBaseRestSection.cs" />
|
||||
<Compile Include="Configuration\BaseRest\IExtension.cs" />
|
||||
@@ -470,6 +472,7 @@
|
||||
<Compile Include="Persistence\Repositories\TaskRepository.cs" />
|
||||
<Compile Include="Persistence\Repositories\TaskTypeRepository.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\GridValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\LabelValueConverter.cs" />
|
||||
<Compile Include="Publishing\UnPublishedStatusType.cs" />
|
||||
<Compile Include="Publishing\UnPublishStatus.cs" />
|
||||
<Compile Include="Security\BackOfficeClaimsIdentityFactory.cs" />
|
||||
|
||||
@@ -19,5 +19,5 @@
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="semver" version="1.1.2" targetFramework="net45" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net4" />
|
||||
<package id="SqlServerCE" version="4.0.0.0" targetFramework="net4" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -72,7 +72,7 @@
|
||||
<system.data>
|
||||
<DbProviderFactories>
|
||||
<remove invariant="System.Data.SqlServerCe.4.0" />
|
||||
<add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
|
||||
<add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
|
||||
<remove invariant="MySql.Data.MySqlClient" />
|
||||
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.6.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
|
||||
</DbProviderFactories>
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Umbraco.Tests.Cache
|
||||
[Test]
|
||||
public void Clones_List()
|
||||
{
|
||||
var original = new DeepCloneableList<DeepCloneableListTests.TestClone>();
|
||||
var original = new DeepCloneableList<DeepCloneableListTests.TestClone>(ListCloneBehavior.Always);
|
||||
original.Add(new DeepCloneableListTests.TestClone());
|
||||
original.Add(new DeepCloneableListTests.TestClone());
|
||||
original.Add(new DeepCloneableListTests.TestClone());
|
||||
|
||||
@@ -120,5 +120,37 @@ namespace Umbraco.Tests.Cache
|
||||
Assert.IsTrue(cacheCleared);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void If_Removes_Throws_Cache_Is_Removed()
|
||||
{
|
||||
var cacheCleared = false;
|
||||
var cache = new Mock<IRuntimeCacheProvider>();
|
||||
cache.Setup(x => x.ClearCacheItem(It.IsAny<string>()))
|
||||
.Callback(() =>
|
||||
{
|
||||
cacheCleared = true;
|
||||
});
|
||||
|
||||
var defaultPolicy = new DefaultRepositoryCachePolicy<AuditItem, object>(cache.Object, new RepositoryCachePolicyOptions());
|
||||
try
|
||||
{
|
||||
using (defaultPolicy)
|
||||
{
|
||||
defaultPolicy.Remove(new AuditItem(1, "blah", AuditType.Copy, 123), item =>
|
||||
{
|
||||
throw new Exception("blah!");
|
||||
});
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
//we need this catch or nunit throw up
|
||||
}
|
||||
finally
|
||||
{
|
||||
Assert.IsTrue(cacheCleared);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace Umbraco.Tests.Cache.DistributedCache
|
||||
{
|
||||
for (var i = 1; i < 11; i++)
|
||||
{
|
||||
Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
|
||||
global::Umbraco.Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
|
||||
}
|
||||
Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count);
|
||||
}
|
||||
@@ -52,7 +52,7 @@ namespace Umbraco.Tests.Cache.DistributedCache
|
||||
{
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
Web.Cache.DistributedCache.Instance.Refresh(
|
||||
global::Umbraco.Web.Cache.DistributedCache.Instance.Refresh(
|
||||
Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"),
|
||||
x => x.Id,
|
||||
new TestObjectWithId{Id = i});
|
||||
@@ -65,7 +65,7 @@ namespace Umbraco.Tests.Cache.DistributedCache
|
||||
{
|
||||
for (var i = 0; i < 11; i++)
|
||||
{
|
||||
Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), Guid.NewGuid());
|
||||
global::Umbraco.Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), Guid.NewGuid());
|
||||
}
|
||||
Assert.AreEqual(11, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).GuidIdsRefreshed.Count);
|
||||
}
|
||||
@@ -75,7 +75,7 @@ namespace Umbraco.Tests.Cache.DistributedCache
|
||||
{
|
||||
for (var i = 1; i < 13; i++)
|
||||
{
|
||||
Web.Cache.DistributedCache.Instance.Remove(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
|
||||
global::Umbraco.Web.Cache.DistributedCache.Instance.Remove(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i);
|
||||
}
|
||||
Assert.AreEqual(12, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRemoved.Count);
|
||||
}
|
||||
@@ -85,7 +85,7 @@ namespace Umbraco.Tests.Cache.DistributedCache
|
||||
{
|
||||
for (var i = 0; i < 13; i++)
|
||||
{
|
||||
Web.Cache.DistributedCache.Instance.RefreshAll(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"));
|
||||
global::Umbraco.Web.Cache.DistributedCache.Instance.RefreshAll(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"));
|
||||
}
|
||||
Assert.AreEqual(13, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).CountOfFullRefreshes);
|
||||
}
|
||||
|
||||
@@ -14,9 +14,57 @@ namespace Umbraco.Tests.Cache
|
||||
[TestFixture]
|
||||
public class FullDataSetCachePolicyTests
|
||||
{
|
||||
[Test]
|
||||
public void Caches_Single()
|
||||
{
|
||||
var getAll = new[]
|
||||
{
|
||||
new AuditItem(1, "blah", AuditType.Copy, 123),
|
||||
new AuditItem(2, "blah2", AuditType.Copy, 123)
|
||||
};
|
||||
|
||||
var isCached = false;
|
||||
var cache = new Mock<IRuntimeCacheProvider>();
|
||||
cache.Setup(x => x.InsertCacheItem(It.IsAny<string>(), It.IsAny<Func<object>>(), It.IsAny<TimeSpan?>(), It.IsAny<bool>(),
|
||||
It.IsAny<CacheItemPriority>(), It.IsAny<CacheItemRemovedCallback>(), It.IsAny<string[]>()))
|
||||
.Callback(() =>
|
||||
{
|
||||
isCached = true;
|
||||
});
|
||||
|
||||
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
|
||||
using (defaultPolicy)
|
||||
{
|
||||
var found = defaultPolicy.Get(1, o => new AuditItem(1, "blah", AuditType.Copy, 123));
|
||||
}
|
||||
Assert.IsTrue(isCached);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Single_From_Cache()
|
||||
{
|
||||
var getAll = new[]
|
||||
{
|
||||
new AuditItem(1, "blah", AuditType.Copy, 123),
|
||||
new AuditItem(2, "blah2", AuditType.Copy, 123)
|
||||
};
|
||||
|
||||
var cache = new Mock<IRuntimeCacheProvider>();
|
||||
cache.Setup(x => x.GetCacheItem(It.IsAny<string>())).Returns(new AuditItem(1, "blah", AuditType.Copy, 123));
|
||||
|
||||
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
|
||||
using (defaultPolicy)
|
||||
{
|
||||
var found = defaultPolicy.Get(1, o => (AuditItem)null);
|
||||
Assert.IsNotNull(found);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_All_Caches_Empty_List()
|
||||
{
|
||||
var getAll = new AuditItem[] {};
|
||||
|
||||
var cached = new List<string>();
|
||||
|
||||
IList list = null;
|
||||
@@ -33,23 +81,23 @@ namespace Umbraco.Tests.Cache
|
||||
cache.Setup(x => x.GetCacheItem(It.IsAny<string>())).Returns(() =>
|
||||
{
|
||||
//return null if this is the first pass
|
||||
return cached.Any() ? new DeepCloneableList<AuditItem>() : null;
|
||||
return cached.Any() ? new DeepCloneableList<AuditItem>(ListCloneBehavior.CloneOnce) : null;
|
||||
});
|
||||
|
||||
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id);
|
||||
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
|
||||
using (defaultPolicy)
|
||||
{
|
||||
var found = defaultPolicy.GetAll(new object[] {}, o => new AuditItem[] {});
|
||||
var found = defaultPolicy.GetAll(new object[] {}, o => getAll);
|
||||
}
|
||||
|
||||
Assert.AreEqual(1, cached.Count);
|
||||
Assert.IsNotNull(list);
|
||||
|
||||
//Do it again, ensure that its coming from the cache!
|
||||
defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id);
|
||||
defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
|
||||
using (defaultPolicy)
|
||||
{
|
||||
var found = defaultPolicy.GetAll(new object[] { }, o => new AuditItem[] { });
|
||||
var found = defaultPolicy.GetAll(new object[] { }, o => getAll);
|
||||
}
|
||||
|
||||
Assert.AreEqual(1, cached.Count);
|
||||
@@ -59,6 +107,12 @@ namespace Umbraco.Tests.Cache
|
||||
[Test]
|
||||
public void Get_All_Caches_As_Single_List()
|
||||
{
|
||||
var getAll = new[]
|
||||
{
|
||||
new AuditItem(1, "blah", AuditType.Copy, 123),
|
||||
new AuditItem(2, "blah2", AuditType.Copy, 123)
|
||||
};
|
||||
|
||||
var cached = new List<string>();
|
||||
IList list = null;
|
||||
|
||||
@@ -73,14 +127,10 @@ namespace Umbraco.Tests.Cache
|
||||
});
|
||||
cache.Setup(x => x.GetCacheItem(It.IsAny<string>())).Returns(new AuditItem[] { });
|
||||
|
||||
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id);
|
||||
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
|
||||
using (defaultPolicy)
|
||||
{
|
||||
var found = defaultPolicy.GetAll(new object[] { }, o => new[]
|
||||
{
|
||||
new AuditItem(1, "blah", AuditType.Copy, 123),
|
||||
new AuditItem(2, "blah2", AuditType.Copy, 123)
|
||||
});
|
||||
var found = defaultPolicy.GetAll(new object[] { }, o => getAll);
|
||||
}
|
||||
|
||||
Assert.AreEqual(1, cached.Count);
|
||||
@@ -89,21 +139,99 @@ namespace Umbraco.Tests.Cache
|
||||
|
||||
[Test]
|
||||
public void Get_All_Without_Ids_From_Cache()
|
||||
{
|
||||
{
|
||||
var getAll = new[] { (AuditItem)null };
|
||||
|
||||
var cache = new Mock<IRuntimeCacheProvider>();
|
||||
|
||||
cache.Setup(x => x.GetCacheItem(It.IsAny<string>())).Returns(() => new DeepCloneableList<AuditItem>
|
||||
cache.Setup(x => x.GetCacheItem(It.IsAny<string>())).Returns(() => new DeepCloneableList<AuditItem>(ListCloneBehavior.CloneOnce)
|
||||
{
|
||||
new AuditItem(1, "blah", AuditType.Copy, 123),
|
||||
new AuditItem(2, "blah2", AuditType.Copy, 123)
|
||||
});
|
||||
|
||||
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id);
|
||||
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
|
||||
using (defaultPolicy)
|
||||
{
|
||||
var found = defaultPolicy.GetAll(new object[] { }, o => new[] { (AuditItem)null });
|
||||
var found = defaultPolicy.GetAll(new object[] { }, o => getAll);
|
||||
Assert.AreEqual(2, found.Length);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void If_CreateOrUpdate_Throws_Cache_Is_Removed()
|
||||
{
|
||||
var getAll = new[]
|
||||
{
|
||||
new AuditItem(1, "blah", AuditType.Copy, 123),
|
||||
new AuditItem(2, "blah2", AuditType.Copy, 123)
|
||||
};
|
||||
|
||||
var cacheCleared = false;
|
||||
var cache = new Mock<IRuntimeCacheProvider>();
|
||||
cache.Setup(x => x.ClearCacheItem(It.IsAny<string>()))
|
||||
.Callback(() =>
|
||||
{
|
||||
cacheCleared = true;
|
||||
});
|
||||
|
||||
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
|
||||
try
|
||||
{
|
||||
using (defaultPolicy)
|
||||
{
|
||||
defaultPolicy.CreateOrUpdate(new AuditItem(1, "blah", AuditType.Copy, 123), item =>
|
||||
{
|
||||
throw new Exception("blah!");
|
||||
});
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
//we need this catch or nunit throw up
|
||||
}
|
||||
finally
|
||||
{
|
||||
Assert.IsTrue(cacheCleared);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void If_Removes_Throws_Cache_Is_Removed()
|
||||
{
|
||||
var getAll = new[]
|
||||
{
|
||||
new AuditItem(1, "blah", AuditType.Copy, 123),
|
||||
new AuditItem(2, "blah2", AuditType.Copy, 123)
|
||||
};
|
||||
|
||||
var cacheCleared = false;
|
||||
var cache = new Mock<IRuntimeCacheProvider>();
|
||||
cache.Setup(x => x.ClearCacheItem(It.IsAny<string>()))
|
||||
.Callback(() =>
|
||||
{
|
||||
cacheCleared = true;
|
||||
});
|
||||
|
||||
var defaultPolicy = new FullDataSetRepositoryCachePolicy<AuditItem, object>(cache.Object, item => item.Id, () => getAll, false);
|
||||
try
|
||||
{
|
||||
using (defaultPolicy)
|
||||
{
|
||||
defaultPolicy.Remove(new AuditItem(1, "blah", AuditType.Copy, 123), item =>
|
||||
{
|
||||
throw new Exception("blah!");
|
||||
});
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
//we need this catch or nunit throw up
|
||||
}
|
||||
finally
|
||||
{
|
||||
Assert.IsTrue(cacheCleared);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,44 @@ namespace Umbraco.Tests.Collections
|
||||
[TestFixture]
|
||||
public class DeepCloneableListTests
|
||||
{
|
||||
[Test]
|
||||
public void Deep_Clones_Each_Item_Once()
|
||||
{
|
||||
var list = new DeepCloneableList<TestClone>(ListCloneBehavior.CloneOnce);
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
|
||||
var cloned = list.DeepClone() as DeepCloneableList<TestClone>;
|
||||
|
||||
//Test that each item in the sequence is equal - based on the equality comparer of TestClone (i.e. it's ID)
|
||||
Assert.IsTrue(list.SequenceEqual(cloned));
|
||||
|
||||
//Test that each instance in the list is not the same one
|
||||
foreach (var item in list)
|
||||
{
|
||||
var clone = cloned.Single(x => x.Id == item.Id);
|
||||
Assert.AreNotSame(item, clone);
|
||||
}
|
||||
|
||||
//clone again from the clone - since it's clone once the items should be the same
|
||||
var cloned2 = cloned.DeepClone() as DeepCloneableList<TestClone>;
|
||||
|
||||
//Test that each item in the sequence is equal - based on the equality comparer of TestClone (i.e. it's ID)
|
||||
Assert.IsTrue(cloned.SequenceEqual(cloned2));
|
||||
|
||||
//Test that each instance in the list is the same one
|
||||
foreach (var item in cloned)
|
||||
{
|
||||
var clone = cloned2.Single(x => x.Id == item.Id);
|
||||
Assert.AreSame(item, clone);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Deep_Clones_All_Elements()
|
||||
{
|
||||
var list = new DeepCloneableList<TestClone>();
|
||||
var list = new DeepCloneableList<TestClone>(ListCloneBehavior.Always);
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
@@ -30,7 +64,7 @@ namespace Umbraco.Tests.Collections
|
||||
[Test]
|
||||
public void Clones_Each_Item()
|
||||
{
|
||||
var list = new DeepCloneableList<TestClone>();
|
||||
var list = new DeepCloneableList<TestClone>(ListCloneBehavior.Always);
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
@@ -46,7 +80,7 @@ namespace Umbraco.Tests.Collections
|
||||
[Test]
|
||||
public void Cloned_Sequence_Equals()
|
||||
{
|
||||
var list = new DeepCloneableList<TestClone>();
|
||||
var list = new DeepCloneableList<TestClone>(ListCloneBehavior.Always);
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
|
||||
@@ -56,19 +56,19 @@ namespace Umbraco.Tests.Integration
|
||||
ServiceContext.DomainService.Save(new UmbracoDomain("*100112") { DomainName = "*100112", RootContentId = c3.Id, LanguageId = l2.Id });
|
||||
|
||||
var content = c2;
|
||||
var culture = Web.Models.ContentExtensions.GetCulture(null,
|
||||
var culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(null,
|
||||
ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService,
|
||||
content.Id, content.Path, new Uri("http://domain1.com/"));
|
||||
Assert.AreEqual("en-US", culture.Name);
|
||||
|
||||
content = c2;
|
||||
culture = Web.Models.ContentExtensions.GetCulture(null,
|
||||
culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(null,
|
||||
ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService,
|
||||
content.Id, content.Path, new Uri("http://domain1.fr/"));
|
||||
Assert.AreEqual("fr-FR", culture.Name);
|
||||
|
||||
content = c4;
|
||||
culture = Web.Models.ContentExtensions.GetCulture(null,
|
||||
culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(null,
|
||||
ServiceContext.DomainService, ServiceContext.LocalizationService, ServiceContext.ContentService,
|
||||
content.Id, content.Path, new Uri("http://domain1.fr/"));
|
||||
Assert.AreEqual("de-DE", culture.Name);
|
||||
|
||||
@@ -11,7 +11,7 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
@@ -208,6 +208,35 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_Query_On_ContentTypeRepository_Sort_By_Name()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
using (var repository = CreateRepository(unitOfWork))
|
||||
{
|
||||
var contentType = repository.Get(NodeDto.NodeIdSeed + 1);
|
||||
var child1 = MockedContentTypes.CreateSimpleContentType("aabc", "aabc", contentType, randomizeAliases: true);
|
||||
repository.AddOrUpdate(child1);
|
||||
var child3 = MockedContentTypes.CreateSimpleContentType("zyx", "zyx", contentType, randomizeAliases: true);
|
||||
repository.AddOrUpdate(child3);
|
||||
var child2 = MockedContentTypes.CreateSimpleContentType("a123", "a123", contentType, randomizeAliases: true);
|
||||
repository.AddOrUpdate(child2);
|
||||
unitOfWork.Commit();
|
||||
|
||||
// Act
|
||||
var contentTypes = repository.GetByQuery(new Query<IContentType>().Where(x => x.ParentId == contentType.Id));
|
||||
|
||||
// Assert
|
||||
Assert.That(contentTypes.Count(), Is.EqualTo(3));
|
||||
Assert.AreEqual("a123", contentTypes.ElementAt(0).Name);
|
||||
Assert.AreEqual("aabc", contentTypes.ElementAt(1).Name);
|
||||
Assert.AreEqual("zyx", contentTypes.ElementAt(2).Name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_Get_On_ContentTypeRepository()
|
||||
{
|
||||
|
||||
@@ -380,7 +380,7 @@ namespace Umbraco.Tests.Routing
|
||||
var content = umbracoContext.ContentCache.GetById(nodeId);
|
||||
Assert.IsNotNull(content);
|
||||
|
||||
var culture = Web.Models.ContentExtensions.GetCulture(umbracoContext, domainService, ServiceContext.LocalizationService, null, content.Id, content.Path, new Uri(currentUrl));
|
||||
var culture = global::Umbraco.Web.Models.ContentExtensions.GetCulture(umbracoContext, domainService, ServiceContext.LocalizationService, null, content.Id, content.Path, new Uri(currentUrl));
|
||||
Assert.AreEqual(expectedCulture, culture.Name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web.PublishedCache.XmlPublishedCache;
|
||||
|
||||
namespace Umbraco.Tests.Routing
|
||||
{
|
||||
[DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerFixture)]
|
||||
[TestFixture]
|
||||
public class RoutesCacheTests : BaseRoutingTest
|
||||
{
|
||||
[Test]
|
||||
public void U4_7939()
|
||||
{
|
||||
//var routingContext = GetRoutingContext("/test", 1111);
|
||||
var umbracoContext = GetUmbracoContext("/test", 0);
|
||||
var cache = umbracoContext.ContentCache.InnerCache as PublishedContentCache;
|
||||
if (cache == null) throw new Exception("Unsupported IPublishedContentCache, only the Xml one is supported.");
|
||||
|
||||
PublishedContentCache.UnitTesting = false; // else does not write to routes cache
|
||||
Assert.IsFalse(PublishedContentCache.UnitTesting);
|
||||
|
||||
var z = cache.GetByRoute(umbracoContext, false, "/home/sub1");
|
||||
Assert.IsNotNull(z);
|
||||
Assert.AreEqual(1173, z.Id);
|
||||
|
||||
var routes = cache.RoutesCache.GetCachedRoutes();
|
||||
Assert.AreEqual(1, routes.Count);
|
||||
|
||||
// before the fix, the following assert would fail because the route would
|
||||
// have been stored as { 0, "/home/sub1" } - essentially meaning we were NOT
|
||||
// storing anything in the route cache!
|
||||
|
||||
Assert.AreEqual(1173, routes.Keys.First());
|
||||
Assert.AreEqual("/home/sub1", routes.Values.First());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Web;
|
||||
using Microsoft.Owin;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Profiling;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
using Umbraco.Web.Security.Identity;
|
||||
|
||||
namespace Umbraco.Tests.Security
|
||||
{
|
||||
[TestFixture]
|
||||
public class BackOfficeCookieManagerTests
|
||||
{
|
||||
[Test]
|
||||
public void ShouldAuthenticateRequest_When_Not_Configured()
|
||||
{
|
||||
//should force app ctx to show not-configured
|
||||
ConfigurationManager.AppSettings.Set("umbracoConfigurationStatus", "");
|
||||
|
||||
var dbCtx = new Mock<DatabaseContext>(Mock.Of<IDatabaseFactory>(), Mock.Of<ILogger>(), Mock.Of<ISqlSyntaxProvider>(), "test");
|
||||
dbCtx.Setup(x => x.IsDatabaseConfigured).Returns(false);
|
||||
|
||||
var appCtx = new ApplicationContext(
|
||||
dbCtx.Object,
|
||||
MockHelper.GetMockedServiceContext(),
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
var umbCtx = UmbracoContext.CreateContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new WebSecurity(Mock.Of<HttpContextBase>(), appCtx),
|
||||
Mock.Of<IUmbracoSettingsSection>(), new List<IUrlProvider>(), false);
|
||||
|
||||
var mgr = new BackOfficeCookieManager(Mock.Of<IUmbracoContextAccessor>(accessor => accessor.Value == umbCtx));
|
||||
|
||||
var result = mgr.ShouldAuthenticateRequest(Mock.Of<IOwinContext>(), new Uri("http://localhost/umbraco"));
|
||||
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldAuthenticateRequest_When_Configured()
|
||||
{
|
||||
var dbCtx = new Mock<DatabaseContext>(Mock.Of<IDatabaseFactory>(), Mock.Of<ILogger>(), Mock.Of<ISqlSyntaxProvider>(), "test");
|
||||
dbCtx.Setup(x => x.IsDatabaseConfigured).Returns(true);
|
||||
|
||||
var appCtx = new ApplicationContext(
|
||||
dbCtx.Object,
|
||||
MockHelper.GetMockedServiceContext(),
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
var umbCtx = UmbracoContext.CreateContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new WebSecurity(Mock.Of<HttpContextBase>(), appCtx),
|
||||
Mock.Of<IUmbracoSettingsSection>(), new List<IUrlProvider>(), false);
|
||||
|
||||
var mgr = new BackOfficeCookieManager(Mock.Of<IUmbracoContextAccessor>(accessor => accessor.Value == umbCtx));
|
||||
|
||||
var request = new Mock<OwinRequest>();
|
||||
request.Setup(owinRequest => owinRequest.Uri).Returns(new Uri("http://localhost/umbraco"));
|
||||
|
||||
var result = mgr.ShouldAuthenticateRequest(
|
||||
Mock.Of<IOwinContext>(context => context.Request == request.Object),
|
||||
new Uri("http://localhost/umbraco"));
|
||||
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
//TODO : Write remaining tests for `ShouldAuthenticateRequest`
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
@@ -9,6 +8,7 @@ using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Tests.Security
|
||||
{
|
||||
@@ -105,7 +105,7 @@ namespace Umbraco.Tests.Security
|
||||
|
||||
var identity = new UmbracoBackOfficeIdentity(userData);
|
||||
|
||||
Assert.AreEqual(10, identity.Claims.Count());
|
||||
Assert.AreEqual(11, identity.Claims.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -132,7 +132,7 @@ namespace Umbraco.Tests.Security
|
||||
|
||||
var backofficeIdentity = new UmbracoBackOfficeIdentity(claimsIdentity, userData);
|
||||
|
||||
Assert.AreEqual(12, backofficeIdentity.Claims.Count());
|
||||
Assert.AreEqual(13, backofficeIdentity.Claims.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -156,7 +156,7 @@ namespace Umbraco.Tests.Security
|
||||
|
||||
var identity = new UmbracoBackOfficeIdentity(ticket);
|
||||
|
||||
Assert.AreEqual(11, identity.Claims.Count());
|
||||
Assert.AreEqual(12, identity.Claims.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -182,7 +182,7 @@ namespace Umbraco.Tests.Security
|
||||
|
||||
var cloned = identity.Clone();
|
||||
|
||||
Assert.AreEqual(11, cloned.Claims.Count());
|
||||
Assert.AreEqual(12, cloned.Claims.Count());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -75,6 +75,10 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Lucene.Net.2.9.4.1\lib\net40\Lucene.Net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||
@@ -94,6 +98,10 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Semver">
|
||||
<HintPath>..\packages\semver.1.1.2\lib\net45\Semver.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -102,13 +110,13 @@
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.Entity.Design" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
@@ -167,10 +175,10 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AngularIntegration\AngularAntiForgeryTests.cs" />
|
||||
<Compile Include="AngularIntegration\ContentModelSerializationTests.cs" />
|
||||
<Compile Include="AngularIntegration\JsInitializationTests.cs" />
|
||||
<Compile Include="AngularIntegration\ServerVariablesParserTests.cs" />
|
||||
<Compile Include="Web\AngularIntegration\AngularAntiForgeryTests.cs" />
|
||||
<Compile Include="Web\AngularIntegration\ContentModelSerializationTests.cs" />
|
||||
<Compile Include="Web\AngularIntegration\JsInitializationTests.cs" />
|
||||
<Compile Include="Web\AngularIntegration\ServerVariablesParserTests.cs" />
|
||||
<Compile Include="ApplicationContextTests.cs" />
|
||||
<Compile Include="AttemptTests.cs" />
|
||||
<Compile Include="Cache\CacheRefresherTests.cs" />
|
||||
@@ -179,12 +187,12 @@
|
||||
<Compile Include="Cache\FullDataSetCachePolicyTests.cs" />
|
||||
<Compile Include="Cache\SingleItemsOnlyCachePolicyTests.cs" />
|
||||
<Compile Include="Collections\DeepCloneableListTests.cs" />
|
||||
<Compile Include="Controllers\BackOfficeControllerUnitTests.cs" />
|
||||
<Compile Include="Web\Controllers\BackOfficeControllerUnitTests.cs" />
|
||||
<Compile Include="DelegateExtensionsTests.cs" />
|
||||
<Compile Include="Logging\AsyncRollingFileAppenderTest.cs" />
|
||||
<Compile Include="Logging\DebugAppender.cs" />
|
||||
<Compile Include="Logging\ParallelForwarderTest.cs" />
|
||||
<Compile Include="Mvc\RenderIndexActionSelectorAttributeTests.cs" />
|
||||
<Compile Include="Web\Mvc\RenderIndexActionSelectorAttributeTests.cs" />
|
||||
<Compile Include="Persistence\Repositories\AuditRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\DomainRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\PartialViewRepositoryTests.cs" />
|
||||
@@ -192,7 +200,9 @@
|
||||
<Compile Include="Persistence\Repositories\TaskRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\TaskTypeRepositoryTest.cs" />
|
||||
<Compile Include="Resolvers\ResolverBaseTest.cs" />
|
||||
<Compile Include="Routing\RoutesCacheTests.cs" />
|
||||
<Compile Include="Routing\UrlRoutingTestBase.cs" />
|
||||
<Compile Include="Security\BackOfficeCookieManagerTests.cs" />
|
||||
<Compile Include="Security\UmbracoBackOfficeIdentityTests.cs" />
|
||||
<Compile Include="Services\PublicAccessServiceTests.cs" />
|
||||
<Compile Include="StringNewlineExtensions.cs" />
|
||||
@@ -232,8 +242,8 @@
|
||||
<Compile Include="Models\UmbracoEntityTests.cs" />
|
||||
<Compile Include="Models\UserTests.cs" />
|
||||
<Compile Include="Models\UserTypeTests.cs" />
|
||||
<Compile Include="Mvc\SurfaceControllerTests.cs" />
|
||||
<Compile Include="Mvc\UmbracoViewPageTests.cs" />
|
||||
<Compile Include="Web\Mvc\SurfaceControllerTests.cs" />
|
||||
<Compile Include="Web\Mvc\UmbracoViewPageTests.cs" />
|
||||
<Compile Include="BootManagers\CoreBootManagerTests.cs" />
|
||||
<Compile Include="BootManagers\WebBootManagerTests.cs" />
|
||||
<Compile Include="Cache\ObjectCacheProviderTests.cs" />
|
||||
@@ -308,9 +318,9 @@
|
||||
<Compile Include="Configurations\UmbracoSettings\ViewstateMoverModuleElementTests.cs" />
|
||||
<Compile Include="Configurations\UmbracoSettings\WebRoutingElementDefaultTests.cs" />
|
||||
<Compile Include="Configurations\UmbracoSettings\WebRoutingElementTests.cs" />
|
||||
<Compile Include="Controllers\WebApiEditors\ContentControllerUnitTests.cs" />
|
||||
<Compile Include="Controllers\WebApiEditors\FilterAllowedOutgoingContentAttributeTests.cs" />
|
||||
<Compile Include="Controllers\WebApiEditors\MediaControllerUnitTests.cs" />
|
||||
<Compile Include="Web\Controllers\WebApiEditors\ContentControllerUnitTests.cs" />
|
||||
<Compile Include="Web\Controllers\WebApiEditors\FilterAllowedOutgoingContentAttributeTests.cs" />
|
||||
<Compile Include="Web\Controllers\WebApiEditors\MediaControllerUnitTests.cs" />
|
||||
<Compile Include="CoreXml\FrameworkXmlTests.cs" />
|
||||
<Compile Include="DynamicsAndReflection\QueryableExtensionTests.cs" />
|
||||
<Compile Include="DynamicsAndReflection\ExtensionMethodFinderTests.cs" />
|
||||
@@ -320,8 +330,8 @@
|
||||
<Compile Include="Migrations\Upgrades\ValidateV7UpgradeTest.cs" />
|
||||
<Compile Include="Models\ContentExtensionsTests.cs" />
|
||||
<Compile Include="Models\UserExtensionsTests.cs" />
|
||||
<Compile Include="Mvc\MergeParentContextViewDataAttributeTests.cs" />
|
||||
<Compile Include="Mvc\ViewDataDictionaryExtensionTests.cs" />
|
||||
<Compile Include="Web\Mvc\MergeParentContextViewDataAttributeTests.cs" />
|
||||
<Compile Include="Web\Mvc\ViewDataDictionaryExtensionTests.cs" />
|
||||
<Compile Include="Persistence\PetaPocoExtensionsTest.cs" />
|
||||
<Compile Include="Persistence\Querying\ContentTypeSqlMappingTests.cs" />
|
||||
<Compile Include="Persistence\Repositories\MacroRepositoryTest.cs" />
|
||||
@@ -417,7 +427,7 @@
|
||||
<Compile Include="PublishedContent\PublishedContentTests.cs" />
|
||||
<Compile Include="PublishedContent\PublishedMediaTests.cs" />
|
||||
<Compile Include="HashCodeCombinerTests.cs" />
|
||||
<Compile Include="Mvc\HtmlHelperExtensionMethodsTests.cs" />
|
||||
<Compile Include="Web\Mvc\HtmlHelperExtensionMethodsTests.cs" />
|
||||
<Compile Include="IO\IOHelperTest.cs" />
|
||||
<Compile Include="LibraryTests.cs" />
|
||||
<Compile Include="PropertyEditors\PropertyEditorValueConverterTests.cs" />
|
||||
@@ -502,7 +512,7 @@
|
||||
<DependentUpon>ImportResources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Services\ThreadSafetyServiceTest.cs" />
|
||||
<Compile Include="Controllers\PluginControllerAreaTests.cs" />
|
||||
<Compile Include="Web\Controllers\PluginControllerAreaTests.cs" />
|
||||
<Compile Include="Cache\DistributedCache\DistributedCacheTests.cs" />
|
||||
<Compile Include="Templates\MasterPageHelperTests.cs" />
|
||||
<Compile Include="TestHelpers\BaseDatabaseFactoryTest.cs" />
|
||||
@@ -566,6 +576,7 @@
|
||||
<Compile Include="Plugins\TypeFinderTests.cs" />
|
||||
<Compile Include="Routing\UmbracoModuleTests.cs" />
|
||||
<Compile Include="VersionExtensionTests.cs" />
|
||||
<Compile Include="Web\WebExtensionMethodTests.cs" />
|
||||
<Compile Include="XmlExtensionsTests.cs" />
|
||||
<Compile Include="XmlHelperTests.cs" />
|
||||
</ItemGroup>
|
||||
@@ -735,8 +746,13 @@
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\amd64\*.* "$(TargetDir)amd64\" /Y /F /E /D
|
||||
xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\" /Y /F /E /D</PostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\amd64\*.* "$(TargetDir)amd64\" /Y /F /E /I /C /D
|
||||
xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\" /Y /F /E /I /C /D</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
||||
+2
-11
@@ -1,20 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
|
||||
namespace Umbraco.Tests.AngularIntegration
|
||||
namespace Umbraco.Tests.Web.AngularIntegration
|
||||
{
|
||||
[TestFixture]
|
||||
public class AngularAntiForgeryTests
|
||||
+77
-80
@@ -1,80 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Tests.AngularIntegration
|
||||
{
|
||||
[TestFixture]
|
||||
public class ContentModelSerializationTests
|
||||
{
|
||||
[Test]
|
||||
public void Content_Display_To_Json()
|
||||
{
|
||||
//create 3 tabs with 3 properties each
|
||||
var tabs = new List<Tab<ContentPropertyDisplay>>();
|
||||
for (var tabIndex = 0; tabIndex < 3; tabIndex ++)
|
||||
{
|
||||
var props = new List<ContentPropertyDisplay>();
|
||||
for (var propertyIndex = 0; propertyIndex < 3; propertyIndex ++)
|
||||
{
|
||||
props.Add(new ContentPropertyDisplay
|
||||
{
|
||||
Alias = "property" + propertyIndex,
|
||||
Label = "Property " + propertyIndex,
|
||||
Id = propertyIndex,
|
||||
Value = "value" + propertyIndex,
|
||||
Config = new Dictionary<string, object> {{ propertyIndex.ToInvariantString(), "value" }},
|
||||
Description = "Description " + propertyIndex,
|
||||
View = "~/Views/View" + propertyIndex,
|
||||
HideLabel = false
|
||||
});
|
||||
}
|
||||
tabs.Add(new Tab<ContentPropertyDisplay>()
|
||||
{
|
||||
Alias = "Tab" + tabIndex,
|
||||
Label = "Tab" + tabIndex,
|
||||
Properties = props
|
||||
});
|
||||
}
|
||||
|
||||
var displayModel = new ContentItemDisplay
|
||||
{
|
||||
Id = 1234,
|
||||
Name = "Test",
|
||||
Tabs = tabs
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(displayModel);
|
||||
|
||||
var jObject = JObject.Parse(json);
|
||||
|
||||
Assert.AreEqual("1234", jObject["id"].ToString());
|
||||
Assert.AreEqual("Test", jObject["name"].ToString());
|
||||
Assert.AreEqual(3, jObject["tabs"].Count());
|
||||
for (var tab = 0; tab < jObject["tabs"].Count(); tab++)
|
||||
{
|
||||
Assert.AreEqual("Tab" + tab, jObject["tabs"][tab]["alias"].ToString());
|
||||
Assert.AreEqual("Tab" + tab, jObject["tabs"][tab]["label"].ToString());
|
||||
Assert.AreEqual(3, jObject["tabs"][tab]["properties"].Count());
|
||||
for (var prop = 0; prop < jObject["tabs"][tab]["properties"].Count(); prop++)
|
||||
{
|
||||
Assert.AreEqual("property" + prop, jObject["tabs"][tab]["properties"][prop]["alias"].ToString());
|
||||
Assert.AreEqual("Property " + prop, jObject["tabs"][tab]["properties"][prop]["label"].ToString());
|
||||
Assert.AreEqual(prop, jObject["tabs"][tab]["properties"][prop]["id"].Value<int>());
|
||||
Assert.AreEqual("value" + prop, jObject["tabs"][tab]["properties"][prop]["value"].ToString());
|
||||
Assert.AreEqual("{\"" + prop + "\":\"value\"}", jObject["tabs"][tab]["properties"][prop]["config"].ToString(Formatting.None));
|
||||
Assert.AreEqual("Description " + prop, jObject["tabs"][tab]["properties"][prop]["description"].ToString());
|
||||
Assert.AreEqual(false, jObject["tabs"][tab]["properties"][prop]["hideLabel"].Value<bool>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Tests.Web.AngularIntegration
|
||||
{
|
||||
[TestFixture]
|
||||
public class ContentModelSerializationTests
|
||||
{
|
||||
[Test]
|
||||
public void Content_Display_To_Json()
|
||||
{
|
||||
//create 3 tabs with 3 properties each
|
||||
var tabs = new List<Tab<ContentPropertyDisplay>>();
|
||||
for (var tabIndex = 0; tabIndex < 3; tabIndex ++)
|
||||
{
|
||||
var props = new List<ContentPropertyDisplay>();
|
||||
for (var propertyIndex = 0; propertyIndex < 3; propertyIndex ++)
|
||||
{
|
||||
props.Add(new ContentPropertyDisplay
|
||||
{
|
||||
Alias = "property" + propertyIndex,
|
||||
Label = "Property " + propertyIndex,
|
||||
Id = propertyIndex,
|
||||
Value = "value" + propertyIndex,
|
||||
Config = new Dictionary<string, object> {{ propertyIndex.ToInvariantString(), "value" }},
|
||||
Description = "Description " + propertyIndex,
|
||||
View = "~/Views/View" + propertyIndex,
|
||||
HideLabel = false
|
||||
});
|
||||
}
|
||||
tabs.Add(new Tab<ContentPropertyDisplay>()
|
||||
{
|
||||
Alias = "Tab" + tabIndex,
|
||||
Label = "Tab" + tabIndex,
|
||||
Properties = props
|
||||
});
|
||||
}
|
||||
|
||||
var displayModel = new ContentItemDisplay
|
||||
{
|
||||
Id = 1234,
|
||||
Name = "Test",
|
||||
Tabs = tabs
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(displayModel);
|
||||
|
||||
var jObject = JObject.Parse(json);
|
||||
|
||||
Assert.AreEqual("1234", jObject["id"].ToString());
|
||||
Assert.AreEqual("Test", jObject["name"].ToString());
|
||||
Assert.AreEqual(3, jObject["tabs"].Count());
|
||||
for (var tab = 0; tab < jObject["tabs"].Count(); tab++)
|
||||
{
|
||||
Assert.AreEqual("Tab" + tab, jObject["tabs"][tab]["alias"].ToString());
|
||||
Assert.AreEqual("Tab" + tab, jObject["tabs"][tab]["label"].ToString());
|
||||
Assert.AreEqual(3, jObject["tabs"][tab]["properties"].Count());
|
||||
for (var prop = 0; prop < jObject["tabs"][tab]["properties"].Count(); prop++)
|
||||
{
|
||||
Assert.AreEqual("property" + prop, jObject["tabs"][tab]["properties"][prop]["alias"].ToString());
|
||||
Assert.AreEqual("Property " + prop, jObject["tabs"][tab]["properties"][prop]["label"].ToString());
|
||||
Assert.AreEqual(prop, jObject["tabs"][tab]["properties"][prop]["id"].Value<int>());
|
||||
Assert.AreEqual("value" + prop, jObject["tabs"][tab]["properties"][prop]["value"].ToString());
|
||||
Assert.AreEqual("{\"" + prop + "\":\"value\"}", jObject["tabs"][tab]["properties"][prop]["config"].ToString(Formatting.None));
|
||||
Assert.AreEqual("Description " + prop, jObject["tabs"][tab]["properties"][prop]["description"].ToString());
|
||||
Assert.AreEqual(false, jObject["tabs"][tab]["properties"][prop]["hideLabel"].Value<bool>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+36
-41
@@ -1,41 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Manifest;
|
||||
using Umbraco.Web.UI.JavaScript;
|
||||
|
||||
namespace Umbraco.Tests.AngularIntegration
|
||||
{
|
||||
[TestFixture]
|
||||
public class JsInitializationTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Get_Default_Init()
|
||||
{
|
||||
var init = JsInitialization.GetDefaultInitialization();
|
||||
Assert.IsTrue(init.Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_Main()
|
||||
{
|
||||
var result = JsInitialization.ParseMain(new[] {"[World]", "Hello" });
|
||||
|
||||
Assert.AreEqual(@"LazyLoad.js([World], function () {
|
||||
//we need to set the legacy UmbClientMgr path
|
||||
UmbClientMgr.setUmbracoPath('Hello');
|
||||
|
||||
jQuery(document).ready(function () {
|
||||
|
||||
angular.bootstrap(document, ['umbraco']);
|
||||
|
||||
});
|
||||
});", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.UI.JavaScript;
|
||||
|
||||
namespace Umbraco.Tests.Web.AngularIntegration
|
||||
{
|
||||
[TestFixture]
|
||||
public class JsInitializationTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void Get_Default_Init()
|
||||
{
|
||||
var init = JsInitialization.GetDefaultInitialization();
|
||||
Assert.IsTrue(init.Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Parse_Main()
|
||||
{
|
||||
var result = JsInitialization.ParseMain(new[] {"[World]", "Hello" });
|
||||
|
||||
Assert.AreEqual(@"LazyLoad.js([World], function () {
|
||||
//we need to set the legacy UmbClientMgr path
|
||||
UmbClientMgr.setUmbracoPath('Hello');
|
||||
|
||||
jQuery(document).ready(function () {
|
||||
|
||||
angular.bootstrap(document, ['umbraco']);
|
||||
|
||||
});
|
||||
});".StripWhitespace(), result.StripWhitespace());
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
-32
@@ -1,33 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Web.UI.JavaScript;
|
||||
|
||||
namespace Umbraco.Tests.AngularIntegration
|
||||
{
|
||||
[TestFixture]
|
||||
public class ServerVariablesParserTests
|
||||
{
|
||||
|
||||
|
||||
[Test]
|
||||
public void Parse()
|
||||
{
|
||||
var d = new Dictionary<string, object>();
|
||||
d.Add("test1", "Test 1");
|
||||
d.Add("test2", "Test 2");
|
||||
d.Add("test3", "Test 3");
|
||||
d.Add("test4", "Test 4");
|
||||
d.Add("test5", "Test 5");
|
||||
|
||||
var output = ServerVariablesParser.Parse(d);
|
||||
|
||||
Assert.IsTrue(output.Contains(@"Umbraco.Sys.ServerVariables = {
|
||||
""test1"": ""Test 1"",
|
||||
""test2"": ""Test 2"",
|
||||
""test3"": ""Test 3"",
|
||||
""test4"": ""Test 4"",
|
||||
""test5"": ""Test 5""
|
||||
} ;"));
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Web.UI.JavaScript;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.Web.AngularIntegration
|
||||
{
|
||||
[TestFixture]
|
||||
public class ServerVariablesParserTests
|
||||
{
|
||||
|
||||
|
||||
[Test]
|
||||
public void Parse()
|
||||
{
|
||||
var d = new Dictionary<string, object>();
|
||||
d.Add("test1", "Test 1");
|
||||
d.Add("test2", "Test 2");
|
||||
d.Add("test3", "Test 3");
|
||||
d.Add("test4", "Test 4");
|
||||
d.Add("test5", "Test 5");
|
||||
|
||||
var output = ServerVariablesParser.Parse(d).StripWhitespace();
|
||||
|
||||
Assert.IsTrue(output.Contains(@"Umbraco.Sys.ServerVariables = {
|
||||
""test1"": ""Test 1"",
|
||||
""test2"": ""Test 2"",
|
||||
""test3"": ""Test 3"",
|
||||
""test4"": ""Test 4"",
|
||||
""test5"": ""Test 5""
|
||||
} ;".StripWhitespace()));
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Web.Editors;
|
||||
|
||||
namespace Umbraco.Tests.Controllers
|
||||
namespace Umbraco.Tests.Web.Controllers
|
||||
{
|
||||
[TestFixture]
|
||||
public class BackOfficeControllerUnitTests
|
||||
+1
-1
@@ -4,7 +4,7 @@ using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Tests.Controllers
|
||||
namespace Umbraco.Tests.Web.Controllers
|
||||
{
|
||||
[TestFixture]
|
||||
public class PluginControllerAreaTests : BaseWebTest
|
||||
+366
-366
@@ -1,366 +1,366 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Http;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Editors;
|
||||
|
||||
namespace Umbraco.Tests.Controllers.WebApiEditors
|
||||
{
|
||||
[TestFixture]
|
||||
public class ContentControllerUnitTests
|
||||
{
|
||||
[Test]
|
||||
public void Access_Allowed_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
var contentMock = new Mock<IContent>();
|
||||
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
|
||||
var content = contentMock.Object;
|
||||
var contentServiceMock = new Mock<IContentService>();
|
||||
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
|
||||
var contentService = contentServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, contentService, 1234);
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Throws_Exception_When_No_Content_Found()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
var contentMock = new Mock<IContent>();
|
||||
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
|
||||
var content = contentMock.Object;
|
||||
var contentServiceMock = new Mock<IContentService>();
|
||||
contentServiceMock.Setup(x => x.GetById(0)).Returns(content);
|
||||
var contentService = contentServiceMock.Object;
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>();
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act/assert
|
||||
Assert.Throws<HttpResponseException>(() => ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F' }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(9876);
|
||||
var user = userMock.Object;
|
||||
var contentMock = new Mock<IContent>();
|
||||
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
|
||||
var content = contentMock.Object;
|
||||
var contentServiceMock = new Mock<IContentService>();
|
||||
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
|
||||
var contentService = contentServiceMock.Object;
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>();
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F'});
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_By_Permission()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
var contentMock = new Mock<IContent>();
|
||||
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
|
||||
var content = contentMock.Object;
|
||||
var contentServiceMock = new Mock<IContentService>();
|
||||
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
|
||||
var contentService = contentServiceMock.Object;
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1234, new string[]{ "A", "B", "C" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F'});
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_Allowed_By_Permission()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
var contentMock = new Mock<IContent>();
|
||||
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
|
||||
var content = contentMock.Object;
|
||||
var contentServiceMock = new Mock<IContentService>();
|
||||
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
|
||||
var contentService = contentServiceMock.Object;
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1234, new string[]{ "A", "F", "C" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F'});
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_To_Root_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -1);
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_To_Recycle_Bin_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -20);
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_To_Recycle_Bin_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(1234);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -20);
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_To_Root_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(1234);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -1);
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_To_Root_By_Permission()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1234, new string[]{ "A" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, -1)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -1, new[] { 'A'});
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_To_Root_By_Permission()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1234, new string[]{ "A" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, -1)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -1, new[] { 'B'});
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_To_Recycle_Bin_By_Permission()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1234, new string[]{ "A" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, -20)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -20, new[] { 'A'});
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_To_Recycle_Bin_By_Permission()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1234, new string[]{ "A" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, -20)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -20, new[] { 'B'});
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//NOTE: The below self hosted stuff does work so need to get some tests written. Some are not possible atm because
|
||||
// of the legacy SQL calls like checking permissions.
|
||||
|
||||
//[TestFixture]
|
||||
//public class ContentControllerHostedTests : BaseRoutingTest
|
||||
//{
|
||||
|
||||
// protected override DatabaseBehavior DatabaseTestBehavior
|
||||
// {
|
||||
// get { return DatabaseBehavior.NoDatabasePerFixture; }
|
||||
// }
|
||||
|
||||
// public override void TearDown()
|
||||
// {
|
||||
// base.TearDown();
|
||||
// UmbracoAuthorizeAttribute.Enable = true;
|
||||
// UmbracoApplicationAuthorizeAttribute.Enable = true;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Tests to ensure that the response filter works so that any items the user
|
||||
// /// doesn't have access to are removed
|
||||
// /// </summary>
|
||||
// [Test]
|
||||
// public async void Get_By_Ids_Response_Filtered()
|
||||
// {
|
||||
// UmbracoAuthorizeAttribute.Enable = false;
|
||||
// UmbracoApplicationAuthorizeAttribute.Enable = false;
|
||||
|
||||
// var baseUrl = string.Format("http://{0}:9876", Environment.MachineName);
|
||||
// var url = baseUrl + "/api/Content/GetByIds?ids=1&ids=2";
|
||||
|
||||
// var routingCtx = GetRoutingContext(url, 1234, null, true);
|
||||
|
||||
// var config = new HttpSelfHostConfiguration(baseUrl);
|
||||
// using (var server = new HttpSelfHostServer(config))
|
||||
// {
|
||||
// var route = config.Routes.MapHttpRoute("test", "api/Content/GetByIds",
|
||||
// new
|
||||
// {
|
||||
// controller = "Content",
|
||||
// action = "GetByIds",
|
||||
// id = RouteParameter.Optional
|
||||
// });
|
||||
// route.DataTokens["Namespaces"] = new string[] { "Umbraco.Web.Editors" };
|
||||
|
||||
// var client = new HttpClient(server);
|
||||
|
||||
// var request = new HttpRequestMessage
|
||||
// {
|
||||
// RequestUri = new Uri(url),
|
||||
// Method = HttpMethod.Get
|
||||
// };
|
||||
|
||||
// var result = await client.SendAsync(request);
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
//}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Http;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Editors;
|
||||
|
||||
namespace Umbraco.Tests.Web.Controllers.WebApiEditors
|
||||
{
|
||||
[TestFixture]
|
||||
public class ContentControllerUnitTests
|
||||
{
|
||||
[Test]
|
||||
public void Access_Allowed_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
var contentMock = new Mock<IContent>();
|
||||
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
|
||||
var content = contentMock.Object;
|
||||
var contentServiceMock = new Mock<IContentService>();
|
||||
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
|
||||
var contentService = contentServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, contentService, 1234);
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Throws_Exception_When_No_Content_Found()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
var contentMock = new Mock<IContent>();
|
||||
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
|
||||
var content = contentMock.Object;
|
||||
var contentServiceMock = new Mock<IContentService>();
|
||||
contentServiceMock.Setup(x => x.GetById(0)).Returns(content);
|
||||
var contentService = contentServiceMock.Object;
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>();
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act/assert
|
||||
Assert.Throws<HttpResponseException>(() => ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F' }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(9876);
|
||||
var user = userMock.Object;
|
||||
var contentMock = new Mock<IContent>();
|
||||
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
|
||||
var content = contentMock.Object;
|
||||
var contentServiceMock = new Mock<IContentService>();
|
||||
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
|
||||
var contentService = contentServiceMock.Object;
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>();
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F'});
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_By_Permission()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
var contentMock = new Mock<IContent>();
|
||||
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
|
||||
var content = contentMock.Object;
|
||||
var contentServiceMock = new Mock<IContentService>();
|
||||
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
|
||||
var contentService = contentServiceMock.Object;
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1234, new string[]{ "A", "B", "C" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F'});
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_Allowed_By_Permission()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
var contentMock = new Mock<IContent>();
|
||||
contentMock.Setup(c => c.Path).Returns("-1,1234,5678");
|
||||
var content = contentMock.Object;
|
||||
var contentServiceMock = new Mock<IContentService>();
|
||||
contentServiceMock.Setup(x => x.GetById(1234)).Returns(content);
|
||||
var contentService = contentServiceMock.Object;
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1234, new string[]{ "A", "F", "C" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, 1234)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, contentService, 1234, new[] { 'F'});
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_To_Root_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -1);
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_To_Recycle_Bin_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -20);
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_To_Recycle_Bin_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(1234);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -20);
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_To_Root_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(1234);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, null, null, -1);
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_To_Root_By_Permission()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1234, new string[]{ "A" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, -1)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -1, new[] { 'A'});
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_To_Root_By_Permission()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1234, new string[]{ "A" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, -1)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -1, new[] { 'B'});
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_To_Recycle_Bin_By_Permission()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1234, new string[]{ "A" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, -20)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -20, new[] { 'A'});
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_To_Recycle_Bin_By_Permission()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1234, new string[]{ "A" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, -20)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = ContentController.CheckPermissions(new Dictionary<string, object>(), user, userService, null, -20, new[] { 'B'});
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//NOTE: The below self hosted stuff does work so need to get some tests written. Some are not possible atm because
|
||||
// of the legacy SQL calls like checking permissions.
|
||||
|
||||
//[TestFixture]
|
||||
//public class ContentControllerHostedTests : BaseRoutingTest
|
||||
//{
|
||||
|
||||
// protected override DatabaseBehavior DatabaseTestBehavior
|
||||
// {
|
||||
// get { return DatabaseBehavior.NoDatabasePerFixture; }
|
||||
// }
|
||||
|
||||
// public override void TearDown()
|
||||
// {
|
||||
// base.TearDown();
|
||||
// UmbracoAuthorizeAttribute.Enable = true;
|
||||
// UmbracoApplicationAuthorizeAttribute.Enable = true;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Tests to ensure that the response filter works so that any items the user
|
||||
// /// doesn't have access to are removed
|
||||
// /// </summary>
|
||||
// [Test]
|
||||
// public async void Get_By_Ids_Response_Filtered()
|
||||
// {
|
||||
// UmbracoAuthorizeAttribute.Enable = false;
|
||||
// UmbracoApplicationAuthorizeAttribute.Enable = false;
|
||||
|
||||
// var baseUrl = string.Format("http://{0}:9876", Environment.MachineName);
|
||||
// var url = baseUrl + "/api/Content/GetByIds?ids=1&ids=2";
|
||||
|
||||
// var routingCtx = GetRoutingContext(url, 1234, null, true);
|
||||
|
||||
// var config = new HttpSelfHostConfiguration(baseUrl);
|
||||
// using (var server = new HttpSelfHostServer(config))
|
||||
// {
|
||||
// var route = config.Routes.MapHttpRoute("test", "api/Content/GetByIds",
|
||||
// new
|
||||
// {
|
||||
// controller = "Content",
|
||||
// action = "GetByIds",
|
||||
// id = RouteParameter.Optional
|
||||
// });
|
||||
// route.DataTokens["Namespaces"] = new string[] { "Umbraco.Web.Editors" };
|
||||
|
||||
// var client = new HttpClient(server);
|
||||
|
||||
// var request = new HttpRequestMessage
|
||||
// {
|
||||
// RequestUri = new Uri(url),
|
||||
// Method = HttpMethod.Get
|
||||
// };
|
||||
|
||||
// var result = await client.SendAsync(request);
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
//}
|
||||
}
|
||||
+135
-135
@@ -1,136 +1,136 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Formatting;
|
||||
using System.Net.Http.Headers;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
|
||||
namespace Umbraco.Tests.Controllers.WebApiEditors
|
||||
{
|
||||
[TestFixture]
|
||||
public class FilterAllowedOutgoingContentAttributeTests
|
||||
{
|
||||
[Test]
|
||||
public void GetValueFromResponse_Already_EnumerableContent()
|
||||
{
|
||||
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>));
|
||||
var val = new List<ContentItemBasic>() {new ContentItemBasic()};
|
||||
var result = att.GetValueFromResponse(
|
||||
new ObjectContent(typeof (IEnumerable<ContentItemBasic>),
|
||||
val,
|
||||
new JsonMediaTypeFormatter(),
|
||||
new MediaTypeHeaderValue("html/text")));
|
||||
|
||||
Assert.AreEqual(val, result);
|
||||
Assert.AreEqual(1, ((IEnumerable<ContentItemBasic>)result).Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetValueFromResponse_From_Property()
|
||||
{
|
||||
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>), "MyList");
|
||||
var val = new List<ContentItemBasic>() { new ContentItemBasic() };
|
||||
var container = new MyTestClass() {MyList = val};
|
||||
|
||||
var result = att.GetValueFromResponse(
|
||||
new ObjectContent(typeof(MyTestClass),
|
||||
container,
|
||||
new JsonMediaTypeFormatter(),
|
||||
new MediaTypeHeaderValue("html/text")));
|
||||
|
||||
Assert.AreEqual(val, result);
|
||||
Assert.AreEqual(1, ((IEnumerable<ContentItemBasic>)result).Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetValueFromResponse_Returns_Null_Not_Found_Property()
|
||||
{
|
||||
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>), "DontFind");
|
||||
var val = new List<ContentItemBasic>() { new ContentItemBasic() };
|
||||
var container = new MyTestClass() { MyList = val };
|
||||
|
||||
var result = att.GetValueFromResponse(
|
||||
new ObjectContent(typeof(MyTestClass),
|
||||
container,
|
||||
new JsonMediaTypeFormatter(),
|
||||
new MediaTypeHeaderValue("html/text")));
|
||||
|
||||
Assert.AreEqual(null, result);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Filter_On_Start_Node()
|
||||
{
|
||||
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>));
|
||||
var list = new List<dynamic>();
|
||||
var path = "";
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
if (i > 0 && path.EndsWith(",") == false)
|
||||
{
|
||||
path += ",";
|
||||
}
|
||||
path += i.ToInvariantString();
|
||||
list.Add(new ContentItemBasic { Id = i, Name = "Test" + i, ParentId = i, Path = path });
|
||||
}
|
||||
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(5);
|
||||
var user = userMock.Object;
|
||||
|
||||
att.FilterBasedOnStartNode(list, user);
|
||||
|
||||
Assert.AreEqual(5, list.Count);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Filter_On_Permissions()
|
||||
{
|
||||
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>));
|
||||
var list = new List<dynamic>();
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
list.Add(new ContentItemBasic{Id = i, Name = "Test" + i, ParentId = -1});
|
||||
}
|
||||
var ids = list.Select(x => (int)x.Id).ToArray();
|
||||
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
//we're only assigning 3 nodes browse permissions so that is what we expect as a result
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1, new string[]{ "F" }),
|
||||
new EntityPermission(9, 2, new string[]{ "F" }),
|
||||
new EntityPermission(9, 3, new string[]{ "F" }),
|
||||
new EntityPermission(9, 4, new string[]{ "A" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, ids)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
att.FilterBasedOnPermissions(list, user, userService);
|
||||
|
||||
Assert.AreEqual(3, list.Count);
|
||||
Assert.AreEqual(1, list.ElementAt(0).Id);
|
||||
Assert.AreEqual(2, list.ElementAt(1).Id);
|
||||
Assert.AreEqual(3, list.ElementAt(2).Id);
|
||||
}
|
||||
|
||||
private class MyTestClass
|
||||
{
|
||||
public IEnumerable<ContentItemBasic> MyList { get; set; }
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Formatting;
|
||||
using System.Net.Http.Headers;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
|
||||
namespace Umbraco.Tests.Web.Controllers.WebApiEditors
|
||||
{
|
||||
[TestFixture]
|
||||
public class FilterAllowedOutgoingContentAttributeTests
|
||||
{
|
||||
[Test]
|
||||
public void GetValueFromResponse_Already_EnumerableContent()
|
||||
{
|
||||
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>));
|
||||
var val = new List<ContentItemBasic>() {new ContentItemBasic()};
|
||||
var result = att.GetValueFromResponse(
|
||||
new ObjectContent(typeof (IEnumerable<ContentItemBasic>),
|
||||
val,
|
||||
new JsonMediaTypeFormatter(),
|
||||
new MediaTypeHeaderValue("html/text")));
|
||||
|
||||
Assert.AreEqual(val, result);
|
||||
Assert.AreEqual(1, ((IEnumerable<ContentItemBasic>)result).Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetValueFromResponse_From_Property()
|
||||
{
|
||||
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>), "MyList");
|
||||
var val = new List<ContentItemBasic>() { new ContentItemBasic() };
|
||||
var container = new MyTestClass() {MyList = val};
|
||||
|
||||
var result = att.GetValueFromResponse(
|
||||
new ObjectContent(typeof(MyTestClass),
|
||||
container,
|
||||
new JsonMediaTypeFormatter(),
|
||||
new MediaTypeHeaderValue("html/text")));
|
||||
|
||||
Assert.AreEqual(val, result);
|
||||
Assert.AreEqual(1, ((IEnumerable<ContentItemBasic>)result).Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetValueFromResponse_Returns_Null_Not_Found_Property()
|
||||
{
|
||||
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>), "DontFind");
|
||||
var val = new List<ContentItemBasic>() { new ContentItemBasic() };
|
||||
var container = new MyTestClass() { MyList = val };
|
||||
|
||||
var result = att.GetValueFromResponse(
|
||||
new ObjectContent(typeof(MyTestClass),
|
||||
container,
|
||||
new JsonMediaTypeFormatter(),
|
||||
new MediaTypeHeaderValue("html/text")));
|
||||
|
||||
Assert.AreEqual(null, result);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Filter_On_Start_Node()
|
||||
{
|
||||
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>));
|
||||
var list = new List<dynamic>();
|
||||
var path = "";
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
if (i > 0 && path.EndsWith(",") == false)
|
||||
{
|
||||
path += ",";
|
||||
}
|
||||
path += i.ToInvariantString();
|
||||
list.Add(new ContentItemBasic { Id = i, Name = "Test" + i, ParentId = i, Path = path });
|
||||
}
|
||||
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(5);
|
||||
var user = userMock.Object;
|
||||
|
||||
att.FilterBasedOnStartNode(list, user);
|
||||
|
||||
Assert.AreEqual(5, list.Count);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Filter_On_Permissions()
|
||||
{
|
||||
var att = new FilterAllowedOutgoingContentAttribute(typeof(IEnumerable<ContentItemBasic>));
|
||||
var list = new List<dynamic>();
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
list.Add(new ContentItemBasic{Id = i, Name = "Test" + i, ParentId = -1});
|
||||
}
|
||||
var ids = list.Select(x => (int)x.Id).ToArray();
|
||||
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartContentId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
var userServiceMock = new Mock<IUserService>();
|
||||
//we're only assigning 3 nodes browse permissions so that is what we expect as a result
|
||||
var permissions = new List<EntityPermission>
|
||||
{
|
||||
new EntityPermission(9, 1, new string[]{ "F" }),
|
||||
new EntityPermission(9, 2, new string[]{ "F" }),
|
||||
new EntityPermission(9, 3, new string[]{ "F" }),
|
||||
new EntityPermission(9, 4, new string[]{ "A" })
|
||||
};
|
||||
userServiceMock.Setup(x => x.GetPermissions(user, ids)).Returns(permissions);
|
||||
var userService = userServiceMock.Object;
|
||||
|
||||
att.FilterBasedOnPermissions(list, user, userService);
|
||||
|
||||
Assert.AreEqual(3, list.Count);
|
||||
Assert.AreEqual(1, list.ElementAt(0).Id);
|
||||
Assert.AreEqual(2, list.ElementAt(1).Id);
|
||||
Assert.AreEqual(3, list.ElementAt(2).Id);
|
||||
}
|
||||
|
||||
private class MyTestClass
|
||||
{
|
||||
public IEnumerable<ContentItemBasic> MyList { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
+141
-141
@@ -1,142 +1,142 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Http;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Editors;
|
||||
|
||||
namespace Umbraco.Tests.Controllers.WebApiEditors
|
||||
{
|
||||
[TestFixture]
|
||||
public class MediaControllerUnitTests
|
||||
{
|
||||
[Test]
|
||||
public void Access_Allowed_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
var mediaMock = new Mock<IMedia>();
|
||||
mediaMock.Setup(m => m.Path).Returns("-1,1234,5678");
|
||||
var media = mediaMock.Object;
|
||||
var mediaServiceMock = new Mock<IMediaService>();
|
||||
mediaServiceMock.Setup(x => x.GetById(1234)).Returns(media);
|
||||
var mediaService = mediaServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, mediaService, 1234);
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Throws_Exception_When_No_Media_Found()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
var mediaMock = new Mock<IMedia>();
|
||||
mediaMock.Setup(m => m.Path).Returns("-1,1234,5678");
|
||||
var media = mediaMock.Object;
|
||||
var mediaServiceMock = new Mock<IMediaService>();
|
||||
mediaServiceMock.Setup(x => x.GetById(0)).Returns(media);
|
||||
var mediaService = mediaServiceMock.Object;
|
||||
|
||||
//act/assert
|
||||
Assert.Throws<HttpResponseException>(() => MediaController.CheckPermissions(new Dictionary<string, object>(), user, mediaService, 1234));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(9876);
|
||||
var user = userMock.Object;
|
||||
var mediaMock = new Mock<IMedia>();
|
||||
mediaMock.Setup(m => m.Path).Returns("-1,1234,5678");
|
||||
var media = mediaMock.Object;
|
||||
var mediaServiceMock = new Mock<IMediaService>();
|
||||
mediaServiceMock.Setup(x => x.GetById(1234)).Returns(media);
|
||||
var mediaService = mediaServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, mediaService, 1234);
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_To_Root_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -1);
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_To_Root_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(1234);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -1);
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_To_Recycle_Bin_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -21);
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_To_Recycle_Bin_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(1234);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -21);
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Http;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Editors;
|
||||
|
||||
namespace Umbraco.Tests.Web.Controllers.WebApiEditors
|
||||
{
|
||||
[TestFixture]
|
||||
public class MediaControllerUnitTests
|
||||
{
|
||||
[Test]
|
||||
public void Access_Allowed_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
var mediaMock = new Mock<IMedia>();
|
||||
mediaMock.Setup(m => m.Path).Returns("-1,1234,5678");
|
||||
var media = mediaMock.Object;
|
||||
var mediaServiceMock = new Mock<IMediaService>();
|
||||
mediaServiceMock.Setup(x => x.GetById(1234)).Returns(media);
|
||||
var mediaService = mediaServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, mediaService, 1234);
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Throws_Exception_When_No_Media_Found()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
var mediaMock = new Mock<IMedia>();
|
||||
mediaMock.Setup(m => m.Path).Returns("-1,1234,5678");
|
||||
var media = mediaMock.Object;
|
||||
var mediaServiceMock = new Mock<IMediaService>();
|
||||
mediaServiceMock.Setup(x => x.GetById(0)).Returns(media);
|
||||
var mediaService = mediaServiceMock.Object;
|
||||
|
||||
//act/assert
|
||||
Assert.Throws<HttpResponseException>(() => MediaController.CheckPermissions(new Dictionary<string, object>(), user, mediaService, 1234));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(9);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(9876);
|
||||
var user = userMock.Object;
|
||||
var mediaMock = new Mock<IMedia>();
|
||||
mediaMock.Setup(m => m.Path).Returns("-1,1234,5678");
|
||||
var media = mediaMock.Object;
|
||||
var mediaServiceMock = new Mock<IMediaService>();
|
||||
mediaServiceMock.Setup(x => x.GetById(1234)).Returns(media);
|
||||
var mediaService = mediaServiceMock.Object;
|
||||
|
||||
//act
|
||||
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, mediaService, 1234);
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_To_Root_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -1);
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_To_Root_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(1234);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -1);
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Access_To_Recycle_Bin_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(-1);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -21);
|
||||
|
||||
//assert
|
||||
Assert.IsTrue(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void No_Access_To_Recycle_Bin_By_Path()
|
||||
{
|
||||
//arrange
|
||||
var userMock = new Mock<IUser>();
|
||||
userMock.Setup(u => u.Id).Returns(0);
|
||||
userMock.Setup(u => u.StartMediaId).Returns(1234);
|
||||
var user = userMock.Object;
|
||||
|
||||
//act
|
||||
var result = MediaController.CheckPermissions(new Dictionary<string, object>(), user, null, -21);
|
||||
|
||||
//assert
|
||||
Assert.IsFalse(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@ using System.Web.Mvc;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Web;
|
||||
|
||||
namespace Umbraco.Tests.Mvc
|
||||
namespace Umbraco.Tests.Web.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
public class HtmlHelperExtensionMethodsTests
|
||||
+85
-85
@@ -1,86 +1,86 @@
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Tests.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
public class MergeParentContextViewDataAttributeTests
|
||||
{
|
||||
[Test]
|
||||
public void Ensure_All_Ancestor_ViewData_Is_Merged()
|
||||
{
|
||||
var http = new FakeHttpContextFactory("http://localhost");
|
||||
|
||||
//setup an heirarchy
|
||||
var rootViewCtx = new ViewContext {Controller = new MyController(), RequestContext = http.RequestContext, ViewData = new ViewDataDictionary()};
|
||||
var parentViewCtx = new ViewContext { Controller = new MyController(), RequestContext = http.RequestContext, RouteData = new RouteData(), ViewData = new ViewDataDictionary() };
|
||||
parentViewCtx.RouteData.DataTokens.Add("ParentActionViewContext", rootViewCtx);
|
||||
var controllerCtx = new ControllerContext(http.RequestContext, new MyController()) {RouteData = new RouteData()};
|
||||
controllerCtx.RouteData.DataTokens.Add("ParentActionViewContext", parentViewCtx);
|
||||
|
||||
//set up the view data
|
||||
controllerCtx.Controller.ViewData["Test1"] = "Test1";
|
||||
controllerCtx.Controller.ViewData["Test2"] = "Test2";
|
||||
controllerCtx.Controller.ViewData["Test3"] = "Test3";
|
||||
parentViewCtx.ViewData["Test4"] = "Test4";
|
||||
parentViewCtx.ViewData["Test5"] = "Test5";
|
||||
parentViewCtx.ViewData["Test6"] = "Test6";
|
||||
rootViewCtx.ViewData["Test7"] = "Test7";
|
||||
rootViewCtx.ViewData["Test8"] = "Test8";
|
||||
rootViewCtx.ViewData["Test9"] = "Test9";
|
||||
|
||||
var filter = new ResultExecutingContext(controllerCtx, new ContentResult()) {RouteData = controllerCtx.RouteData};
|
||||
var att = new MergeParentContextViewDataAttribute();
|
||||
|
||||
Assert.IsTrue(filter.IsChildAction);
|
||||
att.OnResultExecuting(filter);
|
||||
|
||||
Assert.AreEqual(9, controllerCtx.Controller.ViewData.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_All_Ancestor_ViewData_Is_Merged_Without_Data_Loss()
|
||||
{
|
||||
var http = new FakeHttpContextFactory("http://localhost");
|
||||
|
||||
//setup an heirarchy
|
||||
var rootViewCtx = new ViewContext { Controller = new MyController(), RequestContext = http.RequestContext, ViewData = new ViewDataDictionary() };
|
||||
var parentViewCtx = new ViewContext { Controller = new MyController(), RequestContext = http.RequestContext, RouteData = new RouteData(), ViewData = new ViewDataDictionary() };
|
||||
parentViewCtx.RouteData.DataTokens.Add("ParentActionViewContext", rootViewCtx);
|
||||
var controllerCtx = new ControllerContext(http.RequestContext, new MyController()) { RouteData = new RouteData() };
|
||||
controllerCtx.RouteData.DataTokens.Add("ParentActionViewContext", parentViewCtx);
|
||||
|
||||
//set up the view data with overlapping keys
|
||||
controllerCtx.Controller.ViewData["Test1"] = "Test1";
|
||||
controllerCtx.Controller.ViewData["Test2"] = "Test2";
|
||||
controllerCtx.Controller.ViewData["Test3"] = "Test3";
|
||||
parentViewCtx.ViewData["Test2"] = "Test4";
|
||||
parentViewCtx.ViewData["Test3"] = "Test5";
|
||||
parentViewCtx.ViewData["Test4"] = "Test6";
|
||||
rootViewCtx.ViewData["Test3"] = "Test7";
|
||||
rootViewCtx.ViewData["Test4"] = "Test8";
|
||||
rootViewCtx.ViewData["Test5"] = "Test9";
|
||||
|
||||
var filter = new ResultExecutingContext(controllerCtx, new ContentResult()) { RouteData = controllerCtx.RouteData };
|
||||
var att = new MergeParentContextViewDataAttribute();
|
||||
|
||||
Assert.IsTrue(filter.IsChildAction);
|
||||
att.OnResultExecuting(filter);
|
||||
|
||||
Assert.AreEqual(5, controllerCtx.Controller.ViewData.Count);
|
||||
Assert.AreEqual("Test1", controllerCtx.Controller.ViewData["Test1"]);
|
||||
Assert.AreEqual("Test2", controllerCtx.Controller.ViewData["Test2"]);
|
||||
Assert.AreEqual("Test3", controllerCtx.Controller.ViewData["Test3"]);
|
||||
Assert.AreEqual("Test6", controllerCtx.Controller.ViewData["Test4"]);
|
||||
Assert.AreEqual("Test9", controllerCtx.Controller.ViewData["Test5"]);
|
||||
}
|
||||
|
||||
internal class MyController : Controller
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Tests.Web.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
public class MergeParentContextViewDataAttributeTests
|
||||
{
|
||||
[Test]
|
||||
public void Ensure_All_Ancestor_ViewData_Is_Merged()
|
||||
{
|
||||
var http = new FakeHttpContextFactory("http://localhost");
|
||||
|
||||
//setup an heirarchy
|
||||
var rootViewCtx = new ViewContext {Controller = new MyController(), RequestContext = http.RequestContext, ViewData = new ViewDataDictionary()};
|
||||
var parentViewCtx = new ViewContext { Controller = new MyController(), RequestContext = http.RequestContext, RouteData = new RouteData(), ViewData = new ViewDataDictionary() };
|
||||
parentViewCtx.RouteData.DataTokens.Add("ParentActionViewContext", rootViewCtx);
|
||||
var controllerCtx = new ControllerContext(http.RequestContext, new MyController()) {RouteData = new RouteData()};
|
||||
controllerCtx.RouteData.DataTokens.Add("ParentActionViewContext", parentViewCtx);
|
||||
|
||||
//set up the view data
|
||||
controllerCtx.Controller.ViewData["Test1"] = "Test1";
|
||||
controllerCtx.Controller.ViewData["Test2"] = "Test2";
|
||||
controllerCtx.Controller.ViewData["Test3"] = "Test3";
|
||||
parentViewCtx.ViewData["Test4"] = "Test4";
|
||||
parentViewCtx.ViewData["Test5"] = "Test5";
|
||||
parentViewCtx.ViewData["Test6"] = "Test6";
|
||||
rootViewCtx.ViewData["Test7"] = "Test7";
|
||||
rootViewCtx.ViewData["Test8"] = "Test8";
|
||||
rootViewCtx.ViewData["Test9"] = "Test9";
|
||||
|
||||
var filter = new ResultExecutingContext(controllerCtx, new ContentResult()) {RouteData = controllerCtx.RouteData};
|
||||
var att = new MergeParentContextViewDataAttribute();
|
||||
|
||||
Assert.IsTrue(filter.IsChildAction);
|
||||
att.OnResultExecuting(filter);
|
||||
|
||||
Assert.AreEqual(9, controllerCtx.Controller.ViewData.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ensure_All_Ancestor_ViewData_Is_Merged_Without_Data_Loss()
|
||||
{
|
||||
var http = new FakeHttpContextFactory("http://localhost");
|
||||
|
||||
//setup an heirarchy
|
||||
var rootViewCtx = new ViewContext { Controller = new MyController(), RequestContext = http.RequestContext, ViewData = new ViewDataDictionary() };
|
||||
var parentViewCtx = new ViewContext { Controller = new MyController(), RequestContext = http.RequestContext, RouteData = new RouteData(), ViewData = new ViewDataDictionary() };
|
||||
parentViewCtx.RouteData.DataTokens.Add("ParentActionViewContext", rootViewCtx);
|
||||
var controllerCtx = new ControllerContext(http.RequestContext, new MyController()) { RouteData = new RouteData() };
|
||||
controllerCtx.RouteData.DataTokens.Add("ParentActionViewContext", parentViewCtx);
|
||||
|
||||
//set up the view data with overlapping keys
|
||||
controllerCtx.Controller.ViewData["Test1"] = "Test1";
|
||||
controllerCtx.Controller.ViewData["Test2"] = "Test2";
|
||||
controllerCtx.Controller.ViewData["Test3"] = "Test3";
|
||||
parentViewCtx.ViewData["Test2"] = "Test4";
|
||||
parentViewCtx.ViewData["Test3"] = "Test5";
|
||||
parentViewCtx.ViewData["Test4"] = "Test6";
|
||||
rootViewCtx.ViewData["Test3"] = "Test7";
|
||||
rootViewCtx.ViewData["Test4"] = "Test8";
|
||||
rootViewCtx.ViewData["Test5"] = "Test9";
|
||||
|
||||
var filter = new ResultExecutingContext(controllerCtx, new ContentResult()) { RouteData = controllerCtx.RouteData };
|
||||
var att = new MergeParentContextViewDataAttribute();
|
||||
|
||||
Assert.IsTrue(filter.IsChildAction);
|
||||
att.OnResultExecuting(filter);
|
||||
|
||||
Assert.AreEqual(5, controllerCtx.Controller.ViewData.Count);
|
||||
Assert.AreEqual("Test1", controllerCtx.Controller.ViewData["Test1"]);
|
||||
Assert.AreEqual("Test2", controllerCtx.Controller.ViewData["Test2"]);
|
||||
Assert.AreEqual("Test3", controllerCtx.Controller.ViewData["Test3"]);
|
||||
Assert.AreEqual("Test6", controllerCtx.Controller.ViewData["Test4"]);
|
||||
Assert.AreEqual("Test9", controllerCtx.Controller.ViewData["Test5"]);
|
||||
}
|
||||
|
||||
internal class MyController : Controller
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -17,7 +17,7 @@ using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
|
||||
namespace Umbraco.Tests.Mvc
|
||||
namespace Umbraco.Tests.Web.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
public class RenderIndexActionSelectorAttributeTests
|
||||
+2
-5
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
@@ -12,7 +11,6 @@ using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Profiling;
|
||||
@@ -20,11 +18,10 @@ using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
|
||||
namespace Umbraco.Tests.Mvc
|
||||
namespace Umbraco.Tests.Web.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
public class SurfaceControllerTests
|
||||
@@ -165,7 +162,7 @@ namespace Umbraco.Tests.Mvc
|
||||
};
|
||||
|
||||
var routeData = new RouteData();
|
||||
routeData.DataTokens.Add("umbraco-route-def", routeDefinition);
|
||||
routeData.DataTokens.Add(Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken, routeDefinition);
|
||||
|
||||
var ctrl = new TestSurfaceController(umbCtx, new UmbracoHelper());
|
||||
ctrl.ControllerContext = new ControllerContext(contextBase, routeData, ctrl);
|
||||
+500
-504
File diff suppressed because it is too large
Load Diff
+40
-42
@@ -1,42 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Tests.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
public class ViewDataDictionaryExtensionTests
|
||||
{
|
||||
[Test]
|
||||
public void Merge_View_Data()
|
||||
{
|
||||
var source = new ViewDataDictionary();
|
||||
var dest = new ViewDataDictionary();
|
||||
source.Add("Test1", "Test1");
|
||||
dest.Add("Test2", "Test2");
|
||||
|
||||
dest.MergeViewDataFrom(source);
|
||||
|
||||
Assert.AreEqual(2, dest.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Merge_View_Data_Retains_Destination_Values()
|
||||
{
|
||||
var source = new ViewDataDictionary();
|
||||
var dest = new ViewDataDictionary();
|
||||
source.Add("Test1", "Test1");
|
||||
dest.Add("Test1", "MyValue");
|
||||
dest.Add("Test2", "Test2");
|
||||
|
||||
dest.MergeViewDataFrom(source);
|
||||
|
||||
Assert.AreEqual(2, dest.Count);
|
||||
Assert.AreEqual("MyValue", dest["Test1"]);
|
||||
Assert.AreEqual("Test2", dest["Test2"]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
using System.Web.Mvc;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Tests.Web.Mvc
|
||||
{
|
||||
[TestFixture]
|
||||
public class ViewDataDictionaryExtensionTests
|
||||
{
|
||||
[Test]
|
||||
public void Merge_View_Data()
|
||||
{
|
||||
var source = new ViewDataDictionary();
|
||||
var dest = new ViewDataDictionary();
|
||||
source.Add("Test1", "Test1");
|
||||
dest.Add("Test2", "Test2");
|
||||
|
||||
dest.MergeViewDataFrom(source);
|
||||
|
||||
Assert.AreEqual(2, dest.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Merge_View_Data_Retains_Destination_Values()
|
||||
{
|
||||
var source = new ViewDataDictionary();
|
||||
var dest = new ViewDataDictionary();
|
||||
source.Add("Test1", "Test1");
|
||||
dest.Add("Test1", "MyValue");
|
||||
dest.Add("Test2", "Test2");
|
||||
|
||||
dest.MergeViewDataFrom(source);
|
||||
|
||||
Assert.AreEqual(2, dest.Count);
|
||||
Assert.AreEqual("MyValue", dest["Test1"]);
|
||||
Assert.AreEqual("Test2", dest["Test2"]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Profiling;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.Routing;
|
||||
using Umbraco.Web.Security;
|
||||
|
||||
namespace Umbraco.Tests.Web
|
||||
{
|
||||
[TestFixture]
|
||||
public class WebExtensionMethodTests
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void UmbracoContextExtensions_GetUmbracoContext()
|
||||
{
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var umbCtx = UmbracoContext.CreateContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new WebSecurity(Mock.Of<HttpContextBase>(), appCtx),
|
||||
Mock.Of<IUmbracoSettingsSection>(),
|
||||
new List<IUrlProvider>(),
|
||||
false);
|
||||
var items = new Dictionary<object, object>()
|
||||
{
|
||||
{UmbracoContext.HttpContextItemName, umbCtx}
|
||||
};
|
||||
var http = new Mock<HttpContextBase>();
|
||||
http.Setup(x => x.Items).Returns(items);
|
||||
|
||||
var result = http.Object.GetUmbracoContext();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreSame(umbCtx, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RouteDataExtensions_GetUmbracoContext()
|
||||
{
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var umbCtx = UmbracoContext.CreateContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new WebSecurity(Mock.Of<HttpContextBase>(), appCtx),
|
||||
Mock.Of<IUmbracoSettingsSection>(),
|
||||
new List<IUrlProvider>(),
|
||||
false);
|
||||
var r1 = new RouteData();
|
||||
r1.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbCtx);
|
||||
|
||||
var result = r1.GetUmbracoContext();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreSame(umbCtx, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ControllerContextExtensions_GetUmbracoContext_From_RouteValues()
|
||||
{
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var umbCtx = UmbracoContext.CreateContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new WebSecurity(Mock.Of<HttpContextBase>(), appCtx),
|
||||
Mock.Of<IUmbracoSettingsSection>(),
|
||||
new List<IUrlProvider>(),
|
||||
false);
|
||||
|
||||
var r1 = new RouteData();
|
||||
r1.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbCtx);
|
||||
var ctx1 = CreateViewContext(new ControllerContext(Mock.Of<HttpContextBase>(), r1, new MyController()));
|
||||
var r2 = new RouteData();
|
||||
r2.DataTokens.Add("ParentActionViewContext", ctx1);
|
||||
var ctx2 = CreateViewContext(new ControllerContext(Mock.Of<HttpContextBase>(), r2, new MyController()));
|
||||
var r3 = new RouteData();
|
||||
r3.DataTokens.Add("ParentActionViewContext", ctx2);
|
||||
var ctx3 = CreateViewContext(new ControllerContext(Mock.Of<HttpContextBase>(), r3, new MyController()));
|
||||
|
||||
var result = ctx3.GetUmbracoContext();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreSame(umbCtx, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ControllerContextExtensions_GetUmbracoContext_From_HttpContext()
|
||||
{
|
||||
var appCtx = new ApplicationContext(
|
||||
CacheHelper.CreateDisabledCacheHelper(),
|
||||
new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
var umbCtx = UmbracoContext.CreateContext(
|
||||
Mock.Of<HttpContextBase>(),
|
||||
appCtx,
|
||||
new WebSecurity(Mock.Of<HttpContextBase>(), appCtx),
|
||||
Mock.Of<IUmbracoSettingsSection>(),
|
||||
new List<IUrlProvider>(),
|
||||
false);
|
||||
var items = new Dictionary<object, object>()
|
||||
{
|
||||
{UmbracoContext.HttpContextItemName, umbCtx}
|
||||
};
|
||||
var http = new Mock<HttpContextBase>();
|
||||
http.Setup(x => x.Items).Returns(items);
|
||||
|
||||
var r1 = new RouteData();
|
||||
var ctx1 = CreateViewContext(new ControllerContext(http.Object, r1, new MyController()));
|
||||
var r2 = new RouteData();
|
||||
r2.DataTokens.Add("ParentActionViewContext", ctx1);
|
||||
var ctx2 = CreateViewContext(new ControllerContext(http.Object, r2, new MyController()));
|
||||
var r3 = new RouteData();
|
||||
r3.DataTokens.Add("ParentActionViewContext", ctx2);
|
||||
var ctx3 = CreateViewContext(new ControllerContext(http.Object, r3, new MyController()));
|
||||
|
||||
var result = ctx3.GetUmbracoContext();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreSame(umbCtx, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ControllerContextExtensions_GetDataTokenInViewContextHierarchy()
|
||||
{
|
||||
var r1 = new RouteData();
|
||||
r1.DataTokens.Add("hello", "world");
|
||||
var ctx1 = CreateViewContext(new ControllerContext(Mock.Of<HttpContextBase>(), r1, new MyController()));
|
||||
var r2 = new RouteData();
|
||||
r2.DataTokens.Add("ParentActionViewContext", ctx1);
|
||||
var ctx2 = CreateViewContext(new ControllerContext(Mock.Of<HttpContextBase>(), r2, new MyController()));
|
||||
var r3 = new RouteData();
|
||||
r3.DataTokens.Add("ParentActionViewContext", ctx2);
|
||||
var ctx3 = CreateViewContext(new ControllerContext(Mock.Of<HttpContextBase>(), r3, new MyController()));
|
||||
|
||||
var result = ctx3.GetDataTokenInViewContextHierarchy("hello");
|
||||
|
||||
Assert.IsNotNull(result as string);
|
||||
Assert.AreEqual((string)result, "world");
|
||||
}
|
||||
|
||||
private ViewContext CreateViewContext(ControllerContext ctx)
|
||||
{
|
||||
return new ViewContext(ctx, Mock.Of<IView>(),
|
||||
new ViewDataDictionary(), new TempDataDictionary(), new StringWriter());
|
||||
}
|
||||
|
||||
private class MyController : Controller
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,15 @@
|
||||
<package id="Microsoft.AspNet.WebApi.SelfHost" version="4.0.30506.0" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net45" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
|
||||
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
|
||||
<package id="Moq" version="4.1.1309.0919" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
|
||||
<package id="NUnit" version="2.6.2" targetFramework="net45" />
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="Selenium.WebDriver" version="2.32.0" targetFramework="net45" />
|
||||
<package id="semver" version="1.1.2" targetFramework="net45" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.0" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -106,6 +106,31 @@ angular.module("umbraco.directives")
|
||||
|
||||
|
||||
if (tinyMceConfig.customConfig) {
|
||||
|
||||
//if there is some custom config, we need to see if the string value of each item might actually be json and if so, we need to
|
||||
// convert it to json instead of having it as a string since this is what tinymce requires
|
||||
for (var i in tinyMceConfig.customConfig) {
|
||||
var val = tinyMceConfig.customConfig[i];
|
||||
if (val) {
|
||||
val = val.toString().trim();
|
||||
if (val.detectIsJson()) {
|
||||
try {
|
||||
tinyMceConfig.customConfig[i] = JSON.parse(val);
|
||||
//now we need to check if this custom config key is defined in our baseline, if it is we don't want to
|
||||
//overwrite the baseline config item if it is an array, we want to concat the items in the array, otherwise
|
||||
//if it's an object it will overwrite the baseline
|
||||
if (angular.isArray(baseLineConfigObj[i]) && angular.isArray(tinyMceConfig.customConfig[i])) {
|
||||
//concat it and below this concat'd array will overwrite the baseline in angular.extend
|
||||
tinyMceConfig.customConfig[i] = baseLineConfigObj[i].concat(tinyMceConfig.customConfig[i]);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
//cannot parse, we'll just leave it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
angular.extend(baseLineConfigObj, tinyMceConfig.customConfig);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,4 +67,95 @@ iframe, .content-column-body {
|
||||
}
|
||||
.icon-chevron-down:before {
|
||||
content: "\e0c9";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Styling for validation in Public Access */
|
||||
|
||||
.pa-umb-overlay {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.pa-umb-overlay + .pa-umb-overlay {
|
||||
padding-top: 30px;
|
||||
border-top: 1px solid @grayLight;
|
||||
}
|
||||
|
||||
.pa-select-type {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.pa-select-type label {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.pa-access-header {
|
||||
font-weight: bold;
|
||||
margin: 0 0 3px 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.pa-access-description {
|
||||
color: #b3b3b3;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pa-validation-message {
|
||||
padding: 6px 12px !important;
|
||||
margin: 5px 0 0 0 !important;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.pa-select-pages label {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.pa-select-pages label + .controls-row {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.pa-select-pages .umb-detail {
|
||||
font-size: 13px;
|
||||
margin: 2px 0 5px;
|
||||
}
|
||||
|
||||
.pa-choose-page a {
|
||||
color: @blue;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.pa-choose-page a:hover, .pa-choose-page a:active, .pa-choose-page a:focus {
|
||||
color: @blueDark;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.pa-choose-page a:before {
|
||||
content:"+";
|
||||
margin-right: 3px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pa-choose-page .treePickerTitle {
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
font-style: italic;
|
||||
background: whitesmoke;
|
||||
padding: 3px 5px;
|
||||
color: grey;
|
||||
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
|
||||
.pa-form + .pa-form {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
@@ -210,14 +210,12 @@
|
||||
<Name>System.Data</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.0\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Drawing" />
|
||||
@@ -2401,10 +2399,10 @@
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\amd64\*.* "$(TargetDir)amd64\" /Y /F /E /D
|
||||
xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\" /Y /F /E /D</PostBuildEvent>
|
||||
<PreBuildEvent>xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\amd64\*.* "$(TargetDir)amd64\" /Y /F /E /I /C /D
|
||||
xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\" /Y /F /E /I /C /D</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
|
||||
@@ -2414,9 +2412,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.0\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7360</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7380</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7360</IISUrl>
|
||||
<IISUrl>http://localhost:7380</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.0" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="UrlRewritingNet.UrlRewriter" version="2.0.7" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -5,30 +5,30 @@
|
||||
<asp:Content ContentPlaceHolderID="head" runat="server">
|
||||
<script type="text/javascript">
|
||||
function updateLoginId() {
|
||||
var treePicker = window.showModalDialog('<%=umbraco.cms.presentation.Trees.TreeService.GetPickerUrl(true,"content","content")%>', 'treePicker', 'dialogWidth=350px;dialogHeight=300px;scrollbars=no;center=yes;border=thin;help=no;status=no')
|
||||
var treePicker = window.showModalDialog('<%=umbraco.cms.presentation.Trees.TreeService.GetPickerUrl(true,"content","content")%>', 'treePicker', 'dialogWidth=350px;dialogHeight=300px;scrollbars=no;center=yes;border=thin;help=no;status=no')
|
||||
if (treePicker != undefined) {
|
||||
document.getElementById("loginId").value = treePicker;
|
||||
if (treePicker > 0) {
|
||||
umbraco.presentation.webservices.CMSNode.GetNodeName('<%=umbraco.BasePages.BasePage.umbracoUserContextID%>', treePicker, updateLoginTitle);
|
||||
} else
|
||||
} else
|
||||
document.getElementById("loginTitle").innerHTML = "<strong><%=umbraco.ui.Text("content", base.getUser())%></strong>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function updateLoginTitle(result) {
|
||||
document.getElementById("loginTitle").innerHTML = "<strong>" + result + "</strong> ";
|
||||
}
|
||||
|
||||
function updateErrorId() {
|
||||
var treePicker = window.showModalDialog('<%=umbraco.cms.presentation.Trees.TreeService.GetPickerUrl(true,"content","content")%>', 'treePicker', 'dialogWidth=350px;dialogHeight=300px;scrollbars=no;center=yes;border=thin;help=no;status=no')
|
||||
var treePicker = window.showModalDialog('<%=umbraco.cms.presentation.Trees.TreeService.GetPickerUrl(true,"content","content")%>', 'treePicker', 'dialogWidth=350px;dialogHeight=300px;scrollbars=no;center=yes;border=thin;help=no;status=no')
|
||||
if (treePicker != undefined) {
|
||||
document.getElementById("errorId").value = treePicker;
|
||||
if (treePicker > 0) {
|
||||
umbraco.presentation.webservices.CMSNode.GetNodeName('<%=umbraco.BasePages.BasePage.umbracoUserContextID%>', treePicker, updateErrorTitle);
|
||||
} else
|
||||
} else
|
||||
document.getElementById("errorTitle").innerHTML = "<strong><%=umbraco.ui.Text("content", base.getUser())%></strong>";
|
||||
}
|
||||
}
|
||||
}
|
||||
function updateErrorTitle(result) {
|
||||
document.getElementById("errorTitle").innerHTML = "<strong>" + result + "</strong> ";
|
||||
}
|
||||
@@ -49,7 +49,7 @@
|
||||
document.getElementById("pagesForm").style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function togglePages() {
|
||||
document.getElementById("pagesForm").style.display = "block";
|
||||
}
|
||||
@@ -81,34 +81,37 @@
|
||||
|
||||
<cc1:Feedback ID="feedback" runat="server" />
|
||||
|
||||
<asp:Panel ID="p_mode" runat="server">
|
||||
|
||||
<asp:Panel ID="p_mode" runat="server" CssClass="pa-umb-overlay">
|
||||
|
||||
<div class="umg-dialog-body">
|
||||
|
||||
<cc1:Pane ID="pane_chooseMode" runat="server" Text="Choose how to restict access to this page">
|
||||
|
||||
<asp:RadioButton GroupName="mode" ID="rb_simple" runat="server" Style="float: left; margin: 10px;" Checked="true" />
|
||||
<div class="pa-select-type">
|
||||
<asp:RadioButton GroupName="mode" ID="rb_simple" runat="server" Checked="true" />
|
||||
|
||||
<div style="float: right;">
|
||||
<h4 style="padding-top: 0px;"><%= umbraco.ui.Text("publicAccess", "paSimple", base.getUser())%></h4>
|
||||
<p><%= umbraco.ui.Text("publicAccess", "paSimpleHelp", base.getUser())%></p>
|
||||
</div>
|
||||
<label for="body_rb_simple">
|
||||
<h4 class="pa-access-header"><%= umbraco.ui.Text("publicAccess", "paSimple", base.getUser())%></h4>
|
||||
<p class="pa-access-description"><%= umbraco.ui.Text("publicAccess", "paSimpleHelp", base.getUser())%></p>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<br style="clear: both;" />
|
||||
|
||||
<asp:RadioButton GroupName="mode" ID="rb_advanced" runat="server" Style="float: left; margin: 10px;" />
|
||||
<div class="pa-select-type">
|
||||
<asp:RadioButton GroupName="mode" ID="rb_advanced" runat="server"/>
|
||||
|
||||
<div style="float: left; padding-left: 10px;">
|
||||
<h4 style="padding-top: 0px;"><%= umbraco.ui.Text("publicAccess", "paAdvanced", base.getUser())%></h4>
|
||||
<p><%= umbraco.ui.Text("publicAccess", "paAdvancedHelp", base.getUser())%></p>
|
||||
<label for="body_rb_advanced">
|
||||
<h4 class="pa-access-header"><%= umbraco.ui.Text("publicAccess", "paAdvanced", base.getUser())%></h4>
|
||||
<p class="pa-access-description"><%= umbraco.ui.Text("publicAccess", "paAdvancedHelp", base.getUser())%></p>
|
||||
|
||||
<asp:Panel runat="server" Visible="false" ID="p_noGroupsFound" CssClass="error">
|
||||
<p>
|
||||
<%= umbraco.ui.Text("publicAccess", "paAdvancedNoGroups", UmbracoUser)%>
|
||||
</p>
|
||||
</asp:Panel>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</cc1:Pane>
|
||||
</div>
|
||||
|
||||
@@ -119,20 +122,24 @@
|
||||
</asp:Panel>
|
||||
|
||||
|
||||
<cc1:Pane ID="pane_simple" runat="server" Visible="false" Text="Single user protection">
|
||||
<cc1:PropertyPanel ID="PropertyPanel1" runat="server">
|
||||
<p><%= umbraco.ui.Text("publicAccess", "paSetLogin", UmbracoUser)%></p>
|
||||
<asp:CustomValidator runat="server" ID="SimpleLoginNameValidator" Display="Dynamic" EnableViewState="False">
|
||||
<p class="alert">Member name already exists, click <asp:LinkButton runat="server" OnClick="ChangeOnClick" CssClass="btn btn-mini btn-warning">Change</asp:LinkButton> to use a different name or Update to continue</p>
|
||||
</asp:CustomValidator>
|
||||
</cc1:PropertyPanel>
|
||||
<cc1:PropertyPanel Text="Login" ID="pp_login" runat="server">
|
||||
<asp:TextBox ID="simpleLogin" runat="server" Width="150px"></asp:TextBox>
|
||||
<asp:Label runat="server" ID="SimpleLoginLabel" Visible="False"></asp:Label>
|
||||
</cc1:PropertyPanel>
|
||||
<cc1:PropertyPanel Text="Password" ID="pp_pass" runat="server">
|
||||
<asp:TextBox ID="simplePassword" runat="server" Width="150px"></asp:TextBox>
|
||||
</cc1:PropertyPanel>
|
||||
<cc1:Pane ID="pane_simple" runat="server" Visible="false" Text="Set the login and password for this page" CssClass="pa-umb-overlay">
|
||||
|
||||
<div class="pa-form">
|
||||
<cc1:PropertyPanel Text="Login" ID="pp_login" runat="server">
|
||||
<asp:TextBox ID="simpleLogin" runat="server" Width="250px"></asp:TextBox>
|
||||
<asp:Label runat="server" ID="SimpleLoginLabel" Visible="False"></asp:Label>
|
||||
</cc1:PropertyPanel>
|
||||
</div>
|
||||
|
||||
<div class="pa-form">
|
||||
<cc1:PropertyPanel Text="Password" ID="pp_pass" runat="server">
|
||||
<asp:TextBox ID="simplePassword" runat="server" Width="250px"></asp:TextBox>
|
||||
</cc1:PropertyPanel>
|
||||
</div>
|
||||
|
||||
<asp:CustomValidator CssClass="pa-validation-message error" runat="server" ID="SimpleLoginNameValidator" Display="Dynamic" EnableViewState="False">
|
||||
<p class="alert">Member name already exists, click <asp:LinkButton runat="server" OnClick="ChangeOnClick" CssClass="btn btn-mini btn-warning">Change</asp:LinkButton> to use a different name or Update to continue</p>
|
||||
</asp:CustomValidator>
|
||||
</cc1:Pane>
|
||||
|
||||
<cc1:Pane ID="pane_advanced" runat="server" Visible="false" Text="Role based protection">
|
||||
@@ -144,27 +151,29 @@
|
||||
</cc1:PropertyPanel>
|
||||
</cc1:Pane>
|
||||
|
||||
<asp:Panel ID="p_buttons" runat="server" Visible="false">
|
||||
<asp:Panel ID="p_buttons" runat="server" Visible="false" CssClass="pa-umb-overlay">
|
||||
<cc1:Pane runat="server" ID="pane_pages" Text="Select the pages that contain login form and error messages">
|
||||
<cc1:PropertyPanel runat="server" ID="pp_loginPage">
|
||||
<asp:PlaceHolder ID="ph_loginpage" runat="server" />
|
||||
<asp:CustomValidator ErrorMessage="*" runat="server" ID="cv_loginPage" ForeColor="Red" />
|
||||
<br />
|
||||
<small>
|
||||
|
||||
<cc1:PropertyPanel runat="server" ID="pp_loginPage" CssClass="pa-select-pages">
|
||||
<small class="umb-detail">
|
||||
<%=umbraco.ui.Text("paLoginPageHelp")%>
|
||||
</small>
|
||||
<br />
|
||||
<br />
|
||||
<div class="pa-choose-page">
|
||||
<asp:PlaceHolder ID="ph_loginpage" runat="server" />
|
||||
</div>
|
||||
|
||||
<asp:CustomValidator ErrorMessage="Please pick a login page" runat="server" ID="cv_loginPage" ForeColor="Red" />
|
||||
</cc1:PropertyPanel>
|
||||
|
||||
<cc1:PropertyPanel runat="server" ID="pp_errorPage">
|
||||
<asp:PlaceHolder ID="ph_errorpage" runat="server" />
|
||||
<asp:CustomValidator ErrorMessage="*" runat="server" ID="cv_errorPage" ForeColor="Red" />
|
||||
<br />
|
||||
<small>
|
||||
|
||||
<cc1:PropertyPanel runat="server" ID="pp_errorPage" CssClass="pa-select-pages">
|
||||
<small class="umb-detail">
|
||||
<%=umbraco.ui.Text("paErrorPageHelp")%>
|
||||
</small>
|
||||
<br />
|
||||
<div class="pa-choose-page">
|
||||
<asp:PlaceHolder ID="ph_errorpage" runat="server" />
|
||||
</div>
|
||||
<asp:CustomValidator ErrorMessage="Please pick an error page" runat="server" ID="cv_errorPage" ForeColor="Red" />
|
||||
</cc1:PropertyPanel>
|
||||
|
||||
</cc1:Pane>
|
||||
|
||||
@@ -141,7 +141,9 @@ namespace Umbraco.Web.Cache
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.ContentTypeCacheKey);
|
||||
//clear static object cache
|
||||
global::umbraco.cms.businesslogic.ContentType.RemoveAllDataTypeCache();
|
||||
|
||||
|
||||
PublishedContentType.ClearAll();
|
||||
|
||||
base.RefreshAll();
|
||||
}
|
||||
|
||||
@@ -278,7 +280,9 @@ namespace Umbraco.Web.Cache
|
||||
|
||||
//clears the dictionary object cache of the legacy ContentType
|
||||
global::umbraco.cms.businesslogic.ContentType.RemoveFromDataTypeCache(payload.Alias);
|
||||
|
||||
|
||||
PublishedContentType.ClearContentType(payload.Id);
|
||||
|
||||
//need to recursively clear the cache for each child content type
|
||||
foreach (var descendant in payload.DescendantPayloads)
|
||||
{
|
||||
|
||||
@@ -108,6 +108,7 @@ namespace Umbraco.Web.Cache
|
||||
if (dataTypeCache)
|
||||
dataTypeCache.Result.ClearCacheByKeySearch(string.Format("{0}{1}", CacheKeys.DataTypePreValuesCacheKey, payload.Id));
|
||||
|
||||
PublishedContentType.ClearDataType(payload.Id);
|
||||
});
|
||||
|
||||
base.Refresh(jsonPayload);
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace Umbraco.Web.Macros
|
||||
var routeVals = new RouteData();
|
||||
routeVals.Values.Add("controller", "PartialViewMacro");
|
||||
routeVals.Values.Add("action", "Index");
|
||||
routeVals.DataTokens.Add("umbraco-context", umbCtx); //required for UmbracoViewPage
|
||||
routeVals.DataTokens.Add(Umbraco.Core.Constants.Web.UmbracoContextDataToken, umbCtx); //required for UmbracoViewPage
|
||||
|
||||
//lets render this controller as a child action
|
||||
var viewContext = new ViewContext {ViewData = new ViewDataDictionary()};;
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Umbraco.Web.Models.Mapping
|
||||
.ForMember(detail => detail.UserId, opt => opt.MapFrom(profile => GetIntId(profile.Id)));
|
||||
|
||||
config.CreateMap<IUser, UserData>()
|
||||
.ConstructUsing((IUser user) => new UserData(Guid.NewGuid().ToString("N"))) //this is the 'session id'
|
||||
.ConstructUsing((IUser user) => new UserData())
|
||||
.ForMember(detail => detail.Id, opt => opt.MapFrom(user => user.Id))
|
||||
.ForMember(detail => detail.AllowedApplications, opt => opt.MapFrom(user => user.AllowedSections))
|
||||
.ForMember(detail => detail.RealName, opt => opt.MapFrom(user => user.Name))
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace Umbraco.Web.Mvc
|
||||
|
||||
//match this area
|
||||
controllerPluginRoute.DataTokens.Add("area", area.AreaName);
|
||||
controllerPluginRoute.DataTokens.Add("umbraco", umbracoTokenValue); //ensure the umbraco token is set
|
||||
controllerPluginRoute.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, umbracoTokenValue); //ensure the umbraco token is set
|
||||
|
||||
return controllerPluginRoute;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Web.Mvc
|
||||
{
|
||||
public static class ControllerContextExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to get the Umbraco context from the whole ControllerContext hierarchy based on data tokens and if that fails
|
||||
/// it will attempt to fallback to retrieving it from the HttpContext.
|
||||
/// </summary>
|
||||
/// <param name="controllerContext"></param>
|
||||
/// <returns></returns>
|
||||
public static UmbracoContext GetUmbracoContext(this ControllerContext controllerContext)
|
||||
{
|
||||
var umbCtx = controllerContext.RouteData.GetUmbracoContext();
|
||||
if (umbCtx != null) return umbCtx;
|
||||
|
||||
if (controllerContext.ParentActionViewContext != null)
|
||||
{
|
||||
//recurse
|
||||
return controllerContext.ParentActionViewContext.GetUmbracoContext();
|
||||
}
|
||||
|
||||
//fallback to getting from HttpContext
|
||||
return controllerContext.HttpContext.GetUmbracoContext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a data token in the whole ControllerContext hierarchy of execution
|
||||
/// </summary>
|
||||
/// <param name="controllerContext"></param>
|
||||
/// <param name="dataTokenName"></param>
|
||||
/// <returns></returns>
|
||||
internal static object GetDataTokenInViewContextHierarchy(this ControllerContext controllerContext, string dataTokenName)
|
||||
{
|
||||
if (controllerContext.RouteData.DataTokens.ContainsKey(dataTokenName))
|
||||
{
|
||||
return controllerContext.RouteData.DataTokens[dataTokenName];
|
||||
}
|
||||
|
||||
if (controllerContext.ParentActionViewContext != null)
|
||||
{
|
||||
//recurse!
|
||||
return controllerContext.ParentActionViewContext.GetDataTokenInViewContextHierarchy(dataTokenName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,24 +5,8 @@ using System.Web.Mvc;
|
||||
|
||||
namespace Umbraco.Web.Mvc
|
||||
{
|
||||
internal static class ControllerExtensions
|
||||
internal static class ControllerExtensions
|
||||
{
|
||||
internal static object GetDataTokenInViewContextHierarchy(this ControllerContext controllerContext, string dataTokenName)
|
||||
{
|
||||
if (controllerContext.RouteData.DataTokens.ContainsKey(dataTokenName))
|
||||
{
|
||||
return controllerContext.RouteData.DataTokens[dataTokenName];
|
||||
}
|
||||
|
||||
if (controllerContext.ParentActionViewContext != null)
|
||||
{
|
||||
//recurse!
|
||||
return controllerContext.ParentActionViewContext.GetDataTokenInViewContextHierarchy(dataTokenName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the controller name from the controller type
|
||||
/// </summary>
|
||||
|
||||
@@ -59,11 +59,11 @@ namespace Umbraco.Web.Mvc
|
||||
{
|
||||
if (_publishedContentRequest != null)
|
||||
return _publishedContentRequest;
|
||||
if (RouteData.DataTokens.ContainsKey("umbraco-doc-request") == false)
|
||||
if (RouteData.DataTokens.ContainsKey(Core.Constants.Web.PublishedDocumentRequestDataToken) == false)
|
||||
{
|
||||
throw new InvalidOperationException("DataTokens must contain an 'umbraco-doc-request' key with a PublishedContentRequest object");
|
||||
}
|
||||
_publishedContentRequest = (PublishedContentRequest)RouteData.DataTokens["umbraco-doc-request"];
|
||||
_publishedContentRequest = (PublishedContentRequest)RouteData.DataTokens[Core.Constants.Web.PublishedDocumentRequestDataToken];
|
||||
return _publishedContentRequest;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,9 +97,9 @@ namespace Umbraco.Web.Mvc
|
||||
internal void SetupRouteDataForRequest(RenderModel renderModel, RequestContext requestContext, PublishedContentRequest docRequest)
|
||||
{
|
||||
//put essential data into the data tokens, the 'umbraco' key is required to be there for the view engine
|
||||
requestContext.RouteData.DataTokens.Add("umbraco", renderModel); //required for the RenderModelBinder and view engine
|
||||
requestContext.RouteData.DataTokens.Add("umbraco-doc-request", docRequest); //required for RenderMvcController
|
||||
requestContext.RouteData.DataTokens.Add("umbraco-context", UmbracoContext); //required for UmbracoTemplatePage
|
||||
requestContext.RouteData.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, renderModel); //required for the RenderModelBinder and view engine
|
||||
requestContext.RouteData.DataTokens.Add(Core.Constants.Web.PublishedDocumentRequestDataToken, docRequest); //required for RenderMvcController
|
||||
requestContext.RouteData.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, UmbracoContext); //required for UmbracoTemplatePage
|
||||
}
|
||||
|
||||
private void UpdateRouteDataForRequest(RenderModel renderModel, RequestContext requestContext)
|
||||
@@ -107,7 +107,7 @@ namespace Umbraco.Web.Mvc
|
||||
if (renderModel == null) throw new ArgumentNullException("renderModel");
|
||||
if (requestContext == null) throw new ArgumentNullException("requestContext");
|
||||
|
||||
requestContext.RouteData.DataTokens["umbraco"] = renderModel;
|
||||
requestContext.RouteData.DataTokens[Core.Constants.Web.UmbracoDataToken] = renderModel;
|
||||
// the rest should not change -- it's only the published content that has changed
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ namespace Umbraco.Web.Mvc
|
||||
}
|
||||
|
||||
//store the route definition
|
||||
requestContext.RouteData.DataTokens["umbraco-route-def"] = def;
|
||||
requestContext.RouteData.DataTokens[Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken] = def;
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// <returns></returns>
|
||||
private bool ShouldFindView(ControllerContext controllerContext, bool isPartial)
|
||||
{
|
||||
var umbracoToken = controllerContext.GetDataTokenInViewContextHierarchy("umbraco");
|
||||
var umbracoToken = controllerContext.GetDataTokenInViewContextHierarchy(Core.Constants.Web.UmbracoDataToken);
|
||||
|
||||
//first check if we're rendering a partial view for the back office, or surface controller, etc...
|
||||
//anything that is not IUmbracoRenderModel as this should only pertain to Umbraco views.
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Umbraco.Web.Mvc
|
||||
public static object GetRequiredObject(this RouteValueDictionary items, string key)
|
||||
{
|
||||
if (key == null) throw new ArgumentNullException("key");
|
||||
if (!items.Keys.Contains(key))
|
||||
if (items.Keys.Contains(key) == false)
|
||||
throw new ArgumentNullException("The " + key + " parameter was not found but is required");
|
||||
return items[key];
|
||||
}
|
||||
|
||||
@@ -185,9 +185,9 @@ namespace Umbraco.Web.Mvc
|
||||
while (currentContext != null)
|
||||
{
|
||||
var currentRouteData = currentContext.RouteData;
|
||||
if (currentRouteData.DataTokens.ContainsKey("umbraco-route-def"))
|
||||
if (currentRouteData.DataTokens.ContainsKey(Core.Constants.Web.UmbracoRouteDefinitionDataToken))
|
||||
{
|
||||
return Attempt.Succeed((RouteDefinition)currentRouteData.DataTokens["umbraco-route-def"]);
|
||||
return Attempt.Succeed((RouteDefinition)currentRouteData.DataTokens[Core.Constants.Web.UmbracoRouteDefinitionDataToken]);
|
||||
}
|
||||
if (currentContext.IsChildAction)
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Umbraco.Web.Mvc
|
||||
return false;
|
||||
|
||||
//ensure there is an umbraco token set
|
||||
var umbracoToken = request.RouteData.DataTokens["umbraco"];
|
||||
var umbracoToken = request.RouteData.DataTokens[Core.Constants.Web.UmbracoDataToken];
|
||||
if (umbracoToken == null || string.IsNullOrWhiteSpace(umbracoToken.ToString()))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Web.Mvc
|
||||
|
||||
ValidateRouteData(context.RouteData);
|
||||
|
||||
var routeDef = (RouteDefinition)context.RouteData.DataTokens["umbraco-route-def"];
|
||||
var routeDef = (RouteDefinition)context.RouteData.DataTokens[Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken];
|
||||
|
||||
//Special case, if it is webforms but we're posting to an MVC surface controller, then we
|
||||
// need to return the webforms result instead
|
||||
@@ -91,7 +91,7 @@ namespace Umbraco.Web.Mvc
|
||||
/// </summary>
|
||||
private static void ValidateRouteData(RouteData routeData)
|
||||
{
|
||||
if (routeData.DataTokens.ContainsKey("umbraco-route-def") == false)
|
||||
if (routeData.DataTokens.ContainsKey(Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken) == false)
|
||||
{
|
||||
throw new InvalidOperationException("Can only use " + typeof(UmbracoPageResult).Name +
|
||||
" in the context of an Http POST when using a SurfaceController form");
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
@@ -26,24 +27,13 @@ namespace Umbraco.Web.Mvc
|
||||
get
|
||||
{
|
||||
//we should always try to return the context from the data tokens just in case its a custom context and not
|
||||
//using the UmbracoContext.Current.
|
||||
//we will fallback to the singleton if necessary.
|
||||
if (ViewContext.RouteData.DataTokens.ContainsKey("umbraco-context"))
|
||||
{
|
||||
return (UmbracoContext)ViewContext.RouteData.DataTokens.GetRequiredObject("umbraco-context");
|
||||
}
|
||||
//next check if it is a child action and see if the parent has it set in data tokens
|
||||
if (ViewContext.IsChildAction)
|
||||
{
|
||||
if (ViewContext.ParentActionViewContext.RouteData.DataTokens.ContainsKey("umbraco-context"))
|
||||
{
|
||||
return (UmbracoContext)ViewContext.ParentActionViewContext.RouteData.DataTokens.GetRequiredObject("umbraco-context");
|
||||
}
|
||||
}
|
||||
|
||||
//lastly, we will use the singleton, the only reason this should ever happen is is someone is rendering a page that inherits from this
|
||||
//class and are rendering it outside of the normal Umbraco routing process. Very unlikely.
|
||||
return UmbracoContext.Current;
|
||||
//using the UmbracoContext.Current, we will fallback to the singleton if necessary.
|
||||
var umbCtx = ViewContext.GetUmbracoContext()
|
||||
//lastly, we will use the singleton, the only reason this should ever happen is is someone is rendering a page that inherits from this
|
||||
//class and are rendering it outside of the normal Umbraco routing process. Very unlikely.
|
||||
?? UmbracoContext.Current;
|
||||
|
||||
return umbCtx;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,16 +55,16 @@ namespace Umbraco.Web.Mvc
|
||||
//we should always try to return the object from the data tokens just in case its a custom object and not
|
||||
//using the UmbracoContext.Current.
|
||||
//we will fallback to the singleton if necessary.
|
||||
if (ViewContext.RouteData.DataTokens.ContainsKey("umbraco-doc-request"))
|
||||
if (ViewContext.RouteData.DataTokens.ContainsKey(Core.Constants.Web.PublishedDocumentRequestDataToken))
|
||||
{
|
||||
return (PublishedContentRequest)ViewContext.RouteData.DataTokens.GetRequiredObject("umbraco-doc-request");
|
||||
return (PublishedContentRequest)ViewContext.RouteData.DataTokens.GetRequiredObject(Core.Constants.Web.PublishedDocumentRequestDataToken);
|
||||
}
|
||||
//next check if it is a child action and see if the parent has it set in data tokens
|
||||
if (ViewContext.IsChildAction)
|
||||
{
|
||||
if (ViewContext.ParentActionViewContext.RouteData.DataTokens.ContainsKey("umbraco-doc-request"))
|
||||
if (ViewContext.ParentActionViewContext.RouteData.DataTokens.ContainsKey(Core.Constants.Web.PublishedDocumentRequestDataToken))
|
||||
{
|
||||
return (PublishedContentRequest)ViewContext.ParentActionViewContext.RouteData.DataTokens.GetRequiredObject("umbraco-doc-request");
|
||||
return (PublishedContentRequest)ViewContext.ParentActionViewContext.RouteData.DataTokens.GetRequiredObject(Core.Constants.Web.PublishedDocumentRequestDataToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,10 +168,12 @@ namespace Umbraco.Web.Mvc
|
||||
|
||||
var ok = sourceContent != null;
|
||||
if (sourceContent != null)
|
||||
{
|
||||
// try to grab the culture
|
||||
// using context's culture by default
|
||||
var culture = UmbracoContext.PublishedContentRequest.Culture;
|
||||
{
|
||||
// use context culture as default, if available
|
||||
var culture = CultureInfo.CurrentCulture;
|
||||
if (UmbracoContext.PublishedContentRequest != null && UmbracoContext.PublishedContentRequest.Culture != null)
|
||||
culture = UmbracoContext.PublishedContentRequest.Culture;
|
||||
|
||||
var sourceRenderModel = source as RenderModel;
|
||||
if (sourceRenderModel != null)
|
||||
culture = sourceRenderModel.CurrentCulture;
|
||||
|
||||
@@ -3,6 +3,8 @@ using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using System.Web.Security;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Web.Models;
|
||||
using Umbraco.Web.Routing;
|
||||
@@ -19,7 +21,8 @@ namespace Umbraco.Web.Mvc
|
||||
if (found == null) return new NotFoundHandler();
|
||||
|
||||
umbracoContext.PublishedContentRequest = new PublishedContentRequest(
|
||||
umbracoContext.CleanedUmbracoUrl, umbracoContext.RoutingContext)
|
||||
umbracoContext.CleanedUmbracoUrl, umbracoContext.RoutingContext,
|
||||
UmbracoConfig.For.UmbracoSettings().WebRouting, s => Roles.Provider.GetRolesForUser(s))
|
||||
{
|
||||
PublishedContent = found
|
||||
};
|
||||
@@ -31,11 +34,11 @@ namespace Umbraco.Web.Mvc
|
||||
var renderModel = new RenderModel(umbracoContext.PublishedContentRequest.PublishedContent, umbracoContext.PublishedContentRequest.Culture);
|
||||
|
||||
//assigns the required tokens to the request
|
||||
requestContext.RouteData.DataTokens.Add("umbraco", renderModel);
|
||||
requestContext.RouteData.DataTokens.Add("umbraco-doc-request", umbracoContext.PublishedContentRequest);
|
||||
requestContext.RouteData.DataTokens.Add("umbraco-context", umbracoContext);
|
||||
requestContext.RouteData.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, renderModel);
|
||||
requestContext.RouteData.DataTokens.Add(Core.Constants.Web.PublishedDocumentRequestDataToken, umbracoContext.PublishedContentRequest);
|
||||
requestContext.RouteData.DataTokens.Add(Core.Constants.Web.UmbracoContextDataToken, umbracoContext);
|
||||
//this is used just for a flag that this is an umbraco custom route
|
||||
requestContext.RouteData.DataTokens.Add("umbraco-custom-route", true);
|
||||
requestContext.RouteData.DataTokens.Add(Core.Constants.Web.CustomRouteDataToken, true);
|
||||
|
||||
//Here we need to detect if a SurfaceController has posted
|
||||
var formInfo = RenderRouteHandler.GetFormInfo(requestContext);
|
||||
@@ -49,7 +52,7 @@ namespace Umbraco.Web.Mvc
|
||||
};
|
||||
|
||||
//set the special data token to the current route definition
|
||||
requestContext.RouteData.DataTokens["umbraco-route-def"] = def;
|
||||
requestContext.RouteData.DataTokens[Umbraco.Core.Constants.Web.UmbracoRouteDefinitionDataToken] = def;
|
||||
|
||||
return RenderRouteHandler.HandlePostedValues(requestContext, formInfo);
|
||||
}
|
||||
|
||||
@@ -57,12 +57,12 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
if (content != null && preview == false)
|
||||
{
|
||||
var domainRootNodeId = route.StartsWith("/") ? -1 : int.Parse(route.Substring(0, route.IndexOf('/')));
|
||||
var iscanon =
|
||||
UnitTesting == false
|
||||
var iscanon =
|
||||
UnitTesting == false
|
||||
&& DomainHelper.ExistsDomainInPath(umbracoContext.Application.Services.DomainService.GetAll(false), content.Path, domainRootNodeId) == false;
|
||||
// and only if this is the canonical url (the one GetUrl would return)
|
||||
if (iscanon)
|
||||
_routesCache.Store(contentId, route);
|
||||
_routesCache.Store(content.Id, route);
|
||||
}
|
||||
|
||||
return content;
|
||||
@@ -159,7 +159,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
// we add this check - we look for the document matching "/" and if it's not us, then
|
||||
// we do not hide the top level path
|
||||
// it has to be taken care of in GetByRoute too so if
|
||||
// "/foo" fails (looking for "/*/foo") we try also "/foo".
|
||||
// "/foo" fails (looking for "/*/foo") we try also "/foo".
|
||||
// this does not make much sense anyway esp. if both "/foo/" and "/bar/foo" exist, but
|
||||
// that's the way it works pre-4.10 and we try to be backward compat for the time being
|
||||
if (node.Parent == null)
|
||||
@@ -244,8 +244,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
|
||||
private static IPublishedContent ConvertToDocument(XmlNode xmlNode, bool isPreviewing)
|
||||
{
|
||||
return xmlNode == null
|
||||
? null
|
||||
return xmlNode == null
|
||||
? null
|
||||
: (new XmlPublishedContent(xmlNode, isPreviewing)).CreateModel();
|
||||
}
|
||||
|
||||
@@ -398,7 +398,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
if (startNodeId > 0)
|
||||
{
|
||||
// if in a domain then use the root node of the domain
|
||||
xpath = string.Format(XPathStringsDefinition.Root + XPathStrings.DescendantDocumentById, startNodeId);
|
||||
xpath = string.Format(XPathStringsDefinition.Root + XPathStrings.DescendantDocumentById, startNodeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -409,7 +409,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
// umbraco does not consistently guarantee that sortOrder starts with 0
|
||||
// so the one that we want is the one with the smallest sortOrder
|
||||
// read http://stackoverflow.com/questions/1128745/how-can-i-use-xpath-to-find-the-minimum-value-of-an-attribute-in-a-set-of-elemen
|
||||
|
||||
|
||||
// so that one does not work, because min(@sortOrder) maybe 1
|
||||
// xpath = "/root/*[@isDoc and @sortOrder='0']";
|
||||
|
||||
@@ -453,7 +453,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
else
|
||||
{
|
||||
xpathBuilder.AppendFormat(XPathStrings.ChildDocumentByUrlName, part);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Web.Routing;
|
||||
|
||||
namespace Umbraco.Web
|
||||
{
|
||||
public static class RouteDataExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to get the Umbraco context from the DataTokens
|
||||
/// </summary>
|
||||
/// <param name="routeData"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is useful when working on async threads since the UmbracoContext is not copied over explicitly
|
||||
/// </remarks>
|
||||
public static UmbracoContext GetUmbracoContext(this RouteData routeData)
|
||||
{
|
||||
if (routeData == null) throw new ArgumentNullException("routeData");
|
||||
|
||||
if (routeData.DataTokens.ContainsKey(Core.Constants.Web.UmbracoContextDataToken))
|
||||
{
|
||||
var umbCtx = routeData.DataTokens[Core.Constants.Web.UmbracoContextDataToken] as UmbracoContext;
|
||||
return umbCtx;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ namespace Umbraco.Web.Routing
|
||||
if (umbracoContext.HttpContext.Request.RequestContext == null) return null;
|
||||
if (umbracoContext.HttpContext.Request.RequestContext.RouteData == null) return null;
|
||||
if (umbracoContext.HttpContext.Request.RequestContext.RouteData.DataTokens == null) return null;
|
||||
if (umbracoContext.HttpContext.Request.RequestContext.RouteData.DataTokens.ContainsKey("umbraco-custom-route") == false) return null;
|
||||
if (umbracoContext.HttpContext.Request.RequestContext.RouteData.DataTokens.ContainsKey(Umbraco.Core.Constants.Web.CustomRouteDataToken) == false) return null;
|
||||
//ok so it's a custom route with published content assigned, check if the id being requested for is the same id as the assigned published content
|
||||
return id == umbracoContext.PublishedContentRequest.PublishedContent.Id
|
||||
? umbracoContext.PublishedContentRequest.PublishedContent.Url
|
||||
|
||||
@@ -73,6 +73,16 @@ namespace Umbraco.Web.Security.Identity
|
||||
/// </remarks>
|
||||
internal bool ShouldAuthenticateRequest(IOwinContext ctx, Uri originalRequestUrl, bool checkForceAuthTokens = true)
|
||||
{
|
||||
if (_umbracoContextAccessor.Value.Application.IsConfigured == false
|
||||
&& _umbracoContextAccessor.Value.Application.DatabaseContext.IsDatabaseConfigured == false)
|
||||
{
|
||||
//Do not authenticate the request if we don't have a db and we are not configured - since we will never need
|
||||
// to know a current user in this scenario - we treat it as a new install. Without this we can have some issues
|
||||
// when people have older invalid cookies on the same domain since our user managers might attempt to lookup a user
|
||||
// and we don't even have a db.
|
||||
return false;
|
||||
}
|
||||
|
||||
var request = ctx.Request;
|
||||
var httpCtx = ctx.TryGetHttpContext();
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Umbraco.Web.Security.Identity
|
||||
CookieName = securitySection.AuthCookieName;
|
||||
CookieHttpOnly = true;
|
||||
CookieSecure = forceSsl ? CookieSecureOption.Always : CookieSecureOption.SameAsRequest;
|
||||
CookiePath = "/";
|
||||
CookiePath = "/";
|
||||
|
||||
//Custom cookie manager so we can filter requests
|
||||
CookieManager = new BackOfficeCookieManager(new SingletonUmbracoContextAccessor(), explicitPaths);
|
||||
@@ -84,7 +84,7 @@ namespace Umbraco.Web.Security.Identity
|
||||
|
||||
if (ticket.Properties.IsPersistent)
|
||||
{
|
||||
cookieOptions.Expires = expiresUtc.ToUniversalTime().DateTime;
|
||||
cookieOptions.Expires = expiresUtc.UtcDateTime;
|
||||
}
|
||||
|
||||
return cookieOptions;
|
||||
|
||||
@@ -304,11 +304,13 @@
|
||||
<Compile Include="Media\EmbedProviders\Flickr.cs" />
|
||||
<Compile Include="Models\ContentEditing\SimpleNotificationModel.cs" />
|
||||
<Compile Include="Models\PublishedContentWithKeyBase.cs" />
|
||||
<Compile Include="Mvc\ControllerContextExtensions.cs" />
|
||||
<Compile Include="Mvc\IRenderController.cs" />
|
||||
<Compile Include="Mvc\RenderIndexActionSelectorAttribute.cs" />
|
||||
<Compile Include="Mvc\ValidateMvcAngularAntiForgeryTokenAttribute.cs" />
|
||||
<Compile Include="PropertyEditors\DatePreValueEditor.cs" />
|
||||
<Compile Include="RequestLifespanMessagesFactory.cs" />
|
||||
<Compile Include="RouteDataExtensions.cs" />
|
||||
<Compile Include="Scheduling\LatchedBackgroundTaskBase.cs" />
|
||||
<Compile Include="Security\Identity\ExternalSignInAutoLinkOptions.cs" />
|
||||
<Compile Include="Security\Identity\FixWindowsAuthMiddlware.cs" />
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Umbraco.Web
|
||||
/// </summary>
|
||||
public class UmbracoContext : DisposableObject, IDisposeOnRequestEnd
|
||||
{
|
||||
private const string HttpContextItemName = "Umbraco.Web.UmbracoContext";
|
||||
internal const string HttpContextItemName = "Umbraco.Web.UmbracoContext";
|
||||
private static readonly object Locker = new object();
|
||||
|
||||
private bool _replacing;
|
||||
@@ -133,7 +133,7 @@ namespace Umbraco.Web
|
||||
UmbracoContext.Current._replacing = true;
|
||||
}
|
||||
|
||||
var umbracoContext = CreateContext(httpContext, applicationContext, webSecurity, umbracoSettings, urlProviders, preview ?? false);
|
||||
var umbracoContext = CreateContext(httpContext, applicationContext, webSecurity, umbracoSettings, urlProviders, preview);
|
||||
|
||||
//assign the singleton
|
||||
UmbracoContext.Current = umbracoContext;
|
||||
@@ -158,7 +158,7 @@ namespace Umbraco.Web
|
||||
WebSecurity webSecurity,
|
||||
IUmbracoSettingsSection umbracoSettings,
|
||||
IEnumerable<IUrlProvider> urlProviders,
|
||||
bool preview)
|
||||
bool? preview)
|
||||
{
|
||||
if (httpContext == null) throw new ArgumentNullException("httpContext");
|
||||
if (applicationContext == null) throw new ArgumentNullException("applicationContext");
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Events;
|
||||
|
||||
namespace Umbraco.Web
|
||||
@@ -11,6 +13,38 @@ namespace Umbraco.Web
|
||||
/// </summary>
|
||||
public static class UmbracoContextExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// tries to get the Umbraco context from the HttpContext
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is useful when working on async threads since the UmbracoContext is not copied over explicitly
|
||||
/// </remarks>
|
||||
public static UmbracoContext GetUmbracoContext(this HttpContext http)
|
||||
{
|
||||
return GetUmbracoContext(new HttpContextWrapper(http));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// tries to get the Umbraco context from the HttpContext
|
||||
/// </summary>
|
||||
/// <param name="http"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is useful when working on async threads since the UmbracoContext is not copied over explicitly
|
||||
/// </remarks>
|
||||
public static UmbracoContext GetUmbracoContext(this HttpContextBase http)
|
||||
{
|
||||
if (http == null) throw new ArgumentNullException("http");
|
||||
|
||||
if (http.Items.Contains(UmbracoContext.HttpContextItemName))
|
||||
{
|
||||
var umbCtx = http.Items[UmbracoContext.HttpContextItemName] as UmbracoContext;
|
||||
return umbCtx;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If there are event messages in the current request this will return them , otherwise it will return null
|
||||
|
||||
@@ -336,7 +336,7 @@ namespace Umbraco.Web
|
||||
{
|
||||
route.DataTokens = new RouteValueDictionary();
|
||||
}
|
||||
route.DataTokens.Add("umbraco", "api"); //ensure the umbraco token is set
|
||||
route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "api"); //ensure the umbraco token is set
|
||||
}
|
||||
|
||||
private void RouteLocalSurfaceController(Type controller, string umbracoPath)
|
||||
@@ -347,7 +347,7 @@ namespace Umbraco.Web
|
||||
umbracoPath + "/Surface/" + meta.ControllerName + "/{action}/{id}",//url to match
|
||||
new { controller = meta.ControllerName, action = "Index", id = UrlParameter.Optional },
|
||||
new[] { meta.ControllerNamespace }); //look in this namespace to create the controller
|
||||
route.DataTokens.Add("umbraco", "surface"); //ensure the umbraco token is set
|
||||
route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "surface"); //ensure the umbraco token is set
|
||||
route.DataTokens.Add("UseNamespaceFallback", false); //Don't look anywhere else except this namespace!
|
||||
//make it use our custom/special SurfaceMvcHandler
|
||||
route.RouteHandler = new SurfaceRouteHandler();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using Umbraco.Core.CodeAnnotations;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
@@ -52,7 +53,7 @@ namespace umbraco
|
||||
if (IsPartialViewMacro == false)
|
||||
{
|
||||
var attempt = fileService.CreatePartialView(model, snippetName, User.Id);
|
||||
_returnUrl = string.Format("settings/views/EditView.aspx?treeType=partialViews&file={0}", model.Path.TrimStart('/'));
|
||||
_returnUrl = string.Format("settings/views/EditView.aspx?treeType=partialViews&file={0}", HttpUtility.UrlEncode(model.Path.TrimStart('/').Replace("\\", "/")));
|
||||
return attempt.Success;
|
||||
}
|
||||
else
|
||||
@@ -68,7 +69,7 @@ namespace umbraco
|
||||
macroService.Save(new Macro(attempt.Result.Alias, attempt.Result.Alias) { ScriptPath = virtualPath });
|
||||
}
|
||||
|
||||
_returnUrl = string.Format("settings/views/EditView.aspx?treeType=partialViewMacros&file={0}", model.Path.TrimStart('/'));
|
||||
_returnUrl = string.Format("settings/views/EditView.aspx?treeType=partialViewMacros&file={0}", HttpUtility.UrlEncode(model.Path.TrimStart('/').Replace("\\", "/")));
|
||||
return attempt.Success;
|
||||
}
|
||||
|
||||
|
||||
@@ -183,71 +183,71 @@ namespace umbraco.presentation.umbraco.dialogs
|
||||
SimpleLoginNameValidator.IsValid = true;
|
||||
|
||||
var provider = MembershipProviderExtensions.GetMembersMembershipProvider();
|
||||
|
||||
int pageId = int.Parse(helper.Request("nodeId"));
|
||||
|
||||
if (Page.IsValid)
|
||||
if (e.CommandName == "simple")
|
||||
{
|
||||
int pageId = int.Parse(helper.Request("nodeId"));
|
||||
var memberLogin = simpleLogin.Visible ? simpleLogin.Text : SimpleLoginLabel.Text;
|
||||
|
||||
if (e.CommandName == "simple")
|
||||
var member = provider.GetUser(memberLogin, false);
|
||||
if (member == null)
|
||||
{
|
||||
var memberLogin = simpleLogin.Visible ? simpleLogin.Text : SimpleLoginLabel.Text;
|
||||
var tempEmail = "u" + Guid.NewGuid().ToString("N") + "@example.com";
|
||||
|
||||
var member = provider.GetUser(memberLogin, false);
|
||||
if (member == null)
|
||||
// this needs to work differently depending on umbraco members or external membership provider
|
||||
if (provider.IsUmbracoMembershipProvider() == false)
|
||||
{
|
||||
var tempEmail = "u" + Guid.NewGuid().ToString("N") + "@example.com";
|
||||
|
||||
// this needs to work differently depending on umbraco members or external membership provider
|
||||
if (provider.IsUmbracoMembershipProvider() == false)
|
||||
member = provider.CreateUser(memberLogin, simplePassword.Text, tempEmail);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if it's the umbraco membership provider, then we need to tell it what member type to create it with
|
||||
if (MemberType.GetByAlias(Constants.Conventions.MemberTypes.SystemDefaultProtectType) == null)
|
||||
{
|
||||
member = provider.CreateUser(memberLogin, simplePassword.Text, tempEmail);
|
||||
MemberType.MakeNew(BusinessLogic.User.GetUser(0), Constants.Conventions.MemberTypes.SystemDefaultProtectType);
|
||||
}
|
||||
else
|
||||
var castedProvider = provider.AsUmbracoMembershipProvider();
|
||||
MembershipCreateStatus status;
|
||||
member = castedProvider.CreateUser(Constants.Conventions.MemberTypes.SystemDefaultProtectType,
|
||||
memberLogin, simplePassword.Text, tempEmail, null, null, true, null, out status);
|
||||
if (status != MembershipCreateStatus.Success)
|
||||
{
|
||||
//if it's the umbraco membership provider, then we need to tell it what member type to create it with
|
||||
if (MemberType.GetByAlias(Constants.Conventions.MemberTypes.SystemDefaultProtectType) == null)
|
||||
{
|
||||
MemberType.MakeNew(BusinessLogic.User.GetUser(0), Constants.Conventions.MemberTypes.SystemDefaultProtectType);
|
||||
}
|
||||
var castedProvider = provider.AsUmbracoMembershipProvider();
|
||||
MembershipCreateStatus status;
|
||||
member = castedProvider.CreateUser(Constants.Conventions.MemberTypes.SystemDefaultProtectType,
|
||||
memberLogin, simplePassword.Text, tempEmail, null, null, true, null, out status);
|
||||
if (status != MembershipCreateStatus.Success)
|
||||
{
|
||||
SimpleLoginNameValidator.IsValid = false;
|
||||
SimpleLoginNameValidator.ErrorMessage = "Could not create user: " + status;
|
||||
SimpleLoginNameValidator.Text = "Could not create user: " + status;
|
||||
return;
|
||||
}
|
||||
SimpleLoginNameValidator.IsValid = false;
|
||||
SimpleLoginNameValidator.ErrorMessage = "Could not create user: " + status;
|
||||
SimpleLoginNameValidator.Text = "Could not create user: " + status;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (pp_pass.Visible)
|
||||
{
|
||||
SimpleLoginNameValidator.IsValid = false;
|
||||
SimpleLoginLabel.Visible = true;
|
||||
SimpleLoginLabel.Text = memberLogin;
|
||||
simpleLogin.Visible = false;
|
||||
pp_pass.Visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create or find a memberGroup
|
||||
var simpleRoleName = "__umbracoRole_" + member.UserName;
|
||||
if (Roles.RoleExists(simpleRoleName) == false)
|
||||
{
|
||||
Roles.CreateRole(simpleRoleName);
|
||||
}
|
||||
if (Roles.IsUserInRole(member.UserName, simpleRoleName) == false)
|
||||
{
|
||||
Roles.AddUserToRole(member.UserName, simpleRoleName);
|
||||
}
|
||||
|
||||
Access.ProtectPage(true, pageId, int.Parse(loginPagePicker.Value), int.Parse(errorPagePicker.Value));
|
||||
Access.AddMembershipRoleToDocument(pageId, simpleRoleName);
|
||||
Access.AddMembershipUserToDocument(pageId, member.UserName);
|
||||
}
|
||||
else if (e.CommandName == "advanced")
|
||||
else if (pp_pass.Visible)
|
||||
{
|
||||
SimpleLoginNameValidator.IsValid = false;
|
||||
SimpleLoginLabel.Visible = true;
|
||||
SimpleLoginLabel.Text = memberLogin;
|
||||
simpleLogin.Visible = false;
|
||||
pp_pass.Visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create or find a memberGroup
|
||||
var simpleRoleName = "__umbracoRole_" + member.UserName;
|
||||
if (Roles.RoleExists(simpleRoleName) == false)
|
||||
{
|
||||
Roles.CreateRole(simpleRoleName);
|
||||
}
|
||||
if (Roles.IsUserInRole(member.UserName, simpleRoleName) == false)
|
||||
{
|
||||
Roles.AddUserToRole(member.UserName, simpleRoleName);
|
||||
}
|
||||
|
||||
Access.ProtectPage(true, pageId, int.Parse(loginPagePicker.Value), int.Parse(errorPagePicker.Value));
|
||||
Access.AddMembershipRoleToDocument(pageId, simpleRoleName);
|
||||
Access.AddMembershipUserToDocument(pageId, member.UserName);
|
||||
}
|
||||
else if (e.CommandName == "advanced")
|
||||
{
|
||||
if (cv_errorPage.IsValid && cv_loginPage.IsValid)
|
||||
{
|
||||
Access.ProtectPage(false, pageId, int.Parse(loginPagePicker.Value), int.Parse(errorPagePicker.Value));
|
||||
|
||||
@@ -257,19 +257,23 @@ namespace umbraco.presentation.umbraco.dialogs
|
||||
else
|
||||
Access.RemoveMembershipRoleFromDocument(pageId, li.Value);
|
||||
}
|
||||
|
||||
feedback.Text = ui.Text("publicAccess", "paIsProtected", new cms.businesslogic.CMSNode(pageId).Text) + "</p><p><a href='#' onclick='" + ClientTools.Scripts.CloseModalWindow() + "'>" + ui.Text("closeThisWindow") + "</a>";
|
||||
|
||||
p_buttons.Visible = false;
|
||||
pane_advanced.Visible = false;
|
||||
pane_simple.Visible = false;
|
||||
var content = ApplicationContext.Current.Services.ContentService.GetById(pageId);
|
||||
//reloads the current node in the tree
|
||||
ClientTools.SyncTree(content.Path, true);
|
||||
//reloads the current node's children in the tree
|
||||
ClientTools.ReloadActionNode(false, true);
|
||||
feedback.type = global::umbraco.uicontrols.Feedback.feedbacktype.success;
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
feedback.Text = ui.Text("publicAccess", "paIsProtected", new cms.businesslogic.CMSNode(pageId).Text) + "</p><p><a href='#' onclick='" + ClientTools.Scripts.CloseModalWindow() + "'>" + ui.Text("closeThisWindow") + "</a>";
|
||||
|
||||
p_buttons.Visible = false;
|
||||
pane_advanced.Visible = false;
|
||||
pane_simple.Visible = false;
|
||||
var content = ApplicationContext.Current.Services.ContentService.GetById(pageId);
|
||||
//reloads the current node in the tree
|
||||
ClientTools.SyncTree(content.Path, true);
|
||||
//reloads the current node's children in the tree
|
||||
ClientTools.ReloadActionNode(false, true);
|
||||
feedback.type = global::umbraco.uicontrols.Feedback.feedbacktype.success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user