Example #1
0
        void ExchangeTokensAndJoinOrganization(string unityAccessToken)
        {
            int ini = Environment.TickCount;

            TokenExchangeResponse response = null;

            IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);

            waiter.Execute(
                /*threadOperationDelegate*/ delegate
            {
                mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ResponseInit;
                response = PlasticScmRestApiClient.TokenExchange(unityAccessToken);
            },
                /*afterOperationDelegate*/ delegate
            {
                mLog.DebugFormat(
                    "TokenExchange time {0} ms",
                    Environment.TickCount - ini);

                if (waiter.Exception != null)
                {
                    mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ErrorTokenException;
                    ExceptionsHandler.LogException(
                        "TokenExchangeSetting",
                        waiter.Exception);
                    return;
                }

                if (response == null)
                {
                    mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ErrorResponseNull;
                    Debug.Log("response null");
                    return;
                }

                if (response.Error != null)
                {
                    mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ErrorResponseError;
                    mLog.ErrorFormat(
                        "Unable to exchange token: {0} [code {1}]",
                        response.Error.Message, response.Error.ErrorCode);
                    return;
                }

                if (string.IsNullOrEmpty(response.AccessToken))
                {
                    mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ErrorTokenEmpty;
                    mLog.InfoFormat(
                        "Access token is empty for user: {0}",
                        response.User);
                    return;
                }

                mPlasticWindow.GetWelcomeView().autoLoginState = AutoLogin.State.ResponseEnd;
                sAccessToken = response.AccessToken;
                sUserName    = response.User;
                GetOrganizationList();
            });
        }
Example #2
0
        internal void ExchangeTokens(string unityAccessToken)
        {
            int ini = Environment.TickCount;

            TokenExchangeResponse response = null;

            IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);

            waiter.Execute(
                /*threadOperationDelegate*/ delegate
            {
                response = PlasticScmRestApiClient.TokenExchange(unityAccessToken);
            },
                /*afterOperationDelegate*/ delegate
            {
                mLog.DebugFormat(
                    "TokenExchange time {0} ms",
                    Environment.TickCount - ini);

                if (waiter.Exception != null)
                {
                    ExceptionsHandler.LogException(
                        "TokenExchangeSetting",
                        waiter.Exception);
                    return;
                }

                if (response == null)
                {
                    Debug.Log("response null");
                    return;
                }

                if (response.Error != null)
                {
                    mLog.ErrorFormat(
                        "Unable to exchange token: {0} [code {1}]",
                        response.Error.Message,
                        response.Error.ErrorCode);
                    return;
                }

                if (string.IsNullOrEmpty(response.AccessToken))
                {
                    mLog.InfoFormat(
                        "Access token is empty for user: {0}",
                        response.User);
                    return;
                }

                sAccessToken = response.AccessToken;
                sUserName    = response.User;
            });
        }
Example #3
0
        public async Task ContactStravaAndSaveTokens()
        {
            using (var httpTest = new HttpTest())
            {
                const string athleteId    = "2";
                const string accessToken  = "1";
                const string refreshToken = "4";
                DateTime     expiresAt    = new DateTime(1970, 1, 1);

                // Arrange
                string tokenResponse = JsonConvert.SerializeObject(new StravaTokenExchangeResponse
                {
                    access_token = accessToken,
                    athlete      = new TokenExchangeAthlete {
                        id = athleteId
                    },
                    expires_at    = 0,
                    refresh_token = refreshToken,
                    state         = "5",
                    token_type    = "6"
                });

                httpTest.RespondWith(tokenResponse);

                // Act
                TokenExchangeResponse result = await _testSubject.TokenExchange("0");

                // Assert
                Assert.Equal(accessToken, result.TokenSet.AccessToken);
                Assert.Equal(expiresAt, result.TokenSet.ExpiresAtUtc);
                Assert.Equal(athleteId, result.TokenSet.AthleteId);
                Assert.Equal(athleteId, result.AthleteSummary.Id);
                httpTest.ShouldHaveCalled(_options.TokenEndPoint)
                .WithVerb(HttpMethod.Post);
                await _tokenCache.Received().SaveTokenSet(athleteId, accessToken, refreshToken, expiresAt);

                await _tokenRepository.Received().SaveTokenSet(athleteId, accessToken, refreshToken, expiresAt);
            }
        }
