Exemple #1
0
        internal void WriteChildrenCollection(String path, PortalContext portalContext, ODataRequest req)
        {
            var content = Content.Load(path);
            var chdef   = content.ChildrenDefinition;

            if (req.HasContentQuery)
            {
                chdef.ContentQuery = ContentQuery.AddClause(req.ContentQueryText, String.Concat("InTree:'", path, "'"), LogicalOperator.And);

                if (req.AutofiltersEnabled != FilterStatus.Default)
                {
                    chdef.EnableAutofilters = req.AutofiltersEnabled;
                }
                if (req.LifespanFilterEnabled != FilterStatus.Default)
                {
                    chdef.EnableLifespanFilter = req.LifespanFilterEnabled;
                }
                if (req.QueryExecutionMode != QueryExecutionMode.Default)
                {
                    chdef.QueryExecutionMode = req.QueryExecutionMode;
                }
                if (req.Top > 0)
                {
                    chdef.Top = req.Top;
                }
                if (req.Skip > 0)
                {
                    chdef.Skip = req.Skip;
                }
                if (req.Sort.Any())
                {
                    chdef.Sort = req.Sort;
                }
            }
            else
            {
                chdef.EnableAutofilters = FilterStatus.Disabled;
                if (string.IsNullOrEmpty(chdef.ContentQuery))
                {
                    chdef.ContentQuery = ContentQuery.AddClause(chdef.ContentQuery, String.Concat("InFolder:'", path, "'"), LogicalOperator.And);
                }
            }


            var contents = ProcessOperationQueryResponse(chdef, req, out var count);

            if (req.CountOnly)
            {
                WriteCount(portalContext, count);
            }
            else
            {
                WriteMultipleContent(portalContext, contents, count);
            }
        }
Exemple #2
0
        internal void WriteChildrenCollection(String path, PortalContext portalContext, ODataRequest req)
        {
            var content = Content.Load(path);
            var chdef   = content.ChildrenDefinition;

            if (string.IsNullOrEmpty(chdef.ContentQuery))
            {
                chdef.ContentQuery = ContentQuery.AddClause(chdef.ContentQuery, String.Concat("InFolder:'", path, "'"), ContentRepository.Storage.Search.ChainOperator.And);
            }
            chdef.EnableAutofilters = FilterStatus.Disabled;
            int count;
            var contents = ProcessOperationQueryResponse(chdef, portalContext, req, out count);

            if (req.CountOnly)
            {
                WriteCount(portalContext, count);
            }
            else
            {
                WriteMultipleContent(portalContext, contents, count);
            }
        }
Exemple #3
0
 internal void Initialize(ODataRequest odataRequest)
 {
     this.ODataRequest = odataRequest;
 }
Exemple #4
0
        private List <Dictionary <string, object> > ProcessOperationCollectionResponse(IEnumerable <Content> inputContents, ODataRequest req, out int count)
        {
            var x = ProcessODataFilters(inputContents, req, out var totalCount);

            var outContents = new List <Dictionary <string, object> >();
            var projector   = Projector.Create(req, true);

            foreach (var content in x)
            {
                var fields = CreateFieldDictionary(content, projector);
                outContents.Add(fields);
            }

            count = totalCount ?? outContents.Count;
            if (req.CountOnly)
            {
                return(null);
            }
            return(outContents);
        }
