public ContentItemDisplay PostSave(
     [ModelBinder(typeof(ContentItemBinder))]
     ContentItemSave contentItem)
 {
     return(PostSaveInternal(contentItem,
                             content => Services.ContentService.WithResult().Save(contentItem.PersistedContent, Security.CurrentUser.Id)));
 }
Esempio n. 2
0
        /// <summary>
        /// Maps the dto property values to the persisted model
        /// </summary>
        /// <param name="contentItem"></param>
        private void MapPropertyValues(ContentItemSave contentItem)
        {
            UpdateName(contentItem);

            //TODO: We need to support 'send to publish'

            contentItem.PersistedContent.ExpireDate  = contentItem.ExpireDate;
            contentItem.PersistedContent.ReleaseDate = contentItem.ReleaseDate;
            //only set the template if it didn't change
            var templateChanged = (contentItem.PersistedContent.Template == null && contentItem.TemplateAlias.IsNullOrWhiteSpace() == false) ||
                                  (contentItem.PersistedContent.Template != null && contentItem.PersistedContent.Template.Alias != contentItem.TemplateAlias) ||
                                  (contentItem.PersistedContent.Template != null && contentItem.TemplateAlias.IsNullOrWhiteSpace());

            if (templateChanged)
            {
                var template = Services.FileService.GetTemplate(contentItem.TemplateAlias);
                if (template == null && contentItem.TemplateAlias.IsNullOrWhiteSpace() == false)
                {
                    //ModelState.AddModelError("Template", "No template exists with the specified alias: " + contentItem.TemplateAlias);
                    LogHelper.Warn <ContentController>("No template exists with the specified alias: " + contentItem.TemplateAlias);
                }
                else
                {
                    //NOTE: this could be null if there was a template and the posted template is null, this should remove the assigned template
                    contentItem.PersistedContent.Template = template;
                }
            }

            base.MapPropertyValues(contentItem);
        }
Esempio n. 3
0
    internal static void BindModel(ContentItemSave model, IContent persistedContent,
                                   ContentModelBinderHelper modelBinderHelper, IUmbracoMapper umbracoMapper)
    {
        model.PersistedContent = persistedContent;

        //create the dto from the persisted model
        if (model.PersistedContent != null)
        {
            foreach (ContentVariantSave variant in model.Variants)
            {
                //map the property dto collection with the culture of the current variant
                variant.PropertyCollectionDto = umbracoMapper.Map <ContentPropertyCollectionDto>(
                    model.PersistedContent,
                    context =>
                {
                    // either of these may be null and that is ok, if it's invariant they will be null which is what is expected
                    context.SetCulture(variant.Culture);
                    context.SetSegment(variant.Segment);
                });

                //now map all of the saved values to the dto
                modelBinderHelper.MapPropertyValuesFromSaved(variant, variant.PropertyCollectionDto);
            }
        }
    }
        /// <summary>
        /// If there are no variants tagged for Saving, then this is an invalid request
        /// </summary>
        /// <param name="contentItem"></param>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        private bool ValidateAtLeastOneVariantIsBeingSaved(ContentItemSave contentItem, HttpActionContext actionContext)
        {
            if (!contentItem.Variants.Any(x => x.Save))
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, "No variants flagged for saving");
                return(false);
            }

            return(true);
        }