Example #4
0
        internal static TokenExchangeResponse PlasticCredentials(
            string unityAccessToken,
            string serverName,
            string projectPath)
        {
            SetupUnityEditionToken.CreateCloudEditionTokenIfNeeded();

            bool isClientConfigConfigured = ClientConfig.IsConfigured();

            if (!isClientConfigConfigured)
            {
                ConfigureClientConf.FromUnityAccessToken(
                    unityAccessToken, serverName, projectPath);
            }

            TokenExchangeResponse tokenExchangeResponse = WebRestApiClient.
                                                          PlasticScm.TokenExchange(unityAccessToken);

            if (tokenExchangeResponse.Error != null)
            {
                return(tokenExchangeResponse);
            }

            CloudEditionWelcomeWindow.JoinCloudServer(
                serverName,
                tokenExchangeResponse.User,
                tokenExchangeResponse.AccessToken);

            if (!isClientConfigConfigured)
            {
                return(tokenExchangeResponse);
            }

            ConfigureProfile.ForServerIfNeeded(
                serverName,
                tokenExchangeResponse.User);

            return(tokenExchangeResponse);
        }
Example #5
0
        public async Task <List <TokenExchangeResponse> > ProcessExchangeAsync(TokenExchangeRequest tokenExchangeRequest)
        {
            if (tokenExchangeRequest.Extras == null || tokenExchangeRequest.Extras.Count == 0)
            {
                throw new Exception($"{Name}: We require that extras be populated!");
            }

            // for this demo, lets assume all the extras are roles.
            var response = new List <TokenExchangeResponse>();

            for (int i = 0; i < 2; i++)
            {
                var tokenExchangeResponse = new TokenExchangeResponse()
                {
                    accessToken = new AccessTokenResponse()
                    {
                        hint          = "Alien Response",
                        access_token  = $"Alien_access_token_{Guid.NewGuid().ToString()}",
                        refresh_token = $"Alien_refresh_token_{Guid.NewGuid().ToString()}",
                        expires_in    = 1234 + i,
                        token_type    = $"Alien_{Guid.NewGuid().ToString()}",
                        authority     = $"{_httpContextAssessor.HttpContext.Request.Scheme}://{_httpContextAssessor.HttpContext.Request.Host}/Alien",
                        HttpHeaders   = new List <HttpHeader>
                        {
                            new HttpHeader()
                            {
                                Name = "x-authScheme", Value = "Alien"
                            }
                        }
                    }
                };
                response.Add(tokenExchangeResponse);
            }

            return(response);
        }
        void DownloadRepository(object state)
        {
            DownloadRepositoryParameters parameters = (DownloadRepositoryParameters)state;

            try
            {
                if (FindWorkspace.HasWorkspace(parameters.ProjectPath))
                {
                    // each domain reload, the package is reloaded.
                    // way need to check if we already downloaded it
                    return;
                }

                mDisplayProgress = true;

                IPlasticWebRestApi restApi           = new PlasticWebRestApi();
                string             defaultCloudAlias = restApi.GetDefaultCloudAlias();

                RepositorySpec repSpec = BuildRepSpec(
                    parameters.CloudRepository,
                    parameters.CloudOrganization,
                    defaultCloudAlias);

                // we just download a cloud project,
                // so let's assume we're going to use Cloud Edition
                SetupUnityEditionToken.CreateCloudEditionTokenIfNeeded();

                if (!ClientConfig.IsConfigured())
                {
                    AutoConfigClientConf.FromUnityAccessToken(
                        parameters.AccessToken,
                        repSpec.Server,
                        parameters.ProjectPath);
                }

                TokenExchangeResponse tokenExchangeResponse = WebRestApiClient.
                                                              PlasticScm.TokenExchange(parameters.AccessToken);

                if (tokenExchangeResponse.Error != null)
                {
                    mOperationFailed = true;

                    UnityEngine.Debug.LogErrorFormat(
                        PlasticLocalization.GetString(PlasticLocalization.Name.ErrorDownloadingCloudProject),
                        string.Format("Unable to get TokenExchangeResponse: {0} [code {1}]",
                                      tokenExchangeResponse.Error.Message,
                                      tokenExchangeResponse.Error.ErrorCode));
                    return;
                }

                CloudEditionWelcomeWindow.JoinCloudServer(
                    repSpec.Server,
                    tokenExchangeResponse.User,
                    tokenExchangeResponse.AccessToken);

                ClientConfigData clientConfigData = ClientConfig.Get().GetClientConfigData();
                clientConfigData.WorkspaceServer = repSpec.Server;
                ClientConfig.Get().Save(clientConfigData);

                WorkspaceInfo wkInfo = CreateWorkspace(
                    repSpec, parameters.ProjectPath);

                mLog.DebugFormat("Created workspace {0} on {1}",
                                 wkInfo.Name,
                                 wkInfo.ClientPath);

                PlasticGui.Plastic.API.Update(
                    wkInfo.ClientPath,
                    UpdateFlags.None,
                    null,
                    mUpdateNotifier);
            }
            catch (Exception ex)
            {
                LogException(ex);

                UnityEngine.Debug.LogErrorFormat(
                    PlasticLocalization.GetString(PlasticLocalization.Name.ErrorDownloadingCloudProject),
                    ex.Message);

                mOperationFailed = true;
            }
            finally
            {
                mOperationFinished = true;
            }
        }
        void LaunchMigration(
            string unityAccessToken,
            string projectPath,
            string organizationName,
            RepId repId,
            long changesetId,
            long branchId,
            Action afterWorkspaceMigratedAction,
            ProgressControlsForMigration progressControls)
        {
            string serverName = string.Format(
                "{0}@cloud", organizationName);

            TokenExchangeResponse tokenExchangeResponse = null;

            mWorkspaceInfo = null;

            CreateWorkspaceFromCollab.Progress progress = new CreateWorkspaceFromCollab.Progress();

            BuildProgressSpeedAndRemainingTime.ProgressData progressData =
                new BuildProgressSpeedAndRemainingTime.ProgressData(DateTime.Now);

            IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);

            waiter.Execute(
                /*threadOperationDelegate*/
                delegate
            {
                tokenExchangeResponse = AutoConfig.PlasticCredentials(
                    unityAccessToken,
                    serverName,
                    projectPath);

                if (tokenExchangeResponse.Error != null)
                {
                    return;
                }

                RepositoryInfo repInfo = new BaseCommandsImpl().
                                         GetRepositoryInfo(repId, serverName);

                if (repInfo == null)
                {
                    return;
                }

                repInfo.SetExplicitServer(serverName);

                mWorkspaceInfo = CreateWorkspaceFromCollab.Create(
                    projectPath, repInfo.Name, repInfo,
                    changesetId, branchId,
                    progress);
            },
                /*afterOperationDelegate*/
                delegate
            {
                progressControls.HideProgress();

                if (waiter.Exception != null)
                {
                    DisplayException(progressControls, waiter.Exception);
                    TrackWorkspaceMigrationFinishedFailureEvent(mWorkspaceInfo);
                    return;
                }

                if (tokenExchangeResponse.Error != null)
                {
                    mLog.ErrorFormat(
                        "Unable to get TokenExchangeResponse: {0} [code {1}]",
                        tokenExchangeResponse.Error.Message,
                        tokenExchangeResponse.Error.ErrorCode);
                }

                if (tokenExchangeResponse.Error != null ||
                    mWorkspaceInfo == null)
                {
                    progressControls.ShowError(
                        "Failed to convert your workspace to Plastic SCM");
                    TrackWorkspaceMigrationFinishedFailureEvent(mWorkspaceInfo);
                    return;
                }

                progressControls.ShowSuccess(
                    "Your workspace has been successfully converted to Plastic SCM");

                mIsMigrationCompleted = true;

                TrackFeatureUseEvent.For(
                    PlasticGui.Plastic.API.GetRepositorySpec(mWorkspaceInfo),
                    TrackFeatureUseEvent.Features.WorkspaceMigrationFinishedSuccess);

                afterWorkspaceMigratedAction();
            },
                /*timerTickDelegate*/
                delegate
            {
                UpdateProgress(projectPath, progress, progressControls, progressData);
            });
        }
        public async Task <List <TokenExchangeResponse> > ProcessExchangeAsync(TokenExchangeRequest tokenExchangeRequest)
        {
            if (tokenExchangeRequest.Extras == null || tokenExchangeRequest.Extras.Count == 0)
            {
                throw new Exception($"{Name}: We require that extras be populated!");
            }

            List <ValidatedToken> validatedIdentityTokens = new List <ValidatedToken>();

            foreach (var item in tokenExchangeRequest.Tokens)
            {
                var prince = await _tokenValidator.ValidateTokenAsync(new TokenDescriptor
                {
                    TokenScheme = item.TokenScheme,
                    Token       = item.Token
                });

                var sub = prince.GetSubjectFromPincipal();
                if (string.IsNullOrEmpty(sub))
                {
                    _summaryLogger.Add("subject", "A subject was not found in the ClaimsPrincipal object!");
                    throw new Exception("A subject was not found in the ClaimsPrincipal object!");
                }
                validatedIdentityTokens.Add(new ValidatedToken
                {
                    Token       = item.Token,
                    TokenScheme = item.TokenScheme,
                    Principal   = prince
                });
            }

            // for this demo, lets assume all the extras are roles.
            var roles = tokenExchangeRequest.Extras;

            roles.Add("user");


            ResourceOwnerTokenRequest resourceOwnerTokenRequest = new ResourceOwnerTokenRequest()
            {
                AccessTokenLifetime = 3600,
                ArbitraryClaims     = new Dictionary <string, List <string> >()
                {
                    { "role", roles }
                },
                Scope    = "offline_access graphQLPlay",
                Subject  = validatedIdentityTokens[0].Principal.GetSubjectFromPincipal(),
                ClientId = "arbitrary-resource-owner-client"
            };
            var response = await _tokenMintingService.MintResourceOwnerTokenAsync(resourceOwnerTokenRequest);

            if (response.IsError)
            {
                throw new Exception(response.Error);
            }

            var tokenExchangeResponse = new TokenExchangeResponse()
            {
                accessToken = new AccessTokenResponse()
                {
                    access_token  = response.AccessToken,
                    refresh_token = response.RefreshToken,
                    expires_in    = response.ExpiresIn,
                    token_type    = response.TokenType,
                    authority     =
                        $"{_httpContextAssessor.HttpContext.Request.Scheme}://{_httpContextAssessor.HttpContext.Request.Host}",
                    HttpHeaders = new List <HttpHeader>
                    {
                        new HttpHeader()
                        {
                            Name = "x-authScheme", Value = response.Scheme
                        }
                    }
                }
            };

            return(new List <TokenExchangeResponse> {
                tokenExchangeResponse
            });
        }
