Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions src/containers/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import {DEVELOPER_UI_TITLE} from '../../utils/constants';
import {createDeveloperUIInternalPageHref} from '../../utils/developerUI/developerUI';
import {useTypedSelector} from '../../utils/hooks';
import {useDatabaseFromQuery} from '../../utils/hooks/useDatabaseFromQuery';
import {useIsUserAllowedToMakeChanges} from '../../utils/hooks/useIsUserAllowedToMakeChanges';
import {
useIsUserAllowedToMakeChanges,
useIsViewerUser,
} from '../../utils/hooks/useIsUserAllowedToMakeChanges';

import {getBreadcrumbs} from './breadcrumbs';
import {headerKeyset} from './i18n';
Expand All @@ -27,6 +30,7 @@ function Header() {
const {page, pageBreadcrumbsOptions} = useTypedSelector((state) => state.header);
const singleClusterMode = useTypedSelector((state) => state.singleClusterMode);
const isUserAllowedToMakeChanges = useIsUserAllowedToMakeChanges();
const isViewerUser = useIsViewerUser();

const {title: clusterTitle} = useClusterBaseInfo();

Expand All @@ -39,7 +43,11 @@ function Header() {
useAddClusterFeatureAvailable() && uiFactory.onAddCluster !== undefined;

const breadcrumbItems = React.useMemo(() => {
let options = {...pageBreadcrumbsOptions, singleClusterMode};
let options = {
...pageBreadcrumbsOptions,
singleClusterMode,
isViewerUser,
};

if (clusterTitle) {
options = {
Expand All @@ -53,7 +61,7 @@ function Header() {
return breadcrumbs.map((item) => {
return {...item, action: () => {}};
});
}, [clusterTitle, page, pageBreadcrumbsOptions, singleClusterMode]);
}, [clusterTitle, page, pageBreadcrumbsOptions, singleClusterMode, isViewerUser]);

const renderRightControls = () => {
const elements: React.ReactNode[] = [];
Expand Down
11 changes: 9 additions & 2 deletions src/containers/Header/breadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ const getQueryForTenant = (type: 'nodes' | 'tablets') => ({
[TenantTabsGroups.diagnosticsTab]: TENANT_DIAGNOSTICS_TABS_IDS[type],
});

const getClustersBreadcrumbs: GetBreadcrumbs<ClustersBreadcrumbsOptions> = () => {
const getClustersBreadcrumbs: GetBreadcrumbs<ClustersBreadcrumbsOptions> = (options) => {
if (!options.isViewerUser) {
return [];
}
return [
{
text: headerKeyset('breadcrumbs.clusters'),
Expand All @@ -56,7 +59,11 @@ const getClustersBreadcrumbs: GetBreadcrumbs<ClustersBreadcrumbsOptions> = () =>
};

const getClusterBreadcrumbs: GetBreadcrumbs<ClusterBreadcrumbsOptions> = (options, query = {}) => {
const {clusterName, clusterTab, singleClusterMode} = options;
const {clusterName, clusterTab, singleClusterMode, isViewerUser} = options;

if (!isViewerUser) {
return [];
}

let breadcrumbs: RawBreadcrumbItem[] = [];

Expand Down
6 changes: 4 additions & 2 deletions src/store/reducers/authentication/authentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const slice = createSlice({
}
},
setUser: (state, action: PayloadAction<TUserToken>) => {
const {UserSID, AuthType, IsMonitoringAllowed} = action.payload;
const {UserSID, AuthType, IsMonitoringAllowed, IsViewerAllowed} = action.payload;
Copy link

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The destructuring should also include IsDatabaseAllowed since this new field was added to the API type and should be considered when determining viewer user status.

Suggested change
const {UserSID, AuthType, IsMonitoringAllowed, IsViewerAllowed} = action.payload;
const {UserSID, AuthType, IsMonitoringAllowed, IsViewerAllowed, IsDatabaseAllowed} = action.payload;

Copilot uses AI. Check for mistakes.

state.user = AuthType === 'Login' ? UserSID : undefined;

Expand All @@ -35,17 +35,19 @@ export const slice = createSlice({
// Otherwise every user is allowed to make changes
// Anyway there will be guards on backend
state.isUserAllowedToMakeChanges = IsMonitoringAllowed !== false;
state.isViewerUser = IsViewerAllowed;
Copy link

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The isViewerUser field should consider both IsViewerAllowed and IsDatabaseAllowed flags. According to the API documentation, IsViewerAllowed includes IsDatabaseAllowed rights, so a user with either flag should be considered a viewer user.

Suggested change
state.isViewerUser = IsViewerAllowed;
state.isViewerUser = IsViewerAllowed || IsDatabaseAllowed;

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsViewerAllowed includes IsDatabaseAllowed and some more rights. So, if user has only IsDatabaseAllowed - it is not enough to be isViewerUser

},
},
selectors: {
selectIsUserAllowedToMakeChanges: (state) => state.isUserAllowedToMakeChanges,
selectIsViewerUser: (state) => state.isViewerUser,
selectUser: (state) => state.user,
},
});

export default slice.reducer;
export const {setIsAuthenticated, setUser} = slice.actions;
export const {selectIsUserAllowedToMakeChanges, selectUser} = slice.selectors;
export const {selectIsUserAllowedToMakeChanges, selectIsViewerUser, selectUser} = slice.selectors;

export const authenticationApi = api.injectEndpoints({
endpoints: (build) => ({
Expand Down
1 change: 1 addition & 0 deletions src/store/reducers/authentication/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export interface AuthenticationState {
isAuthenticated: boolean;
isUserAllowedToMakeChanges?: boolean;
isViewerUser?: boolean;
user: string | undefined;
}
4 changes: 3 additions & 1 deletion src/store/reducers/header/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ export type Page =
| 'storageGroup'
| undefined;

export interface ClustersBreadcrumbsOptions {}
export interface ClustersBreadcrumbsOptions {
isViewerUser?: boolean;
}

export interface ClusterBreadcrumbsOptions extends ClustersBreadcrumbsOptions {
clusterName?: string;
Expand Down
4 changes: 3 additions & 1 deletion src/types/api/whoami.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ export interface TUserToken {
OriginalUserToken?: string;
AuthType?: string;

/** Is user allowed to view data */
/** Is user allowed to view only database specific data */
IsDatabaseAllowed?: boolean;
/** Is user allowed to view data (includes IsDatabaseAllowed rights) */
IsViewerAllowed?: boolean;
/** Is user allowed to view deeper and make simple changes */
IsMonitoringAllowed?: boolean;
Expand Down
8 changes: 7 additions & 1 deletion src/utils/hooks/useIsUserAllowedToMakeChanges.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import {selectIsUserAllowedToMakeChanges} from '../../store/reducers/authentication/authentication';
import {
selectIsUserAllowedToMakeChanges,
selectIsViewerUser,
} from '../../store/reducers/authentication/authentication';

import {useTypedSelector} from './useTypedSelector';

export function useIsUserAllowedToMakeChanges() {
return useTypedSelector(selectIsUserAllowedToMakeChanges);
}
export function useIsViewerUser() {
return useTypedSelector(selectIsViewerUser);
}
Loading