Esempio n. 5
0
        //TODO: Validate the property type data
        private bool ValidateData(ContentItemSave postedItem, ContentItemDto realItem, HttpActionContext actionContext)
        {
            foreach (var p in realItem.Properties)
            {
                var editor = PropertyEditorResolver.Current.GetById(p.DataType.ControlId);
                if (editor == null)
                {
                    var message = string.Format("The property editor with id: {0} was not found for property with id {1}", p.DataType.ControlId, p.Id);
                    actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
                    return(false);
                }

                //get the posted value for this property
                var postedValue = postedItem.Properties.Single(x => x.Id == p.Id).Value;

                //get the pre-values for this property
                var preValues = TestContentService.GetPreValue(p.DataType.Id);

                //TODO: when we figure out how to 'override' certain pre-value properties we'll either need to:
                // * Combine the preValues with the overridden values stored with the document type property (but how to combine?)
                // * Or, pass in the overridden values stored with the doc type property separately

                foreach (var v in editor.ValueEditor.Validators)
                {
                    foreach (var result in v.Validate(postedValue, preValues, editor))
                    {
                        //if there are no member names supplied then we assume that the validation message is for the overall property
                        // not a sub field on the property editor
                        if (!result.MemberNames.Any())
                        {
                            //add a model state error for the entire property
                            actionContext.ModelState.AddModelError(p.Alias, result.ErrorMessage);
                        }
                        else
                        {
                            //there's assigned field names so we'll combine the field name with the property name
                            // so that we can try to match it up to a real sub field of this editor
                            foreach (var field in result.MemberNames)
                            {
                                actionContext.ModelState.AddModelError(string.Format("{0}.{1}", p.Alias, field), result.ErrorMessage);
                            }
                        }
                    }
                }
            }

            //create the response if there any errors
            if (!actionContext.ModelState.IsValid)
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, actionContext.ModelState);
            }

            return(actionContext.ModelState.IsValid);
        }
        //TODO: Validate the property type data
        private bool ValidateData(ContentItemSave postedItem, ContentItemDto realItem, HttpActionContext actionContext)
        {
            foreach (var p in realItem.Properties)
            {
                var editor = PropertyEditorResolver.Current.GetById(p.DataType.ControlId);
                if (editor == null)
                {
                    var message = string.Format("The property editor with id: {0} was not found for property with id {1}", p.DataType.ControlId, p.Id);
                    actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
                    return false;
                }

                //get the posted value for this property
                var postedValue = postedItem.Properties.Single(x => x.Id == p.Id).Value;

                //get the pre-values for this property
                var preValues = TestContentService.GetPreValue(p.DataType.Id);

                //TODO: when we figure out how to 'override' certain pre-value properties we'll either need to:
                // * Combine the preValues with the overridden values stored with the document type property (but how to combine?)
                // * Or, pass in the overridden values stored with the doc type property separately

                foreach (var v in editor.ValueEditor.Validators)
                {
                    foreach (var result in v.Validate(postedValue, preValues, editor))
                    {
                        //if there are no member names supplied then we assume that the validation message is for the overall property
                        // not a sub field on the property editor
                        if (!result.MemberNames.Any())
                        {
                            //add a model state error for the entire property
                            actionContext.ModelState.AddModelError(p.Alias, result.ErrorMessage);
                        }
                        else
                        {
                            //there's assigned field names so we'll combine the field name with the property name
                            // so that we can try to match it up to a real sub field of this editor
                            foreach (var field in result.MemberNames)
                            {
                                actionContext.ModelState.AddModelError(string.Format("{0}.{1}", p.Alias, field), result.ErrorMessage);
                            }
                        }
                    }
                }
            }

            //create the response if there any errors
            if (!actionContext.ModelState.IsValid)
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, actionContext.ModelState);
            }

            return actionContext.ModelState.IsValid;
        }
        public HttpResponseMessage PostSaveContent(
            [ModelBinder(typeof(ContentItemBinder))]
            ContentItemSave contentItem)
        {
            //If we've reached here it means:
            // * Our model has been bound
            // * and validated
            // * any file attachments have been saved to their temporary location for us to use

            return(Request.CreateResponse(HttpStatusCode.OK, "success!"));
        }
Esempio n. 8
0
 /// <summary>
 /// Ensure the content exists
 /// </summary>
 /// <param name="postedItem"></param>
 /// <param name="actionContext"></param>
 /// <param name="found"></param>
 /// <returns></returns>
 private bool ValidateExistingContent(ContentItemSave postedItem, HttpActionContext actionContext, out ContentItemDto found)
 {
     //TODO: We need to of course change this to the real umbraco api
     found = TestContentService.GetContentItem(postedItem.Id);
     if (found == null)
     {
         var message = string.Format("content with id: {0} was not found", postedItem.Id);
         actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
         return(false);
     }
     return(true);
 }
            /// <summary>
            ///     If there are no variants tagged for Saving, then this is an invalid request
            /// </summary>
            /// <param name="contentItem"></param>
            /// <param name="actionContext"></param>
            /// <returns></returns>
            private bool ValidateAtLeastOneVariantIsBeingSaved(
                ContentItemSave contentItem,
                ActionExecutingContext actionContext)
            {
                if (!contentItem.Variants.Any(x => x.Save))
                {
                    actionContext.Result = new NotFoundObjectResult(new { Message = "No variants flagged for saving" });
                    return(false);
                }

                return(true);
            }
