Skip to content

Commit 98b8f5d

Browse files
dgolovinbenoitf
andauthored
feat: show Red Hat SSO status icon with tooltip in status bar (#91)
Signed-off-by: Denis Golovin <[email protected]> Co-authored-by: Florent BENOIT <[email protected]>
1 parent e85c5df commit 98b8f5d

5 files changed

+105
-24
lines changed

package.json

+14-1
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,21 @@
1515
{
1616
"command": "redhat.authentication.signin",
1717
"title": "Red Hat SSO Provider: Sign In"
18+
},
19+
{
20+
"command": "redhat.authentication.navigate.settings",
21+
"title": "Red Hat SSO Provider: Navigate to Authentication Settings"
22+
}
23+
],
24+
"icons": {
25+
"redhat-icon": {
26+
"description": "Red Hat icon",
27+
"default": {
28+
"fontPath": "redhat-icon.woff2",
29+
"fontCharacter": "\\e900"
30+
}
1831
}
19-
]
32+
}
2033
},
2134
"scripts": {
2235
"build": "rollup --bundleConfigAsCjs --config rollup.config.js --compact --environment BUILD:production && node ./scripts/build.js",

redhat-icon.woff2

704 Bytes
Binary file not shown.

src/extension.ts

+37-12
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ import {
2424
} from './authentication-service';
2525
import { ServiceAccountV1, ContainerRegistryAuthorizerClient } from '@redhat-developer/rhcra-client';
2626
import path from 'node:path';
27-
import { accessSync, constants, existsSync, readFileSync } from 'node:fs';
27+
import { accessSync, constants, readFileSync } from 'node:fs';
2828
import { restartPodmanMachine, runRpmInstallSubscriptionManager, runSubscriptionManager, runSubscriptionManagerActivationStatus, runSubscriptionManagerRegister, runSubscriptionManagerUnregister } from './podman-cli';
2929
import { SubscriptionManagerClient } from '@redhat-developer/rhsm-client';
3030
import { isLinux } from './util';
31+
import { SSOStatusBarItem } from './status-bar-item';
3132

3233
let authenticationServicePromise: Promise<RedHatAuthenticationService>;
3334
let currentSession: extensionApi.AuthenticationSession | undefined;
@@ -201,16 +202,27 @@ async function removeSession(sessionId: string): Promise<void> {
201202
onDidChangeSessions.fire({ removed: [session!] });
202203
}
203204

205+
async function buildAndInitializeAuthService(context: extensionApi.ExtensionContext, statusBarItem: SSOStatusBarItem) {
206+
const service = await RedHatAuthenticationService.build(context, getAuthConfig())
207+
context.subscriptions.push(service);
208+
await service.initialize();
209+
const storedSessions = await service.getSessions();
210+
if (storedSessions.length > 0) {
211+
statusBarItem.logInAs(storedSessions[0].account.label);
212+
}
213+
return service;
214+
}
215+
204216
export async function activate(context: extensionApi.ExtensionContext): Promise<void> {
205217
console.log('starting redhat-authentication extension');
206-
if (!authenticationServicePromise) {
207-
authenticationServicePromise = RedHatAuthenticationService.build(context, getAuthConfig())
208-
.then(service => {
209-
context.subscriptions.push(service);
210-
service.initialize();
211-
return service;
212-
});
213-
}
218+
219+
// create status bar item for Red Hat SSO Provider
220+
const statusBarItem = new SSOStatusBarItem();
221+
statusBarItem.show();
222+
context.subscriptions.push(statusBarItem);
223+
224+
// build and initialize auth service and update status bar state
225+
authenticationServicePromise = buildAndInitializeAuthService(context, statusBarItem);
214226
context.subscriptions.push(extensionApi.registry.suggestRegistry({
215227
name: 'Red Hat Container Registry',
216228
icon: fileToBase64(path.resolve(__dirname,'..', 'icon.png')),
@@ -240,14 +252,18 @@ export async function activate(context: extensionApi.ExtensionContext): Promise<
240252
},
241253
);
242254

243-
const onDidChangeSessionDisposable = extensionApi.authentication.onDidChangeSessions(async (e) => {
244-
if(e.provider.id === 'redhat.authentication-provider') {
255+
const onDidChangeSessionDisposable = extensionApi.authentication.onDidChangeSessions(async e => {
256+
if (e.provider.id === 'redhat.authentication-provider') {
245257
const newSession = await signIntoRedHatDeveloperAccount(false);
246258
if (!currentSession && newSession) {
247259
currentSession = newSession;
260+
statusBarItem.logInAs(newSession.account.label);
248261
return extensionApi.commands.executeCommand('redhat.authentication.signin');
249262
}
250263
currentSession = newSession;
264+
if (!newSession) {
265+
statusBarItem.logOut();
266+
}
251267
}
252268
});
253269

@@ -257,6 +273,8 @@ export async function activate(context: extensionApi.ExtensionContext): Promise<
257273

258274
const SignInCommand = extensionApi.commands.registerCommand('redhat.authentication.signin', async () => {
259275

276+
await signIntoRedHatDeveloperAccount(true); //for the use case when user logged out, vm activated and registry configured
277+
260278
const registryAccess = extensionApi.window.withProgress({
261279
location: extensionApi.ProgressLocation.TASK_WIDGET, title: 'Configuring Red Hat Registry'
262280
},
@@ -315,7 +333,14 @@ export async function activate(context: extensionApi.ExtensionContext): Promise<
315333
);
316334
});
317335

318-
context.subscriptions.push(SignInCommand, SignOutCommand, SignUpCommand, onDidChangeSessionDisposable);
336+
const GotoAuthCommand = extensionApi.commands.registerCommand(
337+
'redhat.authentication.navigate.settings',
338+
async () => {
339+
extensionApi.navigation.navigateToAuthentication();
340+
},
341+
);
342+
343+
context.subscriptions.push(SignInCommand, SignOutCommand, SignUpCommand, onDidChangeSessionDisposable, GotoAuthCommand);
319344
}
320345

321346
export function deactivate(): void {

src/status-bar-item.ts

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**********************************************************************
2+
* Copyright (C) 2024 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
19+
import { StatusBarAlignLeft, StatusBarItem, window, Disposable } from '@podman-desktop/api';
20+
21+
export class SSOStatusBarItem implements Disposable {
22+
#statusBarItem: StatusBarItem = window.createStatusBarItem(StatusBarAlignLeft, 50);
23+
24+
constructor() {
25+
this.#statusBarItem.iconClass = '${redhat-icon}';
26+
this.logOut();
27+
}
28+
29+
public dispose(): void {
30+
this.#statusBarItem.dispose();
31+
}
32+
33+
public logInAs(email: string) {
34+
this.#statusBarItem.tooltip = `Red Hat SSO: Logged in as ${email}`;
35+
this.#statusBarItem.command = 'redhat.authentication.navigate.settings';
36+
}
37+
38+
public logOut() {
39+
this.#statusBarItem.tooltip = 'Red Hat SSO: Logged Out';
40+
this.#statusBarItem.command = 'redhat.authentication.signin';
41+
}
42+
43+
public show() {
44+
this.#statusBarItem.show();
45+
}
46+
}

tsconfig.json

+8-11
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
{
22
"compilerOptions": {
3-
"lib": [
4-
"ES2017",
5-
"webworker"
6-
],
3+
"lib": [ "ES2017", "webworker" ],
4+
"module": "esnext",
5+
"target": "esnext",
76
"sourceMap": true,
87
"rootDir": "src",
98
"outDir": "dist",
109
"skipLibCheck": true,
11-
"types": [
12-
"node",
13-
],
14-
"allowSyntheticDefaultImports": true
10+
"types": [ "node" ],
11+
"allowSyntheticDefaultImports": true,
12+
"moduleResolution": "Node",
13+
"esModuleInterop": true
1514
},
16-
"include": [
17-
"src/**/*.ts"
18-
]
15+
"include": [ "src/**/*.ts" ]
1916
}

0 commit comments

Comments
 (0)