Ejemplo n.º 1
0
        internal async Task ProcessRequestAsync(HttpContext httpContext, ODataRequest odataRequest)
        {
            httpContext.SetODataRequest(odataRequest);

            var         request     = httpContext.Request;
            var         httpMethod  = request.Method;
            var         inputStream = request.Body;
            ODataWriter odataWriter = null;

            try
            {
                Content content;
                if (odataRequest == null)
                {
                    odataWriter = new ODataJsonWriter();
                    throw new ODataException("The Request is not an OData request.", ODataExceptionCode.RequestError);
                }

                odataWriter = ODataWriter.Create(httpContext, odataRequest);
                if (odataWriter == null)
                {
                    odataWriter = new ODataJsonWriter();
                    odataWriter.Initialize(odataRequest);
                    throw new ODataException(ODataExceptionCode.InvalidFormatParameter);
                }

                odataWriter.Initialize(odataRequest);

                var requestError = odataRequest.RequestError;
                if (requestError != null)
                {
                    var innerOdataError = requestError as ODataException;
                    var message         = "An error occured during request parsing. " + requestError.Message +
                                          " See inner exception for details.";
                    var code = innerOdataError?.ODataExceptionCode ?? ODataExceptionCode.RequestError;
                    throw new ODataException(message, code, requestError);
                }

                odataRequest.Format = odataWriter.FormatName;

                var requestedContent = LoadContentByVersionRequest(odataRequest.RepositoryPath, httpContext);

                var exists = requestedContent != null;
                if (!exists && !odataRequest.IsServiceDocumentRequest && !odataRequest.IsMetadataRequest &&
                    !AllowedMethodNamesWithoutContent.Contains(httpMethod))
                {
                    ContentNotFound(httpContext);
                    return;
                }

                JObject model;
                switch (httpMethod)
                {
                case "GET":
                    if (odataRequest.IsServiceDocumentRequest)
                    {
                        await odataWriter.WriteServiceDocumentAsync(httpContext, odataRequest)
                        .ConfigureAwait(false);
                    }
                    else if (odataRequest.IsMetadataRequest)
                    {
                        await odataWriter.WriteMetadataAsync(httpContext, odataRequest)
                        .ConfigureAwait(false);
                    }
                    else
                    {
                        if (!Node.Exists(odataRequest.RepositoryPath))
                        {
                            ContentNotFound(httpContext);
                        }
                        else if (odataRequest.IsCollection)
                        {
                            await odataWriter.WriteChildrenCollectionAsync(odataRequest.RepositoryPath, httpContext,
                                                                           odataRequest)
                            .ConfigureAwait(false);
                        }
                        else if (odataRequest.IsMemberRequest)
                        {
                            await odataWriter.WriteContentPropertyAsync(
                                odataRequest.RepositoryPath, odataRequest.PropertyName,
                                odataRequest.IsRawValueRequest, httpContext, odataRequest, _appConfig)
                            .ConfigureAwait(false);
                        }
                        else
                        {
                            await odataWriter.WriteSingleContentAsync(requestedContent, httpContext)
                            .ConfigureAwait(false);
                        }
                    }

                    break;

                case "PUT":     // update
                    if (odataRequest.IsMemberRequest)
                    {
                        throw new ODataException("Cannot access a member with HTTP PUT.",
                                                 ODataExceptionCode.IllegalInvoke);
                    }
                    else
                    {
                        model = await ReadToJsonAsync(httpContext).ConfigureAwait(false);

                        content = LoadContentOrVirtualChild(odataRequest);
                        if (content == null)
                        {
                            ContentNotFound(httpContext);
                            return;
                        }

                        ResetContent(content);
                        UpdateContent(content, model, odataRequest);
                        await odataWriter.WriteSingleContentAsync(content, httpContext)
                        .ConfigureAwait(false);
                    }

                    break;

                case "MERGE":
                case "PATCH":     // update
                    if (odataRequest.IsMemberRequest)
                    {
                        throw new ODataException(
                                  String.Concat("Cannot access a member with HTTP ", httpMethod, "."),
                                  ODataExceptionCode.IllegalInvoke);
                    }
                    else
                    {
                        model = await ReadToJsonAsync(httpContext).ConfigureAwait(false);

                        content = LoadContentOrVirtualChild(odataRequest);
                        if (content == null)
                        {
                            ContentNotFound(httpContext);
                            return;
                        }

                        UpdateContent(content, model, odataRequest);
                        await odataWriter.WriteSingleContentAsync(content, httpContext)
                        .ConfigureAwait(false);
                    }

                    break;

                case "POST":     // invoke an action, create content
                    if (odataRequest.IsMemberRequest)
                    {
                        // MEMBER REQUEST
                        await odataWriter.WritePostOperationResultAsync(httpContext, odataRequest, _appConfig)
                        .ConfigureAwait(false);
                    }
                    else
                    {
                        // CREATION
                        if (!Node.Exists(odataRequest.RepositoryPath))
                        {
                            // parent does not exist
                            ContentNotFound(httpContext);
                            return;
                        }

                        model = await ReadToJsonAsync(httpContext).ConfigureAwait(false);

                        var newContent = CreateNewContent(model, odataRequest);
                        await odataWriter.WriteSingleContentAsync(newContent, httpContext)
                        .ConfigureAwait(false);
                    }

                    break;

                case "DELETE":
                    if (odataRequest.IsMemberRequest)
                    {
                        throw new ODataException(
                                  String.Concat("Cannot access a member with HTTP ", httpMethod, "."),
                                  ODataExceptionCode.IllegalInvoke);
                    }
                    else
                    {
                        content = LoadContentOrVirtualChild(odataRequest);
                        if (content != null)
                        {
                            var x = httpContext.Request.Query["permanent"].ToString();
                            if (x.Equals("true", StringComparison.OrdinalIgnoreCase))
                            {
                                content.DeletePhysical();
                            }
                            else
                            {
                                content.Delete();
                            }
                        }
                    }

                    break;
                }
            }
            catch (ContentNotFoundException e)
            {
                var oe = new ODataException(ODataExceptionCode.ResourceNotFound, e);
                await odataWriter.WriteErrorResponseAsync(httpContext, oe)
                .ConfigureAwait(false);
            }
            catch (ODataException e)
            {
                if (e.HttpStatusCode == 500)
                {
                    SnLog.WriteException(e);
                }
                await odataWriter.WriteErrorResponseAsync(httpContext, e)
                .ConfigureAwait(false);
            }
            catch (AccessDeniedException e)
            {
                var oe = new ODataException(ODataExceptionCode.Forbidden, e);
                await odataWriter.WriteErrorResponseAsync(httpContext, oe)
                .ConfigureAwait(false);
            }
            catch (UnauthorizedAccessException e)
            {
                var oe = new ODataException(ODataExceptionCode.Unauthorized, e);
                await odataWriter.WriteErrorResponseAsync(httpContext, oe)
                .ConfigureAwait(false);
            }
            catch (SenseNetSecurityException e)
            {
                // In case of a visitor we should not expose the information that this content actually exists. We return
                // a simple 404 instead to provide exactly the same response as the regular 404, where the content
                // really does not exist. But do this only if the visitor really does not have permission for the
                // requested content (because security exception could be thrown by an action or something else too).
                if (odataRequest != null && User.Current.Id == Identifiers.VisitorUserId)
                {
                    var head = NodeHead.Get(odataRequest.RepositoryPath);
                    if (head != null && !SecurityHandler.HasPermission(head, PermissionType.Open))
                    {
                        ContentNotFound(httpContext);
                        return;
                    }
                }

                var oe = new ODataException(ODataExceptionCode.NotSpecified, e);

                SnLog.WriteException(oe);

                await odataWriter.WriteErrorResponseAsync(httpContext, oe)
                .ConfigureAwait(false);
            }
            catch (InvalidContentActionException ex)
            {
                var oe = new ODataException(ODataExceptionCode.NotSpecified, ex);
                if (ex.Reason != InvalidContentActionReason.NotSpecified)
                {
                    oe.ErrorCode = Enum.GetName(typeof(InvalidContentActionReason), ex.Reason);
                }

                // it is unnecessary to log this exception as this is not a real error
                await odataWriter.WriteErrorResponseAsync(httpContext, oe)
                .ConfigureAwait(false);
            }
            catch (ContentRepository.Storage.Data.NodeAlreadyExistsException nae)
            {
                var oe = new ODataException(ODataExceptionCode.ContentAlreadyExists, nae);

                await odataWriter.WriteErrorResponseAsync(httpContext, oe)
                .ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                var oe = new ODataException(ODataExceptionCode.NotSpecified, ex);

                SnLog.WriteException(oe);

                await odataWriter.WriteErrorResponseAsync(httpContext, oe)
                .ConfigureAwait(false);
            }
        }
