Skip to content

Commit

Permalink
Merge pull request #272 from atlassian/ARC-2807-admin-check-part-3
Browse files Browse the repository at this point in the history
Arc-2807 admin check part 3
  • Loading branch information
rachellerathbone authored Feb 7, 2024
2 parents a78ca00 + 3b536cd commit eabbe48
Show file tree
Hide file tree
Showing 16 changed files with 236 additions and 62 deletions.
19 changes: 13 additions & 6 deletions app/jenkins-for-jira-ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const App: React.FC = () => {
const [isFetchingFlag, setIsFetchingFlag] = useState<boolean>(false);
const [renovateConfigFlag, setRenovateConfigFlag] = useState<boolean>(false);
const [moduleKey, setModuleKey] = useState<string>('');
const [checkUserPermissionsFlag, setCheckUserPermissionsFlag] = useState<boolean>(false);

const getModuleKey = async () => {
const currentModuleKey = await fetchModuleKey();
Expand All @@ -59,14 +60,20 @@ const App: React.FC = () => {
FeatureFlags.RENOVATED_JENKINS_FOR_JIRA_CONFIG_FLOW
);

const checkUserPermissions = await fetchFeatureFlagFromBackend(
FeatureFlags.CHECK_USER_PERMISSIONS
);

getModuleKey();

if (isMounted) {
setRenovateConfigFlag(renovatedJenkinsFeatureFlag);
setCheckUserPermissionsFlag(checkUserPermissions);
setIsFetchingFlag(false);
}
} catch (error) {
console.error('Error fetching data:', error);
setIsFetchingFlag(false);
}
};

