public Yield Invoke(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) { // NOTE (steveb): we convert 'xri://@name/path?params' into 'http://xri.net/@name/path?params' // prepend segments with authority List<string> segments = new List<string>(); segments.Add(uri.Authority); if(uri.Segments != null) { segments.AddRange(uri.Segments); } // build new plug List<PlugHandler> preHandlers = (plug.PreHandlers != null) ? new List<PlugHandler>(plug.PreHandlers) : null; List<PlugHandler> postHandlers = (plug.PostHandlers != null) ? new List<PlugHandler>(plug.PostHandlers) : null; Plug xri = new Plug(new XUri("http", null, null, "xri.net", 80, segments.ToArray(), uri.TrailingSlash, uri.Params, uri.Fragment), plug.Timeout, request.Headers, preHandlers, postHandlers, plug.Credentials, plug.CookieJar, plug.MaxAutoRedirects); // add 'Accept' header for 'application/xrds+xml' mime-type if((xri.Headers == null) || (xri.Headers.Accept == null)) { xri = xri.WithHeader(DreamHeaders.ACCEPT, MimeType.RenderAcceptHeader(MimeType.XRDS)); } // BUGBUGBUG (steveb): this will probably fail in some cases since we may exit this coroutine before the call has completed! xri.InvokeEx(verb, request, response); yield break; }
private IEnumerator<IYield> AuthenticateImportUser(Plug api, string wikiId, string apikey, Result<Plug> result) { XDoc settings = null; yield return api.At("site", "settings").With("apikey", apikey).GetAsync().Set(x => settings = x.ToDocument()); var username = settings["packageupdater/username"].AsText ?? settings["security/admin-user-for-impersonation"].AsText; string authToken = null; if(string.IsNullOrEmpty(username)) { _log.DebugFormat("[{0}] no user in 'packageupdater/username' config key, trying 'admin'", wikiId); username = "******"; yield return Coroutine.Invoke(Authenticate, api, username, apikey, new Result<string>()).Set(x => authToken = x); if(string.IsNullOrEmpty(authToken)) { _log.DebugFormat("[{0}] 'admin' didn't authenticate, trying 'sysop'", wikiId); username = "******"; } } if(string.IsNullOrEmpty(authToken)) { _log.DebugFormat("[{0}] authenticating as '{1}'", wikiId, username); yield return Coroutine.Invoke(Authenticate, api, username, apikey, new Result<string>()).Set(x => authToken = x); } if(string.IsNullOrEmpty(authToken)) { throw new UnauthorizedAccessException(string.Format("Unable to authenticate as '{0}'", username)); } result.Return(api.WithHeader(DekiWikiService.AUTHTOKEN_HEADERNAME, authToken)); }
private Yield SubscribeIndexer(Plug pubsubPlug, Result result) { _log.DebugFormat("subscribing indexer to pubsub {0}", pubsubPlug.Uri.ToString()); var subscriptionSet = new XDoc("subscription-set") .Elem("uri.owner", Self.Uri) .Start("subscription") .Add(DreamCookie.NewSetCookie("service-key", InternalAccessKey, Self.Uri).AsSetCookieDocument) .Elem("channel", "event://*/deki/pages/noop") .Elem("channel", "event://*/deki/pages/create") .Elem("channel", "event://*/deki/pages/move") .Elem("channel", "event://*/deki/pages/update") .Elem("channel", "event://*/deki/pages/delete") .Elem("channel", "event://*/deki/pages/revert") .Elem("channel", "event://*/deki/pages/rated") .Elem("channel", "event://*/deki/pages/createalias") .Elem("channel", "event://*/deki/pages/tags/update") .Elem("channel", "event://*/deki/pages/dependentschanged/properties/*") .Elem("channel", "event://*/deki/files/noop") .Elem("channel", "event://*/deki/files/create") .Elem("channel", "event://*/deki/files/update") .Elem("channel", "event://*/deki/files/delete") .Elem("channel", "event://*/deki/files/move") .Elem("channel", "event://*/deki/files/restore") .Elem("channel", "event://*/deki/comments/noop") .Elem("channel", "event://*/deki/comments/create") .Elem("channel", "event://*/deki/comments/update") .Elem("channel", "event://*/deki/comments/delete") .Elem("channel", "event://*/deki/users/dependentschanged/properties/*") .Elem("channel", "event://*/deki/users/create") .Elem("channel", "event://*/deki/users/update") .Elem("channel", "event://*/deki/users/login") .Start("recipient") .Attr("authtoken", _apikey) .Elem("uri", Self.Uri.At("queue")) .End() .End(); if(_usePersistentSubscription) { var locationKey = StringUtil.ComputeHashString(pubsubPlug.Uri.AsPublicUri().WithoutQuery() + InternalAccessKey); var accessKey = StringUtil.ComputeHashString(InternalAccessKey); subscriptionSet.Attr("max-failure-duration", _subscriptionMaxFailureDuration); pubsubPlug = pubsubPlug.WithHeader("X-Set-Access-Key", accessKey).WithHeader("X-Set-Location-Key", locationKey); } DreamMessage subscription = null; yield return pubsubPlug.At("subscribers").PostAsync(subscriptionSet).Set(x => subscription = x); // only care about created responses, but log other failures switch(subscription.Status) { case DreamStatus.Created: { var accessKey = subscription.ToDocument()["access-key"].AsText; var location = subscription.Headers.Location; Cookies.Update(DreamCookie.NewSetCookie("access-key", accessKey, location), null); _subscriptionLocation = location.AsLocalUri().WithoutQuery(); _log.DebugFormat("subscribed indexer for events at {0}", _subscriptionLocation); break; } case DreamStatus.Conflict: _log.DebugFormat("didn't subscribe, since we already had a subscription in place"); break; default: _log.WarnFormat("subscribe to {0} failed: {1}", pubsubPlug.Uri.ToString(), subscription.Status); break; } result.Return(); }