Exemple #5
0
        public void ProcessRequest(HttpContext context, string httpMethod, Stream inputStream)
        {
            ODataRequest   odataReq      = null;
            ODataFormatter formatter     = null;
            var            portalContext = (PortalContext)context.Items[PortalContext.CONTEXT_ITEM_KEY];

            try
            {
                // Allows browsers to send cross-domain requests to this URL
                context.Response.AddHeader("Access-Control-Allow-Origin", "*");

                Content content;

                Exception requestError = null;
                try
                {
                    odataReq          = ODataRequest.Parse(portalContext.RequestedUri.GetComponents(UriComponents.Path, UriFormat.Unescaped), portalContext);
                    this.ODataRequest = odataReq;
                }
                catch (Exception e)
                {
                    requestError = e;
                }

                formatter = ODataFormatter.Create(portalContext, odataReq);
                if (formatter == null)
                {
                    formatter = ODataFormatter.Create("json", portalContext);
                    throw new ODataException(ODataExceptionCode.InvalidFormatParameter);
                }

                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 == null ? ODataExceptionCode.RequestError : innerOdataError.ODataExceptionCode;
                    throw new ODataException(message, code, requestError);
                }

                odataReq.Format = formatter.FormatName;
                formatter.Initialize(odataReq);

                var exists = Node.Exists(odataReq.RepositoryPath);
                if (httpMethod != "POST" && !exists)
                {
                    ContentNotFound(context, odataReq.RepositoryPath);
                    return;
                }

                JObject model = null;
                switch (httpMethod)
                {
                case "GET":
                    if (odataReq.IsServiceDocumentRequest)
                    {
                        formatter.WriteServiceDocument(portalContext, odataReq);
                    }
                    else if (odataReq.IsMetadataRequest)
                    {
                        formatter.WriteMetadata(context, odataReq);
                    }
                    else
                    {
                        if (!Node.Exists(odataReq.RepositoryPath))
                        {
                            ContentNotFound(context, odataReq.RepositoryPath);
                        }
                        if (odataReq.HasContentQuery)
                        {
                            formatter.WriteQueryResult(portalContext, odataReq);
                        }
                        else if (odataReq.IsCollection)
                        {
                            formatter.WriteChildrenCollection(odataReq.RepositoryPath, portalContext, odataReq);
                        }
                        else if (odataReq.IsMemberRequest)
                        {
                            formatter.WriteContentProperty(odataReq.RepositoryPath, odataReq.PropertyName, odataReq.IsRawValueRequest, portalContext, odataReq);
                        }
                        else
                        {
                            formatter.WriteSingleContent(odataReq.RepositoryPath, portalContext);
                        }
                    }
                    break;

                case "PUT":     // update
                    if (odataReq.IsMemberRequest)
                    {
                        throw new ODataException("Cannot access a member with HTTP PUT.", ODataExceptionCode.IllegalInvoke);
                    }
                    else
                    {
                        model   = Read(inputStream);
                        content = Content.Load(odataReq.RepositoryPath);
                        ResetContent(content);
                        UpdateContent(content, model, odataReq);
                        formatter.WriteSingleContent(content, portalContext);
                    }
                    break;

                case "MERGE":
                case "PATCH":     // update
                    if (odataReq.IsMemberRequest)
                    {
                        throw new ODataException(String.Concat("Cannot access a member with HTTP ", httpMethod, "."), ODataExceptionCode.IllegalInvoke);
                    }
                    else
                    {
                        model   = Read(inputStream);
                        content = Content.Load(odataReq.RepositoryPath);
                        UpdateContent(content, model, odataReq);
                        formatter.WriteSingleContent(content, portalContext);
                    }
                    break;

                case "POST":     // invoke an action, create content
                    if (odataReq.IsMemberRequest)
                    {
                        formatter.WriteOperationResult(inputStream, portalContext, odataReq);
                    }
                    else
                    {
                        model   = Read(inputStream);
                        content = CreateContent(model, odataReq, portalContext);
                        formatter.WriteSingleContent(content, portalContext);
                    }
                    break;

                case "DELETE":
                    if (odataReq.IsMemberRequest)
                    {
                        throw new ODataException(String.Concat("Cannot access a member with HTTP ", httpMethod, "."), ODataExceptionCode.IllegalInvoke);
                    }
                    else
                    {
                        //model = Read(inputStream);
                        Content.Delete(odataReq.RepositoryPath);
                    }
                    break;
                }
            }
            catch (ContentNotFoundException e)
            {
                var oe = new ODataException(ODataExceptionCode.ResourceNotFound, e);

                formatter.WriteErrorResponse(context, oe);
            }
            catch (ODataException e)
            {
                if (e.HttpStatusCode == 500)
                {
                    Logger.WriteException(e);
                }

                formatter.WriteErrorResponse(context, e);
            }
            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 (odataReq != null && User.Current.Id == User.Visitor.Id)
                {
                    var head = NodeHead.Get(odataReq.RepositoryPath);
                    if (head != null && !SecurityHandler.HasPermission(head, PermissionType.Open))
                    {
                        ContentNotFound(context, odataReq.RepositoryPath);
                        return;
                    }
                }

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

                Logger.WriteException(oe);

                formatter.WriteErrorResponse(context, oe);
            }
            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
                //Logger.WriteException(oe);

                formatter.WriteErrorResponse(context, oe);
            }
            catch (Exception ex)
            {
                var oe = new ODataException(ODataExceptionCode.NotSpecified, ex);

                Logger.WriteException(oe);

                formatter.WriteErrorResponse(context, oe);
            }
            finally
            {
                context.Response.End();
            }
        }
Exemple #6
0
        /// <summary>
        /// Handles POST operations. Parameters come from request stream.
        /// </summary>
        /// <param name="inputStream"></param>
        /// <param name="portalContext"></param>
        /// <param name="odataReq"></param>
        internal void WriteOperationResult(Stream inputStream, PortalContext portalContext, ODataRequest odataReq)
        {
            var content = ODataHandler.LoadContentByVersionRequest(odataReq.RepositoryPath);

            if (content == null)
            {
                throw new ContentNotFoundException(string.Format(SNSR.GetString("$Action,ErrorContentNotFound"), odataReq.RepositoryPath));
            }

            var action = ODataHandler.ActionResolver.GetAction(content, odataReq.Scenario, odataReq.PropertyName, null, null);

            if (action == null)
            {
                // check if this is a versioning action (e.g. a checkout)
                SavingAction.AssertVersioningAction(content, odataReq.PropertyName, true);

                throw new InvalidContentActionException(InvalidContentActionReason.UnknownAction, content.Path, null, odataReq.PropertyName);
            }

            if (action.Forbidden || (action.GetApplication() != null && !action.GetApplication().Security.HasPermission(PermissionType.RunApplication)))
            {
                throw new InvalidContentActionException("Forbidden action: " + odataReq.PropertyName);
            }

            var parameters = GetOperationParameters(action, inputStream);
            var response   = action.Execute(content, parameters);

            if (response is Content responseAsContent)
            {
                WriteSingleContent(responseAsContent, portalContext);
                return;
            }

            response = ProcessOperationResponse(response, odataReq, out var count);
            WriteOperationResult(response, portalContext, odataReq, count);
        }
