Example #1
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 service = preferences.HttpService ?? ConnectionPreferences.GetService();

            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(service, uri, preferences));
                }
            };

            var result = new Promise <IRemoteConnection>();
            var req    = new HttpRequest
            {
                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(service.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(service, url, preferences));
                }
                else
                {
                    try
                    {
                        var servers = ServerMapping.FromXml(data).ToArray();
                        if (servers.Length < 1)
                        {
                            result.Resolve(ArasConn(service, 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(service, url, preferences));
                    }
                }
            }).Fail(ex =>
            {
                result.Resolve(ArasConn(service, 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);
        }
Example #2
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 =>
            {
                try
                {
                    var config = new OAuthConfig(r.AsString(), oauthBaseUri);
                    if (config.ProtocolVersion >= new Version("1.0"))
                    {
                        result.Resolve(new OAuthAuthenticator(service, config, creds));
                    }
                    else
                    {
                        result.Resolve(new LegacyAuthenticator(innovatorServerBaseUrl, creds));
                    }
                }
                catch (Exception ex)
                {
                    result.Reject(ex);
                }
            })
                .Fail(e =>
            {
                result.Resolve(new LegacyAuthenticator(innovatorServerBaseUrl, creds));
            }));
            return(result);
        }