예제 #1
0
        public void PredicationEngine_Deleted()
        {
            Test(() =>
            {
                var testNode = new SystemFolder(Repository.Root)
                {
                    Name = "TestRoot"
                };
                testNode.Save();
                testNode.ForceDelete();

                var testContent = testNode.Content ?? Content.Create(testNode);
                var prE         = new PredicationEngine(testContent);

                Assert.IsTrue(prE.IsTrue("Name:TestRoot"));
            });
        }
        /// <inheritdoc/>
        public IEnumerable <WebHookSubscriptionInfo> GetRelevantSubscriptions(ISnEvent snEvent)
        {
            //TODO: implement a subscription cache that is invalidated when a subscription changes
            // Do NOT cache nodes, their data is already cached. Cache only ids, paths, or trees.

            List <WebHookSubscriptionInfo> allSubs;

            // load subscriptions in elevated mode because this is a system feature
            using (new SystemAccount())
            {
                // ReSharper disable once RedundantBoolCompare
                allSubs = Content.All.DisableAutofilters().Where(c =>
                                                                 c.InTree("/Root/System/WebHooks") &&
                                                                 c.ContentHandler is WebHookSubscription &&
                                                                 (bool)c["Enabled"] == true)
                          .AsEnumerable()
                          .Select(c => (WebHookSubscription)c.ContentHandler)
                          .SelectMany(sub =>
                {
                    // prefilter: check if this event is relevant for the subscription
                    var eventTypes = sub.GetRelevantEventTypes(snEvent);

                    // handle multiple relevant event types by adding the subscription multiple times
                    return(eventTypes.Select(et => new WebHookSubscriptionInfo(sub, et)));
                })
                          .Where(si => si != null && si.Subscription.IsValid)
                          .ToList();
            }

            if (!allSubs.Any())
            {
                return(Array.Empty <WebHookSubscriptionInfo>());
            }

            // use the already constructed Content instance if possible
            var content = snEvent.NodeEventArgs.SourceNode is GenericContent gc
                ? gc.Content
                : Content.Create(snEvent.NodeEventArgs.SourceNode);

            // filter by the query defined by the subscriber
            var pe = new PredicationEngine(content);

            return(allSubs.Where(sub => pe.IsTrue(sub.Subscription.FilterQuery)).ToList());
        }
예제 #3
0
        public void PredicationEngine_TypeIs()
        {
            Test(() =>
            {
                var root = new SystemFolder(Repository.Root)
                {
                    Name = "TestRoot"
                }; root.Save();

                // CASE 1
                var prE = new PredicationEngine(Content.Load("/Root/TestRoot"));
                Assert.IsTrue(prE.IsTrue("+TypeIs:SystemFolder"));
                Assert.IsTrue(prE.IsTrue("+TypeIs:Folder"));
                Assert.IsTrue(prE.IsTrue("+TypeIs:GenericContent"));

                // CASE 2
                prE = new PredicationEngine(Content.Load("/Root/Content"));
                Assert.IsTrue(prE.IsTrue("+TypeIs:Workspace"));
                Assert.IsTrue(prE.IsTrue("+TypeIs:Folder"));
                Assert.IsTrue(prE.IsTrue("+TypeIs:GenericContent"));
            });
        }
예제 #4
0
        public void PredicationEngine_Errors()
        {
            void AssertError(PredicationEngine prE, string predication, Type exceptionType)
            {
                try
                {
                    prE.IsTrue(predication);
                    Assert.Fail($"{exceptionType.Namespace} was not thrown.");
                }
                catch (Exception e)
                {
                    if (e.GetType() != exceptionType)
                    {
                        Assert.Fail($"{e.GetType().Name} was thrown. Expected: {exceptionType.Name}.");
                    }
                }
            }

            Test(() =>
            {
                ContentTypeInstaller.InstallContentType(CTD);
                var root = new SystemFolder(Repository.Root)
                {
                    Name = "TestRoot"
                }; root.Save();
                var content          = Content.CreateNew("PredicationEngineTestNode", root, "PredicationEngineTestNode1");
                content.Index        = 42;
                content["Currency1"] = 42.42;
                content["DateTime1"] = new DateTime(1234, 5, 6);
                content.Save();

                var prE = new PredicationEngine(content);

                // equality
                AssertError(prE, "Name:a?b", typeof(NotSupportedException)); // The '?' wildcard is not allowed
                AssertError(prE, "Name:*", typeof(NotSupportedException));   // The only one '*' is not allowed;
            });
        }