Exemple #7
0
        private List <Dictionary <string, object> > ProcessOperationQueryResponse(ChildrenDefinition qdef, ODataRequest req, out int count)
        {
            var queryText = qdef.ContentQuery;

            if (queryText.Contains("}}"))
            {
                queryText = ContentQuery.ResolveInnerQueries(qdef.ContentQuery, new QuerySettings
                {
                    EnableAutofilters    = qdef.EnableAutofilters,
                    EnableLifespanFilter = qdef.EnableLifespanFilter,
                    QueryExecutionMode   = qdef.QueryExecutionMode,
                    Sort = qdef.Sort
                });
            }

            var cdef = new ChildrenDefinition
            {
                PathUsage            = qdef.PathUsage,
                ContentQuery         = queryText,
                Top                  = req.Top > 0 ? req.Top : qdef.Top,
                Skip                 = req.Skip > 0 ? req.Skip : qdef.Skip,
                Sort                 = req.Sort != null && req.Sort.Any() ? req.Sort : qdef.Sort,
                CountAllPages        = req.HasInlineCount ? req.InlineCount == InlineCount.AllPages : qdef.CountAllPages,
                EnableAutofilters    = req.AutofiltersEnabled != FilterStatus.Default ? req.AutofiltersEnabled : qdef.EnableAutofilters,
                EnableLifespanFilter = req.LifespanFilterEnabled != FilterStatus.Default ? req.AutofiltersEnabled : qdef.EnableLifespanFilter,
                QueryExecutionMode   = req.QueryExecutionMode != QueryExecutionMode.Default ? req.QueryExecutionMode : qdef.QueryExecutionMode,
            };

            var snQuery = SnExpression.BuildQuery(req.Filter, typeof(Content), null, cdef);

            if (cdef.EnableAutofilters != FilterStatus.Default)
            {
                snQuery.EnableAutofilters = cdef.EnableAutofilters;
            }
            if (cdef.EnableLifespanFilter != FilterStatus.Default)
            {
                snQuery.EnableLifespanFilter = cdef.EnableLifespanFilter;
            }
            if (cdef.QueryExecutionMode != QueryExecutionMode.Default)
            {
                snQuery.QueryExecutionMode = cdef.QueryExecutionMode;
            }

            var result = snQuery.Execute(new SnQueryContext(null, User.Current.Id));

            // for optimization purposes this combined condition is examined separately
            if (req.InlineCount == InlineCount.AllPages && req.CountOnly)
            {
                count = result.TotalCount;
                return(null);
            }

            var ids = result.Hits.ToArray();

            count = req.InlineCount == InlineCount.AllPages ? result.TotalCount : ids.Length;
            if (req.CountOnly)
            {
                return(null);
            }

            var contents   = new List <Dictionary <string, object> >();
            var projector  = Projector.Create(req, true);
            var missingIds = new List <int>();

            foreach (var id in ids)
            {
                var content = Content.Load(id);
                if (content == null)
                {
                    // collect missing ids for logging purposes
                    missingIds.Add(id);
                    continue;
                }

                var fields = CreateFieldDictionary(content, projector);
                contents.Add(fields);
            }

            if (missingIds.Count > 0)
            {
                // subtract missing count from result count
                count = Math.Max(0, count - missingIds.Count);

                // index anomaly: there are ids in the index that could not be loaded from the database
                SnLog.WriteWarning("Missing ids found in the index that could not be loaded from the database. See id list below.",
                                   EventId.Indexing,
                                   properties: new Dictionary <string, object>
                {
                    { "MissingIds", string.Join(", ", missingIds.OrderBy(id => id)) }
                });
            }

            return(contents);
        }
Exemple #8
0
        private List <Dictionary <string, object> > ProcessOperationQueryResponse(ChildrenDefinition qdef, PortalContext portalContext, ODataRequest req, out int count)
        {
            var cdef = new ChildrenDefinition
            {
                PathUsage            = qdef.PathUsage,
                ContentQuery         = qdef.ContentQuery,
                Top                  = req.Top > 0 ? req.Top : qdef.Top,
                Skip                 = req.Skip > 0 ? req.Skip : qdef.Skip,
                Sort                 = req.Sort != null && req.Sort.Count() > 0 ? req.Sort : qdef.Sort,
                EnableAutofilters    = req.AutofiltersEnabled != FilterStatus.Default ? req.AutofiltersEnabled : qdef.EnableAutofilters,
                EnableLifespanFilter = req.LifespanFilterEnabled != FilterStatus.Default ? req.AutofiltersEnabled : qdef.EnableLifespanFilter,
                QueryExecutionMode   = req.QueryExecutionMode != QueryExecutionMode.Default ? req.QueryExecutionMode : qdef.QueryExecutionMode,
            };

            var lucQuery = SnExpression.BuildQuery(req.Filter, typeof(Content), null, cdef);

            if (cdef.EnableAutofilters != FilterStatus.Default)
            {
                lucQuery.EnableAutofilters = cdef.EnableAutofilters;
            }
            if (cdef.EnableLifespanFilter != FilterStatus.Default)
            {
                lucQuery.EnableLifespanFilter = cdef.EnableLifespanFilter;
            }
            if (cdef.QueryExecutionMode != QueryExecutionMode.Default)
            {
                lucQuery.QueryExecutionMode = cdef.QueryExecutionMode;
            }

            var result   = lucQuery.Execute();
            var idResult = result.Select(x => x.NodeId);

            count = req.InlineCount == InlineCount.AllPages ? lucQuery.TotalCount : idResult.Count();

            if (req.CountOnly)
            {
                return(null);
            }

            var contents   = new List <Dictionary <string, object> >();
            var projector  = Projector.Create(req, true);
            var missingIds = new List <int>();

            foreach (var id in idResult)
            {
                var content = Content.Load(id);
                if (content == null)
                {
                    // collect missing ids for logging purposes
                    missingIds.Add(id);
                    continue;
                }

                var fields = CreateFieldDictionary(content, portalContext, projector);
                contents.Add(fields);
            }

            if (missingIds.Count > 0)
            {
                // subtract missing count from result count
                count = Math.Max(0, count - missingIds.Count);

                // index anomaly: there are ids in the index that could not be loaded from the database
                SnLog.WriteWarning("Missing ids found in the index that could not be loaded from the database. See id list below.",
                                   EventId.Indexing,
                                   properties: new Dictionary <string, object>
                {
                    { "MissingIds", string.Join(", ", missingIds.OrderBy(id => id)) }
                });
            }

            return(contents);
        }
