public Yield GetPageRating(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     UserBE user = DekiContext.Current.User;
     PageBE page = PageBL.AuthorizePage(user, Permissions.READ, false);
     XDoc ret = RatingBL.GetRatingXml(page, user);
     response.Return(DreamMessage.Ok(ret));
     yield break;
 }
        protected user Authenticate(DreamContext context, DreamMessage request, DekiUserLevel level) {
            user result = null;

            // get username and password
            string user;
            string password;
            if (!DreamUtil.GetAuthentication(context, request, out user, out password)) {

                // anonymous access is always granted
                if (level == DekiUserLevel.Anonymous) {

                    // TODO (steveb): missing code
                    throw new NotImplementedException("return anonymous user");
                } else {
                    throw new DreamAbortException(DreamMessage.AccessDenied(AuthenticationRealm, "authentication failed"));
                }
            }

            // validate username and password
            result = MindTouch.Deki.user.GetUserByName(user);
            if (result == null) {
                throw new DreamAbortException(DreamMessage.AccessDenied(AuthenticationRealm, "authentication failed"));
            }
            if (!result.checkPassword(password)) {
                throw new DreamAbortException(DreamMessage.AccessDenied(AuthenticationRealm, "authentication failed"));
            }
            if ((level == DekiUserLevel.Admin) && !result.isSysop()) {
                throw new DreamAbortException(DreamMessage.AccessDenied(AuthenticationRealm, "authentication failed"));
            }
            return result;
        }
 public Yield PostBans(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
     BanBE ban = BanningBL.SaveBan(request.ToDocument());
     DekiContext.Current.Instance.EventSink.BanCreated(context.StartTime, ban);
     response.Return(DreamMessage.Ok(BanningBL.GetBanXml(ban)));
     yield break;
 }
Exemplo n.º 4
0
 //--- Methods ---
 private void CallbackHandler(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) {
     if(uri.Segments.Length == 0) {
         response.Return(DreamMessage.Ok());
         return;
     }
     var segments = uri.Segments;
     var wikiId = segments[0];
     if(wikiId.StartsWith("=")) {
         var id = (HostLookupOverride == null) ? DefaultWikiId : HostLookupOverride(wikiId.Substring(1));
         response.Return(DreamMessage.Ok(new XDoc("wiki").Attr("id", id)));
         return;
     }
     if(segments.Length == 2 && segments[1] == "license") {
         XDoc license;
         if(LicenseOverride == null) {
             _log.Debug("returning license from disk");
             license = XDocFactory.LoadFrom(Utils.Settings.LicensePath, MimeType.TEXT_XML);
         } else {
             _log.Debug("returning license from override callback");
             license = LicenseOverride(wikiId);
         }
         response.Return(DreamMessage.Ok(license));
         return;
     }
     var config = (ConfigOverride == null) ? DefaultConfig : ConfigOverride(wikiId);
     response.Return(DreamMessage.Ok(config));
 }
Exemplo n.º 5
0
 public Yield GetSiteStatus(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.UPDATE);
     var status = new XDoc("status")
         .Elem("state", DekiContext.Current.Instance.Status);
     response.Return(DreamMessage.Ok(status));
     yield break;
 }
Exemplo n.º 6
0
        public Yield GetTags(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
            string type = DreamContext.Current.GetParam("type", "");
            string fromStr = DreamContext.Current.GetParam("from", "");
            string toStr = DreamContext.Current.GetParam("to", "");
            bool showPages = DreamContext.Current.GetParam("pages", false);
            string partialName = DreamContext.Current.GetParam("q", "");

            // parse type
            TagType tagType = TagType.ALL;
            if(!string.IsNullOrEmpty(type) && !SysUtil.TryParseEnum(type, out tagType)) {
                throw new DreamBadRequestException("Invalid type parameter");
            }

            // check and validate from date
            DateTime from = (tagType == TagType.DATE) ? DateTime.Now : DateTime.MinValue;
            if(!string.IsNullOrEmpty(fromStr) && !DateTime.TryParse(fromStr, out from)) {
                throw new DreamBadRequestException("Invalid from date parameter");
            }

            // check and validate to date
            DateTime to = (tagType == TagType.DATE) ? from.AddDays(30) : DateTime.MaxValue;
            if(!string.IsNullOrEmpty(toStr) && !DateTime.TryParse(toStr, out to)) {
                throw new DreamBadRequestException("Invalid to date parameter");
            }

            // execute query
            var tags = TagBL.GetTags(partialName, tagType, from, to);
            XDoc doc = TagBL.GetTagListXml(tags, "tags", null, showPages);
            response.Return(DreamMessage.Ok(doc));
            yield break;
        }
 public Yield SubscribeToChange(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     var wikiId = GetWikiIdFromRequest(request);
     var pageId = context.GetParam<uint>("pageid");
     var depth = context.GetParam("depth", "0") == "0" ? false : true;
     Result<PageSubscriptionUser> userResult;
     yield return userResult = Coroutine.Invoke(GetRequestUser, request, new Result<PageSubscriptionUser>()).Catch();
     if(userResult.HasException) {
         ReturnUserError(userResult.Exception, response);
         yield break;
     }
     var userInfo = userResult.Value;
     DreamMessage pageAuth = null;
     yield return _deki
         .At("pages", pageId.ToString(), "allowed")
         .With("permissions", "read,subscribe")
         .WithHeaders(request.Headers)
         .Post(new XDoc("users").Start("user").Attr("id", userInfo.Id).End(), new Result<DreamMessage>())
         .Set(x => pageAuth = x);
     if(!pageAuth.IsSuccessful || pageAuth.ToDocument()["user/@id"].AsText != userInfo.Id.ToString()) {
         throw new DreamForbiddenException("User not permitted to subscribe to page");
     }
     var dataSession = GetDataSession(wikiId);
     dataSession.Subscribe(userInfo.Id, pageId, depth);
     response.Return(DreamMessage.Ok());
     yield break;
 }
Exemplo n.º 8
0
        public Yield Register(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
            string servicePath = context.GetParam("service-path");
            string location = StringUtil.CreateAlphaNumericKey(8);

            // register the script
            XDoc config = new XDoc("config")
                .Elem("manifest", servicePath)
                .Elem("debug", true);

            //create the script service
            Result<Plug> res;
            yield return res = CreateService(location, "sid://mindtouch.com/2007/12/dekiscript", config, new Result<Plug>());
            Plug service = res.Value;

            // register script functions in environment
            XDoc manifest = service.Get().ToDocument();
            string ns = manifest["namespace"].AsText;
            foreach(XDoc function in manifest["function"]) {
                string name = function["name"].AsText;
                if(string.IsNullOrEmpty(ns)) {
                    _env.Vars.AddNativeValueAt(name, function["uri"].AsUri);
                } else {
                    _env.Vars.AddNativeValueAt(ns + "." + name, function["uri"].AsUri);
                }
            }
            response.Return(DreamMessage.Ok(MimeType.XML, manifest));
        }
