Skip to content

Commit

Permalink
lightspeed: use the code value from the 403 (#1024)
Browse files Browse the repository at this point in the history
* lightspeed: use the code value from the 403

The 403 error can now return a `code` value to specify the nature of the
error.
`permission_denied_wca_api_key_is_missing` is the first case we can get.
The error happens when the access is denied because the user has a seat
but the organization has not been fully configured yet.

* Lightspeed: show an error when the WCA key is not set yet

Handle the `permission_denied__org_not_ready_because_wca_not_configured`
error and returns the following error to the user:

```
Contact your administrator to configure IBM watsonx Code Assistant model settings for your organization.
```

---------

Co-authored-by: Sorin Sbarnea <ssbarnea@redhat.com>
  • Loading branch information
goneri and ssbarnea authored Dec 9, 2023
1 parent 164c375 commit 4517575
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 3 deletions.
18 changes: 18 additions & 0 deletions src/features/lightspeed/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,24 @@ export class LightSpeedAPI {
vscode.window.showErrorMessage(
`Model ID "${this.settingsManager.settings.lightSpeedService.model}" is invalid. Please contact your administrator.`
);
} else if (
responseErrorData &&
responseErrorData.hasOwnProperty("code") &&
responseErrorData.code ===
"permission_denied__org_ready_user_has_no_seat"
) {
vscode.window.showErrorMessage(
`You do not have a licensed seat for Ansible Lightspeed and your organization is using the paid commercial service. Contact your Red Hat Organization's administrator for more information on how to get a licensed seat.`
);
} else if (
responseErrorData &&
responseErrorData.hasOwnProperty("code") &&
responseErrorData.code ===
"permission_denied__org_not_ready_because_wca_not_configured"
) {
vscode.window.showErrorMessage(
`Contact your administrator to configure IBM watsonx Code Assistant model settings for your organization.`
);
} else {
vscode.window.showErrorMessage(
`User not authorized to access Ansible Lightspeed.`
Expand Down
28 changes: 27 additions & 1 deletion src/features/lightspeed/lightSpeedOAuthProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,18 @@ export class LightSpeedAuthenticationProvider

const identifier = uuid();
const userName = userinfo.external_username || userinfo.username || "";
const rhOrgHasSubscription = userinfo.rh_org_has_subscription
? userinfo.rh_org_has_subscription
: false;
const rhUserHasSeat = userinfo.rh_user_has_seat
? userinfo.rh_user_has_seat
: false;

let label = userName;
if (rhUserHasSeat) {
label += " (licensed)";
} else if (rhOrgHasSubscription) {
label += " (no seat assigned)";
} else {
label += " (Tech Preview)";
}
Expand Down Expand Up @@ -172,7 +177,8 @@ export class LightSpeedAuthenticationProvider

lightSpeedManager.statusBarProvider.statusBar.text =
await lightSpeedManager.statusBarProvider.getLightSpeedStatusBarText(
rhUserHasSeat
rhUserHasSeat,
rhOrgHasSubscription
);

lightSpeedManager.statusBarProvider.setLightSpeedStatusBarTooltip(
Expand Down Expand Up @@ -630,4 +636,24 @@ export class LightSpeedAuthenticationProvider
return false;
}
}

public async rhOrgHasSubscription(): Promise<boolean | undefined> {
const authSession = await this.getLightSpeedAuthSession();
if (authSession === undefined) {
console.log(
"[ansible-lightspeed-oauth] User authentication session not found."
);
return undefined;
} else if (authSession?.rhOrgHasSubscription) {
console.log(
`[ansible-lightspeed-oauth] User "${authSession?.account?.label}" has an Org with a subscription.`
);
return true;
} else {
console.log(
`[ansible-lightspeed-oauth] User "${authSession?.account?.label}" does not have an Org with a subscription.`
);
return false;
}
}
}
9 changes: 8 additions & 1 deletion src/features/lightspeed/statusBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,21 @@ export class LightspeedStatusBar {
}

public async getLightSpeedStatusBarText(
rhUserHasSeat?: boolean
rhUserHasSeat?: boolean,
rhOrgHasSubscription?: boolean
): Promise<string> {
let lightSpeedStatusbarText;
if (rhUserHasSeat === undefined) {
rhUserHasSeat = await this.lightSpeedAuthProvider.rhUserHasSeat();
}
if (rhOrgHasSubscription === undefined) {
rhOrgHasSubscription =
await this.lightSpeedAuthProvider.rhOrgHasSubscription();
}
if (rhUserHasSeat === true) {
lightSpeedStatusbarText = "Lightspeed (licensed)";
} else if (rhOrgHasSubscription === true && rhUserHasSeat === false) {
lightSpeedStatusbarText = "Lightspeed (no seat assigned)";
} else if (rhUserHasSeat === false) {
lightSpeedStatusbarText = "Lightspeed (Tech Preview)";
} else {
Expand Down
2 changes: 2 additions & 0 deletions src/features/lightspeed/utils/webUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ export function getLoggedInSessionDetails(
const modelInfo: LightspeedSessionModelInfo = {};
if (sessionData.rhUserHasSeat) {
userInfo.userType = "Licensed";
} else if (sessionData.rhOrgHasSubscription && sessionData.rhUserHasSeat) {
userInfo.userType = "No seat assigned";
} else {
userInfo.userType = "Tech Preview";
}
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/lightspeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export interface IAdditionalContext {
}

export interface LightspeedSessionUserInfo {
userType?: "Licensed" | "Tech Preview";
userType?: "Licensed" | "No seat assigned" | "Tech Preview";
role?: string;
subscribed?: boolean;
}
Expand Down

0 comments on commit 4517575

Please sign in to comment.