public static DreamMessage SavePage(Plug p, string parentPath, string pageTitle, string content, string edittime, out string id, out string path) { string title = pageTitle; if (parentPath != string.Empty) title = parentPath + pageTitle; title = "=" + XUri.DoubleEncode(title); p = p.At("pages", title, "contents"); if (!string.IsNullOrEmpty(edittime)) p = p.With("edittime", edittime); DreamMessage msg = p.PostAsync(DreamMessage.Ok(MimeType.TEXT_UTF8, content)).Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "Page creation failed!"); id = msg.ToDocument()["page/@id"].AsText; path = msg.ToDocument()["page/path"].AsText; Assert.IsTrue(!string.IsNullOrEmpty(path), "Page path is null!"); Assert.IsTrue(!string.IsNullOrEmpty(id), "Page ID is null!"); return msg; }
//--- Methods --- protected override Yield Start(XDoc config, IContainer container, Result result) { yield return Coroutine.Invoke(base.Start, config, new Result()); // set up plug for phpscript that will handle the notifications _emailer = Plug.New(config["uri.emailer"].AsUri); // set up plug deki, so we can validate users _deki = Plug.New(config["uri.deki"].AsUri); // get the apikey, which we will need as a subscription auth token for subscriptions not done on behalf of a user _apikey = config["apikey"].AsText; _cache = new PageChangeCache(_deki.With("apikey", _apikey), TimeSpan.FromSeconds(config["page-cache-ttl"].AsInt ?? 2)); if(!container.IsRegistered<IPageSubscriptionInstance>()) { var builder = new ContainerBuilder(); builder.Register<PageSubscriptionInstance>().As<IPageSubscriptionInstance>().FactoryScoped(); builder.Build(container); } // TODO (arnec): this should be hitting the API to retrieve resources // resource manager for email template var resourcePath = Config["resources-path"].AsText; if(!string.IsNullOrEmpty(resourcePath)) { _resourceManager = new PlainTextResourceManager(Environment.ExpandEnvironmentVariables(resourcePath)); } else { // creating a test resource manager _log.WarnFormat("'resource-path' was not defined in Config, using a test resource manager for email templating"); var testSet = new TestResourceSet { {"Notification.Page.email-subject", "Page Modified"}, {"Notification.Page.email-header", "The following pages have changed:"} }; _resourceManager = new PlainTextResourceManager(testSet); } // set up subscription for pubsub var subscriptionSet = new XDoc("subscription-set") .Elem("uri.owner", Self.Uri.AsServerUri().ToString()) .Start("subscription") .Elem("channel", "event://*/deki/users/*") .Add(DreamCookie.NewSetCookie("service-key", InternalAccessKey, Self.Uri).AsSetCookieDocument) .Start("recipient") .Attr("authtoken", _apikey) .Elem("uri", Self.Uri.AsServerUri().At("updateuser").ToString()) .End() .End() .Start("subscription") .Elem("channel", "event://*/deki/pages/create") .Elem("channel", "event://*/deki/pages/update") .Elem("channel", "event://*/deki/pages/delete") .Elem("channel", "event://*/deki/pages/revert") .Elem("channel", "event://*/deki/pages/move") .Elem("channel", "event://*/deki/pages/tags/update") .Elem("channel", "event://*/deki/pages/dependentschanged/comments/create") .Elem("channel", "event://*/deki/pages/dependentschanged/comments/update") .Elem("channel", "event://*/deki/pages/dependentschanged/comments/delete") .Elem("channel", "event://*/deki/pages/dependentschanged/files/create") .Elem("channel", "event://*/deki/pages/dependentschanged/files/update") .Elem("channel", "event://*/deki/pages/dependentschanged/files/delete") .Elem("channel", "event://*/deki/pages/dependentschanged/files/properties/*") .Elem("channel", "event://*/deki/pages/dependentschanged/files/restore") .Add(DreamCookie.NewSetCookie("service-key", InternalAccessKey, Self.Uri).AsSetCookieDocument) .Start("recipient") .Attr("authtoken", _apikey) .Elem("uri", Self.Uri.AsServerUri().At("notify").ToString()) .End() .End(); Result<DreamMessage> subscribe; yield return subscribe = PubSub.At("subscribers").PostAsync(subscriptionSet); string accessKey = subscribe.Value.ToDocument()["access-key"].AsText; XUri location = subscribe.Value.Headers.Location; Cookies.Update(DreamCookie.NewSetCookie("access-key", accessKey, location), null); _subscriptionLocation = Plug.New(location.AsLocalUri().WithoutQuery()); _log.DebugFormat("set up initial subscription location at {0}", _subscriptionLocation.Uri); // set up notification accumulator queue TimeSpan accumulationMinutes = TimeSpan.FromSeconds(config["accumulation-time"].AsInt ?? 10 * 60); _log.DebugFormat("Initializing queue with {0:0.00} minute accumulation", accumulationMinutes.TotalMinutes); _notificationQueue = new NotificationDelayQueue(accumulationMinutes, SendEmail); result.Return(); }
//--- Methods --- protected override Yield Start(XDoc config, Result result) { yield return Coroutine.Invoke(base.Start, config, new Result()); // set up plug for phpscript that will handle the notifications _emailer = Plug.New(config["uri.emailer"].AsUri); // set up plug deki, so we can validate users _deki = Plug.New(config["uri.deki"].AsUri); // get the apikey, which we will need as a subscription auth token for subscriptions not done on behalf of a user _apikey = config["apikey"].AsText; _cache = new PageChangeCache(_deki.With("apikey", _apikey), TimeSpan.FromSeconds(config["page-cache-ttl"].AsInt ?? 2)); // resource manager for email template string resourcePath = Config["resources-path"].AsText; if(!string.IsNullOrEmpty(resourcePath)) { _resourceManager = new PlainTextResourceManager(Environment.ExpandEnvironmentVariables(resourcePath)); } else { // creating a test resource manager _log.WarnFormat("'resource-path' was not defined in Config, using a test resource manager for email templating"); TestResourceSet testSet = new TestResourceSet(); testSet.Add("Notification.Page.email-subject", "Page Modified"); testSet.Add("Notification.Page.email-header", "The following pages have changed:"); _resourceManager = new PlainTextResourceManager(testSet); } // get persisted subscription storage List<Tuplet<string, List<XDoc>>> allWikiSubs = new List<Tuplet<string, List<XDoc>>>(); Result<DreamMessage> storageCatalog; yield return storageCatalog = Storage.At("subscriptions").GetAsync(); foreach(XDoc wikiSubs in storageCatalog.Value.ToDocument()["folder/name"]) { string wikihost = wikiSubs.AsText; Tuplet<string, List<XDoc>> wikiDoc = new Tuplet<string, List<XDoc>>(wikihost, new List<XDoc>()); allWikiSubs.Add(wikiDoc); Result<DreamMessage> wikiUsers; yield return wikiUsers = Storage.At("subscriptions", wikihost).GetAsync(); foreach(XDoc userDocname in wikiUsers.Value.ToDocument()["file/name"]) { string userFile = userDocname.AsText; if(!userFile.EndsWith(".xml")) { _log.WarnFormat("Found stray file '{0}' in wiki '{1}' store, ignoring", userFile, wikihost); continue; } Result<DreamMessage> userDoc; yield return userDoc = Storage.At("subscriptions", wikihost, userFile).GetAsync(); try { wikiDoc.Item2.Add(userDoc.Value.ToDocument()); } catch(InvalidDataException e) { _log.Error(string.Format("Unable to retrieve subscription store for user {0}/{1}", wikihost, userFile), e); } } } _subscriptions = new SubscriptionManager(Self.Uri.AsServerUri().At("notify"), allWikiSubs); _subscriptions.RecordsChanged += PersistSubscriptions; _subscriptions.SubscriptionsChanged += PushSubscriptionSetUpstream; // set up subscription for pubsub _baseSubscriptionSet = new XDoc("subscription-set") .Elem("uri.owner", Self.Uri.AsServerUri().ToString()) .Start("subscription") .Elem("channel", "event://*/deki/users/*") .Add(DreamCookie.NewSetCookie("service-key", InternalAccessKey, Self.Uri).AsSetCookieDocument) .Start("recipient") .Attr("authtoken", _apikey) .Elem("uri", Self.Uri.AsServerUri().At("updateuser").ToString()) .End() .End(); XDoc subSet = _baseSubscriptionSet.Clone(); foreach(XDoc sub in _subscriptions.Subscriptions) { subSet.Add(sub); } Result<DreamMessage> subscribe; yield return subscribe = PubSub.At("subscribers").PostAsync(subSet); string accessKey = subscribe.Value.ToDocument()["access-key"].AsText; XUri location = subscribe.Value.Headers.Location; Cookies.Update(DreamCookie.NewSetCookie("access-key", accessKey, location), null); _subscriptionLocation = Plug.New(location.AsLocalUri().WithoutQuery()); _log.DebugFormat("set up initial subscription location at {0}", _subscriptionLocation.Uri); // set up notification accumulator queue TimeSpan accumulationMinutes = TimeSpan.FromSeconds(config["accumulation-time"].AsInt ?? 10 * 60); _log.DebugFormat("Initializing queue with {0:0.00} minute accumulation", accumulationMinutes.TotalMinutes); _notificationQueue = new NotificationDelayQueue(accumulationMinutes, SendEmail); result.Return(); }
//--- Methods --- internal bool RunTest(Plug converter) { foreach(KeyValuePair<string, string> setting in Settings) { converter = converter.With(setting.Key, setting.Value); } DreamMessage message = converter.With("text", Test).PostQuery(); string result = message.AsText(); string[] received = result.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); XDoc converted = XDocFactory.From(result, MimeType.HTML); Site site = new Site(); string lang; if(Settings.TryGetValue("lang", out lang)) { site.Language = lang; } string title; if(!Settings.TryGetValue("title", out title)) { title = "None"; } WikiTextProcessor.Convert(site, converted, StringUtil.StartsWithInvariantIgnoreCase(title, "Template:")); string[] actual = converted.ToPrettyString().Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); bool success = true; if(actual.Length == Expected.Length) { for(int i = 0; i < Expected.Length; ++i) { if(actual[i] != Expected[i]) { success = false; break; } } } else { success = false; } if(!success) { string bug; if(Settings.TryGetValue("bug", out bug)) { Console.WriteLine("Line {0}, Bug# {1}", Line, bug); } else { Console.WriteLine("Line {0}", Line); } Console.WriteLine(); Console.WriteLine("Sent"); Console.WriteLine("----"); Console.WriteLine(Test); Console.WriteLine(); Console.WriteLine("Received"); Console.WriteLine("--------"); foreach(string line in received) { Console.WriteLine(line); } Console.WriteLine(); Console.WriteLine("Converted"); Console.WriteLine("---------"); Console.WriteLine(converted.ToPrettyString()); Console.WriteLine(); Console.WriteLine("Expected"); Console.WriteLine("--------"); foreach(string line in Expected) { Console.WriteLine(line); } Console.WriteLine(); Console.WriteLine("========================================"); return false; } return true; }