Exemplo n.º 9
0
		public Yield DeleteSource(DreamContext context, DreamMessage request, Result<DreamMessage> response)
		{
			Result<bool> result = new Result<bool>();
			yield return Context.Current.Instance.SourceController.Delete(context.GetParam("id"), context.GetParam("rev",null), result);

			response.Return(DreamMessage.Ok(MimeType.JSON, result.Value.ToString()));
		} 
Exemplo n.º 10
0
 public DreamMessage GetContentHandler(DreamContext context, DreamMessage message) {
     user user = Authenticate(context, message, DekiUserLevel.User);
     page page = Authorize(context, user, DekiAccessLevel.Read, "pageid");
     DekiContext deki = new DekiContext(message, this.DekiConfig);
     bool nofollow = (context.Uri.GetParam("nofollow", 0, null) != null);
     string contents = page.getContent(nofollow);
     string xml = string.Format(DekiWikiService.XHTML_LOOSE, contents);
     XDoc doc = XDoc.FromXml(xml);
     if (doc == null) {
         LogUtils.LogWarning(_log, "GetContentHandler: null document page content", page.PrefixedName, contents);
         throw new DreamAbortException(DreamMessage.BadRequest("null document"));
     }
     XDoc result = new XDoc("list");
     string type = context.Uri.GetParam("type", 0, null);
     string id = context.Uri.GetParam("id", 0, null);
     if (id != null) {
         XDoc widget = doc[string.Format("//default:span[@widgetid={0}]", id)];
         if (widget.IsEmpty) {
             LogUtils.LogWarning(_log, "GetContentHandler: widget not found for ID", id);
             return DreamMessage.NotFound("");
         }
         LogUtils.LogTrace(_log, "GetContentHandler: widget by id (id, xspan)", id, widget);
         result.Add(ConvertFromXSpan(widget));
     } else if (type != null) {
         foreach (XDoc widget in doc[string.Format("//default:span[@widgettype='{0}']", type)])
             result.Add(ConvertFromXSpan(widget));
         LogUtils.LogTrace(_log, "GetContentHandler: widget by type (type, #)", type, result.Count);
     } else {
         foreach (XDoc widget in doc["//default:span[@class='widget']"])
             result.Add(ConvertFromXSpan(widget));
         LogUtils.LogTrace(_log, "GetContentHandler: all widgets (#)", type, result.Count);
     }
     return DreamMessage.Ok(result);
 }
Exemplo n.º 11
0
 public Yield GetPage(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     CheckResponseCache(context, false);
     PageBE page = PageBL.GetPageFromUrl(true);
     page = PageBL.AuthorizePage(DekiContext.Current.User, Permissions.READ, page, false);
     response.Return(DreamMessage.Ok(PageBL.GetPageXmlVerbose(page, null)));
     yield break;
 }
Exemplo n.º 12
0
        public static CommentBE PostNewComment(PageBE page, DreamMessage request, DreamContext context) {
            ValidateCommentText(request.ContentType, request.AsText());

            CommentBE comment = new CommentBE();
            comment.Title = context.GetParam("title", string.Empty);
            comment.PageId = page.ID;
            comment.Content = request.AsText();
            comment.ContentMimeType = request.ContentType.ToString();
            comment.PosterUserId = DekiContext.Current.User.ID;
            comment.CreateDate = DateTime.UtcNow;

            //Note (MaxM): Replytoid/replies not yet exposed
            //ulong replyToId = context.GetParam<ulong>("replyto", 0);
            //if (replyToId == 0)
            //    newComment.ReplyToId = null;
            //else
            //    newComment.ReplyToId = replyToId;

            ushort commentNumber;
            uint commentId = DbUtils.CurrentSession.Comments_Insert(comment, out commentNumber);
            if (commentId == 0) {
                return null;
            } else {
                comment.Id = commentId;
                comment.Number = commentNumber;
                PageBL.Touch(page, comment.CreateDate);
                RecentChangeBL.AddCommentCreateRecentChange(comment.CreateDate, page, DekiContext.Current.User, string.Format(DekiResources.COMMENT_ADDED, comment.Number.ToString()), comment);
                return comment;
            } 
        }
Exemplo n.º 13
0
        public Yield GetSearchDescription(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
            XDoc description = new XDoc("OpenSearchDescription", "http://a9.com/-/spec/opensearch/1.1/");
            description.Elem("ShortName", string.Format(DekiResources.OPENSEARCH_SHORTNAME, DekiContext.Current.Instance.SiteName))
                       .Elem("Description", DekiResources.OPENSEARCH_DESCRIPTION)
                       .Start("Query")
                            .Attr("role", "example")
                            .Attr("searchTerms", "Wiki")
                       .End();

            // HACK HACK HACK: we can't use XUri because it encodes the "{}" characters
            string uri = DekiContext.Current.ApiUri.At("site", "opensearch").ToString();
            uri += "?q={searchTerms}&offset={startIndex}&limit={count?}&";

            description.Start("Url")
                 .Attr("type", "text/html")
                 .Attr("indexOffset", 0)
                 .Attr("template", DekiContext.Current.UiUri.At("Special:Search").ToString() + "?search={searchTerms}&offset=0&limit={count?}&format=html")
            .End()
            .Start("Url")
                 .Attr("type", "application/atom+xml")
                 .Attr("indexOffset", 0)
                 .Attr("template", uri + "format=atom")
            .End()
            .Start("Url")
                 .Attr("type", "application/rss+xml")
                 .Attr("indexOffset", 0)
                 .Attr("template", uri + "format=rss")
            .End()
            .Start("Url")
                 .Attr("type", "application/x-suggestions+json")
                 .Attr("template", DekiContext.Current.ApiUri.At("site", "opensearch", "suggestions").ToString() + "?q={searchTerms}")
             .End();
            response.Return(DreamMessage.Ok(description));
            yield break;
        }
        public Yield GetServiceById(DreamContext context, DreamMessage request, Result<DreamMessage> response) {

            bool privateDetails = PermissionsBL.IsUserAllowed(DekiContext.Current.User, Permissions.ADMIN);

            //Private feature requires api-key
            var identifier = context.GetParam("id");
            uint serviceId = 0;
            if(identifier.StartsWith("=")) {
                var serviceInfo = DekiContext.Current.Instance.RunningServices[XUri.Decode(identifier.Substring(1))];
                if(serviceInfo != null) {
                    serviceId = serviceInfo.ServiceId;
                }
            } else {
                if(!uint.TryParse(identifier, out serviceId)) {
                    throw new DreamBadRequestException(string.Format("Invalid id '{0}'", identifier));
                }
            }
            ServiceBE service = ServiceBL.GetServiceById(serviceId);
            DreamMessage responseMsg = null;
            if(service == null) {
                responseMsg = DreamMessage.NotFound(string.Format(DekiResources.SERVICE_NOT_FOUND, identifier));
            } else {
                responseMsg = DreamMessage.Ok(ServiceBL.GetServiceXmlVerbose(DekiContext.Current.Instance, service, null, privateDetails));
            }
            response.Return(responseMsg);
            yield break;
        }