Esempio n. 10
0
        private IContent CreateNew(ContentItemSave model)
        {
            var contentType = Services.ContentTypeService.Get(model.ContentTypeAlias);

            if (contentType == null)
            {
                throw new InvalidOperationException("No content type found with alias " + model.ContentTypeAlias);
            }
            return(new Content(
                       contentType.VariesByCulture() ? null : model.Variants.First().Name,
                       model.ParentId,
                       contentType));
        }
Esempio n. 11
0
        /// <summary>
        /// Ensure all of the ids in the post are valid
        /// </summary>
        /// <param name="postedItem"></param>
        /// <param name="actionContext"></param>
        /// <param name="realItem"></param>
        /// <returns></returns>
        private bool ValidateProperties(ContentItemSave postedItem, ContentItemDto realItem, HttpActionContext actionContext)
        {
            foreach (var p in postedItem.Properties)
            {
                //ensure the property actually exists in our server side properties
                if (!realItem.Properties.Contains(p))
                {
                    //TODO: Do we return errors here ? If someone deletes a property whilst their editing then should we just
                    //save the property data that remains? Or inform them they need to reload... not sure. This problem exists currently too i think.

                    var message = string.Format("property with id: {0} was not found", p.Id);
                    actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
                    return(false);
                }
            }
            return(true);
        }
        public ContentItemDisplay PostSaveBlueprint(
            [ModelBinder(typeof(ContentItemBinder))] ContentItemSave contentItem)
        {
            var contentItemDisplay = PostSaveInternal(contentItem,
                                                      content =>
            {
                EnsureUniqueName(content.Name, content, "Name");

                Services.ContentService.SaveBlueprint(contentItem.PersistedContent, Security.CurrentUser.Id);
                //we need to reuse the underlying logic so return the result that it wants
                return(Attempt <OperationStatus> .Succeed(new OperationStatus(OperationStatusType.Success, new EventMessages())));
            });

            SetupBlueprint(contentItemDisplay, contentItemDisplay.PersistedContent);

            return(contentItemDisplay);
        }