Example #9
0
        void DownloadRepository(object state)
        {
            DownloadRepositoryParameters parameters = (DownloadRepositoryParameters)state;

            try
            {
                if (FindWorkspace.HasWorkspace(parameters.ProjectPath))
                {
                    // each domain reload, the package is reloaded.
                    // way need to check if we already downloaded it
                    return;
                }

                mDisplayProgress = true;

                IPlasticWebRestApi restApi           = new PlasticWebRestApi();
                string             defaultCloudAlias = restApi.GetDefaultCloudAlias();

                RepositorySpec repSpec = BuildRepSpec(
                    parameters.CloudRepository,
                    parameters.CloudOrganization,
                    defaultCloudAlias);

                TokenExchangeResponse tokenExchangeResponse =
                    AutoConfig.PlasticCredentials(
                        parameters.AccessToken,
                        repSpec.Server,
                        parameters.ProjectPath);

                if (tokenExchangeResponse.Error != null)
                {
                    mOperationFailed = true;

                    UnityEngine.Debug.LogErrorFormat(
                        PlasticLocalization.GetString(PlasticLocalization.Name.ErrorDownloadingCloudProject),
                        string.Format("Unable to get TokenExchangeResponse: {0} [code {1}]",
                                      tokenExchangeResponse.Error.Message,
                                      tokenExchangeResponse.Error.ErrorCode));
                    return;
                }

                WorkspaceInfo wkInfo = CreateWorkspace(
                    repSpec, parameters.ProjectPath);

                mLog.DebugFormat("Created workspace {0} on {1}",
                                 wkInfo.Name,
                                 wkInfo.ClientPath);

                PlasticGui.Plastic.API.Update(
                    wkInfo.ClientPath,
                    UpdateFlags.None,
                    null,
                    mUpdateNotifier);
            }
            catch (Exception ex)
            {
                LogException(ex);

                UnityEngine.Debug.LogErrorFormat(
                    PlasticLocalization.GetString(PlasticLocalization.Name.ErrorDownloadingCloudProject),
                    ex.Message);

                mOperationFailed = true;
            }
            finally
            {
                mOperationFinished = true;
            }
        }
        public async Task <List <TokenExchangeResponse> > ProcessExchangeAsync(
            TokenExchangeRequest tokenExchangeRequest,
            Dictionary <string, List <KeyValuePair <string, string> > > mapOpaqueKeyValuePairs)
        {
            var access_token = await GetTokenAsync();

            if (string.IsNullOrEmpty(access_token))
            {
                throw new Exception("Unable to fetch client_credentials access_token");
            }

            var headers = new List <HttpHeader>(_externalExchangeRecord.oAuth2_client_credentials.AdditionalHeaders)
            {
                new HttpHeader()
                {
                    Name = "Authorization", Value = $"Bearer {access_token}"
                },
                new HttpHeader()
                {
                    Name = "Accept", Value = $"application/json"
                }
            };
            var passThrough = _externalExchangeRecord.MintType == "passThroughHandler";
            var externalUrl = passThrough ? _externalExchangeRecord.PassThroughHandler.Url : _externalExchangeRecord.ExternalFinalExchangeHandler.Url;

            (string content, HttpStatusCode statusCode)responseBag;
            using (var httpClient = _defaultHttpClientFactory.HttpClient)
            {
                responseBag = await Utils.EfficientApiCalls.HttpClientHelpers.PostStreamAsync(
                    _defaultHttpClientFactory.HttpClient,
                    externalUrl,
                    headers,
                    new TokenExchangeRequestPackage(tokenExchangeRequest)
                {
                    MapOpaqueKeyValuePairs = mapOpaqueKeyValuePairs
                },
                    CancellationToken.None);
            }

            if (responseBag.statusCode == HttpStatusCode.OK)
            {
                if (passThrough)
                {
                    var passThroughResult = JsonConvert.DeserializeObject <List <TokenExchangeResponse> >(responseBag.content);
                    return(passThroughResult);
                }
                else
                {
                    var tokenExchangeResponses        = new List <TokenExchangeResponse>();
                    var externalExchangeTokenRequests = JsonConvert.DeserializeObject <List <ExternalExchangeTokenResponse> >(responseBag.content);

                    foreach (var externalExchangeResourceOwnerTokenRequest in externalExchangeTokenRequests)
                    {
                        if (externalExchangeResourceOwnerTokenRequest.CustomTokenResponse != null)
                        {
                            var tokenExchangeResponse = new TokenExchangeResponse()
                            {
                                customToken = externalExchangeResourceOwnerTokenRequest.CustomTokenResponse
                            };
                            tokenExchangeResponses.Add(tokenExchangeResponse);
                        }
                        if (externalExchangeResourceOwnerTokenRequest.ArbitraryIdentityTokenRequest != null)
                        {
                            var arbitraryIdentityTokenRequest = externalExchangeResourceOwnerTokenRequest
                                                                .ArbitraryIdentityTokenRequest;
                            IdentityTokenRequest tokenRequest = new IdentityTokenRequest()
                            {
                                IdentityTokenLifetime = arbitraryIdentityTokenRequest.IdentityTokenLifetime,
                                ArbitraryClaims       = arbitraryIdentityTokenRequest.ArbitraryClaims,
                                Scope    = arbitraryIdentityTokenRequest.Scope,
                                Subject  = arbitraryIdentityTokenRequest.Subject,
                                ClientId = _externalExchangeRecord.ExternalFinalExchangeHandler.ClientId // configured value
                            };

                            var response =
                                await _tokenMintingService.MintIdentityTokenAsync(tokenRequest);

                            if (response.IsError)
                            {
                                throw new Exception(response.Error);
                            }
                            var tokenExchangeResponse = new TokenExchangeResponse()
                            {
                                IdentityToken = new IdentityTokenResponse()
                                {
                                    hint       = arbitraryIdentityTokenRequest.Hint,
                                    id_token   = response.IdentityToken,
                                    expires_in = response.ExpiresIn,
                                    authority  =
                                        $"{_httpContextAssessor.HttpContext.Request.Scheme}://{_httpContextAssessor.HttpContext.Request.Host}",
                                    HttpHeaders = arbitraryIdentityTokenRequest.HttpHeaders
                                }
                            };
                            tokenExchangeResponses.Add(tokenExchangeResponse);
                        }

                        if (externalExchangeResourceOwnerTokenRequest.ArbitraryResourceOwnerTokenRequest != null)
                        {
                            var arbitraryResourceOwnerTokenRequest = externalExchangeResourceOwnerTokenRequest
                                                                     .ArbitraryResourceOwnerTokenRequest;
                            ResourceOwnerTokenRequest resourceOwnerTokenRequest = new ResourceOwnerTokenRequest()
                            {
                                AccessTokenLifetime = arbitraryResourceOwnerTokenRequest.AccessTokenLifetime,
                                ArbitraryClaims     = arbitraryResourceOwnerTokenRequest.ArbitraryClaims,
                                Scope    = arbitraryResourceOwnerTokenRequest.Scope,
                                Subject  = arbitraryResourceOwnerTokenRequest.Subject,
                                ClientId = _externalExchangeRecord.ExternalFinalExchangeHandler.ClientId // configured value
                            };

                            var response =
                                await _tokenMintingService.MintResourceOwnerTokenAsync(resourceOwnerTokenRequest);

                            if (response.IsError)
                            {
                                throw new Exception(response.Error);
                            }

                            var tokenExchangeResponse = new TokenExchangeResponse()
                            {
                                accessToken = new AccessTokenResponse()
                                {
                                    hint          = arbitraryResourceOwnerTokenRequest.Hint,
                                    access_token  = response.AccessToken,
                                    refresh_token = response.RefreshToken,
                                    expires_in    = response.ExpiresIn,
                                    token_type    = response.TokenType,
                                    authority     =
                                        $"{_httpContextAssessor.HttpContext.Request.Scheme}://{_httpContextAssessor.HttpContext.Request.Host}",
                                    HttpHeaders = arbitraryResourceOwnerTokenRequest.HttpHeaders
                                }
                            };
                            tokenExchangeResponses.Add(tokenExchangeResponse);
                        }
                    }
                    return(tokenExchangeResponses);
                }
            }

            return(null);
        }
