Skip to content

Commit 0c38f12

Browse files
committed
frontend: Add multi-cluster user logout support
- Visual support for displaying authenticated users per cluster in TopBar. - Implemented individual cluster logout functionality. - Added SelfSubjectReview API support for fetching user info. - Fixed multi-cluster selection state bug in useSelectedClusters hook. - Improved logout UX to persist view on remaining clusters. - Added unit tests for user info fetching logic. - Added Storybook story for multi-cluster user logout. Signed-off-by: alokdangre <alokdangre@gmail.com>
1 parent d9a3326 commit 0c38f12

File tree

7 files changed

+529
-107
lines changed

7 files changed

+529
-107
lines changed

frontend/src/components/App/TopBar.stories.tsx

Lines changed: 116 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { configureStore } from '@reduxjs/toolkit';
1818
import { Meta, StoryFn } from '@storybook/react';
1919
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
2020
import { get } from 'lodash';
21+
import { http, HttpResponse } from 'msw';
2122
import { PropsWithChildren } from 'react';
2223
import { Provider } from 'react-redux';
2324
import { MemoryRouter } from 'react-router-dom';
@@ -62,6 +63,16 @@ export default {
6263
);
6364
},
6465
],
66+
parameters: {
67+
msw: {
68+
handlers: [
69+
http.post(
70+
'http://localhost:4466/clusters/ak8s-desktop/apis/authentication.k8s.io/v1/selfsubjectreviews',
71+
() => HttpResponse.json({ status: { userInfo: { username: 'default-user' } } })
72+
),
73+
],
74+
},
75+
},
6576
} as Meta;
6677

6778
function OurTopBar(args: PropsWithChildren<PureTopBarProps>) {
@@ -131,9 +142,24 @@ WithUserInfo.args = {
131142
logout: () => {},
132143
cluster: 'ak8s-desktop',
133144
clusters: { 'ak8s-desktop': '' },
134-
userInfo: {
135-
username: 'Ada Lovelace',
136-
email: 'ada@example.com',
145+
};
146+
WithUserInfo.parameters = {
147+
msw: {
148+
handlers: {
149+
story: [
150+
http.post(
151+
'http://localhost:4466/clusters/ak8s-desktop/apis/authentication.k8s.io/v1/selfsubjectreviews',
152+
() =>
153+
HttpResponse.json({
154+
status: {
155+
userInfo: {
156+
username: 'Ada Lovelace',
157+
},
158+
},
159+
})
160+
),
161+
],
162+
},
137163
},
138164
};
139165

@@ -143,8 +169,24 @@ WithEmailOnly.args = {
143169
logout: () => {},
144170
cluster: 'ak8s-desktop',
145171
clusters: { 'ak8s-desktop': '' },
146-
userInfo: {
147-
email: 'grace@example.com',
172+
};
173+
WithEmailOnly.parameters = {
174+
msw: {
175+
handlers: {
176+
story: [
177+
http.post(
178+
'http://localhost:4466/clusters/ak8s-desktop/apis/authentication.k8s.io/v1/selfsubjectreviews',
179+
() =>
180+
HttpResponse.json({
181+
status: {
182+
userInfo: {
183+
username: 'grace@example.com',
184+
},
185+
},
186+
})
187+
),
188+
],
189+
},
148190
},
149191
};
150192

@@ -154,7 +196,19 @@ UndefinedData.args = {
154196
logout: () => {},
155197
cluster: 'ak8s-desktop',
156198
clusters: { 'ak8s-desktop': '' },
157-
userInfo: undefined,
199+
};
200+
UndefinedData.parameters = {
201+
msw: {
202+
handlers: {
203+
story: [
204+
// Return 404 to simulate missing API or data
205+
http.post(
206+
'http://localhost:4466/clusters/ak8s-desktop/apis/authentication.k8s.io/v1/selfsubjectreviews',
207+
() => new HttpResponse(null, { status: 404 })
208+
),
209+
],
210+
},
211+
},
158212
};
159213

160214
export const EmptyUserInfo = PureTemplate.bind({});
@@ -163,8 +217,61 @@ EmptyUserInfo.args = {
163217
logout: () => {},
164218
cluster: 'ak8s-desktop',
165219
clusters: { 'ak8s-desktop': '' },
166-
userInfo: {
167-
email: '',
168-
username: '',
220+
};
221+
EmptyUserInfo.parameters = {
222+
msw: {
223+
handlers: {
224+
story: [
225+
http.post(
226+
'http://localhost:4466/clusters/ak8s-desktop/apis/authentication.k8s.io/v1/selfsubjectreviews',
227+
() => HttpResponse.json({})
228+
),
229+
],
230+
},
231+
},
232+
};
233+
234+
export const MultiCluster = PureTemplate.bind({});
235+
MultiCluster.args = {
236+
appBarActions: [],
237+
logout: () => {},
238+
cluster: 'admin-cluster',
239+
clusters: {
240+
'admin-cluster': '',
241+
'view-cluster': '',
242+
'other-cluster': '',
243+
},
244+
selectedClusters: ['admin-cluster', 'view-cluster'],
245+
};
246+
MultiCluster.parameters = {
247+
msw: {
248+
handlers: {
249+
story: [
250+
http.post(
251+
'http://localhost:4466/clusters/admin-cluster/apis/authentication.k8s.io/v1/selfsubjectreviews',
252+
() =>
253+
HttpResponse.json({
254+
status: {
255+
userInfo: {
256+
username: 'admin-user',
257+
groups: ['system:masters'],
258+
},
259+
},
260+
})
261+
),
262+
http.post(
263+
'http://localhost:4466/clusters/view-cluster/apis/authentication.k8s.io/v1/selfsubjectreviews',
264+
() =>
265+
HttpResponse.json({
266+
status: {
267+
userInfo: {
268+
username: 'view-user',
269+
groups: ['view-group'],
270+
},
271+
},
272+
})
273+
),
274+
],
275+
},
169276
},
170277
};

0 commit comments

Comments
 (0)