Port v7@2aa0dfb2c5 - WIP

This commit is contained in:
Stephan
2018-03-27 10:51:41 +02:00
parent 0a4878d2a3
commit d40a835701
25 changed files with 363 additions and 171 deletions

View File

@@ -38,5 +38,13 @@ namespace Umbraco.Core.Scoping
/// <para>The action boolean parameter indicates whether the scope completed or not.</para>
/// </remarks>
T Enlist<T>(string key, Func<T> creator, Action<bool, T> action = null, int priority = 100);
/// <summary>
/// Gets an enlisted object.
/// </summary>
/// <typeparam name="T">The type of the object.</typeparam>
/// <param name="key">The object unique identifier.</param>
/// <returns>The enlisted object, if any, else the default value.</returns>
T GetEnlisted<T>(string key);
}
}

View File

@@ -1,39 +1,9 @@
using System;
using System.Web.Http.Filters;
using System.Web.Http.Filters;
using Umbraco.Core.Events;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Editors
{
public class EditorModelEventArgs : EventArgs
{
public EditorModelEventArgs(object model, UmbracoContext umbracoContext)
{
Model = model;
UmbracoContext = umbracoContext;
}
public object Model { get; private set; }
public UmbracoContext UmbracoContext { get; private set; }
}
public sealed class EditorModelEventArgs<T> : EditorModelEventArgs
{
public EditorModelEventArgs(EditorModelEventArgs baseArgs)
: base(baseArgs.Model, baseArgs.UmbracoContext)
{
Model = (T)baseArgs.Model;
}
public EditorModelEventArgs(T model, UmbracoContext umbracoContext)
: base(model, umbracoContext)
{
Model = model;
}
public new T Model { get; private set; }
}
/// <summary>
/// Used to emit events for editor models in the back office
/// </summary>
@@ -42,23 +12,30 @@ namespace Umbraco.Web.Editors
public static event TypedEventHandler<HttpActionExecutedContext, EditorModelEventArgs<ContentItemDisplay>> SendingContentModel;
public static event TypedEventHandler<HttpActionExecutedContext, EditorModelEventArgs<MediaItemDisplay>> SendingMediaModel;
public static event TypedEventHandler<HttpActionExecutedContext, EditorModelEventArgs<MemberDisplay>> SendingMemberModel;
public static event TypedEventHandler<HttpActionExecutedContext, EditorModelEventArgs<UserDisplay>> SendingUserModel;
private static void OnSendingUserModel(HttpActionExecutedContext sender, EditorModelEventArgs<UserDisplay> e)
{
var handler = SendingUserModel;
handler?.Invoke(sender, e);
}
private static void OnSendingContentModel(HttpActionExecutedContext sender, EditorModelEventArgs<ContentItemDisplay> e)
{
var handler = SendingContentModel;
if (handler != null) handler(sender, e);
handler?.Invoke(sender, e);
}
private static void OnSendingMediaModel(HttpActionExecutedContext sender, EditorModelEventArgs<MediaItemDisplay> e)
{
var handler = SendingMediaModel;
if (handler != null) handler(sender, e);
handler?.Invoke(sender, e);
}
private static void OnSendingMemberModel(HttpActionExecutedContext sender, EditorModelEventArgs<MemberDisplay> e)
{
var handler = SendingMemberModel;
if (handler != null) handler(sender, e);
handler?.Invoke(sender, e);
}
/// <summary>
@@ -68,24 +45,17 @@ namespace Umbraco.Web.Editors
/// <param name="e"></param>
internal static void EmitEvent(HttpActionExecutedContext sender, EditorModelEventArgs e)
{
var contentItemDisplay = e.Model as ContentItemDisplay;
if (contentItemDisplay != null)
{
if (e.Model is ContentItemDisplay)
OnSendingContentModel(sender, new EditorModelEventArgs<ContentItemDisplay>(e));
}
var mediaItemDisplay = e.Model as MediaItemDisplay;
if (mediaItemDisplay != null)
{
if (e.Model is MediaItemDisplay)
OnSendingMediaModel(sender, new EditorModelEventArgs<MediaItemDisplay>(e));
}
var memberItemDisplay = e.Model as MemberDisplay;
if (memberItemDisplay != null)
{
if (e.Model is MemberDisplay)
OnSendingMemberModel(sender, new EditorModelEventArgs<MemberDisplay>(e));
}
}
if (e.Model is UserDisplay)
OnSendingUserModel(sender, new EditorModelEventArgs<UserDisplay>(e));
}
}
}

View File