Exemplo n.º 15
0
 public AwsSqsRequestException(AwsSqsError error, DreamMessage request)
     : base(error.Message)
 {
     Request = request;
     Error = error;
     IsSqsError = true;
 }
Exemplo n.º 16
0
 public Yield GetGroup(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.READ);
     GroupBE group = GetGroupFromUrl();
     DreamMessage responseMsg = DreamMessage.Ok(GroupBL.GetGroupXmlVerbose(group, null));
     response.Return(responseMsg);
     yield break;
 }
Exemplo n.º 17
0
 public Yield GetPageTags(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     PageBE page = PageBL.AuthorizePage(DekiContext.Current.User, Permissions.READ, false);
     XUri href = DekiContext.Current.ApiUri.At("pages", page.ID.ToString(), "tags");
     XDoc doc = TagBL.GetTagListXml(TagBL.GetTagsForPage(page), "tags", href, false);
     response.Return(DreamMessage.Ok(doc));
     yield break;
 } 
 public Yield SubscribeToChange(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     uint pageId = context.GetParam<uint>("pageid");
     string depth = context.GetParam("depth", "0");
     Result<UserInfo> userResult;
     yield return userResult = Coroutine.Invoke(GetUserInfo, true, request, new Result<UserInfo>()).Catch();
     if(userResult.HasException) {
         ReturnUserError(userResult.Exception, response);
         yield break;
     }
     UserInfo userInfo = userResult.Value;
     DreamMessage pageAuth = null;
     yield return _deki
         .At("pages", pageId.ToString(), "allowed")
         .With("permissions", "read,subscribe")
         .WithHeaders(request.Headers)
         .Post(new XDoc("users").Start("user").Attr("id", userInfo.Id).End(), new Result<DreamMessage>())
         .Set(x => pageAuth = x);
     if(!pageAuth.IsSuccessful || pageAuth.ToDocument()["user/@id"].AsText != userInfo.Id.ToString()) {
         throw new DreamForbiddenException("User not permitted to subscribe to page");
     }
     userInfo.AddResource(pageId, depth);
     userInfo.Save();
     response.Return(DreamMessage.Ok());
     yield break;
 }
Exemplo n.º 19
0
        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;
        }
Exemplo n.º 20
0
 public Yield GetCommentContent(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     PageBE page = null;
     CommentBE comment = null;
     GetCommentFromRequest(context, Permissions.READ, out page, out comment);
     response.Return(DreamMessage.Ok(new MimeType(comment.ContentMimeType), comment.Content));
     yield break;
 }
 public Yield GetArchiveFiles(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
     IList<AttachmentBE> removedFiles = AttachmentBL.Instance.GetResources(DeletionFilter.DELETEDONLY, null, null);
     XDoc responseXml = AttachmentBL.Instance.GetFileXml(removedFiles, true, "archive", null, null);            
     response.Return(DreamMessage.Ok(responseXml));
     yield break;
 }
        public Yield PutSiteRole(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
            PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);

            RoleBE role = GetRoleFromUrl(false);
            role = PermissionsBL.PutRole(role, request, context);
            response.Return(DreamMessage.Ok(PermissionsBL.GetRoleXml(role, null)));
            yield break;
        }
Exemplo n.º 23
0
 private void WriteErrorRequest(DreamMessage request)
 {
     try
     {
         WriteLineToLog("Request message: " + request.ToString());
     }
     catch { }
 }
        private Yield PrologueMediaWikiConverterContext(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
            MediaWikiConverterContext mwContext = new MediaWikiConverterContext(Config);
            DreamContext.Current.SetState<MediaWikiConverterContext>(mwContext);

            // continue processing
            response.Return(request);
            yield break;
        }
Exemplo n.º 25
0
 public DreamMessage PostTidyXHmlt(DreamContext context, DreamMessage message) {
     string baseHref = context.Uri.GetParam("base", "");
     string pageID = context.Uri.GetParam("context", "");
     bool toEdit = context.Uri.GetParam<bool>("toEdit", false);
     XDoc doc = XDoc.FromHtml(new StreamReader(message.Stream, message.ContentEncoding));
     XHTMLConverter.Convert(doc, baseHref, pageID, toEdit);
     return DreamMessage.Ok(MimeType.XHTML, doc.Root.ToXHtml());
 }
Exemplo n.º 26
0
		public Yield GetInfo(DreamContext aContext, DreamMessage aRequest, Result<DreamMessage> aResponse)
		{
			XDoc xmlInfo = new XDoc("info");
			xmlInfo.Elem("User", Context.Current.User);
			xmlInfo.Elem("About", "Foiremuses web service (c) 2011 Vincent DARON / Danny WILLEM");
			aResponse.Return(DreamMessage.Ok(MimeType.XML, xmlInfo));
			yield break;
		}
Exemplo n.º 27
0
		public Yield UpdateSource(DreamContext context, DreamMessage request, Result<DreamMessage> response)
		{
			ISource source = Context.Current.Instance.SourceController.FromJson(request.ToText());
			Result<ISource> result = new Result<ISource>();
			yield return Context.Current.Instance.SourceController.Update(context.GetParam("id"), context.GetParam("rev", null), source, result);

			response.Return(DreamMessage.Ok(MimeType.JSON, Context.Current.Instance.SourceController.ToJson(result.Value)));
		}
Exemplo n.º 28
0
		public Yield CreatePlay(DreamContext context, DreamMessage request, Result<DreamMessage> response)
		{
			IPlay play  = Context.Current.Instance.PlayController.FromJson(request.ToText());
			Result<IPlay> result = new Result<IPlay>();
			yield return Context.Current.Instance.PlayController.Insert(play, result);

			response.Return(DreamMessage.Ok(MimeType.JSON, Context.Current.Instance.PlayController.ToJson(result.Value)));
		}