Expand Down Expand Up @@ -102,7 +109,7 @@ const App: React.FC = () => {
<Router history={history}>
<Switch>
<Route path="/">
<GlobalPage />
<GlobalPage checkUserPermissionsFlag={checkUserPermissionsFlag} />
</Route>
</Switch>
</Router>
Expand Down Expand Up @@ -134,19 +141,19 @@ const App: React.FC = () => {
<Route path="/pending/:id">
<PendingDeploymentState />
</Route>
<Route path="/create-server">
<Route path="/create-server/:path">
<ServerNameForm />
</Route>
<Route path="/update-server-name/:id">
<Route path="/update-server-name/:id/:path">
<ServerNameForm />
</Route>
<Route path="/setup/:id/:settings">
<Route path="/setup/:id/:settings/:path">
<JenkinsSetup />
</Route>
<Route path="/connection-complete/:id/:admin">
<Route path="/connection-complete/:id/:admin/:path">
<ConnectionComplete />
</Route>
<Route path="/connection-info">
<Route path="/connection-info/:path">
<ConnectionWizard />
</Route>
</Switch>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import {
import { useParams } from 'react-router';
import { ConnectionComplete } from './ConnectionComplete';
import * as getJenkinsServerWithSecretModule from '../../api/getJenkinsServerWithSecret';
import * as fetchGlobalPageUrlModule from '../../api/fetchGlobalPageUrl';

jest.mock('../../api/getJenkinsServerWithSecret');
jest.mock('../../api/fetchGlobalPageUrl');

jest.mock('react-router', () => ({
...jest.requireActual('react-router'),
Expand Down Expand Up @@ -55,6 +57,7 @@ describe('ConnectionComplete Component', () => {
});

it('should render server name and connection confirmation for non Jenkins admin', async () => {
jest.spyOn(fetchGlobalPageUrlModule, 'fetchGlobalPageUrl').mockResolvedValueOnce('https://somesite.atlassian.net/blah');
const mockParams = { id: '12345678', admin: 'requires-jenkins-admin' };
(useParams as jest.Mock).mockReturnValue(mockParams);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useHistory, useParams } from 'react-router';
import { cx } from '@emotion/css';
import Spinner from '@atlaskit/spinner';
import Button from '@atlaskit/button/standard-button';
import { router } from '@forge/bridge';
import { connectionFlowContainer, connectionFlowInnerContainer } from '../../GlobalStyles.styles';
import { ConnectionFlowHeader, ConnectionFlowServerNameSubHeader } from '../ConnectionWizard/ConnectionFlowHeader';
import { getJenkinsServerWithSecret } from '../../api/getJenkinsServerWithSecret';
Expand All @@ -11,14 +12,17 @@ import { serverNameFormOuterContainer } from '../ServerNameForm/ServerNameForm.s
import { connectionCompleteConfirmation, connectionCompleteContent } from './ConnectionComplete.styles';
import { AnalyticsEventTypes, AnalyticsScreenEventsEnum } from '../../common/analytics/analytics-events';
import { AnalyticsClient } from '../../common/analytics/analytics-client';
import { fetchGlobalPageUrl } from '../../api/fetchGlobalPageUrl';
import { ParamTypes } from '../../common/types';

const analyticsClient = new AnalyticsClient();

const ConnectionComplete = () => {
const history = useHistory();
const { path } = useParams<ParamTypes>();
const { admin: isJenkinsAdmin, id: uuid } = useParams<ParamTypes>();
const [serverName, setServerName] = useState('');
const [globalPageUrl, setGlobalPageUrl] = useState<string>('');

const getServer = useCallback(async () => {
try {
Expand All @@ -37,7 +41,9 @@ const ConnectionComplete = () => {

const fetchData = async () => {
try {
getServer();
const url = await fetchGlobalPageUrl();
setGlobalPageUrl(url);
await getServer();
} catch (error) {
console.error('Error fetching data:', error);
}
Expand All @@ -48,6 +54,12 @@ const ConnectionComplete = () => {

const handleNavigateToConnectionServerManagementScreen = (e: React.MouseEvent) => {
e.preventDefault();
console.log('path', path);

if (path === 'global') {
router.navigate(globalPageUrl);
}

history.push('/');
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ type ConnectionPanelProps = {
isUpdatingServer: boolean,
uuidOfRefreshServer: string,
handleRefreshUpdateServer(uuid: string): void,
moduleKey: string
moduleKey: string,
userIsAdmin?: boolean
};

const ConnectionPanel = ({
Expand All @@ -72,7 +73,8 @@ const ConnectionPanel = ({
isUpdatingServer,
uuidOfRefreshServer,
handleRefreshUpdateServer,
moduleKey
moduleKey,
userIsAdmin
}: ConnectionPanelProps): JSX.Element => {
const handleServerRefresh = (serverToRemove: JenkinsServer) => {
const refreshedServers = jenkinsServers.filter(
Expand Down Expand Up @@ -114,6 +116,7 @@ const ConnectionPanel = ({
updatedServer={updatedServer}
isUpdatingServer={isUpdatingServer}
moduleKey={moduleKey}
userIsAdmin={userIsAdmin}
/>
<ConnectionPanelMain
jenkinsServer={server}
Expand All @@ -123,6 +126,7 @@ const ConnectionPanel = ({
isUpdatingServer={isUpdatingServer}
uuidOfRefreshServer={uuidOfRefreshServer}
moduleKey={moduleKey}
userIsAdmin={userIsAdmin}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ type ConnectionPanelMainProps = {
updatedServer?: JenkinsServer,
isUpdatingServer: boolean,
uuidOfRefreshServer: string,
moduleKey: string
moduleKey: string,
userIsAdmin?: boolean
};

const SET_UP_GUIDE_TAB = 1;
Expand All @@ -75,7 +76,8 @@ const ConnectionPanelMain = ({
updatedServer,
isUpdatingServer,
uuidOfRefreshServer,
moduleKey
moduleKey,
userIsAdmin
}: ConnectionPanelMainProps): JSX.Element => {
const connectedState = jenkinsServer.connectedState || ConnectedState.PENDING;
const [selectedTabIndex, setSelectedTabIndex] = useState(0);
Expand Down Expand Up @@ -185,6 +187,7 @@ const ConnectionPanelMain = ({
refreshServersAfterDelete={refreshServers}
refreshServersAfterUpdate={handleRefreshUpdateServer}
moduleKey={moduleKey}
userIsAdmin={userIsAdmin}
/>
: <Tabs id="connection-panel-tabs" selected={selectedTabIndex} onChange={handleTabSelect}>
<TabList>
Expand Down Expand Up @@ -229,6 +232,7 @@ const ConnectionPanelMain = ({
uuidOfRefreshServer={uuidOfRefreshServer}
isUpdatingServer={isUpdatingServer}
moduleKey={moduleKey}
userIsAdmin={userIsAdmin}
/>
</Panel>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { useHistory } from 'react-router';
import { cx } from '@emotion/css';
import Button from '@atlaskit/button/standard-button';
import MoreIcon from '@atlaskit/icon/glyph/more';
import DropdownMenu, { DropdownItem, DropdownItemGroup } from '@atlaskit/dropdown-menu';
import { router } from '@forge/bridge';
import {
connectionPanelHeaderContainer,
connectionPanelHeaderContentContainer,
Expand All @@ -22,6 +23,7 @@ import {
AnalyticsUiEventsEnum
} from '../../common/analytics/analytics-events';
import { AnalyticsClient } from '../../common/analytics/analytics-client';
import { fetchAdminPath } from '../../api/fetchGlobalPageUrl';

const analyticsClient = new AnalyticsClient();

Expand All @@ -37,12 +39,15 @@ type ConnectionPanelTopProps = {
refreshServers(serverToRemove: JenkinsServer): void,
updatedServer?: JenkinsServer,
isUpdatingServer: boolean,
moduleKey: string
moduleKey: string,
userIsAdmin?: boolean
};

const ConnectionPanelTop = ({
server,
refreshServers,
moduleKey
moduleKey,
userIsAdmin
}: ConnectionPanelTopProps): JSX.Element => {
const history = useHistory();
const connectedState = server.connectedState || ConnectedState.PENDING;
Expand All @@ -51,8 +56,26 @@ const ConnectionPanelTop = ({
const [showConfirmServerDisconnect, setShowConfirmServerDisconnect] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [disconnectError, setDisconnectError] = useState<boolean>(false);
const [adminPageUrl, setAdminPageUrl] = useState<string>('');
const isAdminPage = moduleKey === CONFIG_PAGE;

useEffect(() => {
const fetchData = async () => {
try {
const url = await fetchAdminPath();
setAdminPageUrl(url);
} catch (error) {
console.error('Error fetching data:', error);
}
};

fetchData();
}, []);

const onClickDisconnect = async (serverToDelete: JenkinsServer) => {
setServerToDisconnect(serverToDelete);
setShowConfirmServerDisconnect(true);

await analyticsClient.sendAnalytics(
AnalyticsEventTypes.UiEvent,
AnalyticsUiEventsEnum.DisconnectServerName,
Expand All @@ -61,9 +84,6 @@ const ConnectionPanelTop = ({
actionSubject: 'button'
}
);

setServerToDisconnect(serverToDelete);
setShowConfirmServerDisconnect(true);
};

const onClickConnectionSettings = async (serverToOpen: JenkinsServer) => {
Expand All @@ -76,7 +96,13 @@ const ConnectionPanelTop = ({
}
);

history.push(`/setup/${serverToOpen.uuid}/connection-settings`);
const connectionSettingsPath = `/setup/${serverToOpen.uuid}/connection-settings`;

if (isAdminPage) {
history.push(`${connectionSettingsPath}/admin`);
} else {
router.navigate(`${adminPageUrl}${connectionSettingsPath}/global`);
}
};

const onClickRename = async (serverToRename: JenkinsServer) => {
Expand All @@ -89,7 +115,13 @@ const ConnectionPanelTop = ({
}
);

history.push(`/update-server-name/${serverToRename.uuid}`);
const updateServerNamePath = `/update-server-name/${serverToRename.uuid}`;

if (isAdminPage) {
history.push(`${updateServerNamePath}/admin`);
} else {
router.navigate(`${adminPageUrl}${updateServerNamePath}/global`);
}
};

const disconnectJenkinsServerHandler = async (
Expand Down Expand Up @@ -134,8 +166,6 @@ const ConnectionPanelTop = ({
};

const serverIsNotDuplicate = server.connectedState !== ConnectedState.DUPLICATE;
const isConfigPage = moduleKey && moduleKey === CONFIG_PAGE;

const buttonAndIconAppearance = disconnectError ? 'danger' : 'warning';
const modalTitleMessage =
disconnectError ? 'An error occurred while deleting your server' : 'Disconnect this Jenkins server?';
Expand Down Expand Up @@ -165,7 +195,7 @@ const ConnectionPanelTop = ({
</div>
</div>

{serverIsNotDuplicate && isConfigPage &&
{serverIsNotDuplicate && (userIsAdmin || CONFIG_PAGE) &&
<DropdownMenu
trigger={({ triggerRef, ...props }) => (
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ describe('NotConnectedState', () => {
refreshServersAfterDelete={refreshServers}
refreshServersAfterUpdate={handleRefreshAfterUpdate}
moduleKey={CONFIG_PAGE}
userIsAdmin={true}
/>);

expect(screen.getByText('Duplicate server')).toBeInTheDocument();
expect(screen.getByText('Delete')).toBeInTheDocument();
});
Expand All @@ -56,6 +58,7 @@ describe('NotConnectedState', () => {
refreshServersAfterDelete={refreshServers}
refreshServersAfterUpdate={handleRefreshAfterUpdate}
moduleKey={CONFIG_PAGE}
userIsAdmin={true}
/>);

fireEvent.click(screen.getByText('Delete'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { JenkinsServer } from '../../../../src/common/types';
import { disconnectJenkinsServer } from '../../api/disconnectJenkinsServer';
import { ConnectionPanelContent } from './ConnectionPanelContent';
import { DELETE_MODAL_TEST_ID, GLOBAL_PAGE } from '../../common/constants';
import { CONFIG_PAGE, DELETE_MODAL_TEST_ID } from '../../common/constants';
import { JenkinsModal } from '../JenkinsServerList/ConnectedServer/JenkinsModal';
import { AnalyticsEventTypes, AnalyticsTrackEventsEnum } from '../../common/analytics/analytics-events';
import { AnalyticsClient } from '../../common/analytics/analytics-client';
Expand All @@ -23,7 +23,8 @@ type NotConnectedStateProps = {
refreshServersAfterUpdate(serverUuidToUpdate: string): void,
uuidOfRefreshServer?: string,
isUpdatingServer?: boolean,
moduleKey: string
moduleKey: string,
userIsAdmin?: boolean
};

const NotConnectedState = ({
Expand All @@ -33,7 +34,8 @@ const NotConnectedState = ({
refreshServersAfterUpdate,
uuidOfRefreshServer,
isUpdatingServer,
moduleKey
moduleKey,
userIsAdmin
}: NotConnectedStateProps): JSX.Element => {
const [serverToDeleteUuid, setServerToDeleteUuid] = useState<string>('');
const [isDeletingServer, setIsDeletingServer] = useState<boolean>(false);
Expand Down Expand Up @@ -79,9 +81,9 @@ const NotConnectedState = ({

let firstButtonLabel;

if (connectedState === ConnectedState.DUPLICATE && moduleKey !== GLOBAL_PAGE) {
if (connectedState === ConnectedState.DUPLICATE && (userIsAdmin || moduleKey === CONFIG_PAGE)) {
firstButtonLabel = 'Delete';
} else if (connectedState === ConnectedState.DUPLICATE && moduleKey === GLOBAL_PAGE) {
} else if (connectedState === ConnectedState.DUPLICATE && !userIsAdmin) {
firstButtonLabel = undefined;
} else {
firstButtonLabel = 'Refresh';
Expand Down
Loading

0 comments on commit eabbe48

Please sign in to comment.