@@ -486,7 +486,12 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
// not trying to be thread-safe here, that's not the point
if (preview == false)
{
// if there's a current enlisted reader/writer, use its xml
var tempXml = _xmlStore.TempXml;
if (tempXml != null) return tempXml;
return _xml;
}
// Xml cache does not support retrieving preview content when not previewing
if (_previewContent == null)

View File

@@ -108,7 +108,43 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
public override IEnumerable<IPublishedContent> GetAtRoot(bool preview)
{
//TODO: We should be able to look these ids first in Examine!
var searchProvider = GetSearchProviderSafe();
if (searchProvider != null)
{
try
{
// first check in Examine for the cache values
// +(+parentID:-1) +__IndexType:media
var criteria = searchProvider.CreateSearchCriteria("media");
var filter = criteria.ParentId(-1).Not().Field(UmbracoContentIndexer.IndexPathFieldName, "-1,-21,".MultipleCharacterWildcard());
var result = searchProvider.Search(filter.Compile());
if (result != null)
return result.Select(x => CreateFromCacheValues(ConvertFromSearchResult(x)));
}
catch (Exception ex)
{
if (ex is FileNotFoundException)
{
//Currently examine is throwing FileNotFound exceptions when we have a loadbalanced filestore and a node is published in umbraco
//See this thread: http://examine.cdodeplex.com/discussions/264341
//Catch the exception here for the time being, and just fallback to GetMedia
//TODO: Need to fix examine in LB scenarios!
Current.Logger.Error<PublishedMediaCache>("Could not load data from Examine index for media", ex);
}
else if (ex is AlreadyClosedException)
{
//If the app domain is shutting down and the site is under heavy load the index reader will be closed and it really cannot
//be re-opened since the app domain is shutting down. In this case we have no option but to try to load the data from the db.
Current.Logger.Error<PublishedMediaCache>("Could not load data from Examine index for media, the app domain is most likely in a shutdown state", ex);
}
else throw;
}
}
//something went wrong, fetch from the db
var rootMedia = _mediaService.GetRootMedia();
return rootMedia.Select(m => GetUmbracoMedia(m.Id));

View File

@@ -17,6 +17,11 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
private bool _using;
private bool _registerXmlChange;
// the default enlist priority is 100
// enlist with a lower priority to ensure that anything "default" has a clean xml
private const int EnlistPriority = 60;
private const string EnlistKey = "safeXmlReaderWriter";
private SafeXmlReaderWriter(IDisposable releaser, XmlDocument xml, Action<XmlDocument> refresh, Action<XmlDocument, bool> apply, bool isWriter, bool scoped)
{
_releaser = releaser;
@@ -29,6 +34,12 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
_xml = IsWriter ? Clone(xml) : xml;
}
public static SafeXmlReaderWriter Get(IScopeProvider scopeProvider)
{
var scopeContext = scopeProvider.Context;
return scopeContext?.GetEnlisted<SafeXmlReaderWriter>(EnlistKey);
}
public static SafeXmlReaderWriter Get(IScopeProvider scopeProvider, AsyncLock xmlLock, XmlDocument xml, Action<XmlDocument> refresh, Action<XmlDocument, bool> apply, bool writer)
{
var scopeContext = scopeProvider.Context;
@@ -42,7 +53,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
}
// get or create an enlisted reader/writer
var rw = scopeContext.Enlist("safeXmlReaderWriter",
var rw = scopeContext.Enlist(EnlistKey,
() => // creator
{
// obtain exclusive access to xml and create reader/writer
@@ -52,7 +63,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
(completed, item) => // action
{
item.DisposeForReal(completed);
});
}, EnlistPriority);
// ensure it's not already in-use - should never happen, just being super safe
if (rw._using)

View File

@@ -38,7 +38,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
/// then passed to all <see cref="PublishedContentCache"/> instances that are created (one per request).</para>
/// <para>This class should *not* be public.</para>
/// </remarks>
class XmlStore : IDisposable
internal class XmlStore : IDisposable
{
private readonly IDocumentRepository _documentRepository;
private readonly IMediaRepository _mediaRepository;
@@ -329,6 +329,9 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
}
}
// Gets the temp. Xml managed by SafeXmlReaderWrite, if any
public XmlDocument TempXml => SafeXmlReaderWriter.Get(_scopeProvider)?.Xml;
// assumes xml lock
private void SetXmlLocked(XmlDocument xml, bool registerXmlChange)
{

View File

@@ -14,6 +14,7 @@ using Umbraco.Core.Components;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Changes;
using Umbraco.Core.Services.Implement;
@@ -31,8 +32,17 @@ namespace Umbraco.Web.Search
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public sealed class ExamineComponent : UmbracoComponentBase, IUmbracoCoreComponent
{
public void Initialize(IRuntimeState runtime, PropertyEditorCollection propertyEditors, IExamineIndexCollectionAccessor indexCollection, ILogger logger)
private IScopeProvider _scopeProvider;
// the default enlist priority is 100
// enlist with a lower priority to ensure that anything "default" runs after us
// but greater that SafeXmlReaderWriter priority which is 60
private const int EnlistPriority = 80;
public void Initialize(IRuntimeState runtime, PropertyEditorCollection propertyEditors, IExamineIndexCollectionAccessor indexCollection, IScopeProvider scopeProvider, ILogger logger)
{
_scopeProvider = scopeProvider;
logger.Info<ExamineComponent>("Starting initialize async background thread.");
// make it async in order not to slow down the boot
@@ -119,7 +129,7 @@ namespace Umbraco.Web.Search
i.DocumentWriting += grid.DocumentWriting;
}
static void MemberCacheRefresherUpdated(MemberCacheRefresher sender, CacheRefresherEventArgs args)
void MemberCacheRefresherUpdated(MemberCacheRefresher sender, CacheRefresherEventArgs args)
{
if (Suspendable.ExamineEvents.CanIndex == false)
return;
@@ -164,7 +174,7 @@ namespace Umbraco.Web.Search
}
}
static void MediaCacheRefresherUpdated(MediaCacheRefresher sender, CacheRefresherEventArgs args)
void MediaCacheRefresherUpdated(MediaCacheRefresher sender, CacheRefresherEventArgs args)
{
if (Suspendable.ExamineEvents.CanIndex == false)
return;
@@ -213,7 +223,7 @@ namespace Umbraco.Web.Search
}
}
static void ContentCacheRefresherUpdated(ContentCacheRefresher sender, CacheRefresherEventArgs args)
void ContentCacheRefresherUpdated(ContentCacheRefresher sender, CacheRefresherEventArgs args)
{
if (Suspendable.ExamineEvents.CanIndex == false)
return;
@@ -289,7 +299,7 @@ namespace Umbraco.Web.Search
}
}
private static void ReIndexForContent(IContent content, IContent published)
private void ReIndexForContent(IContent content, IContent published)
{
if (published != null && content.VersionId == published.VersionId)
{
@@ -311,42 +321,30 @@ namespace Umbraco.Web.Search
}
}
private static void ReIndexForContent(IContent sender, bool? supportUnpublished = null)
private void ReIndexForContent(IContent sender, bool? supportUnpublished = null)
{
var xml = sender.ToXml();
//add an icon attribute to get indexed
xml.Add(new XAttribute("icon", sender.ContentType.Icon));
ExamineManager.Instance.ReIndexNode(
xml, IndexTypes.Content,
ExamineManager.Instance.IndexProviderCollection.OfType<UmbracoContentIndexer>()
// only for the specified indexers
.Where(x => supportUnpublished.HasValue == false || supportUnpublished.Value == x.SupportUnpublishedContent)
.Where(x => x.EnableDefaultEventHandler));
var actions = DeferedActions.Get(_scopeProvider);
if (actions != null)
actions.Add(new DeferedReIndexForContent(sender, supportUnpublished));
else
DeferedReIndexForContent.Execute(sender, supportUnpublished);
}
private static void ReIndexForMember(IMember member)
private void ReIndexForMember(IMember member)
{
ExamineManager.Instance.ReIndexNode(
member.ToXml(), IndexTypes.Member,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//ensure that only the providers are flagged to listen execute
.Where(x => x.EnableDefaultEventHandler));
}
var actions = DeferedActions.Get(_scopeProvider);
if (actions != null)
actions.Add(new DeferedReIndexForMember(member));
else
DeferedReIndexForMember.Execute(member); }
private static void ReIndexForMedia(IMedia sender, bool isMediaPublished)
private void ReIndexForMedia(IMedia sender, bool isMediaPublished)
{
var xml = sender.ToXml();
//add an icon attribute to get indexed
xml.Add(new XAttribute("icon", sender.ContentType.Icon));
ExamineManager.Instance.ReIndexNode(
xml, IndexTypes.Media,
ExamineManager.Instance.IndexProviderCollection.OfType<UmbracoContentIndexer>()
// index this item for all indexers if the media is not trashed, otherwise if the item is trashed
// then only index this for indexers supporting unpublished media
.Where(x => isMediaPublished || (x.SupportUnpublishedContent))
.Where(x => x.EnableDefaultEventHandler));
var actions = DeferedActions.Get(_scopeProvider);
if (actions != null)
actions.Add(new DeferedReIndexForMedia(sender, isMediaPublished));
else
DeferedReIndexForMedia.Execute(sender, isMediaPublished);
}
/// <summary>
@@ -357,15 +355,13 @@ namespace Umbraco.Web.Search
/// If true, indicates that we will only delete this item from indexes that don't support unpublished content.
/// If false it will delete this from all indexes regardless.
/// </param>
private static void DeleteIndexForEntity(int entityId, bool keepIfUnpublished)
private void DeleteIndexForEntity(int entityId, bool keepIfUnpublished)
{
ExamineManager.Instance.DeleteFromIndex(
entityId.ToString(CultureInfo.InvariantCulture),
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
// if keepIfUnpublished == true then only delete this item from indexes not supporting unpublished content,
// otherwise if keepIfUnpublished == false then remove from all indexes
.Where(x => keepIfUnpublished == false || (x is UmbracoContentIndexer && ((UmbracoContentIndexer)x).SupportUnpublishedContent == false))
.Where(x => x.EnableDefaultEventHandler));
var actions = DeferedActions.Get(_scopeProvider);
if (actions != null)
actions.Add(new DeferedDeleteIndex(entityId, keepIfUnpublished));
else
DeferedDeleteIndex.Execute(entityId, keepIfUnpublished);
}
/// <summary>
@@ -390,5 +386,162 @@ namespace Umbraco.Web.Search
));
}
}
private class DeferedActions
{
private readonly List<DeferedAction> _actions = new List<DeferedAction>();
public static DeferedActions Get(IScopeProvider scopeProvider)
{
var scopeContext = scopeProvider.Context;
if (scopeContext == null) return null;
return scopeContext.Enlist("examineEvents",
() => new DeferedActions(), // creator
(completed, actions) => // action
{
if (completed) actions.Execute();
}, EnlistPriority);
}
public void Add(DeferedAction action)
{
_actions.Add(action);
}
private void Execute()
{
foreach (var action in _actions)
action.Execute();
}
}
private abstract class DeferedAction
{
public virtual void Execute()
{ }
}
private class DeferedReIndexForContent : DeferedAction
{
private readonly IContent _content;
private readonly bool? _supportUnpublished;
public DeferedReIndexForContent(IContent content, bool? supportUnpublished)
{
_content = content;
_supportUnpublished = supportUnpublished;
}
public override void Execute()
{
Execute(_content, _supportUnpublished);
}
public static void Execute(IContent content, bool? supportUnpublished)
{
var xml = content.ToXml();
//add an icon attribute to get indexed
xml.Add(new XAttribute("icon", content.ContentType.Icon));
ExamineManager.Instance.ReIndexNode(
xml, IndexTypes.Content,
ExamineManager.Instance.IndexProviderCollection.OfType<UmbracoContentIndexer>()
//Index this item for all indexers if the content is published, otherwise if the item is not published
// then only index this for indexers supporting unpublished content
.Where(x => supportUnpublished.HasValue == false || supportUnpublished.Value == x.SupportUnpublishedContent)
.Where(x => x.EnableDefaultEventHandler));
}
}
private class DeferedReIndexForMedia : DeferedAction
{
private readonly IMedia _media;
private readonly bool _isPublished;
public DeferedReIndexForMedia(IMedia media, bool isPublished)
{
_media = media;
_isPublished = isPublished;
}
public override void Execute()
{
Execute(_media, _isPublished);
}
public static void Execute(IMedia media, bool isPublished)
{
var xml = media.ToXml();
//add an icon attribute to get indexed
xml.Add(new XAttribute("icon", media.ContentType.Icon));
ExamineManager.Instance.ReIndexNode(
xml, IndexTypes.Media,
ExamineManager.Instance.IndexProviderCollection.OfType<UmbracoContentIndexer>()
//Index this item for all indexers if the media is not trashed, otherwise if the item is trashed
// then only index this for indexers supporting unpublished media
.Where(x => isPublished || (x.SupportUnpublishedContent))
.Where(x => x.EnableDefaultEventHandler));
}
}
private class DeferedReIndexForMember : DeferedAction
{
private readonly IMember _member;
public DeferedReIndexForMember(IMember member)
{
_member = member;
}
public override void Execute()
{
Execute(_member);
}
public static void Execute(IMember member)
{
ExamineManager.Instance.ReIndexNode(
member.ToXml(), IndexTypes.Member,
ExamineManager.Instance.IndexProviderCollection.OfType<BaseUmbracoIndexer>()
//ensure that only the providers are flagged to listen execute
.Where(x => x.EnableDefaultEventHandler));
}
}
private class DeferedDeleteIndex : DeferedAction
{
private readonly int _id;
private readonly bool _keepIfUnpublished;
public DeferedDeleteIndex(int id, bool keepIfUnpublished)
{
_id = id;
_keepIfUnpublished = keepIfUnpublished;
}
public override void Execute()
{
Execute(_id, _keepIfUnpublished);
}
public static void Execute(int id, bool keepIfUnpublished)
{
ExamineManager.Instance.DeleteFromIndex(
id.ToString(CultureInfo.InvariantCulture),
ExamineManager.Instance.IndexProviderCollection.OfType<UmbracoContentIndexer>()
//if keepIfUnpublished == true then only delete this item from indexes not supporting unpublished content,
// otherwise if keepIfUnpublished == false then remove from all indexes
.Where(x => keepIfUnpublished == false || x.SupportUnpublishedContent == false)
.Where(x => x.EnableDefaultEventHandler));
}
}
}
}