Exemplo n.º 29
0
 internal IEnumerator<IYield> GetImportStatus(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     var wikiId = context.GetParam("wikiid");
     _log.DebugFormat("checking status on instance '{0}'", wikiId);
     var instance = GetInstance(wikiId, false);
     var status = instance == null ? "none" : instance.Status.ToString().ToLower();
     response.Return(DreamMessage.Ok(new XDoc("package-updater").Attr("wikiid", wikiId).Attr("status", status)));
     yield break;
 }
 public Yield GetArchive(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
     XDoc ret = new XDoc("archive");
     ret.Start("pages.archive").Attr("href", DekiContext.Current.ApiUri.At("archive", "pages")).End();
     ret.Start("files.archive").Attr("href", DekiContext.Current.ApiUri.At("archive", "files")).End();
     response.Return(DreamMessage.Ok(ret));
     yield break;
 }
Exemplo n.º 31
0
 //--- Constructors ---
 public DreamCachedResponseException(DreamMessage response)
 {
     this.Response = response;
 }
Exemplo n.º 32
0
 private static object GetMessageResponse(DreamContext context, DreamMessage request, Result <DreamMessage> response)
 {
     return(response);
 }
Exemplo n.º 33
0
 private static object GetContextFeatureSubpath(DreamContext context, DreamMessage request, Result <DreamMessage> response)
 {
     return(context.Uri.GetRelativePathTo(context.Feature.ServiceUri));
 }
Exemplo n.º 34
0
 private static object GetRequestAsBytes(DreamContext context, DreamMessage request, Result <DreamMessage> response)
 {
     return(request.ToBytes());
 }
Exemplo n.º 35
0
        //--- Methods ---
        internal void Handler(Result <DreamMessage> result)
        {
            DreamMessage request;

            // check if previous feature handler threw an exception
            try {
                if (result.HasException)
                {
                    DreamAbortException abort = result.Exception as DreamAbortException;
                    if (abort != null)
                    {
                        // extract contained message
                        request = abort.Response;
                    }
                    else
                    {
                        // check if this is a cached response we need to forward
                        DreamCachedResponseException cached = result.Exception as DreamCachedResponseException;
                        if (cached != null)
                        {
                            _response.Throw(cached);
                            return;
                        }

                        // convert exception into message
                        DreamMessage          exceptionMessage = null;
                        ExceptionTranslator[] translators      = _context.Feature.ExceptionTranslators;
                        if (translators != null)
                        {
                            bool locallyAttachedContext = false;
                            try {
                                if (DreamContext.CurrentOrNull == null)
                                {
                                    _context.AttachToCurrentTaskEnv();
                                    locallyAttachedContext = true;
                                }
                                foreach (var translate in translators)
                                {
                                    exceptionMessage = translate(_context, result.Exception);
                                    if (exceptionMessage != null)
                                    {
                                        break;
                                    }
                                }
                            } finally {
                                if (locallyAttachedContext)
                                {
                                    _context.DetachFromTaskEnv();
                                }
                            }
                        }
                        if (exceptionMessage == null)
                        {
                            _log.ErrorExceptionFormat(result.Exception, "handler for {0}:{1} failed ({2})", _context.Verb, _context.Uri.ToString(false), _previousName);
                            exceptionMessage = DreamMessage.InternalError(result.Exception);
                        }
                        request = exceptionMessage;
                    }
                }
                else
                {
                    request = result.Value;
                }
            } catch (Exception e) {
                if (result.HasException)
                {
                    _log.ErrorExceptionFormat(result.Exception, "handler for {0}:{1} failed ({2}), cascading via processing exception '{3}'", _context.Verb, _context.Uri.ToString(false), _previousName, e);
                    request = DreamMessage.InternalError(result.Exception);
                }
                else
                {
                    _log.ErrorExceptionFormat(e, "handler for {0}:{1} failed completing stage '{2}'", _context.Verb, _context.Uri.ToString(false), _previousName);
                    request = DreamMessage.InternalError(e);
                }
            }

            // check if feature handler can handle this message
            if (!MainStage || request.IsSuccessful)
            {
                TaskEnv.ExecuteNew(() => Handler_DreamMessage(request));
            }
            else
            {
                // non-success messages skip the main stage
                _response.Return(request);
            }
        }
Exemplo n.º 36
0
 private Yield InServiceInvokeHandler(DreamContext context, DreamMessage request, Result <DreamMessage> response)
 {
     throw new InvalidOperationException("this feature should never be invoked");
 }
Exemplo n.º 37
0
        /// <summary>
        /// Invoke an action in the context of a service feature.
        /// </summary>
        /// <remarks>
        /// Assumes that there exists a current <see cref="DreamContext"/> that belongs to a request to another feature of this service.
        /// </remarks>
        /// <param name="verb">Http verb.</param>
        /// <param name="path">Feature path.</param>
        /// <param name="handler">Action to perform in this context.</param>
        /// <returns>Exception thrown by handler or null.</returns>
        public Exception InvokeInServiceContext(string verb, string path, Action handler)
        {
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }
            if (string.IsNullOrEmpty(verb))
            {
                throw new ArgumentNullException("verb");
            }
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            // create new new environment for execution
            XUri         uri     = Self.AtPath(path);
            DreamContext current = DreamContext.Current;
            Exception    e       = TaskEnv.ExecuteNew(delegate {
                DreamFeatureStage[] stages = new[] {
                    new DreamFeatureStage("InServiceInvokeHandler", InServiceInvokeHandler, DreamAccess.Private)
                };

                // BUGBUGBUG (steveb): when invoking a remote function this way, we're are not running the proloques and epilogues, which leads to errors;
                //  also dream-access attributes are being ignored (i.e. 'public' vs. 'private')
                DreamMessage message = DreamUtil.AppendHeadersToInternallyForwardedMessage(current.Request, DreamMessage.Ok());
                var context          = current.CreateContext(verb, uri, new DreamFeature(this, Self, 0, stages, verb, path), message);
                context.AttachToCurrentTaskEnv();

                // pass along host and public-uri information
                handler();
            }, TimerFactory);

            return(e);
        }
Exemplo n.º 38
0
        //--- Constructors ---

        /// <summary>
        /// Create new instance with a message describing the reason for the aborted request.
        /// </summary>
        /// <param name="response">Message describing the reason for the aborted request.</param>
        public DreamAbortException(DreamMessage response) : base(DreamMessage.GetStatusStringOrNull(response))
        {
            this.Response = response;
        }