Esempio n. 13
0
        /// <summary>
        /// Maps the dto property values to the persisted model
        /// </summary>
        /// <param name="contentItem"></param>
        private void MapPropertyValues(ContentItemSave contentItem)
        {
            UpdateName(contentItem);

            //TODO: We need to support 'send to publish'

            contentItem.PersistedContent.ExpireDate = contentItem.ExpireDate;
            contentItem.PersistedContent.ReleaseDate = contentItem.ReleaseDate;
            //only set the template if it didn't change
            var templateChanged = (contentItem.PersistedContent.Template == null && contentItem.TemplateAlias.IsNullOrWhiteSpace() == false)
                                  || (contentItem.PersistedContent.Template != null && contentItem.PersistedContent.Template.Alias != contentItem.TemplateAlias)
                                  || (contentItem.PersistedContent.Template != null && contentItem.TemplateAlias.IsNullOrWhiteSpace());
            if (templateChanged)
            {
                var template = Services.FileService.GetTemplate(contentItem.TemplateAlias);
                if (template == null && contentItem.TemplateAlias.IsNullOrWhiteSpace() == false)
                {
                    //ModelState.AddModelError("Template", "No template exists with the specified alias: " + contentItem.TemplateAlias);
                    LogHelper.Warn<ContentController>("No template exists with the specified alias: " + contentItem.TemplateAlias);
                }
                else
                {
                    //NOTE: this could be null if there was a template and the posted template is null, this should remove the assigned template
                    contentItem.PersistedContent.Template = template;
                }
            }

            base.MapPropertyValues(contentItem);
        }
 protected override IContent GetExisting(ContentItemSave model)
 {
     return(ApplicationContext.Services.ContentService.GetBlueprintById(Convert.ToInt32(model.Id)));
 }
        public void Validating_ContentItemSave()
        {
            var validator = new ContentSaveModelValidator(
                Factory.GetInstance <ILogger>(),
                Mock.Of <IUmbracoContextAccessor>(),
                Factory.GetInstance <ILocalizedTextService>());

            var content = MockedContent.CreateTextpageContent(_contentType, "test", -1);

            var id1 = new Guid("c8df5136-d606-41f0-9134-dea6ae0c2fd9");
            var id2 = new Guid("f916104a-4082-48b2-a515-5c4bf2230f38");
            var id3 = new Guid("77E15DE9-1C79-47B2-BC60-4913BC4D4C6A");

            // TODO: Ok now test with a 4th level complex nested editor

            var complexValue = @"[{
                    ""key"": """     + id1.ToString() + @""",
                    ""name"": ""Hello world"",
                    ""ncContentTypeAlias"": """     + ContentTypeAlias + @""",
                    ""title"": ""Hello world"",
                    ""bodyText"": ""The world is round""
                }, {
                    ""key"": """     + id2.ToString() + @""",
                    ""name"": ""Super nested"",
                    ""ncContentTypeAlias"": """     + ContentTypeAlias + @""",
                    ""title"": ""Hi there!"",
                    ""bodyText"": ""Well hello there"",
                    ""complex"" : [{
                        ""key"": """     + id3.ToString() + @""",
                        ""name"": ""I am a sub nested content"",
                        ""ncContentTypeAlias"": """     + ContentTypeAlias + @""",
                        ""title"": ""Hello up there :)"",
                        ""bodyText"": ""Hello way up there on a different level""
                    }]
                }
            ]";

            content.SetValue("complex", complexValue);

            // map the persisted properties to a model representing properties to save
            //var saveProperties = content.Properties.Select(x => Mapper.Map<ContentPropertyBasic>(x)).ToList();
            var saveProperties = content.Properties.Select(x =>
            {
                return(new ContentPropertyBasic
                {
                    Alias = x.Alias,
                    Id = x.Id,
                    Value = x.GetValue()
                });
            }).ToList();

            var saveVariants = new List <ContentVariantSave>
            {
                new ContentVariantSave
                {
                    Culture    = string.Empty,
                    Segment    = string.Empty,
                    Name       = content.Name,
                    Save       = true,
                    Properties = saveProperties
                }
            };

            var save = new ContentItemSave
            {
                Id               = content.Id,
                Action           = ContentSaveAction.Save,
                ContentTypeAlias = _contentType.Alias,
                ParentId         = -1,
                PersistedContent = content,
                TemplateAlias    = null,
                Variants         = saveVariants
            };

            // This will map the ContentItemSave.Variants.PropertyCollectionDto and then map the values in the saved model
            // back onto the persisted IContent model.
            ContentItemBinder.BindModel(save, content);

            var modelState = new ModelStateDictionary();
            var isValid    = validator.ValidatePropertiesData(save, saveVariants[0], saveVariants[0].PropertyCollectionDto, modelState);

            // list results for debugging
            foreach (var state in modelState)
            {
                Console.WriteLine(state.Key);
                foreach (var error in state.Value.Errors)
                {
                    Console.WriteLine("\t" + error.ErrorMessage);
                }
            }

            // assert

            Assert.IsFalse(isValid);
            Assert.AreEqual(11, modelState.Keys.Count);
            const string complexPropertyKey = "_Properties.complex.invariant.null";

            Assert.IsTrue(modelState.Keys.Contains(complexPropertyKey));
            foreach (var state in modelState.Where(x => x.Key != complexPropertyKey))
            {
                foreach (var error in state.Value.Errors)
                {
                    Assert.IsFalse(error.ErrorMessage.DetectIsJson()); // non complex is just an error message
                }
            }
            var complexEditorErrors = modelState.Single(x => x.Key == complexPropertyKey).Value.Errors;

            Assert.AreEqual(1, complexEditorErrors.Count);
            var nestedError = complexEditorErrors[0];
            var jsonError   = JsonConvert.DeserializeObject <JArray>(nestedError.ErrorMessage);

            var modelStateKeys = new[] { "_Properties.title.invariant.null.innerFieldId", "_Properties.title.invariant.null.value", "_Properties.bodyText.invariant.null.innerFieldId", "_Properties.bodyText.invariant.null.value" };

            AssertNestedValidation(jsonError, 0, id1, modelStateKeys);
            AssertNestedValidation(jsonError, 1, id2, modelStateKeys.Concat(new[] { "_Properties.complex.invariant.null.innerFieldId", "_Properties.complex.invariant.null.value" }).ToArray());
            var nestedJsonError = jsonError.SelectToken("$[1].complex") as JArray;

            Assert.IsNotNull(nestedJsonError);
            AssertNestedValidation(nestedJsonError, 0, id3, modelStateKeys);
        }
