Ejemplo n.º 1
0
        /// <summary>
        /// Continue a promise chain by acting on the previous promise's result and returning a new promise
        /// </summary>
        /// <param name="promise">Previous promise</param>
        /// <param name="callback">Code to execute on resolution of the promise and returning a new promise</param>
        /// <returns>A new promise</returns>
        public static IPromise <S> Continue <T, S>(this IPromise <T> promise, Func <T, IPromise <S> > callback)
        {
            var result = new Promise <S>();

            result.CancelTarget(
                promise
                .Progress((p, m) => result.Notify(p / 50, m))
                .Done(t =>
            {
                try
                {
                    result.CancelTarget(callback(t)
                                        .Progress((p, m) => result.Notify(50 + p / 50, m))
                                        .Done(s => result.Resolve(s))
                                        .Fail(exS => result.Reject(exS)));
                }
                catch (Exception ex)
                {
                    result.Reject(ex);
                }
            }).Fail(exT => result.Reject(exT)));
            return(result);
        }
        private static IPromise <T> ToHttpPromise <T>(this Task <T> task, TimeoutSource timeout, LogData trace)
        {
            var result = new Promise <T>();

            result.CancelTarget(timeout);
            task
            .ContinueWith(t =>
            {
                if (t.IsFaulted)
                {
                    Exception ex = t.Exception;
                    while (ex != null && ex.InnerException != null && ex.GetType().Name == "AggregateException")
                    {
                        ex = ex.InnerException;
                    }

                    if (ex != null)
                    {
                        foreach (var kvp in trace)
                        {
                            ex.Data[kvp.Key] = kvp.Value;
                        }
                        trace.Add("exception", ex);
                    }
                    result.Reject(ex);
                }
                else if (t.IsCanceled)
                {
                    result.Reject(new HttpTimeoutException(string.Format("A response was not received after waiting for {0:m' minutes, 's' seconds'}", TimeSpan.FromMilliseconds(timeout.TimeoutDelay))));
                }
                else
                {
                    result.Resolve(t.Result);
                }
            });
            return(result);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Asynchronously gets an HTTP connection to an innovator instance (or proxy) at the given URL
        /// </summary>
        /// <param name="preferences">Object containing preferences for the connection</param>
        /// <param name="async">Whether or not to return the connection asynchronously.  This is important
        /// as an HTTP request must be issued to determine the type of connection to create</param>
        /// <returns>A promise to return a connection object</returns>
        public static IPromise <IRemoteConnection> GetConnection(ConnectionPreferences preferences, bool async)
        {
            preferences = preferences ?? new ConnectionPreferences();
            var url = preferences.Url;

            url = (url ?? "").TrimEnd('/');
            if (url.EndsWith("Server/InnovatorServer.aspx", StringComparison.OrdinalIgnoreCase))
            {
                url = url.Substring(0, url.Length - 21);
            }
            if (!url.EndsWith("/server", StringComparison.OrdinalIgnoreCase))
            {
                url += "/Server";
            }
            var configUrl = url + "/mapping.xml";

            var masterService = preferences.HttpService ?? DefaultService.Invoke();
            var arasSerice    = preferences.HttpService ?? DefaultService.Invoke();
            Func <ServerMapping, IRemoteConnection> connFactory = m =>
            {
                var uri = (m.Url ?? "").TrimEnd('/');
                if (!uri.EndsWith("/server", StringComparison.OrdinalIgnoreCase))
                {
                    url += "/Server";
                }
                switch (m.Type)
                {
                case ServerType.Proxy:
                    throw new NotSupportedException();

                default:
                    return(ArasConn(arasSerice, uri, preferences));
                }
            };

            var result = new Promise <IRemoteConnection>();
            var req    = new HttpRequest();

            req.UserAgent = preferences.Headers.UserAgent;
            req.SetHeader("Accept", "text/xml");
            foreach (var header in preferences.Headers.NonUserAgentHeaders())
            {
                req.SetHeader(header.Key, header.Value);
            }

            var trace = new LogData(4, "Innovator: Try to download mapping file", Factory.LogListener)
            {
                { "url", configUrl },
            };

            result.CancelTarget(masterService.GetPromise(new Uri(configUrl), async, trace, req)
                                .Progress((p, m) => result.Notify(p, m))
                                .Done(r =>
            {
                var data = r.AsString();
                if (string.IsNullOrEmpty(data))
                {
                    result.Resolve(ArasConn(arasSerice, url, preferences));
                }
                else
                {
                    try
                    {
                        var servers = ServerMapping.FromXml(data).ToArray();
                        if (servers.Length < 1)
                        {
                            result.Resolve(ArasConn(arasSerice, url, preferences));
                        }
                        else if (servers.Length == 1)
                        {
                            result.Resolve(connFactory(servers.Single()));
                        }
                        else
                        {
                            foreach (var server in servers)
                            {
                                server.Factory = connFactory;
                            }
                            result.Resolve(new MappedConnection(servers, preferences.AuthCallback));
                        }
                    }
                    catch (XmlException)
                    {
                        result.Resolve(ArasConn(arasSerice, url, preferences));
                    }
                }
            }).Fail(ex =>
            {
                result.Resolve(ArasConn(arasSerice, url, preferences));
            })).Always(trace.Dispose);


            if (preferences.Credentials != null)
            {
                IRemoteConnection conn = null;
                return(result
                       .Continue(c =>
                {
                    conn = c;
                    return c.Login(preferences.Credentials, async);
                })
                       .Convert(u => conn));
            }

            return(result);
        }
Ejemplo n.º 4
0
        public static IPromise <IAuthenticator> GetAuthenticator(Uri innovatorServerBaseUrl, HttpClient service, ICredentials creds, bool async)
        {
            var discovery = new Uri(innovatorServerBaseUrl, "OAuthServerDiscovery.aspx");
            var req       = new HttpRequest();

            req.Headers.Add("Aras-Set-HttpSessionState-Behavior", "switch_to_initial");
            var oauthBaseUri = default(Uri);

            var result = new Promise <IAuthenticator>();

            result.CancelTarget(
                service.GetPromise(discovery, async, new LogData(4
                                                                 , "Innovator: Get OAuth URL"
                                                                 , Factory.LogListener)
            {
                { "url", discovery },
            }, req)
                .Continue(r =>
            {
                if (r.StatusCode != System.Net.HttpStatusCode.OK)
                {
                    throw new Exception("OAuth not found");
                }

                var serverUrls = default(List <Uri>);
                using (var json = new Json.Embed.JsonTextReader(r.AsStream))
                {
                    serverUrls = json.Flatten()
                                 .Where(k => k.Key.StartsWith("$.locations[") &&
                                        k.Key.EndsWith("].uri") &&
                                        k.Value is string str &&
                                        !string.IsNullOrEmpty(str))
                                 .Select(k => new Uri(k.Value.ToString()))
                                 .OrderBy(u => string.Equals(u.Host, innovatorServerBaseUrl.Host, StringComparison.OrdinalIgnoreCase) ? 0 : 1)
                                 .ToList();
                }

                if (serverUrls?.Count < 1)
                {
                    throw new InvalidOperationException("OAuth server URL could not be found");
                }

                oauthBaseUri = serverUrls[0];
                var oauthUri = new Uri(oauthBaseUri, ".well-known/openid-configuration");
                return(service.GetPromise(oauthUri, async, new LogData(4
                                                                       , "Innovator: Get OAuth Config"
                                                                       , Factory.LogListener)
                {
                    { "url", oauthUri },
                }));
            })
                .Progress(result.Notify)
                .Done(r =>
            {
                var config = new OAuthConfig(r.AsStream, oauthBaseUri);
                if (config.ProtocolVersion >= new Version("1.0"))
                {
                    result.Resolve(new OAuthAuthenticator(service, config, creds));
                }
                else
                {
                    result.Resolve(new LegacyAuthenticator(innovatorServerBaseUrl, creds));
                }
            })
                .Fail(e =>
            {
                result.Resolve(new LegacyAuthenticator(innovatorServerBaseUrl, creds));
            }));
            return(result);
        }
Ejemplo n.º 5
0
        private IPromise <ICredentials> DefaultAuthCallback(INetCredentials netCred, string endpoint, bool async)
        {
            var promise = new Promise <ICredentials>();

            if (string.IsNullOrEmpty(endpoint))
            {
                promise.Resolve(netCred);
            }
            else
            {
                var handler = new SyncClientHandler()
                {
                    Credentials     = netCred.Credentials,
                    PreAuthenticate = true
                };
                var http = new SyncHttpClient(handler);

                var endpointUri = new Uri(endpoint + "?db=" + netCred.Database);
                var trace       = new LogData(4, "Innovator: Authenticate user via mapping", Factory.LogListener)
                {
                    { "database", netCred.Database },
                    { "user_name", netCred.Credentials.GetCredential(endpointUri, null).UserName },
                    { "url", endpointUri },
                };
                http.GetPromise(endpointUri, async, trace)
                .Done(r =>
                {
                    var res  = r.AsXml().DescendantsAndSelf("Result").FirstOrDefault();
                    var user = res.Element("user").Value;
                    var pwd  = res.Element("password").Value;
                    if (pwd.IsNullOrWhiteSpace())
                    {
                        promise.Reject(new ArgumentException("Failed to authenticate with Innovator server '" + endpoint + "'. Original error: " + user, "credentials"));
                    }

                    var needHash = !string.Equals(res.Element("hash").Value, "false", StringComparison.OrdinalIgnoreCase);
                    if (needHash)
                    {
                        promise.Resolve(new ExplicitCredentials(netCred.Database, user, pwd));
                    }
                    else
                    {
                        promise.Resolve(new ExplicitHashCredentials(netCred.Database, user, pwd));
                    }
                }).Fail(ex =>
                {
                    // Only hard fail for problems which aren't time outs and not found issues.
                    var webEx = ex as HttpException;
                    if (webEx != null && webEx.Response.StatusCode == HttpStatusCode.NotFound)
                    {
                        promise.Resolve(netCred);
                    }
                    else if (webEx != null && webEx.Response.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        promise.Reject(ElementFactory.Local.ServerException("Invalid username or password"));
                    }
                    else if (webEx != null)
                    {
                        try
                        {
                            var result = ElementFactory.Local.FromXml(webEx.Response.AsStream);
                            if (result.Exception != null)
                            {
                                promise.Reject(result.Exception);
                            }
                            else
                            {
                                promise.Reject(ex);
                            }
                        }
                        catch (Exception)
                        {
                            promise.Reject(ex);
                        }
                    }
                    else if (ex is TaskCanceledException)
                    {
                        promise.Resolve(netCred);
                    }
                    else
                    {
                        promise.Reject(ex);
                    }
                }).Always(trace.Dispose);
            }

            return(promise);
        }