in server/aws-lsp-codewhisperer/src/shared/amazonQServiceManager/AmazonQTokenServiceManager.ts [273:404]
private async handleProfileChange(newProfileArn: string | null, token: CancellationToken): Promise<void> {
if (!this.enableDeveloperProfileSupport) {
this.log('Developer Profiles Support is not enabled')
return
}
if (typeof newProfileArn === 'string' && newProfileArn.length === 0) {
throw new Error('Received invalid Profile ARN (empty string)')
}
this.logServiceState('UpdateProfile is requested')
// Test if connection type changed
this.handleSsoConnectionChange()
if (this.connectionType === 'none') {
if (newProfileArn !== null) {
throw new AmazonQServicePendingSigninError()
}
this.logServiceState('Received null profile while not connected, ignoring request')
return
}
if (this.connectionType !== 'identityCenter') {
this.logServiceState('Q Profile can not be set')
throw new AmazonQServiceNoProfileSupportError(
`Connection type ${this.connectionType} does not support Developer Profiles feature.`
)
}
if ((this.state === 'INITIALIZED' && this.activeIdcProfile) || this.state === 'PENDING_Q_PROFILE') {
// Change status to pending to prevent API calls until profile is updated.
// Because `listAvailableProfiles` below can take few seconds to complete,
// there is possibility that client could send requests while profile is changing.
this.state = 'PENDING_Q_PROFILE_UPDATE'
}
// Client sent an explicit null, indicating they want to reset the assigned profile (if any)
if (newProfileArn === null) {
this.logServiceState('Received null profile, resetting to PENDING_Q_PROFILE state')
this.resetCodewhispererService()
this.state = 'PENDING_Q_PROFILE'
return
}
const parsedArn = parse(newProfileArn)
const endpoint = AWS_Q_ENDPOINTS.get(parsedArn.region)
if (!endpoint) {
throw new Error('Requested profileArn region is not supported')
}
const profiles = await getListAllAvailableProfilesHandler(this.serviceFactory)({
connectionType: 'identityCenter',
logging: this.logging,
token: token,
endpoints: new Map([[parsedArn.region, endpoint]]),
})
this.handleTokenCancellationRequest(token)
const newProfile = profiles.find(el => el.arn === newProfileArn)
if (!newProfile || !newProfile.identityDetails?.region) {
this.log(`Amazon Q Profile ${newProfileArn} is not valid`)
this.resetCodewhispererService()
this.state = 'PENDING_Q_PROFILE'
throw new AmazonQServiceInvalidProfileError('Requested Amazon Q Profile does not exist')
}
this.handleTokenCancellationRequest(token)
if (!this.activeIdcProfile) {
this.activeIdcProfile = newProfile
this.createCodewhispererServiceInstances('identityCenter', newProfile.identityDetails.region)
this.state = 'INITIALIZED'
this.log(
`Initialized identityCenter connection to region ${newProfile.identityDetails.region} for profile ${newProfile.arn}`
)
return
}
// Profile didn't change
if (this.activeIdcProfile && this.activeIdcProfile.arn === newProfile.arn) {
// Update cached profile fields, keep existing client
this.log(`Profile selection did not change, active profile is ${this.activeIdcProfile.arn}`)
this.activeIdcProfile = newProfile
this.state = 'INITIALIZED'
return
}
this.handleTokenCancellationRequest(token)
// At this point new valid profile is selected.
const oldRegion = this.activeIdcProfile.identityDetails?.region
const newRegion = newProfile.identityDetails.region
if (oldRegion === newRegion) {
this.log(`New profile is in the same region as old one, keeping exising service.`)
this.log(`New active profile is ${this.activeIdcProfile.arn}, region ${oldRegion}`)
this.activeIdcProfile = newProfile
this.state = 'INITIALIZED'
if (this.cachedCodewhispererService) {
this.cachedCodewhispererService.profileArn = newProfile.arn
}
if (this.cachedStreamingClient) {
this.cachedStreamingClient.profileArn = newProfile.arn
}
return
}
this.log(`Switching service client region from ${oldRegion} to ${newRegion}`)
this.handleTokenCancellationRequest(token)
// Selected new profile is in different region. Re-initialize service
this.resetCodewhispererService()
this.activeIdcProfile = newProfile
this.createCodewhispererServiceInstances('identityCenter', newProfile.identityDetails.region)
this.state = 'INITIALIZED'
return
}