예제 #5
0
        public void PredicationEngine_InTree()
        {
            Test(() =>
            {
                ContentTypeInstaller.InstallContentType(CTD);
                var root = new SystemFolder(Repository.Root)
                {
                    Name = "TestRoot"
                }; root.Save();
                var content          = Content.CreateNew("PredicationEngineTestNode", root, "TestNode1");
                content.Index        = 42;
                content["DateTime1"] = new DateTime(1234, 5, 6);
                content["Currency1"] = 42.42;
                content.Save();

                // CASE 1
                var prE = new PredicationEngine(Content.Load("/Root/TestRoot/TestNode1"));
                Assert.IsTrue(prE.IsTrue("+InTree:/Root/TestRoot/TestNode1"));
                Assert.IsFalse(prE.IsTrue("+InTree:/Root/Content"));
                Assert.IsTrue(prE.IsTrue("+InTree:/Root/TestRoot"));
                Assert.IsTrue(prE.IsTrue("+InTree:/Root"));

                // CASE 2
                prE = new PredicationEngine(Content.Load("/Root/TestRoot"));
                Assert.IsFalse(prE.IsTrue("+InTree:/Root/TestRoot/TestNode1"));
                Assert.IsFalse(prE.IsTrue("+InTree:/Root/Content"));
                Assert.IsTrue(prE.IsTrue("+InTree:/Root/TestRoot"));
                Assert.IsTrue(prE.IsTrue("+InTree:/Root"));

                // CASE 3
                prE = new PredicationEngine(Content.Load("/Root"));
                Assert.IsFalse(prE.IsTrue("+InTree:/Root/TestRoot/TestNode1"));
                Assert.IsFalse(prE.IsTrue("+InTree:/Root/Content"));
                Assert.IsFalse(prE.IsTrue("+InTree:/Root/TestRoot"));
                Assert.IsTrue(prE.IsTrue("+InTree:/Root"));
            });
        }
예제 #6
0
        public IEnumerable <WebHookSubscriptionInfo> GetRelevantSubscriptions(ISnEvent snEvent)
        {
            var node = snEvent.NodeEventArgs.SourceNode;

            if (node == null)
            {
                return(Array.Empty <WebHookSubscriptionInfo>());
            }

            var pe = new PredicationEngine(Content.Create(node));

            // filter the hardcoded subscription list: return the ones that
            // match the current content
            return(Subscriptions.SelectMany(sub =>
            {
                var eventTypes = sub.GetRelevantEventTypes(snEvent);

                // handle multiple relevant event types by adding the subscription multiple times
                return eventTypes.Select(et => new WebHookSubscriptionInfo(sub, et));
            }).Where(si => si != null &&
                     pe.IsTrue(si.Subscription.FilterQuery) &&
                     si.Subscription.Enabled &&
                     si.Subscription.IsValid));
        }