Ejemplo n.º 2
0
 internal static IEnumerable <ODataActionItem> GetActionItems(Content content, ODataRequest request, HttpContext httpContext)
 {
     return(GetActionsWithScenario(content, request, httpContext).Select(a => new ODataActionItem
     {
         Name = a.Action.Name,
         DisplayName = SNSR.GetString(a.Action.Text),
         Icon = a.Action.Icon,
         Index = a.Action.Index,
         Url = a.Action.Uri,
         Forbidden = a.Action.Forbidden,
         IsODataAction = a.Action.IsODataOperation,
         ActionParameters = a.Action.ActionParameters.Select(p => p.Name).ToArray(),
         Scenario = a.Scenario
     }));
 }
Ejemplo n.º 3
0
 /// <summary>
 /// Adds the OData request object to the items of HttpContext.
 /// </summary>
 internal static void SetODataRequest(this HttpContext httpContext, ODataRequest odataRequest)
 {
     httpContext.Items[ODataMiddleware.ODataRequestHttpContextKey] = odataRequest;
 }
Ejemplo n.º 4
0
 internal static IEnumerable <ActionBase> GetActions(Content content, ODataRequest request, HttpContext httpContext)
 {
     return(ODataMiddleware.ActionResolver.GetActions(content, request?.Scenario, null, httpContext));
 }
