From 308a9408a024d0a823069795973c7100786b1648 Mon Sep 17 00:00:00 2001 From: Timo Pollmeier Date: Wed, 16 Aug 2023 14:17:31 +0200 Subject: [PATCH] Remove: Remove unused license management page The unused license management page and corresponding dialog are removed. Notifications about the license are still kept as a template for new notifications but will be removed later. The license page was removed because it caused confusion for users expecting an information page instead of a warning about a disabled feature when they entered the URL manually. --- src/web/components/bar/menubar.js | 5 - src/web/pages/licenses/__tests__/dialog.js | 134 -------- .../pages/licenses/__tests__/licensepage.js | 293 ------------------ src/web/pages/licenses/dialog.js | 101 ------ src/web/pages/licenses/licensepage.js | 292 ----------------- src/web/routes.js | 2 - 6 files changed, 827 deletions(-) delete mode 100644 src/web/pages/licenses/__tests__/dialog.js delete mode 100644 src/web/pages/licenses/__tests__/licensepage.js delete mode 100644 src/web/pages/licenses/dialog.js delete mode 100644 src/web/pages/licenses/licensepage.js diff --git a/src/web/components/bar/menubar.js b/src/web/components/bar/menubar.js index 7695c4f836..0c94f70b9d 100644 --- a/src/web/components/bar/menubar.js +++ b/src/web/components/bar/menubar.js @@ -273,11 +273,6 @@ const MenuBar = ({isLoggedIn, capabilities}) => { )} )} - {capabilities.mayOp('get_license') && ( - - - - )} diff --git a/src/web/pages/licenses/__tests__/dialog.js b/src/web/pages/licenses/__tests__/dialog.js deleted file mode 100644 index d2189d38c7..0000000000 --- a/src/web/pages/licenses/__tests__/dialog.js +++ /dev/null @@ -1,134 +0,0 @@ -/* Copyright (C) 2022 Greenbone AG - * - * SPDX-License-Identifier: AGPL-3.0-or-later - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -import React from 'react'; -import userEvent from '@testing-library/user-event'; - -import {setLocale} from 'gmp/models/date'; - -import {render} from 'web/utils/testing'; - -import Dialog from '../dialog'; - -setLocale('en'); - -describe('LicenseDialog component tests', () => { - test('should render dialog with file selection', () => { - const handleClose = jest.fn(); - const handleSave = jest.fn(); - - const {baseElement, getByName} = render( - , - ); - - expect(baseElement).toHaveTextContent('New License'); - expect(baseElement).toHaveTextContent('License File'); - - const button = getByName('file'); - expect(button).toBeDefined(); - }); - - test('should close Dialog with close button', () => { - const handleClose = jest.fn(); - const handleSave = jest.fn(); - - const {getByTestId} = render( - , - ); - const closeButton = getByTestId('dialog-title-close-button'); - - expect(closeButton).toBeInTheDocument(); - - userEvent.click(closeButton); - - expect(handleClose).toHaveBeenCalled(); - }); - - test('should close Dialog with cancel button', () => { - const handleClose = jest.fn(); - const handleSave = jest.fn(); - - const {getByTestId} = render( - , - ); - const cancelButton = getByTestId('dialog-close-button'); - - expect(cancelButton).toBeInTheDocument(); - - userEvent.click(cancelButton); - - expect(handleClose).toHaveBeenCalled(); - }); - - test('should call clickhandler for save button if license not active', () => { - const handleClose = jest.fn(); - const handleSave = jest.fn(); - - const {getByTestId} = render( - , - ); - const saveButton = getByTestId('dialog-save-button'); - - expect(saveButton).toBeInTheDocument(); - - userEvent.click(saveButton); - - expect(handleSave).toHaveBeenCalled(); - }); - - test('should not call clickhandler for save button if license active', () => { - // this indirectly figures out if the click handler was intercepted by the - // ConfirmationDialog, which should pop up for valid/active licenses - const handleClose = jest.fn(); - const handleSave = jest.fn(); - - const {getByTestId} = render( - , - ); - const saveButton = getByTestId('dialog-save-button'); - - expect(saveButton).toBeInTheDocument(); - - userEvent.click(saveButton); - - expect(handleSave).not.toHaveBeenCalled(); - }); -}); - -// vim: set ts=2 sw=2 tw=80: diff --git a/src/web/pages/licenses/__tests__/licensepage.js b/src/web/pages/licenses/__tests__/licensepage.js deleted file mode 100644 index 6b50d80c8e..0000000000 --- a/src/web/pages/licenses/__tests__/licensepage.js +++ /dev/null @@ -1,293 +0,0 @@ -/* Copyright (C) 2021-2022 Greenbone AG - * - * SPDX-License-Identifier: AGPL-3.0-or-later - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -import React from 'react'; - -import Capabilities from 'gmp/capabilities/capabilities'; - -import {setLocale} from 'gmp/locale/lang'; - -import {License} from 'gmp/models/license'; - -import Response from 'gmp/http/response'; - -import {setTimezone} from 'web/store/usersettings/actions'; - -import {rendererWith, waitFor, wait} from 'web/utils/testing'; - -import LicensePage from '../licensepage'; - -setLocale('en'); - -const data = License.fromElement({ - status: 'active', - content: { - meta: { - id: '12345', - version: '1.0.0', - title: 'Test License', - type: 'trial', - customer_name: 'Monsters Inc.', - created: '2021-08-27T06:05:21Z', - begins: '2021-08-27T07:05:21Z', - expires: '2021-09-08T07:05:21Z', - comment: 'Han shot first', - }, - appliance: { - model: '450', - model_type: 'hardware', - sensor: false, - }, - }, -}); - -const data2 = License.fromElement({ - status: 'active', - content: { - meta: { - id: '12345', - version: '1.0.0', - title: 'Test License', - type: 'trial', - customer_name: 'Monsters Inc.', - created: '2021-08-27T06:05:21Z', - begins: '2021-08-27T07:05:21Z', - expires: '2021-09-09T07:05:21Z', - comment: 'Han shot first', - }, - appliance: { - model: '450', - model_type: 'hardware', - sensor: false, - }, - keys: { - key: { - _name: 'feed', - __text: '*base64 GSF key*', - }, - }, - signatures: { - license: '*base64 signature*', - }, - }, -}); - -const xhr = { - response: 'foo', - responseText: 'bar', - responseXML: 'ipsum', -}; - -const caps = new Capabilities(['everything']); - -const mockDate = new Date('2021-08-09T07:05:21Z'); - -beforeEach(() => { - jest.spyOn(global.Date, 'now').mockImplementation(() => mockDate); -}); - -describe('LicensePage tests', () => { - test('should render with <=30 days until expiration', async () => { - const response = new Response(xhr, data); - - const gmp = { - license: { - getLicenseInformation: jest.fn(() => Promise.resolve(response)), - }, - settings: { - manualUrl: 'http://foo.bar', - }, - }; - - const {render, store} = rendererWith({ - capabilities: caps, - license: data, - gmp, - router: true, - store: true, - }); - const {element, getAllByRole, getAllByTestId} = render(); - - store.dispatch(setTimezone('UTC')); - - await waitFor(() => element.querySelectorAll('table')); - - // Should render all icons - const icons = getAllByTestId('svg-icon'); - - expect(icons.length).toEqual(4); - - expect(icons[0]).toHaveTextContent('help.svg'); - expect(icons[0]).toHaveAttribute('title', 'Help: License Management'); - expect(icons[1]).toHaveTextContent('new.svg'); - expect(icons[2]).toHaveTextContent('license.svg'); - expect(icons[3]).toHaveTextContent('help.svg'); - - // Should render links - const links = element.querySelectorAll('a'); - - expect(links.length).toEqual(2); - - expect(links[0]).toHaveAttribute( - 'href', - 'http://foo.bar/en/web-interface.html#license-management', - ); - - expect(links[1]).toHaveAttribute('href', 'mailto:sales@greenbone.net'); - - // License Information - expect(element).toHaveTextContent('The license expires'); - expect(element).toHaveTextContent('in 30 days'); - expect(element).toHaveTextContent('Status'); - expect(element).toHaveTextContent('License is active'); - expect(element).toHaveTextContent('ID'); - expect(element).toHaveTextContent('12345'); - expect(element).toHaveTextContent('Customer Name'); - expect(element).toHaveTextContent('Monsters Inc.'); - expect(element).toHaveTextContent('Creation Date'); - expect(element).toHaveTextContent('Fri, Aug 27, 2021 7:05 AM UTC'); - expect(element).toHaveTextContent('Version'); - expect(element).toHaveTextContent('1.0.0'); - expect(element).toHaveTextContent('Begins'); - expect(element).toHaveTextContent('Fri, Aug 27, 2021 7:05 AM UTC'); - expect(element).toHaveTextContent('Expires on'); - expect(element).toHaveTextContent('Wed, Sep 8, 2021 7:05 AM UTC'); - expect(element).toHaveTextContent('Comment'); - expect(element).toHaveTextContent('Han shot first'); - expect(element).toHaveTextContent('Model'); - expect(element).toHaveTextContent('Greenbone Enterprise 450'); - expect(element).toHaveTextContent('Model Type'); - expect(element).toHaveTextContent('Hardware Appliance'); - - // Headings - const headings = getAllByRole('heading'); - expect(headings[0]).toHaveTextContent('License Management'); - expect(headings[1]).toHaveTextContent('Information'); - expect(headings[2]).toHaveTextContent('Model'); - expect(headings[3]).toHaveTextContent( - 'How to get a Greenbone Enterprise License', - ); - }); - - test('should render with >30 days until expiration', async () => { - const response = new Response(xhr, data2); - const gmp = { - license: { - getLicenseInformation: jest.fn(() => Promise.resolve(response)), - }, - settings: { - manualUrl: 'http://foo.bar', - }, - }; - const {render, store} = rendererWith({ - capabilities: caps, - license: data2, - gmp, - router: true, - store: true, - }); - const {element, getAllByRole, getAllByTestId} = render(); - - store.dispatch(setTimezone('UTC')); - - await waitFor(() => element.querySelectorAll('table')); - - // Should render all icons - const icons = getAllByTestId('svg-icon'); - - expect(icons.length).toEqual(4); - - expect(icons[0]).toHaveTextContent('help.svg'); - expect(icons[0]).toHaveAttribute('title', 'Help: License Management'); - expect(icons[1]).toHaveTextContent('new.svg'); - expect(icons[2]).toHaveTextContent('license.svg'); - expect(icons[3]).toHaveTextContent('help.svg'); - - // Should render links - const links = element.querySelectorAll('a'); - - expect(links.length).toEqual(2); - - expect(links[0]).toHaveAttribute( - 'href', - 'http://foo.bar/en/web-interface.html#license-management', - ); - - expect(links[1]).toHaveAttribute('href', 'mailto:sales@greenbone.net'); - - // License Information - expect(element).toHaveTextContent('The license expires'); - expect(element).toHaveTextContent('in a month'); - expect(element).toHaveTextContent('Status'); - expect(element).toHaveTextContent('License is active'); - expect(element).toHaveTextContent('ID'); - expect(element).toHaveTextContent('12345'); - expect(element).toHaveTextContent('Customer Name'); - expect(element).toHaveTextContent('Monsters Inc.'); - expect(element).toHaveTextContent('Creation Date'); - expect(element).toHaveTextContent('Fri, Aug 27, 2021 7:05 AM UTC'); - expect(element).toHaveTextContent('Version'); - expect(element).toHaveTextContent('1.0.0'); - expect(element).toHaveTextContent('Begins'); - expect(element).toHaveTextContent('Fri, Aug 27, 2021 7:05 AM UTC'); - expect(element).toHaveTextContent('Expires on'); - expect(element).toHaveTextContent('Thu, Sep 9, 2021 7:05 AM UTC'); - expect(element).toHaveTextContent('Comment'); - expect(element).toHaveTextContent('Han shot first'); - expect(element).toHaveTextContent('Model'); - expect(element).toHaveTextContent('Greenbone Enterprise 450'); - expect(element).toHaveTextContent('Model Type'); - expect(element).toHaveTextContent('Hardware Appliance'); - - // Headings - const headings = getAllByRole('heading'); - expect(headings[0]).toHaveTextContent('License Management'); - expect(headings[1]).toHaveTextContent('Information'); - expect(headings[2]).toHaveTextContent('Model'); - expect(headings[3]).toHaveTextContent( - 'How to get a Greenbone Enterprise License', - ); - }); - - test('should render error dialog if no license could be loaded', async () => { - const gmpRejected = { - license: { - getLicenseInformation: jest.fn(() => Promise.reject(new Error('foo'))), - }, - settings: { - manualUrl: 'http://foo.bar', - }, - }; - - const {render, store} = rendererWith({ - capabilities: caps, - license: data, - gmp: gmpRejected, - router: true, - store: true, - }); - const {getByTestId} = render(); - - store.dispatch(setTimezone('UTC')); - - await wait(); - - const content = getByTestId('errordialog-content'); - - expect(content).toHaveTextContent('foo'); - }); -}); diff --git a/src/web/pages/licenses/dialog.js b/src/web/pages/licenses/dialog.js deleted file mode 100644 index 07cb284a44..0000000000 --- a/src/web/pages/licenses/dialog.js +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (C) 2021-2022 Greenbone AG - * - * SPDX-License-Identifier: AGPL-3.0-or-later - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -import React, {useState} from 'react'; - -import _ from 'gmp/locale'; - -import ConfirmationDialog from 'web/components/dialog/confirmationdialog'; -import SaveDialog from 'web/components/dialog/savedialog'; - -import FileField from 'web/components/form/filefield'; -import FormGroup from 'web/components/form/formgroup'; - -import PropTypes from 'web/utils/proptypes'; - -const LicenseDialog = ({ - error, - status, - onClose, - onErrorClose, - onSave, - onValueChange, -}) => { - const [confirmationDialogVisible, setConfirmationDialogVisible] = - useState(false); - - const closeConfirmationDialog = () => { - setConfirmationDialogVisible(false); - }; - - const handleSaveClick = data => { - if (status === 'active') { - setConfirmationDialogVisible(true); - } else { - onSave(data); - } - }; - - const handleResumeClick = data => { - closeConfirmationDialog(); - onSave(data); - }; - - return ( - handleSaveClick(onSave, data)} - > - {({values}) => ( - - - - - {confirmationDialogVisible && ( - - )} - - )} - - ); -}; - -LicenseDialog.propTypes = { - error: PropTypes.string, - status: PropTypes.string, - onClose: PropTypes.func.isRequired, - onErrorClose: PropTypes.func.isRequired, - onSave: PropTypes.func.isRequired, - onValueChange: PropTypes.func, -}; - -export default LicenseDialog; - -// vim: set ts=2 sw=2 tw=80: diff --git a/src/web/pages/licenses/licensepage.js b/src/web/pages/licenses/licensepage.js deleted file mode 100644 index d590dd40b6..0000000000 --- a/src/web/pages/licenses/licensepage.js +++ /dev/null @@ -1,292 +0,0 @@ -/* Copyright (C) 2021-2022 Greenbone AG - * - * SPDX-License-Identifier: AGPL-3.0-or-later - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -import React, {useEffect, useState} from 'react'; - -import styled from 'styled-components'; - -import _ from 'gmp/locale'; - -import date from 'gmp/models/date'; -import { - getLicenseApplianceModelName, - getLicenseApplianceModelType, - getTranslatableLicenseStatus, -} from 'gmp/models/license'; - -import {isDefined} from 'gmp/utils/identity'; - -import DateTime from 'web/components/date/datetime'; - -import ErrorDialog from 'web/components/dialog/errordialog'; - -import LicenseIcon from 'web/components/icon/licenseicon'; -import ManualIcon from 'web/components/icon/manualicon'; -import NewIcon from 'web/components/icon/newicon'; -import HelpIcon from 'web/components/icon/helpicon'; - -import IconDivider from 'web/components/layout/icondivider'; -import Layout from 'web/components/layout/layout'; -import PageTitle from 'web/components/layout/pagetitle'; - -import Loading from 'web/components/loading/loading'; - -import Section from 'web/components/section/section'; - -import InfoTable from 'web/components/table/infotable'; -import TableBody from 'web/components/table/body'; -import TableData from 'web/components/table/data'; -import TableRow from 'web/components/table/row'; - -import {Col} from 'web/entity/page'; - -import PropTypes from 'web/utils/proptypes'; -import useGmp from 'web/utils/useGmp'; -import useLicense from 'web/utils/useLicense'; - -import useCapabilities from 'web/utils/useCapabilities'; - -import LicenseDialog from './dialog'; - -const HowToDiv = styled.div` - width: 33%; -`; - -const ToolBarIcons = ({onNewLicenseClick}) => { - const capabilities = useCapabilities(); - const mayModify = capabilities.mayEdit('license'); - - return ( - - - - {mayModify && ( - - )} - - - ); -}; -ToolBarIcons.propTypes = { - onNewLicenseClick: PropTypes.func.isRequired, -}; - -const LicensePage = () => { - const gmp = useGmp(); - const {isLoading, license, licenseError, updateLicense} = useLicense(); - const [file, setFile] = useState(); - const [error, setError] = useState(licenseError); - const [dialogError, setDialogError] = useState(); - const [newLicenseDialogVisible, setNewLicenseDialogVisible] = useState(false); - - useEffect(() => { - setError(licenseError); - }, [licenseError]); - - const handleNewLicenseClick = () => { - setNewLicenseDialogVisible(true); - }; - - const handleCloseDialog = () => { - setNewLicenseDialogVisible(false); - setDialogError(undefined); - setFile(undefined); - }; - - const handleSaveLicense = data => { - return gmp.license - .modifyLicense(file) - .then(() => { - handleCloseDialog(); - updateLicense(); - }) - .catch(err => { - setDialogError(err.message); - }); - }; - - const handleValueChange = value => { - setFile(value); - }; - - const handleErrorClose = () => { - setError(undefined); - }; - - const handleDialogErrorClose = () => { - setDialogError(undefined); - }; - - let durationUntilExpires; - - if (license.status === 'active') { - const dur = date(license.expires).diff(date(), 'days'); - - if (dur > 30) { - durationUntilExpires = date(license.expires).fromNow(); - } else { - durationUntilExpires = _('in {{dur}} days', {dur}); - } - } - - return ( - - - - - {error && ( - - )} -
} - title={_('License Management')} - > - {isLoading ? ( - - ) : ( - -

Information

- - - - - - - - {_('The license expires')} - {durationUntilExpires} - - - {_('Status')} - - {getTranslatableLicenseStatus(license.status)} - - - - {_('ID')} - {license.id} - - - {_('Customer Name')} - {license.customerName} - - - {_('Creation Date')} - - - - - - {_('Version')} - {license.version} - - - {_('Begins')} - - - - - - {_('Expires on')} - - - - - {isDefined(license.comment) && ( - - {_('Comment')} - {license.comment} - - )} - - -

{_('Model')}

- - - - - - - - {_('Model')} - - {getLicenseApplianceModelName(license.applianceModel)} - - - - {_('Model Type')} - - {getLicenseApplianceModelType(license.applianceModelType)} - - - - -

- {_('How to get a Greenbone Enterprise License')} -

- -

- {_( - 'A Greenbone Enterprise License grants access to the ' + - 'newest vulnerability information, including tests for ' + - 'several proprietary products, policies, report formats and' + - ' system updates.', - )} -

-

- {_( - 'Please contact our sales team for purchasing or ' + - ' re-newing a subscription to Greenbone Enterprise ' + - 'products.', - )} -

- sales@greenbone.net -
-
- )} -
-
- {newLicenseDialogVisible && ( - - )} -
- ); -}; - -export default LicensePage; - -// vim: set ts=2 sw=2 tw=80: diff --git a/src/web/routes.js b/src/web/routes.js index 911500e59f..e07ba67b95 100644 --- a/src/web/routes.js +++ b/src/web/routes.js @@ -55,7 +55,6 @@ import GroupDetailsPage from './pages/groups/detailspage'; import HostsPage from './pages/hosts/listpage'; import HostDetailsPage from './pages/hosts/detailspage'; import LdapPage from './pages/ldap/ldappage'; -import LicensePage from './pages/licenses/licensepage'; import LoginPage from './pages/login/loginpage'; import NotesPage from './pages/notes/listpage'; import NoteDetailsPage from './pages/notes/detailspage'; @@ -143,7 +142,6 @@ const Routes = () => ( -