Exemple #9
0
 internal static IEnumerable <ODataActionItem> GetActionItems(Content content, ODataRequest request)
 {
     return(GetActionsWithScenario(content, request).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,
         IncludeBackUrl = a.Action.GetApplication() == null ? 0 : (int)a.Action.GetApplication().IncludeBackUrl,
         ClientAction = !string.IsNullOrEmpty((a.Action as ClientAction)?.Callback),
         Forbidden = a.Action.Forbidden,
         IsODataAction = a.Action.IsODataOperation,
         ActionParameters = a.Action.ActionParameters.Select(p => p.Name).ToArray(),
         Scenario = a.Scenario
     }));
 }
Exemple #10
0
        private List <Dictionary <string, object> > ProcessOperationQueryResponse(ChildrenDefinition qdef, PortalContext portalContext, ODataRequest req, out int count)
        {
            var cdef = new ChildrenDefinition
            {
                PathUsage            = qdef.PathUsage,
                ContentQuery         = qdef.ContentQuery,
                Top                  = req.Top > 0 ? req.Top : qdef.Top,
                Skip                 = req.Skip > 0 ? req.Skip : qdef.Skip,
                Sort                 = req.Sort != null && req.Sort.Count() > 0 ? req.Sort : qdef.Sort,
                EnableAutofilters    = req.AutofiltersEnabled != FilterStatus.Default ? req.AutofiltersEnabled : qdef.EnableAutofilters,
                EnableLifespanFilter = req.LifespanFilterEnabled != FilterStatus.Default ? req.AutofiltersEnabled : qdef.EnableLifespanFilter
            };

            var sourceCollectionItemType = typeof(Content);
            var lucQuery = SnExpression.BuildQuery(req.Filter, typeof(Content), null, cdef);
            var result   = lucQuery.Execute();
            var idResult = result.Select(x => x.NodeId);

            //var count = req.InlineCount == InlineCount.AllPages ? ExecuteQueryWithCountOnly(lucQuery, cdef.EnableAutofilters, cdef.EnableLifespanFilter) : idResult.Count();
            count = req.InlineCount == InlineCount.AllPages ? lucQuery.TotalCount : idResult.Count();

            if (req.CountOnly)
            {
                return(null);
            }

            var contents  = new List <Dictionary <string, object> >();
            var projector = Projector.Create(req, true);

            foreach (var id in idResult)
            {
                var content = Content.Load(id);
                var fields  = CreateFieldDictionary(content, portalContext, projector);
                contents.Add(fields);
            }
            return(contents);
        }
Exemple #11
0
        private IEnumerable <Content> ProcessODataFilters(IEnumerable <Content> inputContents, PortalContext portalContext, ODataRequest req)
        {
            var x = inputContents;

            if (req.HasFilter)
            {
                var y = x as IQueryable <Content>;
                if (y != null)
                {
                    x = y.Where((Expression <Func <Content, bool> >)req.Filter);
                }
                else
                {
                    var lambdaExpr = (LambdaExpression)req.Filter;
                    x = x.Where((Func <Content, bool>)lambdaExpr.Compile());
                }
            }
            if (req.HasSort)
            {
                x = AddSortToCollectionExpression(x, req.Sort);
            }
            if (req.HasSkip)
            {
                x = x.Skip(req.Skip);
            }
            if (req.HasTop)
            {
                x = x.Take(req.Top);
            }

            return(x);
        }
Exemple #12
0
        private void WriteOperationResult(object result, PortalContext portalContext, ODataRequest odataReq)
        {
            var content = result as Content;

            if (content != null)
            {
                WriteSingleContent(content, portalContext);
                return;
            }

            var enumerable = result as IEnumerable <Content>;

            if (enumerable != null)
            {
                WriteMultiRefContents(enumerable, portalContext, odataReq);
                return;
            }

            WriteOperationCustomResult(portalContext, result);
        }
