diff --git a/src/server/index.tsx b/src/server/index.tsx index 949a5ae0e..1bb9eecee 100644 --- a/src/server/index.tsx +++ b/src/server/index.tsx @@ -104,6 +104,9 @@ app.get('*', async (req: express.Request, res: express.Response) => { jiraProjectCustomFieldName: process.env.JIRA_PROJECT_FIELD_NAME || '', jiraProjectCustomFieldLabel: process.env.JIRA_PROJECT_FIELD_LABEL || 'Nexus Project', + ...(process.env.JIRA_SUPPORTED_REALMS && { + jiraSupportedRealms: process.env.JIRA_SUPPORTED_REALMS.split(','), + }), }, uiSettings: DEFAULT_UI_SETTINGS, oidc: { diff --git a/src/shared/containers/JIRA/JIRAPluginContainer.tsx b/src/shared/containers/JIRA/JIRAPluginContainer.tsx index c4b86dd7a..53f57aa91 100644 --- a/src/shared/containers/JIRA/JIRAPluginContainer.tsx +++ b/src/shared/containers/JIRA/JIRAPluginContainer.tsx @@ -1,4 +1,3 @@ -import { Collapse } from 'antd'; import * as React from 'react'; import { Resource } from '@bbp/nexus-sdk'; import JIRAPluginUI, { AuthorizeJiraUI } from '../../components/JIRA/JIRA'; @@ -8,16 +7,12 @@ type JIRAPluginContainerProps = { resource: Resource; projectLabel: string; orgLabel: string; - collapsed: boolean; - handleCollapseChanged: () => void; }; const JIRAPluginContainer = ({ resource, projectLabel, orgLabel, - collapsed, - handleCollapseChanged, }: JIRAPluginContainerProps) => { const { projects, @@ -45,35 +40,26 @@ const JIRAPluginContainer = ({ commentCount: issue.commentCount, })); - return ( - - - {!isJiraConnected ? ( - { - connectJira(verificationCode); - }} - /> - ) : ( - - createIssue(project, summary, description) - } - onLinkIssue={issueUrl => linkIssue(issueUrl)} - onUnlinkIssue={issueKey => unlinkIssue(issueKey)} - searchJiraLink={`${jiraWebBaseUrl}/issues/?jql=`} - isLoading={isLoading} - /> - )} - - + return !isJiraConnected ? ( + { + connectJira(verificationCode); + }} + /> + ) : ( + + createIssue(project, summary, description) + } + onLinkIssue={issueUrl => linkIssue(issueUrl)} + onUnlinkIssue={issueKey => unlinkIssue(issueKey)} + searchJiraLink={`${jiraWebBaseUrl}/issues/?jql=`} + isLoading={isLoading} + /> ); }; diff --git a/src/shared/containers/ResourceViewContainer.tsx b/src/shared/containers/ResourceViewContainer.tsx index 914ddf1ac..83ba4a60c 100644 --- a/src/shared/containers/ResourceViewContainer.tsx +++ b/src/shared/containers/ResourceViewContainer.tsx @@ -30,6 +30,7 @@ import JIRAPluginContainer from './JIRA/JIRAPluginContainer'; import { useSelector } from 'react-redux'; import { RootState } from '../store/reducers'; import { StudioResource } from '../../subapps/studioLegacy/containers/StudioContainer'; +import { useJiraPlugin } from '../hooks/useJIRA'; export type PluginMapping = { [pluginKey: string]: object; @@ -480,17 +481,29 @@ const ResourceViewContainer: React.FunctionComponent<{ }} /> ); - const jiraPlugin = resource && deltaPlugins && 'jira' in deltaPlugins && ( - { - pluginCollapsedToggle('jira'); - }} - /> - ); + const { isUserInSupportedJiraRealm } = useJiraPlugin(); + + const jiraPlugin = resource && + deltaPlugins && + 'jira' in deltaPlugins && + isUserInSupportedJiraRealm && ( + { + pluginCollapsedToggle('jira'); + }} + activeKey={openPlugins.includes('jira') ? 'jira' : undefined} + > + + {openPlugins.includes('jira') && ( + + )} + + + ); const builtInPlugins = [ { key: 'preview', name: 'preview', pluginComponent: previewPlugin }, diff --git a/src/shared/hooks/useJIRA.ts b/src/shared/hooks/useJIRA.ts index 89772577e..e83b81481 100644 --- a/src/shared/hooks/useJIRA.ts +++ b/src/shared/hooks/useJIRA.ts @@ -3,10 +3,28 @@ import { useNexusContext } from '@bbp/react-nexus'; import * as React from 'react'; import { useSelector } from 'react-redux'; import { RootState } from '../store/reducers'; -import { getResourceLabel, labelOf } from '../utils'; +import { getResourceLabel, isUserInAtLeastOneRealm, labelOf } from '../utils'; import useLocalStorage from './useLocalStorage'; import useNotification from './useNotification'; +export function useJiraPlugin() { + const { jiraSupportedRealms } = useSelector( + (state: RootState) => state.config + ); + + if (jiraSupportedRealms === undefined) { + return { isUserInSupportedJiraRealm: true }; + } + + const { identities } = useSelector((state: RootState) => state.auth); + const isUserInSupportedJiraRealm = + identities?.data && + jiraSupportedRealms && + isUserInAtLeastOneRealm(identities.data.identities, jiraSupportedRealms); + + return { isUserInSupportedJiraRealm }; +} + /** * Manages our JIRA data model * diff --git a/src/shared/store/reducers/config.ts b/src/shared/store/reducers/config.ts index c661d8295..6a58d6b61 100644 --- a/src/shared/store/reducers/config.ts +++ b/src/shared/store/reducers/config.ts @@ -29,6 +29,7 @@ export interface ConfigState { jiraResourceCustomFieldLabel: string; jiraProjectCustomFieldName: string; jiraProjectCustomFieldLabel: string; + jiraSupportedRealms?: string[]; } const initialState: ConfigState = { diff --git a/src/shared/utils/index.ts b/src/shared/utils/index.ts index f0f52ccd3..f96059d59 100644 --- a/src/shared/utils/index.ts +++ b/src/shared/utils/index.ts @@ -147,6 +147,15 @@ export const labelOf = (inputString: string) => { export const isBrowser = typeof window !== 'undefined'; +export function isUserInAtLeastOneRealm( + userIdentities: Identity[], + realm: string[] +) { + return ( + userIdentities.filter(i => i.realm && realm.includes(i.realm)).length > 0 + ); +} + /** * Returns the logout URL of the realm the user is authenticated with * diff --git a/src/subapps/admin/views/ProjectView.tsx b/src/subapps/admin/views/ProjectView.tsx index 4a5649f9a..80e89edb7 100644 --- a/src/subapps/admin/views/ProjectView.tsx +++ b/src/subapps/admin/views/ProjectView.tsx @@ -29,6 +29,7 @@ import './ProjectView.less'; import ResourceCreateUploadContainer from '../../../shared/containers/ResourceCreateUploadContainer'; import { makeOrganizationUri } from '../../../shared/utils'; import JiraPluginProjectContainer from '../containers/JiraContainer'; +import { useJiraPlugin } from '../../../shared/hooks/useJIRA'; const ProjectView: React.FunctionComponent = () => { const notification = useNotification(); @@ -262,6 +263,9 @@ const ProjectView: React.FunctionComponent = () => { if (activeKey === 'studios' || activeKey === 'workflows') return; history.push(pathFromTab(activeKey)); }; + + const { isUserInSupportedJiraRealm } = useJiraPlugin(); + return (
{!!project && ( @@ -401,14 +405,16 @@ const ProjectView: React.FunctionComponent = () => {
- {deltaPlugins && 'jira' in deltaPlugins && ( - - - - )} + {deltaPlugins && + 'jira' in deltaPlugins && + isUserInSupportedJiraRealm && ( + + + + )} {deltaPlugins && 'graph-analytics' in deltaPlugins && (