From: Lucas Di Pentima Date: Thu, 16 Jun 2022 17:26:53 +0000 (-0300) Subject: Merge branch '19007-file-browser-action-button'. Closes #19007 X-Git-Tag: 2.5.0~51 X-Git-Url: https://git.arvados.org/arvados-workbench2.git/commitdiff_plain/c21c6582a12fe3968e3ef3a4786de5dfacce3b18?hp=5550460d7ca90ad69b325ec58897cb0d55210bca Merge branch '19007-file-browser-action-button'. Closes #19007 Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima --- diff --git a/src/common/config.ts b/src/common/config.ts index 2518c95e..2954d704 100644 --- a/src/common/config.ts +++ b/src/common/config.ts @@ -50,6 +50,7 @@ export interface ClusterConfigJSON { } }; Workbench: { + DisableSharingURLsUI: boolean; ArvadosDocsite: string; FileViewersConfigURL: string; WelcomePageHTML: string; @@ -233,6 +234,7 @@ export const mockClusterConfigJSON = (config: Partial): Clust WebShell: { ExternalURL: "" }, }, Workbench: { + DisableSharingURLsUI: false, ArvadosDocsite: "", FileViewersConfigURL: "", WelcomePageHTML: "", diff --git a/src/store/sharing-dialog/sharing-dialog-actions.ts b/src/store/sharing-dialog/sharing-dialog-actions.ts index 367eea81..cdc6c0c7 100644 --- a/src/store/sharing-dialog/sharing-dialog-actions.ts +++ b/src/store/sharing-dialog/sharing-dialog-actions.ts @@ -118,13 +118,14 @@ export const deleteSharingToken = (uuid: string) => async (dispatch: Dispatch, g const loadSharingDialog = async (dispatch: Dispatch, getState: () => RootState, { apiClientAuthorizationService }: ServiceRepository) => { const dialog = getDialog(getState().dialog, SHARING_DIALOG_NAME); + const sharingURLsDisabled = getState().auth.config.clusterConfig.Workbench.DisableSharingURLsUI; if (dialog) { dispatch(progressIndicatorActions.START_WORKING(SHARING_DIALOG_NAME)); try { const resourceUuid = dialog.data.resourceUuid; await dispatch(initializeManagementForm); // For collections, we need to load the public sharing tokens - if (extractUuidObjectType(resourceUuid) === ResourceObjectType.COLLECTION) { + if (!sharingURLsDisabled && extractUuidObjectType(resourceUuid) === ResourceObjectType.COLLECTION) { const sharingTokens = await apiClientAuthorizationService.listCollectionSharingTokens(resourceUuid); dispatch(resourcesActions.SET_RESOURCES([...sharingTokens.items])); } diff --git a/src/views-components/sharing-dialog/sharing-dialog-component.test.tsx b/src/views-components/sharing-dialog/sharing-dialog-component.test.tsx new file mode 100644 index 00000000..36447a8d --- /dev/null +++ b/src/views-components/sharing-dialog/sharing-dialog-component.test.tsx @@ -0,0 +1,71 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import React from 'react'; +import { mount, configure } from 'enzyme'; +import Adapter from 'enzyme-adapter-react-16'; +import { Provider } from 'react-redux'; +import { combineReducers, createStore } from 'redux'; + +import SharingDialogComponent, { + SharingDialogComponentProps, +} from './sharing-dialog-component'; +import { + extractUuidObjectType, + ResourceObjectType +} from 'models/resource'; + +configure({ adapter: new Adapter() }); + +describe("", () => { + let props: SharingDialogComponentProps; + let store; + + beforeEach(() => { + const initialAuthState = { + config: { + keepWebServiceUrl: 'http://example.com/', + keepWebInlineServiceUrl: 'http://*.collections.example.com/', + } + } + store = createStore(combineReducers({ + auth: (state: any = initialAuthState, action: any) => state, + })); + + props = { + open: true, + loading: false, + saveEnabled: false, + sharedResourceUuid: 'zzzzz-4zz18-zzzzzzzzzzzzzzz', + privateAccess: true, + sharingURLsNr: 2, + sharingURLsDisabled: false, + onClose: jest.fn(), + onSave: jest.fn(), + onCreateSharingToken: jest.fn(), + refreshPermissions: jest.fn(), + }; + }); + + it("show sharing urls tab on collections when not disabled", () => { + expect(props.sharingURLsDisabled).toBe(false); + expect(props.sharingURLsNr).toBe(2); + expect(extractUuidObjectType(props.sharedResourceUuid) === ResourceObjectType.COLLECTION).toBe(true); + let wrapper = mount(); + expect(wrapper.html()).toContain('Sharing URLs (2)'); + + // disable Sharing URLs UI + props.sharingURLsDisabled = true; + wrapper = mount(); + expect(wrapper.html()).not.toContain('Sharing URLs'); + }); + + it("does not show sharing urls on non-collection resources", () => { + props.sharedResourceUuid = 'zzzzz-j7d0g-0123456789abcde'; + expect(extractUuidObjectType(props.sharedResourceUuid) === ResourceObjectType.COLLECTION).toBe(false); + expect(props.sharingURLsDisabled).toBe(false); + let wrapper = mount(); + expect(wrapper.html()).not.toContain('Sharing URLs'); + }); +}); \ No newline at end of file diff --git a/src/views-components/sharing-dialog/sharing-dialog-component.tsx b/src/views-components/sharing-dialog/sharing-dialog-component.tsx index 15d7f660..b2f31397 100644 --- a/src/views-components/sharing-dialog/sharing-dialog-component.tsx +++ b/src/views-components/sharing-dialog/sharing-dialog-component.tsx @@ -47,6 +47,7 @@ export interface SharingDialogDataProps { sharedResourceUuid: string; sharingURLsNr: number; privateAccess: boolean; + sharingURLsDisabled: boolean; } export interface SharingDialogActionProps { onClose: () => void; @@ -58,11 +59,13 @@ enum SharingDialogTab { PERMISSIONS = 0, URLS = 1, } -export default (props: SharingDialogDataProps & SharingDialogActionProps) => { +export type SharingDialogComponentProps = SharingDialogDataProps & SharingDialogActionProps; + +export default (props: SharingDialogComponentProps) => { const { open, loading, saveEnabled, sharedResourceUuid, - sharingURLsNr, privateAccess, + sharingURLsNr, privateAccess, sharingURLsDisabled, onClose, onSave, onCreateSharingToken, refreshPermissions } = props; - const showTabs = extractUuidObjectType(sharedResourceUuid) === ResourceObjectType.COLLECTION; + const showTabs = !sharingURLsDisabled && extractUuidObjectType(sharedResourceUuid) === ResourceObjectType.COLLECTION; const [tabNr, setTabNr] = React.useState(SharingDialogTab.PERMISSIONS); const [expDate, setExpDate] = React.useState(); const [withExpiration, setWithExpiration] = React.useState(false); @@ -151,7 +154,8 @@ export default (props: SharingDialogDataProps & SharingDialogActionProps) => { } - { tabNr === SharingDialogTab.PERMISSIONS && privateAccess && sharingURLsNr > 0 && + { tabNr === SharingDialogTab.PERMISSIONS && !sharingURLsDisabled && + privateAccess && sharingURLsNr > 0 && Although there aren't specific permissions set, this is publicly accessible via Sharing URL(s). diff --git a/src/views-components/sharing-dialog/sharing-dialog.tsx b/src/views-components/sharing-dialog/sharing-dialog.tsx index 6b488e44..01cd390b 100644 --- a/src/views-components/sharing-dialog/sharing-dialog.tsx +++ b/src/views-components/sharing-dialog/sharing-dialog.tsx @@ -35,18 +35,21 @@ type Props = WithDialogProps & WithProgressStateProps; const mapStateToProps = (state: RootState, { working, ...props }: Props): SharingDialogDataProps => { const dialog = getDialog(state.dialog, SHARING_DIALOG_NAME); const sharedResourceUuid = dialog?.data.resourceUuid || ''; + const sharingURLsDisabled = state.auth.config.clusterConfig.Workbench.DisableSharingURLsUI; return ({ ...props, saveEnabled: hasChanges(state), loading: working, sharedResourceUuid, - sharingURLsNr: (filterResources( - (resource: ApiClientAuthorization) => + sharingURLsDisabled, + sharingURLsNr: !sharingURLsDisabled + ? (filterResources( (resource: ApiClientAuthorization) => resource.kind === ResourceKind.API_CLIENT_AUTHORIZATION && resource.scopes.includes(`GET /arvados/v1/collections/${sharedResourceUuid}`) && resource.scopes.includes(`GET /arvados/v1/collections/${sharedResourceUuid}/`) && resource.scopes.includes('GET /arvados/v1/keep_services/accessible') - )(state.resources) as ApiClientAuthorization[]).length, + )(state.resources) as ApiClientAuthorization[]).length + : 0, privateAccess: getSharingPublicAccessFormData(state)?.visibility === VisibilityLevel.PRIVATE, }) };