Exemplo n.º 39
0
        private Dictionary <string, string> CheckServiceLicense()
        {
            // check request validity (unless it's for the @config uri, which is a special case)
            Dictionary <string, string> result = null;

            if ((Feature.Service.Self != null) && (Feature.Service is IDreamServiceLicense) && !(Uri.LastSegment ?? string.Empty).EqualsInvariant("@config"))
            {
                string service_license = ((IDreamServiceLicense)Feature.Service).ServiceLicense;
                if (string.IsNullOrEmpty(service_license))
                {
                    throw new DreamAbortException(DreamMessage.LicenseRequired("service-license missing"));
                }

                // extract public RSA key for validation
                RSACryptoServiceProvider public_key = RSAUtil.ProviderFrom(Feature.Service.GetType().Assembly);
                if (public_key == null)
                {
                    throw new DreamAbortException(DreamMessage.InternalError("service assembly invalid"));
                }

                // validate the service-license
                try {
                    // parse service-license
                    result = HttpUtil.ParseNameValuePairs(service_license);
                    if (!Encoding.UTF8.GetBytes(service_license.Substring(0, service_license.LastIndexOf(','))).VerifySignature(result["dsig"], public_key))
                    {
                        throw new DreamAbortException(DreamMessage.InternalError("invalid service-license"));
                    }
                } catch (Exception e) {
                    // unexpected error, blame it on the license
                    if (e is DreamAbortException)
                    {
                        throw;
                    }
                    else
                    {
                        throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license"));
                    }
                }

                // check license
                string text;
                if ((!result.TryGetValue("licensee", out text) || string.IsNullOrEmpty(text)) && !result.ContainsKey("expire"))
                {
                    // unexpected error, blame it on the license
                    throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license"));
                }

                // determine 'now' date-time
                DateTime now          = GlobalClock.UtcNow;
                DateTime?request_date = Request.Headers.Date;
                if (request_date.HasValue)
                {
                    now = (request_date.Value > now) ? request_date.Value : now;
                }

                // check expiration
                DateTime expire;
                if (result.TryGetValue("expire", out text) && (!DateTimeUtil.TryParseInvariant(text, out expire) || (expire.ToUniversalTime() < now)))
                {
                    throw new DreamAbortException(DreamMessage.LicenseRequired("service-license has expired"));
                }
            }
            return(result);
        }
Exemplo n.º 40
0
 internal DreamContext CreateContext(string verb, XUri uri, DreamFeature feature, DreamMessage message)
 {
     return(new DreamContext(Env, verb, uri, feature, PublicUri, ServerUri, message, Culture, _requestContainerFactory, null));
 }
Exemplo n.º 41
0
 private DreamContext(IDreamEnvironment env, string verb, XUri uri, DreamFeature feature, XUri publicUri, XUri serverUri, DreamMessage request, CultureInfo culture, Func <Action <ContainerBuilder>, ILifetimeScope> requestContainerFactory, Dictionary <string, string> license)
 {
     if (env == null)
     {
         throw new ArgumentNullException("env");
     }
     if (verb == null)
     {
         throw new ArgumentNullException("verb");
     }
     if (uri == null)
     {
         throw new ArgumentNullException("uri");
     }
     if (feature == null)
     {
         throw new ArgumentNullException("feature");
     }
     if (publicUri == null)
     {
         throw new ArgumentNullException("publicUri");
     }
     if (request == null)
     {
         throw new ArgumentNullException("request");
     }
     if (culture == null)
     {
         throw new ArgumentNullException("culture");
     }
     if (requestContainerFactory == null)
     {
         throw new ArgumentNullException("requestContainerFactory");
     }
     this.ID      = System.Threading.Interlocked.Increment(ref _contextIdCounter);
     this.Env     = env;
     this.Verb    = verb;
     this.Uri     = uri;
     this.Feature = feature;
     this.Feature.ExtractArguments(this.Uri, out _suffixes, out _pathParams);
     this.ServerUri           = serverUri;
     this.Request             = request;
     this.StartTime           = GlobalClock.UtcNow;
     _publicUri               = publicUri;
     _culture                 = culture;
     _requestContainerFactory = requestContainerFactory;
     _license                 = license;
 }
Exemplo n.º 42
0
 /// <summary>
 /// Append Dream specific headers from a source message to an internally forwarded one.
 /// </summary>
 /// <param name="original">Source messag.</param>
 /// <param name="forwarded">Message to be forwarded.</param>
 /// <returns>Message to be forwarded instance.</returns>
 public static DreamMessage AppendHeadersToInternallyForwardedMessage(DreamMessage original, DreamMessage forwarded)
 {
     // pass along host and public-uri information
     forwarded.Headers.DreamTransport = original.Headers.DreamTransport;
     forwarded.Headers.DreamPublicUri = original.Headers.DreamPublicUri;
     forwarded.Headers.DreamUserHost  = original.Headers.DreamUserHost;
     forwarded.Headers.DreamOrigin    = original.Headers.DreamOrigin;
     forwarded.Headers.DreamClientIP  = original.Headers.DreamClientIP;
     return(forwarded);
 }