Ejemplo n.º 5
0
        private static IEnumerable <ScenarioAction> GetActionsWithScenario(Content content, ODataRequest request, HttpContext httpContext)
        {
            var scenario = request?.Scenario;
            var actions  = ActionFramework.GetActions(content, scenario, null, null);

            return(actions.Select(action => new ScenarioAction
            {
                Action = action,
                Scenario = scenario
            }));
        }
Ejemplo n.º 6
0
        internal static ODataRequest Parse(HttpContext httpContext)
        {
            var path = httpContext.Request.Path.Value;
            var req  = new ODataRequest();

            try
            {
                var relPath =
                    path.Substring(path.IndexOf(Configuration.Services.ODataServiceToken, StringComparison.OrdinalIgnoreCase) +
                                   Configuration.Services.ODataServiceToken.Length);

                req.IsServiceDocumentRequest = relPath.Length == 0;

                var segments    = relPath.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
                var resSegments = new List <string>();
                var prmSegments = new List <string>();
                req.IsCollection = true;
                for (var i = 0; i < segments.Length; i++)
                {
                    if (String.Compare(segments[i], "$metadata", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        req.IsMetadataRequest = true;
                        break;
                    }
                    if (String.Compare(segments[i], "$value", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        req.IsRawValueRequest = true;
                        break;
                    }
                    if (String.Compare(segments[i], "$count", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        req.CountOnly = true;
                        break;
                    }

                    if (!req.IsCollection)
                    {
                        prmSegments.Add(segments[i]);
                        continue;
                    }

                    var segment = segments[i];
                    if (i == 0 && segment.StartsWith("content(", StringComparison.OrdinalIgnoreCase) &&
                        segment.EndsWith(")"))
                    {
                        var idStr = segment.Substring(8).Trim('(', ')');
                        if (idStr[0] != '\'' && idStr[idStr.Length - 1] != '\'')
                        {
                            int id;
                            if (!int.TryParse(idStr, out id))
                            {
                                throw new ODataException(SNSR.Exceptions.OData.InvalidId, ODataExceptionCode.InvalidId);
                            }
                            req.IsCollection       = false;
                            req.RequestedContentId = id;
                            resSegments.Add(segment);
                            continue;
                        }
                    }
                    if (!segment.EndsWith("')"))
                    {
                        resSegments.Add(segment);
                    }
                    else
                    {
                        req.IsCollection = false;

                        var ii         = segment.IndexOf("('");
                        var entityName = segment.Substring(ii).Trim('(', ')').Trim('\'');
                        segment = segment.Substring(0, ii);
                        if (segment.Length > 0)
                        {
                            resSegments.Add(segment);
                        }
                        resSegments.Add(entityName);
                    }
                }

                if (resSegments.Count == 0)
                {
                    req.IsCollection = true;
                }
                else
                {
                    if (prmSegments.Count > 0)
                    {
                        req.IsMemberRequest = true;
                        req.PropertyName    = prmSegments[0];
                    }
                }

                Content content;
                if (req.RequestedContentId > 0 && (content = SystemAccount.Execute(() => Content.Load(req.RequestedContentId))) != null)
                {
                    req.RepositoryPath = content.Path;
                }
                else
                {
                    var newPath = String.Concat("/", String.Join("/", resSegments));
                    req.RepositoryPath = newPath;
                }

                req.ParseQuery(path, httpContext);
            }
            catch (Exception e)
            {
                req.RequestError = e;
            }
            return(req);
        }
Ejemplo n.º 7
0
        private Content CreateNewContent(JObject model, ODataRequest odataRequest)
        {
            var contentTypeName = GetPropertyValue <string>("__ContentType", model);
            var templateName    = GetPropertyValue <string>("__ContentTemplate", model);

            var name = GetPropertyValue <string>("Name", model);

            if (string.IsNullOrEmpty(name))
            {
                var displayName = GetPropertyValue <string>("DisplayName", model);
                name = ContentNamingProvider.GetNameFromDisplayName(displayName);
            }
            else
            {
                // do not allow saving a content with unencoded name
                name = ContentNamingProvider.GetNameFromDisplayName(name);
            }

            var parent = Node.Load <GenericContent>(odataRequest.RepositoryPath);

            if (string.IsNullOrEmpty(contentTypeName))
            {
                var allowedChildTypeNames = parent.GetAllowedChildTypeNames();

                if (allowedChildTypeNames is AllContentTypeNames)
                {
                    contentTypeName = typeof(ContentRepository.File).Name;
                }
                else
                {
                    var allowedContentTypeNames = parent.GetAllowedChildTypeNames().ToArray();
                    contentTypeName = allowedContentTypeNames.FirstOrDefault();
                    if (string.IsNullOrEmpty(contentTypeName))
                    {
                        contentTypeName = typeof(ContentRepository.File).Name;
                    }
                }
            }

            Content content;
            Node    template = null;

            if (templateName != null)
            {
                template = ContentTemplate.GetNamedTemplate(contentTypeName, templateName);
            }

            if (template == null)
            {
                content = Content.CreateNew(contentTypeName, parent, name);
            }
            else
            {
                var node = ContentTemplate.CreateFromTemplate(parent, template, name);
                content = Content.Create(node);
            }


            UpdateFields(content, model);

            if (odataRequest.MultistepSave)
            {
                content.Save(SavingMode.StartMultistepSave);
            }
            else
            {
                content.Save();
            }

            return(content);
        }
Ejemplo n.º 8
0
 protected string GetRichTextOutput(string fieldName, RichTextFieldValue rtfValue, ODataRequest oDataRequest)
 {
     if (!oDataRequest.HasExpandedRichTextField)
     {
         return(rtfValue.Text);
     }
     return(oDataRequest.AllRichTextFieldExpanded || oDataRequest.ExpandedRichTextFields.Contains(fieldName)
         ? JsonConvert.SerializeObject(rtfValue)
         : rtfValue.Text);
 }