Exemple #13
0
        internal void WriteContentProperty(String path, string propertyName, bool rawValue, PortalContext portalContext, ODataRequest req)
        {
            var content = ODataHandler.LoadContentByVersionRequest(path);

            if (content == null)
            {
                ODataHandler.ContentNotFound(portalContext.OwnerHttpContext, path);
                return;
            }

            if (propertyName == ODataHandler.PROPERTY_ACTIONS)
            {
                var backUrl = portalContext.BackUrl;

                //Get actions without back url: let the client append the back parameter,
                //as we are in a service here that does not know about the redirect url.
                var snActions = ODataHandler.ActionResolver.GetActions(content, req.Scenario, string.IsNullOrEmpty(backUrl) ? null : backUrl);

                var actions = snActions.Where(a => a.IsHtmlOperation).Select(a => new ODataActionItem
                {
                    Name           = a.Name,
                    DisplayName    = SNSR.GetString(a.Text),
                    Icon           = a.Icon,
                    Index          = a.Index,
                    Url            = a.Uri,
                    IncludeBackUrl = a.GetApplication() == null ? 0 : (int)a.GetApplication().IncludeBackUrl,
                    ClientAction   = a is ClientAction && !string.IsNullOrEmpty(((ClientAction)a).Callback),
                    Forbidden      = a.Forbidden
                });
                WriteActionsProperty(portalContext, actions.ToArray(), rawValue);
                return;
            }

            Field field;

            if (content.Fields.TryGetValue(propertyName, out field))
            {
                var refField = field as ReferenceField;
                if (refField != null)
                {
                    var refFieldSetting = refField.FieldSetting as ReferenceFieldSetting;
                    var isMultiRef      = true;
                    if (refFieldSetting != null)
                    {
                        isMultiRef = refFieldSetting.AllowMultiple == true;
                    }
                    if (isMultiRef)
                    {
                        WriteMultiRefContents(refField.GetData(), portalContext, req);
                    }
                    else
                    {
                        WriteSingleRefContent(refField.GetData(), portalContext);
                    }
                }
                else if (!rawValue)
                {
                    WriteSingleContent(portalContext, new Dictionary <string, object> {
                        { propertyName, field.GetData() }
                    });
                }
                else
                {
                    WriteRaw(field.GetData(), portalContext);
                }
            }
            else
            {
                //ResourceNotFound(content, propertyName);
                WriteOperationResult(portalContext, req);
            }
        }
Exemple #14
0
        private void WriteMultiRefContents(object references, PortalContext portalContext, ODataRequest req) //UNDONE: x: Rename: WriteMultiRefContents
        {
            var resp = portalContext.OwnerHttpContext.Response;

            if (references != null)
            {
                Node node      = references as Node;
                var  projector = Projector.Create(req, true);
                if (node != null)
                {
                    var contents = new List <Dictionary <string, object> >();
                    contents.Add(CreateFieldDictionary(Content.Create(node), portalContext, projector)); //TODO: ODATA: multiref item: get available types from reference property
                    WriteMultipleContent(portalContext, contents, 1);
                }
                else
                {
                    var enumerable = references as System.Collections.IEnumerable;
                    if (enumerable != null)
                    {
                        var skipped   = 0;
                        var allcount  = 0;
                        var count     = 0;
                        var realcount = 0;
                        var contents  = new List <Dictionary <string, object> >();
                        if (req.HasFilter)
                        {
                            var filtered = new FilteredEnumerable(enumerable, (System.Linq.Expressions.LambdaExpression)req.Filter, req.Top, req.Skip);
                            foreach (Node item in filtered)
                            {
                                contents.Add(CreateFieldDictionary(Content.Create(item), portalContext, projector));
                            }
                            allcount  = filtered.AllCount;
                            realcount = contents.Count;
                        }
                        else
                        {
                            foreach (Node item in enumerable)
                            {
                                allcount++;
                                if (skipped++ < req.Skip)
                                {
                                    continue;
                                }
                                if (req.Top == 0 || count++ < req.Top)
                                {
                                    contents.Add(CreateFieldDictionary(Content.Create(item), portalContext, projector));
                                    realcount++;
                                }
                            }
                        }
                        WriteMultipleContent(portalContext, contents, req.InlineCount == InlineCount.AllPages ? allcount : realcount);
                    }
                }
            }
        }
Exemple #15
0
        private void WriteMultiRefContents(object references, PortalContext portalContext, ODataRequest req)
        {
            if (references == null)
            {
                return;
            }

            var node      = references as Node;
            var projector = Projector.Create(req, true);

            if (node != null)
            {
                var contents = new List <Dictionary <string, object> >
                {
                    CreateFieldDictionary(Content.Create(node), projector)
                };
                //TODO: ODATA: multiref item: get available types from reference property
                WriteMultipleContent(portalContext, contents, 1);
            }
            else
            {
                if (references is IEnumerable enumerable)
                {
                    var skipped   = 0;
                    var allcount  = 0;
                    var count     = 0;
                    var realcount = 0;
                    var contents  = new List <Dictionary <string, object> >();
                    if (req.HasFilter)
                    {
                        var filtered = new FilteredEnumerable(enumerable, (LambdaExpression)req.Filter, req.Top, req.Skip);
                        foreach (Node item in filtered)
                        {
                            contents.Add(CreateFieldDictionary(Content.Create(item), projector));
                        }
                        allcount  = filtered.AllCount;
                        realcount = contents.Count;
                    }
                    else
                    {
                        foreach (Node item in enumerable)
                        {
                            allcount++;
                            if (skipped++ < req.Skip)
                            {
                                continue;
                            }
                            if (req.Top == 0 || count++ < req.Top)
                            {
                                contents.Add(CreateFieldDictionary(Content.Create(item), projector));
                                realcount++;
                            }
                        }
                    }
                    WriteMultipleContent(portalContext, contents, req.InlineCount == InlineCount.AllPages ? allcount : realcount);
                }
            }
        }