Exemplo n.º 43
0
        public virtual Yield GetServiceInfo(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            XDoc   blueprint = Blueprint;
            string title     = blueprint["name"].AsText ?? "Service Blueprint";
            XDoc   result    = new XDoc("html").Attr("xmlns", "http://www.w3.org/1999/xhtml")
                               .Start("head")
                               .Elem("title", title)
                               .Start("meta").Attr("http-equiv", "content-type").Attr("content", "text/html;charset=utf-8").End()
                               .Start("meta").Attr("http-equiv", "Content-Style-Type").Attr("content", "text/css").End()
                               .End();

            if (blueprint.IsEmpty)
            {
                result.Elem("body", "Missing service blueprint");
            }
            else
            {
                result.Start("body")
                .Elem("h1", title)
                .Start("p")
                .Value(blueprint["copyright"].Contents)
                .Value(" ")
                .Start("a").Attr("href", blueprint["info"].Contents).Value("(more)").End()
                .Value(" ")
                .Start("a").Attr("href", Self.Uri.At("@blueprint").Path).Value("(blueprint)").End()
                .End();

                // show configuration information
                XDoc config = blueprint["configuration"];
                if (!config.IsEmpty)
                {
                    result.Elem("h2", "Configuration");
                    result.Start("ul");
                    foreach (XDoc entry in config["entry"])
                    {
                        result.Start("li");
                        if (entry["valuetype"].Contents != string.Empty)
                        {
                            result.Value(string.Format("{0} = {1} : {2}", entry["name"].Contents, entry["valuetype"].Contents, entry["description"].Contents));
                        }
                        else
                        {
                            result.Value(string.Format("{0} : {1}", entry["name"].Contents, entry["description"].Contents));
                        }
                        result.End();
                    }
                    result.End();
                }

                // sort features by signature then verb
                blueprint["features"].Sort(delegate(XDoc first, XDoc second) {
                    string[] firstPattern  = first["pattern"].Contents.Split(new[] { ':' }, 2);
                    string[] secondPattern = second["pattern"].Contents.Split(new[] { ':' }, 2);
                    int cmp = firstPattern[1].CompareInvariantIgnoreCase(secondPattern[1]);
                    if (cmp != 0)
                    {
                        return(cmp);
                    }
                    return(firstPattern[0].CompareInvariant(secondPattern[0]));
                });

                // display features
                XDoc features = blueprint["features/feature"];
                if (!features.IsEmpty)
                {
                    result.Elem("h2", "Features");
                    List <string> modifiers = new List <string>();
                    foreach (XDoc feature in features)
                    {
                        modifiers.Clear();

                        // add modifiers
                        string modifier = feature["access"].AsText;
                        if (modifier != null)
                        {
                            modifiers.Add(modifier);
                        }
                        modifier = feature["obsolete"].AsText;
                        if (modifier != null)
                        {
                            modifiers.Add("OBSOLETE => " + modifier);
                        }
                        if (modifiers.Count > 0)
                        {
                            modifier = " (" + string.Join(", ", modifiers.ToArray()) + ")";
                        }
                        else
                        {
                            modifier = string.Empty;
                        }

                        // check if feature has GET verb and no path parameters
                        string pattern = feature["pattern"].Contents;
                        if (pattern.StartsWithInvariantIgnoreCase(Verb.GET + ":") && (pattern.IndexOfAny(new[] { '{', '*', '?' }) == -1))
                        {
                            string[] parts = pattern.Split(new[] { ':' }, 2);
                            result.Start("h3")
                            .Start("a").Attr("href", context.AsPublicUri(Self.Uri.AtPath(parts[1])))
                            .Value(feature["pattern"].Contents)
                            .End()
                            .Value(modifier)
                            .End();
                        }
                        else
                        {
                            result.Elem("h3", feature["pattern"].Contents + modifier);
                        }
                        result.Start("p")
                        .Value(feature["description"].Contents)
                        .Value(" ")
                        .Start("a").Attr("href", feature["info"].Contents).Value("(more)").End();
                        XDoc paramlist = feature["param"];
                        if (!paramlist.IsEmpty)
                        {
                            result.Start("ul");
                            foreach (XDoc param in paramlist)
                            {
                                result.Start("li");
                                if (param["valuetype"].Contents != string.Empty)
                                {
                                    result.Value(string.Format("{0} = {1} : {2}", param["name"].Contents, param["valuetype"].Contents, param["description"].Contents));
                                }
                                else
                                {
                                    result.Value(string.Format("{0} : {1}", param["name"].Contents, param["description"].Contents));
                                }
                                result.End();
                            }
                            result.End();
                        }
                        result.End();
                    }
                }
            }
            response.Return(DreamMessage.Ok(MimeType.HTML, result.ToString()));
            yield break;
        }
Exemplo n.º 44
0
        protected virtual Yield DeleteService(DreamContext context, DreamMessage request, Result <DreamMessage> response)
        {
            yield return(Env.At("stop").Post(new XDoc("service").Elem("uri", Self), new Result <DreamMessage>(TimeSpan.MaxValue)).CatchAndLog(_log));

            response.Return(DreamMessage.Ok());
        }
Exemplo n.º 45
0
 public virtual Yield GetServiceBlueprint(DreamContext context, DreamMessage request, Result <DreamMessage> response)
 {
     response.Return(DreamMessage.Ok(Blueprint));
     yield break;
 }
Exemplo n.º 46
0
 /// <summary>
 /// Create new instance with a message describing the reason for the aborted request.
 /// </summary>
 /// <param name="response">Message describing the reason for the aborted request.</param>
 /// <param name="message">Additional text message about the problem.</param>
 public DreamAbortException(DreamMessage response, string message) : base(message)
 {
     this.Response = response;
 }
Exemplo n.º 47
0
 /// <summary>
 /// Create new instance with a message describing the reason for the aborted request.
 /// </summary>
 /// <param name="response">Message describing the reason for the aborted request.</param>
 /// <param name="message">Additional text message about the problem.</param>
 /// <param name="innerException">The exception that caused the message to be unsuccessful.</param>
 public DreamAbortException(DreamMessage response, string message, Exception innerException) : base(message, innerException)
 {
     this.Response = response;
 }
Exemplo n.º 48
0
        //--- Constructors ---

        /// <summary>
        /// Create a new instance for an <see cref="DreamStatus.InternalError"/> failure.
        /// </summary>
        public DreamInternalErrorException() : base(DreamMessage.InternalError())
        {
        }