예제 #7
0
        public void PredicationEngine_Predication()
        {
            Test(() =>
            {
                ContentTypeInstaller.InstallContentType(CTD);
                var root = new SystemFolder(Repository.Root)
                {
                    Name = "TestRoot"
                }; root.Save();
                var content          = Content.CreateNew("PredicationEngineTestNode", root, "PredicationEngineTestNode1");
                content.Index        = 42;
                content["DateTime1"] = new DateTime(1234, 5, 6);
                content["Currency1"] = 42.42;
                content.Save();

                var prE = new PredicationEngine(content);

                // equality
                Assert.IsTrue(prE.IsTrue("+Name:predicationENGINEtestnode1"));
                Assert.IsFalse(prE.IsTrue("-Name:predicationENGINEtestnode1"));
                Assert.IsFalse(prE.IsTrue("+Name:anothername"));
                Assert.IsTrue(prE.IsTrue("+Index:42"));
                Assert.IsFalse(prE.IsTrue("-Index:42"));
                Assert.IsFalse(prE.IsTrue("+Index:41"));
                Assert.IsFalse(prE.IsTrue("+Index:43"));
                Assert.IsTrue(prE.IsTrue("-Index:43")); // different from ContentQuery
                Assert.IsTrue(prE.IsTrue("+DateTime1:'1234-05-06'"));
                Assert.IsFalse(prE.IsTrue("-DateTime1:'1234-05-06'"));
                Assert.IsFalse(prE.IsTrue("+DateTime1:'1234-05-05'"));
                Assert.IsTrue(prE.IsTrue("-DateTime1:'1234-05-05'")); // different from ContentQuery
                Assert.IsFalse(prE.IsTrue("+DateTime1:'1234-05-07'"));
                Assert.IsTrue(prE.IsTrue("+Currency1:42.42"));
                Assert.IsFalse(prE.IsTrue("-Currency1:42.42"));
                Assert.IsFalse(prE.IsTrue("+Currency1:42.41"));
                Assert.IsFalse(prE.IsTrue("+Currency1:42.43"));
                Assert.IsTrue(prE.IsTrue("+IsSystemContent:yes"));
                Assert.IsFalse(prE.IsTrue("+IsSystemContent:no"));

                // wildcard
                Assert.IsTrue(prE.IsTrue("+Name:*engine*"));
                Assert.IsFalse(prE.IsTrue("+Name:*Molokai*"));
                Assert.IsTrue(prE.IsTrue("+Name:*testnode1"));
                Assert.IsFalse(prE.IsTrue("+Name:*Oahu"));
                Assert.IsTrue(prE.IsTrue("+Name:predication*"));
                Assert.IsFalse(prE.IsTrue("+Name:Kauai*"));
                Assert.IsTrue(prE.IsTrue("+Name:predication*testnode1"));
                Assert.IsFalse(prE.IsTrue("+Name:Maui*Lanai"));

                // basic range
                Assert.IsTrue(prE.IsTrue("+Index:>41"));
                Assert.IsFalse(prE.IsTrue("+Index:>42"));
                Assert.IsFalse(prE.IsTrue("+Index:<42"));
                Assert.IsTrue(prE.IsTrue("+Index:<43"));
                Assert.IsTrue(prE.IsTrue("+Index:>=41"));
                Assert.IsTrue(prE.IsTrue("+Index:>=42"));
                Assert.IsTrue(prE.IsTrue("+Index:<=42"));
                Assert.IsTrue(prE.IsTrue("+Index:<=43"));
                Assert.IsTrue(prE.IsTrue("+DateTime1:>'1234-05-05'"));
                Assert.IsTrue(prE.IsTrue("+DateTime1:<'1234-05-07'"));
                Assert.IsTrue(prE.IsTrue("+DateTime1:>'999-05-07'"));
                Assert.IsTrue(prE.IsTrue("+Currency1:>42.41"));
                Assert.IsTrue(prE.IsTrue("+Currency1:<42.43"));
                Assert.IsTrue(prE.IsTrue("+Currency1:>9"));

                // extended range
                Assert.IsTrue(prE.IsTrue("+Index:[40 TO 44]"));
                Assert.IsTrue(prE.IsTrue("+Index:[40 TO 44}"));
                Assert.IsTrue(prE.IsTrue("+Index:{40 TO 44]"));
                Assert.IsTrue(prE.IsTrue("+Index:{40 TO 44}"));

                Assert.IsTrue(prE.IsTrue("+Index:[40 TO 42]"));
                Assert.IsFalse(prE.IsTrue("+Index:[40 TO 42}"));
                Assert.IsTrue(prE.IsTrue("+Index:{40 TO 42]"));
                Assert.IsFalse(prE.IsTrue("+Index:{40 TO 42}"));

                Assert.IsTrue(prE.IsTrue("+Index:[42 TO 44]"));
                Assert.IsTrue(prE.IsTrue("+Index:[42 TO 44}"));
                Assert.IsFalse(prE.IsTrue("+Index:{42 TO 44]"));
                Assert.IsFalse(prE.IsTrue("+Index:{42 TO 44}"));

                Assert.IsFalse(prE.IsTrue("+Index:[0 TO 40]"));
                Assert.IsFalse(prE.IsTrue("+Index:[0 TO 40}"));
                Assert.IsFalse(prE.IsTrue("+Index:{0 TO 40]"));
                Assert.IsFalse(prE.IsTrue("+Index:{0 TO 40}"));

                Assert.IsFalse(prE.IsTrue("+Index:[44 TO 50]"));
                Assert.IsFalse(prE.IsTrue("+Index:[44 TO 50}"));
                Assert.IsFalse(prE.IsTrue("+Index:{44 TO 50]"));
                Assert.IsFalse(prE.IsTrue("+Index:{44 TO 50}"));

                // complex (logical) predicates
                Assert.IsTrue(prE.IsTrue("-Index:41 -Index:43"));
                Assert.IsTrue(prE.IsTrue("-Index:41 +Index:42 -Index:43"));
                Assert.IsTrue(prE.IsTrue("Index:41 Index:42 Index:43"));
                Assert.IsFalse(prE.IsTrue("-(Index:41 Index:42 Index:43)")); // different from ContentQuery
                Assert.IsTrue(prE.IsTrue("-(+Index:41 +Index:42 +Index:43)"));
                Assert.IsTrue(prE.IsTrue("Index:(41 42 43)"));
                Assert.IsFalse(prE.IsTrue("-Index:(41 42 43)")); // different from ContentQuery
                Assert.IsTrue(prE.IsTrue("+DateTime1:'1234-05-06' +(Index:41 Index:42)"));
                Assert.IsFalse(prE.IsTrue("+DateTime1:'999-05-06' +(Index:41 Index:43)"));

                Assert.IsTrue(prE.IsTrue("DateTime1:'1234-05-06' AND (Index:41 OR Index:42)"));
                Assert.IsTrue(prE.IsTrue("Index:41 OR Index:42 OR Index:43"));

                Assert.IsTrue(prE.IsTrue("NOT Index:43")); // different from ContentQuery
                Assert.IsFalse(prE.IsTrue("NOT Index:42"));
                Assert.IsFalse(prE.IsTrue("(Index:41 AND Index:42 AND Index:43)"));
                Assert.IsTrue(prE.IsTrue("NOT (Index:41 AND Index:42 AND Index:43)")); // different from ContentQuery
            });
        }