Exemple #16
0
        private static IEnumerable <ScenarioAction> GetActionsWithScenario(Content content, ODataRequest request)
        {
            // Use the back url provided by the client. If it is empty, use
            // the url of the caller page (the referrer provided by ASP.NET).
            // The back url can be omitted (switched off) by the client if it provides the
            // appropriate request parameter (includebackurl false).
            var backUrl = PortalContext.Current != null && (request == null || request.IncludeBackUrl)
                ? PortalContext.Current.BackUrl
                : null;

            if (string.IsNullOrEmpty(backUrl) && (request == null || request.IncludeBackUrl) &&
                HttpContext.Current?.Request?.UrlReferrer != null)
            {
                backUrl = HttpContext.Current.Request.UrlReferrer.ToString();
            }

            var scenario = request?.Scenario;
            var actions  = ActionFramework.GetActions(content, scenario, null, string.IsNullOrEmpty(backUrl) ? null : backUrl, HttpContext.Current);

            return(actions.Select(action => new ScenarioAction
            {
                Action = action,
                Scenario = scenario
            }));
        }
Exemple #17
0
        internal void WriteContentProperty(String path, string propertyName, bool rawValue, PortalContext portalContext, ODataRequest req)
        {
            var content = ODataHandler.LoadContentByVersionRequest(path);

            if (content == null)
            {
                ODataHandler.ContentNotFound(portalContext.OwnerHttpContext, path);
                return;
            }

            if (propertyName == ODataHandler.ActionsPropertyName)
            {
                WriteActionsProperty(portalContext, ODataTools.GetActionItems(content, req).ToArray(), rawValue);
                return;
            }
            if (propertyName == ODataHandler.ChildrenPropertyName)
            {
                WriteChildrenCollection(path, portalContext, req);
                return;
            }

            if (content.Fields.TryGetValue(propertyName, out var field))
            {
                if (field is ReferenceField refField)
                {
                    var refFieldSetting = refField.FieldSetting as ReferenceFieldSetting;
                    var isMultiRef      = true;
                    if (refFieldSetting != null)
                    {
                        isMultiRef = refFieldSetting.AllowMultiple == true;
                    }
                    if (isMultiRef)
                    {
                        WriteMultiRefContents(refField.GetData(), portalContext, req);
                    }
                    else
                    {
                        WriteSingleRefContent(refField.GetData(), portalContext);
                    }
                }
                else if (field is AllowedChildTypesField actField)
                {
                    WriteMultiRefContents(actField.GetData(), portalContext, req);
                }
                else if (!rawValue)
                {
                    WriteSingleContent(portalContext, new Dictionary <string, object> {
                        { propertyName, field.GetData() }
                    });
                }
                else
                {
                    WriteRaw(field.GetData(), portalContext);
                }
            }
            else
            {
                WriteOperationResult(portalContext, req);
            }
        }
Exemple #18
0
        internal static ODataRequest Parse(string path, PortalContext portalContext)
        {
            var req     = new ODataRequest();
            var relPath = path.Substring(path.IndexOf(ODATA_SVC, StringComparison.OrdinalIgnoreCase) + ODATA_SVC.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);
                }
            }

            var pathIsRelative = true;

            if (resSegments.Count == 0)
            {
                req.RepositoryPath = portalContext.Site.Path;
                req.IsCollection   = true;
            }
            else
            {
                pathIsRelative = String.Compare(resSegments[0], "root", StringComparison.OrdinalIgnoreCase) != 0;
                if (pathIsRelative)
                {
                    pathIsRelative = !resSegments[0].StartsWith("root(", StringComparison.OrdinalIgnoreCase);
                }

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

            Content content;

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

            //---------------------------------------------------

            req.ParseQuery(path, portalContext);
            return(req);
        }
Exemple #19
0
        private void WriteOperationResult(object result, PortalContext portalContext, ODataRequest odataReq, int allCount)
        {
            if (result is Content content)
            {
                WriteSingleContent(content, portalContext);
                return;
            }

            if (result is IEnumerable <Content> enumerable)
            {
                WriteMultiRefContents(enumerable, portalContext, odataReq);
                return;
            }

            WriteOperationCustomResult(portalContext, result, odataReq.InlineCount == InlineCount.AllPages ? allCount : (int?)null);
        }
        private object ProcessOperationResponse(object response, PortalContext portalContext, ODataRequest odataReq, out int count)
        {
            var qdef = response as ChildrenDefinition;

            if (qdef != null)
            {
                return(ProcessOperationQueryResponse(qdef, portalContext, odataReq, out count));
            }

            var coll = response as IEnumerable <Content>;

            if (coll != null)
            {
                return(ProcessOperationCollectionResponse(coll, portalContext, odataReq, out count));
            }

            var dict = response as IDictionary;

            if (dict != null)
            {
                count = dict.Count;
                var targetTypized = new Dictionary <Content, object>();
                foreach (var item in dict.Keys)
                {
                    var content = item as Content;
                    if (content == null)
                    {
                        return(response);
                    }
                    targetTypized.Add(content, dict[content]);
                }
                return(ProcessOperationDictionaryResponse(targetTypized, portalContext, odataReq, out count));
            }

            // get real count from an enumerable
            var enumerable = response as IEnumerable;

            if (enumerable != null)
            {
                var c = 0;
                foreach (var x in enumerable)
                {
                    c++;
                }
                count = c;
            }
            else
            {
                count = 1;
            }

            if (response != null && response.ToString() == "{ PreviewAvailable = True }")
            {
                return(true);
            }
            if (response != null && response.ToString() == "{ PreviewAvailable = False }")
            {
                return(false);
            }
            return(response);
        }
