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
        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);
        }
Example #3
0
        public override IPromise <Stream> Commit(bool async)
        {
            if (Status != UploadStatus.Pending)
            {
                return(_lastPromise);
            }

            Status = UploadStatus.Committed;
            // No transaction has been started
            if (_transactionId == null && !Files.Any(f => f.UploadPromise != null))
            {
                _lastPromise = UploadAndApply(async);
            }
            else
            {
                var transactionId = default(string);
                _lastPromise = BeginTransaction(async)
                               .Continue(t =>
                {
                    transactionId = t;
                    return(Promises.All(Files
                                        .Select(f => f.UploadPromise ?? UploadFile(f, async))
                                        .ToArray()));
                })
                               .Continue(l =>
                {
                    var aml     = this.ToNormalizedAml(_conn.AmlContext.LocalizationContext);
                    var content = new FormContent
                    {
                        {
                            "XMLData",
                            "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:i18n=\"http://www.aras.com/I18N\"><SOAP-ENV:Body><ApplyItem>"
                            + aml
                            + "</ApplyItem></SOAP-ENV:Body></SOAP-ENV:Envelope>"
                        }
                    };

                    var req = new HttpRequest()
                    {
                        Content = content
                    };
                    _conn.SetDefaultHeaders(req.SetHeader);
                    foreach (var ac in _conn.DefaultSettings)
                    {
                        ac.Invoke(req);
                    }
                    Settings?.Invoke(req);
                    req.SetHeader("SOAPAction", "CommitTransaction");
                    req.SetHeader("VAULTID", Vault.Id);
                    req.SetHeader("transactionid", transactionId);

                    var trace = new LogData(4
                                            , "Innovator: Execute vault query"
                                            , LogListener ?? Factory.LogListener
                                            , Parameters)
                    {
                        { "aras_url", _conn.MapClientUrl("../../Server") },
                        { "database", _conn.Database },
                        { "query", aml },
                        { "soap_action", "CommitTransaction" },
                        { "url", Vault.Url },
                        { "user_id", _conn.UserId },
                        { "vault_id", Vault.Id },
                        { "version", _conn.Version }
                    };
                    return(Vault.HttpClient.PostPromise(new Uri(Vault.Url), async, req, trace).Always(trace.Dispose));
                })
                               .Convert(r => r.AsStream);
            }
            return(_lastPromise);
        }
Example #4
0
        /// <summary>
        /// Uploads the files and applies the AML in a single transaction
        /// </summary>
        /// <param name="async">Whether to perform this action asynchronously</param>
        /// <returns>A promise to return an XML SOAP response as a <see cref="System.IO.Stream"/></returns>
        internal IPromise <Stream> UploadAndApply(string soapAction, string aml, IEnumerable <CommandFile> files, bool async)
        {
            return(_conn.FetchVersion(async).Continue(v =>
            {
                return Vault.TransformUrl(_conn, async).Continue(u =>
                {
                    // Compile the headers and AML query into the appropriate content
                    HttpRequest req;
                    var content = new FormContent
                    {
                        {
                            "XMLdata",
                            "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:i18n=\"http://www.aras.com/I18N\"><SOAP-ENV:Body><ApplyItem>" +
                            aml +
                            "</ApplyItem></SOAP-ENV:Body></SOAP-ENV:Envelope>"
                        }
                    };
                    foreach (var file in files)
                    {
                        content.Add(file.AsContent(this, _conn.AmlContext.LocalizationContext, true).Single());
                    }
                    content.Compression = _conn.Compression;
                    if (_conn.Version >= new Version(12, 0, 9))
                    {
                        req = GetUploadRequest12sp09(content, soapAction);
                    }
                    else
                    {
                        req = GetUploadRequestLegacy(content, soapAction);
                    }
                    foreach (var ac in _conn.DefaultSettings)
                    {
                        ac.Invoke(req);
                    }
                    Settings?.Invoke(req);

                    req.Headers.TransferEncodingChunked = true;

                    var trace = new LogData(4
                                            , "Innovator: Execute query"
                                            , LogListener ?? Factory.LogListener
                                            , Parameters)
                    {
                        { "aras_url", _conn.MapClientUrl("../../Server") },
                        { "database", _conn.Database },
                        { "query", aml },
                        { "soap_action", soapAction },
                        { "url", Vault.Url },
                        { "user_id", _conn.UserId },
                        { "vault_id", Vault.Id },
                        { "version", _conn.Version }
                    };
                    _conn.SetDefaultHeaders((name, value) =>
                    {
                        if (string.Equals(name, "LOCALE", StringComparison.OrdinalIgnoreCase) ||
                            string.Equals(name, "TIMEZONE_NAME", StringComparison.OrdinalIgnoreCase))
                        {
                            trace.Add(name.ToLowerInvariant(), value);
                        }
                    });
                    return Vault.HttpClient
                    .PostPromise(new Uri(Vault.Url), async, req, trace)
                    .Always(trace.Dispose)
                    .Always(req.Dispose);
                }).Convert(r => r.AsStream);
            }));
        }