예제 #1
0
파일: PageUtils.cs 프로젝트: heran/DekiWiki
        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();
        }
예제 #4
0
 //--- 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;
 }