Example #11
0
        void LaunchMigration(
            string unityAccessToken,
            string projectPath,
            string organizationName,
            RepId repId,
            long changesetId,
            long branchId,
            Action afterWorkspaceMigratedAction,
            IProgressControls progressControls)
        {
            string serverName = string.Format(
                "{0}@cloud", organizationName);

            progressControls.ShowProgress(
                "Migrating project to Plastic SCM...");

            TokenExchangeResponse tokenExchangeResponse = null;
            WorkspaceInfo         workspaceInfo         = null;

            IThreadWaiter waiter = ThreadWaiter.GetWaiter(10);

            waiter.Execute(
                /*threadOperationDelegate*/
                delegate
            {
                // we just migrate a cloud project,
                // so let's assume we're going to use Cloud Edition
                SetupUnityEditionToken.CreateCloudEditionTokenIfNeeded();

                if (!ClientConfig.IsConfigured())
                {
                    AutoConfigClientConf.FromUnityAccessToken(
                        unityAccessToken, serverName, projectPath);
                }

                tokenExchangeResponse = WebRestApiClient.
                                        PlasticScm.TokenExchange(unityAccessToken);

                if (tokenExchangeResponse.Error != null)
                {
                    return;
                }

                CloudEditionWelcomeWindow.JoinCloudServer(
                    serverName,
                    tokenExchangeResponse.User,
                    tokenExchangeResponse.AccessToken);

                RepositoryInfo repInfo = new BaseCommandsImpl().
                                         GetRepositoryInfo(repId, serverName);

                if (repInfo == null)
                {
                    return;
                }

                repInfo.SetExplicitServer(serverName);

                workspaceInfo = CreateWorkspaceFromCollab.Create(
                    projectPath, repInfo.Name, repInfo,
                    changesetId, branchId,
                    new CreateWorkspaceFromCollab.Progress());
            },
                /*afterOperationDelegate*/
                delegate
            {
                progressControls.HideProgress();

                if (waiter.Exception != null)
                {
                    DisplayException(progressControls, waiter.Exception);
                    return;
                }

                if (tokenExchangeResponse.Error != null)
                {
                    mLog.ErrorFormat(
                        "Unable to get TokenExchangeResponse: {0} [code {1}]",
                        tokenExchangeResponse.Error.Message,
                        tokenExchangeResponse.Error.ErrorCode);
                }

                if (tokenExchangeResponse.Error != null ||
                    workspaceInfo == null)
                {
                    progressControls.ShowError(
                        "Failed to migrate the project to Plastic SCM");
                    return;
                }

                progressControls.ShowSuccess(
                    "The project migration to Plastic SCM is completed successfully");

                mIsMigrationCompleted = true;

                afterWorkspaceMigratedAction();
            });
        }