public void Subscribers_to_a_single_page_do_not_get_escalated_by_a_subscriber_with_infinite_depth_on_same_page() { var mockDekiUri = new XUri("http://mock/deki"); var mockDeki = MockPlug.Register(mockDekiUri); mockDeki.Expect().Verb("GET").Uri(mockDekiUri.At("pages", "10")).Response(DreamMessage.Ok(new XDoc("page") .Attr("id", "10") .Start("page.parent") .Attr("id", "9") .Start("page.parent") .Attr("id", "8") .Start("page.parent") .Attr("id", "7") .EndAll())); var dispatcherUri = new XUri("http://mock/dispatcher"); var dispatcher = new DekiDispatcher(new DispatcherConfig { ServiceUri = dispatcherUri, ServiceAccessCookie = new DreamCookie("service-key", "foo", dispatcherUri), ServiceConfig = new XDoc("config").Elem("uri.deki", mockDekiUri).Elem("authtoken", "abc") }); var combinedSetUpdated = 0; dispatcher.CombinedSetUpdated += (o, e) => { combinedSetUpdated++; }; // subscribe to page 7 and all children var mockHierarchyRecipientUri = new XUri("http://mock/recipient/hierarchy"); var mockHierarchyRecipient = MockPlug.Register(mockHierarchyRecipientUri); mockHierarchyRecipient.Expect().Verb("POST"); dispatcher.RegisterSet(new XDoc("subscription-set") .Elem("uri.owner", mockHierarchyRecipientUri) .Start("subscription") .Attr("id", "3") .Elem("uri.resource", "deki://default/pages/7#depth=infinity") .Elem("channel", "event://default/deki/pages/*") .Start("recipient").Attr("authtoken", "abc").Elem("uri", mockHierarchyRecipientUri).End() .End()); // subscribe to only page 7 var mockPageonlyRecipientUri = new XUri("http://mock/recipient/pageonly"); var mockPageonlyRecipientCalled = 0; MockPlug.Register(mockPageonlyRecipientUri, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("mockPageonlyRecipient called at: {0}", u); mockPageonlyRecipientCalled++; r2.Return(DreamMessage.Ok()); }); dispatcher.RegisterSet(new XDoc("subscription-set") .Elem("uri.owner", mockPageonlyRecipientUri) .Start("subscription") .Attr("id", "3") .Elem("uri.resource", "deki://default/pages/7") .Elem("channel", "event://default/deki/pages/*") .Start("recipient").Attr("authtoken", "abc").Elem("uri", mockPageonlyRecipientUri).End() .End()); // wait for subscriptions to be set up _log.DebugFormat("wait for subscriptions to be updated"); Assert.IsTrue(Wait.For(() => combinedSetUpdated == 2, TimeSpan.FromSeconds(10)), "timeout waiting for subscriptions"); // fire page change for page 10 (sub-child of page 7) XDoc evDoc = new XDoc("deki-event") .Attr("wikiid", "default") .Elem("channel", "event://default/deki/pages/update") .Elem("uri", "deki://default/pages/10") .Elem("pageid", "10"); var ev = new DispatcherEvent(evDoc, new XUri("event://default/deki/pages/update"), new XUri("deki://default/pages/10"), new XUri("http://default/deki/pages/10")); _log.DebugFormat("ready to dispatch event"); dispatcher.Dispatch(ev); // wait for deki to have been called _log.DebugFormat("wait for deki call"); Assert.IsTrue(mockDeki.WaitAndVerify(TimeSpan.FromSeconds(10)), mockDeki.VerificationFailure); // wait for recipients to be notified _log.DebugFormat("wait for hierarchy notification"); Assert.IsTrue(mockHierarchyRecipient.WaitAndVerify(TimeSpan.FromSeconds(10)), mockHierarchyRecipient.VerificationFailure); // only 'hierarchy' subscriber should have been notified _log.DebugFormat("make sure page only doesn't get called"); Assert.IsFalse(Wait.For(() => mockPageonlyRecipientCalled > 0, TimeSpan.FromSeconds(5))); }
public void Page_events_uses_deki_to_check_parent_wildcard_resource_matches() { var dekiPageAuthEvent = new ManualResetEvent(false); var authorizedRecipientCalledEv = new ManualResetEvent(false); var mockMatchCalledEv = new ManualResetEvent(false); var mockWildcardCalledEv = new ManualResetEvent(false); XUri mockDeki = new XUri("http://mock/deki"); int dekiPageAuthCalled = 0; int dekiPageCalled = 0; MockPlug.Register(mockDeki, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { XDoc rDoc = null; _log.DebugFormat("mockDeki called at: {0}", u); if(u.Segments.Length == 3) { _log.DebugFormat("getting page xml"); if(u.LastSegment == "10") { dekiPageCalled++; } rDoc = new XDoc("page") .Attr("id", "10") .Start("page.parent") .Attr("id", "9") .Start("page.parent") .Attr("id", "8") .Start("page.parent") .Attr("id", "7") .EndAll(); } else { _log.DebugFormat("getting users for page: {0}", u.LastSegment); dekiPageAuthCalled++; rDoc = new XDoc("users"); foreach(XDoc user in r.ToDocument()["user/@id"]) { rDoc.Start("user").Attr("id", user.AsText).End(); } if(dekiPageAuthCalled == 2) { dekiPageAuthEvent.Set(); } } r2.Return(DreamMessage.Ok(rDoc)); }); XUri authorizedRecipient = new XUri("http://mock/authorized2"); int authorizedRecipientCalled = 0; XDoc authorizedReceived = null; MockPlug.Register(authorizedRecipient, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("authorizedRecipient called at: {0}", u); authorizedRecipientCalled++; authorizedReceived = r.ToDocument(); authorizedRecipientCalledEv.Set(); r2.Return(DreamMessage.Ok()); }); XUri mockRecipient = new XUri("http://mock/r1"); int mockRecipientCalled = 0; int mockMatchCalled = 0; int mockWildcardCalled = 0; MockPlug.Register(mockRecipient, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("mockRecipient called at: {0}", u); mockRecipientCalled++; if(u == mockRecipient.At("match")) { mockMatchCalled++; mockMatchCalledEv.Set(); } else if(u == mockRecipient.At("wildcard")) { mockWildcardCalled++; mockWildcardCalledEv.Set(); } r2.Return(DreamMessage.Ok()); }); XUri dispatcherUri = new XUri("http://mock/dispatcher"); DekiDispatcher dispatcher = new DekiDispatcher(new DispatcherConfig() { ServiceUri = dispatcherUri, ServiceAccessCookie = new DreamCookie("service-key", "foo", dispatcherUri), ServiceConfig = new XDoc("config").Elem("uri.deki", mockDeki).Elem("authtoken", "abc") }); XDoc sub1 = new XDoc("subscription-set") .Elem("uri.owner", authorizedRecipient) .Start("subscription") .Attr("id", "1") .Elem("channel", "event://default/deki/pages/*") .Start("recipient").Attr("authtoken", "abc").Elem("uri", authorizedRecipient).End() .End(); _log.DebugFormat("registering sub set 1"); dispatcher.RegisterSet(sub1); Assert.IsTrue(Wait.For(() => { Thread.Sleep(50); return dispatcher.CombinedSet.Subscriptions .Where(s => s.Channels.Where(c => c.ToString() == "event://default/deki/pages/*").Any() && !s.Resources.Any() ).Any(); }, 10.Seconds())); XDoc sub2 = new XDoc("subscription-set") .Elem("uri.owner", mockRecipient.At("1")) .Start("subscription") .Attr("id", "1") .Elem("uri.resource", "deki://default/pages/10") .Elem("channel", "event://default/deki/pages/*") .Start("recipient").Attr("userid", "1").Elem("uri", "http://mock/r1/match").End() .End(); _log.DebugFormat("registering sub set 2"); dispatcher.RegisterSet(sub2); Assert.IsTrue(Wait.For(() => { Thread.Sleep(50); return dispatcher.CombinedSet.Subscriptions .Where(s => s.Channels.Where(c => c.ToString() == "event://default/deki/pages/*").Any() && s.Resources.Where(r => r.ToString() == "deki://default/pages/10").Any() ).Any(); }, 10.Seconds())); XDoc sub3 = new XDoc("subscription-set") .Elem("uri.owner", mockRecipient.At("2")) .Start("subscription") .Attr("id", "2") .Elem("uri.resource", "deki://default/pages/11") .Elem("channel", "event://default/deki/pages/*") .Start("recipient").Attr("userid", "1").Elem("uri", "http://mock/r1/miss").End() .End(); _log.DebugFormat("registering sub set 3"); dispatcher.RegisterSet(sub3); Assert.IsTrue(Wait.For(() => { Thread.Sleep(50); return dispatcher.CombinedSet.Subscriptions .Where(s => s.Channels.Where(c => c.ToString() == "event://default/deki/pages/*").Any() && s.Resources.Where(r => r.ToString() == "deki://default/pages/11").Any() ).Any(); }, 10.Seconds())); XDoc sub4 = new XDoc("subscription-set") .Elem("uri.owner", mockRecipient.At("3")) .Start("subscription") .Attr("id", "3") .Elem("uri.resource", "deki://default/pages/8#depth=infinity") .Elem("channel", "event://default/deki/pages/*") .Start("recipient").Attr("userid", "1").Elem("uri", "http://mock/r1/wildcard").End() .End(); _log.DebugFormat("registering sub set 4"); dispatcher.RegisterSet(sub4); Assert.IsTrue(Wait.For(() => { Thread.Sleep(50); return dispatcher.CombinedSet.Subscriptions .Where(s => s.Channels.Where(c => c.ToString() == "event://default/deki/pages/*").Any() && s.Resources.Where(r => r.ToString() == "deki://default/pages/8#depth%3dinfinity").Any() ).Any(); }, 10.Seconds())); XDoc evDoc = new XDoc("deki-event") .Attr("wikiid", "default") .Elem("channel", "event://default/deki/pages/update") .Elem("uri", "deki://default/pages/10") .Elem("pageid", "10"); var ev = new DispatcherEvent(evDoc, new XUri("event://default/deki/pages/update"), new XUri("deki://default/pages/10"), new XUri("http://default/deki/pages/10")); _log.DebugFormat("ready to dispatch event"); dispatcher.Dispatch(ev); Assert.IsTrue(dekiPageAuthEvent.WaitOne(5000, true)); Assert.IsTrue(authorizedRecipientCalledEv.WaitOne(5000, true)); Assert.IsTrue(mockMatchCalledEv.WaitOne(5000, true)); Assert.IsTrue(mockWildcardCalledEv.WaitOne(5000, true)); Assert.AreEqual(1, dekiPageCalled); Assert.AreEqual(2, dekiPageAuthCalled); Assert.AreEqual(1, authorizedRecipientCalled); Assert.AreEqual(2, mockRecipientCalled); Assert.AreEqual(1, mockMatchCalled); Assert.AreEqual(1, mockWildcardCalled); Assert.AreEqual(evDoc, authorizedReceived); }
public void Page_delete_events_skip_page_auth() { XUri mockDeki = new XUri("http://mock/deki"); int dekiCalled = 0; MockPlug.Register(mockDeki, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("mockDeki called at: {0}", u); dekiCalled++; r2.Return(DreamMessage.BadRequest("shouldn't have called deki")); }); XUri authorizedRecipient = new XUri("http://mock/authorized2"); AutoResetEvent authorizedResetEvent = new AutoResetEvent(false); XDoc authorizedReceived = null; MockPlug.Register(authorizedRecipient, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("authorizedRecipient called at: {0}", u); authorizedReceived = r.ToDocument(); authorizedResetEvent.Set(); r2.Return(DreamMessage.Ok()); }); XUri mockRecipient = new XUri("http://mock/r1"); int mockRecipientCalled = 0; MockPlug.Register(mockRecipient, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("mockRecipient called at: {0}", u); mockRecipientCalled++; r2.Return(DreamMessage.Ok()); }); XUri dispatcherUri = new XUri("http://mock/dispatcher"); DekiDispatcher dispatcher = new DekiDispatcher(new DispatcherConfig { ServiceUri = dispatcherUri, ServiceAccessCookie = new DreamCookie("service-key", "foo", dispatcherUri), ServiceConfig = new XDoc("config").Elem("uri.deki", mockDeki).Elem("authtoken", "abc") }); XDoc sub1 = new XDoc("subscription-set") .Elem("uri.owner", authorizedRecipient) .Start("subscription") .Attr("id", "1") .Elem("channel", "event://default/deki/pages/*") .Start("recipient").Attr("authtoken", "abc").Elem("uri", authorizedRecipient).End() .End(); Thread.Sleep(100); _log.DebugFormat("registering sub set 1"); dispatcher.RegisterSet(sub1); XDoc sub2 = new XDoc("subscription-set") .Elem("uri.owner", mockRecipient.At("1")) .Start("subscription") .Attr("id", "1") .Elem("uri.resource", "deki://default/pages/10") .Elem("channel", "event://default/deki/pages/*") .Start("recipient").Attr("userid", "1").Elem("uri", "http://mock/r1/match").End() .End(); Thread.Sleep(100); _log.DebugFormat("registering sub set 2"); dispatcher.RegisterSet(sub2); XDoc evDoc = new XDoc("deki-event") .Attr("wikiid", "default") .Elem("channel", "event://default/deki/pages/delete") .Elem("uri", "deki://default/pages/10") .Elem("pageid", "10"); var ev = new DispatcherEvent(evDoc, new XUri("event://default/deki/pages/delete"), new XUri("deki://default/pages/10"), new XUri("http://default/deki/pages/10")); _log.DebugFormat("ready to dispatch event"); // Meh. Testing multithreaded code is wonky. This 1000ms sleep is required, otherwise the event below never fires Thread.Sleep(1000); dispatcher.Dispatch(ev); // since we're waiting for more than one dekiPageAuthEvent, we give it a chance to finish after the first triggers Assert.IsTrue(authorizedResetEvent.WaitOne(5000, false)); Assert.AreEqual(0, dekiCalled); Assert.AreEqual(0, mockRecipientCalled); Assert.AreEqual(evDoc, authorizedReceived); }
public void InstanceKey_authtoken_gets_verified_against_deki() { var mockDeki = new XUri("http://mock/deki"); var dispatcherUri = new XUri("http://mock/dispatcher"); var authorizedRecipient = new XUri("http://mock/authorized"); var dispatcher = new DekiDispatcher( new DispatcherConfig { ServiceUri = dispatcherUri, ServiceAccessCookie = new DreamCookie("service-key", "foo", dispatcherUri), ServiceConfig = new XDoc("config").Elem("uri.deki", mockDeki).Elem("authtoken", "abc") }, _mockRepository.Object ); var sub = new XDoc("subscription-set") .Elem("uri.owner", authorizedRecipient) .Start("subscription") .Attr("id", "1") .Elem("channel", "event://default/deki/pages/*") .Start("recipient").Attr("authtoken", "def").Elem("uri", authorizedRecipient).End() .End(); _log.DebugFormat("registering sub set"); dispatcher.RegisterSet("abc", sub, "def"); Assert.IsTrue(Wait.For( () => dispatcher.CombinedSet.Subscriptions .Where(s => s.Channels.Where(c => c.ToString() == "event://default/deki/pages/*").Any() && !s.Resources.Any() ).Any(), 10.Seconds())); MockPlug.Setup(mockDeki) .Verb("GET") .At("site", "settings") .With("apikey", "abc") .WithHeader("X-Deki-Site", "id=default") .Returns(new XDoc("config").Start("security").Elem("api-key", "def").End()) .ExpectCalls(Times.Once()); MockPlug.Setup(authorizedRecipient) .Verb("POST") .WithMessage(r => { if(!r.HasDocument) { return false; } var doc = r.ToDocument(); _log.Debug(doc.ToPrettyString()); return doc["channel"].AsText == "event://default/deki/pages/update" && doc["pageid"].AsText == "10"; }) .ExpectCalls(Times.Once()); var evDoc = new XDoc("deki-event") .Attr("wikiid", "default") .Elem("channel", "event://default/deki/pages/update") .Elem("uri", "deki://default/pages/10") .Elem("pageid", "10"); var ev = new DispatcherEvent(evDoc, new XUri("event://default/deki/pages/update"), new XUri("deki://default/pages/10"), new XUri("http://default/deki/pages/10")); _log.DebugFormat("ready to dispatch event"); dispatcher.Dispatch(ev); MockPlug.VerifyAll(TimeSpan.FromSeconds(10)); }