Exemple #21
0
        private List <Dictionary <string, object> > ProcessOperationDictionaryResponse(IDictionary <Content, object> input, ODataRequest req, out int count)
        {
            var x = ProcessODataFilters(input.Keys, req, out var totalCount);

            var output    = new List <Dictionary <string, object> >();
            var projector = Projector.Create(req, true);

            foreach (var content in x)
            {
                var fields = CreateFieldDictionary(content, projector);
                var item   = new Dictionary <string, object>
                {
                    { "key", fields },
                    { "value", input[content] }
                };
                output.Add(item);
            }
            count = totalCount ?? output.Count;
            if (req.CountOnly)
            {
                return(null);
            }
            return(output);
        }
Exemple #22
0
        private Content CreateContent(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(SenseNet.ContentRepository.File).Name;
                }
                else
                {
                    var allowedContentTypeNames = parent.GetAllowedChildTypeNames().ToArray();
                    contentTypeName = allowedContentTypeNames.FirstOrDefault();
                    if (string.IsNullOrEmpty(contentTypeName))
                    {
                        contentTypeName = typeof(SenseNet.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 templated = ContentTemplate.CreateFromTemplate(parent, template, name);
                content = Content.Create(templated);
            }


            UpdateFields(content, model);

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

            return(content);
        }
Exemple #23
0
        private IEnumerable <Content> ProcessODataFilters(IEnumerable <Content> inputContents, ODataRequest req, out int?totalCount)
        {
            var x = inputContents;

            if (req.HasFilter)
            {
                if (x is IQueryable <Content> y)
                {
                    x = y.Where((Expression <Func <Content, bool> >)req.Filter);
                }
                else
                {
                    var filter     = SnExpression.GetCaseInsensitiveFilter(req.Filter);
                    var lambdaExpr = (LambdaExpression)filter;
                    x = x.Where((Func <Content, bool>)lambdaExpr.Compile());
                }
            }
            if (req.HasSort)
            {
                x = AddSortToCollectionExpression(x, req.Sort);
            }

            if (req.InlineCount == InlineCount.AllPages)
            {
                x          = x.ToList();
                totalCount = ((IList)x).Count;
            }
            else
            {
                totalCount = null;
            }

            if (req.HasSkip)
            {
                x = x.Skip(req.Skip);
            }
            if (req.HasTop)
            {
                x = x.Take(req.Top);
            }

            return(x);
        }
Exemple #24
0
        public void ProcessRequest(HttpContext context, string httpMethod, Stream inputStream)
        {
            ODataRequest   odataReq      = null;
            ODataFormatter formatter     = null;
            var            portalContext = (PortalContext)context.Items[PortalContext.CONTEXT_ITEM_KEY];

            try
            {
                Content content;

                odataReq = portalContext.ODataRequest;
                if (odataReq == null)
                {
                    formatter = ODataFormatter.Create("json", portalContext);
                    throw new ODataException("The Request is not an OData request.", ODataExceptionCode.RequestError);
                }

                this.ODataRequest = portalContext.ODataRequest;
                Exception requestError = this.ODataRequest.RequestError;

                formatter = ODataFormatter.Create(portalContext, odataReq);
                if (formatter == null)
                {
                    formatter = ODataFormatter.Create("json", portalContext);
                    throw new ODataException(ODataExceptionCode.InvalidFormatParameter);
                }

                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);
                }

                odataReq.Format = formatter.FormatName;
                formatter.Initialize(odataReq);

                var exists = Node.Exists(odataReq.RepositoryPath);
                if (!exists && !odataReq.IsServiceDocumentRequest && !odataReq.IsMetadataRequest && !AllowedMethodNamesWithoutContent.Contains(httpMethod))
                {
                    ContentNotFound(context, odataReq.RepositoryPath);
                    return;
                }

                JObject model = null;
                switch (httpMethod)
                {
                case "GET":
                    if (odataReq.IsServiceDocumentRequest)
                    {
                        formatter.WriteServiceDocument(portalContext, odataReq);
                    }
                    else if (odataReq.IsMetadataRequest)
                    {
                        formatter.WriteMetadata(context, odataReq);
                    }
                    else
                    {
                        if (!Node.Exists(odataReq.RepositoryPath))
                        {
                            ContentNotFound(context, odataReq.RepositoryPath);
                        }
                        else if (odataReq.IsCollection)
                        {
                            formatter.WriteChildrenCollection(odataReq.RepositoryPath, portalContext, odataReq);
                        }
                        else if (odataReq.IsMemberRequest)
                        {
                            formatter.WriteContentProperty(odataReq.RepositoryPath, odataReq.PropertyName,
                                                           odataReq.IsRawValueRequest, portalContext, odataReq);
                        }
                        else
                        {
                            formatter.WriteSingleContent(odataReq.RepositoryPath, portalContext);
                        }
                    }
                    break;

                case "PUT":     // update
                    if (odataReq.IsMemberRequest)
                    {
                        throw new ODataException("Cannot access a member with HTTP PUT.",
                                                 ODataExceptionCode.IllegalInvoke);
                    }
                    else
                    {
                        model   = Read(inputStream);
                        content = LoadContentOrVirtualChild(odataReq);
                        if (content == null)
                        {
                            ContentNotFound(context, odataReq.RepositoryPath);
                            return;
                        }

                        ResetContent(content);
                        UpdateContent(content, model, odataReq);
                        formatter.WriteSingleContent(content, portalContext);
                    }
                    break;

                case "MERGE":
                case "PATCH":     // update
                    if (odataReq.IsMemberRequest)
                    {
                        throw new ODataException(
                                  String.Concat("Cannot access a member with HTTP ", httpMethod, "."),
                                  ODataExceptionCode.IllegalInvoke);
                    }
                    else
                    {
                        model   = Read(inputStream);
                        content = LoadContentOrVirtualChild(odataReq);
                        if (content == null)
                        {
                            ContentNotFound(context, odataReq.RepositoryPath);
                            return;
                        }

                        UpdateContent(content, model, odataReq);
                        formatter.WriteSingleContent(content, portalContext);
                    }
                    break;

                case "POST":     // invoke an action, create content
                    if (odataReq.IsMemberRequest)
                    {
                        formatter.WriteOperationResult(inputStream, portalContext, odataReq);
                    }
                    else
                    {
                        // parent must exist
                        if (!Node.Exists(odataReq.RepositoryPath))
                        {
                            ContentNotFound(context, odataReq.RepositoryPath);
                            return;
                        }
                        model   = Read(inputStream);
                        content = CreateContent(model, odataReq);
                        formatter.WriteSingleContent(content, portalContext);
                    }
                    break;

                case "DELETE":
                    if (odataReq.IsMemberRequest)
                    {
                        throw new ODataException(
                                  String.Concat("Cannot access a member with HTTP ", httpMethod, "."),
                                  ODataExceptionCode.IllegalInvoke);
                    }
                    else
                    {
                        content = LoadContentOrVirtualChild(odataReq);
                        if (content != null)
                        {
                            content.Delete();
                        }
                    }
                    break;
                }
            }
            catch (ContentNotFoundException e)
            {
                var oe = new ODataException(ODataExceptionCode.ResourceNotFound, e);

                formatter.WriteErrorResponse(context, oe);
            }
            catch (ODataException e)
            {
                if (e.HttpStatusCode == 500)
                {
                    SnLog.WriteException(e);
                }

                formatter.WriteErrorResponse(context, e);
            }
            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 (odataReq != null && User.Current.Id == User.Visitor.Id)
                {
                    var head = NodeHead.Get(odataReq.RepositoryPath);
                    if (head != null && !SecurityHandler.HasPermission(head, PermissionType.Open))
                    {
                        ContentNotFound(context, odataReq.RepositoryPath);
                        return;
                    }
                }

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

                SnLog.WriteException(oe);

                formatter.WriteErrorResponse(context, oe);
            }
            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
                formatter.WriteErrorResponse(context, oe);
            }
            catch (ContentRepository.Storage.Data.NodeAlreadyExistsException nae)
            {
                var oe = new ODataException(ODataExceptionCode.ContentAlreadyExists, nae);

                formatter.WriteErrorResponse(context, oe);
            }
            catch (System.Threading.ThreadAbortException tae)
            {
                if (!context.Response.IsRequestBeingRedirected)
                {
                    var oe = new ODataException(ODataExceptionCode.RequestError, tae);
                    formatter.WriteErrorResponse(context, oe);
                }
                // specific redirect response so do nothing
            }
            catch (Exception ex)
            {
                var oe = new ODataException(ODataExceptionCode.NotSpecified, ex);

                SnLog.WriteException(oe);

                formatter.WriteErrorResponse(context, oe);
            }
            finally
            {
                context.Response.End();
            }
        }
Exemple #25
0
 internal static IEnumerable <ODataActionItem> GetHtmlActionItems(Content content, ODataRequest request)
 {
     return(GetActions(content, request).Where(a => a.IsHtmlOperation).Select(a => new ODataActionItem
     {
         Name = a.Name,
         DisplayName = SNSR.GetString(a.Text),
         Icon = a.Icon,
         Index = a.Index,
         Url = a.Uri,
         IncludeBackUrl = a.GetApplication() == null ? 0 : (int)a.GetApplication().IncludeBackUrl,
         ClientAction = a is ClientAction && !string.IsNullOrEmpty(((ClientAction)a).Callback),
         Forbidden = a.Forbidden
     }));
 }
Exemple #26
0
        private string[] GetTopLevelNames(ODataRequest req)
        {
            var site = Node.Load <Site>(req.RepositoryPath);

            return(site.Children /*.Where(n => n is IFolder)*/.Select(n => n.Name).ToArray());
        }