Exemplo n.º 1
0
        /// <summary>
        /// Request user credentials, coordinating between multiple threads looking for the same credentials.
        /// </summary>
        /// <remarks>Unlike Update, this will not re-prompt the user if they previously declined to provide credentials and it will assume any cached credentials work.</remarks>
        /// <returns>The new authentication provider</returns>
        /// <exception cref="WebChannelAuthorizationException">Thrown when no credentials were provided</exception>
        private static IWebAuthenticationProvider RequestUserCredentials(string entryUri, Guid repositoryId)
        {
            var cacheKey = new CredentialCacheKey(entryUri, repositoryId);

            IWebAuthenticationProvider authenticationProvider;

            //we only want one thread to pop up the UI to request authentication at a time.
            lock (g_RequestLock)
            {
                //WAIT: Since we requested the lock someone may have put credentials in the collection, so we have to check again.
                lock (g_Lock)
                {
                    System.Threading.Monitor.PulseAll(g_Lock);

                    if (g_CachedBlockedCredentials.ContainsKey(entryUri)) //someone may have just canceled.
                    {
                        throw new WebChannelAuthorizationException("User declined to provide credentials");
                    }

                    if (g_CachedCredentials.TryGetValue(cacheKey, out authenticationProvider))
                    {
                        return(authenticationProvider); //yep, someone else got them.
                    }
                }

                var credentialEventArgs = new CredentialsRequiredEventArgs(entryUri, repositoryId, false, null);
                OnCredentialsRequired(null, credentialEventArgs);

                if (credentialEventArgs.Cancel)
                {
                    //if the user canceled we need to cache that so we don't keep pounding the user.
                    lock (g_Lock)
                    {
                        g_CachedBlockedCredentials[entryUri] = entryUri;

                        System.Threading.Monitor.PulseAll(g_Lock);
                    }

                    throw new WebChannelAuthorizationException("User declined to provide credentials");
                }

                if (ReferenceEquals(credentialEventArgs.AuthenticationProvider, null))
                {
                    throw new WebChannelAuthorizationException("No credentials are available for the specified server");
                }

                authenticationProvider = credentialEventArgs.AuthenticationProvider;

                lock (g_Lock)
                {
                    g_CachedCredentials.Add(cacheKey, authenticationProvider);

                    System.Threading.Monitor.PulseAll(g_Lock);
                }

                System.Threading.Monitor.PulseAll(g_RequestLock);
            }

            return(authenticationProvider);
        }
Exemplo n.º 2
0
        private static void OnCredentialsRequired(object source, CredentialsRequiredEventArgs e)
        {
            CredentialsRequiredEventHandler handler = CredentialsRequired;

            if (handler != null)
            {
                handler(source, e);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Attempt to re-query the credentials for the specified URI
        /// </summary>
        /// <param name="entryUri">The entry URI to update credentials for</param>
        /// <param name="repositoryId">The owner Id to specify to the server (for example repository Id)</param>
        /// <param name="forceUpdate">True to force a requery to the user even if they previously canceled requesting credentials</param>
        /// <returns>True if the user provided updated credentials, false if they canceled</returns>
        public static bool UpdateCredentials(string entryUri, Guid repositoryId, bool forceUpdate)
        {
            var cacheKey = new CredentialCacheKey(entryUri, repositoryId);

            bool newCredentialsProvided = false;

            lock (g_Lock) //if we have any in cache we need to update those, so in this case we stall EVERYONE.
            {
                //WAIT: Since we requested the lock someone may have put credentials in the collection, so we have to check again.
                System.Threading.Monitor.PulseAll(g_Lock);

                if ((forceUpdate == false) && (g_CachedBlockedCredentials.ContainsKey(entryUri)))
                {
                    return(false);
                }

                IWebAuthenticationProvider credentials;
                g_CachedCredentials.TryGetValue(cacheKey, out credentials);

                //we only want one thread to pop up the UI to request authentication at a time.
                lock (g_RequestLock)
                {
                    var credentialEventArgs = new CredentialsRequiredEventArgs(entryUri, repositoryId, true, credentials);
                    OnCredentialsRequired(null, credentialEventArgs);

                    if (credentialEventArgs.Cancel == false)
                    {
                        if (credentialEventArgs.AuthenticationProvider == null)
                        {
                            throw new InvalidOperationException("No credentials are available for the specified server");
                        }

                        newCredentialsProvided = true;

                        g_CachedBlockedCredentials.Remove(entryUri);                                //if it was previously blocked, unblock it.

                        g_CachedCredentials[cacheKey] = credentialEventArgs.AuthenticationProvider; //overwrite any existing value.
                    }

                    System.Threading.Monitor.PulseAll(g_RequestLock);
                }

                System.Threading.Monitor.PulseAll(g_Lock);
            }

            return(newCredentialsProvided);
        }