View File

@@ -208,6 +208,10 @@ namespace Umbraco.Web.Search
if (sb == null) throw new ArgumentNullException("sb");
if (entityService == null) throw new ArgumentNullException("entityService");
Udi udi;
Udi.TryParse(searchFrom, true, out udi);
searchFrom = udi == null ? searchFrom : entityService.GetIdForUdi(udi).Result.ToString();
int searchFromId;
var entityPath = int.TryParse(searchFrom, out searchFromId) && searchFromId > 0
? entityService.GetAllPaths(objectType, searchFromId).FirstOrDefault()

View File

@@ -6,6 +6,7 @@ using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
namespace Umbraco.Web.Security.Identity
{

View File

@@ -52,6 +52,12 @@ namespace Umbraco.Web.Security.Identity
/// </summary>
public Action<BackOfficeIdentityUser, ExternalLoginInfo> OnAutoLinking { get; set; }
/// <summary>
/// A callback executed during every time a user authenticates using an external login.
/// returns a boolean indicating if sign in should continue or not.
/// </summary>
public Func<BackOfficeIdentityUser, ExternalLoginInfo, bool> OnExternalLogin { get; set; }
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Use the overload specifying user groups instead")]
public string GetDefaultUserType(UmbracoContext umbracoContext, ExternalLoginInfo loginInfo)

View File

@@ -1,7 +1,7 @@
using System;
using Umbraco.Core;
using System.Threading.Tasks;
using Microsoft.Owin;
using Umbraco.Core.Security;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Infrastructure;

View File

@@ -2,12 +2,15 @@
using System.Diagnostics;
using System.Globalization;
using System.Threading.Tasks;
using System.Web;
using System.Web.Security;
using Microsoft.Owin;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security.Cookies;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Security;
namespace Umbraco.Web.Security.Identity
{
@@ -82,6 +85,9 @@ namespace Umbraco.Web.Security.Identity
//if it's time to renew, then do it
if (timeRemaining < timeElapsed)
{
//TODO: This would probably be simpler just to do: context.OwinContext.Authentication.SignIn(context.Properties, identity);
// this will invoke the default Cookie middleware to basically perform this logic for us.
ticket.Properties.IssuedUtc = currentUtc;
var timeSpan = expiresUtc.Value.Subtract(issuedUtc.Value);
ticket.Properties.ExpiresUtc = currentUtc.Add(timeSpan);
@@ -99,6 +105,9 @@ namespace Umbraco.Web.Security.Identity
remainingSeconds = (ticket.Properties.ExpiresUtc.Value - currentUtc).TotalSeconds;
}
}
//We also need to re-validate the user's session if we are relying on this ping to keep their session alive
await SessionIdValidator.ValidateSessionAsync(TimeSpan.FromMinutes(1), context, _authOptions.CookieManager, _authOptions.SystemClock, issuedUtc, ticket.Identity);
}
else if (remainingSeconds <= 30)
{
@@ -114,6 +123,13 @@ namespace Umbraco.Web.Security.Identity
return;
}
}
//Hack! we need to suppress the stupid forms authentcation module but we can only do that by using non owin stuff
if (HttpContext.Current != null && HttpContext.Current.Response != null)
{
HttpContext.Current.Response.SuppressFormsAuthenticationRedirect = true;
}
response.StatusCode = 401;
}
else if (Next != null)