Esempio n. 16
0
 protected virtual IContent?GetExisting(ContentItemSave model) => _contentService.GetById(model.Id);
Esempio n. 17
0
 public static IContent GetPersistedContent(ContentItemSave item) => PersistedContentGetter(item);
Esempio n. 18
0
 protected override IContent GetExisting(ContentItemSave model)
 {
     return(Services.ContentService.GetBlueprintById(model.Id));
 }
Esempio n. 19
0
 public static string GetUpdateDateOverrideString([NotNull] this ContentItemSave item)
 {
     Argument.NotNull(nameof(item), item);
     return((string)GetValueOrDefault(item.AdditionalData, UpdateDateOverrideKey));
 }
Esempio n. 20
0
        public ContentItemDisplay PostSave(
            [ModelBinder(typeof(ContentItemBinder))]
            ContentItemSave contentItem)
        {
            //If we've reached here it means:
            // * Our model has been bound
            // * and validated
            // * any file attachments have been saved to their temporary location for us to use
            // * we have a reference to the DTO object and the persisted object
            // * Permissions are valid

            MapPropertyValues(contentItem);

            //We need to manually check the validation results here because:
            // * We still need to save the entity even if there are validation value errors
            // * Depending on if the entity is new, and if there are non property validation errors (i.e. the name is null)
            //      then we cannot continue saving, we can only display errors
            // * If there are validation errors and they were attempting to publish, we can only save, NOT publish and display
            //      a message indicating this
            if (ModelState.IsValid == false)
            {
                if (ValidationHelper.ModelHasRequiredForPersistenceErrors(contentItem) && IsCreatingAction(contentItem.Action))
                {
                    //ok, so the absolute mandatory data is invalid and it's new, we cannot actually continue!
                    // add the modelstate to the outgoing object and throw a validation message
                    var forDisplay = Mapper.Map <IContent, ContentItemDisplay>(contentItem.PersistedContent);
                    forDisplay.Errors = ModelState.ToErrorDictionary();
                    throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay));
                }

                //if the model state is not valid we cannot publish so change it to save
                switch (contentItem.Action)
                {
                case ContentSaveAction.Publish:
                    contentItem.Action = ContentSaveAction.Save;
                    break;

                case ContentSaveAction.PublishNew:
                    contentItem.Action = ContentSaveAction.SaveNew;
                    break;
                }
            }

            //initialize this to successful
            var publishStatus = Attempt <PublishStatus> .Succeed();

            var wasCancelled = false;

            if (contentItem.Action == ContentSaveAction.Save || contentItem.Action == ContentSaveAction.SaveNew)
            {
                //save the item
                var saveResult = Services.ContentService.WithResult().Save(contentItem.PersistedContent, Security.CurrentUser.Id);

                wasCancelled = saveResult.Success == false && saveResult.Result.StatusType == OperationStatusType.FailedCancelledByEvent;
            }
            else if (contentItem.Action == ContentSaveAction.SendPublish || contentItem.Action == ContentSaveAction.SendPublishNew)
            {
                var sendResult = Services.ContentService.SendToPublication(contentItem.PersistedContent, Security.CurrentUser.Id);
                wasCancelled = sendResult == false;
            }
            else
            {
                //publish the item and check if it worked, if not we will show a diff msg below
                publishStatus = Services.ContentService.SaveAndPublishWithStatus(contentItem.PersistedContent, Security.CurrentUser.Id);
                wasCancelled  = publishStatus.Result.StatusType == PublishStatusType.FailedCancelledByEvent;
            }

            //return the updated model
            var display = Mapper.Map <IContent, ContentItemDisplay>(contentItem.PersistedContent);

            //lasty, if it is not valid, add the modelstate to the outgoing object and throw a 403
            HandleInvalidModelState(display);

            //put the correct msgs in
            switch (contentItem.Action)
            {
            case ContentSaveAction.Save:
            case ContentSaveAction.SaveNew:
                if (wasCancelled == false)
                {
                    display.AddSuccessNotification(
                        Services.TextService.Localize("speechBubbles/editContentSavedHeader"),
                        Services.TextService.Localize("speechBubbles/editContentSavedText"));
                }
                else
                {
                    AddCancelMessage(display);
                }
                break;

            case ContentSaveAction.SendPublish:
            case ContentSaveAction.SendPublishNew:
                if (wasCancelled == false)
                {
                    display.AddSuccessNotification(
                        Services.TextService.Localize("speechBubbles/editContentSendToPublish"),
                        Services.TextService.Localize("speechBubbles/editContentSendToPublishText"));
                }
                else
                {
                    AddCancelMessage(display);
                }
                break;

            case ContentSaveAction.Publish:
            case ContentSaveAction.PublishNew:
                ShowMessageForPublishStatus(publishStatus.Result, display);
                break;
            }

            UpdatePreviewContext(contentItem.PersistedContent.Id);

            //If the item is new and the operation was cancelled, we need to return a different
            // status code so the UI can handle it since it won't be able to redirect since there
            // is no Id to redirect to!
            if (wasCancelled && IsCreatingAction(contentItem.Action))
            {
                throw new HttpResponseException(Request.CreateValidationErrorResponse(display));
            }

            return(display);
        }
            /// <summary>
            ///     Checks if the user has access to post a content item based on whether it's being created or saved.
            /// </summary>
            /// <param name="actionContext"></param>
            /// <param name="contentItem"></param>
            /// <param name="backofficeSecurity"></param>
            private async Task <bool> ValidateUserAccessAsync(
                ContentItemSave contentItem,
                ActionExecutingContext actionContext)
            {
                // We now need to validate that the user is allowed to be doing what they are doing.
                // Based on the action we need to check different permissions.
                // Then if it is new, we need to lookup those permissions on the parent!

                var      permissionToCheck = new List <char>();
                IContent contentToCheck    = null;
                int      contentIdToCheck;

                switch (contentItem.Action)
                {
                case ContentSaveAction.Save:
                    permissionToCheck.Add(ActionUpdate.ActionLetter);
                    contentToCheck   = contentItem.PersistedContent;
                    contentIdToCheck = contentToCheck.Id;
                    break;

                case ContentSaveAction.Publish:
                case ContentSaveAction.PublishWithDescendants:
                case ContentSaveAction.PublishWithDescendantsForce:
                    permissionToCheck.Add(ActionPublish.ActionLetter);
                    contentToCheck   = contentItem.PersistedContent;
                    contentIdToCheck = contentToCheck.Id;
                    break;

                case ContentSaveAction.SendPublish:
                    permissionToCheck.Add(ActionToPublish.ActionLetter);
                    contentToCheck   = contentItem.PersistedContent;
                    contentIdToCheck = contentToCheck.Id;
                    break;

                case ContentSaveAction.Schedule:
                    permissionToCheck.Add(ActionUpdate.ActionLetter);
                    permissionToCheck.Add(ActionToPublish.ActionLetter);
                    contentToCheck   = contentItem.PersistedContent;
                    contentIdToCheck = contentToCheck.Id;
                    break;

                case ContentSaveAction.SaveNew:
                    //Save new requires ActionNew

                    permissionToCheck.Add(ActionNew.ActionLetter);

                    if (contentItem.ParentId != Constants.System.Root)
                    {
                        contentToCheck   = _contentService.GetById(contentItem.ParentId);
                        contentIdToCheck = contentToCheck.Id;
                    }
                    else
                    {
                        contentIdToCheck = contentItem.ParentId;
                    }

                    break;

                case ContentSaveAction.SendPublishNew:
                    //Send new requires both ActionToPublish AND ActionNew

                    permissionToCheck.Add(ActionNew.ActionLetter);
                    permissionToCheck.Add(ActionToPublish.ActionLetter);
                    if (contentItem.ParentId != Constants.System.Root)
                    {
                        contentToCheck   = _contentService.GetById(contentItem.ParentId);
                        contentIdToCheck = contentToCheck.Id;
                    }
                    else
                    {
                        contentIdToCheck = contentItem.ParentId;
                    }

                    break;

                case ContentSaveAction.PublishNew:
                case ContentSaveAction.PublishWithDescendantsNew:
                case ContentSaveAction.PublishWithDescendantsForceNew:
                    //Publish new requires both ActionNew AND ActionPublish
                    // TODO: Shouldn't publish also require ActionUpdate since it will definitely perform an update to publish but maybe that's just implied

                    permissionToCheck.Add(ActionNew.ActionLetter);
                    permissionToCheck.Add(ActionPublish.ActionLetter);

                    if (contentItem.ParentId != Constants.System.Root)
                    {
                        contentToCheck   = _contentService.GetById(contentItem.ParentId);
                        contentIdToCheck = contentToCheck.Id;
                    }
                    else
                    {
                        contentIdToCheck = contentItem.ParentId;
                    }

                    break;

                case ContentSaveAction.ScheduleNew:

                    permissionToCheck.Add(ActionNew.ActionLetter);
                    permissionToCheck.Add(ActionUpdate.ActionLetter);
                    permissionToCheck.Add(ActionPublish.ActionLetter);

                    if (contentItem.ParentId != Constants.System.Root)
                    {
                        contentToCheck   = _contentService.GetById(contentItem.ParentId);
                        contentIdToCheck = contentToCheck.Id;
                    }
                    else
                    {
                        contentIdToCheck = contentItem.ParentId;
                    }

                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }


                var resource = contentToCheck == null
                    ? new ContentPermissionsResource(contentToCheck, contentIdToCheck, permissionToCheck)
                    : new ContentPermissionsResource(contentToCheck, permissionToCheck);

                var authorizationResult = await _authorizationService.AuthorizeAsync(
                    actionContext.HttpContext.User,
                    resource,
                    AuthorizationPolicies.ContentPermissionByResource);

                if (!authorizationResult.Succeeded)
                {
                    return(false);
                }

                return(true);
            }