Exemplo n.º 49
0
        /// <summary>
        /// Create a new host with provided configuration and an Inversion of Control container.
        /// </summary>
        /// <remarks>
        /// The IoC container is also injected into default activator, so that <see cref="IDreamService"/> instances
        /// can be resolved from the container. The host configuration is provided to the container as a typed parameter.
        /// </remarks>
        /// <param name="config">Host configuration.</param>
        /// <param name="container">IoC Container.</param>
        public DreamHost(XDoc config, IContainer container)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            // read host settings
            string appDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName);
            int    limit        = config["connect-limit"].AsInt ?? 0;
            int    httpPort     = config["http-port"].AsInt ?? DEFAULT_PORT;
            AuthenticationSchemes authenticationScheme = AuthenticationSchemes.Anonymous;
            string authShemes = config["authentication-shemes"].AsText;

            if (!String.IsNullOrEmpty(authShemes))
            {
                try {
                    authenticationScheme = (AuthenticationSchemes)Enum.Parse(typeof(AuthenticationSchemes), authShemes, true);
                } catch (Exception e) {
                    _log.Warn(String.Format("invalid authetication scheme specified :{0}", authShemes), e);
                }
            }

            // get the authtoken for whitelisting dream.in.* query args
            _dreamInParamAuthtoken = config["dream.in.authtoken"].AsText;
            if (!string.IsNullOrEmpty(_dreamInParamAuthtoken))
            {
                _log.Debug("Host is configured in dream.in param authorizing mode");
            }

            // read ip-addresses
            var addresses = new List <string>();

            foreach (XDoc ip in config["host|ip"])
            {
                addresses.Add(ip.AsText);
            }
            if (addresses.Count == 0)
            {
                // if no addresses were supplied listen to all
                addresses.Add("*:" + httpPort);
            }

            // use default servername
            XUri publicUri = config["uri.public"].AsUri;

            if (publicUri == null)
            {
                // backwards compatibility
                publicUri = config["server-name"].AsUri;
                if (publicUri == null)
                {
                    foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
                    {
                        if (addr.AddressFamily == AddressFamily.InterNetwork)
                        {
                            XUri.TryParse("http://" + addr, out publicUri);
                        }
                    }
                    if (publicUri == null)
                    {
                        // failed to get an address out of dns, fall back to localhost
                        XUri.TryParse("http://localhost", out publicUri);
                    }
                }
                publicUri = publicUri.AtPath(config["server-path"].AsText ?? config["path-prefix"].AsText ?? string.Empty);
            }

            // create environment and initialize it
            _env = new DreamHostService(container);
            try {
                // initialize environment
                string apikey        = config["apikey"].AsText ?? StringUtil.CreateAlphaNumericKey(32);
                XDoc   serviceConfig = new XDoc("config");
                var    storageType   = config["storage/@type"].AsText ?? "local";
                if ("s3".EqualsInvariant(storageType))
                {
                    serviceConfig.Add(config["storage"]);
                }
                else
                {
                    serviceConfig.Elem("storage-dir", config["storage-dir"].AsText ?? config["service-dir"].AsText ?? appDirectory);
                }
                serviceConfig.Elem("apikey", apikey);
                serviceConfig.Elem("uri.public", publicUri);
                serviceConfig.Elem("connect-limit", limit);
                serviceConfig.Elem("guid", config["guid"].AsText);
                serviceConfig.AddAll(config["components"]);
                var memorize = config["memorize-aliases"];
                if (!memorize.IsEmpty)
                {
                    serviceConfig.Elem("memorize-aliases", memorize.AsBool);
                }
                _env.Initialize(serviceConfig);

                // initialize host plug
                _host = _env.Self.With("apikey", apikey);

                // load assemblies in 'services' folder
                string servicesFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "services");
                if (Directory.Exists(servicesFolder))
                {
                    // Note (arnec): Deprecated, but the suggested alternative really doesn't apply since we don't want to
                    // load services into a separate appdomain.
#pragma warning disable 618,612
                    AppDomain.CurrentDomain.AppendPrivatePath("services");
#pragma warning restore 618,612
                    foreach (string file in Directory.GetFiles(servicesFolder, "*.dll"))
                    {
                        // register assembly blueprints
                        DreamMessage response = _host.At("load").With("name", Path.GetFileNameWithoutExtension(file)).Post(new Result <DreamMessage>(TimeSpan.MaxValue)).Wait();
                        if (!response.IsSuccessful)
                        {
                            _log.WarnFormat("DreamHost: ERROR: assembly '{0}' failed to load", file);
                        }
                    }
                }

                // add acccess-points
                AddListener(new XUri(String.Format("http://{0}:{1}/", "localhost", httpPort)), authenticationScheme);

                // check if user prescribed a set of IP addresses to use
                if (addresses != null)
                {
                    // listen to custom addresses (don't use the supplied port info, we expect that to be part of the address)
                    foreach (string address in addresses)
                    {
                        if (!StringUtil.EqualsInvariantIgnoreCase(address, "localhost"))
                        {
                            AddListener(new XUri(String.Format("http://{0}/", address)), authenticationScheme);
                        }
                    }
                }
                else
                {
                    // add listeners for all known IP addresses
                    foreach (IPAddress address in Dns.GetHostAddresses(Dns.GetHostName()))
                    {
                        XUri uri = MakeUri(address, httpPort);
                        if (uri != null)
                        {
                            AddListener(uri, authenticationScheme);
                            try {
                                foreach (string alias in Dns.GetHostEntry(address).Aliases)
                                {
                                    AddListener(new XUri(String.Format("http://{0}:{1}/", alias, httpPort)), authenticationScheme);
                                }
                            } catch { }
                        }
                    }
                }
            } catch (Exception e) {
                if ((e is HttpListenerException) && e.Message.EqualsInvariant("Access is denied"))
                {
                    _log.ErrorExceptionMethodCall(e, "ctor", "insufficient privileges to create HttpListener, make sure the application runs with Administrator rights");
                }
                else
                {
                    _log.ErrorExceptionMethodCall(e, "ctor");
                }
                try {
                    _env.Deinitialize();
                } catch { }
                throw;
            }
        }
Exemplo n.º 50
0
 /// <summary>
 /// Create a new instance for an <see cref="DreamStatus.InternalError"/> failure.
 /// </summary>
 /// <param name="message">Text message to use for <see cref="Exception.Message"/> and the internal <see cref="DreamMessage"/>.</param>
 public DreamInternalErrorException(string message) : base(DreamMessage.InternalError(message), message)
 {
 }
Exemplo n.º 51
0
 public DreamCachedResponseException(DreamMessage response, string message)
     : base(message)
 {
     this.Response = response;
 }
Exemplo n.º 52
0
 /// <summary>
 /// Create a new instance for a <see cref="DreamStatus.InternalError"/> condition.
 /// </summary>
 /// <param name="innerException">The exception that cause the internal error for the request.</param>
 public DreamInternalErrorException(Exception innerException) : base(DreamMessage.InternalError(innerException), innerException.Message)
 {
 }
Exemplo n.º 53
0
 private static object GetContextUri(DreamContext context, DreamMessage request, Result <DreamMessage> response)
 {
     return(context.Uri);
 }
Exemplo n.º 54
0
        //--- Constructors ---

        /// <summary>
        /// Create a new instance for a <see cref="DreamStatus.BadRequest"/> condition.
        /// </summary>
        /// <param name="message">Text message to use for <see cref="Exception.Message"/> and the internal <see cref="DreamMessage"/>.</param>
        public DreamBadRequestException(string message) : base(DreamMessage.BadRequest(message), message)
        {
        }
Exemplo n.º 55
0
 private static object GetContextFeatureSubpathSegments(DreamContext context, DreamMessage request, Result <DreamMessage> response)
 {
     return(context.Uri.GetRelativePathTo(context.Feature.ServiceUri).Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries));
 }