View File

@@ -14,18 +14,13 @@ namespace Umbraco.Web.Security
internal static class WebAuthExtensions
{
/// <summary>
/// This will set a an authenticated IPrincipal to the current request given the IUser object
/// This will set a an authenticated IPrincipal to the current request for webforms & webapi
/// </summary>
/// <param name="request"></param>
/// <param name="user"></param>
/// <param name="principal"></param>
/// <returns></returns>
internal static IPrincipal SetPrincipalForRequest(this HttpRequestMessage request, IUser user)
internal static IPrincipal SetPrincipalForRequest(this HttpRequestMessage request, IPrincipal principal)
{
var principal = new ClaimsPrincipal(
new UmbracoBackOfficeIdentity(
new ClaimsIdentity(),
Mapper.Map<UserData>(user)));
//It is actually not good enough to set this on the current app Context and the thread, it also needs
// to be set explicitly on the HttpContext.Current !! This is a strange web api thing that is actually
// an underlying fault of asp.net not propogating the User correctly.
@@ -50,15 +45,10 @@ namespace Umbraco.Web.Security
/// This will set a an authenticated IPrincipal to the current request given the IUser object
/// </summary>
/// <param name="httpContext"></param>
/// <param name="userData"></param>
/// <param name="principal"></param>
/// <returns></returns>
internal static IPrincipal SetPrincipalForRequest(this HttpContextBase httpContext, UserData userData)
{
var principal = new ClaimsPrincipal(
new UmbracoBackOfficeIdentity(
new ClaimsIdentity(),
userData));
internal static IPrincipal SetPrincipalForRequest(this HttpContextBase httpContext, IPrincipal principal)
{
//It is actually not good enough to set this on the current app Context and the thread, it also needs
// to be set explicitly on the HttpContext.Current !! This is a strange web api thing that is actually
// an underlying fault of asp.net not propogating the User correctly.

View File

@@ -23,7 +23,7 @@ namespace Umbraco.Web.Security
/// <summary>
/// A utility class used for dealing with USER security in Umbraco
/// </summary>
public class WebSecurity : DisposableObject
public class WebSecurity : DisposableObjectSlim
{
private HttpContextBase _httpContext;
private readonly IUserService _userService;
@@ -112,34 +112,14 @@ namespace Umbraco.Web.Security
owinCtx.Authentication.SignOut(Constants.Security.BackOfficeExternalAuthenticationType);
var user = UserManager.FindByIdAsync(userId).Result;
var userData = Mapper.Map<UserData>(user);
_httpContext.SetPrincipalForRequest(userData);
SignInManager.SignInAsync(user, isPersistent: true, rememberBrowser: false).Wait();
_httpContext.SetPrincipalForRequest(owinCtx.Request.User);
return TimeSpan.FromMinutes(GlobalSettings.TimeOutInMinutes).TotalSeconds;
}
[Obsolete("This method should not be used, login is performed by the OWIN pipeline, use the overload that returns double and accepts a UserId instead")]
public virtual FormsAuthenticationTicket PerformLogin(IUser user)
{
//clear the external cookie - we do this first without owin context because we're writing cookies directly to httpcontext
// and cookie handling is different with httpcontext vs webapi and owin, normally we'd just do:
//_httpContext.GetOwinContext().Authentication.SignOut(Constants.Security.BackOfficeExternalAuthenticationType);
var externalLoginCookie = _httpContext.Request.Cookies.Get(Constants.Security.BackOfficeExternalCookieName);
if (externalLoginCookie != null)
{
externalLoginCookie.Expires = DateTime.Now.AddYears(-1);
_httpContext.Response.Cookies.Set(externalLoginCookie);
}
//ensure it's done for owin too
_httpContext.GetOwinContext().Authentication.SignOut(Constants.Security.BackOfficeExternalAuthenticationType);
var ticket = _httpContext.CreateUmbracoAuthTicket(Mapper.Map<UserData>(user));
return ticket;
}
/// <summary>
/// Clears the current login for the currently logged in user
/// </summary>

View File

@@ -131,14 +131,17 @@
<Compile Include="Editors\BackOfficeServerVariables.cs" />
<Compile Include="Editors\CodeFileController.cs" />
<Compile Include="Editors\DashboardHelper.cs" />
<Compile Include="Editors\EditorModelEventArgs.cs" />
<Compile Include="Editors\EditorValidatorCollection.cs" />
<Compile Include="Editors\EditorValidatorCollectionBuilder.cs" />
<Compile Include="Editors\EditorValidatorOfT.cs" />
<Compile Include="Editors\FromJsonPathAttribute.cs" />
<Compile Include="Editors\HelpController.cs" />
<Compile Include="Editors\IsCurrentUserModelFilterAttribute.cs" />
<Compile Include="Editors\ParameterSwapControllerActionSelector.cs" />
<Compile Include="Editors\PasswordChanger.cs" />
<Compile Include="Editors\TemplateController.cs" />
<Compile Include="Editors\TourController.cs" />
<Compile Include="Editors\UserEditorAuthorizationHelper.cs" />
<Compile Include="Editors\UserGroupAuthorizationAttribute.cs" />
<Compile Include="Editors\UserGroupEditorAuthorizationHelper.cs" />
@@ -199,6 +202,10 @@
<Compile Include="HealthCheck\StatusResultType.cs" />
<Compile Include="HealthCheck\Checks\DataIntegrity\XmlDataIntegrityHealthCheck.cs" />
<Compile Include="Media\ImageUrlProviderCollection.cs" />
<Compile Include="Models\BackOfficeTour.cs" />
<Compile Include="Models\BackOfficeTourFile.cs" />
<Compile Include="Models\BackOfficeTourFilter.cs" />
<Compile Include="Models\BackOfficeTourStep.cs" />
<Compile Include="Models\ContentEditing\AssignedContentPermissions.cs" />
<Compile Include="Models\ContentEditing\AssignedUserGroupPermissions.cs" />
<Compile Include="Models\ContentEditing\CodeFileDisplay.cs" />
@@ -251,6 +258,7 @@
<Compile Include="Models\RelatedLinkType.cs" />
<Compile Include="Models\SendCodeViewModel.cs" />
<Compile Include="Models\Trees\ExportMember.cs" />
<Compile Include="Models\UserTourStatus.cs" />
<Compile Include="Mvc\FilteredControllerFactoryCollection.cs" />
<Compile Include="Mvc\FilteredControllerFactoryCollectionBuilder.cs" />
<Compile Include="Mvc\SurfaceControllerTypeCollection.cs" />
@@ -386,6 +394,7 @@
<Compile Include="Tour\TourFilterCollection.cs" />
<Compile Include="Tour\TourFilterCollectionBuilder.cs" />
<Compile Include="Trees\ContentBlueprintTreeController.cs" />
<Compile Include="Trees\MacroTreeController.cs" />
<Compile Include="Trees\RelationTypeTreeController.cs" />
<Compile Include="Trees\MacrosTreeController.cs" />
<Compile Include="Models\ContentEditing\MemberGroupDisplay.cs" />

View File

@@ -46,7 +46,7 @@ namespace umbraco.cms.presentation.developer
{
ClientTools
.SetActiveTreeType(Constants.Trees.Macros)
.SyncTree("-1,init," + _macro.Id, false);
.SyncTree("-1," + _macro.Id, false);
string tempMacroAssembly = _macro.ControlAssembly ?? "";
string tempMacroType = _macro.ControlType ?? "";
@@ -291,7 +291,7 @@ namespace umbraco.cms.presentation.developer
ClientTools
.SetActiveTreeType(Constants.Trees.Macros)
.SyncTree("-1,init," + _macro.Id.ToInvariantString(), true); //true forces the reload
.SyncTree("-1," + _macro.Id.ToInvariantString(), true); //true forces the reload
var tempMacroAssembly = macroAssembly.Text;
var tempMacroType = macroType.Text;

View File

@@ -167,6 +167,13 @@ namespace umbraco.presentation.developer.packages
///*Data types */
//cms.businesslogic.datatype.DataTypeDefinition[] umbDataType = cms.businesslogic.datatype.DataTypeDefinition.GetAll();
// sort array by name
Array.Sort(umbDataType, delegate(cms.businesslogic.datatype.DataTypeDefinition umbDataType1, cms.businesslogic.datatype.DataTypeDefinition umbDataType2)
{
return umbDataType1.Text.CompareTo(umbDataType2.Text);
});
//foreach (cms.businesslogic.datatype.DataTypeDefinition umbDtd in umbDataType)
//{

View File

@@ -28,7 +28,7 @@ namespace umbraco.cms.presentation.developer
if (!IsPostBack)
{
string file = Request.QueryString["file"];
string path = BaseTree.GetTreePathFromFilePath(file);
string path = BaseTree.GetTreePathFromFilePath(file, false, tree);
ClientTools
.SetActiveTreeType(Constants.Trees.Xslt)
.SyncTree(path, false);

View File

@@ -73,6 +73,7 @@ namespace umbraco.presentation.umbraco.dialogs
private void import_Click(object sender, EventArgs e)
{
var xd = new XmlDocument();
xd.XmlResolver = null;
xd.Load(tempFile.Value);
var userId = Security.GetUserId();
@@ -107,6 +108,7 @@ namespace umbraco.presentation.umbraco.dialogs
documentTypeFile.PostedFile.SaveAs(fileName);
var xd = new XmlDocument();
xd.XmlResolver = null;
xd.Load(fileName);
dtName.Text = xd.DocumentElement.SelectSingleNode("//DocumentType/Info/Name").FirstChild.Value;
dtAlias.Text = xd.DocumentElement.SelectSingleNode("//DocumentType/Info/Alias").FirstChild.Value;

View File

@@ -30,7 +30,7 @@ namespace umbraco.dialogs
protected void Page_Load(object sender, EventArgs e)
{
Button1.Text = Services.TextService.Localize("update");
pane_form.Text = Services.TextService.Localize("notifications/editNotifications", new[] { node.Name});
pane_form.Text = Services.TextService.Localize("notifications/editNotifications", new[] { Server.HtmlEncode(node.Name) });
}
#region Web Form Designer generated code

View File

@@ -5,6 +5,7 @@
//using System.ComponentModel;
//using System.Data;
//using System.Drawing;
//using System.Linq;
//using System.Web;
//using System.Web.SessionState;
//using System.Web.UI;
@@ -119,36 +120,22 @@
// if (!IsPostBack) {
// allVersions.Items.Add(new ListItem(Services.TextService.Localize("rollback/selectVersion")+ "...", ""));
// foreach (DocumentVersionList dl in currentDoc.GetVersions()) {
// foreach (DocumentVersionList dl in currentDoc.GetVersions())
// {
// //we don't need to show the current version
// if (dl.Version == currentDoc.Version)
// continue;
//
// allVersions.Items.Add(new ListItem(dl.Text + " (" + Services.TextService.Localize("content/createDate") + ": " + dl.Date.ToShortDateString() + " " + dl.Date.ToShortTimeString() + ")", dl.Version.ToString()));
// }
// Button1.Text = Services.TextService.Localize("actions/rollback");
// }
// }
// #region Web Form Designer generated code
// override protected void OnInit(EventArgs e)
// {
// //
// // CODEGEN: This call is required by the ASP.NET Web Form Designer.
// //
// InitializeComponent();
// base.OnInit(e);
// }
// /// <summary>
// /// Required method for Designer support - do not modify
// /// the contents of this method with the code editor.
// /// </summary>
// private void InitializeComponent()
// {
// }
// #endregion
// protected void doRollback_Click(object sender, System.EventArgs e)
// {
// if (allVersions.SelectedValue.Trim() != "") {
// if (allVersions.SelectedValue.Trim() != "")
// {
// Document d = new Document(int.Parse(helper.Request("nodeId")));
// d.RollBack(new Guid(allVersions.SelectedValue), Security.CurrentUser);
@@ -161,6 +148,8 @@
// feedBackMsg.Text = ui.Text("rollback", "documentRolledBack", vars, new global::umbraco.BusinessLogic.User(0)) + "</p><p><a href='#' onclick='" + ClientTools.Scripts.CloseModalWindow() + "'>" + Services.TextService.Localize("closeThisWindow") + "</a>";
// diffPanel.Visible = false;
// pl_buttons.Visible = false;
//
// ClientTools.ReloadLocationIfMatched(string.Format("/content/content/edit/{0}", d.Id));
// }
// }
// }

View File

@@ -7,6 +7,7 @@
<style type="text/css">
.gridHeader{border-bottom:2px solid #D9D7D7;}
.gridItem{border-color: #D9D7D7;}
html, body {overflow: initial;}
</style>
</asp:Content>

View File

@@ -3,7 +3,6 @@ using System.Data;
using System.IO;
using System.Text;
using System.Xml;
using Umbraco.Core;
using Umbraco.Core.Services;
using Umbraco.Core.IO;
using System.Collections.Generic;

View File

@@ -5,7 +5,6 @@ using Umbraco.Core;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Web._Legacy.BusinessLogic;
namespace umbraco.presentation.umbraco.translation {
public partial class details : Umbraco.Web.UI.Pages.UmbracoEnsuredPage {

View File

@@ -168,13 +168,16 @@ namespace umbraco.presentation.webservices
{
var contentService = Services.ContentService;
try
{
var intIds = ids.Select(int.Parse).ToArray();
var allContent = contentService.GetByIds(intIds).ToDictionary(x => x.Id, x => x);
var sortedContent = intIds.Select(x => allContent[x]);
{
// Save content with new sort order and update db+cache accordingly
var sorted = contentService.Sort(sortedContent);
var intIds = new List<int>();
foreach (var stringId in ids)
{
int intId;
if (int.TryParse(stringId, out intId))
intIds.Add(intId);
}
var sorted = contentService.Sort(intIds.ToArray());
// refresh sort order on cached xml
// but no... this is not distributed - solely relying on content service & events should be enough