private IMedia CreateNew(MediaItemSave model) { var mediaType = _mediaTypeService.Get(model.ContentTypeAlias); if (mediaType == null) { throw new InvalidOperationException("No media type found with alias " + model.ContentTypeAlias); } return(new Cms.Core.Models.Media(model.Name, model.ParentId, mediaType)); }
/// <summary> /// Checks if the user has access to post a content item based on whether it's being created or saved. /// </summary> /// <param name="mediaItem"></param> /// <param name="actionContext"></param> private async Task <bool> ValidateUserAccessAsync(MediaItemSave mediaItem, ActionExecutingContext actionContext) { //We now need to validate that the user is allowed to be doing what they are doing. //Then if it is new, we need to lookup those permissions on the parent. IMedia contentToCheck; int contentIdToCheck; switch (mediaItem.Action) { case ContentSaveAction.Save: contentToCheck = mediaItem.PersistedContent; contentIdToCheck = contentToCheck.Id; break; case ContentSaveAction.SaveNew: contentToCheck = _mediaService.GetById(mediaItem.ParentId); if (mediaItem.ParentId != Constants.System.Root) { contentToCheck = _mediaService.GetById(mediaItem.ParentId); contentIdToCheck = contentToCheck.Id; } else { contentIdToCheck = mediaItem.ParentId; } break; default: //we don't support this for media actionContext.Result = new NotFoundResult(); return(false); } var resource = contentToCheck == null ? new MediaPermissionsResource(contentIdToCheck) : new MediaPermissionsResource(contentToCheck); var authorizationResult = await _authorizationService.AuthorizeAsync( actionContext.HttpContext.User, resource, AuthorizationPolicies.MediaPermissionByResource); if (!authorizationResult.Succeeded) { actionContext.Result = new ForbidResult(); return(false); } return(true); }
/// <summary> /// Checks if the user has access to post a content item based on whether it's being created or saved. /// </summary> /// <param name="mediaItem"></param> /// <param name="actionContext"></param> private bool ValidateUserAccess(MediaItemSave mediaItem, HttpActionContext actionContext) { //We now need to validate that the user is allowed to be doing what they are doing. //Then if it is new, we need to lookup those permissions on the parent. IMedia contentToCheck; int contentIdToCheck; switch (mediaItem.Action) { case ContentSaveAction.Save: contentToCheck = mediaItem.PersistedContent; contentIdToCheck = contentToCheck.Id; break; case ContentSaveAction.SaveNew: contentToCheck = _mediaService.GetById(mediaItem.ParentId); if (mediaItem.ParentId != Constants.System.Root) { contentToCheck = _mediaService.GetById(mediaItem.ParentId); contentIdToCheck = contentToCheck.Id; } else { contentIdToCheck = mediaItem.ParentId; } break; default: //we don't support this for media actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.NotFound); return(false); } if (MediaController.CheckPermissions( actionContext.Request.Properties, _umbracoContextAccessor.UmbracoContext.Security.CurrentUser, _mediaService, _entityService, contentIdToCheck, contentToCheck) == false) { actionContext.Response = actionContext.Request.CreateUserNoAccessResponse(); return(false); } return(true); }
public MediaItemDisplay PostSave( [ModelBinder(typeof(MediaItemBinder))] MediaItemSave 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) && (contentItem.Action == ContentSaveAction.SaveNew)) { //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 validation response var forDisplay = Mapper.Map <IMedia, MediaItemDisplay>(contentItem.PersistedContent); forDisplay.Errors = ModelState.ToErrorDictionary(); throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay)); } } //save the item var saveStatus = Services.MediaService.WithResult().Save(contentItem.PersistedContent, (int)Security.CurrentUser.Id); //return the updated model var display = Mapper.Map <IMedia, MediaItemDisplay>(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 (saveStatus.Success) { display.AddSuccessNotification( Services.TextService.Localize("speechBubbles/editMediaSaved"), Services.TextService.Localize("speechBubbles/editMediaSavedText")); } else { AddCancelMessage(display); //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 (saveStatus.Result.StatusType == OperationStatusType.FailedCancelledByEvent && IsCreatingAction(contentItem.Action)) { throw new HttpResponseException(Request.CreateValidationErrorResponse(display)); } } break; } return(display); }
public ActionResult <MediaItemDisplay> PostSave( [ModelBinder(typeof(MediaItemBinder))] MediaItemSave contentItem) { //Recent versions of IE/Edge may send in the full client side file path instead of just the file name. //To ensure similar behavior across all browsers no matter what they do - we strip the FileName property of all //uploaded files to being *only* the actual file name (as it should be). if (contentItem.UploadedFiles != null && contentItem.UploadedFiles.Any()) { foreach (var file in contentItem.UploadedFiles) { file.FileName = Path.GetFileName(file.FileName); } } //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 //Don't update the name if it is empty if (contentItem.Name.IsNullOrWhiteSpace() == false) { contentItem.PersistedContent.Name = contentItem.Name; } MapPropertyValuesForPersistence <IMedia, MediaItemSave>( contentItem, contentItem.PropertyCollectionDto, (save, property) => property.GetValue(), //get prop val (save, property, v) => property.SetValue(v), //set prop val null); // media are all invariant //we will continue to save if model state is invalid, however we cannot save if critical data is missing. //TODO: Allowing media to be saved when it is invalid is odd - media doesn't have a publish phase so suddenly invalid data is allowed to be 'live' if (!ModelState.IsValid) { //check for critical data validation issues, we can't continue saving if this data is invalid if (!RequiredForPersistenceAttribute.HasRequiredValuesForPersistence(contentItem)) { //ok, so the absolute mandatory data is invalid and it's new, we cannot actually continue! // add the model state to the outgoing object and throw validation response MediaItemDisplay forDisplay = _umbracoMapper.Map <MediaItemDisplay>(contentItem.PersistedContent); return(ValidationProblem(forDisplay, ModelState)); } } //save the item var saveStatus = _mediaService.Save(contentItem.PersistedContent, _backofficeSecurityAccessor.BackOfficeSecurity.GetUserId().ResultOr(Constants.Security.SuperUserId)); //return the updated model var display = _umbracoMapper.Map <MediaItemDisplay>(contentItem.PersistedContent); //lastly, if it is not valid, add the model state to the outgoing object and throw a 403 if (!ModelState.IsValid) { return(ValidationProblem(display, ModelState, StatusCodes.Status403Forbidden)); } //put the correct msgs in switch (contentItem.Action) { case ContentSaveAction.Save: case ContentSaveAction.SaveNew: if (saveStatus.Success) { display.AddSuccessNotification( _localizedTextService.Localize("speechBubbles", "editMediaSaved"), _localizedTextService.Localize("speechBubbles", "editMediaSavedText")); } else { AddCancelMessage(display); //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 (saveStatus.Result.Result == OperationResultType.FailedCancelledByEvent && IsCreatingAction(contentItem.Action)) { return(ValidationProblem(display)); } } break; } return(display); }
private IMedia?GetExisting(MediaItemSave model) { return(_mediaService.GetById(Convert.ToInt32(model.Id))); }
public MediaItemDisplay PostSave( [ModelBinder(typeof(MediaItemBinder))] MediaItemSave contentItem) { //Recent versions of IE/Edge may send in the full clientside file path instead of just the file name. //To ensure similar behavior across all browsers no matter what they do - we strip the FileName property of all //uploaded files to being *only* the actual file name (as it should be). if (contentItem.UploadedFiles != null && contentItem.UploadedFiles.Any()) { foreach (var file in contentItem.UploadedFiles) { file.FileName = Path.GetFileName(file.FileName); } } //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 //Don't update the name if it is empty if (contentItem.Name.IsNullOrWhiteSpace() == false) { contentItem.PersistedContent.Name = contentItem.Name; } MapPropertyValuesForPersistence <IMedia, MediaItemSave>( contentItem, contentItem.PropertyCollectionDto, (save, property) => property.GetValue(), //get prop val (save, property, v) => property.SetValue(v), //set prop val null); // media are all invariant //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 (!RequiredForPersistenceAttribute.HasRequiredValuesForPersistence(contentItem) && (contentItem.Action == ContentSaveAction.SaveNew)) { //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 validation response var forDisplay = Mapper.Map <MediaItemDisplay>(contentItem.PersistedContent); forDisplay.Errors = ModelState.ToErrorDictionary(); throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay)); } } //save the item var saveStatus = Services.MediaService.Save(contentItem.PersistedContent, (int)Security.CurrentUser.Id); //return the updated model var display = Mapper.Map <MediaItemDisplay>(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 (saveStatus.Success) { display.AddSuccessNotification( Services.TextService.Localize("speechBubbles/editMediaSaved"), Services.TextService.Localize("speechBubbles/editMediaSavedText")); } else { AddCancelMessage(display); //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 (saveStatus.Result.Result == OperationResultType.FailedCancelledByEvent && IsCreatingAction(contentItem.Action)) { throw new HttpResponseException(Request.CreateValidationErrorResponse(display)); } } break; } return(display); }