Exemplo n.º 56
0
        //--- Constructors ---

        /// <summary>
        /// Create a new instance for a <see cref="DreamStatus.Forbidden"/> condition.
        /// </summary>
        /// <param name="message">Text message to use for <see cref="Exception.Message"/> and the internal <see cref="DreamMessage"/>.</param>
        public DreamForbiddenException(string message) : base(DreamMessage.Forbidden(message), message)
        {
        }
Exemplo n.º 57
0
 public object Invoke(DreamContext context, DreamMessage message, Result <DreamMessage> response)
 {
     return(_invocation(context, message, response));
 }
Exemplo n.º 58
0
        //--- Constructors ---

        /// <summary>
        /// Create a new instance for a <see cref="DreamStatus.NotFound"/> condition.
        /// </summary>
        /// <param name="message">Text message to use for <see cref="Exception.Message"/> and the internal <see cref="DreamMessage"/>.</param>
        public DreamNotFoundException(string message) : base(DreamMessage.NotFound(message), message)
        {
        }
Exemplo n.º 59
0
 /// <summary>
 /// Relay a request to another service using the current query parameters, service cookies and verb.
 /// </summary>
 /// <remarks>
 /// Must be yielded by a coroutine or invoked with <see cref="Coroutine.Invoke"/>.
 /// </remarks>
 /// <param name="plug">Location of relay recipient.</param>
 /// <param name="request">Request message to relay.</param>
 /// <param name="response">The <see cref="Result{DreamMessage}"/> instance this coroutine will use as a synchronization handle.</param>
 /// <returns>Iterator used by <see cref="Coroutine"/> execution environment.</returns>
 public IYield Relay(Plug plug, DreamMessage request, Result <DreamMessage> response)
 {
     return(Relay(plug, Verb, request, response));
 }
Exemplo n.º 60
0
        /// <summary>
        /// Perform startup configuration of a service instance.
        /// </summary>
        /// <remarks>
        /// Should not be manually invoked and should only be overridden if <see cref="Start(MindTouch.Xml.XDoc,Autofac.ILifetimeScope,MindTouch.Tasking.Result)"/> isn't already overriden.
        /// </remarks>
        /// <param name="config">Service configuration.</param>
        /// <param name="result">Synchronization handle for coroutine invocation.</param>
        /// <returns>Iterator used by <see cref="Coroutine"/> execution environment.</returns>
        protected virtual Yield Start(XDoc config, Result result)
        {
            Result <DreamMessage> res;

            // store configuration and uri
            _config = config;
            _self   = Plug.New(config["uri.self"].AsUri);
            if (_self == null)
            {
                throw new ArgumentNullException("config", "Missing element'uri.self'");
            }
            _owner = Plug.New(config["uri.owner"].AsUri);

            // check for service access keys
            var internalAccessKey = config["internal-service-key"].AsText;

            if (!string.IsNullOrEmpty(internalAccessKey))
            {
                _internalAccessKey = internalAccessKey;
            }
            var privateAccessKey = config["private-service-key"].AsText;

            if (!string.IsNullOrEmpty(privateAccessKey))
            {
                _privateAccessKey = privateAccessKey;
            }

            // check for api-key settings
            _apikey = config["apikey"].AsText;

            // process 'set-cookie' entries
            var setCookies = DreamCookie.ParseAllSetCookieNodes(config["set-cookie"]);

            if (setCookies.Count > 0)
            {
                Cookies.Update(setCookies, null);
            }

            // grant private access key to self, host, and owner
            var privateAcccessCookie = DreamCookie.NewSetCookie("service-key", PrivateAccessKey, Self.Uri);

            Cookies.Update(privateAcccessCookie, null);
            yield return(Env.At("@grants").Post(DreamMessage.Ok(privateAcccessCookie.AsSetCookieDocument), new Result <DreamMessage>(TimeSpan.MaxValue)));

            if (Owner != null)
            {
                yield return(res = Owner.At("@grants").Post(DreamMessage.Ok(privateAcccessCookie.AsSetCookieDocument), new Result <DreamMessage>(TimeSpan.MaxValue)));

                if (!res.Value.IsSuccessful)
                {
                    throw new ArgumentException("unexpected failure setting grants on owner service");
                }
            }

            // check if this service requires a service-license to work
            if (this is IDreamServiceLicense)
            {
                string service_license = config["service-license"].AsText;
                if (string.IsNullOrEmpty(service_license))
                {
                    throw new DreamAbortException(DreamMessage.LicenseRequired("service-license missing"));
                }

                // extract public RSA key for validation
                RSACryptoServiceProvider public_key = RSAUtil.ProviderFrom(GetType().Assembly);
                if (public_key == null)
                {
                    throw new DreamAbortException(DreamMessage.InternalError("service assembly invalid"));
                }

                // validate the service-license
                _license = null;
                Dictionary <string, string> values;
                try {
                    // parse service-license
                    values = HttpUtil.ParseNameValuePairs(service_license);
                    if (!Encoding.UTF8.GetBytes(service_license.Substring(0, service_license.LastIndexOf(','))).VerifySignature(values["dsig"], public_key))
                    {
                        throw new DreamAbortException(DreamMessage.InternalError("invalid service-license (1)"));
                    }

                    // check if the SID matches
                    string sid;
                    if (!values.TryGetValue("sid", out sid) || !SID.HasPrefix(XUri.TryParse(sid), true))
                    {
                        throw new DreamAbortException(DreamMessage.InternalError("invalid service-license (2)"));
                    }
                    _license = service_license;
                } catch (Exception e) {
                    // unexpected error, blame it on the license
                    if (e is DreamAbortException)
                    {
                        throw;
                    }
                    throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license (1)"));
                }

                // validate expiration date
                string expirationtext;
                if (values.TryGetValue("expire", out expirationtext))
                {
                    try {
                        DateTime expiration = DateTime.Parse(expirationtext);
                        if (expiration < DateTime.UtcNow)
                        {
                            _license = null;
                        }
                    } catch (Exception e) {
                        _license = null;

                        // unexpected error, blame it on the license
                        if (e is DreamAbortException)
                        {
                            throw;
                        }
                        throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license (2)"));
                    }
                }

                // check if a license was assigned
                if (_license == null)
                {
                    throw new DreamAbortException(DreamMessage.LicenseRequired("service-license has expired"));
                }
            }
            else
            {
                config["service-license"].RemoveAll();
            }

            // create built-in services
            _storage = Plug.New(config["uri.storage"].AsUri);
            _pubsub  = Plug.New(config["uri.pubsub"].AsUri);

            // done
            _log.Debug("Start");
            result.Return();
        }