public void ExportManager_chains_exporter_to_packager() { // Arrange XUri dekiApiUri = new XUri("http://mock/@api/deki"); XDoc exportDocument = new XDoc("export"); XUri item1Uri = dekiApiUri.At("foo", "bar", "abc"); XDoc item1Doc = new XDoc("item1"); XUri item2Uri = dekiApiUri.At("foo", "bar", "def"); XDoc item2Doc = new XDoc("item2"); XDoc exportResponse = new XDoc("export") .Start("requests") .Start("request") .Attr("method", "GET") .Attr("dataid", "abc") .Attr("href", item1Uri) .Start("header").Attr("name", "h_1").Attr("value", "v_1").End() .Start("header").Attr("name", "h_2").Attr("value", "v_2").End() .End() .Start("request") .Attr("method", "GET") .Attr("dataid", "def") .Attr("href", item2Uri) .End() .End() .Start("manifest") .Start("foo").Attr("dataid", "abc").End() .Start("bar").Attr("dataid", "def").End() .End(); AutoMockPlug mock = MockPlug.Register(dekiApiUri); mock.Expect().Verb("POST").Uri(dekiApiUri.At("site", "export").With("relto", "0")).RequestDocument(exportDocument).Response(DreamMessage.Ok(exportResponse)); mock.Expect().Verb("GET").Uri(item1Uri).RequestHeader("h_1", "v_1").RequestHeader("h_2", "v_2").Response(DreamMessage.Ok(item1Doc)); mock.Expect().Verb("GET").Uri(item2Uri).Response(DreamMessage.Ok(item2Doc)); var writes = new List<string>(); var mockPackageWriter = new Mock<IPackageWriter>(); mockPackageWriter.Setup(x => x.WriteDataAsync(It.IsAny<ExportItem>(), It.IsAny<Result>())) .Returns(() => new Result().WithReturn()) .Callback((ExportItem item, Result result) => writes.Add(item.DataId)) .AtMost(2) .Verifiable(); mockPackageWriter.Setup(x => x.WriteManifest(It.IsAny<XDoc>(), It.IsAny<Result>())) .Returns(() => new Result().WithReturn()) .AtMostOnce() .Verifiable(); // Act ExportManager manager = ExportManager.CreateAsync(Plug.New(dekiApiUri), exportDocument, 0, mockPackageWriter.Object, new Result<ExportManager>()).Wait(); manager.ExportAsync(new Result()).Wait(); // Assert Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1)), mock.VerificationFailure); Assert.AreEqual(2, manager.TotalItems); Assert.AreEqual(2, manager.CompletedItems); Assert.AreEqual(new[] { "abc", "def" }, writes.ToArray()); mockPackageWriter.Verify(x => x.Dispose(), Times.Once()); mockPackageWriter.VerifyAll(); }
public void Exporter_hits_export_feature_on_creation_using_relto() { // Arrange XUri dekiApiUri = new XUri("http://mock/@api/deki"); XDoc exportDocument = new XDoc("export") .Start("page") .Attr("path", "/") .Attr("recursive", "true") .Attr("exclude", "all") .End(); XDoc exportResponse = new XDoc("export") .Start("requests") .End() .Start("manifest") .Elem("justanode") .End(); AutoMockPlug mock = MockPlug.Register(dekiApiUri); mock.Expect("POST", dekiApiUri.At("site", "export").With("relto", 5.ToString()), exportDocument, DreamMessage.Ok(exportResponse)); // Act Exporter exporter = Exporter.CreateAsync(Plug.New(dekiApiUri), exportDocument, 5, new Result<Exporter>()).Wait(); //Assert Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1))); Assert.AreEqual(exportResponse["manifest"], exporter.Manifest); }
public void ImportManager_chains_reader_to_importer() { // Arrange var dekiApiUri = new XUri("http://mock/@api/deki"); var importManifest = new XDoc("manifest"); var item1Uri = dekiApiUri.At("foo", "bar", "abc"); var item1Doc = new XDoc("item1"); var item2Uri = dekiApiUri.At("foo", "bar", "def"); var item2Doc = new XDoc("item2"); var importResponse = new XDoc("requests") .Start("request") .Attr("method", "POST") .Attr("dataid", "abc") .Attr("href", item1Uri) .Start("header").Attr("name", "h_1").Attr("value", "v_1").End() .Start("header").Attr("name", "h_2").Attr("value", "v_2").End() .End() .Start("request") .Attr("method", "PUT") .Attr("dataid", "def") .Attr("href", item2Uri) .End(); var mock = MockPlug.Register(dekiApiUri); mock.Expect().Verb("POST").Uri(dekiApiUri.At("site", "import").With("relto", "0")).RequestDocument(importManifest).Response(DreamMessage.Ok(importResponse)); mock.Expect().Verb("POST").Uri(item1Uri).RequestHeader("h_1", "v_1").RequestHeader("h_2", "v_2").RequestDocument(item1Doc); mock.Expect().Verb("PUT").Uri(item2Uri).RequestDocument(item2Doc); var mockPackageReader = new Mock<IPackageReader>(); mockPackageReader.Setup(x => x.ReadManifest(It.IsAny<Result<XDoc>>())).Returns(importManifest.AsResult()).Verifiable("didn't get manifest"); var item1stream = new MemoryStream(item1Doc.ToBytes()); mockPackageReader.Setup(x => x.ReadData(It.Is<ImportItem>(y => y.DataId == "abc"), It.IsAny<Result<ImportItem>>())) .Returns(() => new ImportItem("abc", importResponse["request[@dataid='abc']"], null, item1stream, item1stream.Length).AsResult()) .Verifiable(); var item2stream = new MemoryStream(item2Doc.ToBytes()); mockPackageReader.Setup(x => x.ReadData(It.Is<ImportItem>(y => y.DataId == "def"), It.IsAny<Result<ImportItem>>())) .Returns(() => new ImportItem("def", importResponse["request[@dataid='def']"], null, item2stream, item2stream.Length).AsResult()) .Verifiable(); mockPackageReader.Setup(x => x.Dispose()).Verifiable(); // Act var manager = ImportManager.CreateAsync(Plug.New(dekiApiUri), 0, mockPackageReader.Object, new Result<ImportManager>()).Wait(); manager.ImportAsync(new Result()).Wait(); //Assert Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1)), mock.VerificationFailure); mockPackageReader.VerifyAll(); }
public void Importer_hits_import_feature_with_reltopath() { // Arrange XUri dekiApiUri = new XUri("http://mock/@api/deki"); XDoc importManifest = new XDoc("manifest"); XDoc importResponse = new XDoc("requests") .Start("request").Attr("dataid", "a").End() .Start("request").Attr("dataid", "b").End() .Start("request").Attr("dataid", "c").End(); AutoMockPlug mock = MockPlug.Register(dekiApiUri); mock.Expect("POST", dekiApiUri.At("site", "import").With("reltopath", "/foo/bar"), importManifest, DreamMessage.Ok(importResponse)); // Act Importer importer = Importer.CreateAsync(Plug.New(dekiApiUri), importManifest, "/foo/bar", new Result<Importer>()).Wait(); //Assert Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1))); Assert.AreEqual(importManifest, importer.Manifest); Assert.AreEqual(new[] { "a", "b", "c" }, importer.Items.Select(x => x.DataId).ToArray()); }
public static XDoc GetUserXml(UserBE user, string relation, bool showPrivateInfo) { XDoc userXml = new XDoc(string.IsNullOrEmpty(relation) ? "user" : "user." + relation); userXml.Attr("id", user.ID); userXml.Attr("href", DekiContext.Current.ApiUri.At("users", user.ID.ToString())); userXml.Elem("nick", user.Name); userXml.Elem("username", user.Name); userXml.Elem("fullname", user.RealName ?? String.Empty); // check if we can add the email address if(showPrivateInfo) { userXml.Elem("email", user.Email); } else { userXml.Start("email").Attr("hidden", true).End(); } // add gravatar if(!IsAnonymous(user) && !string.IsNullOrEmpty(user.Email)) { DekiContext context = DekiContext.CurrentOrNull; XUri gravatar = new XUri("http://www.gravatar.com/avatar"); string hash = string.Empty; if(context != null) { DekiInstance deki = context.Instance; string secure = context.Instance.GravatarSalt ?? string.Empty; if(!secure.EqualsInvariantIgnoreCase("hidden")) { hash = StringUtil.ComputeHashString(secure + (user.Email ?? string.Empty).Trim().ToLowerInvariant(), System.Text.Encoding.UTF8); } // add size, if any string size = deki.GravatarSize; if(size != null) { gravatar = gravatar.With("s", size); } // add rating, if any string rating = deki.GravatarRating; if(rating != null) { gravatar = gravatar.With("r", rating); } // add default icon, if any string def = deki.GravatarDefault; if(def != null) { gravatar = gravatar.With("d", def); } } if(!string.IsNullOrEmpty(hash)) { userXml.Elem("hash.email", hash); userXml.Elem("uri.gravatar", gravatar.At(hash + ".png")); } else { userXml.Elem("hash.email", string.Empty); userXml.Elem("uri.gravatar", gravatar.At("no-email.png")); } } return userXml; }
internal Hashtable MakeUserObject(UserBE user) { // initialize gravatar link DekiInstance deki = DekiContext.Current.Instance; XUri gravatar = new XUri("http://www.gravatar.com/avatar"); // add size, if any string size = deki.GravatarSize; if(size != null) { gravatar = gravatar.With("s", size); } // add rating, if any string rating = deki.GravatarRating; if(rating != null) { gravatar = gravatar.With("r", rating); } // add default icon, if any string def = deki.GravatarDefault; if(def != null) { gravatar = gravatar.With("d", def); } // initialize user object Hashtable result = new Hashtable(StringComparer.OrdinalIgnoreCase); string hash = string.Empty; if(user != null) { var env = DreamContext.Current.GetState<DekiScriptEnv>(); string secure = deki.GravatarSalt ?? string.Empty; if(!secure.EqualsInvariantIgnoreCase("hidden") && !string.IsNullOrEmpty(user.Email)) { hash = StringUtil.ComputeHashString(secure + (user.Email ?? string.Empty).Trim().ToLowerInvariant(), Encoding.UTF8); } PageBE homePage = UserBL.GetHomePage(user); result.Add("id", user.ID); result.Add("name", user.Name); result.Add("fullname", !string.IsNullOrEmpty(user.RealName) ? user.RealName : null); result.Add("uri", Utils.AsPublicUiUri(homePage.Title)); result.Add("api", Utils.AsPublicApiUri("users", user.ID).ToString()); result.Add("homepage", PropertyAt("$page", homePage.ID, true)); result.Add("anonymous", UserBL.IsAnonymous(user)); result.Add("admin", PermissionsBL.IsUserAllowed(user, Permissions.ADMIN)); result.Add("feed", Utils.AsPublicApiUri("users", user.ID).At("feed").ToString()); result.Add("authtoken", (!env.IsSafeMode && DekiContext.Current.User.ID == user.ID) ? DekiContext.Current.AuthToken : null); result.Add("properties", PropertyAt("$userprops", user.ID)); result.Add("comments", PropertyAt("$usercomments", user.ID)); result.Add("timezone", DekiScriptLibrary.RenderTimeZone(DekiScriptLibrary.ParseTimeZone(user.Timezone))); result.Add("language", DekiScriptExpression.Constant(string.IsNullOrEmpty(user.Language) ? null : user.Language)); result.Add("metrics", PropertyAt("$usermetrics", user.ID)); if(Utils.ShowPrivateUserInfo(user)) { result.Add("email", user.Email); } result.Add("groups", PropertyAt("$usergroups", user.ID)); } else { result.Add("id", 0); result.Add("name", null); result.Add("fullname", null); result.Add("uri", null); result.Add("api", null); result.Add("homepage", null); result.Add("anonymous", true); result.Add("admin", false); result.Add("feed", null); result.Add("authtoken", null); result.Add("properties", new Hashtable(StringComparer.OrdinalIgnoreCase)); result.Add("comments", new ArrayList()); result.Add("timezone", "GMT"); result.Add("language", DekiScriptNil.Value); result.Add("metrics", new Hashtable(StringComparer.OrdinalIgnoreCase)); result.Add("groups", new Hashtable(StringComparer.OrdinalIgnoreCase)); } // set the emailhash and gravatar values if(!string.IsNullOrEmpty(hash)) { result.Add("emailhash", hash); result.Add("gravatar", gravatar.At(hash + ".png")); } else { result.Add("emailhash", string.Empty); result.Add("gravatar", gravatar.At("no-email.png")); } return result; }
private XDoc GetPropertyXml(IList<ResourceBE> properties, XUri parentResourceUri, bool collection, string propSuffix, bool? explicitRevisionInfo, uint? contentCutoff, XDoc doc) { bool requiresEnd = false; if(collection) { string rootPropertiesNode = string.IsNullOrEmpty(propSuffix) ? "properties" : "properties." + propSuffix; if(doc == null) { doc = new XDoc(rootPropertiesNode); } else { doc.Start(rootPropertiesNode); requiresEnd = true; } doc.Attr("count", properties.Count); if(parentResourceUri != null) { //Note: this assumes that the property collection of a resource is always accessed by appending "properties" to the parent URI doc.Attr("href", parentResourceUri.At("properties")); } } else { doc = XDoc.Empty; } //Batch retrieve users for user.modified and user.deleted Dictionary<uint, UserBE> usersById = new Dictionary<uint, UserBE>(); foreach(ResourceBE r in properties) { usersById[r.UserId] = null; } if(!ArrayUtil.IsNullOrEmpty(properties)) { usersById = DbUtils.CurrentSession.Users_GetByIds(usersById.Keys.ToArray()).AsHash(e => e.ID); } foreach(ResourceBE p in properties) { doc = AppendPropertyXml(doc, p, parentResourceUri, propSuffix, explicitRevisionInfo, contentCutoff, usersById); } if(requiresEnd) { doc.End(); } return doc; }
//--- Methods --- public XUri Uri(XUri parentUri) { return parentUri.At("properties", XUri.DoubleEncodeSegment(Name)); }
public void User_without_proper_page_permission_gets_forbidden_on_subscribe_attempt() { // set up mocks for all the support service calls XUri deki = new XUri("http://mock/deki"); MockPlug.Register(deki, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("deki: {0}", u); DreamMessage msg; if(u.Path.StartsWith("/deki/pages")) { msg = DreamMessage.Ok(new XDoc("users")); } else { msg = DreamMessage.Ok(new XDoc("user") .Attr("id", "1") .Elem("email", "*****@*****.**") .Elem("language", "en") .Start("permissions.user") .Elem("operations", "READ,SUBSCRIBE,LOGIN") .End()); } msg.Headers.Add("X-Deki-Site", "id=wicked"); r2.Return(msg); }); XUri subscribe = new XUri("http://mock/sub"); MockPlug.Register(subscribe, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { if(u == subscribe.At("subscribers")) { _log.Debug("creating subscription"); DreamMessage msg = DreamMessage.Ok(new XDoc("x")); msg.Headers.Location = subscribe.At("testsub"); r2.Return(msg); } else { _log.Debug("updating subscription"); r2.Return(DreamMessage.Ok()); } }); XUri storage = new XUri("http://mock/store"); MockPlug.Register(storage, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("storage: {0}", u); r2.Return(DreamMessage.Ok(new XDoc("foo"))); }); // set up service _log.Debug("set up service"); DreamServiceInfo serviceInfo = DreamTestHelper.CreateService( _hostInfo, typeof(DekiChangeSubscriptionService), "email", new XDoc("config") .Elem("uri.emailer", new XUri("http://mock/email")) .Elem("uri.deki", deki) .Elem("uri.pubsub", subscribe) .Elem("uri.storage", storage) ); Plug service = serviceInfo.WithInternalKey().AtLocalHost; // post a subscription _log.Debug("post page 10 subscription"); DreamMessage response = service .At("pages", "10") .With("depth", "infinity") .WithHeader("X-Deki-Site", "id=wicked") .PostAsync() .Wait(); Assert.IsFalse(response.IsSuccessful); Assert.AreEqual(DreamStatus.Forbidden, response.Status); }
public void Initialize_service_with_persisted_subscriptions() { XUri email = new XUri("http://mock/email"); XUri deki = new XUri("http://mock/deki"); MockPlug.Register(deki, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("deki: {0}", u); DreamMessage msg = DreamMessage.Ok(new XDoc("user") .Attr("id", "1") .Elem("email", "*****@*****.**") .Start("permissions.user") .Elem("operations", "READ,SUBSCRIBE,LOGIN") .End()); msg.Headers.Add("X-Deki-Site", "id=wicked"); r2.Return(msg); }); XUri subscribe = new XUri("http://mock/sub"); int subscribeCalled = 0; MockPlug.Register(subscribe, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("subscribe: {0}", u); subscribeCalled++; DreamMessage msg = DreamMessage.Ok(new XDoc("foo")); msg.Headers.Location = subscribe; r2.Return(msg); }); XUri storage = new XUri("http://mock/store"); int storageListCalled = 0; int storageFileCalled = 0; int storageBadCalled = 0; MockPlug.Register(storage, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("storage: {0}", u); if(v == "GET") { if(u == storage.At("subscriptions")) { storageListCalled++; r2.Return(DreamMessage.Ok(new XDoc("files") .Start("folder").Elem("name", "wicked").End() )); return; } else if(u == storage.At("subscriptions", "wicked")) { storageListCalled++; r2.Return(DreamMessage.Ok(new XDoc("files") .Start("file").Elem("name", "user_1.xml").End() .Start("file").Elem("name", "bar.txt").End() )); return; } else if(u == storage.At("subscriptions", "wicked", "user_1.xml")) { storageFileCalled++; r2.Return(DreamMessage.Ok(new XDoc("user") .Attr("userid", 1) .Elem("email", "foo") .Start("subscription.page").Attr("id", 1).Attr("depth", 0).End() )); return; } } storageBadCalled++; throw new DreamBadRequestException("unexpected call"); }); DreamServiceInfo serviceInfo = DreamTestHelper.CreateService( _hostInfo, typeof(DekiChangeSubscriptionService), "email", new XDoc("config") .Elem("uri.emailer", email) .Elem("uri.deki", deki) .Elem("uri.pubsub", subscribe) .Elem("uri.storage", storage) ); Assert.AreEqual(1, subscribeCalled); Assert.AreEqual(2, storageListCalled); Assert.AreEqual(1, storageFileCalled); Assert.AreEqual(0, storageBadCalled); _log.Debug("get all subscriptions"); DreamMessage response = serviceInfo.AtLocalHost .At("subscriptions") .WithHeader("X-Deki-Site", "id=wicked") .GetAsync() .Wait(); Assert.IsTrue(response.IsSuccessful); XDoc subscriptions = response.ToDocument(); XDoc sub = subscriptions["subscription.page"]; Assert.AreEqual(1, sub.ListLength); Assert.AreEqual("1", sub["@id"].AsText); Assert.AreEqual("0", sub["@depth"].AsText); }
public void Request_without_valid_user_headers_results_in_not_authorized() { // set up mocks for all the support service calls XUri deki = new XUri("http://mock/deki"); MockPlug.Register(deki, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("deki: {0}", u); r2.Return(DreamMessage.AccessDenied("deki", "bad puppy")); }); XUri subscribe = new XUri("http://mock/sub"); MockPlug.Register(subscribe, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { if(u == subscribe.At("subscribers")) { _log.Debug("creating subscription"); DreamMessage msg = DreamMessage.Ok(new XDoc("x")); msg.Headers.Location = subscribe.At("testsub"); r2.Return(msg); } else { _log.Debug("updating subscription"); r2.Return(DreamMessage.Ok()); } }); XUri storage = new XUri("http://mock/store"); MockPlug.Register(storage, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("storage: {0}", u); r2.Return(DreamMessage.Ok(new XDoc("foo"))); }); // set up service _log.Debug("set up service"); DreamServiceInfo serviceInfo = DreamTestHelper.CreateService( _hostInfo, typeof(DekiChangeSubscriptionService), "email", new XDoc("config") .Elem("uri.emailer", new XUri("http://mock/email")) .Elem("uri.deki", deki) .Elem("uri.pubsub", subscribe) .Elem("uri.storage", storage) ); Plug service = serviceInfo.WithInternalKey().AtLocalHost; // post a subscription _log.Debug("post page 10 subscription"); DreamMessage response = service .At("pages", "10") .With("depth", "infinity") .WithHeader("X-Deki-Site", "id=wicked") .PostAsync() .Wait(); Assert.IsFalse(response.IsSuccessful); Assert.AreEqual(DreamStatus.Unauthorized, response.Status); }
public void Uses_deki_to_prune_recipients() { XUri mockDeki = new XUri("http://mock/deki"); int dekiCalled = 0; int dekipage42authCalled = 0; bool dekiArgsGood = false; int dekipage43authCalled = 0; MockPlug.Register(mockDeki, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("mockDeki called at: {0}", u); dekiCalled++; dekiArgsGood = false; List<int> users = new List<int>(); foreach(XDoc user in r.ToDocument()["user/@id"]) { users.Add(user.AsInt.Value); } if(users.Count == 4 && users.Contains(1) && users.Contains(2) && users.Contains(3) && users.Contains(4)) { dekiArgsGood = true; } DreamMessage msg = DreamMessage.Ok(); if(u.WithoutQuery() == mockDeki.At("pages", "42", "allowed")) { dekipage42authCalled++; msg = DreamMessage.Ok(new XDoc("users") .Start("user").Attr("id", 1).End() .Start("user").Attr("id", 2).End()); } else if(u.WithoutQuery() == mockDeki.At("pages", "43", "allowed")) { dekipage43authCalled++; msg = DreamMessage.Ok(new XDoc("users") .Start("user").Attr("id", 3).End() .Start("user").Attr("id", 4).End()); } r2.Return(msg); }); XUri mockRecipient = new XUri("http://mock/r1"); int mockRecipientCalled = 0; XDoc received = null; List<string> recipients = new List<string>(); AutoResetEvent are = new AutoResetEvent(false); MockPlug.Register(mockRecipient, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("mockRecipient called at: {0}", u); mockRecipientCalled++; received = r.ToDocument(); recipients.Clear(); recipients.AddRange(r.Headers.DreamEventRecipients); are.Set(); r2.Return(DreamMessage.Ok()); }); DreamServiceInfo serviceInfo = DreamTestHelper.CreateService( _hostInfo, "sid://mindtouch.com/dream/2008/10/pubsub", "whitelist", new XDoc("config") .Elem("uri.deki", mockDeki) .Start("components") .Attr("context", "service") .Start("component") .Attr("implementation", typeof(DekiDispatcher).AssemblyQualifiedName) .Attr("type", typeof(IPubSubDispatcher).AssemblyQualifiedName) .End() .End() ); XDoc sub = new XDoc("subscription-set") .Elem("uri.owner", mockRecipient) .Start("subscription") .Attr("id", "1") .Elem("uri.resource", "http://mock/resource/x") .Elem("channel", "channel:///foo/*") .Elem("uri.proxy", mockRecipient) .Start("recipient").Attr("userid", "1").Elem("uri", "http://recipient/a").End() .Start("recipient").Attr("userid", "2").Elem("uri", "http://recipient/b").End() .Start("recipient").Attr("userid", "3").Elem("uri", "http://recipient/c").End() .Start("recipient").Attr("userid", "4").Elem("uri", "http://recipient/d").End() .End() .Start("subscription") .Attr("id", "2") .Elem("uri.resource", "http://mock/resource/y") .Elem("channel", "channel:///foo/*") .Elem("uri.proxy", mockRecipient) .Start("recipient").Attr("userid", "1").Elem("uri", "http://recipient/a").End() .Start("recipient").Attr("userid", "2").Elem("uri", "http://recipient/b").End() .Start("recipient").Attr("userid", "3").Elem("uri", "http://recipient/c").End() .Start("recipient").Attr("userid", "4").Elem("uri", "http://recipient/d").End() .End(); DreamMessage result = serviceInfo.WithInternalKey().AtLocalHost.At("subscribers").PostAsync(sub).Wait(); Assert.IsTrue(result.IsSuccessful); XDoc ev = new XDoc("event").Elem("pageid", 42); result = serviceInfo.WithInternalKey() .AtLocalHost .At("publish") .WithHeader(DreamHeaders.DREAM_EVENT_CHANNEL, "channel:///foo/bar") .WithHeader(DreamHeaders.DREAM_EVENT_ORIGIN, mockDeki.ToString()) .WithHeader(DreamHeaders.DREAM_EVENT_RESOURCE, "http://mock/resource/x") .PostAsync(ev).Wait(); Assert.IsTrue(result.IsSuccessful); Assert.IsTrue(are.WaitOne(500, true)); Assert.AreEqual(1, dekiCalled); Assert.AreEqual(1, dekipage42authCalled); Assert.IsTrue(dekiArgsGood); Assert.AreEqual(ev, received); Assert.AreEqual(2, recipients.Count); Assert.Contains("http://recipient/a", recipients); Assert.Contains("http://recipient/b", recipients); ev = new XDoc("event").Elem("pageid", 43); result = serviceInfo.WithInternalKey() .AtLocalHost .At("publish") .WithHeader(DreamHeaders.DREAM_EVENT_CHANNEL, "channel:///foo/bar") .WithHeader(DreamHeaders.DREAM_EVENT_ORIGIN, mockDeki.ToString()) .WithHeader(DreamHeaders.DREAM_EVENT_RESOURCE, "http://mock/resource/y") .PostAsync(ev).Wait(); Assert.IsTrue(result.IsSuccessful); Assert.IsTrue(are.WaitOne(5000, true)); Assert.AreEqual(2, dekiCalled); Assert.AreEqual(1, dekipage42authCalled); Assert.IsTrue(dekiArgsGood); Assert.AreEqual(ev, received); Assert.AreEqual(2, recipients.Count); Assert.Contains("http://recipient/c", recipients); Assert.Contains("http://recipient/d", recipients); }
public void Exporter_can_retrieve_items_by_dataid() { // Arrange XUri dekiApiUri = new XUri("http://mock/@api/deki"); XDoc exportDocument = new XDoc("export"); XUri item1Uri = dekiApiUri.At("foo", "bar", "abc"); XDoc item1Doc = new XDoc("item1"); XUri item2Uri = dekiApiUri.At("foo", "bar", "def"); XDoc item2Doc = new XDoc("item2"); XDoc exportResponse = new XDoc("export") .Start("requests") .Start("request") .Attr("method", "GET") .Attr("dataid", "abc") .Attr("href", item1Uri) .Start("header").Attr("name", "h_1").Attr("value", "v_1").End() .Start("header").Attr("name", "h_2").Attr("value", "v_2").End() .End() .Start("request") .Attr("method", "GET") .Attr("dataid", "def") .Attr("href", item2Uri) .End() .End() .Start("manifest") .Start("foo").Attr("dataid", "abc").End() .Start("bar").Attr("dataid", "def").End() .End(); AutoMockPlug mock = MockPlug.Register(dekiApiUri); mock.Expect().Verb("POST").Uri(dekiApiUri.At("site", "export").With("relto", "0")).RequestDocument(exportDocument).Response(DreamMessage.Ok(exportResponse)); mock.Expect().Verb("GET").Uri(item1Uri).RequestHeader("h_1", "v_1").RequestHeader("h_2", "v_2").Response(DreamMessage.Ok(item1Doc)); mock.Expect().Verb("GET").Uri(item2Uri).Response(DreamMessage.Ok(item2Doc)); // Act Exporter exporter = Exporter.CreateAsync(Plug.New(dekiApiUri), exportDocument, 0, new Result<Exporter>()).Wait(); ExportItem item1 = exporter.GetItemAsync("abc", new Result<ExportItem>()).Wait(); ExportItem item2 = exporter.GetItemAsync("def", new Result<ExportItem>()).Wait(); //Assert Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1))); Assert.AreEqual(exportResponse["manifest"], exporter.Manifest); Assert.AreEqual(new string[] { "abc", "def" }, exporter.DataIds); Assert.AreEqual(exporter.Manifest["*[@dataid='abc']"], item1.ItemManifest); Assert.AreEqual(exporter.Manifest["*[@dataid='def']"], item2.ItemManifest); Assert.AreEqual(item1Doc, XDocFactory.From(new StreamReader(item1.Data), MimeType.TEXT_XML)); Assert.AreEqual(item2Doc, XDocFactory.From(new StreamReader(item2.Data), MimeType.TEXT_XML)); }
//--- Class Methods --- internal static AMedia New(XUri uri, XDoc config) { // check if the uri is a viddler video if(uri.Scheme.EqualsInvariantIgnoreCase("kaltura")) { if(uri.Segments.Length >= 1) { string entryID = uri.Segments[0]; string partnerID = config["kaltura/partner-id"].AsText; // check if extension is configured for kaltura integration if(!string.IsNullOrEmpty(partnerID)) { bool remix = !(uri.GetParam("edit", null) ?? uri.GetParam("remix", "no")).EqualsInvariantIgnoreCase("no"); // verify that user has permission to remix content on current page if(remix) { Plug dekiApi = GetDekiApi(config); if(dekiApi != null) { try { DekiScriptMap env = DreamContext.Current.GetState<DekiScriptMap>(); string pageid = env.GetAt("page.id").AsString(); string userid = env.GetAt("user.id").AsString(); XDoc users = dekiApi.At("pages", pageid, "allowed").With("permissions", "UPDATE").Post(new XDoc("users").Start("user").Attr("id", userid).End()).ToDocument(); remix = !users[string.Format(".//user[@id='{0}']", userid)].IsEmpty; } catch(Exception e) { _log.Error("unable to verify user permission on page", e); } } } // check if SEO links are explicitly disabled bool seo = !(config["kaltura/seo-links"].AsText ?? "enabled").EqualsInvariantIgnoreCase("disabled"); // determin which UI configuration to use based on user's permissions and embed settings for video string uiConfID = remix ? config["kaltura/uiconf/player-mix"].AsText : config["kaltura/uiconf/player-nomix"].AsText; if(!string.IsNullOrEmpty(uiConfID)) { uri = config["kaltura/server-uri"].AsUri ?? new XUri("http://www.kaltura.com"); uri = uri.At("index.php", "kwidget", "wid", "_" + partnerID, "uiconf_id", uiConfID, "entry_id", entryID); return new KalturaVideo(uri, remix, seo); } } } } return null; }
public void Importer_Items_are_populated_with_request_and_manifest_docs() { // Arrange var dekiApiUri = new XUri("http://mock/@api/deki"); var importManifest = new XDoc("manifest") .Start("item").Attr("dataid", "abc").Elem("foo", "bar").End() .Start("item").Attr("dataid", "def").Elem("baz", "flip").End(); var item1Uri = dekiApiUri.At("foo", "bar", "abc"); var item2Uri = dekiApiUri.At("foo", "bar", "def"); var importResponse = new XDoc("requests") .Start("request") .Attr("method", "POST") .Attr("dataid", "abc") .Attr("href", item1Uri) .Start("header").Attr("name", "h_1").Attr("value", "v_1").End() .Start("header").Attr("name", "h_2").Attr("value", "v_2").End() .End() .Start("request") .Attr("method", "PUT") .Attr("dataid", "def") .Attr("href", item2Uri) .End(); var mock = MockPlug.Register(dekiApiUri); mock.Expect().Verb("POST").Uri(dekiApiUri.At("site", "import").With("relto", "0")).RequestDocument(importManifest).Response(DreamMessage.Ok(importResponse)); // Act var importer = Importer.CreateAsync(Plug.New(dekiApiUri), importManifest, 0, new Result<Importer>()).Wait(); //Assert Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1))); var item1 = importer.Items.Where(x => x.DataId == "abc").FirstOrDefault(); Assert.IsNotNull(item1); Assert.IsNotNull(item1.Manifest); Assert.AreEqual(importManifest[".//*[@dataid='abc']"], item1.Manifest); Assert.IsNotNull(item1.Request); Assert.AreEqual(importResponse[".//*[@dataid='abc']"], item1.Request); var item2 = importer.Items.Where(x => x.DataId == "def").FirstOrDefault(); Assert.IsNotNull(item2); Assert.IsNotNull(item2.Manifest); Assert.AreEqual(importManifest[".//*[@dataid='def']"], item2.Manifest); Assert.IsNotNull(item1.Request); Assert.AreEqual(importResponse[".//*[@dataid='def']"], item2.Request); }
public void Importer_can_send_ImportItem_with_xml_body_in_request_doc() { // Arrange var dekiApiUri = new XUri("http://mock/@api/deki"); var importManifest = new XDoc("manifest"); var item1Uri = dekiApiUri.At("foo", "bar", "abc"); var importResponse = new XDoc("requests"); var mock = MockPlug.Register(dekiApiUri); mock.Expect().Verb("POST").Uri(dekiApiUri.At("site", "import").With("relto", "0")).RequestDocument(importManifest).Response(DreamMessage.Ok(importResponse)); mock.Expect().Verb("POST").Uri(item1Uri).RequestDocument(new XDoc("item1").Elem("foo", "bar")); // Act Importer importer = Importer.CreateAsync(Plug.New(dekiApiUri), importManifest, 0, new Result<Importer>()).Wait(); var item1 = new ImportItem( "abc", new XDoc("request") .Attr("method", "POST") .Attr("dataid", "abc") .Attr("href", item1Uri) .Start("body") .Attr("type","xml") .Start("item1").Elem("foo","bar").End() .End(), new XDoc("manifest"), null, 0); importer.WriteDataAsync(item1, new Result()).Wait(); //Assert Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(1))); }
public void User_delete_event_wipes_subscriptions() { // set up mocks for all the support service calls XUri deki = new XUri("http://mock/deki"); XUri dekiAuth = deki.At("users"); AutoResetEvent dekiResetEvent = new AutoResetEvent(false); XDoc dekiResponse = null; XUri dekiCalledUri = null; MockPlug.Register(deki, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("deki: {0}", u); DreamMessage msg; if(u.Path.StartsWith("/deki/pages")) { msg = DreamMessage.Ok(new XDoc("users").Start("user").Attr("id", "1").End()); } else { dekiCalledUri = u; dekiResetEvent.Set(); msg = DreamMessage.Ok(dekiResponse); } msg.Headers.Add("X-Deki-Site", "id=wicked"); r2.Return(msg); }); XUri email = new XUri("http://mock/email").With("apikey", "123"); AutoResetEvent emailResetEvent = new AutoResetEvent(false); List<XDoc> emailPosted = new List<XDoc>(); MockPlug.Register(email, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("email: {0}", u); emailPosted.Add(r.ToDocument()); emailResetEvent.Set(); r2.Return(DreamMessage.Ok()); }); XUri subscribe = new XUri("http://mock/sub"); XUri subscriptionLocation = subscribe.At("testsub"); AutoResetEvent subscribeResetEvent = new AutoResetEvent(false); XUri subscribeCalledUri = null; XDoc subscribePosted = null; MockPlug.Register(subscribe, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { subscribeCalledUri = u; if(u == subscribe.At("subscribers")) { _log.Debug("creating subscription"); DreamMessage msg = DreamMessage.Ok(new XDoc("x")); msg.Headers.Location = subscriptionLocation; subscribeResetEvent.Set(); r2.Return(msg); } else { _log.Debug("updating subscription"); subscribePosted = r.ToDocument(); subscribeResetEvent.Set(); r2.Return(DreamMessage.Ok()); } }); XUri storage = new XUri("http://mock/store"); AutoResetEvent storagePutResetEvent = new AutoResetEvent(false); AutoResetEvent storageGetResetEvent = new AutoResetEvent(false); AutoResetEvent storageDeleteResetEvent = new AutoResetEvent(false); XDoc storageResponse = null; List<Tuplet<string, XDoc>> storagePuts = new List<Tuplet<string, XDoc>>(); int storagePutsExpected = 0; int deleteCalled = 0; MockPlug.Register(storage, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("storage: {0} - {1}", v, u); if(v == "PUT") { string wikihost = u.Segments[u.Segments.Length - 2]; storagePuts.Add(new Tuplet<string, XDoc>(wikihost, r.ToDocument())); if(storagePuts.Count >= storagePutsExpected) { storagePutResetEvent.Set(); } } else if(v == "DELETE") { deleteCalled++; storageDeleteResetEvent.Set(); } else if(v == "GET") { storageGetResetEvent.Set(); } r2.Return(DreamMessage.Ok(storageResponse)); }); // set up service _log.Debug("set up service"); storageResponse = new XDoc("files"); DreamServiceInfo serviceInfo = DreamTestHelper.CreateService( _hostInfo, typeof(DekiChangeSubscriptionService), "email", new XDoc("config") .Elem("uri.emailer", email) .Elem("uri.deki", deki) .Elem("uri.pubsub", subscribe) .Elem("uri.storage", storage) ); Plug service = serviceInfo.WithInternalKey().AtLocalHost; // expect: // - storage was queried // - subscription was created on subscribe Assert.IsTrue(storageGetResetEvent.WaitOne(100, true)); Assert.IsTrue(subscribeResetEvent.WaitOne(100, true)); Assert.AreEqual(subscribe.At("subscribers"), subscribeCalledUri); // post a subscription storagePutsExpected = 1; _log.Debug("post a subscription"); dekiResponse = new XDoc("user") .Attr("id", "1") .Elem("email", "*****@*****.**") .Elem("language", "en") .Start("permissions.user") .Elem("operations", "READ,SUBSCRIBE,LOGIN") .End(); DreamMessage response = service .At("pages", "10") .With("depth", "infinity") .WithHeader("X-Deki-Site", "id=wicked") .PostAsync() .Wait(); Assert.IsTrue(response.IsSuccessful); // expect: // - deki was queried for user info // - subscription location was updated with new sub // - storage was updated with new wiki subscription set Assert.IsTrue(storagePutResetEvent.WaitOne(1000, true)); Assert.IsTrue(subscribeResetEvent.WaitOne(1000, true)); Assert.IsTrue(dekiResetEvent.WaitOne(1000, true)); Thread.Sleep(100); Assert.AreEqual(dekiAuth.At("current"), dekiCalledUri); Assert.AreEqual("wicked", storagePuts[0].Item1); Assert.AreEqual(1, storagePuts.Count); Assert.AreEqual(subscriptionLocation, subscribeCalledUri); Assert.AreEqual(2, subscribePosted["subscription"].ListLength); Assert.AreEqual("deki://wicked/pages/10#depth=infinity", subscribePosted["subscription[channel='event://wicked/deki/pages/create']/uri.resource"].AsText); // post a user delete event _log.Debug("posting a user delete event"); dekiCalledUri = null; storagePuts.Clear(); subscribeCalledUri = null; emailPosted.Clear(); string channel = "event://wicked/deki/users/delete"; response = service.At("updateuser") .WithHeader(DreamHeaders.DREAM_EVENT_CHANNEL, channel) .PostAsync(CreateDekiEvent().Elem("channel", channel).Elem("userid", 1)) .Wait(); Assert.IsTrue(response.IsSuccessful); // expect: // - storage should be called and user is no longer in set // - new sub set should be pushed upstream Assert.IsTrue(storageDeleteResetEvent.WaitOne(1000, true)); Assert.IsTrue(subscribeResetEvent.WaitOne(1000, true)); Assert.IsNull(dekiCalledUri); Assert.IsEmpty(emailPosted); Assert.AreEqual(1, deleteCalled); Assert.AreEqual(subscriptionLocation, subscribeCalledUri); Assert.AreEqual(1, subscribePosted["subscription"].ListLength); }
//--- Methods --- /// <summary> /// Application specific base uri for a given request /// </summary> /// <param name="request">HttpRequest instance.</param> /// <returns>Base Uri.</returns> public XUri GetRequestBaseUri(HttpRequest request) { var transport = new XUri(request.Url).WithoutPathQueryFragment().AtAbsolutePath(request.ApplicationPath); var prefix = _appConfig.Prefix; if(!string.IsNullOrEmpty(prefix)) { transport = transport.At(prefix); } return transport; }
public void Deleted_page_event_wipes_subscriptions_for_page() { // set up mocks for all the support service calls XUri deki = new XUri("http://mock/deki"); XUri dekiAuth = deki.At("users"); AutoResetEvent dekiUserResetEvent = new AutoResetEvent(false); AutoResetEvent dekiPageResetEvent = new AutoResetEvent(false); AutoResetEvent dekiSiteResetEvent = new AutoResetEvent(false); XDoc dekiUserResponse = null; XDoc dekiPageResponse = null; XDoc dekiFeedResponse = null; XDoc dekiSiteResponse = null; XDoc dekiPageRequest = null; XUri dekiCalledUri = null; MockPlug.Register(deki, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("deki: {0}", u); DreamMessage msg; if(u.Path.StartsWith("/deki/pages")) { if(v != "GET") { dekiPageRequest = r.ToDocument(); } if(u.Path.EndsWith("feed")) { msg = DreamMessage.Ok(dekiFeedResponse); } else { msg = DreamMessage.Ok(dekiPageResponse); } dekiPageResetEvent.Set(); } else if(u.Path.StartsWith("/deki/site/settings")) { msg = DreamMessage.Ok(dekiSiteResponse); dekiSiteResetEvent.Set(); } else { msg = DreamMessage.Ok(dekiUserResponse); dekiUserResetEvent.Set(); dekiCalledUri = u; } msg.Headers.Add("X-Deki-Site", "id=wicked"); r2.Return(msg); }); XUri email = new XUri("http://mock/email").With("apikey", "123"); AutoResetEvent emailResetEvent = new AutoResetEvent(false); List<XDoc> emailPosted = new List<XDoc>(); MockPlug.Register(email, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("email: {0}", u); emailPosted.Add(r.ToDocument()); emailResetEvent.Set(); r2.Return(DreamMessage.Ok()); }); XUri subscribe = new XUri("http://mock/sub"); XUri subscriptionLocation = subscribe.At("testsub"); AutoResetEvent subscribeResetEvent = new AutoResetEvent(false); XUri subscribeCalledUri = null; XDoc subscribePosted = null; MockPlug.Register(subscribe, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { subscribeCalledUri = u; if(u == subscribe.At("subscribers")) { _log.Debug("creating subscription"); DreamMessage msg = DreamMessage.Ok(new XDoc("x")); msg.Headers.Location = subscriptionLocation; subscribeResetEvent.Set(); r2.Return(msg); } else { _log.Debug("updating subscription"); subscribePosted = r.ToDocument(); subscribeResetEvent.Set(); r2.Return(DreamMessage.Ok()); } }); XUri storage = new XUri("http://mock/store"); AutoResetEvent storagePutResetEvent = new AutoResetEvent(false); AutoResetEvent storageGetResetEvent = new AutoResetEvent(false); AutoResetEvent storageDeleteResetEvent = new AutoResetEvent(false); XDoc storageResponse = null; List<Tuplet<string, XDoc>> storagePuts = new List<Tuplet<string, XDoc>>(); int storagePutsExpected = 0; XUri storageGetCalled = null; int deleteCalled = 0; MockPlug.Register(storage, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("storage: {0} - {1}", v, u); if(v == "PUT") { string wikihost = u.Segments[u.Segments.Length - 2]; storagePuts.Add(new Tuplet<string, XDoc>(wikihost, r.ToDocument())); if(storagePuts.Count >= storagePutsExpected) { storagePutResetEvent.Set(); } } else if(v == "DELETE") { deleteCalled++; storageDeleteResetEvent.Set(); } else if(v == "GET") { storageGetCalled = u; storageGetResetEvent.Set(); } r2.Return(DreamMessage.Ok(storageResponse)); }); // set up service _log.Debug("set up service"); storageResponse = new XDoc("files"); DreamServiceInfo serviceInfo = DreamTestHelper.CreateService( _hostInfo, typeof(DekiChangeSubscriptionService), "email", new XDoc("config") .Elem("uri.emailer", email) .Elem("uri.deki", deki) .Elem("uri.pubsub", subscribe) .Elem("uri.storage", storage) .Elem("accumulation-time", 0) .Elem("from-address", "*****@*****.**") ); Plug service = serviceInfo.WithInternalKey().AtLocalHost; // expect: // - storage was queried // - subscription was created on subscribe Assert.IsTrue(storageGetResetEvent.WaitOne(100, true)); Assert.IsTrue(subscribeResetEvent.WaitOne(100, true)); Assert.AreEqual(storage.At("subscriptions"), storageGetCalled); Assert.AreEqual(subscribe.At("subscribers"), subscribeCalledUri); // post a subscription _log.Debug("post a subscription"); storagePutsExpected = 1; dekiUserResponse = new XDoc("user") .Attr("id", "1") .Elem("email", "*****@*****.**") .Elem("language", "en") .Start("permissions.user") .Elem("operations", "READ,SUBSCRIBE,LOGIN") .End(); dekiPageResponse = new XDoc("users").Start("user").Attr("id", "1").End(); DreamMessage response = service .At("pages", "10") .With("depth", "infinity") .WithHeader("X-Deki-Site", "id=wicked") .PostAsync() .Wait(); Assert.IsTrue(response.IsSuccessful); // expect: // - deki was queried for user info // - subscription location was updated with new sub // - storage was updated with new wiki subscription set Assert.IsTrue(storagePutResetEvent.WaitOne(1000, true)); Assert.IsTrue(subscribeResetEvent.WaitOne(1000, true)); Assert.IsTrue(dekiUserResetEvent.WaitOne(1000, true)); Assert.AreEqual(dekiAuth.At("current"), dekiCalledUri); Assert.AreEqual("wicked", storagePuts[0].Item1); Assert.AreEqual(1, storagePuts.Count); Assert.AreEqual(subscriptionLocation, subscribeCalledUri); Assert.AreEqual(2, subscribePosted["subscription"].ListLength); Assert.AreEqual("deki://wicked/pages/10#depth=infinity", subscribePosted["subscription[channel='event://wicked/deki/pages/create']/uri.resource"].AsText); // post a page deleted event _log.Debug("posting a page deleted event"); dekiCalledUri = null; storagePutsExpected = 1; subscribeCalledUri = null; string channel = "event://wicked/deki/pages/delete"; dekiPageResponse = new XDoc("page") .Elem("uri.ui", "http://foo.com/@api/deki/pages/10") .Elem("title", "foo") .Elem("path", "foo/bar"); dekiFeedResponse = new XDoc("table") .Start("change") .Elem("rc_summary", "Two edits") .Elem("rc_comment", "edit 1") .Elem("rc_comment", "edit 2") .End(); dekiSiteResponse = new XDoc("config") .Start("ui") .Elem("sitename", "Test Site") .Elem("language", "de-de") .End() .Start("page-subscription") .Elem("from-address", "*****@*****.**") .End(); response = service.At("notify") .WithHeader(DreamHeaders.DREAM_EVENT_CHANNEL, channel) .WithHeader(DreamHeaders.DREAM_EVENT_RECIPIENT, "deki://wicked/user/1") .WithHeader(DreamHeaders.DREAM_EVENT_RECIPIENT, "deki://wicked/user/2") .PostAsync(CreateDekiEvent().Elem("channel", channel).Elem("pageid", 10)) .Wait(); Assert.IsTrue(response.IsSuccessful); // expect: // - email service is called for user // - storage is called with subscription (and user) removed // - subscription is pushed upstream Assert.IsTrue(emailResetEvent.WaitOne(1000, true)); Assert.IsTrue(storageDeleteResetEvent.WaitOne(1000, true)); Assert.IsTrue(subscribeResetEvent.WaitOne(1000, true)); Assert.IsTrue(dekiSiteResetEvent.WaitOne(1000, true)); Assert.IsNull(dekiCalledUri); Assert.AreEqual(1, emailPosted.Count); Assert.AreEqual("*****@*****.**", emailPosted[0]["to"].AsText); Assert.AreEqual(1, deleteCalled); Assert.AreEqual(subscriptionLocation, subscribeCalledUri); Assert.AreEqual(1, subscribePosted["subscription"].ListLength); }
private static void PopulateActivities(XDoc doc, XUri self, DateTime now, IDreamActivityDescription[] activities) { doc.Attr("count", activities.Length).Attr("href", self.At("status", "activities")); foreach(var description in activities) { doc.Start("description").Attr("created", description.Created).Attr("age", (now - description.Created).TotalSeconds).Value(description.Description).End(); } }
public void Subscription_end_to_end() { // set up mocks for all the support service calls string apikey = "abc"; XUri deki = new XUri("http://mock/deki"); XUri dekiAuth = deki.At("users"); var dekiUserResetEvent = new ManualResetEvent(false); var dekiPageResetEvent = new ManualResetEvent(false); var dekiSiteResetEvent = new ManualResetEvent(false); var subscribeResetEvent = new ManualResetEvent(false); var storagePutResetEvent = new ManualResetEvent(false); var storageGetResetEvent = new ManualResetEvent(false); var storageDeleteResetEvent = new ManualResetEvent(false); var emailResetEvent = new ManualResetEvent(false); Action reset = () => { dekiUserResetEvent.Reset(); dekiPageResetEvent.Reset(); dekiSiteResetEvent.Reset(); subscribeResetEvent.Reset(); storagePutResetEvent.Reset(); storageGetResetEvent.Reset(); storageDeleteResetEvent.Reset(); emailResetEvent.Reset(); }; XDoc dekiUserResponse = null; XDoc dekiPageResponse = null; XDoc dekiFeedResponse = null; XDoc dekiSiteResponse = null; XDoc dekiPageRequest = null; XUri dekiCalledUri = null; MockPlug.Register(deki, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("deki: {0}", u); DreamMessage msg; if(u.Path.StartsWith("/deki/pages")) { if(v != "GET") { dekiPageRequest = r.ToDocument(); } if(u.Path.EndsWith("feed")) { msg = DreamMessage.Ok(dekiFeedResponse); } else { msg = DreamMessage.Ok(dekiPageResponse); } dekiPageResetEvent.Set(); } else if(u.Path.StartsWith("/deki/site/settings")) { msg = DreamMessage.Ok(dekiSiteResponse); dekiSiteResetEvent.Set(); } else { msg = DreamMessage.Ok(dekiUserResponse); dekiUserResetEvent.Set(); dekiCalledUri = u; } msg.Headers.Add("X-Deki-Site", "id=wicked"); r2.Return(msg); }); XUri email = new XUri("http://mock/email").With("apikey", "123"); List<XDoc> emailPosted = new List<XDoc>(); int emailsExpected = 0; MockPlug.Register(email, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("email: {0}", u); emailPosted.Add(r.ToDocument()); if(emailPosted.Count >= emailsExpected) { emailResetEvent.Set(); } r2.Return(DreamMessage.Ok()); }); XUri subscribe = new XUri("http://mock/sub"); XUri subscriptionLocation = subscribe.At("testsub"); XUri subscribeCalledUri = null; XDoc subscribePosted = null; MockPlug.Register(subscribe, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { subscribeCalledUri = u; if(u == subscribe.At("subscribers")) { _log.Debug("creating subscription"); DreamMessage msg = DreamMessage.Ok(new XDoc("x")); msg.Headers.Location = subscriptionLocation; subscribeResetEvent.Set(); r2.Return(msg); } else { _log.Debug("updating subscription"); subscribePosted = r.ToDocument(); subscribeResetEvent.Set(); r2.Return(DreamMessage.Ok()); } }); XUri storage = new XUri("http://mock/store"); XDoc storageResponse = null; List<Tuplet<string, XDoc>> storagePuts = new List<Tuplet<string, XDoc>>(); int storagePutsExpected = 1; int deleteCalled = 0; MockPlug.Register(storage, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("storage: {0} - {1}", v, u); if(v == "PUT") { string wikihost = u.Segments[u.Segments.Length - 2]; storagePuts.Add(new Tuplet<string, XDoc>(wikihost, r.ToDocument())); if(storagePuts.Count >= storagePutsExpected) { storagePutResetEvent.Set(); } } else if(v == "DELETE") { deleteCalled++; storageDeleteResetEvent.Set(); } else if(v == "GET") { storageGetResetEvent.Set(); } r2.Return(DreamMessage.Ok(storageResponse)); }); // set up service _log.Debug("set up service"); storageResponse = new XDoc("files"); DreamServiceInfo serviceInfo = DreamTestHelper.CreateService( _hostInfo, typeof(DekiChangeSubscriptionService), "email", new XDoc("config") .Elem("uri.emailer", email) .Elem("uri.deki", deki) .Elem("uri.pubsub", subscribe) .Elem("uri.storage", storage) .Elem("accumulation-time", 0) .Elem("from-address", "*****@*****.**") .Elem("apikey", apikey) ); Plug service = serviceInfo.WithInternalKey().AtLocalHost; // expect: // - storage was queried // - subscription was created on subscribe Assert.IsTrue(Wait.For(() => storageGetResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsTrue(Wait.For(() => subscribeResetEvent.WaitOne(100, true), 10.Seconds())); Assert.AreEqual(subscribe.At("subscribers"), subscribeCalledUri); reset(); // post a subscription _log.Debug("post a subscription"); dekiUserResponse = new XDoc("user") .Attr("id", "1") .Elem("email", "*****@*****.**") .Elem("language", "en") .Start("permissions.user") .Elem("operations", "READ,SUBSCRIBE,LOGIN") .End(); dekiPageResponse = new XDoc("users").Start("user").Attr("id", 1).End(); DreamMessage response = service .At("pages", "10") .With("depth", "infinity") .WithHeader("X-Deki-Site", "id=wicked") .PostAsync() .Wait(); Assert.IsTrue(response.IsSuccessful, response.AsText()); // expect: // - deki was queried for user info // - subscription location was updated with new sub // - storage was updated with new wiki subscription set Assert.IsTrue(Wait.For(() => storagePutResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsTrue(Wait.For(() => subscribeResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsTrue(Wait.For(() => dekiUserResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsTrue(Wait.For(() => dekiPageResetEvent.WaitOne(100, true), 10.Seconds())); Assert.AreEqual(1, dekiPageRequest["user/@id"].AsUInt.Value); Assert.AreEqual(dekiAuth.At("current"), dekiCalledUri); Assert.AreEqual(1, storagePuts.Count); Assert.AreEqual("wicked", storagePuts[0].Item1); Assert.AreEqual(subscriptionLocation, subscribeCalledUri); Assert.AreEqual(2, subscribePosted["subscription"].ListLength); Assert.AreEqual("deki://wicked/pages/10#depth=infinity", subscribePosted["subscription[channel='event://wicked/deki/pages/create']/uri.resource"].AsText); reset(); //post another subscription _log.Debug("post another subscription"); storagePuts.Clear(); subscribePosted = null; dekiCalledUri = null; subscribeCalledUri = null; dekiPageRequest = null; dekiUserResponse = new XDoc("user") .Attr("id", "2") .Elem("email", "*****@*****.**") .Elem("language", "en") .Start("permissions.user") .Elem("operations", "READ,SUBSCRIBE,LOGIN") .End(); dekiPageResponse = new XDoc("users").Start("user").Attr("id", 2).End(); response = service .At("pages", "10") .With("depth", "infinity") .WithHeader("X-Deki-Site", "id=wicked") .PostAsync() .Wait(); Assert.IsTrue(response.IsSuccessful); // expect: // - deki was queried for user info // - subscription location was updated with new sub // - storage was updated with new wiki subscription set Assert.IsTrue(Wait.For(() => storagePutResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsTrue(Wait.For(() => subscribeResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsTrue(Wait.For(() => dekiUserResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsTrue(Wait.For(() => dekiPageResetEvent.WaitOne(100, true), 10.Seconds())); Assert.AreEqual(2, dekiPageRequest["user/@id"].AsUInt.Value); Assert.AreEqual(dekiAuth.At("current"), dekiCalledUri); Assert.AreEqual("wicked", storagePuts[0].Item1); Assert.AreEqual(1, storagePuts.Count); Assert.AreEqual(subscriptionLocation, subscribeCalledUri); Assert.AreEqual(2, subscribePosted["subscription"].ListLength); Assert.AreEqual(2, subscribePosted["subscription[channel='event://wicked/deki/pages/create']/recipient"].ListLength); reset(); // post a page event _log.Debug("posting a page event"); dekiCalledUri = null; subscribeCalledUri = null; string channel = "event://wicked/deki/pages/update"; emailPosted.Clear(); emailsExpected = 2; dekiPageResponse = new XDoc("page") .Elem("uri.ui", "http://foo.com/@api/deki/pages/10") .Elem("title", "foo") .Elem("path", "foo/bar"); dekiFeedResponse = new XDoc("table") .Start("change") .Elem("rc_summary", "Two edits") .Elem("rc_comment", "edit 1") .Elem("rc_comment", "edit 2") .End(); dekiSiteResponse = new XDoc("config") .Start("ui") .Elem("sitename", "Test Site") .Elem("language", "de-de") .End() .Start("page-subscription") .Elem("from-address", "*****@*****.**") .End(); response = service.At("notify") .WithHeader(DreamHeaders.DREAM_EVENT_CHANNEL, channel) .WithHeader(DreamHeaders.DREAM_EVENT_RECIPIENT, "deki://wicked/user/1") .WithHeader(DreamHeaders.DREAM_EVENT_RECIPIENT, "deki://wicked/user/2") .PostAsync(CreateDekiEvent().Elem("channel", channel).Elem("pageid", 10)) .Wait(); Assert.IsTrue(response.IsSuccessful); // expect: // - email service is called for both users Assert.IsTrue(Wait.For(() => emailResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsTrue(Wait.For(() => dekiSiteResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsNull(dekiCalledUri); Assert.IsNull(subscribeCalledUri); Assert.AreEqual(2, emailPosted.Count); bool found1 = false; bool found2 = false; foreach(XDoc emailDoc in emailPosted) { XDoc para = emailDoc["body[@html='true']/p"]; Assert.AreEqual("http://foo.com/@api/deki/pages/10", para["b/a/@href"].AsText); para = para.Next; Assert.AreEqual("<li>edit 1 ( <a href=\"http://foo.com/@api/deki/pages/10?revision\">Mon, 01 Jan 0001 00:00:00 GMT</a> by <a href=\"http://foo.com/User%3a\" /> )</li>", para["ol/li"].ToString()); if(emailDoc["to"].AsText == "*****@*****.**") { found1 = true; } else if(emailDoc["to"].AsText == "*****@*****.**") { found2 = true; } } Assert.IsTrue(found1); Assert.IsTrue(found2); reset(); // post a user update event _log.Debug("posting a user update event"); dekiCalledUri = null; storagePuts.Clear(); subscribeCalledUri = null; emailPosted.Clear(); channel = "event://wicked/deki/users/update"; response = service.At("updateuser") .WithHeader(DreamHeaders.DREAM_EVENT_CHANNEL, channel) .PostAsync(CreateDekiEvent().Elem("channel", channel).Elem("userid", 1)) .Wait(); Assert.IsTrue(response.IsSuccessful); // expect: // - nothing, user should be invalidated but no action should be taken on it Thread.Sleep(500); // give 'nothing' a chance to happen anyhow Assert.IsNull(dekiCalledUri); Assert.IsNull(subscribeCalledUri); Assert.IsEmpty(emailPosted); reset(); // post another page event _log.Debug("posting another page event"); dekiUserResponse = new XDoc("user") .Attr("id", "1") .Elem("email", "*****@*****.**") .Elem("language", "en") .Start("permissions.user") .Elem("operations", "READ,SUBSCRIBE,LOGIN") .End(); channel = "event://wicked/deki/pages/update"; emailPosted.Clear(); emailsExpected = 2; response = service.At("notify") .WithHeader(DreamHeaders.DREAM_EVENT_CHANNEL, channel) .WithHeader(DreamHeaders.DREAM_EVENT_RECIPIENT, "http://wicked/user/1") .WithHeader(DreamHeaders.DREAM_EVENT_RECIPIENT, "http://wicked/user/2") .PostAsync(CreateDekiEvent().Elem("channel", channel).Elem("pageid", 10)) .Wait(); Assert.IsTrue(response.IsSuccessful); // expect: // - deki is queried for invalidated user info // - storage was updated with new wiki subscription set // - email service is called for both users Assert.IsTrue(Wait.For(() => emailResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsTrue(Wait.For(() => dekiUserResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsTrue(Wait.For(() => storagePutResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsNull(subscribeCalledUri); Assert.AreEqual(dekiAuth.At("1").With("apikey", apikey), dekiCalledUri); Assert.AreEqual("wicked", storagePuts[0].Item1); Assert.AreEqual(1, storagePuts.Count); Assert.AreEqual(2, emailPosted.Count); found1 = false; found2 = false; foreach(XDoc emailDoc in emailPosted) { if(emailDoc["to"].AsText == "*****@*****.**") { found1 = true; } else if(emailDoc["to"].AsText == "*****@*****.**") { found2 = true; } } Assert.IsTrue(found1); Assert.IsTrue(found2); reset(); // remove a subscription _log.Debug("remove a subscription"); dekiCalledUri = null; storagePuts.Clear(); subscribeCalledUri = null; dekiUserResponse = new XDoc("user") .Attr("id", "1") .Elem("email", "*****@*****.**") .Elem("language", "en") .Start("permissions.user") .Elem("operations", "READ,SUBSCRIBE,LOGIN") .End(); response = service.At("pages", "10") .WithHeader("X-Deki-Site", "id=wicked") .DeleteAsync() .Wait(); Assert.IsTrue(response.IsSuccessful); // expect: // - deki was queried to get user info // - subscription location was updated with new sub // - storage was updated with new wiki subscription set Assert.IsTrue(Wait.For(() => storageDeleteResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsTrue(Wait.For(() => subscribeResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsTrue(Wait.For(() => dekiUserResetEvent.WaitOne(100, true), 10.Seconds())); Assert.AreEqual(dekiAuth.At("current"), dekiCalledUri); Assert.AreEqual(1, deleteCalled); Assert.AreEqual(subscriptionLocation, subscribeCalledUri); Assert.AreEqual(2, subscribePosted["subscription"].ListLength); Assert.AreEqual(1, subscribePosted["subscription[channel='event://wicked/deki/pages/create']/recipient"].ListLength); Assert.AreEqual("2", subscribePosted["subscription/recipient/@userid"].AsText); reset(); // post a page event _log.Debug("posting a final page event"); dekiCalledUri = null; subscribeCalledUri = null; emailPosted.Clear(); channel = "event://wicked/deki/pages/update"; emailsExpected = 1; response = service.At("notify") .WithHeader(DreamHeaders.DREAM_EVENT_CHANNEL, channel) .WithHeader(DreamHeaders.DREAM_EVENT_RECIPIENT, "http://wicked/user/2") .PostAsync(CreateDekiEvent().Elem("channel", channel).Elem("pageid", 10)) .Wait(); Assert.IsTrue(response.IsSuccessful); // expect: // - email service is called for remaining user Assert.IsTrue(Wait.For(() => emailResetEvent.WaitOne(100, true), 10.Seconds())); Assert.IsNull(dekiCalledUri); Assert.IsNull(subscribeCalledUri); Assert.AreEqual(1, emailPosted.Count); Assert.AreEqual("*****@*****.**", emailPosted[0]["to"].AsText); reset(); }
public void Providing_externalLuceneUri_posts_dekipubsub_plug_info_on_that_service() { var mockLuceneUri = new XUri("http://mock/lucene"); var mockLucene = MockPlug.Register(mockLuceneUri); XDoc pubsubPlugInfo = null; mockLucene.Expect() .Verb("POST") .Uri(mockLuceneUri.At("subscriptions")).RequestDocument(x => { pubsubPlugInfo = x; return true; }) .Response(DreamMessage.Ok()); var dekiConfig = new XDoc("config") .Elem("apikey", "123") .Elem("path", "deki") .Elem("sid", "http://services.mindtouch.com/deki/draft/2006/11/dekiwiki") .Elem("deki-path", Utils.Settings.DekiPath) .Elem("deki-resources-path", Utils.Settings.DekiResourcesPath) .Elem("imagemagick-convert-path", Utils.Settings.ImageMagickConvertPath) .Elem("imagemagick-identify-path", Utils.Settings.ImageMagickIdentifyPath) .Elem("princexml-path", Utils.Settings.PrinceXmlPath) .Start("indexer").Attr("src", mockLuceneUri).End() .Start("page-subscription") .Elem("accumulation-time", "0") .End() .Start("wikis") .Start("config") .Attr("id", "default") .Elem("host", "*") .Start("page-subscription") .Elem("from-address", "*****@*****.**") .End() .Elem("db-server", "na") .Elem("db-port", "3306") .Elem("db-catalog", "wikidb") .Elem("db-user", "wikiuser") .Start("db-password").Attr("hidden", "true").Value("password").End() .Elem("db-options", "pooling=true; Connection Timeout=5; Protocol=socket; Min Pool Size=2; Max Pool Size=50; Connection Reset=false;character set=utf8;ProcedureCacheSize=25;Use Procedure Bodies=true;") .End() .End(); var apikey = dekiConfig["apikey"].AsText; var hostInfo = DreamTestHelper.CreateRandomPortHost(new XDoc("config").Elem("apikey", apikey)); hostInfo.Host.Self.At("load").With("name", "mindtouch.deki").Post(DreamMessage.Ok()); hostInfo.Host.Self.At("load").With("name", "mindtouch.deki.services").Post(DreamMessage.Ok()); var deki = DreamTestHelper.CreateService(hostInfo, dekiConfig); Assert.IsTrue(mockLucene.WaitAndVerify(TimeSpan.FromSeconds(10)), mockLucene.VerificationFailure); var pubsubPlug = Plug.New(pubsubPlugInfo["@href"].AsUri); foreach(var header in pubsubPlugInfo["header"]) { pubsubPlug.WithHeader(header["name"].AsText, header["value"].AsText); } var setCookies = DreamCookie.ParseAllSetCookieNodes(pubsubPlugInfo["set-cookie"]); if(setCookies.Count > 0) { pubsubPlug.CookieJar.Update(setCookies, null); } var subscriptionSet = new XDoc("subscription-set") .Elem("uri.owner", mockLuceneUri) .Start("subscription") .Elem("channel", "event://*/foo") .Start("recipient") .Attr("authtoken", apikey) .Elem("uri", mockLuceneUri) .End() .End(); var subscription = pubsubPlug.At("subscribers").Post(subscriptionSet); Assert.AreEqual(DreamStatus.Created, subscription.Status); }
public void Retrieve_subscriptions_with_wikiid_query_arg() { // set up mocks for all the support service calls XUri deki = new XUri("http://mock/deki"); MockPlug.Register(deki, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("deki: {0}", u); DreamMessage msg; if(u.Path.StartsWith("/deki/pages")) { msg = DreamMessage.Ok(new XDoc("users").Start("user").Attr("id", "1").End()); } else { msg = DreamMessage.Ok(new XDoc("user") .Attr("id", "1") .Elem("email", "*****@*****.**") .Elem("language", "en") .Start("permissions.user") .Elem("operations", "READ,SUBSCRIBE,LOGIN") .End()); } msg.Headers.Add("X-Deki-Site", "id=wicked"); r2.Return(msg); }); XUri subscribe = new XUri("http://mock/sub"); MockPlug.Register(subscribe, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { if(u == subscribe.At("subscribers")) { _log.Debug("creating subscription"); DreamMessage msg = DreamMessage.Ok(new XDoc("x")); msg.Headers.Location = subscribe.At("testsub"); r2.Return(msg); } else { _log.Debug("updating subscription"); r2.Return(DreamMessage.Ok()); } }); XUri storage = new XUri("http://mock/store"); MockPlug.Register(storage, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("storage: {0}", u); r2.Return(DreamMessage.Ok(new XDoc("foo"))); }); // set up service _log.Debug("set up service"); DreamServiceInfo serviceInfo = DreamTestHelper.CreateService( _hostInfo, typeof(DekiChangeSubscriptionService), "email", new XDoc("config") .Elem("uri.emailer", new XUri("http://mock/email")) .Elem("uri.deki", deki) .Elem("uri.pubsub", subscribe) .Elem("uri.storage", storage) ); Plug service = serviceInfo.WithInternalKey().AtLocalHost; // post a subscription _log.Debug("post page 10 subscription"); DreamMessage response = service .At("pages", "10") .With("depth", "infinity") .WithHeader("X-Deki-Site", "id=wicked") .PostAsync() .Wait(); Assert.IsTrue(response.IsSuccessful); // post a subscription _log.Debug("post page 11 subscription"); response = service .At("pages", "11") .With("siteid", "wicked") .PostAsync() .Wait(); Assert.IsTrue(response.IsSuccessful); // post a subscription _log.Debug("post page 12 subscription"); response = service .At("pages", "12") .With("depth", "0") .With("siteid", "wicked") .PostAsync() .Wait(); Assert.IsTrue(response.IsSuccessful); // post a subscription _log.Debug("post page 13 subscription"); response = service .At("pages", "13") .With("depth", "infinity") .With("siteid", "wicked") .PostAsync() .Wait(); Assert.IsTrue(response.IsSuccessful); _log.Debug("get some subscriptions"); response = service .At("subscriptions") .With("pages", "10,12,14,16") .With("siteid", "wicked") .GetAsync() .Wait(); Assert.IsTrue(response.IsSuccessful); XDoc subscriptions = response.ToDocument(); Assert.AreEqual(2, subscriptions["subscription.page"].ListLength); XDoc page10 = subscriptions["subscription.page[@id='10']"]; Assert.IsFalse(page10.IsEmpty); Assert.AreEqual("infinity", page10["@depth"].AsText); XDoc page12 = subscriptions["subscription.page[@id='12']"]; Assert.IsFalse(page12.IsEmpty); Assert.AreEqual("0", page12["@depth"].AsText); _log.Debug("get all subscriptions"); response = service .At("subscriptions") .With("siteid", "wicked") .GetAsync() .Wait(); Assert.IsTrue(response.IsSuccessful); subscriptions = response.ToDocument(); Assert.AreEqual(4, subscriptions["subscription.page"].ListLength); }
protected override Yield Start(XDoc config, Result result) { yield return Coroutine.Invoke(base.Start, config, new Result()); // read configuration settings _username = config["username"].AsText; if (string.IsNullOrEmpty(_username)) { throw new ArgumentException(MISSING_FIELD_ERROR, "username"); } _password = config["password"].AsText; if (string.IsNullOrEmpty(_password)) { throw new ArgumentException(MISSING_FIELD_ERROR, "password"); } _uri = config["jira-uri"].AsUri; if (_uri == null) { throw new ArgumentException(MISSING_FIELD_ERROR, "jira-uri"); } _jiraTokenDuration = TimeSpan.FromMinutes(config["jira-session-timeout-mins"].AsInt ?? DEFAULT_LOGIN_TTL); // initialize web-service _jira = new JiraSoapServiceService(); _jira.Url = _uri.At("rpc", "soap", "jirasoapservice-v2").ToString(); result.Return(); }
public Hashtable PopularPages( [DekiExtParam("max results (default: 10)", true)] int? max, [DekiExtParam("poll interval (only for js format, default: 30)", true)] int? interval ) { int maxResults = max ?? 10; int resultCount = 0; DekiScriptMap env = DreamContext.Current.GetState<DekiScriptMap>(); DekiScriptLiteral uriLiteral = env.GetAt("site.uri"); XUri deki = new XUri(uriLiteral.NativeValue.ToString()).At("@api", "deki"); Hashtable map = new Hashtable(StringComparer.OrdinalIgnoreCase); map.Add("interval", _ttl.TotalSeconds); ArrayList pages = new ArrayList(); map.Add("pages", pages); int total = 0; Dictionary<uint, int> rankLookup = new Dictionary<uint, int>(); lock(_pageViews) { foreach(View view in _pageViews) { if(rankLookup.ContainsKey(view.PageId)) { rankLookup[view.PageId]++; } else { rankLookup[view.PageId] = 1; } total++; } } List<Tuplet<uint, int>> rank = new List<Tuplet<uint, int>>(); foreach(KeyValuePair<uint, int> kvp in rankLookup) { rank.Add(new Tuplet<uint, int>(kvp.Key, kvp.Value)); } rank.Sort(delegate(Tuplet<uint, int> a, Tuplet<uint, int> b) { return b.Item2.CompareTo(a.Item2); }); map.Add("total", total); foreach(Tuplet<uint, int> page in rank) { Hashtable pageMap = new Hashtable(StringComparer.OrdinalIgnoreCase); pages.Add(pageMap); // BUGBUGBUG (arnec): the AsLocalUri should not be required after bug #5964 is resolved pageMap.Add("page", DekiScriptExpression.Constant(deki.At("$page").AsLocalUri(), new[] { DekiScriptExpression.Constant(page.Item1), DekiScriptExpression.Constant(true) })); pageMap.Add("views", page.Item2); resultCount++; if(resultCount >= maxResults) { break; } } return map; }
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 Service_end_to_end_no_deki() { // set up mocks for all the support service calls string apikey = "abc"; XUri deki = new XUri("http://mock/deki"); int dekiCalled = 0; MockPlug.Register(deki, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("deki: {0}:{1}", v, u); dekiCalled++; r2.Return(DreamMessage.Ok()); }); XUri varnish = new XUri("http://mock/varnish"); AutoResetEvent varnishResetEvent = new AutoResetEvent(false); string varnishHeader = ""; int varnishCalled = 0; MockPlug.Register(varnish, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { _log.DebugFormat("varnish: {0}:{1}", v, u); if(v == "PURGE") { varnishHeader = r.Headers["X-Purge-Url"]; varnishCalled++; varnishResetEvent.Set(); } r2.Return(DreamMessage.Ok()); }); XUri subscribe = new XUri("http://mock/sub"); XUri subscriptionLocation = subscribe.At("testsub"); AutoResetEvent subscribeResetEvent = new AutoResetEvent(false); XUri subscribeCalledUri = null; XDoc subscribePosted = null; MockPlug.Register(subscribe, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { subscribeCalledUri = u; if(u == subscribe.At("subscribers")) { _log.Debug("creating subscription"); DreamMessage msg = DreamMessage.Ok(new XDoc("x")); msg.Headers.Location = subscriptionLocation; subscribeResetEvent.Set(); r2.Return(msg); } else { _log.Debug("updating subscription"); subscribePosted = r.ToDocument(); subscribeResetEvent.Set(); r2.Return(DreamMessage.Ok()); } }); // set up service _log.Debug("set up service"); DreamServiceInfo serviceInfo = DreamTestHelper.CreateService( _hostInfo, typeof(VarnishPurgeService), "varnish", new XDoc("config") .Elem("uri.deki", deki) .Elem("uri.varnish", varnish) .Elem("uri.pubsub", subscribe) .Elem("varnish-purge-delay", 1) .Elem("apikey", apikey) ); Plug service = serviceInfo.WithInternalKey().AtLocalHost; // expect: // - storage was queried // - subscription was created on subscribe Assert.IsTrue(subscribeResetEvent.WaitOne(100, true)); Assert.AreEqual(subscribe.At("subscribers"), subscribeCalledUri); // post page varnish event service.At("queue").Post( new XDoc("deki-event") .Attr("wikiid", "abc") .Elem("channel", "event://abc/deki/pages/create") .Elem("pageid", "1") .Elem("path", "x/y/z")); Assert.IsTrue(varnishResetEvent.WaitOne(5000, false)); Assert.AreEqual(0, dekiCalled); Assert.AreEqual(1, varnishCalled); Assert.AreEqual("^/((x/y/z|index\\.php\\?title=x/y/z)[\\?&]?|@api/deki/pages/1/?).*$", varnishHeader); Assert.IsTrue(Wait.For(() => varnishCalled == 1, 10.Seconds()),"varnish wasn't called"); }
protected override Yield Start(XDoc config, Result result) { yield return Coroutine.Invoke(base.Start, config, new Result()); // read configuration settings _username = config["username"].AsText; if(string.IsNullOrEmpty(_username)) { throw new ArgumentException(MISSING_FIELD_ERROR, "username"); } _password = config["password"].AsText; if(string.IsNullOrEmpty(_password)) { throw new ArgumentException(MISSING_FIELD_ERROR, "password"); } _uri = config["mantis-uri"].AsUri; if(_uri == null) { throw new ArgumentException(MISSING_FIELD_ERROR, "mantis-uri"); } // initialize web-service _service = new MantisWebServices.MantisConnect(); _service.Url = _uri.At("api", "soap", "mantisconnect.php").ToString(); result.Return(); }
protected override Yield Start(XDoc config, Result result) { yield return Coroutine.Invoke(base.Start, config, new Result()); // read configuration settings _username = config["username"].AsText; if (string.IsNullOrEmpty(_username)) { throw new ArgumentException(MISSING_FIELD_ERROR, "username"); } _password = config["password"].AsText; if (string.IsNullOrEmpty(_password)) { throw new ArgumentException(MISSING_FIELD_ERROR, "password"); } _uri = config["trac-uri"].AsUri; if (_uri == null) { throw new ArgumentException(MISSING_FIELD_ERROR, "trac-uri"); } // initialize web-service _trac = XmlRpcProxyGen.Create<Trac>(); _trac.Url = _uri.At("login", "xmlrpc").ToString(); if (!string.IsNullOrEmpty(_username)) { _trac.Credentials = new System.Net.NetworkCredential(_username, _password); } result.Return(); }
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))); }