using System; using System.Collections.Generic; using System.Linq; using System.Security.Authentication; using System.Text; using Umbraco.Core; using umbraco.BusinessLogic; using umbraco.businesslogic.Exceptions; using umbraco.interfaces; namespace Umbraco.Web.UI { /// /// An abstract class that is used to implement all secure ITasks /// /// /// In the near future we will overhaul how create dialogs work and how deletions work as well. In the meantime /// if you ever need to create an ITask you should just inherit from this class and do not manually implement /// ITask or ITaskReturnUrl. If you do, you MUST also implement IAppTask which associates an ITask to an app /// so we can validate the current user's security with the implementation. If you do not do this then your /// implementation will not be secure. It means that if someone is logged in and doesn't have access to a /// specific app, they'd still be able to execute code to create/delete for any ITask regardless of what app /// they have access to. /// [Obsolete("ITask is used for legacy webforms back office editors, change to using the v7 angular approach")] public abstract class LegacyDialogTask : ITaskReturnUrl, IAssignedApp { public virtual int ParentID { get; set; } public int TypeID { get; set; } public string Alias { get; set; } /// /// Base class first performs authentication for the current app before proceeding /// /// public bool Save() { if (ValidateUserForApplication()) { return PerformSave(); } throw new AuthenticationException("The current user does not have access to the required application that this task belongs to"); } public abstract bool PerformSave(); /// /// Base class first performs authentication for the current app before proceeding /// /// public bool Delete() { if (ValidateUserForApplication()) { return PerformDelete(); } throw new AuthenticationException("The current user does not have access to the required application that this task belongs to"); } public abstract bool PerformDelete(); /// /// Gets/sets the user object for this Task /// /// /// accessible by inheritors but can only be set internally /// protected internal User User { get; internal set; } /// /// Implemented explicitly as we don't want to expose this /// int ITask.UserId { set { User = User.GetUser(value); } } /// /// Checks if the currently assigned user has access to the assigned app /// /// protected internal bool ValidateUserForApplication() { if (User == null) throw new InvalidOperationException("Cannot authenticate, no User object assigned"); return User.Applications.Any(app => app.alias.InvariantEquals(AssignedApp)); } public abstract string ReturnUrl { get; } public abstract string AssignedApp { get; } public IDictionary AdditionalValues { get; set; } } }