Esempio n. 22
0
 protected virtual IContent GetExisting(ContentItemSave model)
 {
     return(Services.ContentService.GetById(model.Id));
 }
        /// <summary>
        /// Checks if the user has access to post a content item based on whether it's being created or saved.
        /// </summary>
        /// <param name="actionContext"></param>
        /// <param name="contentItem"></param>
        private bool ValidateUserAccess(ContentItemSave contentItem, HttpActionContext actionContext)
        {
            //We now need to validate that the user is allowed to be doing what they are doing.
            //Based on the action we need to check different permissions.
            //Then if it is new, we need to lookup those permissions on the parent!

            var      permissionToCheck = new List <char>();
            IContent contentToCheck    = null;
            int      contentIdToCheck;

            switch (contentItem.Action)
            {
            case ContentSaveAction.Save:
                permissionToCheck.Add(ActionUpdate.ActionLetter);
                contentToCheck   = contentItem.PersistedContent;
                contentIdToCheck = contentToCheck.Id;
                break;

            case ContentSaveAction.Publish:
            case ContentSaveAction.PublishWithDescendants:
            case ContentSaveAction.PublishWithDescendantsForce:
                permissionToCheck.Add(ActionPublish.ActionLetter);
                contentToCheck   = contentItem.PersistedContent;
                contentIdToCheck = contentToCheck.Id;
                break;

            case ContentSaveAction.SendPublish:
                permissionToCheck.Add(ActionToPublish.ActionLetter);
                contentToCheck   = contentItem.PersistedContent;
                contentIdToCheck = contentToCheck.Id;
                break;

            case ContentSaveAction.Schedule:
                permissionToCheck.Add(ActionUpdate.ActionLetter);
                permissionToCheck.Add(ActionToPublish.ActionLetter);
                contentToCheck   = contentItem.PersistedContent;
                contentIdToCheck = contentToCheck.Id;
                break;

            case ContentSaveAction.SaveNew:
                //Save new requires ActionNew

                permissionToCheck.Add(ActionNew.ActionLetter);

                if (contentItem.ParentId != Constants.System.Root)
                {
                    contentToCheck   = _contentService.GetById(contentItem.ParentId);
                    contentIdToCheck = contentToCheck.Id;
                }
                else
                {
                    contentIdToCheck = contentItem.ParentId;
                }
                break;

            case ContentSaveAction.SendPublishNew:
                //Send new requires both ActionToPublish AND ActionNew

                permissionToCheck.Add(ActionNew.ActionLetter);
                permissionToCheck.Add(ActionToPublish.ActionLetter);
                if (contentItem.ParentId != Constants.System.Root)
                {
                    contentToCheck   = _contentService.GetById(contentItem.ParentId);
                    contentIdToCheck = contentToCheck.Id;
                }
                else
                {
                    contentIdToCheck = contentItem.ParentId;
                }
                break;

            case ContentSaveAction.PublishNew:
            case ContentSaveAction.PublishWithDescendantsNew:
            case ContentSaveAction.PublishWithDescendantsForceNew:
                //Publish new requires both ActionNew AND ActionPublish
                //TODO: Shoudn't publish also require ActionUpdate since it will definitely perform an update to publish but maybe that's just implied

                permissionToCheck.Add(ActionNew.ActionLetter);
                permissionToCheck.Add(ActionPublish.ActionLetter);

                if (contentItem.ParentId != Constants.System.Root)
                {
                    contentToCheck   = _contentService.GetById(contentItem.ParentId);
                    contentIdToCheck = contentToCheck.Id;
                }
                else
                {
                    contentIdToCheck = contentItem.ParentId;
                }
                break;

            case ContentSaveAction.ScheduleNew:

                permissionToCheck.Add(ActionNew.ActionLetter);
                permissionToCheck.Add(ActionUpdate.ActionLetter);
                permissionToCheck.Add(ActionPublish.ActionLetter);

                if (contentItem.ParentId != Constants.System.Root)
                {
                    contentToCheck   = _contentService.GetById(contentItem.ParentId);
                    contentIdToCheck = contentToCheck.Id;
                }
                else
                {
                    contentIdToCheck = contentItem.ParentId;
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            ContentPermissionsHelper.ContentAccess accessResult;
            if (contentToCheck != null)
            {
                //store the content item in request cache so it can be resolved in the controller without re-looking it up
                actionContext.Request.Properties[typeof(IContent).ToString()] = contentItem;

                accessResult = ContentPermissionsHelper.CheckPermissions(
                    contentToCheck, _security.CurrentUser,
                    _userService, _entityService, permissionToCheck.ToArray());
            }
            else
            {
                accessResult = ContentPermissionsHelper.CheckPermissions(
                    contentIdToCheck, _security.CurrentUser,
                    _userService, _contentService, _entityService,
                    out contentToCheck,
                    permissionToCheck.ToArray());
                if (contentToCheck != null)
                {
                    //store the content item in request cache so it can be resolved in the controller without re-looking it up
                    actionContext.Request.Properties[typeof(IContent).ToString()] = contentToCheck;
                }
            }

            if (accessResult == ContentPermissionsHelper.ContentAccess.NotFound)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }

            return(accessResult == ContentPermissionsHelper.ContentAccess.Granted);
        }
 /// <summary>
 /// Ensure the content exists
 /// </summary>
 /// <param name="postedItem"></param>
 /// <param name="actionContext"></param>
 /// <param name="found"></param>
 /// <returns></returns>
 private bool ValidateExistingContent(ContentItemSave postedItem, HttpActionContext actionContext, out ContentItemDto found)
 {
     //TODO: We need to of course change this to the real umbraco api
     found = TestContentService.GetContentItem(postedItem.Id);
     if (found == null)
     {
         var message = string.Format("content with id: {0} was not found", postedItem.Id);
         actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
         return false;
     }
     return true;
 }
        /// <summary>
        /// Ensure all of the ids in the post are valid
        /// </summary>
        /// <param name="postedItem"></param>
        /// <param name="actionContext"></param>
        /// <param name="realItem"></param>
        /// <returns></returns>
        private bool ValidateProperties(ContentItemSave postedItem, ContentItemDto realItem, HttpActionContext actionContext)
        {
            foreach (var p in postedItem.Properties)
            {
                //ensure the property actually exists in our server side properties
                if (!realItem.Properties.Contains(p))
                {
                    //TODO: Do we return errors here ? If someone deletes a property whilst their editing then should we just
                    //save the property data that remains? Or inform them they need to reload... not sure. This problem exists currently too i think.

                    var message = string.Format("property with id: {0} was not found", p.Id);
                    actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
                    return false;
                }
            }
            return true;
        }